[
  {
    "path": ".android/Dockerfile",
    "content": "FROM ubuntu:latest\n\nARG ndk_version=r27c\n\nRUN apt-get update && apt-get install -y \\\n    build-essential \\\n    curl \\\n    cmake \\\n    ninja-build \\\n    python3 \\\n    unzip\n\nRUN curl -o ndk.zip https://dl.google.com/android/repository/android-ndk-${ndk_version}-linux.zip\nRUN unzip ndk.zip && mv android-ndk-${ndk_version} /ndk\n\nRUN curl -o capnproto.tar.gz https://capnproto.org/capnproto-c++-0.10.2.tar.gz\nRUN mkdir -p /src/capnproto\nRUN tar zxf capnproto.tar.gz -C /src/capnproto --strip-components=1\nRUN mkdir -p /build/capnproto\nRUN cd /build/capnproto\nRUN /src/capnproto/configure\nRUN make -j$(nproc) install\nRUN cd -\n\nRUN mkdir -p /build/rr\nRUN chmod 777 /build/rr\n\nWORKDIR /build/rr\nCMD [\"/bin/bash\", \"/src/rr/.android/build.sh\"]\n"
  },
  {
    "path": ".android/README.md",
    "content": "# Building for Android\n\nTo build for Android (from the root of the rr source tree):\n\n```\ndocker build .android -t rr-android\nmkdir -p obj/dist\ndocker run -it --rm \\\n    -u $UID:$GID \\\n    -v $(pwd):/src/rr \\\n    -v $(pwd)/obj/dist:/dist \\\n    rr-android\n```\n\n`-u $UID:GID` ensures that the build runs with your current UID/GID, which is\nnecessary to avoid the output being only writable by root.\n\n`-v $(pwd):/src/rr` mounts the source tree in the container so it can be built.\n\n`-v $(pwd)/obj/dist:/dist` sets the output directory for the container to the\ncurrent directory. The last step of the build will copy the rr tarball to the\ndirectory on the left of `:`."
  },
  {
    "path": ".android/build.sh",
    "content": "#!/usr/bin/env bash\nset -e\nset -x\n\nDEVICE_CMAKE_DEFS=\"-DCMAKE_TOOLCHAIN_FILE=/ndk/build/cmake/android.toolchain.cmake -DANDROID_ABI=x86_64 -DANDROID_PLATFORM=android-28\"\n\n# Build capnp again for the device\nINSTALL_PREFIX=$(pwd)/install\nmkdir -p $INSTALL_PREFIX\nmkdir capnproto-android\ncd capnproto-android\ncmake -G Ninja \\\n  $DEVICE_CMAKE_DEFS \\\n  -DEXTERNAL_CAPNP=True \\\n  -DBUILD_SHARED_LIBS=True \\\n  -DCMAKE_INSTALL_PREFIX=$INSTALL_PREFIX \\\n  /src/capnproto\ncmake --build .\ncmake --install .\ncd -\n\nmkdir obj\ncd obj\ncmake -G Ninja \\\n  $DEVICE_CMAKE_DEFS \\\n  -Ddisable32bit=True \\\n  -DBUILD_TESTS=False \\\n  -DCMAKE_FIND_ROOT_PATH=$INSTALL_PREFIX \\\n  -DSKIP_PKGCONFIG=True \\\n  -DEXTRA_VERSION_STRING=\"$BUILD_ID\" \\\n  -DZLIB_LDFLAGS=-lz \\\n  -DEXTRA_EXTERNAL_SOLIBS=\"/build/rr/capnproto-android/src/kj/libkj.so;/build/rr/capnproto-android/src/capnp/libcapnp.so\" \\\n  /src/rr\ncmake --build .\ncpack -G TGZ\n\ncp dist/* /dist/\n"
  },
  {
    "path": ".buildkite/.gitignore",
    "content": "test.yml\ntest-*.yml\n"
  },
  {
    "path": ".buildkite/CTestCostData.txt",
    "content": "check_environment 2 0.0177417\n64bit_child 2 0.388554\n64bit_child-no-syscallbuf 2 0.343397\n_llseek 2 0.178732\n_llseek-no-syscallbuf 2 0.176157\nabort 2 0.405355\nabort-no-syscallbuf 2 0.401123\naccept 2 0.296525\naccept-no-syscallbuf 2 0.238087\nacct 2 0.172497\nacct-no-syscallbuf 2 0.157378\nadjtimex 2 0.164065\nadjtimex-no-syscallbuf 2 0.157286\naio 2 0.174191\naio-no-syscallbuf 2 0.172184\nalarm 2 2.31239\nalarm-no-syscallbuf 2 2.62346\nalarm2 2 1.14969\nalarm2-no-syscallbuf 2 1.17563\nalsa_ioctl 2 0.183019\nalsa_ioctl-no-syscallbuf 2 0.175809\narch_prctl 2 0.165938\narch_prctl-no-syscallbuf 2 0.164753\nasync_segv_ignored 2 0.176697\nasync_segv_ignored-no-syscallbuf 2 0.158012\nat_threadexit 2 0.222064\nat_threadexit-no-syscallbuf 2 0.206986\nbad_ip 2 0.165407\nbad_ip-no-syscallbuf 2 0.187529\nbad_syscall 2 0.174693\nbad_syscall-no-syscallbuf 2 0.143219\nbarrier 2 0.33947\nbarrier-no-syscallbuf 2 0.335352\nbig_buffers 2 0.180078\nbig_buffers-no-syscallbuf 2 0.185628\nblock 2 9.35626\nblock-no-syscallbuf 2 9.41618\nblock_open 2 0.213755\nblock_open-no-syscallbuf 2 0.210349\nbpf 2 0.19726\nbpf-no-syscallbuf 2 0.178959\nbpf_map 2 0.182377\nbpf_map-no-syscallbuf 2 0.16628\nbrk 2 0.202035\nbrk-no-syscallbuf 2 0.268974\nbrk2 2 0.192675\nbrk2-no-syscallbuf 2 0.1618\ncapget 2 0.186253\ncapget-no-syscallbuf 2 0.178183\nchew_cpu 2 9.10871\nchew_cpu-no-syscallbuf 2 9.7596\nx86/chew_cpu_cpuid 2 0.909633\nx86/chew_cpu_cpuid-no-syscallbuf 2 0.241009\nchmod 2 0.175173\nchmod-no-syscallbuf 2 0.193\nchown 2 0.260438\nchown-no-syscallbuf 2 0.247314\nclock 2 0.321689\nclock-no-syscallbuf 2 0.405406\nclock_adjtime 2 0.179823\nclock_adjtime-no-syscallbuf 2 0.182865\nclock_nanosleep 2 1.17138\nclock_nanosleep-no-syscallbuf 2 1.15077\nclock_time64 2 0.18665\nclock_time64-no-syscallbuf 2 0.16131\nclone 2 0.184247\nclone-no-syscallbuf 2 0.194884\nclone_bad_stack 2 0.322686\nclone_bad_stack-no-syscallbuf 2 0.305627\nclone_bad_tls 2 0.200441\nclone_bad_tls-no-syscallbuf 2 0.159102\nclone_cleartid_coredump 2 0.382393\nclone_cleartid_coredump-no-syscallbuf 2 0.327541\nclone_fail 2 0.182033\nclone_fail-no-syscallbuf 2 0.160097\nclone_file_range 2 0.225524\nclone_file_range-no-syscallbuf 2 0.19126\nclone_immediate_exit 2 0.187786\nclone_immediate_exit-no-syscallbuf 2 0.184644\nclone_newflags 2 0.187025\nclone_newflags-no-syscallbuf 2 0.945696\nclone_parent 2 0.182157\nclone_parent-no-syscallbuf 2 0.204792\nclone_untraced 2 0.196201\nclone_untraced-no-syscallbuf 2 0.207853\nclone_vfork_pidfd 2 0.168749\nclone_vfork_pidfd-no-syscallbuf 2 0.169371\ncloned_sigmask 2 0.304638\ncloned_sigmask-no-syscallbuf 2 0.315861\nconstructor 2 2.22217\nconstructor-no-syscallbuf 2 2.21146\ncopy_file_range 2 0.187135\ncopy_file_range-no-syscallbuf 2 0.181734\nx86/cpuid_same_state 2 0.159951\nx86/cpuid_same_state-no-syscallbuf 2 0.165536\ncreat_address_not_truncated 2 0.182924\ncreat_address_not_truncated-no-syscallbuf 2 0.17218\nx86/cross_arch 2 0.175549\nx86/cross_arch-no-syscallbuf 2 0.173372\ncwd_inaccessible 2 0.275782\ncwd_inaccessible-no-syscallbuf 2 0.234584\ndaemon 2 0.205866\ndaemon-no-syscallbuf 2 0.174672\ndesched_blocking_poll 2 0.184894\ndesched_blocking_poll-no-syscallbuf 2 0.172352\ndesched_sigkill 2 0.30291\ndesched_sigkill-no-syscallbuf 2 0.240905\ndetach_state 2 0.219355\ndetach_state-no-syscallbuf 2 0.220512\ndetach_threads 2 0.314015\ndetach_threads-no-syscallbuf 2 0.280626\ndetach_sigkill 2 0.196443\ndetach_sigkill-no-syscallbuf 2 0.218506\ndetach_sigkill_exit 2 0.207984\ndetach_sigkill_exit-no-syscallbuf 2 0.197267\ndeterministic_sigsys 2 0.346079\ndeterministic_sigsys-no-syscallbuf 2 0.307801\ndev_zero 2 0.154614\ndev_zero-no-syscallbuf 2 0.23869\ndirect 2 0.243545\ndirect-no-syscallbuf 2 0.172084\ndup 2 0.232475\ndup-no-syscallbuf 2 0.189027\ndoublesegv 2 0.501823\ndoublesegv-no-syscallbuf 2 0.408514\nepoll_create 2 0.194815\nepoll_create-no-syscallbuf 2 0.153384\nepoll_create1 2 0.171597\nepoll_create1-no-syscallbuf 2 0.17207\nepoll_edge 2 0.178929\nepoll_edge-no-syscallbuf 2 0.158552\nepoll_pwait_eintr_sigmask 2 2.19519\nepoll_pwait_eintr_sigmask-no-syscallbuf 2 2.21515\neventfd 2 0.165454\neventfd-no-syscallbuf 2 0.166546\nexec_flags 2 0.161951\nexec_flags-no-syscallbuf 2 0.183996\nexec_no_env 2 0.220634\nexec_no_env-no-syscallbuf 2 0.212066\nexec_self 2 0.235062\nexec_self-no-syscallbuf 2 0.228894\nexec_from_main_thread 2 0.274183\nexec_from_main_thread-no-syscallbuf 2 0.293866\nexec_from_other_thread 2 16.1407\nexec_from_other_thread-no-syscallbuf 2 7.33557\nexec_stopsig 2 0.251712\nexec_stopsig-no-syscallbuf 2 0.344252\nexecveat 2 0.231512\nexecveat-no-syscallbuf 2 0.227455\nexit_with_syscallbuf_signal 2 0.217025\nexit_with_syscallbuf_signal-no-syscallbuf 2 0.167443\nfadvise 2 0.170039\nfadvise-no-syscallbuf 2 0.160222\nfanotify 2 0.174126\nfanotify-no-syscallbuf 2 0.166894\nfatal_init_signal 2 0.220292\nfatal_init_signal-no-syscallbuf 2 0.191934\nfatal_sigsegv_thread 2 0.645623\nfatal_sigsegv_thread-no-syscallbuf 2 0.624305\nx86/fault_in_code_page 2 0.18644\nx86/fault_in_code_page-no-syscallbuf 2 0.183687\nfcntl_dupfd 2 0.178214\nfcntl_dupfd-no-syscallbuf 2 0.18758\nfcntl_misc 2 0.178466\nfcntl_misc-no-syscallbuf 2 0.164349\nfcntl_notify 2 0.178185\nfcntl_notify-no-syscallbuf 2 0.17075\nfcntl_owner_ex 2 0.172739\nfcntl_owner_ex-no-syscallbuf 2 0.189245\nfcntl_rw_hints 2 0.177118\nfcntl_rw_hints-no-syscallbuf 2 0.169723\nfcntl_seals 2 0.169003\nfcntl_seals-no-syscallbuf 2 0.16143\nfcntl_sig 2 0.192377\nfcntl_sig-no-syscallbuf 2 0.172423\nfd_cleanup 2 0.181429\nfd_cleanup-no-syscallbuf 2 0.190582\nfd_tracking_across_threads 2 0.233957\nfd_tracking_across_threads-no-syscallbuf 2 0.202603\nfds_clean 2 0.281325\nfds_clean-no-syscallbuf 2 0.250604\nflock 2 0.684811\nflock-no-syscallbuf 2 1.10324\nflock_ofd 2 0.251028\nflock_ofd-no-syscallbuf 2 0.608903\nflock2 2 0.178437\nflock2-no-syscallbuf 2 0.166685\nfork_brk 2 0.22916\nfork_brk-no-syscallbuf 2 0.161856\nfork_child_crash 2 0.297335\nfork_child_crash-no-syscallbuf 2 0.305658\nfork_many 2 1.1968\nfork_many-no-syscallbuf 2 0.665619\nfutex_exit_race 2 0.580114\nfutex_exit_race-no-syscallbuf 2 0.402464\nfutex_exit_race_sigsegv 2 0.56445\nfutex_exit_race_sigsegv-no-syscallbuf 2 0.393731\nfutex_pi 2 0.215186\nfutex_pi-no-syscallbuf 2 0.181878\nfutex_priorities 2 0.261775\nfutex_priorities-no-syscallbuf 2 0.198346\nfutex_requeue 2 1.18771\nfutex_requeue-no-syscallbuf 2 1.18066\ngcrypt_rdrand 2 0.178023\ngcrypt_rdrand-no-syscallbuf 2 0.167756\ngetcpu 2 0.22876\ngetcpu-no-syscallbuf 2 0.167692\ngetgroups 2 0.172681\ngetgroups-no-syscallbuf 2 0.17935\ngetpwnam 2 0.237821\ngetpwnam-no-syscallbuf 2 0.32354\ngetrandom 2 0.204551\ngetrandom-no-syscallbuf 2 0.194019\nsetitimer 2 0.222777\nsetitimer-no-syscallbuf 2 0.175497\ngetsid 2 0.184714\ngetsid-no-syscallbuf 2 0.172561\ngettimeofday 2 0.179022\ngettimeofday-no-syscallbuf 2 0.18866\ngrandchild_threads 2 0.219542\ngrandchild_threads-no-syscallbuf 2 0.193676\ngrandchild_threads_main_running 2 2.24898\ngrandchild_threads_main_running-no-syscallbuf 2 2.27881\ngrandchild_threads_thread_running 2 5.26817\ngrandchild_threads_thread_running-no-syscallbuf 2 5.25683\ngrandchild_threads_parent_alive 2 0.197781\ngrandchild_threads_parent_alive-no-syscallbuf 2 0.224033\nx86/hle 2 1.06105\nx86/hle-no-syscallbuf 2 0.951817\ninotify 2 0.206718\ninotify-no-syscallbuf 2 0.161259\nint3 2 0.174208\nint3-no-syscallbuf 2 0.153777\nintr_futex_wait_restart 2 1.77408\nintr_futex_wait_restart-no-syscallbuf 2 1.69339\nintr_poll 2 3.71479\nintr_poll-no-syscallbuf 2 3.66918\nintr_ppoll 2 21.3612\nintr_ppoll-no-syscallbuf 2 21.3163\nintr_pselect 2 9.16476\nintr_pselect-no-syscallbuf 2 9.20851\nintr_read_no_restart 2 1.40236\nintr_read_no_restart-no-syscallbuf 2 1.32017\nintr_read_restart 2 2.42967\nintr_read_restart-no-syscallbuf 2 2.44465\nintr_sleep 2 4.18177\nintr_sleep-no-syscallbuf 2 4.16812\nintr_sleep_no_restart 2 2.16093\nintr_sleep_no_restart-no-syscallbuf 2 1.78601\ninvalid_exec 2 0.179465\ninvalid_exec-no-syscallbuf 2 0.174301\ninvalid_fcntl 2 0.175987\ninvalid_fcntl-no-syscallbuf 2 0.165666\ninvalid_ioctl 2 0.181297\ninvalid_ioctl-no-syscallbuf 2 0.176853\nio 2 0.171498\nio-no-syscallbuf 2 0.161433\nio_uring 2 0.170709\nio_uring-no-syscallbuf 2 0.225948\nioctl 2 0.182441\nioctl-no-syscallbuf 2 0.167527\nioctl_blk 2 0.176945\nioctl_blk-no-syscallbuf 2 0.184102\nioctl_fb 2 0.191506\nioctl_fb-no-syscallbuf 2 0.18009\nioctl_fs 2 0.185416\nioctl_fs-no-syscallbuf 2 0.183753\nioctl_pty 2 0.211126\nioctl_pty-no-syscallbuf 2 0.193052\nioctl_sg 2 0.18375\nioctl_sg-no-syscallbuf 2 0.16753\nioctl_tty 2 0.356545\nioctl_tty-no-syscallbuf 2 0.213868\nioctl_vt 2 0.244868\nioctl_vt-no-syscallbuf 2 0.159736\nioprio 2 0.169212\nioprio-no-syscallbuf 2 0.178082\nx86/ioperm 2 0.186083\nx86/ioperm-no-syscallbuf 2 0.164016\nx86/iopl 2 0.185867\nx86/iopl-no-syscallbuf 2 0.182458\njoin_threads 2 4.90819\njoin_threads-no-syscallbuf 2 3.54206\njoystick 2 0.159592\njoystick-no-syscallbuf 2 0.201406\nkcmp 2 0.19948\nkcmp-no-syscallbuf 2 0.168435\nkeyctl 2 0.187736\nkeyctl-no-syscallbuf 2 0.171832\nkill_newborn 2 0.413833\nkill_newborn-no-syscallbuf 2 0.300332\nkill_ptracee 2 1.81914\nkill_ptracee-no-syscallbuf 2 1.77773\nlarge_hole 2 0.188435\nlarge_hole-no-syscallbuf 2 0.170501\nlarge_write_deadlock 2 0.205733\nlarge_write_deadlock-no-syscallbuf 2 0.198197\nlegacy_ugid 2 0.165708\nlegacy_ugid-no-syscallbuf 2 0.182131\nx86/lsl 2 0.167781\nx86/lsl-no-syscallbuf 2 0.167028\nmadvise 2 0.190806\nmadvise-no-syscallbuf 2 0.196604\nmadvise_free 2 0.200002\nmadvise_free-no-syscallbuf 2 0.171689\nmadvise_wipeonfork 2 0.317507\nmadvise_wipeonfork-no-syscallbuf 2 0.348225\nmap_fixed 2 0.167354\nmap_fixed-no-syscallbuf 2 0.179426\nmap_shared_syscall 2 0.175052\nmap_shared_syscall-no-syscallbuf 2 0.170174\nmembarrier 2 0.228412\nmembarrier-no-syscallbuf 2 0.230171\nmemfd_create 2 0.182084\nmemfd_create-no-syscallbuf 2 0.169879\nmemfd_create_shared 2 0.222174\nmemfd_create_shared-no-syscallbuf 2 0.174558\nmemfd_create_shared_huge 2 0.185374\nmemfd_create_shared_huge-no-syscallbuf 2 0.223016\nmincore 2 0.174544\nmincore-no-syscallbuf 2 0.192059\nmknod 2 0.179847\nmknod-no-syscallbuf 2 0.196489\nmlock 2 0.173352\nmlock-no-syscallbuf 2 0.167404\nmmap_adjacent_to_rr_usage 2 0.17767\nmmap_adjacent_to_rr_usage-no-syscallbuf 2 0.186486\nmmap_private 2 1.12045\nmmap_private-no-syscallbuf 2 1.06585\nmmap_private_grow_under_map 2 0.189616\nmmap_private_grow_under_map-no-syscallbuf 2 0.155726\nmmap_recycle 2 0.20233\nmmap_recycle-no-syscallbuf 2 0.211311\nmmap_ro 2 0.185541\nmmap_ro-no-syscallbuf 2 0.169573\nmmap_self_maps_shared 2 0.229838\nmmap_self_maps_shared-no-syscallbuf 2 0.281218\nmmap_shared 2 0.191652\nmmap_shared-no-syscallbuf 2 0.220219\nmmap_shared_dev_zero 2 0.212095\nmmap_shared_dev_zero-no-syscallbuf 2 0.183368\nmmap_shared_grow 2 0.177507\nmmap_shared_grow-no-syscallbuf 2 0.178328\nmmap_shared_grow_under_map 2 0.199644\nmmap_shared_grow_under_map-no-syscallbuf 2 0.166737\nmmap_shared_multiple 2 0.19847\nmmap_shared_multiple-no-syscallbuf 2 0.157765\nmmap_shared_subpage 2 0.218759\nmmap_shared_subpage-no-syscallbuf 2 0.231295\nmmap_shared_write 2 6.26377\nmmap_shared_write-no-syscallbuf 2 7.91176\nmmap_shared_write_fork 2 0.237884\nmmap_shared_write_fork-no-syscallbuf 2 3.13827\nmmap_short_file 2 0.189922\nmmap_short_file-no-syscallbuf 2 0.171696\nmmap_write_complex 2 0.202205\nmmap_write_complex-no-syscallbuf 2 0.175287\nmmap_zero_size_fd 2 0.18312\nmmap_zero_size_fd-no-syscallbuf 2 0.162213\nx86/modify_ldt 2 0.188821\nx86/modify_ldt-no-syscallbuf 2 0.166663\nmount_ns_exec 2 0.23793\nmount_ns_exec-no-syscallbuf 2 0.250413\nmount_ns_exec2 2 0.24358\nmount_ns_exec2-no-syscallbuf 2 0.268304\nmprotect 2 0.191343\nmprotect-no-syscallbuf 2 0.166355\nmprotect_heterogenous 2 0.193389\nmprotect_heterogenous-no-syscallbuf 2 0.184813\nmprotect_none 2 0.19807\nmprotect_none-no-syscallbuf 2 0.172753\nmprotect_stack 2 0.171026\nmprotect_stack-no-syscallbuf 2 0.183265\nmq 2 2.18257\nmq-no-syscallbuf 2 2.24255\nmremap 2 2.04727\nmremap-no-syscallbuf 2 8.17459\nmremap_after_coalesce 2 0.17843\nmremap_after_coalesce-no-syscallbuf 2 0.20688\nmremap_grow 2 0.20804\nmremap_grow-no-syscallbuf 2 0.160446\nmremap_grow_shared 2 0.225226\nmremap_grow_shared-no-syscallbuf 2 0.16525\nmremap_non_page_size 2 0.177265\nmremap_non_page_size-no-syscallbuf 2 1.12233\nmremap_overwrite 2 0.17549\nmremap_overwrite-no-syscallbuf 2 0.160699\nmremap_private_grow_under_map 2 0.1715\nmremap_private_grow_under_map-no-syscallbuf 2 0.187527\nmremap_shrink 2 0.182712\nmremap_shrink-no-syscallbuf 2 0.167213\nmsg 2 1.72379\nmsg-no-syscallbuf 2 1.69238\nmsg_trunc 2 0.185576\nmsg_trunc-no-syscallbuf 2 0.170801\nmsync 2 1.10828\nmsync-no-syscallbuf 2 1.67113\nmtio 2 0.175655\nmtio-no-syscallbuf 2 0.185065\nmultiple_pending_signals 2 0.241691\nmultiple_pending_signals-no-syscallbuf 2 0.208994\nmultiple_pending_signals_sequential 2 0.228107\nmultiple_pending_signals_sequential-no-syscallbuf 2 0.247733\nmunmap_segv 2 0.187787\nmunmap_segv-no-syscallbuf 2 0.167144\nmunmap_discontinuous 2 0.178539\nmunmap_discontinuous-no-syscallbuf 2 0.168095\nnanosleep 2 1.17135\nnanosleep-no-syscallbuf 2 1.15676\nnetfilter 2 0.194444\nnetfilter-no-syscallbuf 2 0.247537\nnetlink_mmap_disable 2 0.179323\nnetlink_mmap_disable-no-syscallbuf 2 0.166943\nno_mask_timeslice 2 1.0076\nno_mask_timeslice-no-syscallbuf 2 0.869596\nnscd 2 0.166578\nnscd-no-syscallbuf 2 0.17653\nnuma 2 0.183699\nnuma-no-syscallbuf 2 0.199299\nx86/old_fork 2 0.180442\nx86/old_fork-no-syscallbuf 2 0.218585\norphan_process 2 0.197056\norphan_process-no-syscallbuf 2 0.188056\npacket_mmap_disable 2 0.183351\npacket_mmap_disable-no-syscallbuf 2 0.193332\npause 2 1.15275\npause-no-syscallbuf 2 1.17576\nperf_event 2 0.204277\nperf_event-no-syscallbuf 2 0.174976\npersonality 2 0.203447\npersonality-no-syscallbuf 2 0.18611\npid_ns_kill_child 2 0.46607\npid_ns_kill_child-no-syscallbuf 2 0.252649\npid_ns_kill_child_threads 2 0.239128\npid_ns_kill_child_threads-no-syscallbuf 2 0.204937\npid_ns_kill_child_zombie 2 0.275996\npid_ns_kill_child_zombie-no-syscallbuf 2 0.194321\npid_ns_kill_threads 2 0.269501\npid_ns_kill_threads-no-syscallbuf 2 0.216829\npid_ns_kill_threads_exit_wait 2 0.279025\npid_ns_kill_threads_exit_wait-no-syscallbuf 2 0.265377\npid_ns_reap 2 0.253094\npid_ns_reap-no-syscallbuf 2 0.221562\npid_ns_segv 2 0.305488\npid_ns_segv-no-syscallbuf 2 0.296093\npid_ns_shutdown 2 0.425677\npid_ns_shutdown-no-syscallbuf 2 0.401956\npidfd 2 0.239427\npidfd-no-syscallbuf 2 0.178746\nx86/pkeys 2 0.195752\nx86/pkeys-no-syscallbuf 2 0.151316\npoll_sig_race 2 2.97674\npoll_sig_race-no-syscallbuf 2 2.9028\nppoll 2 5.72922\nppoll-no-syscallbuf 2 5.73113\nprctl 2 0.207562\nprctl-no-syscallbuf 2 0.213663\nprctl_caps 2 0.522074\nprctl_caps-no-syscallbuf 2 0.399332\nprctl_deathsig 2 0.202488\nprctl_deathsig-no-syscallbuf 2 0.172917\nprctl_name 2 0.27457\nprctl_name-no-syscallbuf 2 0.272148\nprctl_short_name 2 0.2066\nprctl_short_name-no-syscallbuf 2 0.177081\nprctl_speculation_ctrl 2 0.197116\nprctl_speculation_ctrl-no-syscallbuf 2 0.161439\nx86/prctl_tsc 2 0.179877\nx86/prctl_tsc-no-syscallbuf 2 0.190523\nprivileged_net_ioctl 2 0.364182\nprivileged_net_ioctl-no-syscallbuf 2 0.405736\nproc_fds 2 0.805502\nproc_fds-no-syscallbuf 2 0.599653\nproc_mem 2 0.337102\nproc_mem-no-syscallbuf 2 0.315536\nprotect_rr_fds 2 3.74297\nprotect_rr_fds-no-syscallbuf 2 3.30292\nprw 2 0.168392\nprw-no-syscallbuf 2 0.194568\npthread_condvar_locking 2 0.185851\npthread_condvar_locking-no-syscallbuf 2 0.214291\npthread_mutex_timedlock 2 0.158389\npthread_mutex_timedlock-no-syscallbuf 2 0.183897\npthread_pi_mutex 2 0.205553\npthread_pi_mutex-no-syscallbuf 2 0.16821\npthread_rwlocks 2 0.211671\npthread_rwlocks-no-syscallbuf 2 0.196137\nx86/ptrace 2 0.225648\nx86/ptrace-no-syscallbuf 2 0.214048\nptrace_attach_null_status 2 0.239081\nptrace_attach_null_status-no-syscallbuf 2 0.236807\nptrace_attach_running 2 0.323048\nptrace_attach_running-no-syscallbuf 2 0.318352\nptrace_attach_sleeping 2 0.252628\nptrace_attach_sleeping-no-syscallbuf 2 0.212059\nptrace_attach_stopped 2 0.238656\nptrace_attach_stopped-no-syscallbuf 2 0.232865\nptrace_attach_thread_running 2 7.74088\nptrace_attach_thread_running-no-syscallbuf 2 9.15948\nptrace_breakpoint 2 0.205013\nptrace_breakpoint-no-syscallbuf 2 0.201343\nptrace_change_patched_syscall 2 0.195804\nptrace_change_patched_syscall-no-syscallbuf 2 0.195317\nx86/ptrace_debug_regs 2 0.193017\nx86/ptrace_debug_regs-no-syscallbuf 2 0.184957\nptrace_exec 2 0.301733\nptrace_exec-no-syscallbuf 2 0.29256\nx86/ptrace_exec32 2 0.182961\nx86/ptrace_exec32-no-syscallbuf 2 0.171233\nptrace_kill_grandtracee 2 0.200743\nptrace_kill_grandtracee-no-syscallbuf 2 0.213814\nx86/ptrace_tls 2 0.249886\nx86/ptrace_tls-no-syscallbuf 2 0.223517\nptrace_seize 2 0.188635\nptrace_seize-no-syscallbuf 2 0.195198\nptrace_sigchld_blocked 2 0.18947\nptrace_sigchld_blocked-no-syscallbuf 2 0.168162\nptrace_signals 2 0.345102\nptrace_signals-no-syscallbuf 2 0.289898\nptrace_singlestep 2 0.421221\nptrace_singlestep-no-syscallbuf 2 0.194343\nptrace_syscall 2 0.218101\nptrace_syscall-no-syscallbuf 2 0.179181\nptrace_syscall_clone_untraced 2 0.253265\nptrace_syscall_clone_untraced-no-syscallbuf 2 0.273692\nx86/ptrace_sysemu 2 0.280929\nx86/ptrace_sysemu-no-syscallbuf 2 0.260563\nptrace_sysemu_syscall 2 0.237037\nptrace_sysemu_syscall-no-syscallbuf 2 0.195508\nptrace_trace_clone 2 0.239851\nptrace_trace_clone-no-syscallbuf 2 0.228288\nptrace_trace_exit 2 0.193537\nptrace_trace_exit-no-syscallbuf 2 0.205698\nptrace_traceme 2 0.23772\nptrace_traceme-no-syscallbuf 2 0.186207\nptracer_death 2 0.231978\nptracer_death-no-syscallbuf 2 0.21803\nptracer_death_multithread 2 0.438148\nptracer_death_multithread-no-syscallbuf 2 0.64384\nptracer_death_multithread_peer 2 0.423491\nptracer_death_multithread_peer-no-syscallbuf 2 0.454556\nquotactl 2 0.217318\nquotactl-no-syscallbuf 2 0.195922\nx86/rdtsc 2 0.259211\nx86/rdtsc-no-syscallbuf 2 0.237116\nread_nothing 2 8.08106\nread_nothing-no-syscallbuf 2 14.8259\nreaddir 2 0.188428\nreaddir-no-syscallbuf 2 0.173345\nread_large 2 0.445476\nread_large-no-syscallbuf 2 1.57062\nread_oversize 2 0.179858\nread_oversize-no-syscallbuf 2 0.178238\nreadlink 2 0.188913\nreadlink-no-syscallbuf 2 0.225705\nreadlinkat 2 0.183314\nreadlinkat-no-syscallbuf 2 0.202814\nreadv 2 0.188892\nreadv-no-syscallbuf 2 0.184751\nrecord_replay_subject 2 3.55163\nrecord_replay_subject-no-syscallbuf 2 3.51079\nrecvfrom 2 0.167764\nrecvfrom-no-syscallbuf 2 0.21244\nredzone_integrity 2 1.14234\nredzone_integrity-no-syscallbuf 2 1.15655\nrename 2 0.184375\nrename-no-syscallbuf 2 0.167062\nrlimit 2 0.2005\nrlimit-no-syscallbuf 2 0.170453\nrobust_futex 2 0.212345\nrobust_futex-no-syscallbuf 2 0.206051\nrusage 2 0.19015\nrusage-no-syscallbuf 2 0.165888\nsamask 2 0.38831\nsamask-no-syscallbuf 2 0.328854\nsave_data_fd 2 0.177818\nsave_data_fd-no-syscallbuf 2 0.16115\nsched_attr 2 0.178041\nsched_attr-no-syscallbuf 2 0.199286\nsched_setaffinity 2 0.190171\nsched_setaffinity-no-syscallbuf 2 0.177428\nsched_setparam 2 0.183471\nsched_setparam-no-syscallbuf 2 0.164994\nsched_yield 2 0.270152\nsched_yield-no-syscallbuf 2 0.240553\nsched_yield_to_lower_priority 2 0.183273\nsched_yield_to_lower_priority-no-syscallbuf 2 0.190446\nscm_rights 2 0.671003\nscm_rights-no-syscallbuf 2 0.687657\nscratch_read 2 0.197939\nscratch_read-no-syscallbuf 2 0.186784\nseccomp 2 0.212935\nseccomp-no-syscallbuf 2 0.201332\nseccomp_cloning 2 0.186753\nseccomp_cloning-no-syscallbuf 2 0.181473\nseccomp_clone_fail 2 0.172286\nseccomp_clone_fail-no-syscallbuf 2 0.179858\nseccomp_desched 2 0.24543\nseccomp_desched-no-syscallbuf 2 0.181397\nseccomp_kill_exit 2 0.198507\nseccomp_kill_exit-no-syscallbuf 2 0.189345\nseccomp_null 2 0.178688\nseccomp_null-no-syscallbuf 2 0.231606\nseccomp_sigsys_args 2 0.181621\nseccomp_sigsys_args-no-syscallbuf 2 0.178718\nseccomp_sigsys_sigtrap 2 0.184341\nseccomp_sigsys_sigtrap-no-syscallbuf 2 0.185873\nseccomp_sigsys_syscallbuf 2 0.177722\nseccomp_sigsys_syscallbuf-no-syscallbuf 2 0.21653\nseccomp_tsync 2 0.224772\nseccomp_tsync-no-syscallbuf 2 0.198235\nseccomp_veto_exec 2 0.238224\nseccomp_veto_exec-no-syscallbuf 2 0.182102\nself_shebang 2 0.209619\nself_shebang-no-syscallbuf 2 0.234194\nself_sigint 2 0.16655\nself_sigint-no-syscallbuf 2 0.162785\nsem 2 0.240934\nsem-no-syscallbuf 2 0.220949\nsend_block 2 0.254059\nsend_block-no-syscallbuf 2 1.77992\nsendfile 2 0.198339\nsendfile-no-syscallbuf 2 0.186502\nset_ptracer 2 0.161933\nset_ptracer-no-syscallbuf 2 0.17299\nset_tid_address 2 0.190797\nset_tid_address-no-syscallbuf 2 0.189553\nsetgid 2 0.173111\nsetgid-no-syscallbuf 2 0.152735\nsetgroups 2 0.181831\nsetgroups-no-syscallbuf 2 0.162135\nsetsid 2 0.188063\nsetsid-no-syscallbuf 2 0.187996\nsetuid 2 0.360408\nsetuid-no-syscallbuf 2 0.245904\nshared_exec 2 0.172825\nshared_exec-no-syscallbuf 2 0.174199\nshared_monitor 2 0.172391\nshared_monitor-no-syscallbuf 2 0.168222\nshared_offset 2 0.242735\nshared_offset-no-syscallbuf 2 0.162085\nshared_write 2 0.183634\nshared_write-no-syscallbuf 2 0.178486\nshm 2 0.220493\nshm-no-syscallbuf 2 0.241913\nshm_unmap 2 0.186592\nshm_unmap-no-syscallbuf 2 0.170327\nsigaction_old 2 0.19866\nsigaction_old-no-syscallbuf 2 0.220548\nsigaltstack 2 0.180545\nsigaltstack-no-syscallbuf 2 0.1682\nsigchld_interrupt_signal 2 5.15186\nsigchld_interrupt_signal-no-syscallbuf 2 4.65416\nsigcont 2 0.189647\nsigcont-no-syscallbuf 2 0.192489\nsighandler_bad_rsp_sigsegv 2 0.192811\nsighandler_bad_rsp_sigsegv-no-syscallbuf 2 0.16453\nsighandler_fork 2 0.25179\nsighandler_fork-no-syscallbuf 2 0.223138\nsighandler_mask 2 0.192857\nsighandler_mask-no-syscallbuf 2 0.169821\nsigill 2 0.197423\nsigill-no-syscallbuf 2 0.153897\nsignal_deferred 2 0.206914\nsignal_deferred-no-syscallbuf 2 0.201921\nsignal_during_preload_init 2 0.207008\nsignal_during_preload_init-no-syscallbuf 2 0.195584\nsignal_frame 2 0.196477\nsignal_frame-no-syscallbuf 2 0.176133\nsignal_unstoppable 2 0.202938\nsignal_unstoppable-no-syscallbuf 2 0.181003\nsignalfd 2 0.174708\nsignalfd-no-syscallbuf 2 0.174824\nsigprocmask 2 0.553978\nsigprocmask-no-syscallbuf 2 0.545624\nsigprocmask_ensure_delivery 2 0.198806\nsigprocmask_ensure_delivery-no-syscallbuf 2 0.211635\nsigprocmask_exec 2 0.235655\nsigprocmask_exec-no-syscallbuf 2 0.224897\nsigprocmask_evil 2 0.163768\nsigprocmask_evil-no-syscallbuf 2 0.171957\nsigprocmask_in_syscallbuf_sighandler 2 1.15345\nsigprocmask_in_syscallbuf_sighandler-no-syscallbuf 2 1.14064\nsigprocmask_rr_sigs 2 0.203026\nsigprocmask_rr_sigs-no-syscallbuf 2 0.178018\nsigprocmask_syscallbuf 2 0.197603\nsigprocmask_syscallbuf-no-syscallbuf 2 0.183032\nsigqueueinfo 2 0.176825\nsigqueueinfo-no-syscallbuf 2 0.222178\nx86/sigreturn 2 0.207268\nx86/sigreturn-no-syscallbuf 2 0.203306\nsigreturn_reg 2 0.163808\nsigreturn_reg-no-syscallbuf 2 0.208531\nsigreturnmask 2 0.386215\nsigreturnmask-no-syscallbuf 2 0.342396\nsigrt 2 0.286826\nsigrt-no-syscallbuf 2 0.279347\nsigstop 2 0.259614\nsigstop-no-syscallbuf 2 0.223598\nsigstop2 2 0.2055\nsigstop2-no-syscallbuf 2 0.173578\nsigsuspend 2 0.193424\nsigsuspend-no-syscallbuf 2 0.208011\nsigtrap 2 0.208714\nsigtrap-no-syscallbuf 2 0.193717\nsimple_threads_stress 2 2.02023\nsimple_threads_stress-no-syscallbuf 2 2.52639\nsioc 2 0.611289\nsioc-no-syscallbuf 2 0.791008\nsmall_holes 2 0.186866\nsmall_holes-no-syscallbuf 2 0.160374\nsock_names_opts 2 0.196644\nsock_names_opts-no-syscallbuf 2 0.200876\nspinlock_priorities 2 0.883957\nspinlock_priorities-no-syscallbuf 2 1.77485\nsplice 2 0.1984\nsplice-no-syscallbuf 2 0.168069\nstack_growth_after_syscallbuf 2 0.184737\nstack_growth_after_syscallbuf-no-syscallbuf 2 0.180046\nstack_growth_syscallbuf 2 0.260481\nstack_growth_syscallbuf-no-syscallbuf 2 9.22802\nstack_growth_with_guard 2 0.203816\nstack_growth_with_guard-no-syscallbuf 2 0.187512\nstack_invalid 2 0.207892\nstack_invalid-no-syscallbuf 2 0.178875\nstack_overflow 2 0.291206\nstack_overflow-no-syscallbuf 2 0.270871\nstack_overflow_altstack 2 0.179979\nstack_overflow_altstack-no-syscallbuf 2 0.1755\nstack_overflow_with_guard 2 0.269542\nstack_overflow_with_guard-no-syscallbuf 2 0.235477\nstatfs 2 0.180439\nstatfs-no-syscallbuf 2 0.205603\nstatx 2 0.194644\nstatx-no-syscallbuf 2 0.163539\nstdout_child 2 0.225356\nstdout_child-no-syscallbuf 2 0.25816\nstdout_cloexec 2 0.258915\nstdout_cloexec-no-syscallbuf 2 0.218053\nstdout_dup 2 0.184115\nstdout_dup-no-syscallbuf 2 0.153221\nstdout_redirect 2 0.324121\nstdout_redirect-no-syscallbuf 2 0.236225\nswitch_read 2 0.69731\nswitch_read-no-syscallbuf 2 0.670853\nsymlink 2 0.185111\nsymlink-no-syscallbuf 2 0.19091\nsync 2 0.23794\nsync-no-syscallbuf 2 0.18673\nsync_file_range 2 0.173225\nsync_file_range-no-syscallbuf 2 0.236857\nsyscall_bp 2 0.177799\nsyscall_bp-no-syscallbuf 2 0.156245\nsyscall_in_writable_mem 2 0.174906\nsyscall_in_writable_mem-no-syscallbuf 2 0.177983\nsyscallbuf_signal_reset 2 0.183644\nsyscallbuf_signal_reset-no-syscallbuf 2 0.184238\nsyscallbuf_signal_blocking 2 0.190065\nsyscallbuf_signal_blocking-no-syscallbuf 2 0.198511\nsyscallbuf_sigstop 2 9.68564\nsyscallbuf_sigstop-no-syscallbuf 2 28.1754\nsyscallbuf_timeslice 2 0.251698\nsyscallbuf_timeslice-no-syscallbuf 2 3.52121\nsyscallbuf_timeslice2 2 0.249679\nsyscallbuf_timeslice2-no-syscallbuf 2 9.23084\nsysconf 2 0.186269\nsysconf-no-syscallbuf 2 0.159917\nsysctl 2 0.185003\nsysctl-no-syscallbuf 2 0.158481\nsysemu_singlestep 2 0.182821\nsysemu_singlestep-no-syscallbuf 2 0.162622\nx86/sysfs 2 0.227965\nx86/sysfs-no-syscallbuf 2 0.237494\nsysinfo 2 0.193888\nsysinfo-no-syscallbuf 2 0.164539\ntgkill 2 0.238723\ntgkill-no-syscallbuf 2 0.185187\nthread_yield 2 5.33778\nthread_yield-no-syscallbuf 2 3.68714\ntimer 2 63.0617\ntimer-no-syscallbuf 2 65.8362\ntimerfd 2 0.313991\ntimerfd-no-syscallbuf 2 0.272372\ntimes 2 0.20467\ntimes-no-syscallbuf 2 0.160248\ntruncate_temp 2 0.208904\ntruncate_temp-no-syscallbuf 2 0.200974\ntun 2 0.258967\ntun-no-syscallbuf 2 0.207755\ntwo_signals_with_mask 2 0.191743\ntwo_signals_with_mask-no-syscallbuf 2 0.177604\nulimit_low 2 0.193423\nulimit_low-no-syscallbuf 2 0.187551\nuname 2 0.189885\nuname-no-syscallbuf 2 0.16555\nunexpected_exit 2 0.244427\nunexpected_exit-no-syscallbuf 2 0.54684\nunexpected_exit_execve 2 0.267448\nunexpected_exit_execve-no-syscallbuf 2 0.494722\nunexpected_exit_execve_twice 2 1.3297\nunexpected_exit_execve_twice-no-syscallbuf 2 1.43974\nunexpected_exit_pid_ns 2 0.741595\nunexpected_exit_pid_ns-no-syscallbuf 2 0.233324\nunjoined_thread 2 0.182445\nunjoined_thread-no-syscallbuf 2 0.172195\nunshare 2 0.35039\nunshare-no-syscallbuf 2 1.13442\nuserfaultfd 2 0.169134\nuserfaultfd-no-syscallbuf 2 0.183975\nutimes 2 0.189225\nutimes-no-syscallbuf 2 0.168458\nvdso_parts 2 0.166982\nvdso_parts-no-syscallbuf 2 0.159098\nvfork_flush 2 0.20091\nvfork_flush-no-syscallbuf 2 0.169755\nvfork_shared 2 0.267209\nvfork_shared-no-syscallbuf 2 0.171063\nvideo_capture 2 0.17876\nvideo_capture-no-syscallbuf 2 0.184013\nvm_readv_writev 2 0.206471\nvm_readv_writev-no-syscallbuf 2 0.189777\nvsyscall 2 0.198179\nvsyscall-no-syscallbuf 2 0.18036\nvsyscall_timeslice 2 0.174966\nvsyscall_timeslice-no-syscallbuf 2 0.223726\nx86/x87env 2 0.192093\nx86/x87env-no-syscallbuf 2 0.220662\nwait 2 0.246499\nwait-no-syscallbuf 2 0.176315\nwait_sigstop 2 0.229046\nwait_sigstop-no-syscallbuf 2 0.194761\nwrite_race 2 2.69864\nwrite_race-no-syscallbuf 2 1.78352\nwritev 2 0.277556\nwritev-no-syscallbuf 2 0.195201\nxattr 2 0.187474\nxattr-no-syscallbuf 2 0.194899\nzero_length_read 2 0.1832\nzero_length_read-no-syscallbuf 2 0.169866\nstd_random 2 0.229802\nstd_random-no-syscallbuf 2 0.241042\nunwind_rr_page 2 1.15824\nunwind_rr_page-no-syscallbuf 2 1.1443\nabort_nonmain 2 0.477139\nabort_nonmain-no-syscallbuf 2 0.439677\nalternate_thread_diversion 2 0.937585\nalternate_thread_diversion-no-syscallbuf 2 0.893965\nargs 2 0.204811\nargs-no-syscallbuf 2 0.165566\nasync_kill_with_syscallbuf 2 2.82132\nasync_kill_with_syscallbuf-no-syscallbuf 2 3.81114\nasync_kill_with_syscallbuf2 2 2.27422\nasync_kill_with_syscallbuf2-no-syscallbuf 2 2.30266\nasync_kill_with_threads 2 2.21251\nasync_kill_with_threads-no-syscallbuf 2 2.31443\nasync_kill_with_threads_main_running 2 2.28136\nasync_kill_with_threads_main_running-no-syscallbuf 2 2.30519\nasync_kill_with_threads_thread_running 2 6.19838\nasync_kill_with_threads_thread_running-no-syscallbuf 2 6.15817\nasync_segv 2 4.7611\nasync_segv-no-syscallbuf 2 4.72077\nasync_signal_syscalls 2 1.11327\nasync_signal_syscalls-no-syscallbuf 2 0.0309316\nasync_signal_syscalls2 2 0.609031\nasync_signal_syscalls2-no-syscallbuf 2 0.0218664\nasync_signal_syscalls_siginfo 2 1.06276\nasync_signal_syscalls_siginfo-no-syscallbuf 2 0.0292908\nasync_usr1 2 4.92085\nasync_usr1-no-syscallbuf 2 4.47758\nblacklist 2 0.302815\nblacklist-no-syscallbuf 2 0.178595\nblock_clone_checkpoint 2 1.12958\nblock_clone_checkpoint-no-syscallbuf 2 1.19362\nblock_clone_interrupted 2 6.1536\nblock_clone_interrupted-no-syscallbuf 2 5.39331\nblock_clone_syscallbuf_overflow 2 3.62867\nblock_clone_syscallbuf_overflow-no-syscallbuf 2 7.05479\nblock_intr_sigchld 2 7.05565\nblock_intr_sigchld-no-syscallbuf 2 5.91357\nblocked_bad_ip 2 1.66722\nblocked_bad_ip-no-syscallbuf 2 1.21329\nblocked_sigill 2 0.475554\nblocked_sigill-no-syscallbuf 2 0.473601\nx86/blocked_sigsegv 2 0.454217\nx86/blocked_sigsegv-no-syscallbuf 2 0.409446\nbreakpoint 2 0.884155\nbreakpoint-no-syscallbuf 2 0.911315\nbreakpoint_conditions 2 0.970024\nbreakpoint_conditions-no-syscallbuf 2 1.02469\nbreakpoint_overlap 2 0.936155\nbreakpoint_overlap-no-syscallbuf 2 0.985176\ncall_function 2 0.946274\ncall_function-no-syscallbuf 2 0.90338\ncall_gettid 2 0.958785\ncall_gettid-no-syscallbuf 2 0.903787\ncheckpoint_dying_threads 2 0.936716\ncheckpoint_dying_threads-no-syscallbuf 2 0.896077\ncheckpoint_mixed_mode 2 1.07028\ncheckpoint_mixed_mode-no-syscallbuf 2 1.19646\nchecksum_sanity 2 2.8623\nchecksum_sanity-no-syscallbuf 2 1.60946\ncheck_lost_interrupts 2 1.68794\ncheck_lost_interrupts-no-syscallbuf 2 0.0205135\nclone_interruption 2 1.16011\nclone_interruption-no-syscallbuf 2 1.75708\nclone_vfork 2 0.316896\nclone_vfork-no-syscallbuf 2 0.238336\nconditional_breakpoint_calls 2 0.952078\nconditional_breakpoint_calls-no-syscallbuf 2 0.973057\nconditional_breakpoint_offload 2 96.5987\nconditional_breakpoint_offload-no-syscallbuf 2 90.719\ncondvar_stress 2 18.4794\ncondvar_stress-no-syscallbuf 2 29.7448\ncont_race 2 16.5406\ncont_race-no-syscallbuf 2 58.61349\nx86/cpuid_singlestep 2 0.841225\nx86/cpuid_singlestep-no-syscallbuf 2 0.858188\ncrash 2 0.417805\ncrash-no-syscallbuf 2 0.399749\ncrash_in_function 2 1.48377\ncrash_in_function-no-syscallbuf 2 1.42794\ndaemon_read 2 0.29565\ndaemon_read-no-syscallbuf 2 0.219573\ndconf_mock 2 0.20348\ndconf_mock-no-syscallbuf 2 0.186553\ndev_tty 2 0.168707\ndev_tty-no-syscallbuf 2 0.153884\ndiversion_sigtrap 2 1.33568\ndiversion_sigtrap-no-syscallbuf 2 1.33729\ndiversion_syscall 2 1.11462\ndiversion_syscall-no-syscallbuf 2 1.09594\ndlopen 2 8.35142\ndlopen-no-syscallbuf 2 6.31706\nearly_error 2 0.473624\nearly_error-no-syscallbuf 2 0.483345\nelapsed_time 2 1.85922\nelapsed_time-no-syscallbuf 2 1.81124\nexclusion_region 2 3.07792\nexclusion_region-no-syscallbuf 2 2.39734\nexec_failed 2 0.878224\nexec_failed-no-syscallbuf 2 0.87247\nexec_many 2 7.13534\nexec_many-no-syscallbuf 2 14.2697\nexecve_loop 2 7.54661\nexecve_loop-no-syscallbuf 2 5.2741\nexit_codes 2 0.478534\nexit_codes-no-syscallbuf 2 0.450373\nexit_group 2 0.184202\nexit_group-no-syscallbuf 2 0.196952\nexit_race 2 1.99785\nexit_race-no-syscallbuf 2 1.24573\nexit_status 2 0.129751\nexit_status-no-syscallbuf 2 0.11848\nx86/explicit_checkpoints 2 2.24325\nx86/explicit_checkpoints-no-syscallbuf 2 2.22522\nfd_limit 2 0.226523\nfd_limit-no-syscallbuf 2 1.05535\nfork_stress 2 2.18227\nfork_stress-no-syscallbuf 2 1.28322\nfork_syscalls 2 0.184567\nfork_syscalls-no-syscallbuf 2 0.223932\nfunction_calls 2 2.89782\nfunction_calls-no-syscallbuf 2 2.684\nx86/fxregs 2 0.885736\nx86/fxregs-no-syscallbuf 2 0.903752\ngetcwd 2 0.161177\ngetcwd-no-syscallbuf 2 0.164677\ngdb_bogus_breakpoint 2 0.858367\ngdb_bogus_breakpoint-no-syscallbuf 2 0.868942\ngoto_event 2 3.62863\ngoto_event-no-syscallbuf 2 3.38462\nhello 2 0.178746\nhello-no-syscallbuf 2 0.168594\nhooks 2 0.723224\nhooks-no-syscallbuf 2 0.0217813\nignored_async_usr1 2 4.34846\nignored_async_usr1-no-syscallbuf 2 2.41312\nignored_sigsegv 2 0.512287\nignored_sigsegv-no-syscallbuf 2 0.48108\nignore_nested 2 0.319942\nignore_nested-no-syscallbuf 2 0.329892\nimmediate_restart 2 1.10799\nimmediate_restart-no-syscallbuf 2 1.05464\nx86/int3_ok 2 0.196394\nx86/int3_ok-no-syscallbuf 2 0.164032\ninterrupt 2 5.08432\ninterrupt-no-syscallbuf 2 5.10831\nintr_ptrace_decline 2 4.76314\nintr_ptrace_decline-no-syscallbuf 2 4.71857\ninvalid_interpreter 2 1.39091\ninvalid_interpreter-no-syscallbuf 2 1.42361\ninvalid_jump 2 3.35074\ninvalid_jump-no-syscallbuf 2 2.0456\njit_proc_mem 2 0.923116\njit_proc_mem-no-syscallbuf 2 0.903665\nlink 2 0.196809\nlink-no-syscallbuf 2 0.202282\nmadvise_dontfork 2 1.23451\nmadvise_dontfork-no-syscallbuf 2 1.13971\nmain_thread_exit 2 1.27429\nmain_thread_exit-no-syscallbuf 2 1.21927\nmany_yields 2 3.52293\nmany_yields-no-syscallbuf 2 2.76882\nmmap_fd_reuse_checkpoint 2 1.20862\nmmap_fd_reuse_checkpoint-no-syscallbuf 2 1.17124\nmmap_replace_most_mappings 2 2.06602\nmmap_replace_most_mappings-no-syscallbuf 2 2.16168\nmmap_shared_prot 2 1.11115\nmmap_shared_prot-no-syscallbuf 2 1.139\nmmap_shared_write_exec_race 2 1.18982\nmmap_shared_write_exec_race-no-syscallbuf 2 3.74276\nmmap_tmpfs 2 0.203215\nmmap_tmpfs-no-syscallbuf 2 0.183339\nmmap_write 2 0.0232375\nmmap_write-no-syscallbuf 2 0.0192538\nmmap_write_private 2 0.33905\nmmap_write_private-no-syscallbuf 2 0.278782\nmorestack_unwind 1 0.810541\nmorestack_unwind-no-syscallbuf 1 0.0187404\nmprotect_growsdown 2 0.334716\nmprotect_growsdown-no-syscallbuf 2 0.307453\nmprotect_syscallbuf_overflow 2 0.286063\nmprotect_syscallbuf_overflow-no-syscallbuf 2 14.2703\nmutex_pi_stress 2 20.6333\nmutex_pi_stress-no-syscallbuf 2 27.5912\nnested_detach_wait 2 0.571855\nnested_detach_wait-no-syscallbuf 2 0.56148\noverflow_branch_counter 2 3.09102\noverflow_branch_counter-no-syscallbuf 2 3.21047\npatch_page_end 2 0.21362\npatch_page_end-no-syscallbuf 2 0.0250506\nx86/patch_40_80_f6_81 2 0.195303\nx86/patch_40_80_f6_81-no-syscallbuf 2 0.021418\nperf_event_mmap 2 1.40858\nperf_event_mmap-no-syscallbuf 2 1.49223\npriority 2 0.177644\npriority-no-syscallbuf 2 0.181065\nptrace_remote_unmap 2 4.98646\nptrace_remote_unmap-no-syscallbuf 2 3.95753\nread_big_struct 2 0.911023\nread_big_struct-no-syscallbuf 2 0.917618\nremove_latest_trace 2 1.27511\nremove_latest_trace-no-syscallbuf 2 1.20751\nrestart_abnormal_exit 2 1.33336\nrestart_abnormal_exit-no-syscallbuf 2 1.30786\nreverse_continue_breakpoint 2 1.8994\nreverse_continue_breakpoint-no-syscallbuf 2 1.58048\nreverse_continue_multiprocess 2 10.9357\nreverse_continue_multiprocess-no-syscallbuf 2 9.9408\nreverse_continue_process_signal 2 3.25294\nreverse_continue_process_signal-no-syscallbuf 2 3.37532\nreverse_many_breakpoints 2 4.68598\nreverse_many_breakpoints-no-syscallbuf 2 4.30084\nreverse_step_long 2 6.00979\nreverse_step_long-no-syscallbuf 2 7.54732\nreverse_step_threads 2 3.28319\nreverse_step_threads-no-syscallbuf 2 3.54332\nreverse_step_threads_break 2 4.64687\nreverse_step_threads_break-no-syscallbuf 2 3.3659\nrr_ps 2 0.430032\nrr_ps-no-syscallbuf 2 0.374333\nrr_ps_ns 2 0.214954\nrr_ps_ns-no-syscallbuf 2 0.183478\nrseq 2 20.632\nrseq-no-syscallbuf 2 20.3601\nsearch 2 0.934634\nsearch-no-syscallbuf 2 0.899349\nseccomp_blocks_rr 2 0.419835\nseccomp_blocks_rr-no-syscallbuf 2 0.168566\nseccomp_signals 2 2.46697\nseccomp_signals-no-syscallbuf 2 1.80603\nsegfault 2 0.184121\nsegfault-no-syscallbuf 2 0.171907\nshared_map 2 0.226207\nshared_map-no-syscallbuf 2 0.237703\nshared_persistent_file 2 1.2057\nshared_persistent_file-no-syscallbuf 2 1.19317\nsignal_numbers 2 1.16584\nsignal_numbers-no-syscallbuf 2 1.16436\nsigprocmask_race 2 0.201165\nsigprocmask_race-no-syscallbuf 2 0.0287277\nsigprocmask_rr_sigs_nondefault 2 0.0871455\nsigprocmask_rr_sigs_nondefault-no-syscallbuf 2 0.0841662\nsimple 2 0.302632\nsimple-no-syscallbuf 2 0.26711\nx86/singlestep_pushf 2 0.892934\nx86/singlestep_pushf-no-syscallbuf 2 0.900637\nstack_growth 2 0.89189\nstack_growth-no-syscallbuf 2 0.866447\nstep_thread 2 2.30356\nstep_thread-no-syscallbuf 2 1.30052\nstrict_priorities 2 12.1928\nstrict_priorities-no-syscallbuf 2 12.6763\nx86/string_instructions 2 0.595723\nx86/string_instructions-no-syscallbuf 2 0.760244\nx86/string_instructions_async_signals 2 0.232696\nx86/string_instructions_async_signals-no-syscallbuf 2 71.325464\nx86/string_instructions_async_signals_shared 2 0.28007\nx86/string_instructions_async_signals_shared-no-syscallbuf 2 96.599713\nx86/string_instructions_multiwatch 2 0.942324\nx86/string_instructions_multiwatch-no-syscallbuf 2 0.880441\nx86/string_instructions_replay 2 13.4061\nx86/string_instructions_replay-no-syscallbuf 2 13.7113\nx86/string_instructions_singlestep_fastforward 2 7.56842\nx86/string_instructions_singlestep_fastforward-no-syscallbuf 2 7.6374\nx86/string_instructions_watch 2 0.930721\nx86/string_instructions_watch-no-syscallbuf 2 0.889983\nsyscallbuf_fd_disabling 2 0.271232\nsyscallbuf_fd_disabling-no-syscallbuf 2 0.228286\nsyscallbuf_signal_blocking_read 2 1.02176\nsyscallbuf_signal_blocking_read-no-syscallbuf 2 1.43656\nsysconf_onln 2 0.35877\nsysconf_onln-no-syscallbuf 2 0.31309\ntarget_fork 2 1.73477\ntarget_fork-no-syscallbuf 2 1.63206\ntarget_process 2 1.7258\ntarget_process-no-syscallbuf 2 1.50867\ntcp_sockets 2 0.156821\ntcp_sockets-no-syscallbuf 2 0.155016\nterm_nonmain 2 0.177305\nterm_nonmain-no-syscallbuf 2 0.213272\nterm_rr 2 3.42756\nterm_rr-no-syscallbuf 2 3.40614\nterm_trace_reset 2 0.248562\nterm_trace_reset-no-syscallbuf 2 0.214772\nterm_trace_syscall 2 0.264866\nterm_trace_syscall-no-syscallbuf 2 0.235758\nthread_exit_signal 2 4.35567\nthread_exit_signal-no-syscallbuf 2 4.51597\nthread_open_race 2 35.2856\nthread_open_race-no-syscallbuf 2 0.0207266\nthread_stress 2 19.5549\nthread_stress-no-syscallbuf 2 15.7079\nthreaded_syscall_spam 2 1.11981\nthreaded_syscall_spam-no-syscallbuf 2 0.0223191\nthreads 2 1.22788\nthreads-no-syscallbuf 2 1.15627\ntls 2 0.912272\ntls-no-syscallbuf 2 0.891445\nttyname 2 0.168692\nttyname-no-syscallbuf 2 0.165043\nunexpected_stack_growth 2 1.10499\nunexpected_stack_growth-no-syscallbuf 2 1.1247\nuser_ignore_sig 2 0.195225\nuser_ignore_sig-no-syscallbuf 2 0.16423\nvdso_clock_gettime_stack 2 1.26935\nvdso_clock_gettime_stack-no-syscallbuf 2 0.0191466\nvdso_gettimeofday_stack 2 1.22336\nvdso_gettimeofday_stack-no-syscallbuf 2 0.0223277\nvdso_time_stack 2 1.09675\nvdso_time_stack-no-syscallbuf 2 0.0224125\nvfork 2 0.273825\nvfork-no-syscallbuf 2 0.235919\nvfork_read_clone_stress 2 2.57748\nvfork_read_clone_stress-no-syscallbuf 2 1.52819\nvsyscall_reverse_next 2 4.01991\nvsyscall_reverse_next-no-syscallbuf 2 3.6232\nwait_for_all 2 1.14849\nwait_for_all-no-syscallbuf 2 1.14272\nwatchpoint 2 1.4021\nwatchpoint-no-syscallbuf 2 1.45019\nwatchpoint_at_sched 2 1.26641\nwatchpoint_at_sched-no-syscallbuf 2 2.16817\nwatchpoint_before_signal 2 0.889821\nwatchpoint_before_signal-no-syscallbuf 2 0.873965\nwatchpoint_no_progress 2 2.94675\nwatchpoint_no_progress-no-syscallbuf 2 1.77617\nwatchpoint_size_change 2 0.914569\nwatchpoint_size_change-no-syscallbuf 2 0.914861\nwatchpoint_syscall 2 1.10858\nwatchpoint_syscall-no-syscallbuf 2 0.967778\nwatchpoint_unaligned 2 0.885318\nwatchpoint_unaligned-no-syscallbuf 2 0.850577\nasync_signal_syscalls_100 2 0.216078\nasync_signal_syscalls_100-no-syscallbuf 2 3.64995\nasync_signal_syscalls_1000 2 0.210203\nasync_signal_syscalls_1000-no-syscallbuf 2 3.41878\nbad_breakpoint 2 10.5237\nbad_breakpoint-no-syscallbuf 2 9.75803\nbreak_block 2 9.95668\nbreak_block-no-syscallbuf 2 9.98023\nbreak_clock 2 0.997136\nbreak_clock-no-syscallbuf 2 1.19868\nbreak_clone 2 0.860601\nbreak_clone-no-syscallbuf 2 0.866168\nbreak_exec 2 1.05496\nbreak_exec-no-syscallbuf 2 0.928972\nbreak_int3 2 0.84853\nbreak_int3-no-syscallbuf 2 0.826974\nbreak_mmap_private 2 2.2772\nbreak_mmap_private-no-syscallbuf 2 2.3963\nbreak_msg 2 2.33334\nbreak_msg-no-syscallbuf 2 2.31454\nx86/break_rdtsc 2 0.906172\nx86/break_rdtsc-no-syscallbuf 2 0.898956\nbreak_sigreturn 2 4.86845\nbreak_sigreturn-no-syscallbuf 2 4.7959\nbreak_sync_signal 2 0.889585\nbreak_sync_signal-no-syscallbuf 2 0.953888\nbreak_thread 2 0.987441\nbreak_thread-no-syscallbuf 2 0.95672\nbreak_time_slice 2 9.39381\nbreak_time_slice-no-syscallbuf 2 9.5303\nbreakpoint_consistent 2 0.864593\nbreakpoint_consistent-no-syscallbuf 2 0.862363\ncall_exit 2 1.24356\ncall_exit-no-syscallbuf 2 1.24033\ncheck_patched_pthread 2 2.17917\ncheck_patched_pthread-no-syscallbuf 2 1.88506\ncheckpoint_async_signal_syscalls_1000 2 3.53824\ncheckpoint_async_signal_syscalls_1000-no-syscallbuf 2 0.0191438\ncheckpoint_mmap_shared 2 25.9316\ncheckpoint_mmap_shared-no-syscallbuf 2 19.8694\ncheckpoint_prctl_name 2 36.1448\ncheckpoint_prctl_name-no-syscallbuf 2 33.1562\ncheckpoint_simple 2 17.1481\ncheckpoint_simple-no-syscallbuf 2 20.2543\nchecksum_sanity_noclone 2 2.47752\nchecksum_sanity_noclone-no-syscallbuf 2 1.57982\ncomm 2 0.628376\ncomm-no-syscallbuf 2 0.752701\ncont_signal 2 4.98586\ncont_signal-no-syscallbuf 2 5.02741\nx86/cpuid 2 0.967095\nx86/cpuid-no-syscallbuf 2 0.967151\ndead_thread_target 2 1.25742\ndead_thread_target-no-syscallbuf 2 1.15103\ndesched_ticks 2 0.933889\ndesched_ticks-no-syscallbuf 2 0.0205327\ndeliver_async_signal_during_syscalls 2 0.708237\ndeliver_async_signal_during_syscalls-no-syscallbuf 2 0.0201994\nenv_newline 2 0.172633\nenv_newline-no-syscallbuf 2 0.176236\nexec_deleted 2 0.174422\nexec_deleted-no-syscallbuf 2 0.154924\nexec_stop 2 0.971989\nexec_stop-no-syscallbuf 2 0.932378\nexecp 2 0.179868\nexecp-no-syscallbuf 2 0.172007\nexplicit_checkpoint_clone 2 1.16827\nexplicit_checkpoint_clone-no-syscallbuf 2 1.13606\nfile_name_newline 2 0.206819\nfile_name_newline-no-syscallbuf 2 0.186296\nfinal_sigkill 2 1.2137\nfinal_sigkill-no-syscallbuf 2 1.16333\nfirst_instruction 2 0.714622\nfirst_instruction-no-syscallbuf 2 0.727912\nfork_exec_info_thr 2 3.49358\nfork_exec_info_thr-no-syscallbuf 2 3.3585\nget_thread_list 2 1.14847\nget_thread_list-no-syscallbuf 2 1.12759\nhardlink_mmapped_files 2 2.21432\nhardlink_mmapped_files-no-syscallbuf 2 2.22769\nhbreak 2 0.98144\nhbreak-no-syscallbuf 2 1.06173\nmprotect_step 2 1.19977\nmprotect_step-no-syscallbuf 2 1.17342\nnested_detach 2 0.443621\nnested_detach-no-syscallbuf 2 0.426141\nnested_detach_kill 2 0.579554\nnested_detach_kill-no-syscallbuf 2 0.57556\nnested_release 2 0.416726\nnested_release-no-syscallbuf 2 0.320548\nparent_no_break_child_bkpt 2 1.35192\nparent_no_break_child_bkpt-no-syscallbuf 2 1.43833\nparent_no_stop_child_crash 2 1.27584\nparent_no_stop_child_crash-no-syscallbuf 2 1.28431\npost_exec_fpu_regs 2 0.609478\npost_exec_fpu_regs-no-syscallbuf 2 0.616487\nproc_maps 2 0.869244\nproc_maps-no-syscallbuf 2 0.917006\nread_bad_mem 2 0.884557\nread_bad_mem-no-syscallbuf 2 0.852502\nrecord_replay 2 141.185\nrecord_replay-no-syscallbuf 2 153.148\nremove_watchpoint 2 0.978183\nremove_watchpoint-no-syscallbuf 2 0.94822\nreplay_overlarge_event_number 2 0.194689\nreplay_overlarge_event_number-no-syscallbuf 2 0.159605\nreplay_serve_files 2 3.66096\nreplay_serve_files-no-syscallbuf 2 3.62241\nrestart_invalid_checkpoint 2 1.21307\nrestart_invalid_checkpoint-no-syscallbuf 2 1.27762\nrestart_unstable 2 1.19906\nrestart_unstable-no-syscallbuf 2 1.13003\nrestart_diversion 2 1.43123\nrestart_diversion-no-syscallbuf 2 1.32596\nreverse_alarm 2 4.70091\nreverse_alarm-no-syscallbuf 2 5.96815\nreverse_continue_exec_subprocess 2 2.35457\nreverse_continue_exec_subprocess-no-syscallbuf 2 2.94139\nreverse_continue_fork_subprocess 2 1.28133\nreverse_continue_fork_subprocess-no-syscallbuf 2 1.29387\nreverse_continue_int3 2 3.80374\nreverse_continue_int3-no-syscallbuf 2 5.79677\nreverse_continue_start 2 3.17295\nreverse_continue_start-no-syscallbuf 2 2.41344\nreverse_finish 2 3.16817\nreverse_finish-no-syscallbuf 2 1.85083\nreverse_step_breakpoint 2 3.3135\nreverse_step_breakpoint-no-syscallbuf 2 3.69605\nreverse_step_signal 2 4.24914\nreverse_step_signal-no-syscallbuf 2 4.50127\nreverse_step_threads2 2 4.63635\nreverse_step_threads2-no-syscallbuf 2 4.4955\nreverse_watchpoint 2 3.56927\nreverse_watchpoint-no-syscallbuf 2 3.64424\nreverse_watchpoint_syscall 2 7.81341\nreverse_watchpoint_syscall-no-syscallbuf 2 7.23407\nrun_end 2 1.51075\nrun_end-no-syscallbuf 2 1.48436\nrun_in_function 2 1.06551\nrun_in_function-no-syscallbuf 2 1.22989\nsanity 2 1.01111\nsanity-no-syscallbuf 2 0.787738\nseekticks 2 1.84473\nseekticks-no-syscallbuf 2 1.93585\nshm_checkpoint 2 1.19522\nshm_checkpoint-no-syscallbuf 2 1.15687\nsiginfo 2 0.772502\nsiginfo-no-syscallbuf 2 0.865984\nx86/sigreturn_checksum 2 0.778667\nx86/sigreturn_checksum-no-syscallbuf 2 0.733952\nsignal_stop 2 0.907598\nsignal_stop-no-syscallbuf 2 0.881811\nsignal_checkpoint 2 1.2013\nsignal_checkpoint-no-syscallbuf 2 1.15467\nsimple_script 2 0.197487\nsimple_script-no-syscallbuf 2 0.185854\nsimple_script_debug 2 0.86698\nsimple_script_debug-no-syscallbuf 2 0.876364\nsimple_winch 2 2.97679\nsimple_winch-no-syscallbuf 2 2.26149\nstack_overflow_debug 2 7.46715\nstack_overflow_debug-no-syscallbuf 2 6.59686\nstep1 2 0.895537\nstep1-no-syscallbuf 2 0.955415\nx86/step_rdtsc 2 1.0748\nx86/step_rdtsc-no-syscallbuf 2 0.934643\nstep_signal 2 0.947377\nstep_signal-no-syscallbuf 2 0.959475\nx86/string_instructions_break 2 6.82516\nx86/string_instructions_break-no-syscallbuf 2 7.17043\nx86/string_instructions_replay_quirk 2 7.50406\nx86/string_instructions_replay_quirk-no-syscallbuf 2 6.87678\nsubprocess_exit_ends_session 2 1.27728\nsubprocess_exit_ends_session-no-syscallbuf 2 1.21137\nswitch_processes 2 3.19626\nswitch_processes-no-syscallbuf 2 2.6858\nsyscallbuf_timeslice_250 2 0.249806\nsyscallbuf_timeslice_250-no-syscallbuf 2 3.29356\ntrace_version 2 2.53497\ntrace_version-no-syscallbuf 2 2.70248\nterm_trace_cpu 2 0.514448\nterm_trace_cpu-no-syscallbuf 2 0.565433\ntrace_events 2 0.134258\ntrace_events-no-syscallbuf 2 0.127315\ntty 2 0.151032\ntty-no-syscallbuf 2 0.150354\nunmap_vdso 2 0.353832\nunmap_vdso-no-syscallbuf 2 0.341826\nunwind_on_signal 2 0.948899\nunwind_on_signal-no-syscallbuf 2 0.914195\nvfork_exec 2 0.910633\nvfork_exec-no-syscallbuf 2 0.922927\nvfork_break_parent 2 0.932378\nvfork_break_parent-no-syscallbuf 2 0.953784\nvsyscall_singlestep 2 0.162971\nvsyscall_singlestep-no-syscallbuf 2 0.145158\nwatch_code 2 3.72841\nwatch_code-no-syscallbuf 2 2.43417\nwatchpoint_cond 2 0.891707\nwatchpoint_cond-no-syscallbuf 2 0.837046\nwhen 2 0.866097\nwhen-no-syscallbuf 2 0.885084\n64bit_child-32 2 0.343532\n64bit_child-32-no-syscallbuf 2 0.344224\n_llseek-32 2 0.236283\n_llseek-32-no-syscallbuf 2 0.159258\nabort-32 2 0.440587\nabort-32-no-syscallbuf 2 0.415051\naccept-32 2 0.303637\naccept-32-no-syscallbuf 2 0.273315\nacct-32 2 0.175651\nacct-32-no-syscallbuf 2 0.159558\nadjtimex-32 2 0.178372\nadjtimex-32-no-syscallbuf 2 0.157448\naio-32 2 0.156827\naio-32-no-syscallbuf 2 0.148936\nalarm-32 2 1.95172\nalarm-32-no-syscallbuf 2 2.48883\nalarm2-32 2 1.14684\nalarm2-32-no-syscallbuf 2 1.15135\nalsa_ioctl-32 2 0.164307\nalsa_ioctl-32-no-syscallbuf 2 0.170314\narch_prctl-32 2 0.183115\narch_prctl-32-no-syscallbuf 2 0.1533\nasync_segv_ignored-32 2 0.187489\nasync_segv_ignored-32-no-syscallbuf 2 0.16181\nat_threadexit-32 2 0.233616\nat_threadexit-32-no-syscallbuf 2 0.240465\nbad_ip-32 2 0.161617\nbad_ip-32-no-syscallbuf 2 0.153276\nbad_syscall-32 2 0.172995\nbad_syscall-32-no-syscallbuf 2 0.17333\nbarrier-32 2 0.304388\nbarrier-32-no-syscallbuf 2 0.367683\nbig_buffers-32 2 0.17837\nbig_buffers-32-no-syscallbuf 2 0.197323\nblock-32 2 9.32206\nblock-32-no-syscallbuf 2 9.33081\nblock_open-32 2 0.190076\nblock_open-32-no-syscallbuf 2 0.185152\nbpf-32 2 0.192451\nbpf-32-no-syscallbuf 2 0.202114\nbpf_map-32 2 0.169593\nbpf_map-32-no-syscallbuf 2 0.177982\nbrk-32 2 0.172165\nbrk-32-no-syscallbuf 2 0.153512\nbrk2-32 2 0.194184\nbrk2-32-no-syscallbuf 2 0.152208\ncapget-32 2 0.2065\ncapget-32-no-syscallbuf 2 0.175296\nchew_cpu-32 2 8.73853\nchew_cpu-32-no-syscallbuf 2 8.70924\nx86/chew_cpu_cpuid-32 2 0.622714\nx86/chew_cpu_cpuid-32-no-syscallbuf 2 0.4366\nchmod-32 2 0.21103\nchmod-32-no-syscallbuf 2 0.174042\nchown-32 2 0.21456\nchown-32-no-syscallbuf 2 0.223343\nclock-32 2 0.255467\nclock-32-no-syscallbuf 2 0.358987\nclock_adjtime-32 2 0.194787\nclock_adjtime-32-no-syscallbuf 2 0.162301\nclock_nanosleep-32 2 1.19261\nclock_nanosleep-32-no-syscallbuf 2 1.22023\nclock_time64-32 2 0.182615\nclock_time64-32-no-syscallbuf 2 0.169495\nclone-32 2 0.198422\nclone-32-no-syscallbuf 2 0.162276\nclone_bad_stack-32 2 0.258172\nclone_bad_stack-32-no-syscallbuf 2 0.227873\nclone_bad_tls-32 2 0.1688\nclone_bad_tls-32-no-syscallbuf 2 0.150977\nclone_cleartid_coredump-32 2 0.380296\nclone_cleartid_coredump-32-no-syscallbuf 2 0.357681\nclone_fail-32 2 0.175359\nclone_fail-32-no-syscallbuf 2 0.160996\nclone_file_range-32 2 0.179275\nclone_file_range-32-no-syscallbuf 2 0.166524\nclone_immediate_exit-32 2 0.180154\nclone_immediate_exit-32-no-syscallbuf 2 0.179751\nclone_newflags-32 2 0.213326\nclone_newflags-32-no-syscallbuf 2 1.04818\nclone_parent-32 2 0.195602\nclone_parent-32-no-syscallbuf 2 0.159968\nclone_untraced-32 2 0.173588\nclone_untraced-32-no-syscallbuf 2 0.205649\nclone_vfork_pidfd-32 2 0.183834\nclone_vfork_pidfd-32-no-syscallbuf 2 0.170767\ncloned_sigmask-32 2 0.31069\ncloned_sigmask-32-no-syscallbuf 2 0.264808\nconstructor-32 2 2.18134\nconstructor-32-no-syscallbuf 2 2.23034\ncopy_file_range-32 2 0.170721\ncopy_file_range-32-no-syscallbuf 2 0.185973\nx86/cpuid_same_state-32 2 0.168649\nx86/cpuid_same_state-32-no-syscallbuf 2 0.176264\ncreat_address_not_truncated-32 2 0.172016\ncreat_address_not_truncated-32-no-syscallbuf 2 0.160827\nx86/cross_arch-32 2 0.173734\nx86/cross_arch-32-no-syscallbuf 2 0.186919\ncwd_inaccessible-32 2 0.230593\ncwd_inaccessible-32-no-syscallbuf 2 0.228416\ndaemon-32 2 0.185343\ndaemon-32-no-syscallbuf 2 0.159593\ndesched_blocking_poll-32 2 0.191223\ndesched_blocking_poll-32-no-syscallbuf 2 0.177699\ndesched_sigkill-32 2 0.268607\ndesched_sigkill-32-no-syscallbuf 2 0.238282\ndetach_state-32 2 0.255978\ndetach_state-32-no-syscallbuf 2 0.217356\ndetach_threads-32 2 0.273998\ndetach_threads-32-no-syscallbuf 2 0.234168\ndetach_sigkill-32 2 0.270231\ndetach_sigkill-32-no-syscallbuf 2 0.204298\ndetach_sigkill_exit-32 2 0.266415\ndetach_sigkill_exit-32-no-syscallbuf 2 0.181115\ndeterministic_sigsys-32 2 0.341587\ndeterministic_sigsys-32-no-syscallbuf 2 0.313071\ndev_zero-32 2 0.166296\ndev_zero-32-no-syscallbuf 2 0.163734\ndirect-32 2 0.256896\ndirect-32-no-syscallbuf 2 0.200562\ndup-32 2 0.174304\ndup-32-no-syscallbuf 2 0.175881\ndoublesegv-32 2 0.384812\ndoublesegv-32-no-syscallbuf 2 0.339395\nepoll_create-32 2 0.168445\nepoll_create-32-no-syscallbuf 2 0.177292\nepoll_create1-32 2 0.24383\nepoll_create1-32-no-syscallbuf 2 0.176546\nepoll_edge-32 2 0.172137\nepoll_edge-32-no-syscallbuf 2 0.17578\nepoll_pwait_eintr_sigmask-32 2 2.18362\nepoll_pwait_eintr_sigmask-32-no-syscallbuf 2 2.17528\neventfd-32 2 0.170002\neventfd-32-no-syscallbuf 2 0.195814\nexec_flags-32 2 0.176703\nexec_flags-32-no-syscallbuf 2 0.158051\nexec_no_env-32 2 0.210186\nexec_no_env-32-no-syscallbuf 2 0.223995\nexec_self-32 2 0.212399\nexec_self-32-no-syscallbuf 2 0.278598\nexec_from_main_thread-32 2 0.256533\nexec_from_main_thread-32-no-syscallbuf 2 0.2547\nexec_from_other_thread-32 2 11.4391\nexec_from_other_thread-32-no-syscallbuf 2 7.97065\nexec_stopsig-32 2 0.248389\nexec_stopsig-32-no-syscallbuf 2 0.227471\nexecveat-32 2 0.33122\nexecveat-32-no-syscallbuf 2 0.212293\nexit_with_syscallbuf_signal-32 2 0.208462\nexit_with_syscallbuf_signal-32-no-syscallbuf 2 0.177881\nfadvise-32 2 0.189585\nfadvise-32-no-syscallbuf 2 0.188268\nfanotify-32 2 0.15869\nfanotify-32-no-syscallbuf 2 0.176326\nfatal_init_signal-32 2 0.19146\nfatal_init_signal-32-no-syscallbuf 2 0.217814\nfatal_sigsegv_thread-32 2 0.664268\nfatal_sigsegv_thread-32-no-syscallbuf 2 0.527767\nx86/fault_in_code_page-32 2 0.182553\nx86/fault_in_code_page-32-no-syscallbuf 2 0.176254\nfcntl_dupfd-32 2 0.177373\nfcntl_dupfd-32-no-syscallbuf 2 0.188962\nfcntl_misc-32 2 0.164345\nfcntl_misc-32-no-syscallbuf 2 0.16434\nfcntl_notify-32 2 0.190707\nfcntl_notify-32-no-syscallbuf 2 0.165259\nfcntl_owner_ex-32 2 0.197163\nfcntl_owner_ex-32-no-syscallbuf 2 0.155602\nfcntl_rw_hints-32 2 0.193598\nfcntl_rw_hints-32-no-syscallbuf 2 0.179665\nfcntl_seals-32 2 0.169677\nfcntl_seals-32-no-syscallbuf 2 0.155835\nfcntl_sig-32 2 0.188346\nfcntl_sig-32-no-syscallbuf 2 0.1586\nfd_cleanup-32 2 0.186579\nfd_cleanup-32-no-syscallbuf 2 0.186616\nfd_tracking_across_threads-32 2 0.194344\nfd_tracking_across_threads-32-no-syscallbuf 2 0.212191\nfds_clean-32 2 0.236395\nfds_clean-32-no-syscallbuf 2 0.235536\nflock-32 2 0.710811\nflock-32-no-syscallbuf 2 1.46662\nflock_ofd-32 2 0.194817\nflock_ofd-32-no-syscallbuf 2 0.958058\nflock2-32 2 0.160203\nflock2-32-no-syscallbuf 2 0.154417\nfork_brk-32 2 0.180829\nfork_brk-32-no-syscallbuf 2 0.192136\nfork_child_crash-32 2 0.286437\nfork_child_crash-32-no-syscallbuf 2 0.25726\nfork_many-32 2 1.1483\nfork_many-32-no-syscallbuf 2 0.676637\nfutex_exit_race-32 2 0.473886\nfutex_exit_race-32-no-syscallbuf 2 0.398697\nfutex_exit_race_sigsegv-32 2 0.768718\nfutex_exit_race_sigsegv-32-no-syscallbuf 2 0.395598\nfutex_pi-32 2 0.169976\nfutex_pi-32-no-syscallbuf 2 0.171053\nfutex_priorities-32 2 0.199389\nfutex_priorities-32-no-syscallbuf 2 0.193813\nfutex_requeue-32 2 1.16674\nfutex_requeue-32-no-syscallbuf 2 1.17668\ngcrypt_rdrand-32 2 0.198064\ngcrypt_rdrand-32-no-syscallbuf 2 0.17078\ngetcpu-32 2 0.203612\ngetcpu-32-no-syscallbuf 2 0.162867\ngetgroups-32 2 0.194776\ngetgroups-32-no-syscallbuf 2 0.210254\ngetpwnam-32 2 0.249385\ngetpwnam-32-no-syscallbuf 2 0.218375\ngetrandom-32 2 0.219942\ngetrandom-32-no-syscallbuf 2 0.163141\nsetitimer-32 2 0.197037\nsetitimer-32-no-syscallbuf 2 0.174438\ngetsid-32 2 0.163107\ngetsid-32-no-syscallbuf 2 0.173976\ngettimeofday-32 2 0.215287\ngettimeofday-32-no-syscallbuf 2 0.183324\ngrandchild_threads-32 2 0.194359\ngrandchild_threads-32-no-syscallbuf 2 0.18839\ngrandchild_threads_main_running-32 2 2.25777\ngrandchild_threads_main_running-32-no-syscallbuf 2 2.27805\ngrandchild_threads_thread_running-32 2 5.25249\ngrandchild_threads_thread_running-32-no-syscallbuf 2 5.23783\ngrandchild_threads_parent_alive-32 2 0.199\ngrandchild_threads_parent_alive-32-no-syscallbuf 2 0.187577\nx86/hle-32 2 2.22635\nx86/hle-32-no-syscallbuf 2 0.881525\ninotify-32 2 0.162154\ninotify-32-no-syscallbuf 2 0.16806\nint3-32 2 0.159417\nint3-32-no-syscallbuf 2 0.157118\nintr_futex_wait_restart-32 2 1.69813\nintr_futex_wait_restart-32-no-syscallbuf 2 1.69332\nintr_poll-32 2 3.68626\nintr_poll-32-no-syscallbuf 2 3.66997\nintr_ppoll-32 2 21.4084\nintr_ppoll-32-no-syscallbuf 2 21.2981\nintr_pselect-32 2 9.15019\nintr_pselect-32-no-syscallbuf 2 9.19517\nintr_read_no_restart-32 2 1.28784\nintr_read_no_restart-32-no-syscallbuf 2 1.28253\nintr_read_restart-32 2 2.30173\nintr_read_restart-32-no-syscallbuf 2 2.27716\nintr_sleep-32 2 4.18891\nintr_sleep-32-no-syscallbuf 2 4.16715\nintr_sleep_no_restart-32 2 1.77529\nintr_sleep_no_restart-32-no-syscallbuf 2 1.78142\ninvalid_exec-32 2 0.17303\ninvalid_exec-32-no-syscallbuf 2 0.156343\ninvalid_fcntl-32 2 0.17745\ninvalid_fcntl-32-no-syscallbuf 2 0.148237\ninvalid_ioctl-32 2 0.167459\ninvalid_ioctl-32-no-syscallbuf 2 0.153341\nio-32 2 0.153516\nio-32-no-syscallbuf 2 0.152155\nio_uring-32 2 0.156336\nio_uring-32-no-syscallbuf 2 0.172072\nioctl-32 2 0.168334\nioctl-32-no-syscallbuf 2 0.174499\nioctl_blk-32 2 0.172997\nioctl_blk-32-no-syscallbuf 2 0.14378\nioctl_fb-32 2 0.15604\nioctl_fb-32-no-syscallbuf 2 0.177303\nioctl_fs-32 2 0.1805\nioctl_fs-32-no-syscallbuf 2 0.182854\nioctl_pty-32 2 0.245727\nioctl_pty-32-no-syscallbuf 2 0.198318\nioctl_sg-32 2 0.171162\nioctl_sg-32-no-syscallbuf 2 0.154041\nioctl_tty-32 2 0.264824\nioctl_tty-32-no-syscallbuf 2 0.225188\nioctl_vt-32 2 0.170598\nioctl_vt-32-no-syscallbuf 2 0.16299\nioprio-32 2 0.169689\nioprio-32-no-syscallbuf 2 0.179517\nx86/ioperm-32 2 0.169697\nx86/ioperm-32-no-syscallbuf 2 0.156024\nx86/iopl-32 2 0.163983\nx86/iopl-32-no-syscallbuf 2 0.1679\njoin_threads-32 2 1.54955\njoin_threads-32-no-syscallbuf 2 1.7967\njoystick-32 2 0.180789\njoystick-32-no-syscallbuf 2 0.188287\nkcmp-32 2 0.172476\nkcmp-32-no-syscallbuf 2 0.173309\nkeyctl-32 2 0.213803\nkeyctl-32-no-syscallbuf 2 0.185761\nkill_newborn-32 2 0.434392\nkill_newborn-32-no-syscallbuf 2 0.352364\nkill_ptracee-32 2 0.245936\nkill_ptracee-32-no-syscallbuf 2 1.77335\nlarge_hole-32 2 0.19012\nlarge_hole-32-no-syscallbuf 2 0.152114\nlarge_write_deadlock-32 2 0.187997\nlarge_write_deadlock-32-no-syscallbuf 2 0.157017\nlegacy_ugid-32 2 0.172081\nlegacy_ugid-32-no-syscallbuf 2 0.154932\nx86/lsl-32 2 0.174847\nx86/lsl-32-no-syscallbuf 2 0.182991\nmadvise-32 2 0.171796\nmadvise-32-no-syscallbuf 2 0.168836\nmadvise_free-32 2 0.162956\nmadvise_free-32-no-syscallbuf 2 0.146138\nmadvise_wipeonfork-32 2 0.298329\nmadvise_wipeonfork-32-no-syscallbuf 2 0.248712\nmap_fixed-32 2 0.171006\nmap_fixed-32-no-syscallbuf 2 0.156162\nmap_shared_syscall-32 2 0.240547\nmap_shared_syscall-32-no-syscallbuf 2 0.188137\nmembarrier-32 2 0.230167\nmembarrier-32-no-syscallbuf 2 0.262814\nmemfd_create-32 2 0.159255\nmemfd_create-32-no-syscallbuf 2 0.159951\nmemfd_create_shared-32 2 0.168803\nmemfd_create_shared-32-no-syscallbuf 2 0.169416\nmemfd_create_shared_huge-32 2 0.166679\nmemfd_create_shared_huge-32-no-syscallbuf 2 0.168568\nmincore-32 2 0.195951\nmincore-32-no-syscallbuf 2 0.179282\nmknod-32 2 0.1707\nmknod-32-no-syscallbuf 2 0.220839\nmlock-32 2 0.178006\nmlock-32-no-syscallbuf 2 0.169444\nmmap_adjacent_to_rr_usage-32 2 0.173778\nmmap_adjacent_to_rr_usage-32-no-syscallbuf 2 0.168001\nmmap_private-32 2 1.00159\nmmap_private-32-no-syscallbuf 2 0.99163\nmmap_private_grow_under_map-32 2 0.173808\nmmap_private_grow_under_map-32-no-syscallbuf 2 0.165926\nmmap_recycle-32 2 0.191217\nmmap_recycle-32-no-syscallbuf 2 0.224146\nmmap_ro-32 2 0.174387\nmmap_ro-32-no-syscallbuf 2 0.168227\nmmap_self_maps_shared-32 2 0.235438\nmmap_self_maps_shared-32-no-syscallbuf 2 0.255654\nmmap_shared-32 2 0.223286\nmmap_shared-32-no-syscallbuf 2 0.177803\nmmap_shared_dev_zero-32 2 0.162855\nmmap_shared_dev_zero-32-no-syscallbuf 2 0.187624\nmmap_shared_grow-32 2 0.172259\nmmap_shared_grow-32-no-syscallbuf 2 0.167488\nmmap_shared_grow_under_map-32 2 0.177782\nmmap_shared_grow_under_map-32-no-syscallbuf 2 0.24619\nmmap_shared_multiple-32 2 0.165807\nmmap_shared_multiple-32-no-syscallbuf 2 0.182459\nmmap_shared_subpage-32 2 0.178498\nmmap_shared_subpage-32-no-syscallbuf 2 0.208066\nmmap_shared_write-32 2 7.86342\nmmap_shared_write-32-no-syscallbuf 2 7.60719\nmmap_shared_write_fork-32 2 3.38886\nmmap_shared_write_fork-32-no-syscallbuf 2 4.51516\nmmap_short_file-32 2 0.17335\nmmap_short_file-32-no-syscallbuf 2 0.167058\nmmap_write_complex-32 2 0.172373\nmmap_write_complex-32-no-syscallbuf 2 0.214238\nmmap_zero_size_fd-32 2 0.169857\nmmap_zero_size_fd-32-no-syscallbuf 2 0.178777\nx86/modify_ldt-32 2 0.180909\nx86/modify_ldt-32-no-syscallbuf 2 0.158959\nmount_ns_exec-32 2 0.242339\nmount_ns_exec-32-no-syscallbuf 2 0.231321\nmount_ns_exec2-32 2 0.226181\nmount_ns_exec2-32-no-syscallbuf 2 0.239407\nmprotect-32 2 0.181316\nmprotect-32-no-syscallbuf 2 0.175856\nmprotect_heterogenous-32 2 0.173654\nmprotect_heterogenous-32-no-syscallbuf 2 0.165665\nmprotect_none-32 2 0.180685\nmprotect_none-32-no-syscallbuf 2 0.165696\nmprotect_stack-32 2 0.172227\nmprotect_stack-32-no-syscallbuf 2 0.164478\nmq-32 2 2.15956\nmq-32-no-syscallbuf 2 2.16518\nmremap-32 2 2.73883\nmremap-32-no-syscallbuf 2 3.268\nmremap_after_coalesce-32 2 0.1893\nmremap_after_coalesce-32-no-syscallbuf 2 0.158341\nmremap_grow-32 2 0.197778\nmremap_grow-32-no-syscallbuf 2 0.157984\nmremap_grow_shared-32 2 0.182198\nmremap_grow_shared-32-no-syscallbuf 2 0.224127\nmremap_non_page_size-32 2 0.19472\nmremap_non_page_size-32-no-syscallbuf 2 0.978314\nmremap_overwrite-32 2 0.196536\nmremap_overwrite-32-no-syscallbuf 2 0.169694\nmremap_private_grow_under_map-32 2 0.250805\nmremap_private_grow_under_map-32-no-syscallbuf 2 0.154396\nmremap_shrink-32 2 0.166243\nmremap_shrink-32-no-syscallbuf 2 0.181565\nmsg-32 2 1.68107\nmsg-32-no-syscallbuf 2 1.68818\nmsg_trunc-32 2 0.176434\nmsg_trunc-32-no-syscallbuf 2 0.165524\nmsync-32 2 1.04094\nmsync-32-no-syscallbuf 2 1.28593\nmtio-32 2 0.189331\nmtio-32-no-syscallbuf 2 0.167114\nmultiple_pending_signals-32 2 0.188975\nmultiple_pending_signals-32-no-syscallbuf 2 0.192054\nmultiple_pending_signals_sequential-32 2 0.190957\nmultiple_pending_signals_sequential-32-no-syscallbuf 2 0.179665\nmunmap_segv-32 2 0.218063\nmunmap_segv-32-no-syscallbuf 2 0.173991\nmunmap_discontinuous-32 2 0.192355\nmunmap_discontinuous-32-no-syscallbuf 2 0.167422\nnanosleep-32 2 1.17149\nnanosleep-32-no-syscallbuf 2 1.15108\nnetfilter-32 2 0.236264\nnetfilter-32-no-syscallbuf 2 0.256435\nnetlink_mmap_disable-32 2 0.157522\nnetlink_mmap_disable-32-no-syscallbuf 2 0.165765\nno_mask_timeslice-32 2 0.850216\nno_mask_timeslice-32-no-syscallbuf 2 0.821699\nnscd-32 2 0.179882\nnscd-32-no-syscallbuf 2 0.160008\nnuma-32 2 0.197031\nnuma-32-no-syscallbuf 2 0.166399\nx86/old_fork-32 2 0.21567\nx86/old_fork-32-no-syscallbuf 2 0.18302\norphan_process-32 2 0.206772\norphan_process-32-no-syscallbuf 2 0.184401\npacket_mmap_disable-32 2 0.163268\npacket_mmap_disable-32-no-syscallbuf 2 0.151608\npause-32 2 1.15926\npause-32-no-syscallbuf 2 1.14328\nperf_event-32 2 0.207887\nperf_event-32-no-syscallbuf 2 0.182937\npersonality-32 2 0.184296\npersonality-32-no-syscallbuf 2 0.223865\npid_ns_kill_child-32 2 0.385645\npid_ns_kill_child-32-no-syscallbuf 2 0.3028\npid_ns_kill_child_threads-32 2 0.254021\npid_ns_kill_child_threads-32-no-syscallbuf 2 0.20647\npid_ns_kill_child_zombie-32 2 0.223784\npid_ns_kill_child_zombie-32-no-syscallbuf 2 0.196851\npid_ns_kill_threads-32 2 0.230732\npid_ns_kill_threads-32-no-syscallbuf 2 0.212946\npid_ns_kill_threads_exit_wait-32 2 0.328763\npid_ns_kill_threads_exit_wait-32-no-syscallbuf 2 0.248139\npid_ns_reap-32 2 0.227847\npid_ns_reap-32-no-syscallbuf 2 0.243935\npid_ns_segv-32 2 0.292908\npid_ns_segv-32-no-syscallbuf 2 0.241546\npid_ns_shutdown-32 2 0.508542\npid_ns_shutdown-32-no-syscallbuf 2 0.309565\npidfd-32 2 0.194201\npidfd-32-no-syscallbuf 2 0.179072\nx86/pkeys-32 2 0.16721\nx86/pkeys-32-no-syscallbuf 2 0.151803\npoll_sig_race-32 2 2.94428\npoll_sig_race-32-no-syscallbuf 2 2.89483\nppoll-32 2 5.72427\nppoll-32-no-syscallbuf 2 5.72158\nprctl-32 2 0.243426\nprctl-32-no-syscallbuf 2 0.168644\nprctl_caps-32 2 0.417118\nprctl_caps-32-no-syscallbuf 2 0.362039\nprctl_deathsig-32 2 0.253595\nprctl_deathsig-32-no-syscallbuf 2 0.175611\nprctl_name-32 2 0.28042\nprctl_name-32-no-syscallbuf 2 0.240042\nprctl_short_name-32 2 0.180561\nprctl_short_name-32-no-syscallbuf 2 0.153409\nprctl_speculation_ctrl-32 2 0.177203\nprctl_speculation_ctrl-32-no-syscallbuf 2 0.168493\nx86/prctl_tsc-32 2 0.195859\nx86/prctl_tsc-32-no-syscallbuf 2 0.180645\nprivileged_net_ioctl-32 2 0.435754\nprivileged_net_ioctl-32-no-syscallbuf 2 0.449377\nproc_fds-32 2 0.622971\nproc_fds-32-no-syscallbuf 2 0.766995\nproc_mem-32 2 0.386866\nproc_mem-32-no-syscallbuf 2 0.376723\nprotect_rr_fds-32 2 3.15255\nprotect_rr_fds-32-no-syscallbuf 2 3.95277\nprw-32 2 0.163791\nprw-32-no-syscallbuf 2 0.175139\npthread_condvar_locking-32 2 0.195831\npthread_condvar_locking-32-no-syscallbuf 2 0.198542\npthread_mutex_timedlock-32 2 0.172525\npthread_mutex_timedlock-32-no-syscallbuf 2 0.171628\npthread_pi_mutex-32 2 0.194426\npthread_pi_mutex-32-no-syscallbuf 2 0.147285\npthread_rwlocks-32 2 0.188592\npthread_rwlocks-32-no-syscallbuf 2 0.167646\nx86/ptrace-32 2 0.225572\nx86/ptrace-32-no-syscallbuf 2 0.230391\nptrace_attach_null_status-32 2 0.21989\nptrace_attach_null_status-32-no-syscallbuf 2 0.221423\nptrace_attach_running-32 2 0.322088\nptrace_attach_running-32-no-syscallbuf 2 1.81167\nptrace_attach_sleeping-32 2 0.229337\nptrace_attach_sleeping-32-no-syscallbuf 2 0.259472\nptrace_attach_stopped-32 2 0.254542\nptrace_attach_stopped-32-no-syscallbuf 2 0.254623\nptrace_attach_thread_running-32 2 7.71519\nptrace_attach_thread_running-32-no-syscallbuf 2 9.21576\nptrace_breakpoint-32 2 0.207377\nptrace_breakpoint-32-no-syscallbuf 2 0.205281\nptrace_change_patched_syscall-32 2 0.214222\nptrace_change_patched_syscall-32-no-syscallbuf 2 0.198213\nx86/ptrace_debug_regs-32 2 0.180522\nx86/ptrace_debug_regs-32-no-syscallbuf 2 0.192852\nptrace_exec-32 2 0.311664\nptrace_exec-32-no-syscallbuf 2 0.265444\nx86/ptrace_exec32-32 2 0.169313\nx86/ptrace_exec32-32-no-syscallbuf 2 0.209205\nptrace_kill_grandtracee-32 2 0.218563\nptrace_kill_grandtracee-32-no-syscallbuf 2 0.185387\nx86/ptrace_tls-32 2 0.264243\nx86/ptrace_tls-32-no-syscallbuf 2 0.186428\nptrace_seize-32 2 0.183568\nptrace_seize-32-no-syscallbuf 2 0.159259\nptrace_sigchld_blocked-32 2 0.200425\nptrace_sigchld_blocked-32-no-syscallbuf 2 0.200648\nptrace_signals-32 2 0.304559\nptrace_signals-32-no-syscallbuf 2 0.278018\nptrace_singlestep-32 2 0.639743\nptrace_singlestep-32-no-syscallbuf 2 0.222714\nptrace_syscall-32 2 0.189698\nptrace_syscall-32-no-syscallbuf 2 0.198213\nptrace_syscall_clone_untraced-32 2 0.303777\nptrace_syscall_clone_untraced-32-no-syscallbuf 2 0.238925\nx86/ptrace_sysemu-32 2 0.258322\nx86/ptrace_sysemu-32-no-syscallbuf 2 0.320688\nptrace_sysemu_syscall-32 2 0.185471\nptrace_sysemu_syscall-32-no-syscallbuf 2 0.220217\nptrace_trace_clone-32 2 0.212671\nptrace_trace_clone-32-no-syscallbuf 2 0.203035\nptrace_trace_exit-32 2 0.183704\nptrace_trace_exit-32-no-syscallbuf 2 0.167785\nptrace_traceme-32 2 0.184022\nptrace_traceme-32-no-syscallbuf 2 0.18187\nptracer_death-32 2 0.248333\nptracer_death-32-no-syscallbuf 2 0.249883\nptracer_death_multithread-32 2 0.388901\nptracer_death_multithread-32-no-syscallbuf 2 0.369612\nptracer_death_multithread_peer-32 2 0.419266\nptracer_death_multithread_peer-32-no-syscallbuf 2 0.395806\nquotactl-32 2 0.182772\nquotactl-32-no-syscallbuf 2 0.201297\nx86/rdtsc-32 2 0.255399\nx86/rdtsc-32-no-syscallbuf 2 0.229242\nread_nothing-32 2 7.46141\nread_nothing-32-no-syscallbuf 2 7.72549\nreaddir-32 2 0.174061\nreaddir-32-no-syscallbuf 2 0.167578\nread_large-32 2 0.428546\nread_large-32-no-syscallbuf 2 1.15199\nread_oversize-32 2 0.162112\nread_oversize-32-no-syscallbuf 2 0.162055\nreadlink-32 2 0.186308\nreadlink-32-no-syscallbuf 2 0.212726\nreadlinkat-32 2 0.165631\nreadlinkat-32-no-syscallbuf 2 0.160991\nreadv-32 2 0.190512\nreadv-32-no-syscallbuf 2 0.175585\nrecord_replay_subject-32 2 3.25793\nrecord_replay_subject-32-no-syscallbuf 2 3.43256\nrecvfrom-32 2 0.186827\nrecvfrom-32-no-syscallbuf 2 0.168322\nredzone_integrity-32 2 1.14239\nredzone_integrity-32-no-syscallbuf 2 1.13652\nrename-32 2 0.178096\nrename-32-no-syscallbuf 2 0.168682\nrlimit-32 2 0.182187\nrlimit-32-no-syscallbuf 2 0.165564\nrobust_futex-32 2 0.202095\nrobust_futex-32-no-syscallbuf 2 0.198996\nrusage-32 2 0.168172\nrusage-32-no-syscallbuf 2 0.206066\nsamask-32 2 0.337743\nsamask-32-no-syscallbuf 2 0.301596\nsave_data_fd-32 2 0.22658\nsave_data_fd-32-no-syscallbuf 2 0.16278\nsched_attr-32 2 0.164539\nsched_attr-32-no-syscallbuf 2 0.162087\nsched_setaffinity-32 2 0.20929\nsched_setaffinity-32-no-syscallbuf 2 0.173467\nsched_setparam-32 2 0.173069\nsched_setparam-32-no-syscallbuf 2 0.161447\nsched_yield-32 2 0.293288\nsched_yield-32-no-syscallbuf 2 0.246936\nsched_yield_to_lower_priority-32 2 0.177359\nsched_yield_to_lower_priority-32-no-syscallbuf 2 0.167451\nscm_rights-32 2 0.700044\nscm_rights-32-no-syscallbuf 2 0.681345\nscratch_read-32 2 0.19306\nscratch_read-32-no-syscallbuf 2 0.193434\nseccomp-32 2 0.289931\nseccomp-32-no-syscallbuf 2 0.188005\nseccomp_cloning-32 2 0.174185\nseccomp_cloning-32-no-syscallbuf 2 0.158513\nseccomp_clone_fail-32 2 0.20893\nseccomp_clone_fail-32-no-syscallbuf 2 0.162227\nseccomp_desched-32 2 0.213358\nseccomp_desched-32-no-syscallbuf 2 0.162138\nseccomp_kill_exit-32 2 0.189344\nseccomp_kill_exit-32-no-syscallbuf 2 0.155638\nseccomp_null-32 2 0.16527\nseccomp_null-32-no-syscallbuf 2 0.194281\nseccomp_sigsys_args-32 2 0.200211\nseccomp_sigsys_args-32-no-syscallbuf 2 0.161084\nseccomp_sigsys_sigtrap-32 2 0.210447\nseccomp_sigsys_sigtrap-32-no-syscallbuf 2 0.201276\nseccomp_sigsys_syscallbuf-32 2 0.209561\nseccomp_sigsys_syscallbuf-32-no-syscallbuf 2 0.162703\nseccomp_tsync-32 2 0.187879\nseccomp_tsync-32-no-syscallbuf 2 0.176498\nseccomp_veto_exec-32 2 0.173933\nseccomp_veto_exec-32-no-syscallbuf 2 0.203032\nself_shebang-32 2 0.24153\nself_shebang-32-no-syscallbuf 2 0.231292\nself_sigint-32 2 0.159231\nself_sigint-32-no-syscallbuf 2 0.153099\nsem-32 2 0.250009\nsem-32-no-syscallbuf 2 0.256186\nsend_block-32 2 1.14479\nsend_block-32-no-syscallbuf 2 2.88824\nsendfile-32 2 0.200584\nsendfile-32-no-syscallbuf 2 0.165255\nset_ptracer-32 2 0.189767\nset_ptracer-32-no-syscallbuf 2 0.167316\nset_tid_address-32 2 0.239881\nset_tid_address-32-no-syscallbuf 2 0.196003\nsetgid-32 2 0.172545\nsetgid-32-no-syscallbuf 2 0.205069\nsetgroups-32 2 0.171244\nsetgroups-32-no-syscallbuf 2 0.167926\nsetsid-32 2 0.169398\nsetsid-32-no-syscallbuf 2 0.152853\nsetuid-32 2 0.233078\nsetuid-32-no-syscallbuf 2 0.239728\nshared_exec-32 2 0.16772\nshared_exec-32-no-syscallbuf 2 0.156276\nshared_monitor-32 2 0.183911\nshared_monitor-32-no-syscallbuf 2 0.170766\nshared_offset-32 2 0.196638\nshared_offset-32-no-syscallbuf 2 0.159853\nshared_write-32 2 0.181719\nshared_write-32-no-syscallbuf 2 0.164443\nshm-32 2 0.217793\nshm-32-no-syscallbuf 2 0.201548\nshm_unmap-32 2 0.1996\nshm_unmap-32-no-syscallbuf 2 0.165694\nsigaction_old-32 2 0.163398\nsigaction_old-32-no-syscallbuf 2 0.148241\nsigaltstack-32 2 0.168017\nsigaltstack-32-no-syscallbuf 2 0.177744\nsigchld_interrupt_signal-32 2 4.17391\nsigchld_interrupt_signal-32-no-syscallbuf 2 4.64724\nsigcont-32 2 0.182719\nsigcont-32-no-syscallbuf 2 0.17846\nsighandler_bad_rsp_sigsegv-32 2 0.165357\nsighandler_bad_rsp_sigsegv-32-no-syscallbuf 2 0.200135\nsighandler_fork-32 2 0.229891\nsighandler_fork-32-no-syscallbuf 2 0.201362\nsighandler_mask-32 2 0.198156\nsighandler_mask-32-no-syscallbuf 2 0.197925\nsigill-32 2 0.175937\nsigill-32-no-syscallbuf 2 0.151933\nsignal_deferred-32 2 0.238068\nsignal_deferred-32-no-syscallbuf 2 0.22673\nsignal_during_preload_init-32 2 0.205667\nsignal_during_preload_init-32-no-syscallbuf 2 0.16874\nsignal_frame-32 2 0.183135\nsignal_frame-32-no-syscallbuf 2 0.163214\nsignal_unstoppable-32 2 0.172697\nsignal_unstoppable-32-no-syscallbuf 2 0.176041\nsignalfd-32 2 0.163957\nsignalfd-32-no-syscallbuf 2 0.173083\nsigprocmask-32 2 0.635516\nsigprocmask-32-no-syscallbuf 2 0.512729\nsigprocmask_ensure_delivery-32 2 0.188993\nsigprocmask_ensure_delivery-32-no-syscallbuf 2 0.197066\nsigprocmask_exec-32 2 0.224889\nsigprocmask_exec-32-no-syscallbuf 2 0.203679\nsigprocmask_evil-32 2 0.173367\nsigprocmask_evil-32-no-syscallbuf 2 0.161906\nsigprocmask_in_syscallbuf_sighandler-32 2 1.1356\nsigprocmask_in_syscallbuf_sighandler-32-no-syscallbuf 2 1.16151\nsigprocmask_rr_sigs-32 2 0.203465\nsigprocmask_rr_sigs-32-no-syscallbuf 2 0.154496\nsigprocmask_syscallbuf-32 2 0.257067\nsigprocmask_syscallbuf-32-no-syscallbuf 2 0.163535\nsigqueueinfo-32 2 0.192575\nsigqueueinfo-32-no-syscallbuf 2 0.183718\nx86/sigreturn-32 2 0.200426\nx86/sigreturn-32-no-syscallbuf 2 0.203151\nsigreturn_reg-32 2 0.164388\nsigreturn_reg-32-no-syscallbuf 2 0.157327\nsigreturnmask-32 2 0.360989\nsigreturnmask-32-no-syscallbuf 2 0.329691\nsigrt-32 2 0.279908\nsigrt-32-no-syscallbuf 2 0.273772\nsigstop-32 2 0.272004\nsigstop-32-no-syscallbuf 2 0.21508\nsigstop2-32 2 0.173375\nsigstop2-32-no-syscallbuf 2 0.1829\nsigsuspend-32 2 0.179968\nsigsuspend-32-no-syscallbuf 2 0.181647\nsigtrap-32 2 0.194202\nsigtrap-32-no-syscallbuf 2 0.198646\nsimple_threads_stress-32 2 1.55506\nsimple_threads_stress-32-no-syscallbuf 2 1.91246\nsioc-32 2 0.597241\nsioc-32-no-syscallbuf 2 0.984665\nsmall_holes-32 2 0.216759\nsmall_holes-32-no-syscallbuf 2 0.190171\nsock_names_opts-32 2 0.24013\nsock_names_opts-32-no-syscallbuf 2 0.208039\nspinlock_priorities-32 2 1.18743\nspinlock_priorities-32-no-syscallbuf 2 2.21217\nsplice-32 2 0.211997\nsplice-32-no-syscallbuf 2 0.175437\nstack_growth_after_syscallbuf-32 2 0.176133\nstack_growth_after_syscallbuf-32-no-syscallbuf 2 0.180134\nstack_growth_syscallbuf-32 2 0.224124\nstack_growth_syscallbuf-32-no-syscallbuf 2 7.43736\nstack_growth_with_guard-32 2 0.176287\nstack_growth_with_guard-32-no-syscallbuf 2 0.171927\nstack_invalid-32 2 0.198923\nstack_invalid-32-no-syscallbuf 2 0.158112\nstack_overflow-32 2 0.299813\nstack_overflow-32-no-syscallbuf 2 0.306432\nstack_overflow_altstack-32 2 0.172148\nstack_overflow_altstack-32-no-syscallbuf 2 0.180087\nstack_overflow_with_guard-32 2 0.277676\nstack_overflow_with_guard-32-no-syscallbuf 2 0.259982\nstatfs-32 2 0.247123\nstatfs-32-no-syscallbuf 2 0.223844\nstatx-32 2 0.18761\nstatx-32-no-syscallbuf 2 0.156038\nstdout_child-32 2 0.228882\nstdout_child-32-no-syscallbuf 2 0.202993\nstdout_cloexec-32 2 0.37312\nstdout_cloexec-32-no-syscallbuf 2 0.233512\nstdout_dup-32 2 0.158335\nstdout_dup-32-no-syscallbuf 2 0.180505\nstdout_redirect-32 2 0.233056\nstdout_redirect-32-no-syscallbuf 2 0.228063\nswitch_read-32 2 0.679615\nswitch_read-32-no-syscallbuf 2 0.705301\nsymlink-32 2 0.153647\nsymlink-32-no-syscallbuf 2 0.151247\nsync-32 2 0.224612\nsync-32-no-syscallbuf 2 0.373438\nsync_file_range-32 2 0.176229\nsync_file_range-32-no-syscallbuf 2 0.185675\nsyscall_bp-32 2 0.227873\nsyscall_bp-32-no-syscallbuf 2 0.152013\nsyscall_in_writable_mem-32 2 0.16217\nsyscall_in_writable_mem-32-no-syscallbuf 2 0.162692\nsyscallbuf_signal_reset-32 2 0.171769\nsyscallbuf_signal_reset-32-no-syscallbuf 2 0.172879\nsyscallbuf_signal_blocking-32 2 0.182044\nsyscallbuf_signal_blocking-32-no-syscallbuf 2 0.174233\nsyscallbuf_sigstop-32 2 8.3546\nsyscallbuf_sigstop-32-no-syscallbuf 2 19.726\nsyscallbuf_timeslice-32 2 0.195219\nsyscallbuf_timeslice-32-no-syscallbuf 2 3.18591\nsyscallbuf_timeslice2-32 2 0.235487\nsyscallbuf_timeslice2-32-no-syscallbuf 2 8.84544\nsysconf-32 2 0.216995\nsysconf-32-no-syscallbuf 2 0.183905\nsysctl-32 2 0.17549\nsysctl-32-no-syscallbuf 2 0.182945\nsysemu_singlestep-32 2 0.188511\nsysemu_singlestep-32-no-syscallbuf 2 0.160338\nx86/sysfs-32 2 0.216447\nx86/sysfs-32-no-syscallbuf 2 0.258669\nsysinfo-32 2 0.169013\nsysinfo-32-no-syscallbuf 2 0.159985\ntgkill-32 2 0.211264\ntgkill-32-no-syscallbuf 2 0.224148\nthread_yield-32 2 3.26443\nthread_yield-32-no-syscallbuf 2 3.18955\ntimer-32 2 65.4883\ntimer-32-no-syscallbuf 2 61.5215\ntimerfd-32 2 0.259309\ntimerfd-32-no-syscallbuf 2 0.25765\ntimes-32 2 0.190807\ntimes-32-no-syscallbuf 2 0.165569\ntruncate_temp-32 2 0.192476\ntruncate_temp-32-no-syscallbuf 2 0.183864\ntun-32 2 0.266826\ntun-32-no-syscallbuf 2 0.224363\ntwo_signals_with_mask-32 2 0.193805\ntwo_signals_with_mask-32-no-syscallbuf 2 0.200266\nulimit_low-32 2 0.202149\nulimit_low-32-no-syscallbuf 2 0.185735\nuname-32 2 0.164955\nuname-32-no-syscallbuf 2 0.178798\nunexpected_exit-32 2 0.230114\nunexpected_exit-32-no-syscallbuf 2 0.474315\nunexpected_exit_execve-32 2 0.310605\nunexpected_exit_execve-32-no-syscallbuf 2 0.483972\nunexpected_exit_execve_twice-32 2 1.27987\nunexpected_exit_execve_twice-32-no-syscallbuf 2 1.60515\nunexpected_exit_pid_ns-32 2 0.676718\nunexpected_exit_pid_ns-32-no-syscallbuf 2 0.21609\nunjoined_thread-32 2 0.171839\nunjoined_thread-32-no-syscallbuf 2 0.16768\nunshare-32 2 0.402218\nunshare-32-no-syscallbuf 2 1.21276\nuserfaultfd-32 2 0.189497\nuserfaultfd-32-no-syscallbuf 2 0.161169\nutimes-32 2 0.182642\nutimes-32-no-syscallbuf 2 0.170065\nvdso_parts-32 2 0.156907\nvdso_parts-32-no-syscallbuf 2 0.160536\nvfork_flush-32 2 0.240043\nvfork_flush-32-no-syscallbuf 2 0.182477\nvfork_shared-32 2 0.164851\nvfork_shared-32-no-syscallbuf 2 0.157664\nvideo_capture-32 2 0.1824\nvideo_capture-32-no-syscallbuf 2 0.151597\nvm_readv_writev-32 2 0.178979\nvm_readv_writev-32-no-syscallbuf 2 0.187688\nvsyscall-32 2 0.210085\nvsyscall-32-no-syscallbuf 2 0.158692\nvsyscall_timeslice-32 2 0.188542\nvsyscall_timeslice-32-no-syscallbuf 2 0.176226\nx86/x87env-32 2 0.178634\nx86/x87env-32-no-syscallbuf 2 0.156739\nwait-32 2 0.207803\nwait-32-no-syscallbuf 2 0.181911\nwait_sigstop-32 2 0.245489\nwait_sigstop-32-no-syscallbuf 2 0.20551\nwrite_race-32 2 2.81023\nwrite_race-32-no-syscallbuf 2 1.62455\nwritev-32 2 0.216639\nwritev-32-no-syscallbuf 2 0.158551\nxattr-32 2 0.175634\nxattr-32-no-syscallbuf 2 0.185673\nzero_length_read-32 2 0.20377\nzero_length_read-32-no-syscallbuf 2 0.175449\nstd_random-32 2 0.215086\nstd_random-32-no-syscallbuf 2 0.213033\nunwind_rr_page-32 2 1.15772\nunwind_rr_page-32-no-syscallbuf 2 1.19208\nabort_nonmain-32 2 0.419818\nabort_nonmain-32-no-syscallbuf 2 0.514262\nalternate_thread_diversion-32 2 0.765083\nalternate_thread_diversion-32-no-syscallbuf 2 0.754914\nargs-32 2 0.160012\nargs-32-no-syscallbuf 2 0.164688\nasync_kill_with_syscallbuf-32 2 2.96233\nasync_kill_with_syscallbuf-32-no-syscallbuf 2 3.71867\nasync_kill_with_syscallbuf2-32 2 2.31923\nasync_kill_with_syscallbuf2-32-no-syscallbuf 2 2.7653\nasync_kill_with_threads-32 2 2.28526\nasync_kill_with_threads-32-no-syscallbuf 2 2.25265\nasync_kill_with_threads_main_running-32 2 2.32524\nasync_kill_with_threads_main_running-32-no-syscallbuf 2 2.35965\nasync_kill_with_threads_thread_running-32 2 6.16048\nasync_kill_with_threads_thread_running-32-no-syscallbuf 2 6.17832\nasync_segv-32 2 4.58465\nasync_segv-32-no-syscallbuf 2 4.26574\nasync_signal_syscalls-32 2 1.24413\nasync_signal_syscalls-32-no-syscallbuf 2 0.0191033\nasync_signal_syscalls2-32 2 0.488521\nasync_signal_syscalls2-32-no-syscallbuf 2 0.0195984\nasync_signal_syscalls_siginfo-32 2 2.3458\nasync_signal_syscalls_siginfo-32-no-syscallbuf 2 0.0198688\nasync_usr1-32 2 4.18131\nasync_usr1-32-no-syscallbuf 2 4.37104\nblacklist-32 2 0.199968\nblacklist-32-no-syscallbuf 2 0.169581\nblock_clone_checkpoint-32 2 0.972619\nblock_clone_checkpoint-32-no-syscallbuf 2 1.0248\nblock_clone_interrupted-32 2 6.1161\nblock_clone_interrupted-32-no-syscallbuf 2 5.00848\nblock_clone_syscallbuf_overflow-32 2 7.25687\nblock_clone_syscallbuf_overflow-32-no-syscallbuf 2 7.23739\nblock_intr_sigchld-32 2 6.66237\nblock_intr_sigchld-32-no-syscallbuf 2 5.92013\nblocked_bad_ip-32 2 1.24533\nblocked_bad_ip-32-no-syscallbuf 2 1.06315\nblocked_sigill-32 2 0.449607\nblocked_sigill-32-no-syscallbuf 2 0.436688\nx86/blocked_sigsegv-32 2 0.427648\nx86/blocked_sigsegv-32-no-syscallbuf 2 0.440355\nbreakpoint-32 2 0.781104\nbreakpoint-32-no-syscallbuf 2 0.756534\nbreakpoint_conditions-32 2 0.931492\nbreakpoint_conditions-32-no-syscallbuf 2 0.899478\nbreakpoint_overlap-32 2 0.907463\nbreakpoint_overlap-32-no-syscallbuf 2 0.796609\ncall_function-32 2 0.895301\ncall_function-32-no-syscallbuf 2 0.835369\ncall_gettid-32 2 0.809616\ncall_gettid-32-no-syscallbuf 2 0.797137\ncheckpoint_dying_threads-32 2 0.870958\ncheckpoint_dying_threads-32-no-syscallbuf 2 0.886313\ncheckpoint_mixed_mode-32 2 0.781085\ncheckpoint_mixed_mode-32-no-syscallbuf 2 0.810389\nchecksum_sanity-32 2 2.25127\nchecksum_sanity-32-no-syscallbuf 2 1.54868\ncheck_lost_interrupts-32 2 1.64176\ncheck_lost_interrupts-32-no-syscallbuf 2 0.0340491\nclone_interruption-32 2 1.89058\nclone_interruption-32-no-syscallbuf 2 1.7642\nclone_vfork-32 2 0.228699\nclone_vfork-32-no-syscallbuf 2 0.284549\nconditional_breakpoint_calls-32 2 0.8973\nconditional_breakpoint_calls-32-no-syscallbuf 2 0.853431\nconditional_breakpoint_offload-32 2 97.907\nconditional_breakpoint_offload-32-no-syscallbuf 2 98.3436\ncondvar_stress-32 2 20.5983\ncondvar_stress-32-no-syscallbuf 2 55.8068\ncont_race-32 2 18.4938\ncont_race-32-no-syscallbuf 2 7.5187\nx86/cpuid_singlestep-32 2 0.788428\nx86/cpuid_singlestep-32-no-syscallbuf 2 0.775394\ncrash-32 2 0.375658\ncrash-32-no-syscallbuf 2 0.373543\ncrash_in_function-32 2 1.19966\ncrash_in_function-32-no-syscallbuf 2 1.1729\ndaemon_read-32 2 0.239872\ndaemon_read-32-no-syscallbuf 2 0.206172\ndconf_mock-32 2 0.190717\ndconf_mock-32-no-syscallbuf 2 0.210945\ndev_tty-32 2 0.15771\ndev_tty-32-no-syscallbuf 2 0.152782\ndiversion_sigtrap-32 2 1.14728\ndiversion_sigtrap-32-no-syscallbuf 2 1.14366\ndiversion_syscall-32 2 0.958771\ndiversion_syscall-32-no-syscallbuf 2 0.973065\ndlopen-32 2 5.03807\ndlopen-32-no-syscallbuf 2 6.69\nearly_error-32 2 0.407332\nearly_error-32-no-syscallbuf 2 0.493056\nelapsed_time-32 2 1.80462\nelapsed_time-32-no-syscallbuf 2 1.81788\nexclusion_region-32 2 0.18669\nexclusion_region-32-no-syscallbuf 2 0.165941\nexec_failed-32 2 0.730666\nexec_failed-32-no-syscallbuf 2 0.759682\nexec_many-32 2 6.45334\nexec_many-32-no-syscallbuf 2 4.53874\nexecve_loop-32 2 6.09311\nexecve_loop-32-no-syscallbuf 2 4.70132\nexit_codes-32 2 0.445052\nexit_codes-32-no-syscallbuf 2 0.477203\nexit_group-32 2 0.181852\nexit_group-32-no-syscallbuf 2 0.176978\nexit_race-32 2 1.38796\nexit_race-32-no-syscallbuf 2 1.21512\nexit_status-32 2 0.116335\nexit_status-32-no-syscallbuf 2 0.114189\nx86/explicit_checkpoints-32 2 1.30454\nx86/explicit_checkpoints-32-no-syscallbuf 2 1.26135\nfd_limit-32 2 0.187127\nfd_limit-32-no-syscallbuf 2 0.997723\nfork_stress-32 2 3.61525\nfork_stress-32-no-syscallbuf 2 1.40335\nfork_syscalls-32 2 0.168964\nfork_syscalls-32-no-syscallbuf 2 0.208122\nfunction_calls-32 2 3.03073\nfunction_calls-32-no-syscallbuf 2 3.51453\nx86/fxregs-32 2 0.765217\nx86/fxregs-32-no-syscallbuf 2 0.772687\ngetcwd-32 2 0.169073\ngetcwd-32-no-syscallbuf 2 0.169593\ngdb_bogus_breakpoint-32 2 0.772146\ngdb_bogus_breakpoint-32-no-syscallbuf 2 0.760645\ngoto_event-32 2 3.68828\ngoto_event-32-no-syscallbuf 2 1.69596\nhello-32 2 0.202056\nhello-32-no-syscallbuf 2 0.182372\nhooks-32 2 1.00194\nhooks-32-no-syscallbuf 2 0.0212301\nignored_async_usr1-32 2 2.39089\nignored_async_usr1-32-no-syscallbuf 2 3.59592\nignored_sigsegv-32 2 0.467501\nignored_sigsegv-32-no-syscallbuf 2 0.448767\nignore_nested-32 2 0.328183\nignore_nested-32-no-syscallbuf 2 0.321336\nimmediate_restart-32 2 0.901743\nimmediate_restart-32-no-syscallbuf 2 0.944109\nx86/int3_ok-32 2 0.170286\nx86/int3_ok-32-no-syscallbuf 2 0.175991\ninterrupt-32 2 4.98112\ninterrupt-32-no-syscallbuf 2 4.48325\nintr_ptrace_decline-32 2 5.18875\nintr_ptrace_decline-32-no-syscallbuf 2 4.69277\ninvalid_interpreter-32 2 1.16413\ninvalid_interpreter-32-no-syscallbuf 2 1.12651\ninvalid_jump-32 2 3.69128\ninvalid_jump-32-no-syscallbuf 2 1.89185\njit_proc_mem-32 2 0.871428\njit_proc_mem-32-no-syscallbuf 2 0.869078\nlink-32 2 0.190435\nlink-32-no-syscallbuf 2 0.166527\nmadvise_dontfork-32 2 0.915018\nmadvise_dontfork-32-no-syscallbuf 2 0.916182\nmain_thread_exit-32 2 0.976596\nmain_thread_exit-32-no-syscallbuf 2 0.988971\nmany_yields-32 2 2.70468\nmany_yields-32-no-syscallbuf 2 2.14603\nmmap_fd_reuse_checkpoint-32 2 0.941569\nmmap_fd_reuse_checkpoint-32-no-syscallbuf 2 0.939913\nmmap_replace_most_mappings-32 2 2.68514\nmmap_replace_most_mappings-32-no-syscallbuf 2 2.41771\nmmap_shared_prot-32 2 0.929817\nmmap_shared_prot-32-no-syscallbuf 2 0.92472\nmmap_shared_write_exec_race-32 2 3.81915\nmmap_shared_write_exec_race-32-no-syscallbuf 2 4.60813\nmmap_tmpfs-32 2 0.194743\nmmap_tmpfs-32-no-syscallbuf 2 0.18605\nmmap_write-32 2 0.0192549\nmmap_write-32-no-syscallbuf 2 0.0200511\nmmap_write_private-32 2 0.308225\nmmap_write_private-32-no-syscallbuf 2 0.324777\nmorestack_unwind-32 1 0.537327\nmorestack_unwind-32-no-syscallbuf 1 0.0202514\nmprotect_growsdown-32 2 0.339205\nmprotect_growsdown-32-no-syscallbuf 2 0.31326\nmprotect_syscallbuf_overflow-32 2 0.280952\nmprotect_syscallbuf_overflow-32-no-syscallbuf 2 8.061\nmutex_pi_stress-32 2 22.3886\nmutex_pi_stress-32-no-syscallbuf 2 27.1594\nnested_detach_wait-32 2 0.562413\nnested_detach_wait-32-no-syscallbuf 2 0.555944\noverflow_branch_counter-32 2 2.97918\noverflow_branch_counter-32-no-syscallbuf 2 3.1523\npatch_page_end-32 2 0.168311\npatch_page_end-32-no-syscallbuf 2 0.027147\nx86/patch_40_80_f6_81-32 2 0.164649\nx86/patch_40_80_f6_81-32-no-syscallbuf 2 0.0250984\nperf_event_mmap-32 2 1.20662\nperf_event_mmap-32-no-syscallbuf 2 1.20416\npriority-32 2 0.188146\npriority-32-no-syscallbuf 2 0.187545\nptrace_remote_unmap-32 2 4.96867\nptrace_remote_unmap-32-no-syscallbuf 2 4.48549\nread_big_struct-32 2 0.895185\nread_big_struct-32-no-syscallbuf 2 0.971367\nremove_latest_trace-32 2 1.19413\nremove_latest_trace-32-no-syscallbuf 2 1.18728\nrestart_abnormal_exit-32 2 1.15147\nrestart_abnormal_exit-32-no-syscallbuf 2 1.11481\nreverse_continue_breakpoint-32 2 1.68965\nreverse_continue_breakpoint-32-no-syscallbuf 2 1.79149\nreverse_continue_multiprocess-32 2 10.6853\nreverse_continue_multiprocess-32-no-syscallbuf 2 10.3271\nreverse_continue_process_signal-32 2 3.62473\nreverse_continue_process_signal-32-no-syscallbuf 2 5.01924\nreverse_many_breakpoints-32 2 4.38134\nreverse_many_breakpoints-32-no-syscallbuf 2 5.46287\nreverse_step_long-32 2 6.24439\nreverse_step_long-32-no-syscallbuf 2 9.08036\nreverse_step_threads-32 2 2.50329\nreverse_step_threads-32-no-syscallbuf 2 2.31751\nreverse_step_threads_break-32 2 5.17554\nreverse_step_threads_break-32-no-syscallbuf 2 5.72419\nrr_ps-32 2 0.436267\nrr_ps-32-no-syscallbuf 2 0.374363\nrr_ps_ns-32 2 0.234007\nrr_ps_ns-32-no-syscallbuf 2 0.240328\nrseq-32 2 67.2539\nrseq-32-no-syscallbuf 2 83.9439\nsearch-32 2 0.864452\nsearch-32-no-syscallbuf 2 0.817897\nseccomp_blocks_rr-32 2 0.445652\nseccomp_blocks_rr-32-no-syscallbuf 2 0.191702\nseccomp_signals-32 2 2.71263\nseccomp_signals-32-no-syscallbuf 2 3.18287\nsegfault-32 2 0.187947\nsegfault-32-no-syscallbuf 2 0.167304\nshared_map-32 2 0.231787\nshared_map-32-no-syscallbuf 2 0.217581\nshared_persistent_file-32 2 0.989357\nshared_persistent_file-32-no-syscallbuf 2 0.914795\nsignal_numbers-32 2 1.06353\nsignal_numbers-32-no-syscallbuf 2 1.02158\nsigprocmask_race-32 2 0.183223\nsigprocmask_race-32-no-syscallbuf 2 0.0195983\nsigprocmask_rr_sigs_nondefault-32 2 0.0950051\nsigprocmask_rr_sigs_nondefault-32-no-syscallbuf 2 0.0818044\nsimple-32 2 0.324804\nsimple-32-no-syscallbuf 2 0.29707\nx86/singlestep_pushf-32 2 0.870134\nx86/singlestep_pushf-32-no-syscallbuf 2 0.75588\nstack_growth-32 2 0.835045\nstack_growth-32-no-syscallbuf 2 0.865223\nstep_thread-32 2 1.00272\nstep_thread-32-no-syscallbuf 2 1.03955\nstrict_priorities-32 2 10.905\nstrict_priorities-32-no-syscallbuf 2 12.5371\nx86/string_instructions-32 2 0.732684\nx86/string_instructions-32-no-syscallbuf 2 0.690063\nx86/string_instructions_async_signals-32 2 0.243053\nx86/string_instructions_async_signals-32-no-syscallbuf 2 70.768027\nx86/string_instructions_async_signals_shared-32 2 0.280141\nx86/string_instructions_async_signals_shared-32-no-syscallbuf 2 91.424003\nx86/string_instructions_multiwatch-32 2 0.885137\nx86/string_instructions_multiwatch-32-no-syscallbuf 2 0.815804\nx86/string_instructions_replay-32 2 13.1396\nx86/string_instructions_replay-32-no-syscallbuf 2 13.083\nx86/string_instructions_singlestep_fastforward-32 2 7.99402\nx86/string_instructions_singlestep_fastforward-32-no-syscallbuf 2 8.02594\nx86/string_instructions_watch-32 2 0.944771\nx86/string_instructions_watch-32-no-syscallbuf 2 0.935292\nsyscallbuf_fd_disabling-32 2 0.305953\nsyscallbuf_fd_disabling-32-no-syscallbuf 2 0.282688\nsyscallbuf_signal_blocking_read-32 2 1.23466\nsyscallbuf_signal_blocking_read-32-no-syscallbuf 2 1.14413\nsysconf_onln-32 2 0.344965\nsysconf_onln-32-no-syscallbuf 2 0.327284\ntarget_fork-32 2 2.71431\ntarget_fork-32-no-syscallbuf 2 1.43742\ntarget_process-32 2 1.32236\ntarget_process-32-no-syscallbuf 2 1.21721\ntcp_sockets-32 2 0.14743\ntcp_sockets-32-no-syscallbuf 2 0.151912\nterm_nonmain-32 2 0.21022\nterm_nonmain-32-no-syscallbuf 2 0.208668\nterm_rr-32 2 3.27718\nterm_rr-32-no-syscallbuf 2 3.26641\nterm_trace_reset-32 2 0.214047\nterm_trace_reset-32-no-syscallbuf 2 0.213101\nterm_trace_syscall-32 2 0.228815\nterm_trace_syscall-32-no-syscallbuf 2 0.24171\nthread_exit_signal-32 2 3.09934\nthread_exit_signal-32-no-syscallbuf 2 2.99841\nthread_open_race-32 2 33.8294\nthread_open_race-32-no-syscallbuf 2 0.0212188\nthread_stress-32 2 13.7434\nthread_stress-32-no-syscallbuf 2 16.5669\nthreaded_syscall_spam-32 2 1.71365\nthreaded_syscall_spam-32-no-syscallbuf 2 0.0223637\nthreads-32 2 1.20922\nthreads-32-no-syscallbuf 2 1.14972\ntls-32 2 0.891054\ntls-32-no-syscallbuf 2 0.863566\nttyname-32 2 0.155298\nttyname-32-no-syscallbuf 2 0.185634\nunexpected_stack_growth-32 2 0.960644\nunexpected_stack_growth-32-no-syscallbuf 2 0.938926\nuser_ignore_sig-32 2 0.169817\nuser_ignore_sig-32-no-syscallbuf 2 0.166966\nvdso_clock_gettime_stack-32 2 0.0198637\nvdso_clock_gettime_stack-32-no-syscallbuf 2 0.0198518\nvdso_gettimeofday_stack-32 2 0.0196665\nvdso_gettimeofday_stack-32-no-syscallbuf 2 0.0200317\nvdso_time_stack-32 2 0.0221022\nvdso_time_stack-32-no-syscallbuf 2 0.0202745\nvfork-32 2 0.236849\nvfork-32-no-syscallbuf 2 0.305823\nvfork_read_clone_stress-32 2 1.58314\nvfork_read_clone_stress-32-no-syscallbuf 2 2.62239\nvsyscall_reverse_next-32 2 211.0415\nvsyscall_reverse_next-32-no-syscallbuf 2 205.237\nwait_for_all-32 2 1.14266\nwait_for_all-32-no-syscallbuf 2 1.14552\nwatchpoint-32 2 1.22955\nwatchpoint-32-no-syscallbuf 2 1.35199\nwatchpoint_at_sched-32 2 1.13428\nwatchpoint_at_sched-32-no-syscallbuf 2 1.25188\nwatchpoint_before_signal-32 2 0.910176\nwatchpoint_before_signal-32-no-syscallbuf 2 0.854977\nwatchpoint_no_progress-32 2 3.67209\nwatchpoint_no_progress-32-no-syscallbuf 2 1.86114\nwatchpoint_size_change-32 2 0.887745\nwatchpoint_size_change-32-no-syscallbuf 2 0.902858\nwatchpoint_syscall-32 2 0.901712\nwatchpoint_syscall-32-no-syscallbuf 2 0.813837\nwatchpoint_unaligned-32 2 0.781136\nwatchpoint_unaligned-32-no-syscallbuf 2 0.800987\nasync_signal_syscalls_100-32 2 0.197139\nasync_signal_syscalls_100-32-no-syscallbuf 2 4.47429\nasync_signal_syscalls_1000-32 2 0.18801\nasync_signal_syscalls_1000-32-no-syscallbuf 2 3.44946\nbad_breakpoint-32 2 7.34282\nbad_breakpoint-32-no-syscallbuf 2 8.09281\nbreak_block-32 2 9.83223\nbreak_block-32-no-syscallbuf 2 9.83806\nbreak_clock-32 2 0.946965\nbreak_clock-32-no-syscallbuf 2 1.12394\nbreak_clone-32 2 0.751169\nbreak_clone-32-no-syscallbuf 2 0.820749\nbreak_exec-32 2 0.84265\nbreak_exec-32-no-syscallbuf 2 0.874733\nbreak_int3-32 2 0.780189\nbreak_int3-32-no-syscallbuf 2 0.759644\nbreak_mmap_private-32 2 1.98541\nbreak_mmap_private-32-no-syscallbuf 2 1.89648\nbreak_msg-32 2 2.89203\nbreak_msg-32-no-syscallbuf 2 3.05882\nx86/break_rdtsc-32 2 0.848203\nx86/break_rdtsc-32-no-syscallbuf 2 0.841489\nbreak_sigreturn-32 2 4.78895\nbreak_sigreturn-32-no-syscallbuf 2 4.88569\nbreak_sync_signal-32 2 0.753919\nbreak_sync_signal-32-no-syscallbuf 2 0.750371\nbreak_thread-32 2 0.912845\nbreak_thread-32-no-syscallbuf 2 1.16875\nbreak_time_slice-32 2 9.33131\nbreak_time_slice-32-no-syscallbuf 2 9.28867\nbreakpoint_consistent-32 2 0.792691\nbreakpoint_consistent-32-no-syscallbuf 2 0.775111\ncall_exit-32 2 0.981659\ncall_exit-32-no-syscallbuf 2 0.993623\ncheck_patched_pthread-32 2 1.86368\ncheck_patched_pthread-32-no-syscallbuf 2 1.84408\ncheckpoint_async_signal_syscalls_1000-32 2 2.25777\ncheckpoint_async_signal_syscalls_1000-32-no-syscallbuf 2 0.0206373\ncheckpoint_mmap_shared-32 2 19.0184\ncheckpoint_mmap_shared-32-no-syscallbuf 2 13.8387\ncheckpoint_prctl_name-32 2 24.3736\ncheckpoint_prctl_name-32-no-syscallbuf 2 23.9934\ncheckpoint_simple-32 2 10.1515\ncheckpoint_simple-32-no-syscallbuf 2 7.59328\nchecksum_sanity_noclone-32 2 1.41863\nchecksum_sanity_noclone-32-no-syscallbuf 2 1.55539\ncomm-32 2 0.617483\ncomm-32-no-syscallbuf 2 0.60854\ncont_signal-32 2 4.82038\ncont_signal-32-no-syscallbuf 2 4.83081\nx86/cpuid-32 2 1.34973\nx86/cpuid-32-no-syscallbuf 2 0.999242\ndead_thread_target-32 2 0.989117\ndead_thread_target-32-no-syscallbuf 2 0.952645\ndesched_ticks-32 2 0.872766\ndesched_ticks-32-no-syscallbuf 2 0.0242881\ndeliver_async_signal_during_syscalls-32 2 0.708833\ndeliver_async_signal_during_syscalls-32-no-syscallbuf 2 0.0201246\nenv_newline-32 2 0.168631\nenv_newline-32-no-syscallbuf 2 0.156516\nexec_deleted-32 2 0.170722\nexec_deleted-32-no-syscallbuf 2 0.168588\nexec_stop-32 2 0.897157\nexec_stop-32-no-syscallbuf 2 0.909516\nexecp-32 2 0.180209\nexecp-32-no-syscallbuf 2 0.161059\nexplicit_checkpoint_clone-32 2 0.995701\nexplicit_checkpoint_clone-32-no-syscallbuf 2 0.952514\nfile_name_newline-32 2 0.187082\nfile_name_newline-32-no-syscallbuf 2 0.159259\nfinal_sigkill-32 2 0.985235\nfinal_sigkill-32-no-syscallbuf 2 0.96928\nfirst_instruction-32 2 0.741433\nfirst_instruction-32-no-syscallbuf 2 0.718259\nfork_exec_info_thr-32 2 3.71603\nfork_exec_info_thr-32-no-syscallbuf 2 3.23103\nget_thread_list-32 2 0.995385\nget_thread_list-32-no-syscallbuf 2 0.946593\nhardlink_mmapped_files-32 2 2.21809\nhardlink_mmapped_files-32-no-syscallbuf 2 2.19885\nhbreak-32 2 0.87166\nhbreak-32-no-syscallbuf 2 0.89237\nmprotect_step-32 2 1.05356\nmprotect_step-32-no-syscallbuf 2 1.12296\nnested_detach-32 2 0.48179\nnested_detach-32-no-syscallbuf 2 0.407968\nnested_detach_kill-32 2 0.620392\nnested_detach_kill-32-no-syscallbuf 2 0.522451\nnested_release-32 2 0.310225\nnested_release-32-no-syscallbuf 2 0.303973\nparent_no_break_child_bkpt-32 2 1.07206\nparent_no_break_child_bkpt-32-no-syscallbuf 2 1.04337\nparent_no_stop_child_crash-32 2 1.06683\nparent_no_stop_child_crash-32-no-syscallbuf 2 0.994023\npost_exec_fpu_regs-32 2 0.58547\npost_exec_fpu_regs-32-no-syscallbuf 2 0.584769\nproc_maps-32 2 0.743487\nproc_maps-32-no-syscallbuf 2 0.81206\nread_bad_mem-32 2 0.741059\nread_bad_mem-32-no-syscallbuf 2 0.746854\nrecord_replay-32 2 142.449\nrecord_replay-32-no-syscallbuf 2 142.207\nremove_watchpoint-32 2 0.887807\nremove_watchpoint-32-no-syscallbuf 2 0.848615\nreplay_overlarge_event_number-32 2 0.151729\nreplay_overlarge_event_number-32-no-syscallbuf 2 0.145948\nreplay_serve_files-32 2 3.53657\nreplay_serve_files-32-no-syscallbuf 2 3.72855\nrestart_invalid_checkpoint-32 2 0.979497\nrestart_invalid_checkpoint-32-no-syscallbuf 2 0.936837\nrestart_unstable-32 2 0.976465\nrestart_unstable-32-no-syscallbuf 2 0.946823\nrestart_diversion-32 2 1.05779\nrestart_diversion-32-no-syscallbuf 2 1.06658\nreverse_alarm-32 2 5.55884\nreverse_alarm-32-no-syscallbuf 2 4.26309\nreverse_continue_exec_subprocess-32 2 3.53948\nreverse_continue_exec_subprocess-32-no-syscallbuf 2 3.5475\nreverse_continue_fork_subprocess-32 2 1.11541\nreverse_continue_fork_subprocess-32-no-syscallbuf 2 1.12745\nreverse_continue_int3-32 2 4.08885\nreverse_continue_int3-32-no-syscallbuf 2 3.79756\nreverse_continue_start-32 2 1.74623\nreverse_continue_start-32-no-syscallbuf 2 1.84734\nreverse_finish-32 2 2.71542\nreverse_finish-32-no-syscallbuf 2 2.34464\nreverse_step_breakpoint-32 2 4.20755\nreverse_step_breakpoint-32-no-syscallbuf 2 4.30403\nreverse_step_signal-32 2 4.36456\nreverse_step_signal-32-no-syscallbuf 2 4.44296\nreverse_step_threads2-32 2 4.43858\nreverse_step_threads2-32-no-syscallbuf 2 4.3075\nreverse_watchpoint-32 2 3.28588\nreverse_watchpoint-32-no-syscallbuf 2 3.61425\nreverse_watchpoint_syscall-32 2 7.9328\nreverse_watchpoint_syscall-32-no-syscallbuf 2 7.61239\nrun_end-32 2 1.0957\nrun_end-32-no-syscallbuf 2 1.08614\nrun_in_function-32 2 0.9406\nrun_in_function-32-no-syscallbuf 2 0.975155\nsanity-32 2 0.730954\nsanity-32-no-syscallbuf 2 0.718052\nseekticks-32 2 1.89101\nseekticks-32-no-syscallbuf 2 1.71722\nshm_checkpoint-32 2 0.979113\nshm_checkpoint-32-no-syscallbuf 2 0.95366\nsiginfo-32 2 0.730536\nsiginfo-32-no-syscallbuf 2 0.768976\nx86/sigreturn_checksum-32 2 0.736871\nx86/sigreturn_checksum-32-no-syscallbuf 2 0.69224\nsignal_stop-32 2 0.766017\nsignal_stop-32-no-syscallbuf 2 0.824693\nsignal_checkpoint-32 2 0.958273\nsignal_checkpoint-32-no-syscallbuf 2 1.01121\nsimple_script-32 2 0.177902\nsimple_script-32-no-syscallbuf 2 0.191716\nsimple_script_debug-32 2 0.888283\nsimple_script_debug-32-no-syscallbuf 2 0.894607\nsimple_winch-32 2 2.32163\nsimple_winch-32-no-syscallbuf 2 2.12602\nstack_overflow_debug-32 2 6.3049\nstack_overflow_debug-32-no-syscallbuf 2 6.60805\nstep1-32 2 0.841349\nstep1-32-no-syscallbuf 2 0.766025\nx86/step_rdtsc-32 2 0.883087\nx86/step_rdtsc-32-no-syscallbuf 2 0.927036\nstep_signal-32 2 0.879484\nstep_signal-32-no-syscallbuf 2 0.916336\nx86/string_instructions_break-32 2 6.07348\nx86/string_instructions_break-32-no-syscallbuf 2 7.3036\nx86/string_instructions_replay_quirk-32 2 6.26888\nx86/string_instructions_replay_quirk-32-no-syscallbuf 2 6.62562\nsubprocess_exit_ends_session-32 2 1.00101\nsubprocess_exit_ends_session-32-no-syscallbuf 2 0.979481\nswitch_processes-32 2 5.00449\nswitch_processes-32-no-syscallbuf 2 3.96395\nsyscallbuf_timeslice_250-32 2 0.2163\nsyscallbuf_timeslice_250-32-no-syscallbuf 2 3.28733\ntrace_version-32 2 2.55284\ntrace_version-32-no-syscallbuf 2 2.55163\nterm_trace_cpu-32 2 0.541342\nterm_trace_cpu-32-no-syscallbuf 2 0.621864\ntrace_events-32 2 0.131738\ntrace_events-32-no-syscallbuf 2 0.127949\ntty-32 2 0.166929\ntty-32-no-syscallbuf 2 0.147314\nunmap_vdso-32 2 0.336841\nunmap_vdso-32-no-syscallbuf 2 0.340823\nunwind_on_signal-32 2 0.803562\nunwind_on_signal-32-no-syscallbuf 2 0.792202\nvfork_exec-32 2 0.942089\nvfork_exec-32-no-syscallbuf 2 0.957233\nvfork_break_parent-32 2 0.884067\nvfork_break_parent-32-no-syscallbuf 2 0.873047\nvsyscall_singlestep-32 2 0.0226703\nvsyscall_singlestep-32-no-syscallbuf 2 0.0210348\nwatch_code-32 2 1.8636\nwatch_code-32-no-syscallbuf 2 1.79997\nwatchpoint_cond-32 2 0.788546\nwatchpoint_cond-32-no-syscallbuf 2 0.766512\nwhen-32 2 0.761362\nwhen-32-no-syscallbuf 2 0.787807\nclose_range 1 0.187604\nclose_range-no-syscallbuf 1 0.169697\ndlchecksum 1 0.240732\ndlchecksum-no-syscallbuf 1 0.206452\nepoll_many 1 0.216123\nepoll_many-no-syscallbuf 1 0.240203\nepoll_pwait2 1 1.30869\nepoll_pwait2-no-syscallbuf 1 1.22883\nfutex_invalid_op 1 0.17379\nfutex_invalid_op-no-syscallbuf 1 0.213894\nfutex_restart_race 1 0.263257\nfutex_restart_race-no-syscallbuf 1 0.22909\nfutex_restart_clone 1 0.205975\nfutex_restart_clone-no-syscallbuf 1 0.196681\nioctl_br 1 0.40846\nioctl_br-no-syscallbuf 1 0.591008\nmremap_dontunmap 1 0.222197\nmremap_dontunmap-no-syscallbuf 1 0.192309\nppoll_deliver 1 0.165071\nppoll_deliver-no-syscallbuf 1 0.158939\nx86/rdtsc_flags 1 0.161648\nx86/rdtsc_flags-no-syscallbuf 1 0.149144\nx86/signal_xmm_state 1 6.5201\nx86/signal_xmm_state-no-syscallbuf 1 6.15106\nsigpwr 1 0.145139\nsigpwr-no-syscallbuf 1 0.161406\nsock_name_null 1 0.173122\nsock_name_null-no-syscallbuf 1 0.134844\nsysconf_conf 1 0.155498\nsysconf_conf-no-syscallbuf 1 0.13819\nchaos_oom 1 0.719051\nchaos_oom-no-syscallbuf 1 0.486065\nx86/diversion_rdtsc 1 0.97806\nx86/diversion_rdtsc-no-syscallbuf 1 1.08858\ngdb_qpasssignals 1 110.1108\ngdb_qpasssignals-no-syscallbuf 1 97.4456\nmadvise_fracture_flags 1 57.982\nmadvise_fracture_flags-no-syscallbuf 1 88.7955\nx86/morestack_unwind 1 1.05934\nx86/morestack_unwind-no-syscallbuf 1 0.033799\nnested_detach_kill_stuck 1 5.52231\nnested_detach_kill_stuck-no-syscallbuf 1 5.47973\nx86/rdtsc_loop 1 7.49252\nx86/rdtsc_loop-no-syscallbuf 1 0.0176659\nx86/rdtsc_loop2 1 3.23895\nx86/rdtsc_loop2-no-syscallbuf 1 0.0587636\nrseq_syscallbuf 1 1.68397\nrseq_syscallbuf-no-syscallbuf 1 0.0232907\nseccomp_open 1 0.256711\nseccomp_open-no-syscallbuf 1 0.224981\nx86/syscallbuf_branch_check 1 0.263251\nx86/syscallbuf_branch_check-no-syscallbuf 1 0.0358348\nx86/syscallbuf_rdtsc_page 1 0.224774\nx86/syscallbuf_rdtsc_page-no-syscallbuf 1 0.0200236\nterm_rr_ok 1 0.239889\nterm_rr_ok-no-syscallbuf 1 0.411474\ncopy_all 1 1.14145\ncopy_all-no-syscallbuf 1 0.99862\ntick0 1 0.810798\ntick0-no-syscallbuf 1 0.781358\ntick0_less 1 0.774784\ntick0_less-no-syscallbuf 1 0.708288\nwatchpoint_unaligned2 1 1.04218\nwatchpoint_unaligned2-no-syscallbuf 1 1.04466\nclose_range-32 1 0.145352\nclose_range-32-no-syscallbuf 1 0.189966\ndlchecksum-32 1 0.25934\ndlchecksum-32-no-syscallbuf 1 0.256462\nepoll_many-32 1 0.152067\nepoll_many-32-no-syscallbuf 1 0.201357\nepoll_pwait2-32 1 1.2001\nepoll_pwait2-32-no-syscallbuf 1 1.14867\nfutex_invalid_op-32 1 0.20886\nfutex_invalid_op-32-no-syscallbuf 1 0.211214\nfutex_restart_race-32 1 0.25145\nfutex_restart_race-32-no-syscallbuf 1 0.209322\nfutex_restart_clone-32 1 0.186733\nfutex_restart_clone-32-no-syscallbuf 1 0.187653\nioctl_br-32 1 0.192089\nioctl_br-32-no-syscallbuf 1 0.168439\nmremap_dontunmap-32 1 0.204069\nmremap_dontunmap-32-no-syscallbuf 1 0.121815\nppoll_deliver-32 1 0.149065\nppoll_deliver-32-no-syscallbuf 1 0.16973\nx86/rdtsc_flags-32 1 0.158374\nx86/rdtsc_flags-32-no-syscallbuf 1 0.161395\nx86/signal_xmm_state-32 1 5.82273\nx86/signal_xmm_state-32-no-syscallbuf 1 5.93857\nsigpwr-32 1 0.135917\nsigpwr-32-no-syscallbuf 1 0.12206\nsock_name_null-32 1 0.216395\nsock_name_null-32-no-syscallbuf 1 0.18803\nsysconf_conf-32 1 0.236007\nsysconf_conf-32-no-syscallbuf 1 0.170377\nchaos_oom-32 1 0.258801\nchaos_oom-32-no-syscallbuf 1 0.218391\nx86/diversion_rdtsc-32 1 1.00397\nx86/diversion_rdtsc-32-no-syscallbuf 1 1.03605\ngdb_qpasssignals-32 1 75.7295\ngdb_qpasssignals-32-no-syscallbuf 1 95.712\nmadvise_fracture_flags-32 1 58.9242\nmadvise_fracture_flags-32-no-syscallbuf 1 86.3502\nx86/morestack_unwind-32 1 1.2353\nx86/morestack_unwind-32-no-syscallbuf 1 0.134301\nnested_detach_kill_stuck-32 1 5.67408\nnested_detach_kill_stuck-32-no-syscallbuf 1 5.53669\nx86/rdtsc_loop-32 1 0.189036\nx86/rdtsc_loop-32-no-syscallbuf 1 0.0190103\nx86/rdtsc_loop2-32 1 0.119683\nx86/rdtsc_loop2-32-no-syscallbuf 1 0.0781239\nrseq_syscallbuf-32 1 1.66755\nrseq_syscallbuf-32-no-syscallbuf 1 0.0220513\nseccomp_open-32 1 0.240722\nseccomp_open-32-no-syscallbuf 1 0.183111\nx86/syscallbuf_branch_check-32 1 0.320975\nx86/syscallbuf_branch_check-32-no-syscallbuf 1 0.0538966\nx86/syscallbuf_rdtsc_page-32 1 0.187748\nx86/syscallbuf_rdtsc_page-32-no-syscallbuf 1 0.0202657\nterm_rr_ok-32 1 0.251002\nterm_rr_ok-32-no-syscallbuf 1 0.222906\ncopy_all-32 1 1.00337\ncopy_all-32-no-syscallbuf 1 0.934465\ntick0-32 1 0.61251\ntick0-32-no-syscallbuf 1 0.634147\ntick0_less-32 1 0.605018\ntick0_less-32-no-syscallbuf 1 0.652338\nwatchpoint_unaligned2-32 1 0.860627\nwatchpoint_unaligned2-32-no-syscallbuf 1 0.854681\n---\n"
  },
  {
    "path": ".buildkite/Manifest.toml",
    "content": "# This file is machine-generated - editing it directly is not advised\n\njulia_version = \"1.7.2\"\nmanifest_format = \"2.0\"\n\n[[deps.ArgTools]]\nuuid = \"0dad84c5-d112-42e6-8d28-ef12dabb789f\"\n\n[[deps.Artifacts]]\nuuid = \"56f22d72-fd6d-98f1-02f0-08ddc0907c33\"\n\n[[deps.Base64]]\nuuid = \"2a0f44e3-6c83-55bd-87e4-b1978d98bd5f\"\n\n[[deps.Dates]]\ndeps = [\"Printf\"]\nuuid = \"ade2ca70-3891-5945-98fb-dc099432e06a\"\n\n[[deps.Downloads]]\ndeps = [\"ArgTools\", \"LibCURL\", \"NetworkOptions\"]\nuuid = \"f43a241f-c20a-4ad4-852c-f6b1247861c6\"\n\n[[deps.InteractiveUtils]]\ndeps = [\"Markdown\"]\nuuid = \"b77e0a4c-d291-57a0-90e8-8db25a27a240\"\n\n[[deps.JLLWrappers]]\ndeps = [\"Preferences\"]\ngit-tree-sha1 = \"abc9885a7ca2052a736a600f7fa66209f96506e1\"\nuuid = \"692b3bcd-3c85-4b1f-b108-f13ce0eb3210\"\nversion = \"1.4.1\"\n\n[[deps.LibCURL]]\ndeps = [\"LibCURL_jll\", \"MozillaCACerts_jll\"]\nuuid = \"b27032c2-a3e7-50c8-80cd-2d36dbcbfd21\"\n\n[[deps.LibCURL_jll]]\ndeps = [\"Artifacts\", \"LibSSH2_jll\", \"Libdl\", \"MbedTLS_jll\", \"Zlib_jll\", \"nghttp2_jll\"]\nuuid = \"deac9b47-8bc7-5906-a0fe-35ac56dc84c0\"\n\n[[deps.LibGit2]]\ndeps = [\"Base64\", \"NetworkOptions\", \"Printf\", \"SHA\"]\nuuid = \"76f85450-5226-5b5a-8eaa-529ad045b433\"\n\n[[deps.LibSSH2_jll]]\ndeps = [\"Artifacts\", \"Libdl\", \"MbedTLS_jll\"]\nuuid = \"29816b5a-b9ab-546f-933c-edad1886dfa8\"\n\n[[deps.Libdl]]\nuuid = \"8f399da3-3557-5675-b5ff-fb832c97cbdb\"\n\n[[deps.Libiconv_jll]]\ndeps = [\"Artifacts\", \"JLLWrappers\", \"Libdl\", \"Pkg\"]\ngit-tree-sha1 = \"42b62845d70a619f063a7da093d995ec8e15e778\"\nuuid = \"94ce4f54-9a6c-5748-9c1c-f9c7231a4531\"\nversion = \"1.16.1+1\"\n\n[[deps.Logging]]\nuuid = \"56ddb016-857b-54e1-b83d-db4d58db5568\"\n\n[[deps.Markdown]]\ndeps = [\"Base64\"]\nuuid = \"d6f4376e-aef5-505a-96c1-9c027394607a\"\n\n[[deps.MbedTLS_jll]]\ndeps = [\"Artifacts\", \"Libdl\"]\nuuid = \"c8ffd9c3-330d-5841-b78e-0817d7145fa1\"\n\n[[deps.MozillaCACerts_jll]]\nuuid = \"14a3606d-f60d-562e-9121-12d972cd8159\"\n\n[[deps.NetworkOptions]]\nuuid = \"ca575930-c2e3-43a9-ace4-1e988b2c1908\"\n\n[[deps.Pkg]]\ndeps = [\"Artifacts\", \"Dates\", \"Downloads\", \"LibGit2\", \"Libdl\", \"Logging\", \"Markdown\", \"Printf\", \"REPL\", \"Random\", \"SHA\", \"Serialization\", \"TOML\", \"Tar\", \"UUIDs\", \"p7zip_jll\"]\nuuid = \"44cfe95a-1eb2-52ea-b672-e2afdf69b78f\"\n\n[[deps.Preferences]]\ndeps = [\"TOML\"]\ngit-tree-sha1 = \"47e5f437cc0e7ef2ce8406ce1e7e24d44915f88d\"\nuuid = \"21216c6a-2e73-6563-6e65-726566657250\"\nversion = \"1.3.0\"\n\n[[deps.Printf]]\ndeps = [\"Unicode\"]\nuuid = \"de0858da-6303-5e67-8744-51eddeeeb8d7\"\n\n[[deps.REPL]]\ndeps = [\"InteractiveUtils\", \"Markdown\", \"Sockets\", \"Unicode\"]\nuuid = \"3fa0cd96-eef1-5676-8a61-b3b8758bbffb\"\n\n[[deps.Random]]\ndeps = [\"SHA\", \"Serialization\"]\nuuid = \"9a3f8284-a2c9-5f02-9a11-845980a1fd5c\"\n\n[[deps.SHA]]\nuuid = \"ea8e919c-243c-51af-8825-aaa63cd721ce\"\n\n[[deps.Serialization]]\nuuid = \"9e88b42a-f829-5b0c-bbe9-9e923198166b\"\n\n[[deps.Sockets]]\nuuid = \"6462fe0b-24de-5631-8697-dd941f90decc\"\n\n[[deps.StringEncodings]]\ndeps = [\"Libiconv_jll\"]\ngit-tree-sha1 = \"50ccd5ddb00d19392577902f0079267a72c5ab04\"\nuuid = \"69024149-9ee7-55f6-a4c4-859efe599b68\"\nversion = \"0.3.5\"\n\n[[deps.TOML]]\ndeps = [\"Dates\"]\nuuid = \"fa267f1f-6049-4f14-aa54-33bafae1ed76\"\n\n[[deps.Tar]]\ndeps = [\"ArgTools\", \"SHA\"]\nuuid = \"a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e\"\n\n[[deps.UUIDs]]\ndeps = [\"Random\", \"SHA\"]\nuuid = \"cf7118a7-6976-5b1a-9a39-7adc72f591a4\"\n\n[[deps.Unicode]]\nuuid = \"4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5\"\n\n[[deps.YAML]]\ndeps = [\"Base64\", \"Dates\", \"Printf\", \"StringEncodings\"]\ngit-tree-sha1 = \"3c6e8b9f5cdaaa21340f841653942e1a6b6561e5\"\nuuid = \"ddb6d928-2868-570f-bddf-ab3f9cf99eb6\"\nversion = \"0.4.7\"\n\n[[deps.Zlib_jll]]\ndeps = [\"Libdl\"]\nuuid = \"83775a58-1f1d-513f-b197-d71354ab007a\"\n\n[[deps.nghttp2_jll]]\ndeps = [\"Artifacts\", \"Libdl\"]\nuuid = \"8e850ede-7688-5339-a07c-302acd2aaf8d\"\n\n[[deps.p7zip_jll]]\ndeps = [\"Artifacts\", \"Libdl\"]\nuuid = \"3f19e933-33d8-53b3-aaab-bd5110c3b7a0\"\n"
  },
  {
    "path": ".buildkite/Project.toml",
    "content": "[deps]\nYAML = \"ddb6d928-2868-570f-bddf-ab3f9cf99eb6\"\n"
  },
  {
    "path": ".buildkite/capture_tmpdir.jl",
    "content": "import Dates\nimport Pkg\nimport Tar\n\nfunction my_exit(process::Base.Process)\n    wait(process)\n\n    @info(\n        \"\",\n        process.exitcode,\n        process.termsignal,\n    )\n\n    # Pass the exit code back up\n    if process.termsignal != 0\n        ccall(:raise, Cvoid, (Cint,), process.termsignal)\n\n        # If for some reason the signal did not cause an exit, we'll exit manually.\n        # We need to make sure that we exit with a non-zero exit code.\n        if process.exitcode != 0\n            exit(process.exitcode)\n        else\n            exit(1)\n        end\n    end\n    exit(process.exitcode)\nend\n\nfunction get_from_env(name::AbstractString)\n    value = ENV[name]\n    result = convert(String, strip(value))::String\n    return result\nend\n\ncleanup_string(str::AbstractString) = replace(str, r\"[^A-Za-z0-9_]\" => \"_\")\n\nif Base.VERSION < v\"1.6\"\n    throw(ErrorException(\"The `$(basename(@__FILE__))` script requires Julia 1.6 or greater\"))\nend\n\nif length(ARGS) < 1\n    throw(ErrorException(\"Usage: julia $(basename(@__FILE__)) [command...]\"))\nend\n\nconst build_number                      = get_from_env(\"BUILDKITE_BUILD_NUMBER\") |> cleanup_string\nconst commit_full                       = get_from_env(\"BUILDKITE_COMMIT\")       |> cleanup_string\nconst job_name                          = get_from_env(\"BUILDKITE_STEP_KEY\")     |> cleanup_string\nconst buildkite_timeout_minutes_string  = get_from_env(\"BUILDKITE_TIMEOUT\")\n\nconst commit_short = first(commit_full, 10)\nconst buildkite_timeout_minutes = parse(Int, buildkite_timeout_minutes_string)::Int\nconst cleanup_minutes = 15\nconst ctest_timeout_minutes = buildkite_timeout_minutes - cleanup_minutes\nif ctest_timeout_minutes < 1\n    msg = \"ctest_timeout_minutes must be strictly positive\"\n    @error(\n        msg,\n        ctest_timeout_minutes,\n        buildkite_timeout_minutes,\n        cleanup_minutes,\n    )\n    throw(ErrorException(msg))\nend\n\n@info(\n    \"\",\n    build_number,\n    job_name,\n    commit_full,\n    commit_short,\n    ctest_timeout_minutes,\n    buildkite_timeout_minutes,\n    cleanup_minutes,\n)\n\nconst my_archives_dir    = joinpath(pwd(), \"my_archives_dir\")\nconst my_temp_parent_dir = joinpath(pwd(), \"my_temp_parent_dir\")\n\nmkpath(my_archives_dir)\nmkpath(my_temp_parent_dir)\n\nconst TMPDIR = mktempdir(my_temp_parent_dir)\n\nproc = nothing\n\nmktempdir(my_temp_parent_dir) do dir\n    Pkg.activate(dir)\n    Pkg.add(\"Zstd_jll\")\n    zstd_jll = Base.require(Base.PkgId(Base.UUID(\"3161d3a3-bdf6-5164-811a-617609db77b4\"), \"Zstd_jll\"))\n    # zstdmt(func) = Base.invokelatest(zstd_jll.zstdmt, func; adjust_LIBPATH=false)\n    zstdmt(func) = Base.invokelatest(zstd_jll.zstdmt, func)\n\n    new_env = copy(ENV)\n    new_env[\"TMPDIR\"] = TMPDIR\n    command = setenv(`$ARGS`, new_env)\n    global proc = run(command, (stdin, stdout, stderr); wait = false)\n\n    # Start asynchronous timer that will kill `ctest`\n    @async begin\n        sleep(ctest_timeout_minutes * 60)\n\n        # If we've exceeded the timeout and `ctest` is still running, kill it\n        if isopen(proc)\n            @error(\n                string(\n                    \"Process timed out \",\n                    \"(with a timeout of $(ctest_timeout_minutes) minutes). \",\n                    \"Killing with SIGTERM.\",\n\n                )\n            )\n            kill(proc, Base.SIGTERM)\n        end\n    end\n\n    # Wait for `ctest` to finish, either through naturally finishing its run, or `SIGTERM`\n    wait(proc)\n\n    if proc.termsignal != 0\n        @info \"Command signalled $(proc.termsignal)\"\n    else\n        @info \"Command returned $(proc.exitcode)\"\n    end\n    date_str = Dates.format(Dates.now(), Dates.dateformat\"yyyy_mm_dd_HH_MM_SS\")\n    artifact_specifications = [\n        (\"TMPDIR\", TMPDIR),\n    ]\n    for (artifact_name, artifact_input_dir) in artifact_specifications\n        dst_file_name = string(\n            artifact_name,\n            \"--build_$(build_number)\",\n            \"--$(job_name)\",\n            \"--commit_$(commit_short)\",\n            \"--$(date_str)\",\n            \".tar.zst\",\n        )\n        dst_full_path = joinpath(my_archives_dir, dst_file_name)\n        run(`find . -type p`) # list the named pipes before we delete them\n        run(`find . -type p -delete`)\n        run(`find . -type s`) # list the sockets before we delete them\n        run(`find . -type s -delete`)\n        zstdmt() do zstdp\n            tarproc = open(`$(zstdp) -o $(dst_full_path)`, \"w\")\n            Tar.create(artifact_input_dir, tarproc)\n            close(tarproc.in)\n        end\n\n        buildkite_upload_cmd = `buildkite-agent artifact upload $(dst_file_name)`\n        if !success(proc)\n            run(setenv(buildkite_upload_cmd; dir = my_archives_dir))\n        end\n    end\nend\n\nmy_exit(proc)\n"
  },
  {
    "path": ".buildkite/pipeline.yml",
    "content": "steps:\n  - label: \"Launch jobs\"\n    plugins:\n      - JuliaCI/julia#v1:\n          persist_depot_dirs: packages,artifacts,compiled\n          version: '1.7'\n    timeout_in_minutes: 15\n    agents:\n      queue: \"juliaecosystem\"\n      os: \"linux\"\n    commands: |\n      echo \"--- Instantiate the environment\"\n      julia --project=.buildkite -e 'import Pkg; Pkg.instantiate()'\n\n      echo \"--- Precompile the environment\"\n      julia --project=.buildkite -e 'import Pkg; Pkg.precompile()'\n\n      echo \"--- Generate the Buildkite pipeline YAML files\"\n      julia --project=.buildkite .buildkite/lib/generate.jl\n\n      echo \"--- Upload the Buildkite pipeline YAML files\"\n      julia --project=.buildkite .buildkite/lib/launch.jl\n"
  },
  {
    "path": ".clang-format",
    "content": "# BasedOnStyle:  Mozilla\nAccessModifierOffset: -2\nConstructorInitializerIndentWidth: 4\nAlignEscapedNewlinesLeft: false\nAlignTrailingComments: true\nAllowAllParametersOfDeclarationOnNextLine: false\nAllowShortIfStatementsOnASingleLine: false\nAllowShortLoopsOnASingleLine: false\nAlwaysBreakTemplateDeclarations: false\nAlwaysBreakBeforeMultilineStrings: false\nBreakBeforeBinaryOperators: false\nBreakBeforeTernaryOperators: true\nBreakConstructorInitializersBeforeComma: false\nBinPackParameters: true\nColumnLimit:     80\nConstructorInitializerAllOnOneLineOrOnePerLine: true\nDerivePointerBinding: false\nExperimentalAutoDetectBinPacking: false\nIndentCaseLabels: true\nMaxEmptyLinesToKeep: 1\nNamespaceIndentation: None\nObjCSpaceBeforeProtocolList: false\nPenaltyBreakBeforeFirstCallParameter: 19\nPenaltyBreakComment: 60\nPenaltyBreakString: 1000\nPenaltyBreakFirstLessLess: 120\nPenaltyExcessCharacter: 1000000\nPenaltyReturnTypeOnItsOwnLine: 200\nPointerBindsToType: true\nSpacesBeforeTrailingComments: 1\nCpp11BracedListStyle: false\nStandard:        Cpp11\nIndentWidth:     2\nTabWidth:        8\nUseTab:          Never\nBreakBeforeBraces: Attach\nIndentFunctionDeclarationAfterType: false\nSpacesInParentheses: false\nSpacesInAngles:  false\nSpaceInEmptyParentheses: false\nSpacesInCStyleCastParentheses: false\nSpaceAfterControlStatementKeyword: true\nSpaceBeforeAssignmentOperators: true\nContinuationIndentWidth: 4\n"
  },
  {
    "path": ".github/workflows/android-build.yml",
    "content": "name: Android Build\n\non: [push, pull_request]\n\njobs:\n  android-build:\n    name: Android Build\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n\n      - name: Build Dockerfile\n        shell: bash\n        run: docker build -t rr-android .android\n\n      - name: Create dist dir\n        shell: bash\n        run: mkdir -p obj/dist\n\n      - name: Build RR\n        shell: bash\n        run: |\n          docker run --rm \\\n            -v $(pwd):/src/rr \\\n            -v $(pwd)/obj/dist:/dist \\\n            rr-android\n\n      - uses: actions/upload-artifact@v4\n        with:\n          name: rr\n          path: obj/dist/rr-*-Android-x86_64.tar.gz\n"
  },
  {
    "path": ".github/workflows/build-and-test-main.yml",
    "content": "name: Build and test\n\non: [push, pull_request]\n\njobs:\n  setup:\n    name: Setup runners\n    runs-on: ubuntu-latest\n    if: github.repository == 'rr-debugger/rr'\n    steps:\n      - id: generate\n        name: Generate runner label\n        run: |\n          RUNNER_LABEL=rr_runner_$(uuidgen|tr -d -)\n          echo \"RUNNER_LABEL=$RUNNER_LABEL\" >> \"$GITHUB_OUTPUT\"\n      - name: Start runners\n        run: |2-\n          curl --fail -s -X POST -H \"Content-Type: application/json\" --data \"{\\\"operation\\\": \\\"create\\\", \\\"architectures\\\":[\\\"x86_64\\\", \\\"arm64\\\"], \\\"label\\\": \\\"${{ steps.generate.outputs.RUNNER_LABEL }}\\\"}\" https://bqugdqmvcql6yvz4i362qohyea0namsk.lambda-url.us-east-2.on.aws\n    outputs:\n      RUNNER_LABEL: ${{ steps.generate.outputs.RUNNER_LABEL }}\n\n  x86-64:\n    uses: ./.github/workflows/build-and-test.yml\n    needs: setup\n    if: github.repository == 'rr-debugger/rr'\n    with:\n      label: ${{ needs.setup.outputs.RUNNER_LABEL }}\n      architecture: x86_64\n\n  arm64:\n    uses: ./.github/workflows/build-and-test.yml\n    needs: setup\n    if: github.repository == 'rr-debugger/rr'\n    with:\n      label: ${{ needs.setup.outputs.RUNNER_LABEL }}\n      architecture: arm64\n\n  stop-runners:\n    name: Stop runners\n    runs-on: ubuntu-latest\n    needs:\n      - setup\n      - x86-64\n      - arm64\n    if: ${{ always() && github.repository == 'rr-debugger/rr' }}\n    steps:\n      - name: \"Stop runners\"\n        run: |2-\n          curl --fail -s -X POST -H \"Content-Type: application/json\" --data \"{\\\"operation\\\": \\\"destroy\\\", \\\"label\\\": \\\"${{ needs.setup.outputs.RUNNER_LABEL }}\\\"}\" https://bqugdqmvcql6yvz4i362qohyea0namsk.lambda-url.us-east-2.on.aws\n"
  },
  {
    "path": ".github/workflows/build-and-test.yml",
    "content": "name: Build and test on runner\n\non:\n  workflow_call:\n    inputs:\n      label:\n        required: true\n        type: string\n      architecture:\n        required: true\n        type: string\n\njobs:\n  build-and-test:\n    name: On runner\n    runs-on:\n      - ${{ inputs.label }}\n      - arch_${{ inputs.architecture }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v4\n\n      - name: Build\n        run: ./scripts/github-actions-build.sh\n\n      - name: Test\n        id: test\n        run: ./scripts/github-actions-test.sh\n\n      - name: Upload failed-test artifacts\n        uses: actions/upload-artifact@v4\n        if: failure() && steps.test.outcome == 'failure'\n        with:\n          name: failed-tests-${{ inputs.architecture }}\n          path: failed-tests/*\n          compression-level: 0\n"
  },
  {
    "path": ".gitignore",
    "content": "*~\n.cache\n.cproject\nCMakeCache.txt\nCMakeFiles/\ncmake_install.cmake\nCPackConfig.cmake\nCPackSourceConfig.cmake\n_CPack_Packages/\nCTestTestfile.cmake\ncompile_commands.json\nDebug\nbin_dir\nsource_dir\ndist/\ninstall_manifest.txt\nMakefile\nProfile\nobj/\n.project\n.vscode/\n*.log\n*.orig\n*.rej\n*.pyc\n*.record\n*.replay\n.settings/\nTesting/\n.idea/\n.*.swp\n*generated\nbuild/\nbin/\nlib/\nshare/\nlibbrotli*\nextra_version_string.h\ngit_revision.h\nthird-party/zen-pmu-workaround/.*\nthird-party/zen-pmu-workaround/*.ko\nthird-party/zen-pmu-workaround/*.o\nthird-party/zen-pmu-workaround/*.mod\nthird-party/zen-pmu-workaround/*.mod.c\nthird-party/zen-pmu-workaround/Module.symvers\nthird-party/zen-pmu-workaround/modules.order\nrr_trace.capnp.*\ntest32.c\nsrc/preload/rr_page.ld\n"
  },
  {
    "path": "CMakeLists.txt",
    "content": "# *-* Mode: cmake; *-*\n\ncmake_minimum_required(VERSION 3.12)\nproject(rr C CXX ASM)\n\n# Require c++17 as minimum\nif(NOT DEFINED CMAKE_CXX_STANDARD)\n  set(CMAKE_CXX_STANDARD 17)\nendif()\n\n# Configure so that we use -std=c++17 (as previously done) not -std=gnu++17\nif(NOT DEFINED CMAKE_CXX_EXTENSIONS)\n  set(CMAKE_CXX_EXTENSIONS OFF)\nendif()\n\nset(CMAKE_CXX_STANDARD_REQUIRED ON)\n\n# Because `CMAKE_CXX_STANDARD_REQUIRED ON` does not enforce this for us.\nif(CMAKE_CXX_STANDARD LESS 17)\n  message(FATAL_ERROR \"C++ standard too low: CMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD}. Minimum required is C++17.\")\nendif()\n\n# \"Do not add flags to export symbols from executables without the ENABLE_EXPORTS target property.\"\n# This avoids linking executables with -rdynamic. -rdynamic has been observed\n# to cause rr_exec_stub to be linked with the dynamic linker with some\n# version(s) of clang (but linked to an incorrect file name, causing\n# exec of rr_exec_stub to fail).\nif(POLICY CMP0065)\n  cmake_policy(SET CMP0065 NEW)\nendif()\n\n# We should switch to using FindPython3, but that requires CMake 3.12.\n# We'll switch later.\nif(POLICY CMP0148)\n  cmake_policy(SET CMP0148 OLD)\nendif()\n\n# On single configuration generators, make Debug the default configuration\nif(NOT CMAKE_CONFIGURATION_TYPES)\n  if(NOT CMAKE_BUILD_TYPE)\n    set(CMAKE_BUILD_TYPE \"Debug\" CACHE STRING \"Whether to build in `Debug` or `Release` mode.\" FORCE)\n  endif()\nendif()\n\noption(INSTALL_TESTSUITE \"Install the testsuite\")\noption(force32bit \"Force a 32-bit rr build, rather than both 64 and 32-bit. rr will only be able to record and replay 32-bit processes.\")\noption(disable32bit \"On a 64-bit platform, avoid requiring a 32-bit cross-compilation toolchain by not building 32-bit components. rr will be able to record 32-bit processes but not replay them.\")\noption(staticlibs \"Force usage of static linkage for non-standard libraries like capnproto\")\noption(bpf \"Enable bpf acceleration\")\noption(asan \"Build with address sanitizer enabled.\")\noption(intel_pt_decoding \"Build with Intel PT decoding enabled.\")\noption(strip \"Strip debug info from rr binary\")\n\nenable_testing()\nset(BUILD_SHARED_LIBS ON)\n\nset(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)\nset(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/lib/rr)\nset(CMAKE_EXPORT_COMPILE_COMMANDS ON)\n\nset(BUILD_TESTS ON CACHE BOOL \"Build tests\")\nset(WILL_RUN_TESTS ${BUILD_TESTS} CACHE BOOL \"Run tests\")\n\n# CAREFUL!  \"-\" is an invalid character in RPM package names, while\n# debian is happy with it.  However, \"_\" is illegal in debs, while RPM\n# is cool with it.  Sigh.\nset(rr_VERSION_MAJOR 5)\nset(rr_VERSION_MINOR 9)\nset(rr_VERSION_PATCH 0)\n\nif(ANDROID)\n  find_package(CapnProto REQUIRED)\nendif()\n\nadd_definitions(-DRR_VERSION=\"${rr_VERSION_MAJOR}.${rr_VERSION_MINOR}.${rr_VERSION_PATCH}\")\n\nexecute_process(\n  COMMAND git rev-parse HEAD\n  WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}\n  OUTPUT_VARIABLE GIT_REVISION\n  OUTPUT_STRIP_TRAILING_WHITESPACE\n)\nconfigure_file(\n  \"${PROJECT_SOURCE_DIR}/src/git_revision.h.in\"\n  \"${PROJECT_BINARY_DIR}/git_revision.h\"\n)\nconfigure_file(\n  \"${PROJECT_SOURCE_DIR}/src/extra_version_string.h.in\"\n  \"${PROJECT_BINARY_DIR}/extra_version_string.h\"\n)\n\nset(FLAGS_COMMON \"-D_FILE_OFFSET_BITS=64 -pthread\")\nset(supports32bit true)\nset(x86ish false)\nset(has_syscallbuf false)\nif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\")\n  set(has_syscallbuf true)\n  set(supports32bit false)\n  set(FLAGS_COMMON \"${FLAGS_COMMON} -march=armv8.3-a -moutline-atomics\")\n  set(PRELOAD_LIBRARY_PAGE_SIZE 65536)\n  set(VDSO_NAME \"LINUX_2.6.39\")\n  set(VDSO_SYMBOLS \"__kernel_clock_getres; __kernel_rt_sigreturn; __kernel_gettimeofday; __kernel_clock_gettime;\")\nelseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES i386|i686|x86|x86_64)\n  set(x86ish true)\n  set(has_syscallbuf true)\n  set(FLAGS_COMMON \"${FLAGS_COMMON} -msse2 -D__MMX__ -D__SSE__ -D__SSE2__\")\n  set(PRELOAD_LIBRARY_PAGE_SIZE 4096)\n  set(VDSO_NAME \"LINUX_2.6\")\n  set(VDSO_SYMBOLS \"gettimeofday; clock_gettime; __vdso_gettimeofday; __vdso_clock_getres; __vdso_time; __vdso_clock_gettime; __vdso_getcpu;\")\nelse()\n  message(FATAL_ERROR \"The architecture \" ${CMAKE_SYSTEM_PROCESSOR} \" is not yet supported\")\nendif()\nconfigure_file(src/preload/rr_page.ld.in src/preload/rr_page.ld @ONLY)\n\ninclude(CheckCCompilerFlag)\nCHECK_C_COMPILER_FLAG(\"-fmacro-prefix-map=foo=bar\" SUPPORTS_MACRO_PREFIX_MAP)\nif (SUPPORTS_MACRO_PREFIX_MAP)\n  set(FLAGS_COMMON \"${FLAGS_COMMON} -fmacro-prefix-map='${PROJECT_SOURCE_DIR}/'=\")\nendif()\n\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${FLAGS_COMMON} -Wstrict-prototypes -std=gnu11\")\n# Define __STDC_LIMIT_MACROS so |#include <stdint.h>| works as expected.\n# Define __STDC_FORMAT_MACROS so |#include <inttypes.h>| works as expected.\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${FLAGS_COMMON} -D__STDC_LIMIT_MACROS -D__STDC_FORMAT_MACROS\")\n\n# We support three build types:\n# DEBUG: suitable for debugging rr\n# RELEASE: suitable for using rr in production (but keeps rr debuginfo)\n# OTHER: suitable for using rr in production, but honouring distro/user opt/debug settings\n# (which we assume are suitable for production use)\n\n# Base settings for debug and release/unspecified builds.\n# Use -Werror for debug builds because we assume a developer is building, not a user.\nset(RR_FLAGS_DEBUG \"-Wall -Wextra -DDEBUG -UNDEBUG\")\nset(RR_FLAGS_RELEASE \"-Wall -Wextra -UDEBUG -DNDEBUG\")\n\n# The following settings are the defaults for the OTHER build type.\n# Flags used to build the preload library. MUST have debuginfo enabled. SHOULD be optimized.\n# LTO breaks us by moving code around.\nset(PRELOAD_COMPILE_FLAGS \"${RR_FLAGS_RELEASE} -fno-stack-protector -g3 -U_FORTIFY_SOURCE -fno-lto\")\nset(PRELOAD_LINK_FLAGS \"-nostartfiles -fno-lto\")\n# Flags used to build Brotli. SHOULD be optimized. MUST NOT error on warnings.\nset(BROTLI_COMPILE_FLAGS ${RR_FLAGS_RELEASE})\n# Flags used to build tests. MUST have -DDEBUG and debuginfo enabled, MUST NOT be optimized.\nset(RR_TEST_FLAGS \"${RR_FLAGS_DEBUG} -g3 -O0\")\n# Flags used to build other files. Entirely build-type-dependent.\nset(RR_FLAGS ${RR_FLAGS_RELEASE})\n\n# Now override for build type.\nstring(TOLOWER ${CMAKE_BUILD_TYPE} LOWERCASE_CMAKE_BUILD_TYPE)\nif(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL \"debug\")\n  set(PRELOAD_COMPILE_FLAGS \"${PRELOAD_COMPILE_FLAGS} -O2 -Werror\")\n  set(BROTLI_COMPILE_FLAGS \"${RR_FLAGS_RELEASE} -O2\")\n  set(RR_TEST_FLAGS \"${RR_TEST_FLAGS} -Werror\")\n  set(RR_FLAGS \"${RR_FLAGS_DEBUG} -g3 -Werror\")\nelseif(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL \"release\")\n  # CMake itself will add optimization flags\n  set(RR_FLAGS \"${RR_FLAGS_RELEASE} -g3 -flto\")\nendif()\n\nset(LINKER_FLAGS \"\")\nif(CMAKE_C_COMPILER_ID STREQUAL \"GNU\")\n  # Gcc generates bogus R_386_GOTOFF relocations in .debug_info which\n  # lld 9 rejects\n  set(LINKER_FLAGS \"-fuse-ld=bfd\")\nendif()\n\nif(CMAKE_C_COMPILER_ID STREQUAL \"Clang\")\n  set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} -Wno-unused-command-line-argument\")\nendif()\nif(CMAKE_CXX_COMPILER_ID STREQUAL \"Clang\")\n  set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} -Wno-unused-command-line-argument\")\nendif()\n# -fno-integrated-as tells Clang to use whatever \"as\" happens to be. For an\n# Android build that will end up being whatever /usr/bin/as is, and whatever it\n# is, it's the wrong assembler for Android, because Android only supports the\n# Clang assembler.\nif (CMAKE_ASM_COMPILER_ID STREQUAL \"Clang\" AND NOT ANDROID)\n  set(CMAKE_ASM_FLAGS \"${CMAKE_ASM_FLAGS} -fno-integrated-as\")\nendif()\n\nif(force32bit)\n  set(rr_32BIT true)\n  set(rr_64BIT false)\n  set(rr_MBITNESS_OPTION -m32)\nelse()\n  if(CMAKE_SIZEOF_VOID_P EQUAL 8)\n    if(disable32bit OR NOT supports32bit)\n      set(rr_32BIT false)\n    else()\n      set(rr_32BIT true)\n    endif()\n    set(rr_64BIT true)\n  else()\n    set(rr_32BIT true)\n    set(rr_64BIT false)\n  endif()\n  set(rr_MBITNESS_OPTION)\nendif()\n\n# Check that compiling 32-bit code on a 64-bit target works, if required.\nif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL \"x86_64\" AND rr_32BIT)\n  # try_compile won't accept LINK_FLAGS, so do this manually.\n  file(WRITE \"${CMAKE_BINARY_DIR}/test32.c\" \"int main() { return 0; }\")\n  execute_process(COMMAND ${CMAKE_C_COMPILER} -o ${CMAKE_BINARY_DIR}/test32 ${CMAKE_BINARY_DIR}/test32.c -m32\n                  RESULT_VARIABLE COMPILER_32BIT_RESULT)\n  if(NOT (COMPILER_32BIT_RESULT EQUAL 0))\n    message(FATAL_ERROR \"Your toolchain doesn't support 32-bit cross-compilation. Install the required packages or pass -Ddisable32bit=ON to cmake.\")\n  endif()\nendif()\n\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${rr_MBITNESS_OPTION}\")\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${rr_MBITNESS_OPTION}\")\nset(CMAKE_ASM_FLAGS \"${CMAKE_ASM_FLAGS} ${rr_MBITNESS_OPTION}\")\n\n# If SKIP_PKGCONFIG is set then ${PKG}_CFLAGS and ${PKG}_LDFLAGS must be\n# provided as well.\nif(NOT SKIP_PKGCONFIG)\n  find_package(PkgConfig REQUIRED)\n\n  # If we're cross-compiling a 32-bit rr build on a 64-bit host we need\n  # to ensure we're looking for the right libraries.\n  # This has been tested on Ubuntu and Fedora.\n  if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL \"x86_64\" AND NOT rr_64BIT)\n    set(LIBDIR32_CANDIDATES\n      /usr/lib/i386-linux-gnu/pkgconfig/\n      /usr/lib/pkgconfig/\n    )\n    foreach(libdir ${LIBDIR32_CANDIDATES})\n      if(IS_DIRECTORY ${libdir})\n        set(ENV{PKG_CONFIG_LIBDIR} ${libdir})\n        break()\n      endif()\n    endforeach(libdir)\n    if(NOT DEFINED ENV{PKG_CONFIG_LIBDIR})\n      message(FATAL_ERROR \"Couldn't find a suitable 32-bit pkgconfig lib dir. You probably need to install a 32-bit pkgconfig package (pkgconfig.i686 for Fedora or pkg-config:i386 for Ubuntu\")\n    endif()\n  endif()\nendif()\n\nfind_program(CAPNP capnp)\nif(${CAPNP} STREQUAL \"CAPNP-NOTFOUND\")\n  message(FATAL_ERROR \"Can't find 'capnp' command; install Capnproto packages? https://github.com/rr-debugger/rr/wiki/Building-And-Installing#tldr\")\nendif()\n\nset(REQUIRED_LIBS\n  capnp\n# zlib is required to handle ELF compression\n  zlib\n)\n\nif(NOT ANDROID)\n  set(REQUIRED_LIBS\n    ${REQUIRED_LIBS}\n    # zstd is required to handle ELF compression, but isn't available on Android.\n    libzstd\n  )\n  set(ZSTD 1)\n  add_definitions(-DZSTD=1)\nendif()\n\nif(bpf)\n  add_definitions(-DBPF=1)\n  set(REQUIRED_LIBS\n    ${REQUIRED_LIBS}\n    libbpf\n  )\nendif(bpf)\n\nforeach(required_lib ${REQUIRED_LIBS})\n  string(TOUPPER ${required_lib} PKG)\n  if(NOT SKIP_PKGCONFIG)\n    pkg_check_modules(${PKG} REQUIRED ${required_lib})\n  endif()\n  if(staticlibs)\n    string(REPLACE \";\" \" \" ${PKG}_STATIC_CFLAGS \"${${PKG}_STATIC_CFLAGS}\")\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${${PKG}_STATIC_CFLAGS}\")\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${${PKG}_STATIC_CFLAGS}\")\n  else()\n    string(REPLACE \";\" \" \" ${PKG}_CFLAGS \"${${PKG}_CFLAGS}\")\n    set(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${${PKG}_CFLAGS}\")\n    set(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${${PKG}_CFLAGS}\")\n  endif()\nendforeach(required_lib)\n\n# ==== brotli ====\nset(BROTLI_FILES\n  third-party/brotli/common/constants.c\n  third-party/brotli/common/context.c\n  third-party/brotli/common/dictionary.c\n  third-party/brotli/common/platform.c\n  third-party/brotli/common/shared_dictionary_internal.h\n  third-party/brotli/common/shared_dictionary.c\n  third-party/brotli/common/transform.c\n  third-party/brotli/dec/bit_reader.c\n  third-party/brotli/dec/decode.c\n  third-party/brotli/dec/huffman.c\n  third-party/brotli/dec/state.c\n  third-party/brotli/enc/backward_references.c\n  third-party/brotli/enc/backward_references.h\n  third-party/brotli/enc/backward_references_hq.c\n  third-party/brotli/enc/backward_references_hq.h\n  third-party/brotli/enc/backward_references_inc.h\n  third-party/brotli/enc/bit_cost.c\n  third-party/brotli/enc/bit_cost.h\n  third-party/brotli/enc/bit_cost_inc.h\n  third-party/brotli/enc/block_encoder_inc.h\n  third-party/brotli/enc/block_splitter.c\n  third-party/brotli/enc/block_splitter.h\n  third-party/brotli/enc/block_splitter_inc.h\n  third-party/brotli/enc/brotli_bit_stream.c\n  third-party/brotli/enc/brotli_bit_stream.h\n  third-party/brotli/enc/command.c\n  third-party/brotli/enc/cluster.c\n  third-party/brotli/enc/cluster.h\n  third-party/brotli/enc/cluster_inc.h\n  third-party/brotli/enc/command.h\n  third-party/brotli/enc/compress_fragment.c\n  third-party/brotli/enc/compress_fragment.h\n  third-party/brotli/enc/compound_dictionary.c\n  third-party/brotli/enc/compound_dictionary.h\n  third-party/brotli/enc/compress_fragment_two_pass.c\n  third-party/brotli/enc/compress_fragment_two_pass.h\n  third-party/brotli/enc/dictionary_hash.c\n  third-party/brotli/enc/dictionary_hash.h\n  third-party/brotli/enc/encode.c\n  third-party/brotli/enc/encoder_dict.c\n  third-party/brotli/enc/entropy_encode.c\n  third-party/brotli/enc/entropy_encode.h\n  third-party/brotli/enc/entropy_encode_static.h\n  third-party/brotli/enc/fast_log.c\n  third-party/brotli/enc/fast_log.h\n  third-party/brotli/enc/find_match_length.h\n  third-party/brotli/enc/hash_forgetful_chain_inc.h\n  third-party/brotli/enc/hash.h\n  third-party/brotli/enc/hash_longest_match64_inc.h\n  third-party/brotli/enc/hash_longest_match_inc.h\n  third-party/brotli/enc/hash_longest_match_quickly_inc.h\n  third-party/brotli/enc/hash_to_binary_tree_inc.h\n  third-party/brotli/enc/histogram.c\n  third-party/brotli/enc/histogram.h\n  third-party/brotli/enc/histogram_inc.h\n  third-party/brotli/enc/literal_cost.c\n  third-party/brotli/enc/literal_cost.h\n  third-party/brotli/enc/memory.c\n  third-party/brotli/enc/memory.h\n  third-party/brotli/enc/metablock.c\n  third-party/brotli/enc/metablock.h\n  third-party/brotli/enc/metablock_inc.h\n  third-party/brotli/enc/prefix.h\n  third-party/brotli/enc/quality.h\n  third-party/brotli/enc/ringbuffer.h\n  third-party/brotli/enc/state.h\n  third-party/brotli/enc/static_dict.c\n  third-party/brotli/enc/static_dict.h\n  third-party/brotli/enc/static_dict_lut.h\n  third-party/brotli/enc/utf8_util.c\n  third-party/brotli/enc/utf8_util.h\n  third-party/brotli/enc/write_bits.h\n  third-party/brotli/include/brotli/decode.h\n  third-party/brotli/include/brotli/encode.h\n  third-party/brotli/include/brotli/port.h\n  third-party/brotli/include/brotli/shared_dictionary.h\n)\nadd_library(brotli STATIC ${BROTLI_FILES})\nset_source_files_properties(${BROTLI_FILES}\n                            PROPERTIES COMPILE_FLAGS ${BROTLI_COMPILE_FLAGS})\n# ==== brotli ====\n\nfind_library(LIBRT rt)\n\nset_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS OFF)\nset_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS ON)\nfind_library(LIBRT_32 rt PATHS \"/usr/lib32\" \"/usr/lib\" NO_DEFAULT_PATH)\nset_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS ON)\nset_property(GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS OFF)\n\nfind_path(SECCOMP NAMES \"linux/seccomp.h\")\nif(NOT SECCOMP)\n  message(FATAL_ERROR \"Couldn't find linux/seccomp.h. You may need to upgrade your kernel.\")\nendif()\n\nfind_path(PROC_SERVICE_H NAMES \"proc_service.h\")\nif(PROC_SERVICE_H)\n  add_definitions(-DPROC_SERVICE_H=1)\nelse()\n  message(AUTHOR_WARNING \"proc_service.h not present. Support for libthread_db.so is disabled.\")\nendif()\n\n# Test only includes\nfind_path(MQUEUE_H NAMES \"mqueue.h\")\nif(MQUEUE_H)\n  add_definitions(-DMQUEUE_H=1)\nendif()\n\nfind_path(FANOTIFY_H NAMES \"sys/fanotify.h\")\nif(FANOTIFY_H)\n  add_definitions(-DFANOTIFY_H=1)\nendif()\n\ninclude(CheckSymbolExists)\nlist(APPEND CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)\ncheck_symbol_exists(LAV_CURRENT \"link.h\" RTLD_AUDIT)\nif(NOT RTLD_AUDIT)\n  message(AUTHOR_WARNING \"Couldn't find rtld-audit support. librraudit skipped.\")\nendif()\nlist(REMOVE_ITEM CMAKE_REQUIRED_DEFINITIONS -D_GNU_SOURCE)\n\ncheck_symbol_exists(backtrace \"execinfo.h\" EXECINFO_BACKTRACE)\nif(EXECINFO_BACKTRACE)\n  add_definitions(-DEXECINFO_BACKTRACE)\nelse()\n  message(AUTHOR_WARNING \"backtrace(3) not present in execinfo.h. Automatic backtraces for failures in rr are disabled.\")\nendif()\n\ninclude(CheckTypeSize)\nset(SAVE_CMAKE_EXTRA_INCLUDE_FILES \"${CMAKE_EXTRA_INCLUDE_FILES}\")\nlist(APPEND CMAKE_EXTRA_INCLUDE_FILES \"termios.h\")\ncheck_type_size(\"struct termios2\" SIZEOF_TERMIOS2)\nif(HAVE_SIZEOF_TERMIOS2)\n  add_definitions(-DHAVE_TERMIOS2)\nendif()\nset(CMAKE_EXTRA_INCLUDE_FILES \"${SAVE_CMAKE_EXTRA_INCLUDE_FILES}\")\n\n# Test only symbols\ncheck_symbol_exists(pthread_mutexattr_setrobust \"pthread.h\" HAVE_ROBUST_MUTEX)\n\nset(Python_ADDITIONAL_VERSIONS 3 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)\nfind_package(PythonInterp 3 REQUIRED)\n\nexecute_process(COMMAND \"${PYTHON_EXECUTABLE}\" \"-c\" \"# nothing\"\n                RESULT_VARIABLE python_status)\nif(python_status)\n  message(FATAL_ERROR \"Couldn't run python interpreter ${PYTHON_EXECUTABLE}.\")\nendif()\n\n# Check for required Python modules\nif(WILL_RUN_TESTS)\n  if(NOT BUILD_TESTS)\n    message(FATAL_ERROR \"Running tests requires building them\")\n  endif()\n\n  set(REQUIRED_PYTHON_MODULES\n    pexpect\n  )\nelse()\n  set(REQUIRED_PYTHON_MODULES)\nendif()\n\nforeach(py_module ${REQUIRED_PYTHON_MODULES})\n  execute_process(COMMAND \"${PYTHON_EXECUTABLE}\" \"-c\"\n                  \"import ${py_module}\"\n                  RESULT_VARIABLE module_status)\n  if(module_status)\n    message(FATAL_ERROR \"Couldn't find required Python module ${py_module}.\")\n  endif()\nendforeach(py_module)\n\nif(WILL_RUN_TESTS)\n  # Check for gdb and lldb\n  execute_process(COMMAND \"gdb\" \"--version\" RESULT_VARIABLE module_status OUTPUT_QUIET)\n  if(module_status)\n    message(FATAL_ERROR \"Couldn't find gdb.\")\n  endif()\n  execute_process(COMMAND \"lldb\" \"--version\" RESULT_VARIABLE module_status OUTPUT_QUIET)\n  if(module_status)\n    message(FATAL_ERROR \"Couldn't find lldb.\")\n  endif()\nendif()\n\ninclude_directories(\"${PROJECT_SOURCE_DIR}/include\")\ninclude_directories(\"${PROJECT_SOURCE_DIR}/third-party/proc-service\")\ninclude_directories(\"${PROJECT_SOURCE_DIR}/third-party/brotli/include\")\n# We need to know where our generated files are.\ninclude_directories(\"${CMAKE_CURRENT_BINARY_DIR}\")\n\nset(RR_PAGE_FILES\n  rr_page.S\n)\nset(RR_PAGE_SOURCE_FILES\n  ${RR_PAGE_FILES}\n  rr_page_instructions.S\n  rr_vdso.S\n)\nadd_library(rrpage)\nforeach(file ${RR_PAGE_FILES})\n  target_sources(rrpage PUBLIC \"${PROJECT_SOURCE_DIR}/src/preload/${file}\")\n  set_source_files_properties(\"${PROJECT_SOURCE_DIR}/src/preload/${file}\"\n                              PROPERTIES COMPILE_FLAGS ${PRELOAD_COMPILE_FLAGS})\nendforeach(file)\n\n# Since librrpage replaces the kernel vDSO for processes exec'd by rr,\n# we want it to have the same SONAME as the real vDSO to trick things\n# like AddressSanitizer into recognising it as the vDSO.\nset_target_properties(rrpage PROPERTIES NO_SONAME ON)\nset_target_properties(rrpage PROPERTIES LINK_FLAGS \"-Wl,-T -Wl,'${PROJECT_BINARY_DIR}/src/preload/rr_page.ld' -Wl,--hash-style=both -nostdlib ${PRELOAD_LINK_FLAGS} -Wl,-z,max-page-size=${PRELOAD_LIBRARY_PAGE_SIZE} -Wl,-soname,linux-vdso.so.1 ${LINKER_FLAGS}\")\nset_target_properties(rrpage PROPERTIES LINK_DEPENDS \"${PROJECT_BINARY_DIR}/src/preload/rr_page.ld\")\n# CMake seems to have trouble generating the link line without this\nset_target_properties(rrpage PROPERTIES LINKER_LANGUAGE C)\n\nadd_custom_command(TARGET rrpage POST_BUILD\n                   COMMAND \"${PROJECT_SOURCE_DIR}/src/preload/tweak_librrpage.py\" $<TARGET_FILE:rrpage> ${PRELOAD_LIBRARY_PAGE_SIZE})\n\n# Order matters here! syscall_hook.S must be immediately before syscallbuf.c,\n# raw_syscall.S must be before overrides.c, which must be last.\nif(has_syscallbuf)\n  set(PRELOAD_FILES\n    syscall_hook.S\n    syscallbuf.c\n    raw_syscall.S\n    overrides.c\n    )\nelse()\n  set(PRELOAD_FILES\n    overrides.c\n    )\nendif()\nset(PRELOAD_SOURCE_FILES\n  ${PRELOAD_FILES}\n  preload_interface.h\n  rrcalls.h\n  syscallbuf.h\n)\nadd_library(rrpreload)\nforeach(file ${PRELOAD_FILES})\n  target_sources(rrpreload PUBLIC \"${PROJECT_SOURCE_DIR}/src/preload/${file}\")\n  set_source_files_properties(\"${PROJECT_SOURCE_DIR}/src/preload/${file}\"\n                              PROPERTIES COMPILE_FLAGS ${PRELOAD_COMPILE_FLAGS})\nendforeach(file)\nset_target_properties(rrpreload PROPERTIES LINK_FLAGS \"${PRELOAD_LINK_FLAGS} ${LINKER_FLAGS}\")\nset_target_properties(rrpreload PROPERTIES INSTALL_RPATH \"\\$ORIGIN\")\n\nif(RTLD_AUDIT)\n  set(AUDIT_FILES\n    rtld-audit.c\n    stap-note-iter.c\n    ../preload/raw_syscall.S\n  )\n  set(AUDIT_SOURCE_FILES\n    ${AUDIT_FILES}\n    rtld-audit.h\n    stap-note-iter.h\n    ../preload/preload_interface.h\n    ../preload/rrcalls.h\n  )\n  add_library(rraudit)\n  foreach(file ${AUDIT_FILES})\n    target_sources(rraudit PUBLIC \"${PROJECT_SOURCE_DIR}/src/audit/${file}\")\n    set_source_files_properties(\"${PROJECT_SOURCE_DIR}/src/audit/${file}\"\n                                PROPERTIES COMPILE_FLAGS ${PRELOAD_COMPILE_FLAGS})\n  endforeach(file)\n  set_target_properties(rraudit PROPERTIES LINK_FLAGS \"${PRELOAD_LINK_FLAGS} -ldl ${LINKER_FLAGS}\")\nendif()\n\n# Ensure that CMake knows about our generated files.\n#\n# Alphabetical, please.\nset(GENERATED_FILES\n  AssemblyTemplates.generated\n  CheckSyscallNumbers.generated\n  SyscallEnumsX64.generated\n  SyscallEnumsX86.generated\n  SyscallEnumsGeneric.generated\n  SyscallEnumsForTestsX64.generated\n  SyscallEnumsForTestsX86.generated\n  SyscallEnumsForTestsGeneric.generated\n  SyscallHelperFunctions.generated\n  SyscallnameArch.generated\n  SyscallRecordCase.generated\n)\n\nforeach(generated_file ${GENERATED_FILES})\n  set_source_files_properties(${generated_file}\n                              PROPERTIES GENERATED true HEADER_FILE_ONLY true)\n  add_custom_command(OUTPUT \"${CMAKE_CURRENT_BINARY_DIR}/${generated_file}\"\n                     COMMAND \"${CMAKE_CURRENT_SOURCE_DIR}/src/generate_syscalls.py\"\n                             \"${CMAKE_CURRENT_BINARY_DIR}/${generated_file}\"\n                     DEPENDS \"${CMAKE_CURRENT_SOURCE_DIR}/src/generate_syscalls.py\"\n                             \"${CMAKE_CURRENT_SOURCE_DIR}/src/syscalls.py\"\n                             \"${CMAKE_CURRENT_SOURCE_DIR}/src/assembly_templates.py\")\nendforeach(generated_file)\n\nadd_custom_target(Generated DEPENDS ${GENERATED_FILES})\n\nadd_custom_command(OUTPUT \"${CMAKE_CURRENT_BINARY_DIR}/rr_trace.capnp.c++\"\n                          \"${CMAKE_CURRENT_BINARY_DIR}/rr_trace.capnp.h\"\n                   COMMAND capnp compile\n                           \"--src-prefix=${CMAKE_CURRENT_SOURCE_DIR}/src\"\n                           \"-oc++:${CMAKE_CURRENT_BINARY_DIR}\"\n                           \"${CMAKE_CURRENT_SOURCE_DIR}/src/rr_trace.capnp\"\n                   DEPENDS \"${CMAKE_CURRENT_SOURCE_DIR}/src/rr_trace.capnp\")\nset_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/rr_trace.capnp.c++\"\n                            PROPERTIES GENERATED true)\nset_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/rr_trace.capnp.h\"\n                            PROPERTIES GENERATED true HEADER_FILE_ONLY true)\n\nif (${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\")\n  set(BLAKE_ARCH_DIR third-party/blake2/neon)\nelse()\n  set(BLAKE_ARCH_DIR third-party/blake2/sse)\nendif()\n\nset(RR_SOURCES\n  src/AddressSpace.cc\n  src/AutoRemoteSyscalls.cc\n  src/BuildidCommand.cc\n  src/Command.cc\n  src/CompressedReader.cc\n  src/CompressedWriter.cc\n  src/ContextSwitchEvent.cc\n  src/CPUFeaturesCommand.cc\n  src/CPUIDBugDetector.cc\n  src/CPUs.cc\n  src/DiversionSession.cc\n  src/DumpCommand.cc\n  src/Dwarf.cc\n  src/ElfReader.cc\n  src/EmuFs.cc\n  src/Event.cc\n  src/ExtraRegisters.cc\n  src/fast_forward.cc\n  src/FdTable.cc\n  src/FileMonitor.cc\n  src/FileNameCommand.cc\n  src/Flags.cc\n  src/ftrace.cc\n  src/DebuggerExtensionCommand.cc\n  src/DebuggerExtensionCommandHandler.cc\n  src/GdbServerConnection.cc\n  src/GdbServerExpression.cc\n  src/GdbInitCommand.cc\n  src/GdbServer.cc\n  src/HasTaskSet.cc\n  src/HelpCommand.cc\n  src/ExportImportCheckpoints.cc\n  src/kernel_abi.cc\n  src/kernel_metadata.cc\n  src/launch_debugger.cc\n  src/log.cc\n  src/LldbInitCommand.cc\n  src/LsCommand.cc\n  src/main.cc\n  src/MagicSaveDataMonitor.cc\n  src/MmappedFileMonitor.cc\n  src/MonitoredSharedMemory.cc\n  src/Monkeypatcher.cc\n  src/MvCommand.cc\n  src/PackCommand.cc\n  src/PerfCounters.cc\n  src/PerfCounterBuffers.cc\n  src/PidFdMonitor.cc\n  src/processor_trace_check.cc\n  src/ProcFdDirMonitor.cc\n  src/ProcMemMonitor.cc\n  src/ProcStatMonitor.cc\n  src/PsCommand.cc\n  src/RecordCommand.cc\n  src/RecordSession.cc\n  src/record_signal.cc\n  src/record_syscall.cc\n  src/RecordTask.cc\n  src/Registers.cc\n  src/remote_code_ptr.cc\n  src/ReplayCommand.cc\n  src/ReplaySession.cc\n  src/replay_syscall.cc\n  src/ReplayTask.cc\n  src/ReplayTimeline.cc\n  src/RerunCommand.cc\n  src/ReturnAddressList.cc\n  src/RmCommand.cc\n  src/Scheduler.cc\n  src/SeccompFilterRewriter.cc\n  src/Session.cc\n  src/SourcesCommand.cc\n  src/StdioMonitor.cc\n  src/SysCpuMonitor.cc\n  src/TargetDescription.cc\n  src/Task.cc\n  src/ThreadGroup.cc\n  src/TraceeAttentionSet.cc\n  src/TraceField.cc\n  src/TraceFrame.cc\n  src/TraceInfoCommand.cc\n  src/TraceStream.cc\n  src/VirtualPerfCounterMonitor.cc\n  src/util.cc\n  src/WaitManager.cc\n  src/WaitStatus.cc\n  ${CMAKE_CURRENT_BINARY_DIR}/rr_trace.capnp.c++\n  ${BLAKE_ARCH_DIR}/blake2b.c\n)\n\nif(PROC_SERVICE_H)\n  set(RR_SOURCES ${RR_SOURCES} src/ThreadDb.cc)\nendif()\n\nif (x86ish)\n  set(RR_SOURCES ${RR_SOURCES} src/test/x86/cpuid_loop.S)\nendif()\n\nif (asan)\n  set(ASAN_FLAGS \"-fsanitize=address -fno-omit-frame-pointer\")\n      # Without no-omit-frame-pointer incomplete backtraces get stored.\n  set(RR_FLAGS \"${ASAN_FLAGS} ${RR_FLAGS}\")\nendif()\n\nset_source_files_properties(${RR_SOURCES}\n                            PROPERTIES COMPILE_FLAGS ${RR_FLAGS})\n\nfunction(post_build_executable target)\n# grsecurity needs these. But if we add them ourselves, they may conflict\n# with other flags added in other ways, and they all have to match :-(. So\n# don't do this until a better solution presents itself\n#  add_custom_command(TARGET ${target}\n#                     POST_BUILD\n#                     COMMAND setfattr ARGS -n user.pax.flags -v m $<TARGET_FILE:${target}>)\nendfunction(post_build_executable)\n\nif(UNIX)\n  include(GNUInstallDirs)\nelse()\n  set(CMAKE_INSTALL_LIBDIR \"lib\")\n  set(CMAKE_INSTALL_BINDIR \"bin\")\n  set(CMAKE_INSTALL_DATADIR \"share\")\n  set(CMAKE_INSTALL_DOCDIR \"${CMAKE_INSTALL_DATADIR}/doc\")\n  set(CMAKE_INSTALL_INCLUDEDIR \"include\")\nendif()\n\nif (intel_pt_decoding)\n  set(RR_SOURCES ${RR_SOURCES} src/ProcessorTraceDecoder.cc)\n  add_definitions(-DINTEL_PT_DECODING=1)\nendif()\n\nadd_executable(rr ${RR_SOURCES})\ntarget_compile_definitions(rr PRIVATE\n  \"FULL_LIBDIR=\\\"${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}\\\"\")\nset_target_properties(rr PROPERTIES ENABLE_EXPORTS true)\npost_build_executable(rr)\nset(RR_BIN rr)\nadd_dependencies(rr Generated)\n\nif(bpf)\n  add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/share/rr/async_event_filter.o\n    DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/src/bpf/async_event_filter.c\n    COMMAND clang -g -target bpf -Wall -O2 -c ${CMAKE_CURRENT_SOURCE_DIR}/src/bpf/async_event_filter.c -o ${CMAKE_CURRENT_BINARY_DIR}/share/rr/async_event_filter.o)\n\n  install(FILES ${CMAKE_CURRENT_BINARY_DIR}/share/rr/async_event_filter.o\n    DESTINATION ${CMAKE_INSTALL_DATADIR}/rr)\n\n  add_custom_target(BPF DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/share/rr/async_event_filter.o)\n\n  add_dependencies(rr BPF)\nendif()\n\nset(RR_MAIN_LINKER_FLAGS ${LINKER_FLAGS})\nif(strip)\n  set(RR_MAIN_LINKER_FLAGS \"-s ${RR_MAIN_LINKER_FLAGS}\")\nendif()\nif (asan)\n  set(RR_MAIN_LINKER_FLAGS \" ${ASAN_FLAGS} ${RR_MAIN_LINKER_FLAGS}\")\nendif()\n\n# Add -flto option to linking step if release\nif(LOWERCASE_CMAKE_BUILD_TYPE STREQUAL \"release\")\n  CHECK_C_COMPILER_FLAG(\"-flto=auto\" SUPPORTS_LTO_AUTO)\n  if(SUPPORTS_LTO_AUTO)\n    set(RR_MAIN_LINKER_FLAGS \"${RR_MAIN_LINKER_FLAGS} -flto=auto\")\n  else()\n    set(RR_MAIN_LINKER_FLAGS \"${RR_MAIN_LINKER_FLAGS} -flto\")\n  endif()\nendif()\n\nif(intel_pt_decoding)\n  find_library(LIBIPT ipt)\n  target_link_libraries(rr ${LIBIPT})\nendif()\n\nif(LIBRT)\n  target_link_libraries(rr ${LIBRT})\nendif()\n\ntarget_link_libraries(rr\n  ${CMAKE_DL_LIBS}\n  ${ZLIB_LDFLAGS}\n  ${LIBBPF_LDFLAGS}\n  brotli\n)\n\nif(ZSTD)\n  target_link_libraries(rr ${LIBZSTD_LDFLAGS})\nendif()\n\nif(staticlibs)\n  # Urgh ... this might not work for everyone, but there doesn't seem to be\n  # a way to persuade pkg-config/pkg_check_modules to produce the right flags\n  target_link_libraries(rr -L/home/roc/lib -l:libcapnp.a -l:libkj.a)\n  # Note that this works for both clang++ and g++\n  set(RR_MAIN_LINKER_FLAGS \"-static-libstdc++ ${RR_MAIN_LINKER_FLAGS}\")\nelseif(ANDROID)\n  target_link_libraries(rr CapnProto::capnp)\nelse()\n  target_link_libraries(rr ${CAPNP_LDFLAGS})\nendif()\n\nset_target_properties(rr PROPERTIES LINK_FLAGS \"${RR_MAIN_LINKER_FLAGS}\")\n\ntarget_link_libraries(rrpreload\n  ${CMAKE_DL_LIBS}\n)\n\nadd_executable(rr_exec_stub src/exec_stub.c)\npost_build_executable(rr_exec_stub)\nset_target_properties(rr_exec_stub\n                      PROPERTIES LINK_FLAGS \"-static -nostartfiles -nodefaultlibs ${LINKER_FLAGS}\")\nset_source_files_properties(src/exec_stub.c\n                            COMPILE_FLAGS \"-fno-stack-protector\")\n\nset(RR_GDB_RESOURCES\n  32bit-avx.xml\n  32bit-avx512.xml\n  32bit-core.xml\n  32bit-linux.xml\n  32bit-sse.xml\n  32bit-pkeys.xml\n  64bit-avx.xml\n  64bit-avx512.xml\n  64bit-core.xml\n  64bit-linux.xml\n  64bit-seg.xml\n  64bit-sse.xml\n  64bit-pkeys.xml\n  aarch64-core.xml\n  aarch64-fpu.xml\n  aarch64-pauth.xml\n)\nforeach(file ${RR_GDB_RESOURCES})\n  configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/third-party/gdb/${file}\"\n                 \"${CMAKE_CURRENT_BINARY_DIR}/share/rr/${file}\"\n                 COPYONLY)\n  install(FILES third-party/gdb/${file}\n          DESTINATION ${CMAKE_INSTALL_DATADIR}/rr)\nendforeach(file)\n\nforeach(file ${PRELOAD_SOURCE_FILES})\n  configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/preload/${file}\"\n                 \"${CMAKE_CURRENT_BINARY_DIR}/share/rr/src/preload/${file}\"\n                 COPYONLY)\n  install(FILES src/preload/${file}\n          DESTINATION ${CMAKE_INSTALL_DATADIR}/rr/src/preload)\nendforeach(file)\n\nforeach(file ${RR_PAGE_SOURCE_FILES})\n  configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/preload/${file}\"\n                 \"${CMAKE_CURRENT_BINARY_DIR}/share/rr/src/preload/${file}\"\n                 COPYONLY)\n  install(FILES src/preload/${file}\n          DESTINATION ${CMAKE_INSTALL_DATADIR}/rr/src/preload)\nendforeach(file)\nconfigure_file(\"${CMAKE_CURRENT_BINARY_DIR}/src/preload/rr_page.ld\"\n               \"${CMAKE_CURRENT_BINARY_DIR}/share/rr/src/preload/rr_page.ld\"\n               COPYONLY)\ninstall(FILES \"${CMAKE_CURRENT_BINARY_DIR}/src/preload/rr_page.ld\"\n        DESTINATION ${CMAKE_INSTALL_DATADIR}/rr/src/preload)\n\nconfigure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/scripts/rr-collect-symbols.py\"\n               \"${CMAKE_CURRENT_BINARY_DIR}/bin/rr-collect-symbols.py\"\n               COPYONLY)\nconfigure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/scripts/rr-gdb-script-host.py\"\n               \"${CMAKE_CURRENT_BINARY_DIR}/bin/rr-gdb-script-host.py\"\n               COPYONLY)\n\ninstall(PROGRAMS scripts/signal-rr-recording.sh\n                 scripts/rr-collect-symbols.py\n  DESTINATION ${CMAKE_INSTALL_BINDIR})\n\ninstall(PROGRAMS scripts/rr_completion\n  DESTINATION ${CMAKE_INSTALL_DATADIR}/bash-completion/completions RENAME rr)\n\n# Note that this works fine when installing to /usr/local, but zsh by default doesn't autoload *any* completions in HOME,\n# so people will still have to manually set `FPATH=~/.local/share/zsh/site-functions`.\ninstall(PROGRAMS scripts/rr_completion.zsh\n  DESTINATION ${CMAKE_INSTALL_DATADIR}/zsh/site-functions RENAME _rr)\n\nset(RR_INSTALL_LIBS rrpreload rrpage rr_exec_stub)\nif(RTLD_AUDIT)\n  set(RR_INSTALL_LIBS ${RR_INSTALL_LIBS} rraudit)\nendif()\ninstall(TARGETS ${RR_BIN} ${RR_INSTALL_LIBS}\n  RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n  LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr\n  ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr)\n\nif(EXTRA_EXTERNAL_SOLIBS)\n  install(PROGRAMS ${EXTRA_EXTERNAL_SOLIBS}\n    DESTINATION ${CMAKE_INSTALL_LIBDIR})\nendif()\n\n# Build 32-bit librrpreload and librraudit on 64-bit builds.\n# We copy the source files into '32' subdirectories in the output\n# directory, so we can set different compile options on them.\n# This sucks but I can't find a better way to get CMake to build\n# the same source file in two different ways.\nif(rr_32BIT AND rr_64BIT)\n  set(RR_INSTALL_LIBS_32 rrpreload_32 rrpage_32 rr_exec_stub_32)\n  add_library(rrpage_32)\n\n  foreach(file ${RR_PAGE_SOURCE_FILES})\n    configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/preload/${file}\"\n                   \"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}\"\n                   COPYONLY)\n  endforeach(file)\n\n  foreach(file ${RR_PAGE_FILES})\n    target_sources(rrpage_32 PUBLIC \"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}\")\n    set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}\"\n                                PROPERTIES COMPILE_FLAGS \"-m32 ${PRELOAD_COMPILE_FLAGS}\")\n  endforeach(file)\n\n  set_target_properties(rrpage_32 PROPERTIES NO_SONAME ON)\n  set_target_properties(rrpage_32 PROPERTIES LINK_FLAGS \"-m32 -Wl,-T -Wl,'${PROJECT_BINARY_DIR}/src/preload/rr_page.ld' -Wl,--hash-style=both -nostdlib ${PRELOAD_LINK_FLAGS} -Wl,-soname,linux-vdso.so.1 ${LINKER_FLAGS}\")\n  set_target_properties(rrpage_32 PROPERTIES LINK_DEPENDS \"${PROJECT_BINARY_DIR}/src/preload/rr_page.ld\")\n  set_target_properties(rrpage_32 PROPERTIES LINKER_LANGUAGE C)\n\n  add_custom_command(TARGET rrpage_32 POST_BUILD\n                    COMMAND \"${PROJECT_SOURCE_DIR}/src/preload/tweak_librrpage.py\" $<TARGET_FILE:rrpage_32> ${PRELOAD_LIBRARY_PAGE_SIZE})\n\n\n  add_library(rrpreload_32)\n\n  foreach(file ${PRELOAD_SOURCE_FILES})\n    configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/preload/${file}\"\n                   \"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}\"\n                   COPYONLY)\n  endforeach(file)\n\n  foreach(file ${PRELOAD_FILES})\n    target_sources(rrpreload_32 PUBLIC \"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}\")\n    set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/preload/${file}\"\n                                PROPERTIES COMPILE_FLAGS \"-m32 ${PRELOAD_COMPILE_FLAGS}\")\n  endforeach(file)\n\n  set_target_properties(rrpreload_32 PROPERTIES LINK_FLAGS \"-m32 ${PRELOAD_LINK_FLAGS} ${LINKER_FLAGS}\")\n  set_target_properties(rrpreload_32 PROPERTIES INSTALL_RPATH \"\\$ORIGIN\")\n  target_link_libraries(rrpreload_32\n    ${CMAKE_DL_LIBS}\n  )\n\n  if(RTLD_AUDIT)\n    add_library(rraudit_32)\n\n    foreach(file ${AUDIT_SOURCE_FILES})\n      configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/audit/${file}\"\n                     \"${CMAKE_CURRENT_BINARY_DIR}/32/audit/${file}\"\n                     COPYONLY)\n    endforeach(file)\n\n    foreach(file ${AUDIT_FILES})\n      target_sources(rraudit_32 PUBLIC \"${CMAKE_CURRENT_BINARY_DIR}/32/audit/${file}\")\n      set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/audit/${file}\"\n                                  PROPERTIES COMPILE_FLAGS \"-m32 ${PRELOAD_COMPILE_FLAGS}\")\n    endforeach(file)\n\n    set_target_properties(rraudit_32 PROPERTIES LINK_FLAGS \"-m32 -nostartfiles ${LINKER_FLAGS}\")\n    target_link_libraries(rraudit_32\n      ${CMAKE_DL_LIBS}\n    )\n\n    set(RR_INSTALL_LIBS_32 ${RR_INSTALL_LIBS_32} rraudit_32)\n  endif()\n\n  foreach(file exec_stub.c)\n    configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/${file}\"\n                   \"${CMAKE_CURRENT_BINARY_DIR}/32/${file}\"\n                   COPYONLY)\n    set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/${file}\"\n                                PROPERTIES COMPILE_FLAGS \"-m32 -fno-stack-protector\")\n  endforeach(file)\n\n  add_executable(rr_exec_stub_32 32/exec_stub.c)\n  post_build_executable(rr_exec_stub_32)\n  set_target_properties(rr_exec_stub_32\n                        PROPERTIES LINK_FLAGS \"-static -nostartfiles -nodefaultlibs -m32 ${LINKER_FLAGS}\")\n\n  install(TARGETS ${RR_INSTALL_LIBS_32}\n    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}\n    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr\n    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr)\nendif()\n\n##--------------------------------------------------\n## Testing\n\n# A \"basic test\" consists of a foo.c source file. All basic tests use the\n# same basic_test.run driver script. The test name is passed as an additional\n# parameter to the driver script. This script just does\n# \"compare_test EXIT-SUCCESS\", i.e. records and replays the program and verifies\n# that the output of both runs is identical and contains EXIT-SUCCESS.\n#\n# NB: you must update this variable when adding a new test source\n# file.  The list is not generated automatically.\n#\n# Alphabetical, please.\nset(BASIC_TESTS\n  64bit_child\n  _llseek\n  abort\n  accept\n  acct\n  adjtimex\n  aio\n  alarm\n  alarm2\n  alsa_ioctl\n  x86/arch_prctl_x86\n  x86/arch_prctl_xstate\n  async_segv_ignored\n  at_threadexit\n  bad_ip\n  bad_syscall\n  barrier\n  big_buffers\n  big_select\n  block\n  block_open\n  bpf\n  bpf_map\n  bpf_prog_map\n  bpf_query\n  brk\n  brk2\n  arm/brk_nonzero\n  capget\n  chew_cpu\n  x86/chew_cpu_cpuid\n  chmod\n  chown\n  clock\n  clock_adjtime\n  clock_nanosleep\n  clock_time64\n  clone\n  clone_bad_stack\n  clone_bad_tls\n  clone_cleartid_coredump\n  clone_fail\n  clone_immediate_exit\n  clone_newflags\n  clone_parent\n  clone_untraced\n  clone_vfork_pidfd\n  cloned_sigmask\n  close_range\n  constructor\n  copy_file_range\n  x86/cpuid_same_state\n  creat_address_not_truncated\n  x86/cross_arch\n  cwd_inaccessible\n  daemon\n  x86/deferred_patch\n  desched_blocking_poll\n  desched_sigkill\n  detach_huge_mmap\n  detach_state\n  detach_threads\n  detach_sigkill\n  detach_sigkill_exit\n  deterministic_sigsys\n  dev_zero\n  direct\n  dlchecksum\n  dup\n  doublesegv\n  epoll_create\n  epoll_create1\n  epoll_edge\n  epoll_many\n  epoll_pwait_eintr_sigmask\n  epoll_pwait2\n  eventfd\n  exec_flags\n  exec_no_env\n  exec_self\n  exec_from_main_thread\n  exec_from_other_thread\n  exec_stopsig\n  execveat\n  exit_with_syscallbuf_signal\n  fadvise\n  fatal_init_signal\n  fatal_sigsegv_thread\n  x86/fault_in_code_page\n  fcntl_dupfd\n  fcntl_lease\n  fcntl_misc\n  fcntl_notify\n  fcntl_owner_ex\n  fcntl_rw_hints\n  fcntl_seals\n  fcntl_sig\n  fd_cleanup\n  fd_tracking_across_threads\n  fds_clean\n  fexecve\n  fexecve_memfd\n  flock\n  flock_ofd\n  flock2\n  fork_brk\n  fork_child_crash\n  fork_many\n  fsmount\n  fstatat\n  futex_exit_race\n  futex_exit_race_sigsegv\n  futex_invalid_op\n  futex_pi\n  futex_priorities\n  futex_requeue\n  futex_restart_race\n  futex_restart_clone\n  gcrypt_rdrand\n  getcpu\n  getgroups\n  getpwnam\n  getrandom\n  setitimer\n  getsid\n  gettimeofday\n  grandchild_threads\n  grandchild_threads_main_running\n  grandchild_threads_thread_running\n  grandchild_threads_parent_alive\n  group_stop_thundering_herd\n  x86/hle\n  x86/hlt\n  inotify\n  int3\n  intr_futex_wait_restart\n  intr_poll\n  intr_ppoll\n  intr_pselect\n  intr_read_no_restart\n  intr_read_restart\n  intr_sleep\n  intr_sleep_no_restart\n  invalid_exec\n  invalid_fcntl\n  invalid_ioctl\n  io\n  io_uring\n  ioctl\n  ioctl_blk\n  ioctl_br\n  ioctl_fb\n  ioctl_fs\n  ioctl_pty\n  ioctl_sg\n  ioctl_tty\n  ioctl_ttyS\n  ioctl_vt\n  ioprio\n  x86/ioperm\n  x86/iopl\n  join_threads\n  joystick\n  kcmp\n  keyctl\n  kill_newborn\n  kill_ptracee\n  landlock\n  x86/la57\n  large_hole\n  large_write_deadlock\n  legacy_ugid\n  x86/lsl\n  madvise\n  madvise_dontneed_private\n  madvise_free\n  madvise_misc\n  madvise_remove\n  madvise_wipeonfork\n  map_fixed\n  map_shared_syscall\n  membarrier\n  memfd_create\n  memfd_create_efault\n  memfd_create_shared\n  memfd_create_shared_huge\n  memfd_create_dotnet_huge_mapping\n  mincore\n  mknod\n  mlock\n  mlock_madvise\n  mmap_adjacent_to_rr_usage\n  mmap_huge\n  mmap_private\n  mmap_private_grow_under_map\n  mmap_recycle\n  mmap_ro\n  mmap_self_maps_shared\n  mmap_shared\n  mmap_shared_dev_zero\n  mmap_shared_grow\n  mmap_shared_grow_under_map\n  mmap_shared_multiple\n  mmap_shared_subpage\n  mmap_shared_write\n  mmap_shared_write_fork\n  mmap_short_file\n  mmap_write_complex\n  mmap_zero_size_fd\n  x86/modify_ldt\n  mount_ns_exec\n  mount_ns_exec2\n  mount_ns_execveat\n  mprotect\n  mprotect_heterogenous\n  mprotect_none\n  mprotect_stack\n  mremap\n  mremap_after_coalesce\n  mremap_dontunmap\n  mremap_grow\n  mremap_grow_shared\n  mremap_non_page_size\n  mremap_overwrite\n  mremap_private_grow_under_map\n  mremap_shrink\n  msg\n  msg_trunc\n  msync\n  mtio\n  multiple_pending_signals\n  multiple_pending_signals_sequential\n  munmap_segv\n  munmap_discontinuous\n  nanosleep\n  netfilter\n  netfilter_ipv6\n  netlink_mmap_disable\n  no_mask_timeslice\n  nscd\n  numa\n  x86/old_fork\n  openat2\n  openat_null\n  open_tree\n  orphan_process\n  packet_mmap_disable\n  x86/patch_syscall_restart\n  pause\n  perf_event\n  perf_event_ioctl\n  perf_event_mmap\n  personality\n  pid_ns_kill_child\n  pid_ns_kill_child_threads\n  pid_ns_kill_child_zombie\n  pid_ns_kill_threads\n  pid_ns_kill_threads_exit_wait\n  pid_ns_reap\n  pid_ns_segv\n  pid_ns_shutdown\n  pidfd\n  pidfd_getfd\n  x86/pkeys\n  poll_sig_race\n  ppoll\n  ppoll_deliver\n  prctl\n  prctl_anon_vma_name\n  prctl_auxv\n  prctl_caps\n  prctl_deathsig\n  prctl_mdwe\n  prctl_name\n  prctl_short_name\n  prctl_speculation_ctrl\n  privileged_net_ioctl\n  proc_fds\n  proc_mem\n  protect_rr_fds\n  prw\n  pthread_condvar_locking\n  pthread_mutex_timedlock\n  pthread_pi_mutex\n  pthread_rwlocks\n  x86/ptrace\n  ptrace_attach_null_status\n  ptrace_attach_running\n  ptrace_attach_sleeping\n  ptrace_attach_stopped\n  ptrace_attach_syscall\n  ptrace_attach_thread_running\n  ptrace_breakpoint\n  ptrace_change_patched_syscall\n  x86/ptrace_debug_regs\n  ptrace_exec\n  x86/ptrace_exec32\n  ptrace_group_stop\n  ptrace_kill_grandtracee\n  x86/ptrace_tls\n  ptrace_seize\n  ptrace_sigchld\n  ptrace_sigchld_blocked\n  ptrace_signals\n  ptrace_singlestep\n  ptrace_syscall\n  ptrace_syscall_clone_untraced\n  x86/ptrace_sysemu\n  ptrace_sysemu_syscall\n  ptrace_trace_clone\n  ptrace_trace_exit\n  ptrace_traceme\n  ptrace_traceme_thread\n  ptrace_waiter_thread\n  ptracer_death\n  ptracer_death_multithread\n  ptracer_death_multithread_peer\n  # pivot_root ... disabled because it fails when run as root and does nothing otherwise\n  quotactl\n  x86/rdtsc\n  x86/rdtsc_flags\n  read_nothing\n  readdir\n  read_large\n  read_oversize\n  readlink\n  readlinkat\n  readv\n  record_replay_subject\n  recvfrom\n  redzone_integrity\n  rename\n  rlimit\n  rseq_cpu_id_reset\n  rusage\n  samask\n  save_data_fd\n  sched_attr\n  sched_setaffinity\n  sched_setparam\n  sched_yield\n  sched_yield_to_lower_priority\n  scm_rights\n  scratch_read\n  seccomp\n  seccomp_cloning\n  seccomp_clone_fail\n  seccomp_desched\n  seccomp_kill_exit\n  seccomp_madvise\n  seccomp_null\n  seccomp_sigsys_args\n  seccomp_sigsys_sigtrap\n  seccomp_sigsys_syscallbuf\n  seccomp_tsync\n  seccomp_veto_exec\n  self_shebang\n  self_sigint\n  sem\n  send_block\n  sendfile\n  set_ptracer\n  x86/set_thread_area\n  set_tid_address\n  setgid\n  setgroups\n  setsid\n  shared_exec\n  shared_monitor\n  shared_offset\n  shared_write\n  shm\n  shm_unmap\n  sigaction_old\n  sigaltstack\n  sigchld_interrupt_signal\n  sigcont\n  sigcont_threaded\n  sigframe_grow_stack\n  sighandler_bad_rsp_sigsegv\n  sighandler_fork\n  sighandler_mask\n  sigill\n  signal_deferred\n  signal_during_preload_init\n  signal_frame\n  signal_unstoppable\n  x86/signal_xmm_state\n  signalfd\n  sigprocmask\n  sigprocmask_ensure_delivery\n  sigprocmask_exec\n  sigprocmask_evil\n  sigprocmask_in_syscallbuf_sighandler\n  sigprocmask_rr_sigs\n  sigprocmask_syscallbuf\n  # sigprof\n  sigpwr\n  sigqueueinfo\n  sigtrap_process_group\n  x86/sigreturn\n  sigreturn_reg\n  sigreturnmask\n  sigrt\n  sigstop\n  sigstop2\n  sigsuspend\n  sigtrap\n  simple_threads_stress\n  sioc\n  small_holes\n  sock_name_null\n  sock_names_opts\n  spinlock_priorities\n  splice\n  stack_growth_after_syscallbuf\n  stack_growth_syscallbuf\n  stack_growth_with_guard\n  stack_invalid\n  stack_overflow\n  stack_overflow_altstack\n  stack_overflow_with_guard\n  statfs\n  statx\n  stdout_child\n  stdout_cloexec\n  stdout_dup\n  stdout_redirect\n  switch_read\n  symlink\n  sync\n  sync_file_range\n  syscall_bp\n  syscall_in_writable_mem\n  syscallbuf_signal_reset\n  syscallbuf_signal_blocking\n  syscallbuf_sigstop\n  syscallbuf_timeslice\n  syscallbuf_timeslice2\n  sysconf\n  sysconf_conf\n  sysctl\n  sysemu_singlestep\n  x86/sysfs\n  sysinfo\n  syslog\n  arm/tagged_addr_ctrl\n  tgkill\n  thread_yield\n  timer\n  timerfd\n  times\n  truncate_temp\n  tty_tostop\n  tun\n  two_signals_with_mask\n  ulimit_low\n  uname\n  unexpected_exit\n  unexpected_exit_execve\n  unexpected_exit_execve_twice\n  unexpected_exit_pid_ns\n  unjoined_thread\n  unshare\n  userfaultfd\n  utimes\n  v4l_dmabuf\n  vdso_parts\n  vdso_symbols\n  vfork_done\n  vfork_flush\n  vfork_setopts\n  vfork_shared\n  video_capture\n  vm_readv_writev\n  vsyscall\n  vsyscall_timeslice\n  x86/x87env\n  wait\n  wait_sigstop\n  write_race\n  writev\n  xattr\n  zero_length_read\n)\n\nif(MQUEUE_H)\n  set(BASIC_TESTS ${BASIC_TESTS} mq)\nendif()\n\nif(FANOTIFY_H)\n  set(BASIC_TESTS ${BASIC_TESTS} fanotify)\nendif()\n\nif(HAVE_ROBUST_MUTEX)\n  set(BASIC_TESTS ${BASIC_TESTS} robust_futex)\nendif()\n\nset(BASIC_CPP_TESTS\n  std_random\n  unwind_rr_page\n)\n\n# A \"test with program\" consists of a foo.c source file and a foo.run driver\n# script.  See src/test/util.sh to learn how the .run files work.\n#\n# NB: you must update this variable when adding a new test source\n# file.  The list is not generated automatically.\n#\n# Alphabetical, please.\nset(TESTS_WITH_PROGRAM\n  abort_nonmain\n  alternate_thread_diversion\n  arm/arch_timer\n  args\n  async_kill_with_syscallbuf\n  async_kill_with_syscallbuf2\n  async_kill_with_threads\n  async_kill_with_threads_main_running\n  async_kill_with_threads_thread_running\n  async_segv\n  async_signal_syscalls\n  async_signal_syscalls2\n  async_signal_syscalls_siginfo\n  async_usr1\n  blacklist\n  block_clone_checkpoint\n  block_clone_interrupted\n  block_clone_syscallbuf_overflow\n  block_intr_sigchld\n  blocked_bad_ip\n  blocked_sigill\n  x86/blocked_sigsegv\n  breakpoint\n  breakpoint_conditions\n  breakpoint_overlap\n  call_function\n  call_gettid\n  chaos_oom\n  # Disabled because it's very slow\n  # check_session_leaks\n  checkpoint_dying_threads\n  checkpoint_mixed_mode\n  checksum_sanity\n  check_lost_interrupts\n  clone_file_range\n  clone_interruption\n  # Disabled because it fails\n  # clone_share_vm\n  clone_syscallbuf_cleanup_blocked\n  clone_syscallbuf_cleanup_cpu\n  clone_vfork\n  concurrent_signals\n  conditional_breakpoint_calls\n  conditional_breakpoint_offload\n  condvar_stress\n  cont_race\n  context_switch_after_patch\n  x86/cpuid_singlestep\n  crash\n  crash_in_function\n  daemon_read\n  dconf_mock\n  detach_terminal\n  dev_tty\n  x86/diversion_rdtsc\n  diversion_sigtrap\n  diversion_syscall\n  dlopen\n  early_error\n  elapsed_time\n  exclusion_region\n  exec_failed\n  exec_many\n  exec_shared_as\n  execve_loop\n  exit_codes\n  exit_group\n  exit_race\n  exit_status\n  x86/explicit_checkpoints\n  fd_limit\n  fork_stress\n  fork_syscalls\n  function_calls\n  x86/fxregs\n  x86/gdb_avx512\n  getcwd\n  gdb_bogus_breakpoint\n  gdb_qpasssignals\n  goto_event\n  hello\n  hooks\n  # Disabled because issue #1806 makes tests fail on Debian 8.5 at least\n  # history\n  ignored_async_usr1\n  ignored_sigsegv\n  ignore_nested\n  immediate_restart\n  x86/int3_ok\n  interrupt\n  intr_ptrace_decline\n  invalid_interpreter\n  invalid_jump\n  jit_proc_mem\n  link\n  madvise_dontfork\n  madvise_fracture_flags\n  main_thread_exit\n  many_yields\n  mmap_fd_reuse_checkpoint\n  mmap_replace_most_mappings\n  mmap_shared_extern\n  mmap_shared_prot\n  mmap_shared_write_exec_race\n  mmap_tmpfs\n  mmap_write\n  mmap_write_private\n  mprotect_checkpoint\n  x86/morestack_unwind\n  mprotect_growsdown\n  mprotect_syscallbuf_overflow\n  mutex_pi_stress\n  nested_detach_wait\n  nested_detach_kill_stuck\n  nested_release_signal\n  overflow_branch_counter\n  pack\n  patch_page_end\n  x86/patch_40_80_f6_81\n  x86/patch_pc_rel\n  prctl_tsc\n  priority\n  ptrace_remote_unmap\n  x86/rdtsc_loop\n  x86/rdtsc_loop2\n  x86/rdtsc_interfering\n  read_big_struct\n  remove_latest_trace\n  restart_abnormal_exit\n  reverse_continue_breakpoint\n  reverse_continue_multiprocess\n  reverse_continue_process_signal\n  reverse_many_breakpoints\n  reverse_step_long\n  reverse_step_threads\n  reverse_step_threads_break\n  # Not called ps, because that interferes with using real 'ps' in tests\n  rr_ps\n  rr_ps_ns\n  rseq\n  rseq_syscallbuf\n  rseq_cpu_id_reset_longrunning\n  search\n  seccomp_blocks_rr\n  seccomp_open\n  seccomp_signals\n  seekticks_threads\n  segfault\n  setuid\n  shared_map\n  shared_persistent_file\n  signal_numbers\n  sigprocmask_race\n  sigprocmask_rr_sigs_nondefault\n  simple\n  x86/singlestep_pushf\n  stack_growth\n  step_into_lib\n  step_thread\n  strict_priorities\n  x86/string_instructions\n  x86/string_instructions_async_signals\n  x86/string_instructions_async_signals_shared\n  x86/string_instructions_multiwatch\n  x86/string_instructions_replay\n  x86/string_instructions_singlestep_fastforward\n  x86/string_instructions_watch\n  x86/syscallbuf_branch_check\n  syscallbuf_fd_disabling\n  x86/syscallbuf_rdtsc_page\n  syscallbuf_signal_blocking_read\n  sysconf_onln\n  target_fork\n  target_process\n  tcp_sockets\n  term_nonmain\n  term_rr\n  term_rr_ok\n  term_trace_reset\n  term_trace_syscall\n  thread_exit_signal\n  thread_open_race\n  thread_stress\n  threaded_syscall_spam\n  threads\n  tls\n  tracee_unmap_vdso\n  ttyname\n  unexpected_stack_growth\n  unicode\n  user_ignore_sig\n  vdso_clock_gettime_stack\n  vdso_gettimeofday_stack\n  vdso_time_stack\n  vfork\n  vfork_read_clone_stress\n  vsyscall_reverse_next\n  wait_for_all\n  watchpoint\n  watchpoint_at_sched\n  watchpoint_before_signal\n  x86/watchpoint_error\n  watchpoint_no_progress\n  watchpoint_size_change\n  watchpoint_syscall\n  watchpoint_unaligned\n  when_threads\n)\n\n# A \"test without program\" is a foo.run driver script only, which does\n# something with one of the test executables above (or has special rules\n# to build its own executable).\n#\n# NB: you must update this variable when adding a new test source\n# file.  The list is not generated automatically.\n#\n# Alphabetical, please.\nset(TESTS_WITHOUT_PROGRAM\n  async_signal_syscalls_100\n  async_signal_syscalls_1000\n  bad_breakpoint\n  break_block\n  break_clock\n  break_clone\n  break_exec\n  break_int3\n  break_mmap_private\n  break_msg\n  x86/break_rdtsc\n  break_sigreturn\n  break_sync_signal\n  break_thread\n  break_time_slice\n  breakpoint_consistent\n  breakpoint_print\n  call_exit\n  check_patched_pthread\n  checkpoint_async_signal_syscalls_1000\n  checkpoint_invalid\n  checkpoint_mmap_shared\n  checkpoint_prctl_name\n  checkpoint_simple\n  checksum_block_open\n  checksum_sanity_noclone\n  comm\n  cont_signal\n  copy_all\n  x86/cpuid\n  dead_thread_target\n  desched_ticks\n  deliver_async_signal_during_syscalls\n  env_newline\n  exec_deleted\n  exec_stop\n  execp\n  explicit_checkpoint_clone\n  fd_leak\n  file_name_newline\n  final_sigkill\n  first_instruction\n  fork_exec_info_thr\n  get_thread_list\n  hardlink_mmapped_files\n  hbreak\n  large_file\n  mprotect_step\n  nested_detach\n  nested_detach_kill\n  nested_detach_stop\n  nested_release\n  nested_release_exit_code\n  pack_dir\n  parent_no_break_child_bkpt\n  parent_no_stop_child_crash\n  personality_chaos\n  post_exec_fpu_regs\n  proc_maps\n  read_bad_mem\n  record_replay\n  remove_watchpoint\n  replay_overlarge_event_number\n  replay_serve_files\n  restart_invalid_checkpoint\n  restart_unstable\n  restart_diversion\n  reverse_alarm\n  reverse_continue_exec_subprocess\n  reverse_continue_fork_subprocess\n  reverse_continue_int3\n  reverse_continue_start\n  reverse_finish\n  reverse_step_breakpoint\n  reverse_step_signal\n  reverse_step_threads2\n  reverse_watchpoint\n  reverse_watchpoint_syscall\n  run_end\n  run_in_function\n  sanity\n  seekticks\n  shm_checkpoint\n  siginfo\n  x86/sigreturn_checksum\n  signal_stop\n  signal_checkpoint\n  simple_script\n  simple_script_debug\n  simple_winch\n  stack_overflow_debug\n  step1\n  x86/step_rdtsc\n  step_signal\n  x86/string_instructions_break\n  x86/string_instructions_replay_quirk\n  subprocess_exit_ends_session\n  switch_processes\n  syscallbuf_timeslice_250\n  tick0\n  tick0_less\n  trace_version\n  term_trace_cpu\n  trace_events\n  traceinfo\n  transient_fault_replay_all\n  tty\n  unmap_vdso\n  unwind_on_signal\n  vfork_done_clone\n  vfork_exec\n  vfork_break_parent\n  vsyscall_singlestep\n  watch_code\n  watchpoint_cond\n  watchpoint_step\n  watchpoint_unaligned2\n  when\n)\n\nif(BUILD_TESTS)\n  # Part of the installable testsuite (test files).\n  if(INSTALL_TESTSUITE)\n    install(DIRECTORY ${CMAKE_SOURCE_DIR}/src/test/\n            DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/rr/src/test\n            USE_SOURCE_PERMISSIONS)\n  endif(INSTALL_TESTSUITE)\n\n  # We use symlinks in the tests to access the build and source directories.\n  # This is needed because we cannot change the paths used by the tests when\n  # the testsuite is installed. We work around this by using symlinks during\n  # the normal build, and then installing symlinks with the testsuite that\n  # have the same name but, the new link targets.\n  execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${CMAKE_SOURCE_DIR} source_dir)\n  execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink ${PROJECT_BINARY_DIR} bin_dir)\n\n  if(INSTALL_TESTSUITE)\n    # Create the directory for the symlinks first and then create symlinks.\n    install(CODE \"execute_process(COMMAND ${CMAKE_COMMAND} -E make_directory\n                  \\$ENV{DESTDIR}\\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj)\n                  execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink\n                  \\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/rr/testsuite/rr\n                  \\$ENV{DESTDIR}\\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/source_dir)\n                  execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink\n                  \\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj\n                  \\$ENV{DESTDIR}\\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin_dir)\")\n  endif(INSTALL_TESTSUITE)\n\n  foreach(test ${BASIC_TESTS} ${TESTS_WITH_PROGRAM})\n    if (NOT x86ish AND ${test} MATCHES \"^x86/.*\")\n      continue()\n    endif()\n    if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\" AND ${test} MATCHES \"^arm/.*\")\n      continue()\n    endif()\n    get_filename_component(testname ${test} NAME)\n\n    add_executable(${testname} src/test/${test}.c)\n    target_include_directories(${testname} PRIVATE src/preload)\n    post_build_executable(${testname})\n    set_source_files_properties(src/test/${test}.c\n                                PROPERTIES COMPILE_FLAGS ${RR_TEST_FLAGS})\n    add_dependencies(${testname} Generated)\n    if(LIBRT)\n      target_link_libraries(${testname} ${LIBRT})\n    endif()\n    target_link_libraries(${testname} -ldl)\n    # Part of the installable testsuite (test programs).\n    if(INSTALL_TESTSUITE)\n      install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/${testname}\n              DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n    endif(INSTALL_TESTSUITE)\n  endforeach(test)\n\n  add_executable(tick0 src/test/tick0.c)\n  post_build_executable(tick0)\n  set_target_properties(tick0\n    PROPERTIES LINK_FLAGS \"-static -nostdlib -nodefaultlibs\"\n    COMPILE_FLAGS \"-static -nostdlib -nodefaultlibs -O3 -g2 -DHAS_TICK0=1\")\n\n  add_executable(tick0_less src/test/tick0.c)\n  post_build_executable(tick0_less)\n  set_target_properties(tick0_less\n    PROPERTIES LINK_FLAGS \"-static -nostdlib -nodefaultlibs\"\n    COMPILE_FLAGS \"-static -nostdlib -nodefaultlibs -O3 -g2\")\n\n  add_executable(watchpoint_unaligned2 src/test/watchpoint_unaligned2.c)\n  post_build_executable(watchpoint_unaligned2)\n  set_target_properties(watchpoint_unaligned2\n    PROPERTIES COMPILE_FLAGS \"${RR_TEST_FLAGS} -g -O3\")\n  add_dependencies(watchpoint_unaligned2 Generated)\n\n  add_executable(prctl_tsc_supported src/test/prctl_tsc_supported.c)\n  post_build_executable(prctl_tsc_supported)\n\n  # Test disabled because it requires libuvc to be built and installed, and a\n  # working USB camera\n  # add_executable(usb src/test/usb.c)\n  # post_build_executable(usb)\n  # add_dependencies(usb Generated)\n  # target_link_libraries(usb ${LIBRT} -L/usr/local/lib -luvc -lusb-1.0)\n\n  foreach(test ${BASIC_CPP_TESTS})\n    add_executable(${test} src/test/${test}.cc)\n    post_build_executable(${test})\n    set_source_files_properties(src/test/${test}.cc\n                                PROPERTIES COMPILE_FLAGS ${RR_TEST_FLAGS})\n    add_dependencies(${test} Generated)\n    if(LIBRT)\n      target_link_libraries(${test} ${LIBRT})\n    endif()\n    # Part of the installable testsuite (test programs).\n    if(INSTALL_TESTSUITE)\n      install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/${test}\n              DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n    endif(INSTALL_TESTSUITE)\n  endforeach(test)\n\n  add_library(test_lib\n    src/test/test_lib.c\n    )\n  add_dependencies(test_lib Generated)\n  set_source_files_properties(src/test/test_lib.c\n                              PROPERTIES COMPILE_FLAGS ${RR_TEST_FLAGS})\n  if(LIBRT)\n    target_link_libraries(constructor ${LIBRT})\n    target_link_libraries(step_into_lib ${LIBRT})\n  endif()\n  target_link_libraries(constructor test_lib)\n  target_link_libraries(step_into_lib test_lib)\n\n  # cpuid test needs to link with cpuid_loop.S\n  if (x86ish)\n    add_executable(cpuid src/test/x86/cpuid.c src/test/x86/cpuid_loop.S)\n    post_build_executable(cpuid)\n    set_source_files_properties(src/test/x86/cpuid.c\n                                PROPERTIES COMPILE_FLAGS ${RR_TEST_FLAGS})\n    add_dependencies(cpuid Generated)\n    if(LIBRT)\n      target_link_libraries(cpuid ${LIBRT})\n    endif()\n  endif()\n\n  # Add exit_fast test executable\n  add_executable(exit_fast src/test/exit_fast.c)\n  set_target_properties(exit_fast\n                      PROPERTIES LINK_FLAGS \"-static -nostartfiles -nodefaultlibs ${LINKER_FLAGS}\")\n  post_build_executable(exit_fast)\n  add_dependencies(exit_fast Generated)\n  set_source_files_properties(src/test/exit_fast.c\n                              COMPILE_FLAGS \"-fno-stack-protector\")\n\n  # Check if we're running on KNL. If so, we allot more time to tests, due to\n  # reduced single-core performance.\n  execute_process(COMMAND cat /proc/cpuinfo OUTPUT_VARIABLE CPUINFO)\n  string(REGEX MATCH \"^.*(Xeon Phi).*$\" CPU_MODEL_PHI ${CPUINFO})\n  if(NOT \"${CPU_MODEL_PHI}\" STREQUAL \"\")\n    set(TEST_MONITOR_DEFAULT_TIMEOUT 480)\n  else()\n    set(TEST_MONITOR_DEFAULT_TIMEOUT 120)\n  endif()\n\n  # The real timeouts are handled by test-monitor\n  set(CTEST_TEST_TIMEOUT 1000)\n\n  function(configure_test test)\n    set_tests_properties(${test} PROPERTIES FAIL_REGULAR_EXPRESSION \"FAILED\" SKIP_RETURN_CODE 77)\n  endfunction(configure_test)\n\n  if(INSTALL_TESTSUITE)\n    install(TARGETS test_lib\n            LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr)\n    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/test-monitor\n            DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n    install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/exit_fast\n            DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n    if (x86ish)\n      install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/cpuid\n              DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n    endif(x86ish)\n    install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CTestTestfile.cmake\n            DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj)\n  endif(INSTALL_TESTSUITE)\n\n  foreach(test ${BASIC_TESTS} ${BASIC_CPP_TESTS} ${OTHER_TESTS})\n    if (NOT x86ish AND ${test} MATCHES \"^x86/.*\")\n      continue()\n    endif()\n    if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\" AND ${test} MATCHES \"^arm/.*\")\n      continue()\n    endif()\n    get_filename_component(testname ${test} NAME)\n    add_test(${test}\n      bash source_dir/src/test/basic_test.run ${testname} \"\" bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n    configure_test(${test})\n    add_test(${test}-no-syscallbuf\n      bash source_dir/src/test/basic_test.run ${testname} -n bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n    configure_test(${test}-no-syscallbuf)\n  endforeach(test)\n\n  foreach(test ${TESTS_WITH_PROGRAM} ${TESTS_WITHOUT_PROGRAM})\n    if (NOT x86ish AND ${test} MATCHES \"^x86/.*\")\n      continue()\n    endif()\n    if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\" AND ${test} MATCHES \"^arm/.*\")\n      continue()\n    endif()\n    get_filename_component(testname ${test} NAME)\n    add_test(${test}\n      bash source_dir/src/test/${test}.run ${testname} \"\" bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n    configure_test(${test})\n    add_test(${test}-no-syscallbuf\n      bash source_dir/src/test/${test}.run ${testname} -n bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n    configure_test(${test}-no-syscallbuf)\n  endforeach(test)\n\n  # Run 32-bit tests on 64-bit builds.\n  # We copy the test files into '32' subdirectories in the output\n  # directory, so we can set different compile options on them.\n  # This sucks but I can't find a better way to get CMake to build\n  # the same source file in two different ways.\n  if(rr_32BIT AND rr_64BIT)\n    foreach(header util.h nsutils.h ptrace_util.h util_syscall.h util_internal.h)\n      configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/test/${header}\"\n                    \"${CMAKE_CURRENT_BINARY_DIR}/32/${header}\"\n                    COPYONLY)\n    endforeach(header)\n\n    foreach(test ${BASIC_TESTS} ${TESTS_WITH_PROGRAM} x86/cpuid test_lib tick0 watchpoint_unaligned2 exit_fast)\n      configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/test/${test}.c\"\n                     \"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.c\"\n                     COPYONLY)\n      set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.c\"\n                                  PROPERTIES COMPILE_FLAGS \"-m32 ${RR_TEST_FLAGS}\")\n    endforeach(test)\n\n    foreach(test ${BASIC_CPP_TESTS})\n      configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/test/${test}.cc\"\n                     \"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.cc\"\n                     COPYONLY)\n      set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.cc\"\n                                  PROPERTIES COMPILE_FLAGS \"-m32 ${RR_TEST_FLAGS}\")\n    endforeach(test)\n\n    foreach(file x86/cpuid_loop.S x86/util.h)\n      configure_file(\"${CMAKE_CURRENT_SOURCE_DIR}/src/test/${file}\"\n                     \"${CMAKE_CURRENT_BINARY_DIR}/32/${file}\"\n                     COPYONLY)\n      set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/${file}\"\n                                  PROPERTIES COMPILE_FLAGS \"-m32 ${RR_TEST_FLAGS}\")\n    endforeach(file)\n\n    foreach(test ${BASIC_TESTS} ${BASIC_CPP_TESTS} ${TESTS_WITH_PROGRAM})\n      if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\" AND ${test} MATCHES \"^arm/.*\")\n        continue()\n      endif()\n      get_filename_component(testname ${test} NAME)\n      if(EXISTS \"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.c\")\n        add_executable(${testname}_32 \"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.c\")\n      else()\n        add_executable(${testname}_32 \"${CMAKE_CURRENT_BINARY_DIR}/32/${test}.cc\")\n      endif()\n      target_include_directories(${testname}_32 PRIVATE src/preload)\n      post_build_executable(${testname}_32)\n      add_dependencies(${testname}_32 Generated)\n      set_target_properties(${testname}_32 PROPERTIES LINK_FLAGS \"-m32 ${RR_TEST_FLAGS} ${LINKER_FLAGS}\")\n      if(LIBRT_32)\n        target_link_libraries(${testname}_32 ${LIBRT_32})\n      endif()\n      target_link_libraries(${testname}_32 -ldl)\n      # Part of the installable testsuite (test programs).\n      if (INSTALL_TESTSUITE)\n        install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/${testname}_32\n                DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n      endif (INSTALL_TESTSUITE)\n    endforeach(test)\n\n    add_executable(tick0_32 \"${CMAKE_CURRENT_BINARY_DIR}/32/tick0.c\")\n    post_build_executable(tick0_32)\n    set_target_properties(tick0_32\n      PROPERTIES LINK_FLAGS \"-m32 -static -nostdlib -nodefaultlibs\"\n      COMPILE_FLAGS \"-m32 -static -nostdlib -nodefaultlibs -O3 -g2 -DHAS_TICK0=1\")\n\n    add_executable(tick0_less_32 \"${CMAKE_CURRENT_BINARY_DIR}/32/tick0.c\")\n    post_build_executable(tick0_less_32)\n    set_target_properties(tick0_less_32\n      PROPERTIES LINK_FLAGS \"-m32 -static -nostdlib -nodefaultlibs\"\n      COMPILE_FLAGS \"-m32 -static -nostdlib -nodefaultlibs -O3 -g2\")\n\n    # Add exit_fast test executable\n    add_executable(exit_fast_32 \"${CMAKE_CURRENT_BINARY_DIR}/32/exit_fast.c\")\n    set_target_properties(exit_fast_32\n                        PROPERTIES LINK_FLAGS \"-static -nostartfiles -nodefaultlibs ${LINKER_FLAGS}\")\n    add_dependencies(exit_fast_32 Generated)\n    post_build_executable(exit_fast_32)\n    set_source_files_properties(\"${CMAKE_CURRENT_BINARY_DIR}/32/exit_fast.c\" COMPILE_FLAGS \"-fno-stack-protector\")\n\n    add_executable(watchpoint_unaligned2_32 \"${CMAKE_CURRENT_BINARY_DIR}/32/watchpoint_unaligned2.c\")\n    post_build_executable(watchpoint_unaligned2_32)\n    set_target_properties(watchpoint_unaligned2_32\n      PROPERTIES LINK_FLAGS \"-m32\"\n      COMPILE_FLAGS \"-m32 ${RR_TEST_FLAGS} -g -O3\")\n    add_dependencies(watchpoint_unaligned2_32 Generated)\n\n    add_library(test_lib_32\n      \"${CMAKE_CURRENT_BINARY_DIR}/32/test_lib.c\"\n    )\n    add_dependencies(test_lib_32 Generated)\n    set_target_properties(test_lib_32 PROPERTIES LINK_FLAGS \"-m32 ${LINKER_FLAGS}\")\n\n    if(LIBRT_32)\n      target_link_libraries(constructor_32 ${LIBRT_32})\n      target_link_libraries(step_into_lib_32 ${LIBRT_32})\n    endif()\n    target_link_libraries(constructor_32 test_lib_32)\n    target_link_libraries(step_into_lib_32 test_lib_32)\n\n    # cpuid test needs to link with cpuid_loop.S\n    add_executable(cpuid_32 32/x86/cpuid.c 32/x86/cpuid_loop.S)\n    post_build_executable(cpuid_32)\n    add_dependencies(cpuid_32 Generated)\n    set_target_properties(cpuid_32 PROPERTIES LINK_FLAGS \"-m32 ${LINKER_FLAGS}\")\n    if(LIBRT_32)\n      target_link_libraries(cpuid_32 ${LIBRT_32})\n    endif()\n\n    if(INSTALL_TESTSUITE)\n      install(TARGETS test_lib_32\n              LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr)\n      install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/bin/cpuid_32\n              DESTINATION ${CMAKE_INSTALL_LIBDIR}/rr/testsuite/obj/bin)\n    endif(INSTALL_TESTSUITE)\n\n    foreach(test ${BASIC_TESTS} ${BASIC_CPP_TESTS} ${OTHER_TESTS})\n      if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\" AND ${test} MATCHES \"^arm/.*\")\n        continue()\n      endif()\n      get_filename_component(testname ${test} NAME)\n      add_test(${test}-32\n        bash source_dir/src/test/basic_test.run ${testname}_32 \"\" bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n      configure_test(${test}-32)\n      add_test(${test}-32-no-syscallbuf\n        bash source_dir/src/test/basic_test.run ${testname}_32 -n bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n      configure_test(${test}-32-no-syscallbuf)\n    endforeach(test)\n\n    foreach(test ${TESTS_WITH_PROGRAM} ${TESTS_WITHOUT_PROGRAM})\n      if (NOT ${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"aarch64\" AND ${test} MATCHES \"^arm/.*\")\n        continue()\n      endif()\n      get_filename_component(testname ${test} NAME)\n      add_test(${test}-32\n        bash source_dir/src/test/${test}.run ${testname}_32 \"\" bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n      configure_test(${test}-32)\n      add_test(${test}-32-no-syscallbuf\n        bash source_dir/src/test/${test}.run ${testname}_32 -n bin_dir ${TEST_MONITOR_DEFAULT_TIMEOUT})\n      configure_test(${test}-32-no-syscallbuf)\n    endforeach(test)\n  endif()\n\n  set(CHAOS_TESTS\n    core_count\n    futex_wakeup\n    getaffinity_core_count\n    pipe_wakeup\n    mmap_adjacent\n    mmap_bits\n    startup\n    starvation_multithreaded\n    starvation_singlethreaded\n  )\n\n  foreach(test ${CHAOS_TESTS})\n    add_executable(${test} src/chaos-test/${test}.c)\n    post_build_executable(${test})\n    if(LIBRT)\n      target_link_libraries(${test} ${LIBRT})\n    endif()\n  endforeach(test)\n\n  add_executable(test-monitor src/test-monitor/test-monitor.cc)\n\n  add_executable(ftrace_helper src/ftrace/ftrace_helper.c)\n  add_executable(counters src/counters-test/counters.cc)\n  set_source_files_properties(src/counters-test/counters.cc\n                              PROPERTIES COMPILE_FLAGS \"-fno-stack-protector\")\nendif()\n\ninclude(ProcessorCount)\nProcessorCount(N)\nif(NOT N EQUAL 0)\n  set(JFLAG -j${N})\nendif()\n\nadd_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND} --verbose ${JFLAG} USES_TERMINAL)\n# Run only syscallbuf-enabled and native-bitness tests\nadd_custom_target(fastcheck COMMAND ${CMAKE_CTEST_COMMAND} --verbose --exclude-regex '[-]' ${JFLAG} USES_TERMINAL)\n\n##--------------------------------------------------\n## Package configuration\n\ninclude (InstallRequiredSystemLibraries)\n\nset(CPACK_PACKAGE_NAME \"rr\")\nset(CPACK_PACKAGE_VERSION_MAJOR \"${rr_VERSION_MAJOR}\")\nset(CPACK_PACKAGE_VERSION_MINOR \"${rr_VERSION_MINOR}\")\nset(CPACK_PACKAGE_VERSION_PATCH \"${rr_VERSION_PATCH}\")\nset(CPACK_SYSTEM_NAME \"${CMAKE_SYSTEM_NAME}-${CMAKE_SYSTEM_PROCESSOR}\")\n\nset(CPACK_OUTPUT_FILE_PREFIX dist)\nset(CPACK_GENERATOR \"TGZ;RPM;DEB\" CACHE STRING \"CPack generators\")\nset(CPACK_SOURCE_GENERATOR \"TGZ\")\nset(CPACK_BINARY_DIR \"${PROJECT_BINARY_DIR}\")\n# Don't strip binaries. It's important/useful for librrpreload at least to\n# have debug symbols. For package releases, pass -Dstrip=TRUE to strip symbols\n# from the rr binary at build time.\nset(CPACK_STRIP_FILES FALSE)\n\nset(CPACK_RESOURCE_FILE_LICENSE \"${CMAKE_SOURCE_DIR}/LICENSE\")\nset(CPACK_PACKAGE_DESCRIPTION_SUMMARY\n  \"Lightweight tool for recording and replaying execution of applications (trees of processes and threads)\")\nset(CPACK_PACKAGE_DESCRIPTION_FILE \"${CMAKE_SOURCE_DIR}/README.md\")\nset(CPACK_PACKAGE_VENDOR \"rr-debugger\")\n\nset(CPACK_DEBIAN_PACKAGE_MAINTAINER \"rr-debugger\")\nset(CPACK_DEBIAN_PACKAGE_SECTION \"devel\")\nif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL \"x86_64\")\n  set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE \"amd64\")\nelseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES \"i.86\")\n  set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE \"i386\")\nelseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES \"arm.*\")\n  set(CPACK_DEBIAN_PACKAGE_ARCHITECTURE \"arm\")\nendif()\n\n# XXX Cmake 2.8.7 doesn't know how to avoid specifying /usr,\n# /usr/bin, etc, as files to be installed, but distros are finicky\n# about their specification.  We want to manually filter those paths\n# out of our install list but 2.8.7 also isn't capable of that.\nset(CPACK_RPM_USER_BINARY_SPECFILE \"${CMAKE_SOURCE_DIR}/rr.spec\")\nset(CPACK_RPM_PACKAGE_RELEASE 1)\nset(CPACK_RPM_PACKAGE_GROUP \"Development/Debuggers\")\nset(CPACK_RPM_PACKAGE_LICENSE \"MIT and BSD\")\n# Prevent binaries from being stripped\nset(CPACK_RPM_SPEC_INSTALL_POST \"/bin/true\")\n\ninclude (CPack)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Community Participation Guidelines\n\nThis repository is governed by Mozilla's code of conduct and etiquette guidelines. \nFor more details, please read the\n[Mozilla Community Participation Guidelines](https://www.mozilla.org/about/governance/policies/participation/). \n\n## How to Report\nFor more information on how to report violations of the Community Participation Guidelines, please read our '[How to Report](https://www.mozilla.org/about/governance/policies/participation/reporting/)' page.\n\n<!--\n## Project Specific Etiquette\n\nIn some cases, there will be additional project etiquette i.e.: (https://bugzilla.mozilla.org/page.cgi?id=etiquette.html).\nPlease update for your project.\n-->\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Submission Checklist\n\nPlease make sure you go through this list before submitting a patch.  The rules aren't hard and fast, but mostly adhering to them will make for quicker mergings.\n\n- [ ] Does your PR add support for a new kernel API?  For example, supporting a new syscall.  If so, your patch should include at least one new test for the API.  This is usually pretty easy.  See `$rr/src/test` for examples.\n\n- [ ] Did you run the rr test suite (including your new tests, if any), and pass all the tests?  `make -C $objdir check`.  Unfortunately, rr doesn't have automated infrastructure that can run the tests yet, so developers have to run them locally.\n\n- [ ] If you created new files for your PR, did you `git add` them?  Habitually (or with a script or push hook) checking `git status` is a good habit to acquire.\n\n- [ ] If you changed the trace layout or format, did you bump `TRACE_VERSION`?\n\n- [ ] If you added new command-line parameters, did you update `print_usage()` to document them?\n\n- [ ] Does your PR apply cleanly on top of upstream/master HEAD?  It's dangerous to have someone else sort out your merge conflicts, so just don't do it.  Best of all is to have a PR *rebased* on top of upstream/master HEAD, so that the merge is simply a fast-forward.\n\n- [ ] If your PR includes multiple changesets, do they all (i) build cleanly in sequence; (ii) pass all tests in sequence?  This is important for bisecting over commit history.\n\n- [ ] If your PR is a very large-scale change (for example, a rewrite in Rust to use the visitor pattern), did you discuss the proposed changes in an issue or the mailing list?  It's hard to review large patches that just fall in ones lap.  It's much easier to discuss the important changes at a high level and then approach the patch knowing what's important and what's not.\n\n- [ ] If your PR is large or includes many changesets, would it have been possible to break the changes into a series of smaller PRs?  For example, it's hard to review a big patch that, say, fixes whitespace errors in a file along with a one-line, important, bug fix.  It's much easier to review one PR that fixes whitespace (which can just be skimmed), and then review another PR that makes the one-line bug fix (which would be scrutinized more).  This approach is also better for the patch author in that it usually allows the work to land faster, and reduces the burden of continually un-bit-rotting large, trivial, changes.\n\n- [ ] Did you check your code is formatted correctly? It's easiest to run `scripts/reformat.sh` on each commit.\n\n## Coding Guidelines\n\nrr uses assertions heavily, for code documentation, for automated checking that the code matches the documentation, and to improve the power of automated tests. Assertions are turned on in release builds. Whenever you depend on an invariant not immediately obvious, consider adding assertions to check it.\n\nrr ships with debugging enabled and compiler optimizations disabled for the rr process itself. That's because rr performance almost always depends on algorithmic issues --- minimizing the number of system calls, and especially, minimizing the number of context switches between the tracees and the rr process --- much more than the performance of the code running in the rr process. For the same reason, rr-process code should be as simple as possible even if that's less efficient. To some extent, once we're running code in the rr process, we've already lost performance-wise. OTOH we do enable optimizations in `preload.c` because that runs in tracees.\n\n## Coding Style\n\nPut braces around all statement blocks, even one-line `if` bodies etc.\n\nAll C++ declarations are in the `rr` namespace.\n\nAll C++ types are in CamelCase; all C types are underscore_names.\n"
  },
  {
    "path": "LICENSE",
    "content": "Copyright (c) 2013 Mozilla Foundation\nCopyright 2015 VMware, Inc\nCopyright 2015 Google Inc.\n\nContributors: Albert Noll <noll.albert@gmail.com>, Thomas Anderegg <thomas@tanderegg.com>, Nimrod Partush <nimrodpar@gmail.com>\n              Andrew Walton <awalton@vmware.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the \"Software\"),\nto deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL\nTHE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\nDEALINGS IN THE SOFTWARE.\n\n/*\n * Copyright 2002 Niels Provos <provos@citi.umich.edu>\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\n * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\n * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\n * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\n * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\n * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\n * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n====================================================================================\n\nThe following applies only to files under third-party/gdb:\n\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n====================================================================================\n\nThe following applies only to files under third-party/zen-pmu-workaround:\n\n\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Library General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate qto certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\f\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\f\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\f\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\f\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\f\n\t    How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Library General\nPublic License instead of this License.\n\n====================================================================================\n\nThe following applies only to src/test/dlchecksum.c:\n\n/*\n  Copyright (C) The Julia contributors.\n  Copyright (C) 2013 Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the author be held liable for any damages\n  arising from the use of this software.\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n  Mark Adler\n  madler@alumni.caltech.edu\n*/\n"
  },
  {
    "path": "README.md",
    "content": "# Overview\n\n[![Build and test status](https://github.com/rr-debugger/rr/actions/workflows/build-and-test-main.yml/badge.svg?branch=master)](https://github.com/rr-debugger/rr/actions)\n\nrr is a lightweight tool for recording, replaying and debugging execution of applications (trees of processes and threads).\nDebugging extends gdb with very efficient reverse-execution, which in combination with standard gdb/x86 features like hardware data watchpoints, makes debugging much more fun. More information about the project, including instructions on how to install, run, and build rr, is at [https://rr-project.org](https://rr-project.org). The best technical overview is currently the paper [Engineering Record And Replay For Deployability: Extended Technical Report](https://arxiv.org/pdf/1705.05937.pdf).\n\nOr go directly to the [installation and building instructions](https://github.com/rr-debugger/rr/wiki/Building-And-Installing).\n\nPlease contribute!  Make sure to review the [pull request checklist](/CONTRIBUTING.md) before submitting a pull request.\n\nIf you find rr useful, please [add a testimonial](https://github.com/rr-debugger/rr/wiki/Testimonials).\n\nrr development is sponsored by [Pernosco](https://pernos.co) and was originated by [Mozilla](https://www.mozilla.org).\n\n# System requirements\n\n* Linux kernel >= 4.7 (for support of `__WALL` in `waitid()`)\n  * rr 5.6.0 worked with kernel 3.11 (requiring `PTRACE_SETSIGMASK`)\n* rr currently requires either:\n  * An Intel CPU with [Nehalem](https://en.wikipedia.org/wiki/Nehalem_%28microarchitecture%29) (2010) or later microarchitecture.\n  * Certain AMD Zen or later processors (see https://github.com/rr-debugger/rr/wiki/Zen)\n  * Certain AArch64 microarchitectures (e.g. ARM Neoverse N1 or the Apple Silicon M-series)\n* Running in a VM guest is supported, as long as the VM supports virtualization of hardware performance counters. (VMware and KVM are known to work; Xen does not.)\n"
  },
  {
    "path": "Vagrantfile",
    "content": "# -*- mode: ruby -*-\n# vi: set ft=ruby :\n# Author: David Manouchehri\n\nVagrant.configure(\"2\") do |config|\n\tconfig.vm.box = \"bento/ubuntu-16.04\"\n\n\tconfig.vm.synced_folder \".\", \"/vagrant\", disabled: true\n\n\tconfig.vm.provision \"shell\", inline: <<-SHELL\n\t\tapt-get update\n\t\t# DEBIAN_FRONTEND=noninteractive apt-get -y upgrade\n\t\tDEBIAN_FRONTEND=noninteractive apt-get -y install ccache cmake make g++-multilib gdb pkg-config realpath python-pexpect manpages-dev git ninja-build capnproto libcapnp-dev zlib1g-dev jq\n\t\tapt-get clean\n\tSHELL\n\n\tconfig.vm.provision \"shell\", privileged: false, inline: <<-SHELL\n\t\tgit clone https://github.com/rr-debugger/rr.git\n\t\tcd rr\n\t\tmkdir obj\n\t\tcd obj\n\t\tcmake .. -DPYTHON_EXECUTABLE=/usr/bin/python\n\t\tmake -j8\n\t\tmake test\n\tSHELL\n\n\tconfig.vm.provision \"shell\", inline: <<-SHELL\n\t\tcd /home/vagrant/rr/obj/\n\t\tmake install\n\tSHELL\n\n\t%w(vmware_fusion vmware_workstation vmware_appcatalyst).each do |provider|\n\t\tconfig.vm.provider provider do |v|\n\t\t\tv.vmx[\"memsize\"] = \"4096\"\n\t\t\tv.vmx['vpmc.enable'] = 'true'\n\t\t\tv.vmx['vhv.enable'] = 'true'\n\t\t\tv.vmx['vvtd.enable'] = 'true'\n\t\t\tv.vmx['monitor_control.disable_hvsim_clusters'] = 'true'\n\t\t\tv.vmx['virtualHW.version'] = '14'\n\t\t\tv.vmx['ethernet0.virtualDev'] = 'vmxnet3'\n\t\tend\n\tend\nend\n"
  },
  {
    "path": "configure",
    "content": "#!/usr/bin/env bash\n\n# Helper to make |./configure && make| do what you expect.\ncmake .\n"
  },
  {
    "path": "include/rr/rr.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_H_\n#define RR_H_\n\n/**\n * rr tracees can write data to this special fd that they want\n * verified across record/replay.  When it's written in recording, rr\n * saves the data.  During replay, the data are checked against the\n * recorded data.\n *\n * Tracees using this interface should take care that the buffers\n * storing the data are either not racy, or are synchronized by the\n * tracee.\n *\n * To simplify things, we make this a valid fd opened to /dev/null during\n * recording.\n *\n * Tracees may close this fd, or dup() something over it, etc. If that happens,\n * it will lose its magical properties.\n */\n#define RR_MAGIC_SAVE_DATA_FD 999\n\n/**\n * Tracees use this fd to send other fds to rr.\n * This is only set up during recording.\n * Only the outermost rr uses this. Inner rr replays will use a different fd.\n */\n#define RR_RESERVED_SOCKET_FD 1001\n\n/**\n * The preferred fd that rr uses to control tracee desched. Some software\n * (e.g. the chromium IPC code) wants to have the first few fds all to itself,\n * so we need to stay above some floor. Tracee close()es of the fd that is\n * actually assigned will be silently ignored, and tracee dup()s to that fd will\n * fail with EBADF.\n */\n#define RR_DESCHED_EVENT_FLOOR_FD 100\n\n#endif /* RR_H_ */\n"
  },
  {
    "path": "release-process/README.md",
    "content": "# Setting up AWS-based rr release testing\n\n* Create an AWS account.\n* Switch to the `us-east-2` (Ohio) region. The AMI IDs under `distro-configs` are all for the `us-east-2` region so this region must be used.\n* Use the EC2 console to create a keypair named `rr-testing`. This will download a file called `rr-testing.pem` containing the private key; move it somewhere safe and `chmod go-r <path>/rr-testing.pem` to make ssh happy.\n* Install `boto3` locally, e.g. using `pip install boto3`.\n* Install `aws-cli` locally, e.g. using [these instructions](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html).\n* Set `AWS_DEFAULT_REGION=us-east-2`, `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY` in your environment.\n* Create AWS resources using `aws cloudformation create-stack --stack-name rr-testing --template-body file://path/to/rr-testing-cloud-formation.json`.\n  * In the future, use `aws cloudformation update-stack  --stack-name rr-testing --template-body file://path/to/rr-testing-cloud-formation.json` to update when that configuration file changes.\n\n# Preparing a release\n\nIf you want to support any new distro versions, add files to `release-process/distro-configs`. Likewise remove any config files for distro versions no longer supported. Make sure to commit all changes to the local `master` branch before runnging `prepare-release.py`. Then:\n```\nrelease-process/prepare-release.py <major>.<minor>.0 <path>/rr-testing.pem\n```\nThis will (re)create a `release` branch in Github, then start a number of EC2 VMs for testing and packaging. When a VM successfully completes its work, you will see lines like\n```\nTests succeeded for centos9 arm64\n```\nWhen a VM fails, you will see something like\n```\nTests failed (VM kept): see /tmp/rr-release-logs/debian12.arm64\n```\nThe output log should help diagnose the problem. At the end of the log is an SSH command you can use to log into the VM for further debugging. Make sure to shut down any failing VMs when you're done, either using `sudo shutdown now` in an SSH session, or from the AWS EC2 console.\n\nRepeat until there are no more failures or any failures are ignorable (e.g. due to [#3607](https://github.com/rr-debugger/rr/issues/3607)). The built packages will be in `/tmp/rr-dist`; there should be two `.deb`s, two `.rpm`s, and two `.tar.gz`s.\n\n# Completing the release\n\n- [ ] Cherry-pick `release` to `master` and update tag: `git cherry-pick release; git tag -f <major>.<minor>.0` (Not sure why the tag needs to be updated...)\n- [ ] Delete the local and remote release branches: `git branch -d release; git push origin -d release`\n- [ ] Push changes to Github: `git push origin; git push --tags origin`. Once this is done there is no turning back!\n- [ ] [Create release and upload packages](https://github.com/mozilla/rr/releases) from `/tmp/rr-dist`\n- [ ] Update gh-pages: `./scripts/update-gh-pages.sh && git push origin`\n- [ ] Update [News wiki page](https://github.com/mozilla/rr/wiki/News)\n- [ ] Post to [rr-devel mailing list](mailto:rr-devel@googlegroups.com).\n\n# Testing a specific distro/CPU configuration\n\nThe `release-process/test-system.py` script can be used to start an AWS EC2 VM to test a specific distro version and CPU combination. E.g.\n```\nrelease-process/test-system.py --keep-vm release-process/distro-configs/centos9.json arm64 ~/rr-testing.pem >& /tmp/output\n```\nThis will start the VM, build rr, and run tests. Whether or not the tests succed, the VM will keep running and `/tmp/output` will end with an SSH command to log into the VM --- very handy for testing new distro versions or just running rr tests on a beefy machine. `test-system.py` has various options for customizing the instance type etc.\n\nThis is helpful for debugging intermittent rr test failures. For example, in a VM, you can run\n```\ncd ~/rr/src/test\nfor i in `seq 1 100`; do bash cont_race.run & done\n```\nto run 100 parallel instances of the `cont_race` test. If that doesn't show your bug, try 1000 instances instead. Running instances in parallel stresses thread scheduling and exposes more bugs.\n"
  },
  {
    "path": "release-process/distro-configs/centos9.json",
    "content": "{\n  \"name\": \"CentOS Stream 9\",\n  \"ami_owner\": \"125523088429\",\n  \"ami_name_pattern\": \"CentOS Stream 9 *\",\n  \"user\": \"ec2-user\",\n  \"archs\": [\"x86_64\", \"arm64\"],\n  \"staticlibs\": false,\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"sudo dnf config-manager --set-enabled crb\",\n    \"sudo dnf install -y epel-release epel-next-release\",\n    \"sudo dnf update -y\"\n  ],\n  \"install_build_deps\": \"sudo dnf install -y rpm ccache cmake gcc gcc-c++ gdb lldb glibc-devel libstdc++-devel zlib-devel git python3 python3-pexpect rpm-build ninja-build capnproto capnproto-libs capnproto-devel libzstd libzstd-devel jq\",\n  \"install_build_deps_x86_64\": \"sudo dnf install -y glibc-devel.i686 libstdc++-devel.i686\",\n  \"install_app_test_deps\": \"sudo dnf install -y gtk3 dbus-glib xorg-x11-utils gnutls-devel libacl-devel openldap-devel tigervnc-server-minimal curl tar bzip2 libreoffice-writer\",\n  \"exclude_tests_arm64\": [\"when.*\"]\n}\n"
  },
  {
    "path": "release-process/distro-configs/debian11.json",
    "content": "{\n  \"name\": \"Debian 11\",\n  \"ami_owner\": \"136693071363\",\n  \"ami_name_pattern\": \"debian-11-*\",\n  \"user\": \"admin\",\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"export DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFNEW=1\",\n    \"sudo -E apt-get update -y\",\n    \"sudo -E apt-get dist-upgrade -f -y\"\n  ],\n  \"install_build_deps\": [\n    \"sudo -E apt-get install -y locales-all rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb-16 python3-pexpect libzstd1 libzstd-dev jq\",\n    \"sudo update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-16 50\"\n  ],\n  \"install_build_deps_x86_64\": \"sudo -E apt-get install -y g++-multilib\",\n  \"install_app_test_deps\": \"sudo -E apt-get install -y tightvncserver xtightvncviewer curl tar bzip2 libdbus-glib-1-2 libreoffice\"\n}\n"
  },
  {
    "path": "release-process/distro-configs/debian12.json",
    "content": "{\n  \"name\": \"Debian 12\",\n  \"ami_owner\": \"136693071363\",\n  \"ami_name_pattern\": \"debian-12-*\",\n  \"user\": \"admin\",\n  \"archs\": [\"x86_64\", \"arm64\"],\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"export DEBIAN_FRONTEND=noninteractive UCF_FORCE_CONFNEW=1\",\n    \"sudo -E apt-get update -y\",\n    \"sudo -E apt-get dist-upgrade -f -y\"\n  ],\n  \"install_build_deps\": [\n    \"sudo -E apt-get install -y locales-all rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev-is-python3 libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb-16 python3-pexpect libzstd1 libzstd-dev jq\",\n    \"sudo update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-16 50\"\n  ],\n  \"install_build_deps_x86_64\": \"sudo -E apt-get install -y g++-multilib\",\n  \"install_app_test_deps\": \"sudo -E apt-get install -y tightvncserver xtightvncviewer curl tar bzip2 libdbus-glib-1-2 libreoffice\"\n}\n"
  },
  {
    "path": "release-process/distro-configs/ubuntu20-lts.json",
    "content": "{\n  \"name\": \"Ubuntu 20.04 LTS\",\n  \"ami_owner\": \"099720109477\",\n  \"ami_name_pattern\": \"ubuntu/images/hvm-ssd/ubuntu-focal-20.04-*\",\n  \"user\": \"ubuntu\",\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"sudo apt-get update -y\",\n    \"sudo apt-get dist-upgrade -f -y\"\n  ],\n  \"install_build_deps\": [\n    \"sudo apt-get install -y rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb-18 python3-pexpect libzstd1 libzstd-dev jq\",\n    \"sudo update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-18 50\"\n  ],\n  \"install_build_deps_x86_64\": \"sudo apt-get install -y g++-multilib\",\n  \"install_app_test_deps\": \"sudo apt-get install -y tightvncserver xtightvncviewer curl tar bzip2 libdbus-glib-1-2 libreoffice\",\n  \"exclude_tests\": [\"x86/pkeys.*\"]\n}\n"
  },
  {
    "path": "release-process/distro-configs/ubuntu22-lts.json",
    "content": "{\n  \"name\": \"Ubuntu 22.04 LTS\",\n  \"ami_owner\": \"099720109477\",\n  \"ami_name_pattern\": \"ubuntu/images/hvm-ssd/ubuntu-jammy-22.04-*\",\n  \"user\": \"ubuntu\",\n  \"archs\": [\"x86_64\", \"arm64\"],\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"sudo apt-get update -y\",\n    \"sudo apt-get dist-upgrade -f -y\"\n  ],\n  \"install_build_deps\": [\n    \"sudo apt-get install -y rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev-is-python3 libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb-15 python3-pexpect libzstd1 libzstd-dev jq\",\n    \"sudo update-alternatives --install /usr/bin/lldb lldb /usr/bin/lldb-15 50\",\n    \"export PYTHONPATH=\\\"/usr/lib/llvm-15/lib/python3.10/dist-packages/:$PYTHONPATH\\\"\"\n  ],\n  \"install_build_deps_x86_64\": \"sudo apt-get install -y g++-multilib\",\n  \"install_app_test_deps\": \"sudo apt-get install -y tightvncserver xtightvncviewer curl tar bzip2 libdbus-glib-1-2 libreoffice\"\n}\n"
  },
  {
    "path": "release-process/distro-configs/ubuntu24-lts.json",
    "content": "{\n  \"name\": \"Ubuntu 24.04 LTS\",\n  \"ami_owner\": \"099720109477\",\n  \"ami_name_pattern\": \"ubuntu/images/hvm-ssd-gp3/ubuntu-noble-24.04-*\",\n  \"user\": \"ubuntu\",\n  \"archs\": [\"x86_64\", \"arm64\"],\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"sudo apt-get update -y\",\n    \"sudo apt-get dist-upgrade -f -y\"\n  ],\n  \"install_build_deps\": \"sudo apt-get install -y rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev-is-python3 libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb python3-pexpect libzstd1 libzstd-dev jq\",\n  \"install_build_deps_x86_64\": \"sudo apt-get install -y g++-multilib\",\n  \"install_app_test_deps\": \"sudo apt-get install -y tightvncserver xtightvncviewer curl tar bzip2 libdbus-glib-1-2 libreoffice\"\n}\n"
  },
  {
    "path": "release-process/distro-configs/ubuntu24.10.json",
    "content": "{\n  \"name\": \"Ubuntu 24.10\",\n  \"ami_owner\": \"099720109477\",\n  \"ami_name_pattern\": \"ubuntu/images/hvm-ssd-gp3/ubuntu-oracular-24.10-*\",\n  \"user\": \"ubuntu\",\n  \"archs\": [\"x86_64\"],\n  \"setup_commands\": [\n    \"cloud-init status --wait\",\n    \"sudo apt-get update -y\",\n    \"sudo apt-get dist-upgrade -f -y\"\n  ],\n  \"install_build_deps\": \"sudo apt-get install -y rpm ccache cmake g++ pkg-config zlib1g-dev git python-dev-is-python3 libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb python3-pexpect libzstd1 libzstd-dev jq\",\n  \"install_build_deps_x86_64\": \"sudo apt-get install -y g++-multilib\",\n  \"install_app_test_deps\": \"sudo apt-get install -y tightvncserver xtightvncviewer curl tar bzip2 libdbus-glib-1-2 libreoffice\"\n}\n"
  },
  {
    "path": "release-process/prepare-release.py",
    "content": "#!/usr/bin/python3\n\nimport argparse\nimport glob\nimport json\nimport os\nimport re\nimport subprocess\nimport sys\nimport time\n\n# These are where we build the release binaries. They should be as old as possible\n# while still supported. Update these when the distro release is no longer supported.\ndist_packaging = {\n    ('ubuntu20-lts', 'x86_64'): 'TGZ;DEB',\n    ('ubuntu22-lts', 'arm64'): 'TGZ;DEB',\n    ('centos9', 'x86_64'): 'RPM',\n    ('centos9', 'arm64'): 'RPM',\n}\n\nos.chdir(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))\n\nparser = argparse.ArgumentParser()\nparser.add_argument('version')\nparser.add_argument('keypair_pem_file')\nargs = parser.parse_args()\n\nversion_re = re.compile(r'(\\d+)\\.(\\d+)\\.(\\d+)')\nm = version_re.match(args.version)\nif not m:\n    raise ValueError('version must have three numeric components, got %s' % args.version)\nmajor = int(m.group(1))\nminor = int(m.group(2))\npatch = int(m.group(3))\nversion = '%d.%d.%d' % (major, minor, patch)\n\ndist_dir = '/tmp/rr-dist'\nlog_dir = '/tmp/rr-release-logs'\n\ndef check_call(args):\n    print('Running %s' % args)\n    subprocess.check_call(args)\n\ndef update_cmake(name, num):\n    check_call(['sed', '-i',\n        's/rr_VERSION_%s [0-9][0-9]*/rr_VERSION_%s %d/g' % (name, name, num),\n        'CMakeLists.txt'])\n\ndef prepare_branch():\n    output = subprocess.check_output(['git', 'status',\n        '--untracked-files=no', '--porcelain'], stderr=subprocess.STDOUT)\n    if output:\n        print('Uncommitted changes in git workspace, aborting', file=sys.stderr)\n        sys.exit(2)\n    check_call(['git', 'checkout', '-B', 'release', 'master'])\n    update_cmake('MAJOR', major)\n    update_cmake('MINOR', minor)\n    update_cmake('PATCH', patch)\n    check_call(['git', 'commit', '-a', '-m', 'Bump version to %s' % version])\n    check_call(['git', 'tag', '-f', version])\n    check_call(['git', 'push', '-f', '--set-upstream', 'origin', 'release'])\n    check_call(['git', 'checkout', 'master'])\n\ndef prepare_dirs():\n    check_call(['rm', '-rf', dist_dir, log_dir])\n    check_call(['mkdir', dist_dir, log_dir])\n\ndef output_file_name(distro_name, arch):\n    return os.path.join(log_dir, '%s.%s' % (distro_name, arch))\n\ndef has_line_starting(output_file, prefix):\n    with open(output_file, 'r') as f:\n        for line in f:\n            if line.startswith(prefix):\n                return True\n    return False\n\ndef start_vm(cmd, output_file):\n    with open(output_file, 'w') as f:\n        process = subprocess.Popen(cmd, stderr=subprocess.STDOUT, stdout=f)\n    while True:\n        time.sleep(1)\n        if process.poll() is not None:\n            if has_line_starting(output_file, 'botocore.exceptions.ClientError: An error occurred (VcpuLimitExceeded) '):\n                return None\n            return process\n        if has_line_starting(output_file, 'Started VM '):\n            return process\n\nCOLOR_SUCCESS = '\\033[92m'\nCOLOR_FAILURE = '\\033[91m'\nCOLOR_NORMAL = '\\033[0m'\n\ndef run_tests():\n    distro_files = glob.glob('release-process/distro-configs/*.json')\n    pending = []\n    for distro_file in sorted(distro_files):\n        distro_name = os.path.basename(distro_file).rsplit('.', 1)[0]\n        with open(distro_file, 'r') as f:\n            distro_config = json.load(f)\n        archs = distro_config['archs'] if 'archs' in distro_config else ['x86_64']\n        for arch in sorted(archs):\n            cmd = ['release-process/test-system.py', '--keep-vm-on-error',\n                '--git-revision', 'release',\n                distro_file, arch, args.keypair_pem_file]\n            generators = dist_packaging.get((distro_name, arch))\n            if generators is not None:\n                cmd += ['--dist-files-dir', dist_dir, '--cpack-generators', generators]\n            pending.append((distro_name, arch, cmd))\n    running = []\n    fail_count = 0\n    while pending or running:\n        while pending:\n            distro_name, arch, cmd = pending[0]\n            output_file = output_file_name(distro_name, arch)\n            process = start_vm(cmd, output_file)\n            if process:\n                pending.pop(0)\n                running.append((distro_name, arch, process))\n                print('Started %s %s' % (distro_name, arch))\n            else:\n                break\n        # If no exits are seen after 60 seconds, try to launch a new VM anyway.\n        for i in range(60):\n            ready_index = None\n            for running_index, (distro_name, arch, process) in enumerate(running):\n                if process.poll() is not None:\n                    ready_index = running_index\n                    break\n            if ready_index is not None:\n                distro_name, arch, process = running.pop(ready_index)\n                output_file = output_file_name(distro_name, arch)\n                vm_kept = has_line_starting(output_file, 'VM kept; ')\n                if process.returncode:\n                    print('%sTests failed%s: see %s%s' %\n                        (COLOR_FAILURE, ' (VM kept)' if vm_kept else '', output_file, COLOR_NORMAL), file=sys.stderr)\n                    fail_count += 1\n                else:\n                    print('%sTests succeeded for %s %s%s' % (COLOR_SUCCESS, distro_name, arch, COLOR_NORMAL))\n                break\n            time.sleep(1)\n    print('%d failures total' % fail_count)\n    if fail_count:\n        sys.exit(1)\n    else:\n        print('Dist files left in %s' % dist_dir)\n\nprepare_branch()\nprepare_dirs()\nrun_tests()\n"
  },
  {
    "path": "release-process/rr-testing-cloud-formation.json",
    "content": "{\n  \"AWSTemplateFormatVersion\" : \"2010-09-09\",\n  \"Resources\": {\n    \"SecurityGroup\": {\n      \"Type\": \"AWS::EC2::SecurityGroup\",\n      \"Properties\": {\n        \"GroupDescription\": \"rr testing security group\",\n        \"GroupName\": \"rr-testing\",\n        \"SecurityGroupIngress\" : [\n          {\n            \"IpProtocol\": \"tcp\",\n            \"FromPort\": 22,\n            \"ToPort\": 22,\n            \"CidrIp\": \"0.0.0.0/0\"\n          }\n        ]\n      }\n    }\n  }\n}\n"
  },
  {
    "path": "release-process/rr-testing.sh",
    "content": "# Bash script to build rr and run tests.\n#\n# Requires variables and functions to be set. See test-system.py.\n# $git_revision : git revision to check out, build and test\n# $staticlibs : TRUE or FALSE to build with static libs\n# $build_dist : 1 if we should build dist packages, 0 otherwise\n# $test_firefox : 1 to run firefox tests, 0 to skip\n# $ctest_options : options to pass to ctest, e.g to exclude certain tests\n# $cpack_generators : CPack generators to build dist\n# setup_commands : function to setup environment, e.g. 'apt update'\n# install_build_deps : function to install dependencies required to build rr\n# install_app_test_deps : function to install dependencies required by tests\n\nset -e # default to exiting on error\"\n\nuname -a\n\nsetup_commands\ninstall_build_deps\n\ninstall_app_test_deps & # job %1\n\n# Free up space before we (re)start\n\nrm -rf ~/rr || true\ngit clone https://github.com/rr-debugger/rr ~/rr\ncd ~/rr\ngit checkout $git_revision\n\nrm -rf ~/obj || true\nmkdir ~/obj\ncd ~/obj\ncmake -G Ninja -DCMAKE_BUILD_TYPE=RELEASE -Dstaticlibs=$staticlibs -Dstrip=TRUE -DCPACK_GENERATOR=$cpack_generators ../rr\nninja\n\n# Enable perf events for rr\necho 0 | sudo tee /proc/sys/kernel/perf_event_paranoid\n# Enable ptrace-attach to any process. This lets us get more data when tests fail.\necho 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope\n# Disable AppArmor restrictions on user namespaces, which our tests need to use\n(echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns) || true\nrm -rf /tmp/rr-* || true\nlet halfproc=`nproc`/2\nctest -j$halfproc --verbose $ctest_options\n    echo \"For some reason I cannot figure out, bash drops the first four characters from the line following ctest\"\n\n# Integration test deps are installed in parallel with our build.\n# Make sure that install has finished before running tests\nwait %1\n\nrm -rf ~/.local/share/rr/* || true\n\nfunction xvnc-runner { CMD=$1 EXPECT=$2\n  rm -f /tmp/xvnc /tmp/xvnc-client /tmp/xvnc-wininfo /tmp/xvnc-client-replay || true\n\n  Xvnc :9 > /tmp/xvnc 2>&1 &\n  for retries in `seq 1 60`; do\n    if grep -q \"Listening\" /tmp/xvnc; then\n      break\n    fi\n    if [[ $retries == 60 ]]; then\n      echo FAILED: too many retries of $CMD\n      exit 1\n    fi\n    sleep 1\n  done\n  DISPLAY=:9 ~/obj/bin/rr $CMD > /tmp/xvnc-client 2>&1 &\n  for retries in `seq 1 60`; do\n    DISPLAY=:9 xwininfo -tree -root > /tmp/xvnc-wininfo 2>&1\n    if grep -q \"$EXPECT\" /tmp/xvnc-wininfo; then\n      break\n    fi\n    if [[ $retries == 60 ]]; then\n      echo FAILED: too many retries of $CMD\n      exit 1\n    fi\n    sleep 1\n  done\n  # kill Xvnc\n  kill -9 %1\n  # wait for $CMD to exit. Since we killed the X server it may\n  # exit with a failure code.\n  wait %2 || true\n  ~/obj/bin/rr replay -a > /tmp/xvnc-client-replay 2>&1 || (echo \"FAILED: replay failed\"; exit 1)\n  diff /tmp/xvnc-client /tmp/xvnc-client-replay || (echo \"FAILED: replay differs\"; exit 1)\n  echo PASSED: $CMD\n}\n\nif [[ $test_firefox == 1 ]]; then\n  rm -rf /tmp/firefox /tmp/firefox-profile || true\n  mkdir /tmp/firefox-profile\n  ( cd /tmp; curl -L 'https://download.mozilla.org/?product=firefox-latest&os=linux64&lang=en-US' | tar -Jxf - )\n  xvnc-runner \"/tmp/firefox/firefox --profile /tmp/firefox-profile $HOME/rr/release-process/test-data/test.html\" \"rr Test Page\"\nfi\n\nif [[ $test_libreoffice == 1 ]]; then\n  rm -rf ~/.config/libreoffice || true\n  xvnc-runner \"libreoffice $HOME/rr/release-process/test-data/rr-test-doc.odt\" \"rr-test-doc.odt\"\nfi\n\nif [[ $build_dist != 0 ]]; then\n  ninja package\n  rm /tmp/dist || true\n  ln -s ~/obj/dist /tmp/dist\nfi\n"
  },
  {
    "path": "release-process/test-data/test.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<body>\n<p>Hello!\n<script>\ndocument.title = \"rr Test Page\";\n</script>\n"
  },
  {
    "path": "release-process/test-system.py",
    "content": "#!/usr/bin/python3\n\nimport argparse\nimport boto3\nfrom datetime import datetime\nimport json\nimport pathlib\nimport subprocess\nimport sys\nimport time\n\nparser = argparse.ArgumentParser()\nparser.add_argument('distro_config_json')\nparser.add_argument('architecture')\nparser.add_argument('keypair_pem_file')\nparser.add_argument('--cpack-generators', default='TGZ')\nparser.add_argument('--git-revision', default='master')\nparser.add_argument('--timeout', default=1200) # 20 minutes\nparser.add_argument('--machine-type')\nparser.add_argument('--keep-vm', action='store_true')\nparser.add_argument('--keep-vm-on-error', action='store_true')\nparser.add_argument('--dist-files-dir')\nargs = parser.parse_args()\n\nclass Ec2Vm:\n    def __init__(self, machine_type, architecture, distro_config, keypair_pem_file):\n        \"\"\"Start an EC2 VM using the latest available AMI.\n           If this completes without throwing an exception, then terminate()\n           should be called eventually (unless you want to keep the VM running).\"\"\"\n        self.distro_name = distro_config['name']\n        self.user = distro_config['user']\n        self.keypair_pem_file = keypair_pem_file\n        self.ssh_ready = False\n        self.ec2 = boto3.resource('ec2')\n        self.ec2_client = boto3.client('ec2')\n\n        # For some reason adding MaxResults here causes AWS\n        # to return no results in some cases :-(\n        response = self.ec2_client.describe_images(Owners=[distro_config['ami_owner']], Filters=[\n            {'Name': 'architecture', 'Values': [architecture]},\n            {'Name': 'name', 'Values': [distro_config['ami_name_pattern']]}\n        ])\n        images = response['Images']\n        if len(images) >= 1000:\n            raise Exception('Too many AMIs match filter')\n        if len(images) == 0:\n            raise Exception('No AMIs match filter')\n        latest_image = sorted(response['Images'],\n            key=lambda img: datetime.strptime(img['CreationDate'], '%Y-%m-%dT%H:%M:%S.%f%z').timestamp(),\n            reverse=True\n        )[0]\n        ami = latest_image['ImageId']\n        block_device = None\n        for mapping in latest_image['BlockDeviceMappings']:\n            if 'Ebs' in mapping:\n                if block_device is not None:\n                    raise Exception('Multiple block devices found')\n                block_device = mapping['DeviceName']\n        if block_device is None:\n            raise Exception('No block device found')\n        print('Found AMI %s created %s with block device %s'%(ami, latest_image['CreationDate'], block_device), file=sys.stderr)\n\n        tags = [{\n            'ResourceType': 'instance',\n            'Tags': [{'Key': 'Name', 'Value': \"rr-test %s %s\"%(self.distro_name, architecture)}]\n        }]\n        response = self.ec2.create_instances(ImageId=ami, InstanceType=machine_type,\n            KeyName='rr-testing', MinCount=1, MaxCount=1,\n            BlockDeviceMappings=[{'DeviceName': block_device, 'Ebs': {'VolumeSize': 32}}],\n            InstanceInitiatedShutdownBehavior='terminate',\n            SecurityGroups=['rr-testing'],\n            TagSpecifications=tags)\n        self.instance = response[0]\n        print('Starting VM %s \"%s\"'%(self.instance.id, self.distro_name), file=sys.stderr)\n\n    def wait_for_ssh(self):\n        \"\"\"Wait until the instance is ready to accept ssh commands.\"\"\"\n        self.instance.wait_until_running()\n        self.instance.reload()\n        print('Started VM %s \"%s\" at %s'%(self.instance.id, self.distro_name, self.instance.public_ip_address), file=sys.stderr)\n        for retries in range(60):\n            result = subprocess.run(self.ssh_command() + ['true'], stdin=subprocess.DEVNULL, stderr=subprocess.PIPE)\n            if result.returncode == 0:\n                self.ssh_ready = True\n                return\n            if (b'Connection refused' not in result.stderr and\n                b'reset by peer' not in result.stderr and\n                b'Connection timed out' not in result.stderr and\n                b'Unprivileged users are not permitted to log in yet' not in result.stderr):\n                raise Exception('SSH connection failed:\\n%s'%result.stderr.decode('utf-8'))\n            time.sleep(1)\n        raise Exception('Too many retries, cannot connect via SSH')\n\n    def ssh(self, cmd, input):\n        \"\"\"Run `cmd` (command + args list) via SSH and wait for it to finish.\n           Command stdout and stderr are echoed to our stdout/stderr.\n           If the command fails, throws an exception with the exit status.\n           Returns nothing.\"\"\"\n        full_cmd = self.ssh_command() + cmd\n        print('Running %s'%full_cmd, file=sys.stderr)\n        process = subprocess.Popen(full_cmd, stdin=subprocess.PIPE)\n        process.communicate(input=input, timeout=args.timeout)\n        if process.returncode != 0:\n            raise Exception('Command failed with %d'%process.returncode)\n\n    def scp_from(self, options, src, dst):\n        \"\"\"Copies files from remote `src` to local `dst`.\"\"\"\n        full_cmd = ['scp'] + self.ssh_options() + options + ['%s:%s'%(self.ssh_dest(), src), dst]\n        print('Running %s'%full_cmd, file=sys.stderr)\n        subprocess.check_call(full_cmd)\n\n    def ssh_command(self):\n        return ['ssh'] + self.ssh_options() + [self.ssh_dest()]\n\n    def ssh_options(self):\n        return ['-i', self.keypair_pem_file,\n                '-o', 'StrictHostKeyChecking=no',\n                # A broken agent config can stop SSH from working. Bypass that.\n                '-o', 'IdentityAgent=none',\n                '-o', 'BatchMode=yes',\n                '-o', 'ConnectTimeout=5',\n                '-o', 'IdentitiesOnly=yes']\n\n    def ssh_dest(self):\n        return '%s@%s'%(self.user, self.instance.public_ip_address)\n\n    def terminate(self):\n        response = self.instance.terminate()\n        if response['ResponseMetadata']['HTTPStatusCode'] != 200:\n            print('Terminating VM %s failed: %s'%(self.instance_id, response), file=sys.stderr)\n        self.instance.wait_until_terminated()\n\nwith open(args.distro_config_json, 'r') as f:\n    distro_config = json.load(f)\n\nwith pathlib.Path(__file__).with_name('rr-testing.sh').open('rb') as f:\n    rr_testing_script = f.read()\n\ndef get_config_lines(config_key):\n    entry = distro_config.get(config_key)\n    if isinstance(entry, str):\n        return [entry]\n    if isinstance(entry, list):\n        return entry\n    if entry is None:\n        return []\n    raise ValueError('Invalid config entry %s: %s' % (config_key, entry))\n\ndef get_config_lines_arch(config_key):\n    return get_config_lines(config_key) + get_config_lines('%s_%s'%(config_key, args.architecture))\n\ndef config_script_function(config_key):\n    lines = get_config_lines_arch(config_key)\n    return ('function %s {\\n%s\\n}' % (config_key, '\\n'.join(lines)))\n\nmachine_type = args.machine_type\nif not machine_type:\n    if args.architecture == 'x86_64':\n        machine_type = 'c5.9xlarge'\n    elif args.architecture == 'arm64':\n        machine_type = 'c6g.8xlarge'\n\nvm = Ec2Vm(machine_type, args.architecture, distro_config, args.keypair_pem_file)\nsuccess = False\ntry:\n    vm.wait_for_ssh()\n    exclude_tests = get_config_lines_arch('exclude_tests')\n    if args.architecture == 'arm64':\n        # Currently AWS Graviton instances have a high failure rate on the `rseq` test\n        # because of missed timer interrupts\n        exclude_tests += [\"rseq.*\"]\n    ctest_options = []\n    if exclude_tests:\n        ctest_options = ['-E', '|'.join(exclude_tests)]\n    full_script = '\\n'.join(\n        [\n            'set -x', # echo commands\n            config_script_function('setup_commands'),\n            config_script_function('install_build_deps'),\n            config_script_function('install_app_test_deps'),\n            'git_revision=\"%s\"'%args.git_revision,\n            'staticlibs=%s'%('TRUE' if distro_config.get('staticlibs', True) else 'FALSE'),\n            'build_dist=%d'%(1 if args.dist_files_dir is not None else 0),\n            # Firefox doesn't have release tarballs for Aarch64\n            'test_firefox=%d'%(1 if args.architecture == 'x86_64' else 0),\n            # libreoffice uses STREX\n            'test_libreoffice=%d'%(1 if args.architecture == 'x86_64' else 0),\n            'ctest_options=\"%s\"'%' '.join(c for c in ctest_options),\n            'cpack_generators=\"%s\"'%args.cpack_generators\n        ]).encode('utf-8') + b'\\n' + rr_testing_script\n    vm.ssh(['/bin/bash', '-s'], full_script)\n    if args.dist_files_dir is not None:\n        vm.scp_from(['-r'], '/tmp/dist/*', args.dist_files_dir)\n    success = True\nfinally:\n    if (not success and args.keep_vm_on_error) or args.keep_vm:\n        if vm.ssh_ready:\n            print('VM kept; connect with: %s'%(' '.join(vm.ssh_command())), file=sys.stderr)\n        else:\n            print('VM %s still starting up'%vm.instance.id)\n    else:\n        vm.terminate()\n"
  },
  {
    "path": "rr.spec",
    "content": "Buildroot: @CPACK_BINARY_DIR@/_CPack_Packages/@CPACK_SYSTEM_NAME@/RPM/@CPACK_PACKAGE_FILE_NAME@\nSummary:        Lightweight tool for recording and replaying execution of applications (trees of processes and threads)\nName:           @CPACK_PACKAGE_NAME@\nVersion:        @CPACK_PACKAGE_VERSION@\nRelease:        @CPACK_RPM_PACKAGE_RELEASE@\nLicense:        @CPACK_RPM_PACKAGE_LICENSE@\nGroup:          Development/Debuggers\nVendor:         @CPACK_PACKAGE_VENDOR@\nPrefix:         @CPACK_PACKAGING_INSTALL_PREFIX@\n@CPACK_RPM_PACKAGE_REQUIRES@\n\n%define _rpmfilename @CPACK_PACKAGE_FILE_NAME@.rpm\n%define _unpackaged_files_terminate_build 0\n \n%description\nrr is a lightweight tool for recording and replaying execution of applications (trees of processes and threads).  For more information, please visit\n\nhttp://rr-project.org\n \n# This is a shortcutted spec file generated by CMake RPM generator\n# we skip _install step because CPack does that for us.\n# We do only save CPack installed tree in _prepr\n# and then restore it in build.\n\n%files\n%defattr(-,root,root,-)\n@CPACK_PACKAGING_INSTALL_PREFIX@/lib64/*\n@CPACK_PACKAGING_INSTALL_PREFIX@/bin/rr\n@CPACK_PACKAGING_INSTALL_PREFIX@/bin/rr_exec_stub*\n@CPACK_PACKAGING_INSTALL_PREFIX@/bin/signal-rr-recording.sh\n@CPACK_PACKAGING_INSTALL_PREFIX@/share/rr/*.xml\n\n%changelog\n* Tue Jun 25 2013 Chris Jones <cjones@triton> - \n- Initial build.\n"
  },
  {
    "path": "scripts/checkpoint-visualizer.html",
    "content": "<!DOCTYPE HTML>\n<html>\n<body>\n<canvas width=\"1000\" height=\"50\" id=\"c\" style=\"border:1px solid black\"></canvas>\n<table style=\"margin:1em; border:1px solid black; width:90%\">\n  <thead style=\"font-weight:bold\"><tr><td>Checkpoint<td>Time<td>Time to next</thead>\n  <tbody id=\"t\"></tbody>\n</table>\n<script>\n/* This script simulates the algorithm of ReplayTimeline::update_reverse_exec_checkpoints\n   and visualizes the results.\n   In this script, the ideal inter-checkpoint interval is normalized to 1.\n*/\nvar checkpoint_interval_exponent = 2;\n\nvar checkpoints = [];\n\nfunction countCheckpointsAtOrAfter(start) {\n  var count = 0;\n  for (var i = 0; i < checkpoints.length; ++i) {\n    if (checkpoints[i] >= start) {\n      ++count;\n    }\n  }\n  return count;\n}\n\nfunction removeLastCheckpointInRange(x1, x2) {\n  var lastIndex = -1;\n  for (var i = 0; i < checkpoints.length; ++i) {\n    if (checkpoints[i] >= x1 && checkpoints[i] < x2) {\n      lastIndex = i;\n    }\n  }\n  if (lastIndex >= 0) {\n    checkpoints.splice(lastIndex, 1);\n  }\n}\n\nfunction discard_excess_checkpoints(now) {\n  var checkpoints_allowed = 0;\n  var checkpoints_in_range = 0;\n  var it = checkpoints.length - 1;\n  var checkpoints_to_delete = [];\n\n  for (var len = 1; ; len = checkpoint_interval_exponent*len) {\n    var start = now - len;\n    var tmp_it = it;\n    while (tmp_it >= 0 && checkpoints[tmp_it] >= start) {\n      ++checkpoints_in_range;\n      --tmp_it;\n    }\n    while (checkpoints_in_range > checkpoints_allowed) {\n      checkpoints_to_delete.push(it);\n      --checkpoints_in_range;\n      --it;\n    }\n    ++checkpoints_allowed;\n    it = tmp_it;\n    if (it < 0) {\n      break;\n    }\n  }\n\n  for (var i = 0; i < checkpoints_to_delete.length; ++i) {\n    checkpoints.splice(checkpoints_to_delete[i], 1);\n  }\n}\n\nfunction renderCheckpoints() {\n  var ctx = c.getContext('2d');\n  ctx.clearRect(0, 0, c.width, c.height);\n  ctx.fillStyle = \"lime\";\n  for (var i = 0; i < checkpoints.length; ++i) {\n    var x = Math.floor(checkpoints[i]);\n    ctx.fillRect(x, 0, 1, c.height);\n  }\n}\n\nvar next = 0;\n// Choose a random stopping point in the second half\n// of the canvas.\nvar stopAt = (1 + Math.random())*c.width/2;\n\nfunction step() {\n  if (next >= stopAt) {\n    var s = [];\n    for (var i = 0; i < checkpoints.length; ++i) {\n      s.push(\"<tr><td>\" + i + \"<td>\" + checkpoints[i] + \"<td>\" +\n        ((i < checkpoints.length - 1) ? checkpoints[i + 1] - checkpoints[i] : 0));\n    }\n    t.innerHTML = s.join('\\n');\n    return;\n  }\n  discard_excess_checkpoints(next);\n  checkpoints.push(next);\n  renderCheckpoints();\n  // Add some jitter to reflect the fact that during replay\n  // we'll usually stop a bit later than the inter-checkpoint\n  // threshold.\n  next += 1 + Math.random()*0.1;\n  setTimeout(step, 0);\n}\n\nstep();\n</script>\n"
  },
  {
    "path": "scripts/github-actions-CTestCostData.txt",
    "content": "check_environment 3 0.0164291\n64bit_child 3 0.337334\n64bit_child-no-syscallbuf 3 0.302363\n_llseek 3 0.157875\n_llseek-no-syscallbuf 3 0.158812\nabort 3 0.304707\nabort-no-syscallbuf 3 0.299669\naccept 3 0.284387\naccept-no-syscallbuf 3 0.239335\nacct 3 0.154535\nacct-no-syscallbuf 3 0.149707\nadjtimex 3 0.149192\nadjtimex-no-syscallbuf 3 0.150965\naio 3 0.162193\naio-no-syscallbuf 3 0.156213\nalarm 3 2.19231\nalarm-no-syscallbuf 3 2.36203\nalarm2 3 1.1351\nalarm2-no-syscallbuf 3 1.15334\nalsa_ioctl 3 0.161643\nalsa_ioctl-no-syscallbuf 3 0.156718\narch_prctl 3 0.15381\narch_prctl-no-syscallbuf 3 0.153508\nasync_segv_ignored 3 0.157473\nasync_segv_ignored-no-syscallbuf 3 0.145451\nat_threadexit 3 0.19424\nat_threadexit-no-syscallbuf 3 0.182429\nbad_ip 3 0.151295\nbad_ip-no-syscallbuf 3 0.161028\nbad_syscall 3 0.157744\nbad_syscall-no-syscallbuf 3 0.13592\nbarrier 3 0.320478\nbarrier-no-syscallbuf 3 0.315113\nbig_buffers 3 0.163305\nbig_buffers-no-syscallbuf 3 0.171716\nblock 3 9.33639\nblock-no-syscallbuf 3 9.37496\nblock_open 3 0.188278\nblock_open-no-syscallbuf 3 0.186365\nbpf 3 0.168066\nbpf-no-syscallbuf 3 0.158176\nbpf_map 3 0.159372\nbpf_map-no-syscallbuf 3 0.152375\nbrk 3 0.172667\nbrk-no-syscallbuf 3 0.21366\nbrk2 3 0.16919\nbrk2-no-syscallbuf 3 0.157624\ncapget 3 0.172001\ncapget-no-syscallbuf 3 0.159812\nchew_cpu 3 8.01593\nchew_cpu-no-syscallbuf 3 8.45056\nx86/chew_cpu_cpuid 3 0.659385\nx86/chew_cpu_cpuid-no-syscallbuf 3 0.208381\nchmod 3 0.165601\nchmod-no-syscallbuf 3 0.170718\nchown 3 0.224577\nchown-no-syscallbuf 3 0.217927\nclock 3 0.291529\nclock-no-syscallbuf 3 0.376562\nclock_adjtime 3 0.158049\nclock_adjtime-no-syscallbuf 3 0.160917\nclock_nanosleep 3 1.15919\nclock_nanosleep-no-syscallbuf 3 1.14622\nclock_time64 3 0.16596\nclock_time64-no-syscallbuf 3 0.145465\nclone 3 0.16978\nclone-no-syscallbuf 3 0.175969\nclone_bad_stack 3 0.250671\nclone_bad_stack-no-syscallbuf 3 0.242454\nclone_bad_tls 3 0.172232\nclone_bad_tls-no-syscallbuf 3 0.146773\nclone_cleartid_coredump 3 0.300219\nclone_cleartid_coredump-no-syscallbuf 3 0.256838\nclone_fail 3 0.15996\nclone_fail-no-syscallbuf 3 0.147497\nclone_file_range 3 0.186542\nclone_file_range-no-syscallbuf 3 0.163602\nclone_immediate_exit 3 0.170451\nclone_immediate_exit-no-syscallbuf 3 0.169469\nclone_newflags 3 0.185066\nclone_newflags-no-syscallbuf 3 0.921083\nclone_parent 3 0.171129\nclone_parent-no-syscallbuf 3 0.173956\nclone_untraced 3 0.174148\nclone_untraced-no-syscallbuf 3 0.176188\nclone_vfork_pidfd 3 0.154905\nclone_vfork_pidfd-no-syscallbuf 3 0.151696\ncloned_sigmask 3 0.240172\ncloned_sigmask-no-syscallbuf 3 0.24506\nconstructor 3 2.19692\nconstructor-no-syscallbuf 3 2.18588\ncopy_file_range 3 0.163762\ncopy_file_range-no-syscallbuf 3 0.165092\nx86/cpuid_same_state 3 0.147253\nx86/cpuid_same_state-no-syscallbuf 3 0.153602\ncreat_address_not_truncated 3 0.161669\ncreat_address_not_truncated-no-syscallbuf 3 0.155895\nx86/cross_arch 3 0.157302\nx86/cross_arch-no-syscallbuf 3 0.153614\ncwd_inaccessible 3 0.223587\ncwd_inaccessible-no-syscallbuf 3 0.196703\ndaemon 3 0.180253\ndaemon-no-syscallbuf 3 0.159867\ndesched_blocking_poll 3 0.169864\ndesched_blocking_poll-no-syscallbuf 3 0.157374\ndesched_sigkill 3 0.281728\ndesched_sigkill-no-syscallbuf 3 0.228313\ndetach_state 3 0.205698\ndetach_state-no-syscallbuf 3 0.193471\ndetach_threads 3 0.25549\ndetach_threads-no-syscallbuf 3 0.229942\ndetach_sigkill 3 0.179927\ndetach_sigkill-no-syscallbuf 3 0.188678\ndetach_sigkill_exit 3 0.18524\ndetach_sigkill_exit-no-syscallbuf 3 0.174088\ndeterministic_sigsys 3 0.270055\ndeterministic_sigsys-no-syscallbuf 3 0.249215\ndev_zero 3 0.144176\ndev_zero-no-syscallbuf 3 0.192823\ndirect 3 0.205225\ndirect-no-syscallbuf 3 0.165835\ndup 3 0.192603\ndup-no-syscallbuf 3 0.164489\ndoublesegv 3 0.381171\ndoublesegv-no-syscallbuf 3 0.312939\nepoll_create 3 0.166363\nepoll_create-no-syscallbuf 3 0.140522\nepoll_create1 3 0.153205\nepoll_create1-no-syscallbuf 3 0.153613\nepoll_edge 3 0.158166\nepoll_edge-no-syscallbuf 3 0.144885\nepoll_pwait_eintr_sigmask 3 2.17026\nepoll_pwait_eintr_sigmask-no-syscallbuf 3 2.18145\neventfd 3 0.15034\neventfd-no-syscallbuf 3 0.149446\nexec_flags 3 0.149154\nexec_flags-no-syscallbuf 3 0.160262\nexec_no_env 3 0.197531\nexec_no_env-no-syscallbuf 3 0.18554\nexec_self 3 0.209195\nexec_self-no-syscallbuf 3 0.200386\nexec_from_main_thread 3 0.240319\nexec_from_main_thread-no-syscallbuf 3 0.255829\nexec_from_other_thread 3 13.8722\nexec_from_other_thread-no-syscallbuf 3 8.111\nexec_stopsig 3 0.229359\nexec_stopsig-no-syscallbuf 3 0.278794\nexecveat 3 0.205381\nexecveat-no-syscallbuf 3 0.210941\nexit_with_syscallbuf_signal 3 0.205309\nexit_with_syscallbuf_signal-no-syscallbuf 3 0.15339\nfadvise 3 0.156232\nfadvise-no-syscallbuf 3 0.144128\nfanotify 3 0.15563\nfanotify-no-syscallbuf 3 0.15289\nfatal_init_signal 3 0.202159\nfatal_init_signal-no-syscallbuf 3 0.172656\nfatal_sigsegv_thread 3 3.10984\nfatal_sigsegv_thread-no-syscallbuf 3 3.33673\nx86/fault_in_code_page 3 0.17993\nx86/fault_in_code_page-no-syscallbuf 3 0.168079\nfcntl_dupfd 3 0.162022\nfcntl_dupfd-no-syscallbuf 3 0.175576\nfcntl_misc 3 0.165599\nfcntl_misc-no-syscallbuf 3 0.145983\nfcntl_notify 3 0.163588\nfcntl_notify-no-syscallbuf 3 0.154498\nfcntl_owner_ex 3 0.155885\nfcntl_owner_ex-no-syscallbuf 3 0.16322\nfcntl_rw_hints 3 0.161478\nfcntl_rw_hints-no-syscallbuf 3 0.1507\nfcntl_seals 3 0.157493\nfcntl_seals-no-syscallbuf 3 0.145734\nfcntl_sig 3 0.170472\nfcntl_sig-no-syscallbuf 3 0.152661\nfd_cleanup 3 0.169983\nfd_cleanup-no-syscallbuf 3 0.183182\nfd_tracking_across_threads 3 0.201\nfd_tracking_across_threads-no-syscallbuf 3 0.179575\nfds_clean 3 0.246435\nfds_clean-no-syscallbuf 3 0.223065\nflock 3 0.677845\nflock-no-syscallbuf 3 1.0678\nflock_ofd 3 0.213914\nflock_ofd-no-syscallbuf 3 0.580972\nflock2 3 0.158132\nflock2-no-syscallbuf 3 0.149122\nfork_brk 3 0.197026\nfork_brk-no-syscallbuf 3 0.147554\nfork_child_crash 3 0.237483\nfork_child_crash-no-syscallbuf 3 0.239962\nfork_many 3 1.14265\nfork_many-no-syscallbuf 3 0.631239\nfutex_exit_race 3 0.52669\nfutex_exit_race-no-syscallbuf 3 0.386538\nfutex_exit_race_sigsegv 3 0.512517\nfutex_exit_race_sigsegv-no-syscallbuf 3 0.401706\nfutex_pi 3 0.179632\nfutex_pi-no-syscallbuf 3 0.158569\nfutex_priorities 3 0.219008\nfutex_priorities-no-syscallbuf 3 0.174828\nfutex_requeue 3 1.17145\nfutex_requeue-no-syscallbuf 3 1.16684\ngcrypt_rdrand 3 0.161925\ngcrypt_rdrand-no-syscallbuf 3 0.152451\ngetcpu 3 0.190398\ngetcpu-no-syscallbuf 3 0.151586\ngetgroups 3 0.160673\ngetgroups-no-syscallbuf 3 0.159069\ngetpwnam 3 0.198918\ngetpwnam-no-syscallbuf 3 0.254073\ngetrandom 3 0.18004\ngetrandom-no-syscallbuf 3 0.166992\nsetitimer 3 0.190327\nsetitimer-no-syscallbuf 3 0.160196\ngetsid 3 0.162228\ngetsid-no-syscallbuf 3 0.157766\ngettimeofday 3 0.159695\ngettimeofday-no-syscallbuf 3 0.162379\ngrandchild_threads 3 0.189786\ngrandchild_threads-no-syscallbuf 3 0.175099\ngrandchild_threads_main_running 3 4.2474\ngrandchild_threads_main_running-no-syscallbuf 3 4.26134\ngrandchild_threads_thread_running 3 4.25645\ngrandchild_threads_thread_running-no-syscallbuf 3 4.24836\ngrandchild_threads_parent_alive 3 0.191652\ngrandchild_threads_parent_alive-no-syscallbuf 3 0.188965\nx86/hle 3 0.978571\nx86/hle-no-syscallbuf 3 0.900915\ninotify 3 0.177146\ninotify-no-syscallbuf 3 0.154308\nint3 3 0.15784\nint3-no-syscallbuf 3 0.142212\nintr_futex_wait_restart 3 1.73505\nintr_futex_wait_restart-no-syscallbuf 3 1.68099\nintr_poll 3 3.69626\nintr_poll-no-syscallbuf 3 3.65486\nintr_ppoll 3 21.3328\nintr_ppoll-no-syscallbuf 3 21.2959\nintr_pselect 3 9.15265\nintr_pselect-no-syscallbuf 3 9.18344\nintr_read_no_restart 3 1.35779\nintr_read_no_restart-no-syscallbuf 3 1.29708\nintr_read_restart 3 2.37985\nintr_read_restart-no-syscallbuf 3 2.39035\nintr_sleep 3 4.16267\nintr_sleep-no-syscallbuf 3 4.15123\nintr_sleep_no_restart 3 2.02373\nintr_sleep_no_restart-no-syscallbuf 3 1.77107\ninvalid_exec 3 0.158076\ninvalid_exec-no-syscallbuf 3 0.151837\ninvalid_fcntl 3 0.162009\ninvalid_fcntl-no-syscallbuf 3 0.146827\ninvalid_ioctl 3 0.163682\ninvalid_ioctl-no-syscallbuf 3 0.156615\nio 3 0.15664\nio-no-syscallbuf 3 0.148634\nio_uring 3 0.1553\nio_uring-no-syscallbuf 3 0.183143\nioctl 3 0.160556\nioctl-no-syscallbuf 3 0.151208\nioctl_blk 3 0.156395\nioctl_blk-no-syscallbuf 3 0.158194\nioctl_fb 3 0.167029\nioctl_fb-no-syscallbuf 3 0.162058\nioctl_fs 3 0.169586\nioctl_fs-no-syscallbuf 3 0.169723\nioctl_pty 3 0.19172\nioctl_pty-no-syscallbuf 3 0.17487\nioctl_sg 3 0.166832\nioctl_sg-no-syscallbuf 3 0.148805\nioctl_tty 3 0.273182\nioctl_tty-no-syscallbuf 3 0.181178\nioctl_vt 3 0.198363\nioctl_vt-no-syscallbuf 3 0.147784\nioprio 3 0.151776\nioprio-no-syscallbuf 3 0.159645\nx86/ioperm 3 0.16163\nx86/ioperm-no-syscallbuf 3 0.147295\nx86/iopl 3 0.161969\nx86/iopl-no-syscallbuf 3 0.157894\njoin_threads 3 4.08561\njoin_threads-no-syscallbuf 3 3.21145\njoystick 3 0.148518\njoystick-no-syscallbuf 3 0.168141\nkcmp 3 0.174444\nkcmp-no-syscallbuf 3 0.15277\nkeyctl 3 0.189017\nkeyctl-no-syscallbuf 3 0.159288\nkill_newborn 3 0.361927\nkill_newborn-no-syscallbuf 3 0.305505\nkill_ptracee 3 1.28076\nkill_ptracee-no-syscallbuf 3 1.25036\nlarge_hole 3 0.16602\nlarge_hole-no-syscallbuf 3 0.153725\nlarge_write_deadlock 3 0.181911\nlarge_write_deadlock-no-syscallbuf 3 0.17404\nlegacy_ugid 3 0.1513\nlegacy_ugid-no-syscallbuf 3 0.157001\nx86/lsl 3 0.154411\nx86/lsl-no-syscallbuf 3 0.148669\nmadvise 3 0.166297\nmadvise-no-syscallbuf 3 0.173114\nmadvise_free 3 0.174214\nmadvise_free-no-syscallbuf 3 0.156153\nmadvise_wipeonfork 3 3.66742\nmadvise_wipeonfork-no-syscallbuf 3 0.269445\nmap_fixed 3 0.151788\nmap_fixed-no-syscallbuf 3 0.16034\nmap_shared_syscall 3 0.165261\nmap_shared_syscall-no-syscallbuf 3 0.154912\nmembarrier 3 0.193292\nmembarrier-no-syscallbuf 3 0.192042\nmemfd_create 3 0.16205\nmemfd_create-no-syscallbuf 3 0.150445\nmemfd_create_shared 3 0.184875\nmemfd_create_shared-no-syscallbuf 3 0.152934\nmemfd_create_shared_huge 3 0.166387\nmemfd_create_shared_huge-no-syscallbuf 3 0.183357\nmincore 3 0.161753\nmincore-no-syscallbuf 3 0.166001\nmknod 3 0.164454\nmknod-no-syscallbuf 3 0.16799\nmlock 3 0.157979\nmlock-no-syscallbuf 3 0.150461\nmmap_adjacent_to_rr_usage 3 0.164043\nmmap_adjacent_to_rr_usage-no-syscallbuf 3 0.170133\nmmap_private 3 1.05677\nmmap_private-no-syscallbuf 3 1.00645\nmmap_private_grow_under_map 3 0.173552\nmmap_private_grow_under_map-no-syscallbuf 3 0.142529\nmmap_recycle 3 0.182601\nmmap_recycle-no-syscallbuf 3 0.201383\nmmap_ro 3 0.163455\nmmap_ro-no-syscallbuf 3 0.150009\nmmap_self_maps_shared 3 0.209532\nmmap_self_maps_shared-no-syscallbuf 3 0.252583\nmmap_shared 3 0.178129\nmmap_shared-no-syscallbuf 3 0.188647\nmmap_shared_dev_zero 3 0.179758\nmmap_shared_dev_zero-no-syscallbuf 3 0.158756\nmmap_shared_grow 3 0.158899\nmmap_shared_grow-no-syscallbuf 3 0.155628\nmmap_shared_grow_under_map 3 0.17396\nmmap_shared_grow_under_map-no-syscallbuf 3 0.149174\nmmap_shared_multiple 3 0.169186\nmmap_shared_multiple-no-syscallbuf 3 0.14368\nmmap_shared_subpage 3 0.190767\nmmap_shared_subpage-no-syscallbuf 3 0.197527\nmmap_shared_write 3 6.98721\nmmap_shared_write-no-syscallbuf 3 7.85066\nmmap_shared_write_fork 3 0.221389\nmmap_shared_write_fork-no-syscallbuf 3 2.86303\nmmap_short_file 3 0.176901\nmmap_short_file-no-syscallbuf 3 0.155923\nmmap_write_complex 3 0.175376\nmmap_write_complex-no-syscallbuf 3 0.157194\nmmap_zero_size_fd 3 0.160154\nmmap_zero_size_fd-no-syscallbuf 3 0.147295\nx86/modify_ldt 3 0.163115\nx86/modify_ldt-no-syscallbuf 3 0.155589\nmount_ns_exec 3 0.223752\nmount_ns_exec-no-syscallbuf 3 0.224786\nmount_ns_exec2 3 0.227892\nmount_ns_exec2-no-syscallbuf 3 0.238692\nmprotect 3 0.176637\nmprotect-no-syscallbuf 3 0.149591\nmprotect_heterogenous 3 0.17239\nmprotect_heterogenous-no-syscallbuf 3 0.161125\nmprotect_none 3 0.170764\nmprotect_none-no-syscallbuf 3 0.153895\nmprotect_stack 3 0.154884\nmprotect_stack-no-syscallbuf 3 0.166553\nmq 3 2.16\nmq-no-syscallbuf 3 2.1974\nmremap 3 2.05014\nmremap-no-syscallbuf 3 7.23566\nmremap_after_coalesce 3 0.163365\nmremap_after_coalesce-no-syscallbuf 3 0.186969\nmremap_grow 3 0.176338\nmremap_grow-no-syscallbuf 3 0.15289\nmremap_grow_shared 3 0.186728\nmremap_grow_shared-no-syscallbuf 3 0.15187\nmremap_non_page_size 3 0.171094\nmremap_non_page_size-no-syscallbuf 3 1.03439\nmremap_overwrite 3 0.156689\nmremap_overwrite-no-syscallbuf 3 0.146222\nmremap_private_grow_under_map 3 0.157212\nmremap_private_grow_under_map-no-syscallbuf 3 0.166445\nmremap_shrink 3 0.168334\nmremap_shrink-no-syscallbuf 3 0.149695\nmsg 3 1.71135\nmsg-no-syscallbuf 3 1.67623\nmsg_trunc 3 0.161656\nmsg_trunc-no-syscallbuf 3 0.166105\nmsync 3 1.04228\nmsync-no-syscallbuf 3 1.55702\nmtio 3 0.155943\nmtio-no-syscallbuf 3 0.162524\nmultiple_pending_signals 3 0.208215\nmultiple_pending_signals-no-syscallbuf 3 0.183328\nmultiple_pending_signals_sequential 3 0.198208\nmultiple_pending_signals_sequential-no-syscallbuf 3 0.208821\nmunmap_segv 3 0.170282\nmunmap_segv-no-syscallbuf 3 0.159075\nmunmap_discontinuous 3 0.16428\nmunmap_discontinuous-no-syscallbuf 3 0.150675\nnanosleep 3 1.15837\nnanosleep-no-syscallbuf 3 1.1456\nnetfilter 3 0.177477\nnetfilter-no-syscallbuf 3 0.228226\nnetlink_mmap_disable 3 0.159134\nnetlink_mmap_disable-no-syscallbuf 3 0.150545\nno_mask_timeslice 3 0.753243\nno_mask_timeslice-no-syscallbuf 3 0.65877\nnscd 3 0.161502\nnscd-no-syscallbuf 3 0.157484\nnuma 3 0.16366\nnuma-no-syscallbuf 3 0.170196\nx86/old_fork 3 0.160469\nx86/old_fork-no-syscallbuf 3 0.180753\norphan_process 3 0.18387\norphan_process-no-syscallbuf 3 0.183225\npacket_mmap_disable 3 0.163229\npacket_mmap_disable-no-syscallbuf 3 0.170774\npause 3 1.14168\npause-no-syscallbuf 3 1.15297\nperf_event 3 0.183064\nperf_event-no-syscallbuf 3 0.16078\npersonality 3 0.177953\npersonality-no-syscallbuf 3 0.170125\npid_ns_kill_child 3 0.381137\npid_ns_kill_child-no-syscallbuf 3 0.240087\npid_ns_kill_child_threads 3 0.20782\npid_ns_kill_child_threads-no-syscallbuf 3 0.19151\npid_ns_kill_child_zombie 3 0.234559\npid_ns_kill_child_zombie-no-syscallbuf 3 0.178648\npid_ns_kill_threads 3 0.250399\npid_ns_kill_threads-no-syscallbuf 3 0.204639\npid_ns_kill_threads_exit_wait 3 0.263656\npid_ns_kill_threads_exit_wait-no-syscallbuf 3 0.241576\npid_ns_reap 3 0.231407\npid_ns_reap-no-syscallbuf 3 0.219442\npid_ns_segv 3 0.247395\npid_ns_segv-no-syscallbuf 3 0.238687\npid_ns_shutdown 3 0.390584\npid_ns_shutdown-no-syscallbuf 3 0.358182\npidfd 3 0.20572\npidfd-no-syscallbuf 3 0.164093\nx86/pkeys 3 0.169784\nx86/pkeys-no-syscallbuf 3 0.140272\npoll_sig_race 3 2.89585\npoll_sig_race-no-syscallbuf 3 2.83986\nppoll 3 5.70976\nppoll-no-syscallbuf 3 5.71209\nprctl 3 0.182093\nprctl-no-syscallbuf 3 0.184639\nprctl_caps 3 0.461576\nprctl_caps-no-syscallbuf 3 0.364208\nprctl_deathsig 3 0.180646\nprctl_deathsig-no-syscallbuf 3 0.157487\nprctl_name 3 0.252168\nprctl_name-no-syscallbuf 3 0.243093\nprctl_short_name 3 0.182303\nprctl_short_name-no-syscallbuf 3 0.157695\nprctl_speculation_ctrl 3 0.168457\nprctl_speculation_ctrl-no-syscallbuf 3 0.145312\nx86/prctl_tsc 3 0.169962\nx86/prctl_tsc-no-syscallbuf 3 0.169196\nprivileged_net_ioctl 3 0.312798\nprivileged_net_ioctl-no-syscallbuf 3 0.35125\nproc_fds 3 0.853602\nproc_fds-no-syscallbuf 3 0.776133\nproc_mem 3 0.343661\nproc_mem-no-syscallbuf 3 0.313879\nprotect_rr_fds 3 4.2672\nprotect_rr_fds-no-syscallbuf 3 4.24387\nprw 3 0.154393\nprw-no-syscallbuf 3 0.178059\npthread_condvar_locking 3 0.168729\npthread_condvar_locking-no-syscallbuf 3 0.182665\npthread_mutex_timedlock 3 0.146394\npthread_mutex_timedlock-no-syscallbuf 3 0.157668\npthread_pi_mutex 3 0.172794\npthread_pi_mutex-no-syscallbuf 3 0.150446\npthread_rwlocks 3 0.18842\npthread_rwlocks-no-syscallbuf 3 0.171502\nx86/ptrace 3 0.203384\nx86/ptrace-no-syscallbuf 3 0.193072\nptrace_attach_null_status 3 0.216968\nptrace_attach_null_status-no-syscallbuf 3 0.214387\nptrace_attach_running 3 0.301554\nptrace_attach_running-no-syscallbuf 3 0.296038\nptrace_attach_sleeping 3 0.223261\nptrace_attach_sleeping-no-syscallbuf 3 0.195324\nptrace_attach_stopped 3 0.216737\nptrace_attach_stopped-no-syscallbuf 3 0.208754\nptrace_attach_thread_running 3 7.25312\nptrace_attach_thread_running-no-syscallbuf 3 8.20121\nptrace_breakpoint 3 0.192547\nptrace_breakpoint-no-syscallbuf 3 0.17809\nptrace_change_patched_syscall 3 0.183003\nptrace_change_patched_syscall-no-syscallbuf 3 0.17081\nx86/ptrace_debug_regs 3 0.175538\nx86/ptrace_debug_regs-no-syscallbuf 3 0.165851\nptrace_exec 3 0.281701\nptrace_exec-no-syscallbuf 3 0.273225\nx86/ptrace_exec32 3 0.163584\nx86/ptrace_exec32-no-syscallbuf 3 0.155955\nptrace_kill_grandtracee 3 0.178142\nptrace_kill_grandtracee-no-syscallbuf 3 0.187404\nx86/ptrace_tls 3 0.219246\nx86/ptrace_tls-no-syscallbuf 3 0.20432\nptrace_seize 3 0.178107\nptrace_seize-no-syscallbuf 3 0.169647\nptrace_sigchld_blocked 3 0.172059\nptrace_sigchld_blocked-no-syscallbuf 3 0.154022\nptrace_signals 3 0.270799\nptrace_signals-no-syscallbuf 3 0.232762\nptrace_singlestep 3 0.397147\nptrace_singlestep-no-syscallbuf 3 0.176721\nptrace_syscall 3 0.195\nptrace_syscall-no-syscallbuf 3 0.174687\nptrace_syscall_clone_untraced 3 0.231657\nptrace_syscall_clone_untraced-no-syscallbuf 3 0.242292\nx86/ptrace_sysemu 3 0.248957\nx86/ptrace_sysemu-no-syscallbuf 3 0.230749\nptrace_sysemu_syscall 3 0.201321\nptrace_sysemu_syscall-no-syscallbuf 3 0.170117\nptrace_trace_clone 3 0.21894\nptrace_trace_clone-no-syscallbuf 3 0.205261\nptrace_trace_exit 3 0.178731\nptrace_trace_exit-no-syscallbuf 3 0.174462\nptrace_traceme 3 0.202485\nptrace_traceme-no-syscallbuf 3 0.168764\nptracer_death 3 0.21575\nptracer_death-no-syscallbuf 3 0.205591\nptracer_death_multithread 3 0.42858\nptracer_death_multithread-no-syscallbuf 3 0.543963\nptracer_death_multithread_peer 3 0.409316\nptracer_death_multithread_peer-no-syscallbuf 3 0.411511\nquotactl 3 0.197055\nquotactl-no-syscallbuf 3 0.175854\nx86/rdtsc 3 0.23707\nx86/rdtsc-no-syscallbuf 3 0.221782\nread_nothing 3 7.95296\nread_nothing-no-syscallbuf 3 13.0242\nreaddir 3 0.164987\nreaddir-no-syscallbuf 3 0.159109\nread_large 3 0.409282\nread_large-no-syscallbuf 3 1.37766\nread_oversize 3 0.163473\nread_oversize-no-syscallbuf 3 0.157164\nreadlink 3 0.166481\nreadlink-no-syscallbuf 3 0.18727\nreadlinkat 3 0.162334\nreadlinkat-no-syscallbuf 3 0.171786\nreadv 3 0.176152\nreadv-no-syscallbuf 3 0.16353\nrecord_replay_subject 3 3.42196\nrecord_replay_subject-no-syscallbuf 3 3.41249\nrecvfrom 3 0.15454\nrecvfrom-no-syscallbuf 3 0.177744\nredzone_integrity 3 1.13301\nredzone_integrity-no-syscallbuf 3 1.13952\nrename 3 0.166925\nrename-no-syscallbuf 3 0.150449\nrlimit 3 0.173492\nrlimit-no-syscallbuf 3 0.155836\nrobust_futex 3 0.19713\nrobust_futex-no-syscallbuf 3 0.188571\nrusage 3 0.164429\nrusage-no-syscallbuf 3 0.147817\nsamask 3 0.302997\nsamask-no-syscallbuf 3 0.259254\nsave_data_fd 3 0.161685\nsave_data_fd-no-syscallbuf 3 0.151627\nsched_attr 3 0.161715\nsched_attr-no-syscallbuf 3 0.168602\nsched_setaffinity 3 0.166564\nsched_setaffinity-no-syscallbuf 3 0.15648\nsched_setparam 3 0.162107\nsched_setparam-no-syscallbuf 3 0.147661\nsched_yield 3 0.2494\nsched_yield-no-syscallbuf 3 0.227094\nsched_yield_to_lower_priority 3 0.174122\nsched_yield_to_lower_priority-no-syscallbuf 3 0.166403\nscm_rights 3 0.661961\nscm_rights-no-syscallbuf 3 0.663789\nscratch_read 3 0.176737\nscratch_read-no-syscallbuf 3 0.171718\nseccomp 3 0.191926\nseccomp-no-syscallbuf 3 0.183121\nseccomp_cloning 3 0.16685\nseccomp_cloning-no-syscallbuf 3 0.161844\nseccomp_clone_fail 3 0.156072\nseccomp_clone_fail-no-syscallbuf 3 0.157549\nseccomp_desched 3 0.203677\nseccomp_desched-no-syscallbuf 3 0.160223\nseccomp_kill_exit 3 0.177956\nseccomp_kill_exit-no-syscallbuf 3 0.16329\nseccomp_null 3 0.159922\nseccomp_null-no-syscallbuf 3 0.188436\nseccomp_sigsys_args 3 0.160948\nseccomp_sigsys_args-no-syscallbuf 3 0.164235\nseccomp_sigsys_sigtrap 3 0.167303\nseccomp_sigsys_sigtrap-no-syscallbuf 3 0.164632\nseccomp_sigsys_syscallbuf 3 0.158658\nseccomp_sigsys_syscallbuf-no-syscallbuf 3 0.179574\nseccomp_tsync 3 0.203706\nseccomp_tsync-no-syscallbuf 3 0.17357\nseccomp_veto_exec 3 0.19662\nseccomp_veto_exec-no-syscallbuf 3 0.159613\nself_shebang 3 0.193248\nself_shebang-no-syscallbuf 3 0.206473\nself_sigint 3 0.1518\nself_sigint-no-syscallbuf 3 0.148422\nsem 3 0.230406\nsem-no-syscallbuf 3 0.199575\nsend_block 3 0.245719\nsend_block-no-syscallbuf 3 1.87236\nsendfile 3 0.176642\nsendfile-no-syscallbuf 3 0.17185\nset_ptracer 3 0.151456\nset_ptracer-no-syscallbuf 3 0.152836\nset_tid_address 3 0.188306\nset_tid_address-no-syscallbuf 3 0.172786\nsetgid 3 0.160902\nsetgid-no-syscallbuf 3 0.141594\nsetgroups 3 0.158919\nsetgroups-no-syscallbuf 3 0.149756\nsetsid 3 0.164533\nsetsid-no-syscallbuf 3 0.161501\nsetuid 3 0.30755\nsetuid-no-syscallbuf 3 0.317326\nshared_exec 3 0.154033\nshared_exec-no-syscallbuf 3 0.155572\nshared_monitor 3 0.158261\nshared_monitor-no-syscallbuf 3 0.150617\nshared_offset 3 0.197663\nshared_offset-no-syscallbuf 3 0.150751\nshared_write 3 0.166272\nshared_write-no-syscallbuf 3 0.15558\nshm 3 0.207179\nshm-no-syscallbuf 3 0.204714\nshm_unmap 3 0.174612\nshm_unmap-no-syscallbuf 3 0.151011\nsigaction_old 3 0.169635\nsigaction_old-no-syscallbuf 3 0.186299\nsigaltstack 3 0.159728\nsigaltstack-no-syscallbuf 3 0.155618\nsigchld_interrupt_signal 3 4.37595\nsigchld_interrupt_signal-no-syscallbuf 3 4.00963\nsigcont 3 0.176276\nsigcont-no-syscallbuf 3 0.167049\nsighandler_bad_rsp_sigsegv 3 0.167042\nsighandler_bad_rsp_sigsegv-no-syscallbuf 3 0.149173\nsighandler_fork 3 0.232608\nsighandler_fork-no-syscallbuf 3 0.194239\nsighandler_mask 3 0.171254\nsighandler_mask-no-syscallbuf 3 0.160348\nsigill 3 0.169078\nsigill-no-syscallbuf 3 0.142355\nsignal_deferred 3 0.18936\nsignal_deferred-no-syscallbuf 3 0.170904\nsignal_during_preload_init 3 0.18183\nsignal_during_preload_init-no-syscallbuf 3 0.171621\nsignal_frame 3 0.171874\nsignal_frame-no-syscallbuf 3 0.162511\nsignal_unstoppable 3 0.177569\nsignal_unstoppable-no-syscallbuf 3 0.157658\nsignalfd 3 0.157376\nsignalfd-no-syscallbuf 3 0.161101\nsigprocmask 3 0.526391\nsigprocmask-no-syscallbuf 3 0.518456\nsigprocmask_ensure_delivery 3 0.187085\nsigprocmask_ensure_delivery-no-syscallbuf 3 0.183378\nsigprocmask_exec 3 0.209065\nsigprocmask_exec-no-syscallbuf 3 0.198225\nsigprocmask_evil 3 0.150119\nsigprocmask_evil-no-syscallbuf 3 0.152954\nsigprocmask_in_syscallbuf_sighandler 3 1.13988\nsigprocmask_in_syscallbuf_sighandler-no-syscallbuf 3 1.13529\nsigprocmask_rr_sigs 3 0.171017\nsigprocmask_rr_sigs-no-syscallbuf 3 0.160015\nsigprocmask_syscallbuf 3 0.172349\nsigprocmask_syscallbuf-no-syscallbuf 3 0.160637\nsigqueueinfo 3 0.160929\nsigqueueinfo-no-syscallbuf 3 0.187513\nx86/sigreturn 3 0.188428\nx86/sigreturn-no-syscallbuf 3 0.200912\nsigreturn_reg 3 0.15936\nsigreturn_reg-no-syscallbuf 3 0.195472\nsigreturnmask 3 0.301815\nsigreturnmask-no-syscallbuf 3 0.268609\nsigrt 3 0.261165\nsigrt-no-syscallbuf 3 0.298723\nsigstop 3 0.228819\nsigstop-no-syscallbuf 3 0.203024\nsigstop2 3 0.177842\nsigstop2-no-syscallbuf 3 0.154846\nsigsuspend 3 0.176223\nsigsuspend-no-syscallbuf 3 0.181212\nsigtrap 3 0.185501\nsigtrap-no-syscallbuf 3 0.181996\nsimple_threads_stress 3 2.10814\nsimple_threads_stress-no-syscallbuf 3 2.74932\nsioc 3 0.469445\nsioc-no-syscallbuf 3 0.596984\nsmall_holes 3 0.168045\nsmall_holes-no-syscallbuf 3 0.145796\nsock_names_opts 3 0.182547\nsock_names_opts-no-syscallbuf 3 0.180697\nspinlock_priorities 3 0.680331\nspinlock_priorities-no-syscallbuf 3 1.27508\nsplice 3 0.171734\nsplice-no-syscallbuf 3 0.152318\nstack_growth_after_syscallbuf 3 0.161991\nstack_growth_after_syscallbuf-no-syscallbuf 3 0.158776\nstack_growth_syscallbuf 3 0.266059\nstack_growth_syscallbuf-no-syscallbuf 3 9.337\nstack_growth_with_guard 3 0.180035\nstack_growth_with_guard-no-syscallbuf 3 0.162457\nstack_invalid 3 0.175009\nstack_invalid-no-syscallbuf 3 0.15628\nstack_overflow 3 0.235214\nstack_overflow-no-syscallbuf 3 3.59651\nstack_overflow_altstack 3 0.160196\nstack_overflow_altstack-no-syscallbuf 3 0.154725\nstack_overflow_with_guard 3 0.219329\nstack_overflow_with_guard-no-syscallbuf 3 3.49059\nstatfs 3 0.161696\nstatfs-no-syscallbuf 3 0.176756\nstatx 3 0.170974\nstatx-no-syscallbuf 3 0.152931\nstdout_child 3 0.205053\nstdout_child-no-syscallbuf 3 0.221371\nstdout_cloexec 3 0.228643\nstdout_cloexec-no-syscallbuf 3 0.195781\nstdout_dup 3 0.161649\nstdout_dup-no-syscallbuf 3 0.141799\nstdout_redirect 3 0.270862\nstdout_redirect-no-syscallbuf 3 0.21584\nswitch_read 3 0.677802\nswitch_read-no-syscallbuf 3 0.660996\nsymlink 3 0.16442\nsymlink-no-syscallbuf 3 0.173125\nsync 3 0.218387\nsync-no-syscallbuf 3 0.200264\nsync_file_range 3 0.161356\nsync_file_range-no-syscallbuf 3 0.195714\nsyscall_bp 3 0.157682\nsyscall_bp-no-syscallbuf 3 0.145953\nsyscall_in_writable_mem 3 0.158828\nsyscall_in_writable_mem-no-syscallbuf 3 0.162497\nsyscallbuf_signal_reset 3 0.1669\nsyscallbuf_signal_reset-no-syscallbuf 3 0.160377\nsyscallbuf_signal_blocking 3 0.17366\nsyscallbuf_signal_blocking-no-syscallbuf 3 0.169817\nsyscallbuf_sigstop 3 9.64068\nsyscallbuf_sigstop-no-syscallbuf 3 26.3563\nsyscallbuf_timeslice 3 0.232011\nsyscallbuf_timeslice-no-syscallbuf 3 3.40972\nsyscallbuf_timeslice2 3 0.262001\nsyscallbuf_timeslice2-no-syscallbuf 3 9.18104\nsysconf 3 0.177462\nsysconf-no-syscallbuf 3 0.148994\nsysctl 3 0.169718\nsysctl-no-syscallbuf 3 0.146148\nsysemu_singlestep 3 0.158838\nsysemu_singlestep-no-syscallbuf 3 0.14519\nx86/sysfs 3 0.203504\nx86/sysfs-no-syscallbuf 3 0.209395\nsysinfo 3 0.167864\nsysinfo-no-syscallbuf 3 0.156011\ntgkill 3 0.198617\ntgkill-no-syscallbuf 3 0.169099\nthread_yield 3 4.09239\nthread_yield-no-syscallbuf 3 3.31\ntimer 3 54.6266\ntimer-no-syscallbuf 3 50.1859\ntimerfd 3 0.281036\ntimerfd-no-syscallbuf 3 0.250613\ntimes 3 0.179322\ntimes-no-syscallbuf 3 0.14615\ntruncate_temp 3 0.179651\ntruncate_temp-no-syscallbuf 3 0.17779\ntun 3 0.22692\ntun-no-syscallbuf 3 0.193409\ntwo_signals_with_mask 3 0.174087\ntwo_signals_with_mask-no-syscallbuf 3 0.159943\nulimit_low 3 0.184641\nulimit_low-no-syscallbuf 3 0.168013\nuname 3 0.163994\nuname-no-syscallbuf 3 0.149448\nunexpected_exit 3 0.231308\nunexpected_exit-no-syscallbuf 3 0.425223\nunexpected_exit_execve 3 0.256596\nunexpected_exit_execve-no-syscallbuf 3 0.398299\nunexpected_exit_execve_twice 3 1.31064\nunexpected_exit_execve_twice-no-syscallbuf 3 1.38882\nunexpected_exit_pid_ns 3 0.5777\nunexpected_exit_pid_ns-no-syscallbuf 3 0.270752\nunjoined_thread 3 0.162801\nunjoined_thread-no-syscallbuf 3 0.15667\nunshare 3 0.301114\nunshare-no-syscallbuf 3 1.33806\nuserfaultfd 3 0.156784\nuserfaultfd-no-syscallbuf 3 0.158499\nutimes 3 0.163511\nutimes-no-syscallbuf 3 0.150974\nvdso_parts 3 0.154998\nvdso_parts-no-syscallbuf 3 0.146384\nvfork_flush 3 0.173198\nvfork_flush-no-syscallbuf 3 0.152217\nvfork_shared 3 0.216045\nvfork_shared-no-syscallbuf 3 0.152351\nvideo_capture 3 0.16015\nvideo_capture-no-syscallbuf 3 0.159067\nvm_readv_writev 3 0.178576\nvm_readv_writev-no-syscallbuf 3 0.175043\nvsyscall 3 0.172098\nvsyscall-no-syscallbuf 3 0.16576\nvsyscall_timeslice 3 0.165062\nvsyscall_timeslice-no-syscallbuf 3 0.186885\nx86/x87env 3 0.167093\nx86/x87env-no-syscallbuf 3 0.180754\nwait 3 0.211953\nwait-no-syscallbuf 3 0.164549\nwait_sigstop 3 0.21506\nwait_sigstop-no-syscallbuf 3 0.173565\nwrite_race 3 2.57581\nwrite_race-no-syscallbuf 3 1.75822\nwritev 3 0.253563\nwritev-no-syscallbuf 3 0.168006\nxattr 3 0.172238\nxattr-no-syscallbuf 3 0.170306\nzero_length_read 3 0.160153\nzero_length_read-no-syscallbuf 3 0.149279\nstd_random 3 0.201614\nstd_random-no-syscallbuf 3 0.221352\nunwind_rr_page 3 1.14505\nunwind_rr_page-no-syscallbuf 3 1.13666\nabort_nonmain 3 0.359039\nabort_nonmain-no-syscallbuf 3 0.330682\nalternate_thread_diversion 3 1.57744\nalternate_thread_diversion-no-syscallbuf 3 1.13474\nargs 3 0.177209\nargs-no-syscallbuf 3 0.147602\nasync_kill_with_syscallbuf 3 2.59776\nasync_kill_with_syscallbuf-no-syscallbuf 3 3.93823\nasync_kill_with_syscallbuf2 3 2.21036\nasync_kill_with_syscallbuf2-no-syscallbuf 3 2.22822\nasync_kill_with_threads 3 2.1719\nasync_kill_with_threads-no-syscallbuf 3 2.23957\nasync_kill_with_threads_main_running 3 2.21748\nasync_kill_with_threads_main_running-no-syscallbuf 3 2.23232\nasync_kill_with_threads_thread_running 3 6.17095\nasync_kill_with_threads_thread_running-no-syscallbuf 3 6.14075\nasync_segv 3 4.55141\nasync_segv-no-syscallbuf 3 4.53096\nasync_signal_syscalls 3 1.20161\nasync_signal_syscalls-no-syscallbuf 3 0.0266551\nasync_signal_syscalls2 3 1.33672\nasync_signal_syscalls2-no-syscallbuf 3 0.0215027\nasync_signal_syscalls_siginfo 3 1.16121\nasync_signal_syscalls_siginfo-no-syscallbuf 3 0.025899\nasync_usr1 3 4.6427\nasync_usr1-no-syscallbuf 3 4.34284\nblacklist 3 0.24007\nblacklist-no-syscallbuf 3 0.159517\nblock_clone_checkpoint 3 1.06659\nblock_clone_checkpoint-no-syscallbuf 3 1.1087\nblock_clone_interrupted 3 5.4597\nblock_clone_interrupted-no-syscallbuf 3 4.53533\nblock_clone_syscallbuf_overflow 3 3.26066\nblock_clone_syscallbuf_overflow-no-syscallbuf 3 6.11108\nblock_intr_sigchld 3 6.86856\nblock_intr_sigchld-no-syscallbuf 3 5.89219\nblocked_bad_ip 3 2.25961\nblocked_bad_ip-no-syscallbuf 3 6.46548\nblocked_sigill 3 0.361856\nblocked_sigill-no-syscallbuf 3 0.363938\nx86/blocked_sigsegv 3 0.351694\nx86/blocked_sigsegv-no-syscallbuf 3 0.310531\nbreakpoint 3 1.11305\nbreakpoint-no-syscallbuf 3 1.14492\nbreakpoint_conditions 3 0.93368\nbreakpoint_conditions-no-syscallbuf 3 0.967242\nbreakpoint_overlap 3 0.924194\nbreakpoint_overlap-no-syscallbuf 3 0.93391\ncall_function 3 0.901007\ncall_function-no-syscallbuf 3 0.87467\ncall_gettid 3 0.905643\ncall_gettid-no-syscallbuf 3 0.870804\ncheckpoint_dying_threads 3 0.915922\ncheckpoint_dying_threads-no-syscallbuf 3 0.873478\ncheckpoint_mixed_mode 3 0.990307\ncheckpoint_mixed_mode-no-syscallbuf 3 1.07708\nchecksum_sanity 3 2.40068\nchecksum_sanity-no-syscallbuf 3 1.53533\ncheck_lost_interrupts 3 2.24072\ncheck_lost_interrupts-no-syscallbuf 3 0.0208667\nclone_interruption 3 1.08289\nclone_interruption-no-syscallbuf 3 1.90038\nclone_vfork 3 0.267157\nclone_vfork-no-syscallbuf 3 0.229166\nconditional_breakpoint_calls 3 0.917675\nconditional_breakpoint_calls-no-syscallbuf 3 0.942403\nconditional_breakpoint_offload 3 66.8135\nconditional_breakpoint_offload-no-syscallbuf 3 63.8071\ncondvar_stress 3 19.5301\ncondvar_stress-no-syscallbuf 3 27.9413\ncont_race 3 12.5732\ncont_race-no-syscallbuf 3 40.7727\nx86/cpuid_singlestep 3 0.828577\nx86/cpuid_singlestep-no-syscallbuf 3 0.845506\ncrash 3 0.31033\ncrash-no-syscallbuf 3 0.297819\ncrash_in_function 3 2.74531\ncrash_in_function-no-syscallbuf 3 4.74481\ndaemon_read 3 0.269816\ndaemon_read-no-syscallbuf 3 0.21177\ndconf_mock 3 0.176625\ndconf_mock-no-syscallbuf 3 0.17023\ndev_tty 3 0.155365\ndev_tty-no-syscallbuf 3 0.138834\ndiversion_sigtrap 3 10.6187\ndiversion_sigtrap-no-syscallbuf 3 9.65374\ndiversion_syscall 3 1.04017\ndiversion_syscall-no-syscallbuf 3 1.023\ndlopen 3 5.85379\ndlopen-no-syscallbuf 3 4.56277\nearly_error 3 0.329303\nearly_error-no-syscallbuf 3 0.335078\nelapsed_time 3 1.84526\nelapsed_time-no-syscallbuf 3 1.82311\nexclusion_region 3 2.95212\nexclusion_region-no-syscallbuf 3 2.16854\nexec_failed 3 0.846901\nexec_failed-no-syscallbuf 3 0.845736\nexec_many 3 6.58017\nexec_many-no-syscallbuf 3 10.9563\nexecve_loop 3 6.68547\nexecve_loop-no-syscallbuf 3 4.94738\nexit_codes 3 0.364494\nexit_codes-no-syscallbuf 3 0.338858\nexit_group 3 0.167024\nexit_group-no-syscallbuf 3 0.171674\nexit_race 3 1.9038\nexit_race-no-syscallbuf 3 1.25688\nexit_status 3 0.114959\nexit_status-no-syscallbuf 3 0.104345\nx86/explicit_checkpoints 3 1.95774\nx86/explicit_checkpoints-no-syscallbuf 3 1.94198\nfd_limit 3 0.203426\nfd_limit-no-syscallbuf 3 0.987276\nfork_stress 3 1.69422\nfork_stress-no-syscallbuf 3 1.13269\nfork_syscalls 3 0.164541\nfork_syscalls-no-syscallbuf 3 0.198481\nfunction_calls 3 2.54722\nfunction_calls-no-syscallbuf 3 2.43375\nx86/fxregs 3 0.860057\nx86/fxregs-no-syscallbuf 3 0.870847\ngetcwd 3 0.148878\ngetcwd-no-syscallbuf 3 0.154948\ngdb_bogus_breakpoint 3 0.843596\ngdb_bogus_breakpoint-no-syscallbuf 3 0.856495\ngoto_event 3 3.06602\ngoto_event-no-syscallbuf 3 3.03297\nhello 3 0.174916\nhello-no-syscallbuf 3 0.154474\nhooks 3 0.850872\nhooks-no-syscallbuf 3 0.0219273\nignored_async_usr1 3 3.37766\nignored_async_usr1-no-syscallbuf 3 2.07633\nignored_sigsegv 3 0.382166\nignored_sigsegv-no-syscallbuf 3 0.358145\nignore_nested 3 0.290748\nignore_nested-no-syscallbuf 3 0.305353\nimmediate_restart 3 1.02683\nimmediate_restart-no-syscallbuf 3 1.0017\nx86/int3_ok 3 0.167423\nx86/int3_ok-no-syscallbuf 3 0.147515\ninterrupt 3 4.95536\ninterrupt-no-syscallbuf 3 4.72557\nintr_ptrace_decline 3 4.7439\nintr_ptrace_decline-no-syscallbuf 3 4.70112\ninvalid_interpreter 3 4.37543\ninvalid_interpreter-no-syscallbuf 3 3.48256\ninvalid_jump 3 2.54397\ninvalid_jump-no-syscallbuf 3 1.63359\njit_proc_mem 3 0.904904\njit_proc_mem-no-syscallbuf 3 0.883142\nlink 3 0.169285\nlink-no-syscallbuf 3 0.170742\nmadvise_dontfork 3 1.14195\nmadvise_dontfork-no-syscallbuf 3 1.0685\nmain_thread_exit 3 1.1676\nmain_thread_exit-no-syscallbuf 3 1.13967\nmany_yields 3 3.15188\nmany_yields-no-syscallbuf 3 2.78943\nmmap_fd_reuse_checkpoint 3 1.11664\nmmap_fd_reuse_checkpoint-no-syscallbuf 3 1.09184\nmmap_replace_most_mappings 3 1.77734\nmmap_replace_most_mappings-no-syscallbuf 3 1.84276\nmmap_shared_prot 3 1.06173\nmmap_shared_prot-no-syscallbuf 3 1.10953\nmmap_shared_write_exec_race 3 1.19321\nmmap_shared_write_exec_race-no-syscallbuf 3 3.79371\nmmap_tmpfs 3 0.173133\nmmap_tmpfs-no-syscallbuf 3 0.159476\nmmap_write 3 0.0216368\nmmap_write-no-syscallbuf 3 0.0215376\nmmap_write_private 3 0.288292\nmmap_write_private-no-syscallbuf 3 0.256622\nmorestack_unwind 1 0.810541\nmorestack_unwind-no-syscallbuf 1 0.0187404\nmprotect_growsdown 3 0.294224\nmprotect_growsdown-no-syscallbuf 3 0.268717\nmprotect_syscallbuf_overflow 3 0.281185\nmprotect_syscallbuf_overflow-no-syscallbuf 3 12.2115\nmutex_pi_stress 3 23.7823\nmutex_pi_stress-no-syscallbuf 3 27.247\nnested_detach_wait 3 0.50088\nnested_detach_wait-no-syscallbuf 3 0.510102\noverflow_branch_counter 3 2.81702\noverflow_branch_counter-no-syscallbuf 3 2.87377\npatch_page_end 3 0.1791\npatch_page_end-no-syscallbuf 3 0.0231666\nx86/patch_40_80_f6_81 3 0.170802\nx86/patch_40_80_f6_81-no-syscallbuf 3 0.021558\nperf_event_mmap 3 0.978108\nperf_event_mmap-no-syscallbuf 3 1.03341\npriority 3 0.16131\npriority-no-syscallbuf 3 0.157811\nptrace_remote_unmap 3 3.76436\nptrace_remote_unmap-no-syscallbuf 3 3.04355\nread_big_struct 3 0.891689\nread_big_struct-no-syscallbuf 3 0.890305\nremove_latest_trace 3 1.23464\nremove_latest_trace-no-syscallbuf 3 1.18878\nrestart_abnormal_exit 3 1.27785\nrestart_abnormal_exit-no-syscallbuf 3 1.25203\nreverse_continue_breakpoint 3 1.6634\nreverse_continue_breakpoint-no-syscallbuf 3 1.55189\nreverse_continue_multiprocess 3 10.3054\nreverse_continue_multiprocess-no-syscallbuf 3 9.46503\nreverse_continue_process_signal 3 2.79022\nreverse_continue_process_signal-no-syscallbuf 3 2.83602\nreverse_many_breakpoints 3 3.43429\nreverse_many_breakpoints-no-syscallbuf 3 3.17411\nreverse_step_long 3 5.2054\nreverse_step_long-no-syscallbuf 3 6.35501\nreverse_step_threads 3 2.90159\nreverse_step_threads-no-syscallbuf 3 3.05253\nreverse_step_threads_break 3 3.47602\nreverse_step_threads_break-no-syscallbuf 3 2.58121\nrr_ps 3 0.350603\nrr_ps-no-syscallbuf 3 0.303961\nrr_ps_ns 3 0.191974\nrr_ps_ns-no-syscallbuf 3 0.169622\nrseq 3 16.6959\nrseq-no-syscallbuf 3 16.5372\nsearch 3 0.89271\nsearch-no-syscallbuf 3 0.870175\nseccomp_blocks_rr 3 0.303424\nseccomp_blocks_rr-no-syscallbuf 3 0.151506\nseccomp_signals 3 2.24617\nseccomp_signals-no-syscallbuf 3 1.80499\nsegfault 3 0.167595\nsegfault-no-syscallbuf 3 0.158185\nshared_map 3 0.206508\nshared_map-no-syscallbuf 3 0.209229\nshared_persistent_file 3 1.118\nshared_persistent_file-no-syscallbuf 3 1.10357\nsignal_numbers 3 1.09917\nsignal_numbers-no-syscallbuf 3 1.09911\nsigprocmask_race 3 0.172178\nsigprocmask_race-no-syscallbuf 3 0.0254089\nsigprocmask_rr_sigs_nondefault 3 0.0987354\nsigprocmask_rr_sigs_nondefault-no-syscallbuf 3 0.0967041\nsimple 3 0.262466\nsimple-no-syscallbuf 3 0.236866\nx86/singlestep_pushf 3 0.857486\nx86/singlestep_pushf-no-syscallbuf 3 0.86649\nstack_growth 3 0.865849\nstack_growth-no-syscallbuf 3 0.862781\nstep_thread 3 2.19503\nstep_thread-no-syscallbuf 3 1.22219\nstrict_priorities 3 10.3645\nstrict_priorities-no-syscallbuf 3 11.1165\nx86/string_instructions 3 0.609023\nx86/string_instructions-no-syscallbuf 3 0.685759\nx86/string_instructions_async_signals 3 0.207032\nx86/string_instructions_async_signals-no-syscallbuf 3 47.6509\nx86/string_instructions_async_signals_shared 3 0.243325\nx86/string_instructions_async_signals_shared-no-syscallbuf 3 64.5042\nx86/string_instructions_multiwatch 3 0.902929\nx86/string_instructions_multiwatch-no-syscallbuf 3 0.863364\nx86/string_instructions_replay 3 13.1062\nx86/string_instructions_replay-no-syscallbuf 3 13.3725\nx86/string_instructions_singlestep_fastforward 3 11.3088\nx86/string_instructions_singlestep_fastforward-no-syscallbuf 3 10.5199\nx86/string_instructions_watch 3 0.894201\nx86/string_instructions_watch-no-syscallbuf 3 0.869626\nsyscallbuf_fd_disabling 3 0.23601\nsyscallbuf_fd_disabling-no-syscallbuf 3 0.210209\nsyscallbuf_signal_blocking_read 3 0.994903\nsyscallbuf_signal_blocking_read-no-syscallbuf 3 1.32862\nsysconf_onln 3 0.329179\nsysconf_onln-no-syscallbuf 3 0.301906\ntarget_fork 3 1.72084\ntarget_fork-no-syscallbuf 3 1.61481\ntarget_process 3 1.60957\ntarget_process-no-syscallbuf 3 1.47944\ntcp_sockets 3 0.142919\ntcp_sockets-no-syscallbuf 3 0.147933\nterm_nonmain 3 0.166076\nterm_nonmain-no-syscallbuf 3 0.186748\nterm_rr 3 4.21286\nterm_rr-no-syscallbuf 3 4.20073\nterm_trace_reset 3 0.213788\nterm_trace_reset-no-syscallbuf 3 0.197926\nterm_trace_syscall 3 0.222559\nterm_trace_syscall-no-syscallbuf 3 0.211105\nthread_exit_signal 3 3.06793\nthread_exit_signal-no-syscallbuf 3 3.15729\nthread_open_race 3 48.2834\nthread_open_race-no-syscallbuf 3 0.0215275\nthread_stress 3 18.203\nthread_stress-no-syscallbuf 3 19.9251\nthreaded_syscall_spam 3 1.19269\nthreaded_syscall_spam-no-syscallbuf 3 0.0218339\nthreads 3 1.20615\nthreads-no-syscallbuf 3 1.14746\ntls 3 0.90699\ntls-no-syscallbuf 3 0.881923\nttyname 3 0.150335\nttyname-no-syscallbuf 3 0.147432\nunexpected_stack_growth 3 6.57491\nunexpected_stack_growth-no-syscallbuf 3 1.01145\nuser_ignore_sig 3 0.167483\nuser_ignore_sig-no-syscallbuf 3 0.150179\nvdso_clock_gettime_stack 3 1.33203\nvdso_clock_gettime_stack-no-syscallbuf 3 0.0214651\nvdso_gettimeofday_stack 3 1.37839\nvdso_gettimeofday_stack-no-syscallbuf 3 0.0211004\nvdso_time_stack 3 1.11583\nvdso_time_stack-no-syscallbuf 3 0.0211016\nvfork 3 0.238179\nvfork-no-syscallbuf 3 0.216255\nvfork_read_clone_stress 3 2.13853\nvfork_read_clone_stress-no-syscallbuf 3 1.46609\nvsyscall_reverse_next 3 3.05977\nvsyscall_reverse_next-no-syscallbuf 3 2.77844\nwait_for_all 3 1.13809\nwait_for_all-no-syscallbuf 3 1.13027\nwatchpoint 3 1.36864\nwatchpoint-no-syscallbuf 3 1.41259\nwatchpoint_at_sched 3 1.2043\nwatchpoint_at_sched-no-syscallbuf 3 1.79064\nwatchpoint_before_signal 3 0.891807\nwatchpoint_before_signal-no-syscallbuf 3 0.857241\nwatchpoint_no_progress 3 2.28605\nwatchpoint_no_progress-no-syscallbuf 3 1.50392\nwatchpoint_size_change 3 0.891056\nwatchpoint_size_change-no-syscallbuf 3 0.887724\nwatchpoint_syscall 3 1.02153\nwatchpoint_syscall-no-syscallbuf 3 0.909816\nwatchpoint_unaligned 3 1.23545\nwatchpoint_unaligned-no-syscallbuf 3 1.21433\nasync_signal_syscalls_100 3 0.202603\nasync_signal_syscalls_100-no-syscallbuf 3 3.8296\nasync_signal_syscalls_1000 3 0.188268\nasync_signal_syscalls_1000-no-syscallbuf 3 3.62992\nbad_breakpoint 3 9.76737\nbad_breakpoint-no-syscallbuf 3 9.30115\nbreak_block 3 9.95194\nbreak_block-no-syscallbuf 3 9.95062\nbreak_clock 3 0.958868\nbreak_clock-no-syscallbuf 3 1.13506\nbreak_clone 3 0.842634\nbreak_clone-no-syscallbuf 3 0.83947\nbreak_exec 3 0.979672\nbreak_exec-no-syscallbuf 3 0.883294\nbreak_int3 3 0.838053\nbreak_int3-no-syscallbuf 3 0.817321\nbreak_mmap_private 3 2.21591\nbreak_mmap_private-no-syscallbuf 3 2.3374\nbreak_msg 3 2.32206\nbreak_msg-no-syscallbuf 3 2.30288\nx86/break_rdtsc 3 0.889362\nx86/break_rdtsc-no-syscallbuf 3 0.871792\nbreak_sigreturn 3 4.83707\nbreak_sigreturn-no-syscallbuf 3 4.82174\nbreak_sync_signal 3 0.85105\nbreak_sync_signal-no-syscallbuf 3 0.888775\nbreak_thread 3 0.960811\nbreak_thread-no-syscallbuf 3 0.937708\nbreak_time_slice 3 8.95734\nbreak_time_slice-no-syscallbuf 3 9.1059\nbreakpoint_consistent 3 0.853028\nbreakpoint_consistent-no-syscallbuf 3 0.843801\ncall_exit 3 1.17147\ncall_exit-no-syscallbuf 3 1.17408\ncheck_patched_pthread 3 2.07588\ncheck_patched_pthread-no-syscallbuf 3 1.8827\ncheckpoint_async_signal_syscalls_1000 3 3.29167\ncheckpoint_async_signal_syscalls_1000-no-syscallbuf 3 0.0219982\ncheckpoint_mmap_shared 3 23.8657\ncheckpoint_mmap_shared-no-syscallbuf 3 18.2314\ncheckpoint_prctl_name 3 33.8154\ncheckpoint_prctl_name-no-syscallbuf 3 31.0433\ncheckpoint_simple 3 11.4629\ncheckpoint_simple-no-syscallbuf 3 13.5317\nchecksum_sanity_noclone 3 2.28681\nchecksum_sanity_noclone-no-syscallbuf 3 1.70638\ncomm 3 0.634081\ncomm-no-syscallbuf 3 0.7202\ncont_signal 3 4.92468\ncont_signal-no-syscallbuf 3 4.92682\nx86/cpuid 3 1.06468\nx86/cpuid-no-syscallbuf 3 1.065\ndead_thread_target 3 1.16267\ndead_thread_target-no-syscallbuf 3 1.0941\ndesched_ticks 3 0.896582\ndesched_ticks-no-syscallbuf 3 0.021897\ndeliver_async_signal_during_syscalls 3 0.661812\ndeliver_async_signal_during_syscalls-no-syscallbuf 3 0.0206239\nenv_newline 3 0.155365\nenv_newline-no-syscallbuf 3 0.15244\nexec_deleted 3 0.154572\nexec_deleted-no-syscallbuf 3 0.141445\nexec_stop 3 0.927636\nexec_stop-no-syscallbuf 3 0.902712\nexecp 3 0.162819\nexecp-no-syscallbuf 3 0.152149\nexplicit_checkpoint_clone 3 1.09532\nexplicit_checkpoint_clone-no-syscallbuf 3 1.06678\nfile_name_newline 3 0.175127\nfile_name_newline-no-syscallbuf 3 0.170133\nfinal_sigkill 3 1.1112\nfinal_sigkill-no-syscallbuf 3 1.08854\nfirst_instruction 3 6.4099\nfirst_instruction-no-syscallbuf 3 5.80319\nfork_exec_info_thr 3 3.28546\nfork_exec_info_thr-no-syscallbuf 3 3.18561\nget_thread_list 3 1.07744\nget_thread_list-no-syscallbuf 3 1.07444\nhardlink_mmapped_files 3 2.20039\nhardlink_mmapped_files-no-syscallbuf 3 2.21085\nhbreak 3 0.923998\nhbreak-no-syscallbuf 3 0.984052\nmprotect_step 3 1.12762\nmprotect_step-no-syscallbuf 3 1.11766\nnested_detach 3 2.06587\nnested_detach-no-syscallbuf 3 2.05377\nnested_detach_kill 3 0.514043\nnested_detach_kill-no-syscallbuf 3 0.506464\nnested_release 3 0.351153\nnested_release-no-syscallbuf 3 0.286465\nparent_no_break_child_bkpt 3 2.25801\nparent_no_break_child_bkpt-no-syscallbuf 3 1.68964\nparent_no_stop_child_crash 3 3.8874\nparent_no_stop_child_crash-no-syscallbuf 3 3.06564\npost_exec_fpu_regs 3 0.625056\npost_exec_fpu_regs-no-syscallbuf 3 0.618626\nproc_maps 3 0.835174\nproc_maps-no-syscallbuf 3 0.875045\nread_bad_mem 3 0.852118\nread_bad_mem-no-syscallbuf 3 0.832199\nrecord_replay 3 135.637\nrecord_replay-no-syscallbuf 3 150.387\nremove_watchpoint 3 0.934846\nremove_watchpoint-no-syscallbuf 3 0.914737\nreplay_overlarge_event_number 3 0.166307\nreplay_overlarge_event_number-no-syscallbuf 3 0.142443\nreplay_serve_files 3 3.61885\nreplay_serve_files-no-syscallbuf 3 3.61468\nrestart_invalid_checkpoint 3 1.20532\nrestart_invalid_checkpoint-no-syscallbuf 3 1.241\nrestart_unstable 3 1.12942\nrestart_unstable-no-syscallbuf 3 1.06681\nrestart_diversion 3 1.34119\nrestart_diversion-no-syscallbuf 3 1.25404\nreverse_alarm 3 4.39127\nreverse_alarm-no-syscallbuf 3 5.23622\nreverse_continue_exec_subprocess 3 1.9878\nreverse_continue_exec_subprocess-no-syscallbuf 3 2.34593\nreverse_continue_fork_subprocess 3 1.21381\nreverse_continue_fork_subprocess-no-syscallbuf 3 1.2511\nreverse_continue_int3 3 2.87374\nreverse_continue_int3-no-syscallbuf 3 4.17258\nreverse_continue_start 3 2.42242\nreverse_continue_start-no-syscallbuf 3 1.90444\nreverse_finish 3 2.42719\nreverse_finish-no-syscallbuf 3 1.55052\nreverse_step_breakpoint 3 2.57344\nreverse_step_breakpoint-no-syscallbuf 3 2.76297\nreverse_step_signal 3 3.23417\nreverse_step_signal-no-syscallbuf 3 3.38695\nreverse_step_threads2 3 3.82985\nreverse_step_threads2-no-syscallbuf 3 3.91421\nreverse_watchpoint 3 2.84927\nreverse_watchpoint-no-syscallbuf 3 2.85867\nreverse_watchpoint_syscall 3 5.70676\nreverse_watchpoint_syscall-no-syscallbuf 3 5.29028\nrun_end 3 1.43338\nrun_end-no-syscallbuf 3 1.4049\nrun_in_function 3 1.0343\nrun_in_function-no-syscallbuf 3 1.13816\nsanity 3 0.935729\nsanity-no-syscallbuf 3 0.779338\nseekticks 3 2.28586\nseekticks-no-syscallbuf 3 2.43285\nshm_checkpoint 3 1.12118\nshm_checkpoint-no-syscallbuf 3 1.07186\nsiginfo 3 0.774631\nsiginfo-no-syscallbuf 3 0.83633\nx86/sigreturn_checksum 3 0.700085\nx86/sigreturn_checksum-no-syscallbuf 3 0.665849\nsignal_stop 3 0.871721\nsignal_stop-no-syscallbuf 3 0.850539\nsignal_checkpoint 3 1.1177\nsignal_checkpoint-no-syscallbuf 3 1.07433\nsimple_script 3 0.171676\nsimple_script-no-syscallbuf 3 0.166602\nsimple_script_debug 3 0.83504\nsimple_script_debug-no-syscallbuf 3 0.843184\nsimple_winch 3 2.38524\nsimple_winch-no-syscallbuf 3 1.88033\nstack_overflow_debug 3 5.67621\nstack_overflow_debug-no-syscallbuf 3 5.43747\nstep1 3 0.863026\nstep1-no-syscallbuf 3 0.899019\nx86/step_rdtsc 3 0.996719\nx86/step_rdtsc-no-syscallbuf 3 0.916034\nstep_signal 3 0.912971\nstep_signal-no-syscallbuf 3 0.932546\nx86/string_instructions_break 3 6.31161\nx86/string_instructions_break-no-syscallbuf 3 6.64242\nx86/string_instructions_replay_quirk 3 6.41861\nx86/string_instructions_replay_quirk-no-syscallbuf 3 6.25792\nsubprocess_exit_ends_session 3 3.19729\nsubprocess_exit_ends_session-no-syscallbuf 3 1.1328\nswitch_processes 3 3.02708\nswitch_processes-no-syscallbuf 3 2.54582\nsyscallbuf_timeslice_250 3 0.23855\nsyscallbuf_timeslice_250-no-syscallbuf 3 3.77326\ntrace_version 3 3.4036\ntrace_version-no-syscallbuf 3 2.9073\nterm_trace_cpu 3 0.396909\nterm_trace_cpu-no-syscallbuf 3 0.429927\ntrace_events 3 0.121537\ntrace_events-no-syscallbuf 3 0.114667\ntty 3 0.139457\ntty-no-syscallbuf 3 0.14484\nunmap_vdso 3 0.250266\nunmap_vdso-no-syscallbuf 3 0.242583\nunwind_on_signal 3 0.905326\nunwind_on_signal-no-syscallbuf 3 0.888245\nvfork_exec 3 8.49189\nvfork_exec-no-syscallbuf 3 8.50641\nvfork_break_parent 3 0.897031\nvfork_break_parent-no-syscallbuf 3 0.911991\nvsyscall_singlestep 3 0.144564\nvsyscall_singlestep-no-syscallbuf 3 0.135444\nwatch_code 3 2.77929\nwatch_code-no-syscallbuf 3 1.93848\nwatchpoint_cond 3 0.862841\nwatchpoint_cond-no-syscallbuf 3 0.8413\nwhen 3 0.867488\nwhen-no-syscallbuf 3 0.853477\n64bit_child-32 3 0.304826\n64bit_child-32-no-syscallbuf 3 0.303787\n_llseek-32 3 0.191999\n_llseek-32-no-syscallbuf 3 0.146433\nabort-32 3 0.327658\nabort-32-no-syscallbuf 3 0.308266\naccept-32 3 0.282175\naccept-32-no-syscallbuf 3 0.260281\nacct-32 3 0.15421\nacct-32-no-syscallbuf 3 0.143942\nadjtimex-32 3 0.15552\nadjtimex-32-no-syscallbuf 3 0.142696\naio-32 3 0.14638\naio-32-no-syscallbuf 3 0.140127\nalarm-32 3 1.93498\nalarm-32-no-syscallbuf 3 2.30969\nalarm2-32 3 1.13196\nalarm2-32-no-syscallbuf 3 1.13435\nalsa_ioctl-32 3 0.152554\nalsa_ioctl-32-no-syscallbuf 3 0.148061\narch_prctl-32 3 0.15952\narch_prctl-32-no-syscallbuf 3 0.140761\nasync_segv_ignored-32 3 0.162406\nasync_segv_ignored-32-no-syscallbuf 3 0.147537\nat_threadexit-32 3 0.213141\nat_threadexit-32-no-syscallbuf 3 0.204783\nbad_ip-32 3 0.148684\nbad_ip-32-no-syscallbuf 3 0.150585\nbad_syscall-32 3 0.15528\nbad_syscall-32-no-syscallbuf 3 0.152477\nbarrier-32 3 0.319439\nbarrier-32-no-syscallbuf 3 0.335742\nbig_buffers-32 3 0.162654\nbig_buffers-32-no-syscallbuf 3 0.176969\nblock-32 3 9.30324\nblock-32-no-syscallbuf 3 9.30678\nblock_open-32 3 0.17208\nblock_open-32-no-syscallbuf 3 0.172969\nbpf-32 3 0.163595\nbpf-32-no-syscallbuf 3 0.168828\nbpf_map-32 3 0.150942\nbpf_map-32-no-syscallbuf 3 0.159654\nbrk-32 3 0.157593\nbrk-32-no-syscallbuf 3 0.150036\nbrk2-32 3 0.170542\nbrk2-32-no-syscallbuf 3 0.139161\ncapget-32 3 0.185465\ncapget-32-no-syscallbuf 3 0.156354\nchew_cpu-32 3 8.99645\nchew_cpu-32-no-syscallbuf 3 7.87251\nx86/chew_cpu_cpuid-32 3 0.459509\nx86/chew_cpu_cpuid-32-no-syscallbuf 3 0.338245\nchmod-32 3 0.185436\nchmod-32-no-syscallbuf 3 0.160527\nchown-32 3 0.202622\nchown-32-no-syscallbuf 3 0.197929\nclock-32 3 0.23462\nclock-32-no-syscallbuf 3 0.341852\nclock_adjtime-32 3 0.165316\nclock_adjtime-32-no-syscallbuf 3 0.148155\nclock_nanosleep-32 3 1.16946\nclock_nanosleep-32-no-syscallbuf 3 1.18848\nclock_time64-32 3 0.167807\nclock_time64-32-no-syscallbuf 3 0.151238\nclone-32 3 0.173019\nclone-32-no-syscallbuf 3 0.154217\nclone_bad_stack-32 3 0.210942\nclone_bad_stack-32-no-syscallbuf 3 3.52335\nclone_bad_tls-32 3 0.149978\nclone_bad_tls-32-no-syscallbuf 3 0.140113\nclone_cleartid_coredump-32 3 0.296896\nclone_cleartid_coredump-32-no-syscallbuf 3 0.276544\nclone_fail-32 3 0.157975\nclone_fail-32-no-syscallbuf 3 0.144172\nclone_file_range-32 3 0.15726\nclone_file_range-32-no-syscallbuf 3 0.151451\nclone_immediate_exit-32 3 0.16223\nclone_immediate_exit-32-no-syscallbuf 3 0.160084\nclone_newflags-32 3 0.187997\nclone_newflags-32-no-syscallbuf 3 0.975865\nclone_parent-32 3 0.170891\nclone_parent-32-no-syscallbuf 3 0.151979\nclone_untraced-32 3 0.158722\nclone_untraced-32-no-syscallbuf 3 0.173181\nclone_vfork_pidfd-32 3 0.169316\nclone_vfork_pidfd-32-no-syscallbuf 3 0.154079\ncloned_sigmask-32 3 0.25057\ncloned_sigmask-32-no-syscallbuf 3 0.211312\nconstructor-32 3 2.16525\nconstructor-32-no-syscallbuf 3 2.20915\ncopy_file_range-32 3 0.169187\ncopy_file_range-32-no-syscallbuf 3 0.162071\nx86/cpuid_same_state-32 3 0.153435\nx86/cpuid_same_state-32-no-syscallbuf 3 0.15183\ncreat_address_not_truncated-32 3 0.159988\ncreat_address_not_truncated-32-no-syscallbuf 3 0.146481\nx86/cross_arch-32 3 0.155172\nx86/cross_arch-32-no-syscallbuf 3 0.170779\ncwd_inaccessible-32 3 0.189995\ncwd_inaccessible-32-no-syscallbuf 3 0.200617\ndaemon-32 3 0.168574\ndaemon-32-no-syscallbuf 3 0.148032\ndesched_blocking_poll-32 3 0.180458\ndesched_blocking_poll-32-no-syscallbuf 3 0.160495\ndesched_sigkill-32 3 0.251088\ndesched_sigkill-32-no-syscallbuf 3 0.218754\ndetach_state-32 3 0.218282\ndetach_state-32-no-syscallbuf 3 0.191154\ndetach_threads-32 3 0.231366\ndetach_threads-32-no-syscallbuf 3 0.200302\ndetach_sigkill-32 3 0.224815\ndetach_sigkill-32-no-syscallbuf 3 0.183264\ndetach_sigkill_exit-32 3 0.223165\ndetach_sigkill_exit-32-no-syscallbuf 3 0.164191\ndeterministic_sigsys-32 3 0.265504\ndeterministic_sigsys-32-no-syscallbuf 3 0.244816\ndev_zero-32 3 0.163044\ndev_zero-32-no-syscallbuf 3 0.147487\ndirect-32 3 0.210761\ndirect-32-no-syscallbuf 3 0.176374\ndup-32 3 0.162847\ndup-32-no-syscallbuf 3 0.161734\ndoublesegv-32 3 0.298704\ndoublesegv-32-no-syscallbuf 3 0.266586\nepoll_create-32 3 0.151417\nepoll_create-32-no-syscallbuf 3 0.156274\nepoll_create1-32 3 0.197557\nepoll_create1-32-no-syscallbuf 3 0.153539\nepoll_edge-32 3 0.155009\nepoll_edge-32-no-syscallbuf 3 0.157554\nepoll_pwait_eintr_sigmask-32 3 2.16118\nepoll_pwait_eintr_sigmask-32-no-syscallbuf 3 2.15432\neventfd-32 3 0.152283\neventfd-32-no-syscallbuf 3 0.174019\nexec_flags-32 3 0.154672\nexec_flags-32-no-syscallbuf 3 0.145737\nexec_no_env-32 3 0.192882\nexec_no_env-32-no-syscallbuf 3 0.189718\nexec_self-32 3 0.192453\nexec_self-32-no-syscallbuf 3 0.23233\nexec_from_main_thread-32 3 0.224688\nexec_from_main_thread-32-no-syscallbuf 3 0.223033\nexec_from_other_thread-32 3 11.0073\nexec_from_other_thread-32-no-syscallbuf 3 7.28493\nexec_stopsig-32 3 0.225907\nexec_stopsig-32-no-syscallbuf 3 0.199559\nexecveat-32 3 0.270121\nexecveat-32-no-syscallbuf 3 0.19012\nexit_with_syscallbuf_signal-32 3 0.202789\nexit_with_syscallbuf_signal-32-no-syscallbuf 3 0.165164\nfadvise-32 3 0.166598\nfadvise-32-no-syscallbuf 3 0.162007\nfanotify-32 3 0.146968\nfanotify-32-no-syscallbuf 3 0.158168\nfatal_init_signal-32 3 0.170639\nfatal_init_signal-32-no-syscallbuf 3 0.199012\nfatal_sigsegv_thread-32 3 2.84744\nfatal_sigsegv_thread-32-no-syscallbuf 3 3.65648\nx86/fault_in_code_page-32 3 0.162844\nx86/fault_in_code_page-32-no-syscallbuf 3 0.157253\nfcntl_dupfd-32 3 0.155242\nfcntl_dupfd-32-no-syscallbuf 3 0.160921\nfcntl_misc-32 3 0.147074\nfcntl_misc-32-no-syscallbuf 3 0.151391\nfcntl_notify-32 3 0.164578\nfcntl_notify-32-no-syscallbuf 3 0.148522\nfcntl_owner_ex-32 3 0.180492\nfcntl_owner_ex-32-no-syscallbuf 3 0.144062\nfcntl_rw_hints-32 3 0.172539\nfcntl_rw_hints-32-no-syscallbuf 3 0.156038\nfcntl_seals-32 3 0.15401\nfcntl_seals-32-no-syscallbuf 3 0.140758\nfcntl_sig-32 3 0.164499\nfcntl_sig-32-no-syscallbuf 3 0.144048\nfd_cleanup-32 3 0.171341\nfd_cleanup-32-no-syscallbuf 3 0.17852\nfd_tracking_across_threads-32 3 0.173681\nfd_tracking_across_threads-32-no-syscallbuf 3 0.184136\nfds_clean-32 3 0.215464\nfds_clean-32-no-syscallbuf 3 0.212869\nflock-32 3 0.692259\nflock-32-no-syscallbuf 3 1.43193\nflock_ofd-32 3 0.181016\nflock_ofd-32-no-syscallbuf 3 0.937886\nflock2-32 3 0.150836\nflock2-32-no-syscallbuf 3 0.141763\nfork_brk-32 3 0.162246\nfork_brk-32-no-syscallbuf 3 0.163701\nfork_child_crash-32 3 0.22847\nfork_child_crash-32-no-syscallbuf 3 0.206394\nfork_many-32 3 1.0621\nfork_many-32-no-syscallbuf 3 0.644679\nfutex_exit_race-32 3 0.449855\nfutex_exit_race-32-no-syscallbuf 3 0.383261\nfutex_exit_race_sigsegv-32 3 0.659378\nfutex_exit_race_sigsegv-32-no-syscallbuf 3 0.401827\nfutex_pi-32 3 0.159368\nfutex_pi-32-no-syscallbuf 3 0.154366\nfutex_priorities-32 3 0.178058\nfutex_priorities-32-no-syscallbuf 3 0.171578\nfutex_requeue-32 3 1.15704\nfutex_requeue-32-no-syscallbuf 3 1.16548\ngcrypt_rdrand-32 3 0.169223\ngcrypt_rdrand-32-no-syscallbuf 3 0.151264\ngetcpu-32 3 0.172906\ngetcpu-32-no-syscallbuf 3 0.149694\ngetgroups-32 3 0.17908\ngetgroups-32-no-syscallbuf 3 0.175706\ngetpwnam-32 3 0.203393\ngetpwnam-32-no-syscallbuf 3 0.183748\ngetrandom-32 3 0.184073\ngetrandom-32-no-syscallbuf 3 0.148054\nsetitimer-32 3 0.170033\nsetitimer-32-no-syscallbuf 3 0.161577\ngetsid-32 3 0.149776\ngetsid-32-no-syscallbuf 3 0.150727\ngettimeofday-32 3 0.179861\ngettimeofday-32-no-syscallbuf 3 0.157841\ngrandchild_threads-32 3 0.17692\ngrandchild_threads-32-no-syscallbuf 3 0.177978\ngrandchild_threads_main_running-32 3 4.2573\ngrandchild_threads_main_running-32-no-syscallbuf 3 4.26033\ngrandchild_threads_thread_running-32 3 4.22672\ngrandchild_threads_thread_running-32-no-syscallbuf 3 4.23036\ngrandchild_threads_parent_alive-32 3 0.175372\ngrandchild_threads_parent_alive-32-no-syscallbuf 3 0.17191\nx86/hle-32 3 1.75993\nx86/hle-32-no-syscallbuf 3 0.868235\ninotify-32 3 0.14979\ninotify-32-no-syscallbuf 3 0.155873\nint3-32 3 0.153066\nint3-32-no-syscallbuf 3 0.142991\nintr_futex_wait_restart-32 3 1.68006\nintr_futex_wait_restart-32-no-syscallbuf 3 1.67666\nintr_poll-32 3 3.66217\nintr_poll-32-no-syscallbuf 3 3.65309\nintr_ppoll-32 3 21.356\nintr_ppoll-32-no-syscallbuf 3 21.2727\nintr_pselect-32 3 9.1412\nintr_pselect-32-no-syscallbuf 3 9.16791\nintr_read_no_restart-32 3 1.27337\nintr_read_no_restart-32-no-syscallbuf 3 1.26838\nintr_read_restart-32 3 2.29083\nintr_read_restart-32-no-syscallbuf 3 2.26823\nintr_sleep-32 3 4.16515\nintr_sleep-32-no-syscallbuf 3 4.15069\nintr_sleep_no_restart-32 3 1.76225\nintr_sleep_no_restart-32-no-syscallbuf 3 1.76728\ninvalid_exec-32 3 0.153112\ninvalid_exec-32-no-syscallbuf 3 0.143637\ninvalid_fcntl-32 3 0.155597\ninvalid_fcntl-32-no-syscallbuf 3 0.143971\ninvalid_ioctl-32 3 0.151773\ninvalid_ioctl-32-no-syscallbuf 3 0.141787\nio-32 3 0.141118\nio-32-no-syscallbuf 3 0.144485\nio_uring-32 3 0.143135\nio_uring-32-no-syscallbuf 3 0.153721\nioctl-32 3 0.153616\nioctl-32-no-syscallbuf 3 0.16096\nioctl_blk-32 3 0.153993\nioctl_blk-32-no-syscallbuf 3 0.134024\nioctl_fb-32 3 0.142905\nioctl_fb-32-no-syscallbuf 3 0.160278\nioctl_fs-32 3 0.166305\nioctl_fs-32-no-syscallbuf 3 0.166838\nioctl_pty-32 3 0.212408\nioctl_pty-32-no-syscallbuf 3 0.182692\nioctl_sg-32 3 0.15514\nioctl_sg-32-no-syscallbuf 3 0.139962\nioctl_tty-32 3 0.211347\nioctl_tty-32-no-syscallbuf 3 0.183449\nioctl_vt-32 3 0.157438\nioctl_vt-32-no-syscallbuf 3 0.147469\nioprio-32 3 0.151004\nioprio-32-no-syscallbuf 3 0.154964\nx86/ioperm-32 3 0.156565\nx86/ioperm-32-no-syscallbuf 3 0.140728\nx86/iopl-32 3 0.147943\nx86/iopl-32-no-syscallbuf 3 0.148907\njoin_threads-32 3 1.81576\njoin_threads-32-no-syscallbuf 3 2.03578\njoystick-32 3 0.157531\njoystick-32-no-syscallbuf 3 0.162038\nkcmp-32 3 0.154256\nkcmp-32-no-syscallbuf 3 0.159314\nkeyctl-32 3 0.181774\nkeyctl-32-no-syscallbuf 3 0.163745\nkill_newborn-32 3 0.374656\nkill_newborn-32-no-syscallbuf 3 0.31533\nkill_ptracee-32 3 0.228514\nkill_ptracee-32-no-syscallbuf 3 1.246\nlarge_hole-32 3 0.165388\nlarge_hole-32-no-syscallbuf 3 0.147838\nlarge_write_deadlock-32 3 0.167368\nlarge_write_deadlock-32-no-syscallbuf 3 0.149762\nlegacy_ugid-32 3 0.15176\nlegacy_ugid-32-no-syscallbuf 3 0.145744\nx86/lsl-32 3 0.153843\nx86/lsl-32-no-syscallbuf 3 0.157294\nmadvise-32 3 0.153776\nmadvise-32-no-syscallbuf 3 0.155182\nmadvise_free-32 3 0.149715\nmadvise_free-32-no-syscallbuf 3 0.136664\nmadvise_wipeonfork-32 3 3.64301\nmadvise_wipeonfork-32-no-syscallbuf 3 3.40596\nmap_fixed-32 3 0.153551\nmap_fixed-32-no-syscallbuf 3 0.143067\nmap_shared_syscall-32 3 0.196505\nmap_shared_syscall-32-no-syscallbuf 3 0.164814\nmembarrier-32 3 0.196551\nmembarrier-32-no-syscallbuf 3 0.215238\nmemfd_create-32 3 0.145081\nmemfd_create-32-no-syscallbuf 3 0.144793\nmemfd_create_shared-32 3 0.149983\nmemfd_create_shared-32-no-syscallbuf 3 0.149288\nmemfd_create_shared_huge-32 3 0.150715\nmemfd_create_shared_huge-32-no-syscallbuf 3 0.149097\nmincore-32 3 0.168283\nmincore-32-no-syscallbuf 3 0.155869\nmknod-32 3 0.160622\nmknod-32-no-syscallbuf 3 0.189022\nmlock-32 3 0.157306\nmlock-32-no-syscallbuf 3 0.151448\nmmap_adjacent_to_rr_usage-32 3 0.16504\nmmap_adjacent_to_rr_usage-32-no-syscallbuf 3 0.153358\nmmap_private-32 3 0.955459\nmmap_private-32-no-syscallbuf 3 0.93923\nmmap_private_grow_under_map-32 3 0.156459\nmmap_private_grow_under_map-32-no-syscallbuf 3 0.150686\nmmap_recycle-32 3 0.178728\nmmap_recycle-32-no-syscallbuf 3 0.200388\nmmap_ro-32 3 0.15381\nmmap_ro-32-no-syscallbuf 3 0.152539\nmmap_self_maps_shared-32 3 0.212991\nmmap_self_maps_shared-32-no-syscallbuf 3 0.235169\nmmap_shared-32 3 0.189508\nmmap_shared-32-no-syscallbuf 3 0.165505\nmmap_shared_dev_zero-32 3 0.152691\nmmap_shared_dev_zero-32-no-syscallbuf 3 0.161642\nmmap_shared_grow-32 3 0.154202\nmmap_shared_grow-32-no-syscallbuf 3 0.15251\nmmap_shared_grow_under_map-32 3 0.15559\nmmap_shared_grow_under_map-32-no-syscallbuf 3 0.198992\nmmap_shared_multiple-32 3 0.150452\nmmap_shared_multiple-32-no-syscallbuf 3 0.157868\nmmap_shared_subpage-32 3 0.17358\nmmap_shared_subpage-32-no-syscallbuf 3 0.180505\nmmap_shared_write-32 3 8.93786\nmmap_shared_write-32-no-syscallbuf 3 7.83023\nmmap_shared_write_fork-32 3 3.03776\nmmap_shared_write_fork-32-no-syscallbuf 3 4.18879\nmmap_short_file-32 3 0.157907\nmmap_short_file-32-no-syscallbuf 3 0.152402\nmmap_write_complex-32 3 0.156462\nmmap_write_complex-32-no-syscallbuf 3 0.179488\nmmap_zero_size_fd-32 3 0.151921\nmmap_zero_size_fd-32-no-syscallbuf 3 0.159179\nx86/modify_ldt-32 3 0.16214\nx86/modify_ldt-32-no-syscallbuf 3 0.142049\nmount_ns_exec-32 3 0.218357\nmount_ns_exec-32-no-syscallbuf 3 0.210181\nmount_ns_exec2-32 3 0.210198\nmount_ns_exec2-32-no-syscallbuf 3 0.217898\nmprotect-32 3 0.159588\nmprotect-32-no-syscallbuf 3 0.158859\nmprotect_heterogenous-32 3 0.156733\nmprotect_heterogenous-32-no-syscallbuf 3 0.148801\nmprotect_none-32 3 0.162975\nmprotect_none-32-no-syscallbuf 3 0.165251\nmprotect_stack-32 3 0.157941\nmprotect_stack-32-no-syscallbuf 3 0.15318\nmq-32 3 2.14778\nmq-32-no-syscallbuf 3 2.14405\nmremap-32 3 2.71509\nmremap-32-no-syscallbuf 3 3.77905\nmremap_after_coalesce-32 3 0.167336\nmremap_after_coalesce-32-no-syscallbuf 3 0.15215\nmremap_grow-32 3 0.172376\nmremap_grow-32-no-syscallbuf 3 0.143557\nmremap_grow_shared-32 3 0.161398\nmremap_grow_shared-32-no-syscallbuf 3 0.184349\nmremap_non_page_size-32 3 0.173966\nmremap_non_page_size-32-no-syscallbuf 3 0.960082\nmremap_overwrite-32 3 0.167889\nmremap_overwrite-32-no-syscallbuf 3 0.149849\nmremap_private_grow_under_map-32 3 0.208637\nmremap_private_grow_under_map-32-no-syscallbuf 3 0.141832\nmremap_shrink-32 3 0.149815\nmremap_shrink-32-no-syscallbuf 3 0.159473\nmsg-32 3 1.67129\nmsg-32-no-syscallbuf 3 1.66959\nmsg_trunc-32 3 0.161193\nmsg_trunc-32-no-syscallbuf 3 0.152021\nmsync-32 3 0.980204\nmsync-32-no-syscallbuf 3 1.13639\nmtio-32 3 0.161772\nmtio-32-no-syscallbuf 3 0.150394\nmultiple_pending_signals-32 3 0.172009\nmultiple_pending_signals-32-no-syscallbuf 3 0.181682\nmultiple_pending_signals_sequential-32 3 0.171168\nmultiple_pending_signals_sequential-32-no-syscallbuf 3 0.168579\nmunmap_segv-32 3 0.180509\nmunmap_segv-32-no-syscallbuf 3 0.155486\nmunmap_discontinuous-32 3 0.167498\nmunmap_discontinuous-32-no-syscallbuf 3 0.150001\nnanosleep-32 3 1.15722\nnanosleep-32-no-syscallbuf 3 1.14139\nnetfilter-32 3 0.225731\nnetfilter-32-no-syscallbuf 3 0.253314\nnetlink_mmap_disable-32 3 0.152069\nnetlink_mmap_disable-32-no-syscallbuf 3 0.151469\nno_mask_timeslice-32 3 0.649534\nno_mask_timeslice-32-no-syscallbuf 3 0.631615\nnscd-32 3 0.155986\nnscd-32-no-syscallbuf 3 0.142495\nnuma-32 3 0.169945\nnuma-32-no-syscallbuf 3 0.154122\nx86/old_fork-32 3 0.181812\nx86/old_fork-32-no-syscallbuf 3 0.16164\norphan_process-32 3 0.189727\norphan_process-32-no-syscallbuf 3 0.16286\npacket_mmap_disable-32 3 0.151169\npacket_mmap_disable-32-no-syscallbuf 3 0.13895\npause-32 3 1.14206\npause-32-no-syscallbuf 3 1.12912\nperf_event-32 3 0.178988\nperf_event-32-no-syscallbuf 3 0.163082\npersonality-32 3 0.165676\npersonality-32-no-syscallbuf 3 0.186562\npid_ns_kill_child-32 3 0.315863\npid_ns_kill_child-32-no-syscallbuf 3 0.257869\npid_ns_kill_child_threads-32 3 0.218288\npid_ns_kill_child_threads-32-no-syscallbuf 3 0.181862\npid_ns_kill_child_zombie-32 3 0.197205\npid_ns_kill_child_zombie-32-no-syscallbuf 3 0.178299\npid_ns_kill_threads-32 3 0.212746\npid_ns_kill_threads-32-no-syscallbuf 3 0.197092\npid_ns_kill_threads_exit_wait-32 3 0.288347\npid_ns_kill_threads_exit_wait-32-no-syscallbuf 3 0.237707\npid_ns_reap-32 3 0.224205\npid_ns_reap-32-no-syscallbuf 3 0.219411\npid_ns_segv-32 3 0.244841\npid_ns_segv-32-no-syscallbuf 3 3.5191\npid_ns_shutdown-32 3 0.436881\npid_ns_shutdown-32-no-syscallbuf 3 0.300734\npidfd-32 3 0.170489\npidfd-32-no-syscallbuf 3 0.168095\nx86/pkeys-32 3 0.156903\nx86/pkeys-32-no-syscallbuf 3 0.151483\npoll_sig_race-32 3 2.86617\npoll_sig_race-32-no-syscallbuf 3 2.84212\nppoll-32 3 5.71335\nppoll-32-no-syscallbuf 3 5.71978\nprctl-32 3 0.205522\nprctl-32-no-syscallbuf 3 0.160626\nprctl_caps-32 3 0.418496\nprctl_caps-32-no-syscallbuf 3 0.337073\nprctl_deathsig-32 3 0.211914\nprctl_deathsig-32-no-syscallbuf 3 0.161506\nprctl_name-32 3 0.250287\nprctl_name-32-no-syscallbuf 3 0.219074\nprctl_short_name-32 3 0.157873\nprctl_short_name-32-no-syscallbuf 3 0.139269\nprctl_speculation_ctrl-32 3 0.160405\nprctl_speculation_ctrl-32-no-syscallbuf 3 0.15103\nx86/prctl_tsc-32 3 0.178406\nx86/prctl_tsc-32-no-syscallbuf 3 0.162318\nprivileged_net_ioctl-32 3 0.379696\nprivileged_net_ioctl-32-no-syscallbuf 3 0.387907\nproc_fds-32 3 0.669816\nproc_fds-32-no-syscallbuf 3 0.755054\nproc_mem-32 3 0.37817\nproc_mem-32-no-syscallbuf 3 0.352366\nprotect_rr_fds-32 3 3.79314\nprotect_rr_fds-32-no-syscallbuf 3 4.68026\nprw-32 3 0.159067\nprw-32-no-syscallbuf 3 0.157042\npthread_condvar_locking-32 3 0.171883\npthread_condvar_locking-32-no-syscallbuf 3 0.172416\npthread_mutex_timedlock-32 3 0.157664\npthread_mutex_timedlock-32-no-syscallbuf 3 0.152356\npthread_pi_mutex-32 3 0.180342\npthread_pi_mutex-32-no-syscallbuf 3 0.141443\npthread_rwlocks-32 3 0.171323\npthread_rwlocks-32-no-syscallbuf 3 0.155313\nx86/ptrace-32 3 0.202802\nx86/ptrace-32-no-syscallbuf 3 0.203137\nptrace_attach_null_status-32 3 0.201859\nptrace_attach_null_status-32-no-syscallbuf 3 0.202679\nptrace_attach_running-32 3 0.302493\nptrace_attach_running-32-no-syscallbuf 3 1.29286\nptrace_attach_sleeping-32 3 0.20655\nptrace_attach_sleeping-32-no-syscallbuf 3 0.224097\nptrace_attach_stopped-32 3 0.225358\nptrace_attach_stopped-32-no-syscallbuf 3 0.226626\nptrace_attach_thread_running-32 3 5.23279\nptrace_attach_thread_running-32-no-syscallbuf 3 6.23923\nptrace_breakpoint-32 3 0.187927\nptrace_breakpoint-32-no-syscallbuf 3 0.175526\nptrace_change_patched_syscall-32 3 0.191564\nptrace_change_patched_syscall-32-no-syscallbuf 3 0.178473\nx86/ptrace_debug_regs-32 3 0.165021\nx86/ptrace_debug_regs-32-no-syscallbuf 3 0.170646\nptrace_exec-32 3 0.284666\nptrace_exec-32-no-syscallbuf 3 0.263863\nx86/ptrace_exec32-32 3 0.156262\nx86/ptrace_exec32-32-no-syscallbuf 3 0.177857\nptrace_kill_grandtracee-32 3 0.187637\nptrace_kill_grandtracee-32-no-syscallbuf 3 0.168497\nx86/ptrace_tls-32 3 0.217899\nx86/ptrace_tls-32-no-syscallbuf 3 0.172283\nptrace_seize-32 3 0.166657\nptrace_seize-32-no-syscallbuf 3 0.150007\nptrace_sigchld_blocked-32 3 0.174692\nptrace_sigchld_blocked-32-no-syscallbuf 3 0.170833\nptrace_signals-32 3 0.247924\nptrace_signals-32-no-syscallbuf 3 0.223317\nptrace_singlestep-32 3 0.588033\nptrace_singlestep-32-no-syscallbuf 3 0.208037\nptrace_syscall-32 3 0.175065\nptrace_syscall-32-no-syscallbuf 3 0.175047\nptrace_syscall_clone_untraced-32 3 0.265815\nptrace_syscall_clone_untraced-32-no-syscallbuf 3 0.234984\nx86/ptrace_sysemu-32 3 0.245813\nx86/ptrace_sysemu-32-no-syscallbuf 3 0.281432\nptrace_sysemu_syscall-32 3 0.172529\nptrace_sysemu_syscall-32-no-syscallbuf 3 0.184325\nptrace_trace_clone-32 3 0.192627\nptrace_trace_clone-32-no-syscallbuf 3 0.196129\nptrace_trace_exit-32 3 0.167728\nptrace_trace_exit-32-no-syscallbuf 3 0.152608\nptrace_traceme-32 3 0.170265\nptrace_traceme-32-no-syscallbuf 3 0.167408\nptracer_death-32 3 0.225048\nptracer_death-32-no-syscallbuf 3 0.22157\nptracer_death_multithread-32 3 0.36814\nptracer_death_multithread-32-no-syscallbuf 3 0.355059\nptracer_death_multithread_peer-32 3 0.425597\nptracer_death_multithread_peer-32-no-syscallbuf 3 0.368566\nquotactl-32 3 0.16327\nquotactl-32-no-syscallbuf 3 0.171614\nx86/rdtsc-32 3 0.237795\nx86/rdtsc-32-no-syscallbuf 3 0.23056\nread_nothing-32 3 8.23326\nread_nothing-32-no-syscallbuf 3 8.74176\nreaddir-32 3 0.170494\nreaddir-32-no-syscallbuf 3 0.154295\nread_large-32 3 0.373234\nread_large-32-no-syscallbuf 3 1.08149\nread_oversize-32 3 0.160709\nread_oversize-32-no-syscallbuf 3 0.145395\nreadlink-32 3 0.167153\nreadlink-32-no-syscallbuf 3 0.178274\nreadlinkat-32 3 0.169105\nreadlinkat-32-no-syscallbuf 3 0.148272\nreadv-32 3 0.166935\nreadv-32-no-syscallbuf 3 0.157705\nrecord_replay_subject-32 3 3.17351\nrecord_replay_subject-32-no-syscallbuf 3 3.32555\nrecvfrom-32 3 0.167627\nrecvfrom-32-no-syscallbuf 3 0.152596\nredzone_integrity-32 3 1.13169\nredzone_integrity-32-no-syscallbuf 3 1.12603\nrename-32 3 0.157525\nrename-32-no-syscallbuf 3 0.149803\nrlimit-32 3 0.160895\nrlimit-32-no-syscallbuf 3 0.159288\nrobust_futex-32 3 0.186858\nrobust_futex-32-no-syscallbuf 3 0.174649\nrusage-32 3 0.16248\nrusage-32-no-syscallbuf 3 0.177407\nsamask-32 3 3.67966\nsamask-32-no-syscallbuf 3 0.24021\nsave_data_fd-32 3 0.194628\nsave_data_fd-32-no-syscallbuf 3 0.150419\nsched_attr-32 3 0.151563\nsched_attr-32-no-syscallbuf 3 0.148402\nsched_setaffinity-32 3 0.187992\nsched_setaffinity-32-no-syscallbuf 3 0.155224\nsched_setparam-32 3 0.159496\nsched_setparam-32-no-syscallbuf 3 0.145659\nsched_yield-32 3 0.259235\nsched_yield-32-no-syscallbuf 3 0.229347\nsched_yield_to_lower_priority-32 3 0.162573\nsched_yield_to_lower_priority-32-no-syscallbuf 3 0.153827\nscm_rights-32 3 0.674781\nscm_rights-32-no-syscallbuf 3 0.658719\nscratch_read-32 3 0.17575\nscratch_read-32-no-syscallbuf 3 0.168705\nseccomp-32 3 0.238751\nseccomp-32-no-syscallbuf 3 0.174795\nseccomp_cloning-32 3 0.154522\nseccomp_cloning-32-no-syscallbuf 3 0.144178\nseccomp_clone_fail-32 3 0.186049\nseccomp_clone_fail-32-no-syscallbuf 3 0.144807\nseccomp_desched-32 3 0.185211\nseccomp_desched-32-no-syscallbuf 3 0.14652\nseccomp_kill_exit-32 3 0.165099\nseccomp_kill_exit-32-no-syscallbuf 3 0.146084\nseccomp_null-32 3 0.148407\nseccomp_null-32-no-syscallbuf 3 0.172433\nseccomp_sigsys_args-32 3 0.169652\nseccomp_sigsys_args-32-no-syscallbuf 3 0.148725\nseccomp_sigsys_sigtrap-32 3 0.176765\nseccomp_sigsys_sigtrap-32-no-syscallbuf 3 0.169305\nseccomp_sigsys_syscallbuf-32 3 0.17534\nseccomp_sigsys_syscallbuf-32-no-syscallbuf 3 0.15083\nseccomp_tsync-32 3 0.166462\nseccomp_tsync-32-no-syscallbuf 3 0.161381\nseccomp_veto_exec-32 3 0.155642\nseccomp_veto_exec-32-no-syscallbuf 3 0.171488\nself_shebang-32 3 0.225915\nself_shebang-32-no-syscallbuf 3 0.201259\nself_sigint-32 3 0.146967\nself_sigint-32-no-syscallbuf 3 0.13868\nsem-32 3 0.221923\nsem-32-no-syscallbuf 3 0.232999\nsend_block-32 3 1.20601\nsend_block-32-no-syscallbuf 3 2.74609\nsendfile-32 3 0.174107\nsendfile-32-no-syscallbuf 3 0.160439\nset_ptracer-32 3 0.163169\nset_ptracer-32-no-syscallbuf 3 0.158607\nset_tid_address-32 3 0.203349\nset_tid_address-32-no-syscallbuf 3 0.177229\nsetgid-32 3 0.157202\nsetgid-32-no-syscallbuf 3 0.170407\nsetgroups-32 3 0.152816\nsetgroups-32-no-syscallbuf 3 0.154193\nsetsid-32 3 0.157229\nsetsid-32-no-syscallbuf 3 0.141788\nsetuid-32 3 0.199234\nsetuid-32-no-syscallbuf 3 0.206858\nshared_exec-32 3 0.155282\nshared_exec-32-no-syscallbuf 3 0.141731\nshared_monitor-32 3 0.159804\nshared_monitor-32-no-syscallbuf 3 0.152979\nshared_offset-32 3 0.167958\nshared_offset-32-no-syscallbuf 3 0.14582\nshared_write-32 3 0.16008\nshared_write-32-no-syscallbuf 3 0.148777\nshm-32 3 0.192733\nshm-32-no-syscallbuf 3 0.185219\nshm_unmap-32 3 0.17174\nshm_unmap-32-no-syscallbuf 3 0.152336\nsigaction_old-32 3 0.154676\nsigaction_old-32-no-syscallbuf 3 0.138014\nsigaltstack-32 3 0.152159\nsigaltstack-32-no-syscallbuf 3 0.163207\nsigchld_interrupt_signal-32 3 3.69105\nsigchld_interrupt_signal-32-no-syscallbuf 3 4.02921\nsigcont-32 3 0.168805\nsigcont-32-no-syscallbuf 3 0.163479\nsighandler_bad_rsp_sigsegv-32 3 0.150089\nsighandler_bad_rsp_sigsegv-32-no-syscallbuf 3 0.170034\nsighandler_fork-32 3 0.201522\nsighandler_fork-32-no-syscallbuf 3 0.183042\nsighandler_mask-32 3 0.176638\nsighandler_mask-32-no-syscallbuf 3 0.170064\nsigill-32 3 0.159255\nsigill-32-no-syscallbuf 3 0.142759\nsignal_deferred-32 3 0.200955\nsignal_deferred-32-no-syscallbuf 3 0.193946\nsignal_during_preload_init-32 3 0.181614\nsignal_during_preload_init-32-no-syscallbuf 3 0.153711\nsignal_frame-32 3 0.1648\nsignal_frame-32-no-syscallbuf 3 0.150419\nsignal_unstoppable-32 3 0.160193\nsignal_unstoppable-32-no-syscallbuf 3 0.155311\nsignalfd-32 3 0.150485\nsignalfd-32-no-syscallbuf 3 0.153559\nsigprocmask-32 3 0.564137\nsigprocmask-32-no-syscallbuf 3 0.478055\nsigprocmask_ensure_delivery-32 3 0.173297\nsigprocmask_ensure_delivery-32-no-syscallbuf 3 0.173071\nsigprocmask_exec-32 3 0.201982\nsigprocmask_exec-32-no-syscallbuf 3 0.183497\nsigprocmask_evil-32 3 0.156691\nsigprocmask_evil-32-no-syscallbuf 3 0.158505\nsigprocmask_in_syscallbuf_sighandler-32 3 1.12744\nsigprocmask_in_syscallbuf_sighandler-32-no-syscallbuf 3 1.14572\nsigprocmask_rr_sigs-32 3 0.171702\nsigprocmask_rr_sigs-32-no-syscallbuf 3 0.140313\nsigprocmask_syscallbuf-32 3 0.209291\nsigprocmask_syscallbuf-32-no-syscallbuf 3 0.148303\nsigqueueinfo-32 3 0.172461\nsigqueueinfo-32-no-syscallbuf 3 0.168942\nx86/sigreturn-32 3 0.190793\nx86/sigreturn-32-no-syscallbuf 3 0.193286\nsigreturn_reg-32 3 0.154534\nsigreturn_reg-32-no-syscallbuf 3 0.144831\nsigreturnmask-32 3 3.69684\nsigreturnmask-32-no-syscallbuf 3 0.269075\nsigrt-32 3 0.265449\nsigrt-32-no-syscallbuf 3 0.255231\nsigstop-32 3 0.235289\nsigstop-32-no-syscallbuf 3 0.195399\nsigstop2-32 3 0.161917\nsigstop2-32-no-syscallbuf 3 0.160208\nsigsuspend-32 3 0.163447\nsigsuspend-32-no-syscallbuf 3 0.163487\nsigtrap-32 3 0.19183\nsigtrap-32-no-syscallbuf 3 0.175125\nsimple_threads_stress-32 3 1.88103\nsimple_threads_stress-32-no-syscallbuf 3 2.13344\nsioc-32 3 0.46054\nsioc-32-no-syscallbuf 3 0.71351\nsmall_holes-32 3 0.188756\nsmall_holes-32-no-syscallbuf 3 0.176645\nsock_names_opts-32 3 0.207226\nsock_names_opts-32-no-syscallbuf 3 0.183982\nspinlock_priorities-32 3 0.87841\nspinlock_priorities-32-no-syscallbuf 3 1.52971\nsplice-32 3 0.178047\nsplice-32-no-syscallbuf 3 0.156996\nstack_growth_after_syscallbuf-32 3 0.164017\nstack_growth_after_syscallbuf-32-no-syscallbuf 3 0.163837\nstack_growth_syscallbuf-32 3 0.255754\nstack_growth_syscallbuf-32-no-syscallbuf 3 7.78853\nstack_growth_with_guard-32 3 0.161785\nstack_growth_with_guard-32-no-syscallbuf 3 0.153335\nstack_invalid-32 3 0.169688\nstack_invalid-32-no-syscallbuf 3 0.146576\nstack_overflow-32 3 0.238862\nstack_overflow-32-no-syscallbuf 3 0.240195\nstack_overflow_altstack-32 3 0.154164\nstack_overflow_altstack-32-no-syscallbuf 3 0.162658\nstack_overflow_with_guard-32 3 0.222723\nstack_overflow_with_guard-32-no-syscallbuf 3 0.209434\nstatfs-32 3 0.208717\nstatfs-32-no-syscallbuf 3 0.184497\nstatx-32 3 0.161829\nstatx-32-no-syscallbuf 3 0.145453\nstdout_child-32 3 0.205012\nstdout_child-32-no-syscallbuf 3 0.185209\nstdout_cloexec-32 3 0.30459\nstdout_cloexec-32-no-syscallbuf 3 0.216534\nstdout_dup-32 3 0.144612\nstdout_dup-32-no-syscallbuf 3 0.155127\nstdout_redirect-32 3 0.223423\nstdout_redirect-32-no-syscallbuf 3 0.200103\nswitch_read-32 3 0.663024\nswitch_read-32-no-syscallbuf 3 0.67711\nsymlink-32 3 0.144237\nsymlink-32-no-syscallbuf 3 0.137486\nsync-32 3 0.200357\nsync-32-no-syscallbuf 3 0.317546\nsync_file_range-32 3 0.155488\nsync_file_range-32-no-syscallbuf 3 0.160627\nsyscall_bp-32 3 0.19815\nsyscall_bp-32-no-syscallbuf 3 0.139347\nsyscall_in_writable_mem-32 3 0.151691\nsyscall_in_writable_mem-32-no-syscallbuf 3 0.146629\nsyscallbuf_signal_reset-32 3 0.153528\nsyscallbuf_signal_reset-32-no-syscallbuf 3 0.152267\nsyscallbuf_signal_blocking-32 3 0.163952\nsyscallbuf_signal_blocking-32-no-syscallbuf 3 0.162264\nsyscallbuf_sigstop-32 3 10.053\nsyscallbuf_sigstop-32-no-syscallbuf 3 21.1144\nsyscallbuf_timeslice-32 3 0.20007\nsyscallbuf_timeslice-32-no-syscallbuf 3 3.39877\nsyscallbuf_timeslice2-32 3 0.25615\nsyscallbuf_timeslice2-32-no-syscallbuf 3 9.4888\nsysconf-32 3 0.180379\nsysconf-32-no-syscallbuf 3 0.160266\nsysctl-32 3 0.157521\nsysctl-32-no-syscallbuf 3 0.157257\nsysemu_singlestep-32 3 0.161507\nsysemu_singlestep-32-no-syscallbuf 3 0.147615\nx86/sysfs-32 3 0.202258\nx86/sysfs-32-no-syscallbuf 3 0.235382\nsysinfo-32 3 0.153731\nsysinfo-32-no-syscallbuf 3 0.148979\ntgkill-32 3 0.180015\ntgkill-32-no-syscallbuf 3 0.189076\nthread_yield-32 3 2.72622\nthread_yield-32-no-syscallbuf 3 2.83493\ntimer-32 3 66.233\ntimer-32-no-syscallbuf 3 53.5698\ntimerfd-32 3 0.241996\ntimerfd-32-no-syscallbuf 3 0.245579\ntimes-32 3 0.167239\ntimes-32-no-syscallbuf 3 0.147307\ntruncate_temp-32 3 0.174554\ntruncate_temp-32-no-syscallbuf 3 0.168496\ntun-32 3 0.227859\ntun-32-no-syscallbuf 3 0.206458\ntwo_signals_with_mask-32 3 0.172679\ntwo_signals_with_mask-32-no-syscallbuf 3 0.175765\nulimit_low-32 3 0.181231\nulimit_low-32-no-syscallbuf 3 0.16547\nuname-32 3 0.152877\nuname-32-no-syscallbuf 3 0.154804\nunexpected_exit-32 3 0.221514\nunexpected_exit-32-no-syscallbuf 3 0.376083\nunexpected_exit_execve-32 3 0.291641\nunexpected_exit_execve-32-no-syscallbuf 3 0.389679\nunexpected_exit_execve_twice-32 3 1.27175\nunexpected_exit_execve_twice-32-no-syscallbuf 3 1.50441\nunexpected_exit_pid_ns-32 3 0.559279\nunexpected_exit_pid_ns-32-no-syscallbuf 3 0.259957\nunjoined_thread-32 3 0.161565\nunjoined_thread-32-no-syscallbuf 3 0.152121\nunshare-32 3 0.333582\nunshare-32-no-syscallbuf 3 1.35282\nuserfaultfd-32 3 0.162787\nuserfaultfd-32-no-syscallbuf 3 0.147239\nutimes-32 3 0.163314\nutimes-32-no-syscallbuf 3 0.151632\nvdso_parts-32 3 0.143693\nvdso_parts-32-no-syscallbuf 3 0.1437\nvfork_flush-32 3 0.196677\nvfork_flush-32-no-syscallbuf 3 0.162488\nvfork_shared-32 3 0.156936\nvfork_shared-32-no-syscallbuf 3 0.146859\nvideo_capture-32 3 0.160758\nvideo_capture-32-no-syscallbuf 3 0.138877\nvm_readv_writev-32 3 0.17866\nvm_readv_writev-32-no-syscallbuf 3 0.163655\nvsyscall-32 3 0.175241\nvsyscall-32-no-syscallbuf 3 0.144635\nvsyscall_timeslice-32 3 0.161879\nvsyscall_timeslice-32-no-syscallbuf 3 0.154139\nx86/x87env-32 3 0.157463\nx86/x87env-32-no-syscallbuf 3 0.143789\nwait-32 3 0.189688\nwait-32-no-syscallbuf 3 0.163083\nwait_sigstop-32 3 0.209228\nwait_sigstop-32-no-syscallbuf 3 0.185075\nwrite_race-32 3 2.69575\nwrite_race-32-no-syscallbuf 3 1.71615\nwritev-32 3 0.181917\nwritev-32-no-syscallbuf 3 0.148252\nxattr-32 3 0.161601\nxattr-32-no-syscallbuf 3 0.169778\nzero_length_read-32 3 0.171758\nzero_length_read-32-no-syscallbuf 3 0.152607\nstd_random-32 3 0.190289\nstd_random-32-no-syscallbuf 3 0.197247\nunwind_rr_page-32 3 1.14592\nunwind_rr_page-32-no-syscallbuf 3 1.16719\nabort_nonmain-32 3 0.316806\nabort_nonmain-32-no-syscallbuf 3 0.380755\nalternate_thread_diversion-32 3 0.943783\nalternate_thread_diversion-32-no-syscallbuf 3 0.939422\nargs-32 3 0.146008\nargs-32-no-syscallbuf 3 0.148513\nasync_kill_with_syscallbuf-32 3 2.69049\nasync_kill_with_syscallbuf-32-no-syscallbuf 3 3.7005\nasync_kill_with_syscallbuf2-32 3 2.21314\nasync_kill_with_syscallbuf2-32-no-syscallbuf 3 2.54384\nasync_kill_with_threads-32 3 2.22036\nasync_kill_with_threads-32-no-syscallbuf 3 2.19775\nasync_kill_with_threads_main_running-32 3 2.25137\nasync_kill_with_threads_main_running-32-no-syscallbuf 3 2.2716\nasync_kill_with_threads_thread_running-32 3 6.13926\nasync_kill_with_threads_thread_running-32-no-syscallbuf 3 6.1491\nasync_segv-32 3 4.38816\nasync_segv-32-no-syscallbuf 3 4.20831\nasync_signal_syscalls-32 3 1.50166\nasync_signal_syscalls-32-no-syscallbuf 3 0.0224907\nasync_signal_syscalls2-32 3 1.06915\nasync_signal_syscalls2-32-no-syscallbuf 3 0.0208089\nasync_signal_syscalls_siginfo-32 3 2.1386\nasync_signal_syscalls_siginfo-32-no-syscallbuf 3 0.0208899\nasync_usr1-32 3 4.14552\nasync_usr1-32-no-syscallbuf 3 4.29349\nblacklist-32 3 0.177599\nblacklist-32-no-syscallbuf 3 0.151851\nblock_clone_checkpoint-32 3 0.905129\nblock_clone_checkpoint-32-no-syscallbuf 3 0.944421\nblock_clone_interrupted-32 3 5.37544\nblock_clone_interrupted-32-no-syscallbuf 3 4.34796\nblock_clone_syscallbuf_overflow-32 3 6.43809\nblock_clone_syscallbuf_overflow-32-no-syscallbuf 3 6.23606\nblock_intr_sigchld-32 3 6.71056\nblock_intr_sigchld-32-no-syscallbuf 3 5.87732\nblocked_bad_ip-32 3 5.48907\nblocked_bad_ip-32-no-syscallbuf 3 0.953725\nblocked_sigill-32 3 0.348823\nblocked_sigill-32-no-syscallbuf 3 0.33688\nx86/blocked_sigsegv-32 3 0.334973\nx86/blocked_sigsegv-32-no-syscallbuf 3 0.331443\nbreakpoint-32 3 0.933407\nbreakpoint-32-no-syscallbuf 3 0.899296\nbreakpoint_conditions-32 3 0.875905\nbreakpoint_conditions-32-no-syscallbuf 3 0.850744\nbreakpoint_overlap-32 3 0.854787\nbreakpoint_overlap-32-no-syscallbuf 3 0.794347\ncall_function-32 3 0.836484\ncall_function-32-no-syscallbuf 3 0.801419\ncall_gettid-32 3 0.791342\ncall_gettid-32-no-syscallbuf 3 0.769617\ncheckpoint_dying_threads-32 3 0.841963\ncheckpoint_dying_threads-32-no-syscallbuf 3 0.854261\ncheckpoint_mixed_mode-32 3 0.747812\ncheckpoint_mixed_mode-32-no-syscallbuf 3 0.768738\nchecksum_sanity-32 3 1.84333\nchecksum_sanity-32-no-syscallbuf 3 1.63785\ncheck_lost_interrupts-32 3 2.15464\ncheck_lost_interrupts-32-no-syscallbuf 3 0.0292697\nclone_interruption-32 3 1.81224\nclone_interruption-32-no-syscallbuf 3 1.69677\nclone_vfork-32 3 0.216188\nclone_vfork-32-no-syscallbuf 3 0.2384\nconditional_breakpoint_calls-32 3 0.859498\nconditional_breakpoint_calls-32-no-syscallbuf 3 0.822861\nconditional_breakpoint_offload-32 3 67.6523\nconditional_breakpoint_offload-32-no-syscallbuf 3 68.5646\ncondvar_stress-32 3 20.5078\ncondvar_stress-32-no-syscallbuf 3 49.5064\ncont_race-32 3 14.3118\ncont_race-32-no-syscallbuf 3 6.75519\nx86/cpuid_singlestep-32 3 0.757824\nx86/cpuid_singlestep-32-no-syscallbuf 3 0.741373\ncrash-32 3 0.28169\ncrash-32-no-syscallbuf 3 0.279738\ncrash_in_function-32 3 5.8669\ncrash_in_function-32-no-syscallbuf 3 5.09821\ndaemon_read-32 3 0.218933\ndaemon_read-32-no-syscallbuf 3 0.196873\ndconf_mock-32 3 0.173531\ndconf_mock-32-no-syscallbuf 3 0.17913\ndev_tty-32 3 0.14228\ndev_tty-32-no-syscallbuf 3 0.143919\ndiversion_sigtrap-32 3 10.8416\ndiversion_sigtrap-32-no-syscallbuf 3 10.9284\ndiversion_syscall-32 3 0.899496\ndiversion_syscall-32-no-syscallbuf 3 0.897231\ndlopen-32 3 3.6474\ndlopen-32-no-syscallbuf 3 4.79812\nearly_error-32 3 3.69384\nearly_error-32-no-syscallbuf 3 0.3424\nelapsed_time-32 3 1.77463\nelapsed_time-32-no-syscallbuf 3 1.78306\nexclusion_region-32 3 0.163736\nexclusion_region-32-no-syscallbuf 3 0.173001\nexec_failed-32 3 0.716326\nexec_failed-32-no-syscallbuf 3 0.735136\nexec_many-32 3 6.51486\nexec_many-32-no-syscallbuf 3 4.77725\nexecve_loop-32 3 6.01457\nexecve_loop-32-no-syscallbuf 3 4.5922\nexit_codes-32 3 0.337132\nexit_codes-32-no-syscallbuf 3 0.357051\nexit_group-32 3 0.165823\nexit_group-32-no-syscallbuf 3 0.160489\nexit_race-32 3 1.42874\nexit_race-32-no-syscallbuf 3 1.20134\nexit_status-32 3 0.104493\nexit_status-32-no-syscallbuf 3 0.10491\nx86/explicit_checkpoints-32 3 1.19559\nx86/explicit_checkpoints-32-no-syscallbuf 3 1.16154\nfd_limit-32 3 0.190347\nfd_limit-32-no-syscallbuf 3 1.10721\nfork_stress-32 3 2.70758\nfork_stress-32-no-syscallbuf 3 1.18989\nfork_syscalls-32 3 0.155506\nfork_syscalls-32-no-syscallbuf 3 0.188712\nfunction_calls-32 3 2.63949\nfunction_calls-32-no-syscallbuf 3 2.96793\nx86/fxregs-32 3 0.746486\nx86/fxregs-32-no-syscallbuf 3 0.750233\ngetcwd-32 3 0.151393\ngetcwd-32-no-syscallbuf 3 0.14999\ngdb_bogus_breakpoint-32 3 0.751957\ngdb_bogus_breakpoint-32-no-syscallbuf 3 0.747864\ngoto_event-32 3 3.01067\ngoto_event-32-no-syscallbuf 3 1.68248\nhello-32 3 0.169985\nhello-32-no-syscallbuf 3 0.155974\nhooks-32 3 1.30262\nhooks-32-no-syscallbuf 3 0.0218813\nignored_async_usr1-32 3 2.06897\nignored_async_usr1-32-no-syscallbuf 3 2.86715\nignored_sigsegv-32 3 0.359044\nignored_sigsegv-32-no-syscallbuf 3 0.33573\nignore_nested-32 3 0.303741\nignore_nested-32-no-syscallbuf 3 0.289081\nimmediate_restart-32 3 0.849732\nimmediate_restart-32-no-syscallbuf 3 0.865976\nx86/int3_ok-32 3 0.159444\nx86/int3_ok-32-no-syscallbuf 3 0.152736\ninterrupt-32 3 4.60296\ninterrupt-32-no-syscallbuf 3 4.15208\nintr_ptrace_decline-32 3 5.00777\nintr_ptrace_decline-32-no-syscallbuf 3 4.69584\ninvalid_interpreter-32 3 5.5485\ninvalid_interpreter-32-no-syscallbuf 3 6.50341\ninvalid_jump-32 3 2.73029\ninvalid_jump-32-no-syscallbuf 3 1.53563\njit_proc_mem-32 3 0.831693\njit_proc_mem-32-no-syscallbuf 3 0.821895\nlink-32 3 0.174756\nlink-32-no-syscallbuf 3 0.152836\nmadvise_dontfork-32 3 0.867081\nmadvise_dontfork-32-no-syscallbuf 3 0.872768\nmain_thread_exit-32 3 0.912936\nmain_thread_exit-32-no-syscallbuf 3 0.921572\nmany_yields-32 3 2.5944\nmany_yields-32-no-syscallbuf 3 2.02695\nmmap_fd_reuse_checkpoint-32 3 0.881817\nmmap_fd_reuse_checkpoint-32-no-syscallbuf 3 0.889229\nmmap_replace_most_mappings-32 3 2.14156\nmmap_replace_most_mappings-32-no-syscallbuf 3 1.99783\nmmap_shared_prot-32 3 0.891155\nmmap_shared_prot-32-no-syscallbuf 3 0.884203\nmmap_shared_write_exec_race-32 3 3.65566\nmmap_shared_write_exec_race-32-no-syscallbuf 3 4.31505\nmmap_tmpfs-32 3 0.168187\nmmap_tmpfs-32-no-syscallbuf 3 0.160034\nmmap_write-32 3 0.0215652\nmmap_write-32-no-syscallbuf 3 0.020991\nmmap_write_private-32 3 0.265184\nmmap_write_private-32-no-syscallbuf 3 0.274526\nmorestack_unwind-32 1 0.537327\nmorestack_unwind-32-no-syscallbuf 1 0.0202514\nmprotect_growsdown-32 3 0.296293\nmprotect_growsdown-32-no-syscallbuf 3 0.277314\nmprotect_syscallbuf_overflow-32 3 0.27817\nmprotect_syscallbuf_overflow-32-no-syscallbuf 3 9.01023\nmutex_pi_stress-32 3 23.3154\nmutex_pi_stress-32-no-syscallbuf 3 26.4688\nnested_detach_wait-32 3 0.507768\nnested_detach_wait-32-no-syscallbuf 3 0.494804\noverflow_branch_counter-32 3 2.63386\noverflow_branch_counter-32-no-syscallbuf 3 2.79984\npatch_page_end-32 3 0.163768\npatch_page_end-32-no-syscallbuf 3 0.0242372\nx86/patch_40_80_f6_81-32 3 0.156124\nx86/patch_40_80_f6_81-32-no-syscallbuf 3 0.0233381\nperf_event_mmap-32 3 0.838548\nperf_event_mmap-32-no-syscallbuf 3 0.835866\npriority-32 3 0.16253\npriority-32-no-syscallbuf 3 0.161785\nptrace_remote_unmap-32 3 3.71517\nptrace_remote_unmap-32-no-syscallbuf 3 3.35802\nread_big_struct-32 3 0.836645\nread_big_struct-32-no-syscallbuf 3 0.896171\nremove_latest_trace-32 3 1.18545\nremove_latest_trace-32-no-syscallbuf 3 1.17654\nrestart_abnormal_exit-32 3 1.05629\nrestart_abnormal_exit-32-no-syscallbuf 3 1.03347\nreverse_continue_breakpoint-32 3 1.46066\nreverse_continue_breakpoint-32-no-syscallbuf 3 1.52823\nreverse_continue_multiprocess-32 3 10.0453\nreverse_continue_multiprocess-32-no-syscallbuf 3 9.53719\nreverse_continue_process_signal-32 3 2.93655\nreverse_continue_process_signal-32-no-syscallbuf 3 3.84094\nreverse_many_breakpoints-32 3 3.22103\nreverse_many_breakpoints-32-no-syscallbuf 3 3.91635\nreverse_step_long-32 3 5.47224\nreverse_step_long-32-no-syscallbuf 3 7.10854\nreverse_step_threads-32 3 2.41595\nreverse_step_threads-32-no-syscallbuf 3 2.25214\nreverse_step_threads_break-32 3 3.85589\nreverse_step_threads_break-32-no-syscallbuf 3 4.13086\nrr_ps-32 3 0.352589\nrr_ps-32-no-syscallbuf 3 0.303507\nrr_ps_ns-32 3 0.201816\nrr_ps_ns-32-no-syscallbuf 3 0.203488\nrseq-32 3 48.676\nrseq-32-no-syscallbuf 3 59.1352\nsearch-32 3 0.823497\nsearch-32-no-syscallbuf 3 0.791839\nseccomp_blocks_rr-32 3 0.320542\nseccomp_blocks_rr-32-no-syscallbuf 3 0.163554\nseccomp_signals-32 3 2.67807\nseccomp_signals-32-no-syscallbuf 3 2.71289\nsegfault-32 3 0.168754\nsegfault-32-no-syscallbuf 3 0.15359\nshared_map-32 3 0.207258\nshared_map-32-no-syscallbuf 3 0.194363\nshared_persistent_file-32 3 0.913624\nshared_persistent_file-32-no-syscallbuf 3 0.867889\nsignal_numbers-32 3 0.999511\nsignal_numbers-32-no-syscallbuf 3 0.976622\nsigprocmask_race-32 3 0.161489\nsigprocmask_race-32-no-syscallbuf 3 0.0207901\nsigprocmask_rr_sigs_nondefault-32 3 0.107611\nsigprocmask_rr_sigs_nondefault-32-no-syscallbuf 3 0.0949726\nsimple-32 3 0.274747\nsimple-32-no-syscallbuf 3 0.254695\nx86/singlestep_pushf-32 3 0.813864\nx86/singlestep_pushf-32-no-syscallbuf 3 0.743535\nstack_growth-32 3 0.800243\nstack_growth-32-no-syscallbuf 3 0.822085\nstep_thread-32 3 0.922024\nstep_thread-32-no-syscallbuf 3 0.945214\nstrict_priorities-32 3 9.52235\nstrict_priorities-32-no-syscallbuf 3 10.5882\nx86/string_instructions-32 3 0.666767\nx86/string_instructions-32-no-syscallbuf 3 0.631986\nx86/string_instructions_async_signals-32 3 0.230043\nx86/string_instructions_async_signals-32-no-syscallbuf 3 47.2284\nx86/string_instructions_async_signals_shared-32 3 0.248879\nx86/string_instructions_async_signals_shared-32-no-syscallbuf 3 61.0602\nx86/string_instructions_multiwatch-32 3 0.847261\nx86/string_instructions_multiwatch-32-no-syscallbuf 3 0.779672\nx86/string_instructions_replay-32 3 12.2112\nx86/string_instructions_replay-32-no-syscallbuf 3 11.6733\nx86/string_instructions_singlestep_fastforward-32 3 11.808\nx86/string_instructions_singlestep_fastforward-32-no-syscallbuf 3 11.9804\nx86/string_instructions_watch-32 3 0.872193\nx86/string_instructions_watch-32-no-syscallbuf 3 0.862499\nsyscallbuf_fd_disabling-32 3 0.258406\nsyscallbuf_fd_disabling-32-no-syscallbuf 3 0.238307\nsyscallbuf_signal_blocking_read-32 3 1.11503\nsyscallbuf_signal_blocking_read-32-no-syscallbuf 3 1.03876\nsysconf_onln-32 3 0.316152\nsysconf_onln-32-no-syscallbuf 3 0.306085\ntarget_fork-32 3 2.28992\ntarget_fork-32-no-syscallbuf 3 1.51753\ntarget_process-32 3 1.20558\ntarget_process-32-no-syscallbuf 3 1.13331\ntcp_sockets-32 3 0.146079\ntcp_sockets-32-no-syscallbuf 3 0.139738\nterm_nonmain-32 3 0.179605\nterm_nonmain-32-no-syscallbuf 3 0.17684\nterm_rr-32 3 4.09212\nterm_rr-32-no-syscallbuf 3 4.08009\nterm_trace_reset-32 3 0.190674\nterm_trace_reset-32-no-syscallbuf 3 0.191812\nterm_trace_syscall-32 3 0.197947\nterm_trace_syscall-32-no-syscallbuf 3 0.204153\nthread_exit_signal-32 3 2.23372\nthread_exit_signal-32-no-syscallbuf 3 2.15126\nthread_open_race-32 3 55.872\nthread_open_race-32-no-syscallbuf 3 0.0219118\nthread_stress-32 3 14.8451\nthread_stress-32-no-syscallbuf 3 16.8795\nthreaded_syscall_spam-32 3 1.84407\nthreaded_syscall_spam-32-no-syscallbuf 3 0.0210993\nthreads-32 3 1.18562\nthreads-32-no-syscallbuf 3 1.14132\ntls-32 3 0.882768\ntls-32-no-syscallbuf 3 0.82319\nttyname-32 3 0.144578\nttyname-32-no-syscallbuf 3 0.158472\nunexpected_stack_growth-32 3 6.15177\nunexpected_stack_growth-32-no-syscallbuf 3 0.856114\nuser_ignore_sig-32 3 0.158082\nuser_ignore_sig-32-no-syscallbuf 3 0.150497\nvdso_clock_gettime_stack-32 3 0.0208382\nvdso_clock_gettime_stack-32-no-syscallbuf 3 0.0207882\nvdso_gettimeofday_stack-32 3 0.0206608\nvdso_gettimeofday_stack-32-no-syscallbuf 3 0.0209766\nvdso_time_stack-32 3 0.0216031\nvdso_time_stack-32-no-syscallbuf 3 0.0212657\nvfork-32 3 0.211262\nvfork-32-no-syscallbuf 3 0.25298\nvfork_read_clone_stress-32 3 1.43335\nvfork_read_clone_stress-32-no-syscallbuf 3 2.11159\nvsyscall_reverse_next-32 3 141.046\nvsyscall_reverse_next-32-no-syscallbuf 3 137.178\nwait_for_all-32 3 1.13133\nwait_for_all-32-no-syscallbuf 3 1.13018\nwatchpoint-32 3 1.13577\nwatchpoint-32-no-syscallbuf 3 1.23384\nwatchpoint_at_sched-32 3 1.11\nwatchpoint_at_sched-32-no-syscallbuf 3 1.14594\nwatchpoint_before_signal-32 3 0.854689\nwatchpoint_before_signal-32-no-syscallbuf 3 0.810239\nwatchpoint_no_progress-32 3 2.72562\nwatchpoint_no_progress-32-no-syscallbuf 3 1.50164\nwatchpoint_size_change-32 3 0.858281\nwatchpoint_size_change-32-no-syscallbuf 3 0.850796\nwatchpoint_syscall-32 3 0.856296\nwatchpoint_syscall-32-no-syscallbuf 3 0.782193\nwatchpoint_unaligned-32 3 1.03794\nwatchpoint_unaligned-32-no-syscallbuf 3 1.05474\nasync_signal_syscalls_100-32 3 0.176285\nasync_signal_syscalls_100-32-no-syscallbuf 3 4.23242\nasync_signal_syscalls_1000-32 3 0.169197\nasync_signal_syscalls_1000-32-no-syscallbuf 3 3.55888\nbad_breakpoint-32 3 7.62464\nbad_breakpoint-32-no-syscallbuf 3 7.8842\nbreak_block-32 3 9.81985\nbreak_block-32-no-syscallbuf 3 9.85605\nbreak_clock-32 3 0.891678\nbreak_clock-32-no-syscallbuf 3 1.05496\nbreak_clone-32 3 0.740432\nbreak_clone-32-no-syscallbuf 3 0.790172\nbreak_exec-32 3 0.802764\nbreak_exec-32-no-syscallbuf 3 0.826882\nbreak_int3-32 3 0.750634\nbreak_int3-32-no-syscallbuf 3 0.731741\nbreak_mmap_private-32 3 1.91277\nbreak_mmap_private-32-no-syscallbuf 3 1.85261\nbreak_msg-32 3 2.67174\nbreak_msg-32-no-syscallbuf 3 2.77454\nx86/break_rdtsc-32 3 0.820217\nx86/break_rdtsc-32-no-syscallbuf 3 0.805801\nbreak_sigreturn-32 3 4.76704\nbreak_sigreturn-32-no-syscallbuf 3 4.826\nbreak_sync_signal-32 3 0.731987\nbreak_sync_signal-32-no-syscallbuf 3 0.739062\nbreak_thread-32 3 0.878548\nbreak_thread-32-no-syscallbuf 3 1.04768\nbreak_time_slice-32 3 8.40304\nbreak_time_slice-32-no-syscallbuf 3 8.37739\nbreakpoint_consistent-32 3 0.76863\nbreakpoint_consistent-32-no-syscallbuf 3 0.751159\ncall_exit-32 3 0.944958\ncall_exit-32-no-syscallbuf 3 0.939937\ncheck_patched_pthread-32 3 1.81349\ncheck_patched_pthread-32-no-syscallbuf 3 1.79483\ncheckpoint_async_signal_syscalls_1000-32 3 2.22798\ncheckpoint_async_signal_syscalls_1000-32-no-syscallbuf 3 0.0215992\ncheckpoint_mmap_shared-32 3 18.6084\ncheckpoint_mmap_shared-32-no-syscallbuf 3 13.8794\ncheckpoint_prctl_name-32 3 23.0868\ncheckpoint_prctl_name-32-no-syscallbuf 3 21.7651\ncheckpoint_simple-32 3 6.7996\ncheckpoint_simple-32-no-syscallbuf 3 5.09097\nchecksum_sanity_noclone-32 3 1.31514\nchecksum_sanity_noclone-32-no-syscallbuf 3 1.49628\ncomm-32 3 0.61876\ncomm-32-no-syscallbuf 3 0.620591\ncont_signal-32 3 4.73211\ncont_signal-32-no-syscallbuf 3 4.75449\nx86/cpuid-32 3 1.16829\nx86/cpuid-32-no-syscallbuf 3 0.923756\ndead_thread_target-32 3 0.942176\ndead_thread_target-32-no-syscallbuf 3 0.926653\ndesched_ticks-32 3 0.821425\ndesched_ticks-32-no-syscallbuf 3 0.0225863\ndeliver_async_signal_during_syscalls-32 3 0.66533\ndeliver_async_signal_during_syscalls-32-no-syscallbuf 3 0.0210904\nenv_newline-32 3 0.15028\nenv_newline-32-no-syscallbuf 3 0.143948\nexec_deleted-32 3 0.158318\nexec_deleted-32-no-syscallbuf 3 0.150836\nexec_stop-32 3 0.851366\nexec_stop-32-no-syscallbuf 3 0.850134\nexecp-32 3 0.160006\nexecp-32-no-syscallbuf 3 0.144344\nexplicit_checkpoint_clone-32 3 0.917372\nexplicit_checkpoint_clone-32-no-syscallbuf 3 0.899579\nfile_name_newline-32 3 0.162767\nfile_name_newline-32-no-syscallbuf 3 0.146534\nfinal_sigkill-32 3 0.907278\nfinal_sigkill-32-no-syscallbuf 3 0.899301\nfirst_instruction-32 3 5.60671\nfirst_instruction-32-no-syscallbuf 3 2.67149\nfork_exec_info_thr-32 3 3.29816\nfork_exec_info_thr-32-no-syscallbuf 3 2.95928\nget_thread_list-32 3 0.942064\nget_thread_list-32-no-syscallbuf 3 0.911207\nhardlink_mmapped_files-32 3 2.19101\nhardlink_mmapped_files-32-no-syscallbuf 3 2.17723\nhbreak-32 3 0.837334\nhbreak-32-no-syscallbuf 3 0.845015\nmprotect_step-32 3 0.980319\nmprotect_step-32-no-syscallbuf 3 1.03667\nnested_detach-32 3 2.10512\nnested_detach-32-no-syscallbuf 3 2.05432\nnested_detach_kill-32 3 0.5623\nnested_detach_kill-32-no-syscallbuf 3 0.510195\nnested_release-32 3 0.282025\nnested_release-32-no-syscallbuf 3 0.305014\nparent_no_break_child_bkpt-32 3 0.984814\nparent_no_break_child_bkpt-32-no-syscallbuf 3 0.961328\nparent_no_stop_child_crash-32 3 0.969948\nparent_no_stop_child_crash-32-no-syscallbuf 3 3.786\npost_exec_fpu_regs-32 3 0.600815\npost_exec_fpu_regs-32-no-syscallbuf 3 0.599346\nproc_maps-32 3 0.736028\nproc_maps-32-no-syscallbuf 3 0.774179\nread_bad_mem-32 3 0.722698\nread_bad_mem-32-no-syscallbuf 3 0.729764\nrecord_replay-32 3 136.043\nrecord_replay-32-no-syscallbuf 3 150.954\nremove_watchpoint-32 3 0.843034\nremove_watchpoint-32-no-syscallbuf 3 0.806226\nreplay_overlarge_event_number-32 3 0.139763\nreplay_overlarge_event_number-32-no-syscallbuf 3 0.134153\nreplay_serve_files-32 3 3.41732\nreplay_serve_files-32-no-syscallbuf 3 3.58874\nrestart_invalid_checkpoint-32 3 0.990035\nrestart_invalid_checkpoint-32-no-syscallbuf 3 0.946249\nrestart_unstable-32 3 0.910166\nrestart_unstable-32-no-syscallbuf 3 0.891157\nrestart_diversion-32 3 0.989601\nrestart_diversion-32-no-syscallbuf 3 0.997177\nreverse_alarm-32 3 4.879\nreverse_alarm-32-no-syscallbuf 3 4.06193\nreverse_continue_exec_subprocess-32 3 2.78078\nreverse_continue_exec_subprocess-32-no-syscallbuf 3 2.77524\nreverse_continue_fork_subprocess-32 3 1.08481\nreverse_continue_fork_subprocess-32-no-syscallbuf 3 1.05656\nreverse_continue_int3-32 3 3.04754\nreverse_continue_int3-32-no-syscallbuf 3 2.85159\nreverse_continue_start-32 3 1.45292\nreverse_continue_start-32-no-syscallbuf 3 1.55508\nreverse_finish-32 3 2.07223\nreverse_finish-32-no-syscallbuf 3 1.89863\nreverse_step_breakpoint-32 3 3.09712\nreverse_step_breakpoint-32-no-syscallbuf 3 3.14195\nreverse_step_signal-32 3 3.29368\nreverse_step_signal-32-no-syscallbuf 3 3.35527\nreverse_step_threads2-32 3 3.66363\nreverse_step_threads2-32-no-syscallbuf 3 3.6717\nreverse_watchpoint-32 3 2.6772\nreverse_watchpoint-32-no-syscallbuf 3 2.79468\nreverse_watchpoint_syscall-32 3 5.7712\nreverse_watchpoint_syscall-32-no-syscallbuf 3 5.42939\nrun_end-32 3 1.04191\nrun_end-32-no-syscallbuf 3 1.04049\nrun_in_function-32 3 0.900408\nrun_in_function-32-no-syscallbuf 3 0.916535\nsanity-32 3 0.71032\nsanity-32-no-syscallbuf 3 0.712727\nseekticks-32 3 1.99423\nseekticks-32-no-syscallbuf 3 1.8498\nshm_checkpoint-32 3 0.939245\nshm_checkpoint-32-no-syscallbuf 3 0.913725\nsiginfo-32 3 0.712749\nsiginfo-32-no-syscallbuf 3 0.756536\nx86/sigreturn_checksum-32 3 0.663451\nx86/sigreturn_checksum-32-no-syscallbuf 3 0.632378\nsignal_stop-32 3 0.747289\nsignal_stop-32-no-syscallbuf 3 0.789135\nsignal_checkpoint-32 3 0.888263\nsignal_checkpoint-32-no-syscallbuf 3 0.923522\nsimple_script-32 3 0.161959\nsimple_script-32-no-syscallbuf 3 0.1755\nsimple_script_debug-32 3 0.876329\nsimple_script_debug-32-no-syscallbuf 3 0.861925\nsimple_winch-32 3 1.86968\nsimple_winch-32-no-syscallbuf 3 1.74261\nstack_overflow_debug-32 3 5.38016\nstack_overflow_debug-32-no-syscallbuf 3 5.08019\nstep1-32 3 0.805849\nstep1-32-no-syscallbuf 3 0.742349\nx86/step_rdtsc-32 3 0.837208\nx86/step_rdtsc-32-no-syscallbuf 3 0.879747\nstep_signal-32 3 0.841635\nstep_signal-32-no-syscallbuf 3 0.867701\nx86/string_instructions_break-32 3 6.13452\nx86/string_instructions_break-32-no-syscallbuf 3 6.81011\nx86/string_instructions_replay_quirk-32 3 6.07682\nx86/string_instructions_replay_quirk-32-no-syscallbuf 3 6.45033\nsubprocess_exit_ends_session-32 3 3.62394\nsubprocess_exit_ends_session-32-no-syscallbuf 3 4.04868\nswitch_processes-32 3 4.0944\nswitch_processes-32-no-syscallbuf 3 3.3082\nsyscallbuf_timeslice_250-32 3 0.220478\nsyscallbuf_timeslice_250-32-no-syscallbuf 3 3.58343\ntrace_version-32 3 2.79074\ntrace_version-32-no-syscallbuf 3 3.11765\nterm_trace_cpu-32 3 0.41638\nterm_trace_cpu-32-no-syscallbuf 3 0.466491\ntrace_events-32 3 0.119915\ntrace_events-32-no-syscallbuf 3 0.11621\ntty-32 3 0.147832\ntty-32-no-syscallbuf 3 0.135114\nunmap_vdso-32 3 0.240556\nunmap_vdso-32-no-syscallbuf 3 0.241763\nunwind_on_signal-32 3 0.772052\nunwind_on_signal-32-no-syscallbuf 3 0.761767\nvfork_exec-32 3 0.835302\nvfork_exec-32-no-syscallbuf 3 4.25382\nvfork_break_parent-32 3 0.841462\nvfork_break_parent-32-no-syscallbuf 3 0.834457\nvsyscall_singlestep-32 3 0.0212182\nvsyscall_singlestep-32-no-syscallbuf 3 0.0217498\nwatch_code-32 3 1.55016\nwatch_code-32-no-syscallbuf 3 1.52215\nwatchpoint_cond-32 3 0.761356\nwatchpoint_cond-32-no-syscallbuf 3 0.742508\nwhen-32 3 0.747301\nwhen-32-no-syscallbuf 3 0.762781\nclose_range 2 0.148235\nclose_range-no-syscallbuf 2 0.144619\ndlchecksum 2 0.172606\ndlchecksum-no-syscallbuf 2 0.15371\nepoll_many 2 0.173947\nepoll_many-no-syscallbuf 2 0.171837\nepoll_pwait2 2 1.21091\nepoll_pwait2-no-syscallbuf 2 1.16894\nfutex_invalid_op 2 0.144616\nfutex_invalid_op-no-syscallbuf 2 0.165618\nfutex_restart_race 2 0.24007\nfutex_restart_race-no-syscallbuf 2 0.203436\nfutex_restart_clone 2 0.170832\nfutex_restart_clone-no-syscallbuf 2 0.157809\nioctl_br 2 0.297665\nioctl_br-no-syscallbuf 2 0.406779\nmremap_dontunmap 2 0.167215\nmremap_dontunmap-no-syscallbuf 2 0.149812\nppoll_deliver 2 0.160526\nppoll_deliver-no-syscallbuf 2 0.159987\nx86/rdtsc_flags 2 0.137952\nx86/rdtsc_flags-no-syscallbuf 2 0.129515\nx86/signal_xmm_state 2 3.57247\nx86/signal_xmm_state-no-syscallbuf 2 3.39495\nsigpwr 2 0.140614\nsigpwr-no-syscallbuf 2 0.140422\nsock_name_null 2 0.145081\nsock_name_null-no-syscallbuf 2 0.124984\nsysconf_conf 2 0.137988\nsysconf_conf-no-syscallbuf 2 0.135366\nchaos_oom 2 0.560681\nchaos_oom-no-syscallbuf 2 0.452135\nx86/diversion_rdtsc 2 0.872436\nx86/diversion_rdtsc-no-syscallbuf 2 0.924278\ngdb_qpasssignals 2 81.0278\ngdb_qpasssignals-no-syscallbuf 2 87.6319\nmadvise_fracture_flags 2 29.0459\nmadvise_fracture_flags-no-syscallbuf 2 44.4081\nx86/morestack_unwind 2 0.931251\nx86/morestack_unwind-no-syscallbuf 2 0.026461\nnested_detach_kill_stuck 2 5.47602\nnested_detach_kill_stuck-no-syscallbuf 2 5.4523\nx86/rdtsc_loop 2 9.70436\nx86/rdtsc_loop-no-syscallbuf 2 0.0229299\nx86/rdtsc_loop2 2 3.61317\nx86/rdtsc_loop2-no-syscallbuf 2 0.0397882\nrseq_syscallbuf 2 2.17548\nrseq_syscallbuf-no-syscallbuf 2 0.0213682\nseccomp_open 2 0.198042\nseccomp_open-no-syscallbuf 2 0.165744\nx86/syscallbuf_branch_check 2 0.19857\nx86/syscallbuf_branch_check-no-syscallbuf 2 0.0296137\nx86/syscallbuf_rdtsc_page 2 0.169948\nx86/syscallbuf_rdtsc_page-no-syscallbuf 2 0.0215339\nterm_rr_ok 2 0.183501\nterm_rr_ok-no-syscallbuf 2 0.255434\ncopy_all 2 0.893463\ncopy_all-no-syscallbuf 2 0.834937\ntick0 2 0.799063\ntick0-no-syscallbuf 2 0.782866\ntick0_less 2 0.749213\ntick0_less-no-syscallbuf 2 0.703801\nwatchpoint_unaligned2 2 0.899431\nwatchpoint_unaligned2-no-syscallbuf 2 0.904094\nclose_range-32 2 0.143941\nclose_range-32-no-syscallbuf 2 0.148777\ndlchecksum-32 2 0.181072\ndlchecksum-32-no-syscallbuf 2 0.182325\nepoll_many-32 2 0.139354\nepoll_many-32-no-syscallbuf 2 0.153966\nepoll_pwait2-32 2 1.15499\nepoll_pwait2-32-no-syscallbuf 2 1.12574\nfutex_invalid_op-32 2 0.184322\nfutex_invalid_op-32-no-syscallbuf 2 0.156609\nfutex_restart_race-32 2 0.212542\nfutex_restart_race-32-no-syscallbuf 2 0.187618\nfutex_restart_clone-32 2 0.167387\nfutex_restart_clone-32-no-syscallbuf 2 0.168281\nioctl_br-32 2 0.176593\nioctl_br-32-no-syscallbuf 2 0.151187\nmremap_dontunmap-32 2 0.155741\nmremap_dontunmap-32-no-syscallbuf 2 0.120021\nppoll_deliver-32 2 0.144606\nppoll_deliver-32-no-syscallbuf 2 0.15629\nx86/rdtsc_flags-32 2 0.145916\nx86/rdtsc_flags-32-no-syscallbuf 2 0.150495\nx86/signal_xmm_state-32 2 3.22473\nx86/signal_xmm_state-32-no-syscallbuf 2 3.29032\nsigpwr-32 2 0.133221\nsigpwr-32-no-syscallbuf 2 0.124058\nsock_name_null-32 2 0.161211\nsock_name_null-32-no-syscallbuf 2 0.146322\nsysconf_conf-32 2 0.18367\nsysconf_conf-32-no-syscallbuf 2 0.145432\nchaos_oom-32 2 0.185595\nchaos_oom-32-no-syscallbuf 2 0.16476\nx86/diversion_rdtsc-32 2 0.838864\nx86/diversion_rdtsc-32-no-syscallbuf 2 0.855848\ngdb_qpasssignals-32 2 54.7265\ngdb_qpasssignals-32-no-syscallbuf 2 81.3144\nmadvise_fracture_flags-32 2 29.5068\nmadvise_fracture_flags-32-no-syscallbuf 2 43.1837\nx86/morestack_unwind-32 2 0.966484\nx86/morestack_unwind-32-no-syscallbuf 2 0.0770165\nnested_detach_kill_stuck-32 2 5.57303\nnested_detach_kill_stuck-32-no-syscallbuf 2 5.4918\nx86/rdtsc_loop-32 2 0.149644\nx86/rdtsc_loop-32-no-syscallbuf 2 0.0242253\nx86/rdtsc_loop2-32 2 0.0696302\nx86/rdtsc_loop2-32-no-syscallbuf 2 0.0495866\nrseq_syscallbuf-32 2 2.78341\nrseq_syscallbuf-32-no-syscallbuf 2 0.02137\nseccomp_open-32 2 0.173412\nseccomp_open-32-no-syscallbuf 2 0.149496\nx86/syscallbuf_branch_check-32 2 0.222951\nx86/syscallbuf_branch_check-32-no-syscallbuf 2 0.0375623\nx86/syscallbuf_rdtsc_page-32 2 0.1562\nx86/syscallbuf_rdtsc_page-32-no-syscallbuf 2 0.0225459\nterm_rr_ok-32 2 0.178006\nterm_rr_ok-32-no-syscallbuf 2 0.164041\ncopy_all-32 2 0.830029\ncopy_all-32-no-syscallbuf 2 0.798218\ntick0-32 2 0.696756\ntick0-32-no-syscallbuf 2 0.728154\ntick0_less-32 2 0.692545\ntick0_less-32-no-syscallbuf 2 0.680031\nwatchpoint_unaligned2-32 2 0.785344\nwatchpoint_unaligned2-32-no-syscallbuf 2 0.785254\nbig_select 1 0.122241\nbig_select-no-syscallbuf 1 0.115932\nbpf_query 1 0.142361\nbpf_query-no-syscallbuf 1 0.131865\ndetach_huge_mmap 1 0.148339\ndetach_huge_mmap-no-syscallbuf 1 0.139783\nfstatat 1 0.122254\nfstatat-no-syscallbuf 1 0.146384\nx86/hlt 1 0.131581\nx86/hlt-no-syscallbuf 1 0.145791\nlandlock 1 0.123054\nlandlock-no-syscallbuf 1 0.117692\nmadvise_dontneed_private 1 0.150188\nmadvise_dontneed_private-no-syscallbuf 1 0.120028\nmadvise_misc 1 0.15378\nmadvise_misc-no-syscallbuf 1 0.15016\nmadvise_remove 1 0.146105\nmadvise_remove-no-syscallbuf 1 0.114897\nmemfd_create_efault 1 0.130846\nmemfd_create_efault-no-syscallbuf 1 0.110675\nmlock_madvise 1 0.12743\nmlock_madvise-no-syscallbuf 1 0.110031\nmount_ns_execveat 1 0.194777\nmount_ns_execveat-no-syscallbuf 1 0.181548\nnetfilter_ipv6 1 0.139157\nnetfilter_ipv6-no-syscallbuf 1 0.161424\nopenat2 1 0.121073\nopenat2-no-syscallbuf 1 0.115417\nx86/patch_syscall_restart 1 0.160512\nx86/patch_syscall_restart-no-syscallbuf 1 0.168672\nperf_event_ioctl 1 0.148594\nperf_event_ioctl-no-syscallbuf 1 0.138686\npidfd_getfd 1 0.169156\npidfd_getfd-no-syscallbuf 1 0.128923\nprctl_anon_vma_name 1 0.173153\nprctl_anon_vma_name-no-syscallbuf 1 0.140698\nptrace_attach_syscall 1 0.206087\nptrace_attach_syscall-no-syscallbuf 1 0.188015\nptrace_sigchld 1 0.145944\nptrace_sigchld-no-syscallbuf 1 0.137416\nptrace_waiter_thread 1 0.166131\nptrace_waiter_thread-no-syscallbuf 1 0.157813\nsigframe_grow_stack 1 3.1515\nsigframe_grow_stack-no-syscallbuf 1 4.08248\nvfork_done 1 2.63613\nvfork_done-no-syscallbuf 1 2.4733\nvfork_setopts 1 0.148868\nvfork_setopts-no-syscallbuf 1 0.129542\nconcurrent_signals 1 1.67194\nconcurrent_signals-no-syscallbuf 1 1.66581\ncontext_switch_after_patch 1 0.191045\ncontext_switch_after_patch-no-syscallbuf 1 0.168646\nmprotect_checkpoint 1 4.0859\nmprotect_checkpoint-no-syscallbuf 1 2.99924\npack 1 0.47493\npack-no-syscallbuf 1 0.467682\nx86/rdtsc_interfering 1 10.2643\nx86/rdtsc_interfering-no-syscallbuf 1 0.0197651\nseekticks_threads 1 4.06068\nseekticks_threads-no-syscallbuf 1 4.30202\nstep_into_lib 1 1.00011\nstep_into_lib-no-syscallbuf 1 0.970043\ntracee_unmap_vdso 1 0.0180032\ntracee_unmap_vdso-no-syscallbuf 1 0.134259\nunicode 1 0.918995\nunicode-no-syscallbuf 1 0.953097\nwhen_threads 1 1.99325\nwhen_threads-no-syscallbuf 1 1.92408\nbreakpoint_print 1 1.71038\nbreakpoint_print-no-syscallbuf 1 1.6519\nchecksum_block_open 1 0.517415\nchecksum_block_open-no-syscallbuf 1 0.327791\nlarge_file 1 0.115809\nlarge_file-no-syscallbuf 1 0.13297\nnested_detach_stop 1 1.5455\nnested_detach_stop-no-syscallbuf 1 1.46919\ntransient_fault_replay_all 1 0.17006\ntransient_fault_replay_all-no-syscallbuf 1 0.155604\nvfork_done_clone 1 2.52903\nvfork_done_clone-no-syscallbuf 1 2.56115\nbig_select-32 1 0.132507\nbig_select-32-no-syscallbuf 1 0.11967\nbpf_query-32 1 0.124146\nbpf_query-32-no-syscallbuf 1 0.122492\ndetach_huge_mmap-32 1 0.167636\ndetach_huge_mmap-32-no-syscallbuf 1 0.180431\nfstatat-32 1 0.117417\nfstatat-32-no-syscallbuf 1 0.10673\nx86/hlt-32 1 0.139103\nx86/hlt-32-no-syscallbuf 1 0.128721\nlandlock-32 1 0.15054\nlandlock-32-no-syscallbuf 1 0.104344\nmadvise_dontneed_private-32 1 0.126815\nmadvise_dontneed_private-32-no-syscallbuf 1 0.137481\nmadvise_misc-32 1 0.139222\nmadvise_misc-32-no-syscallbuf 1 0.136681\nmadvise_remove-32 1 0.111512\nmadvise_remove-32-no-syscallbuf 1 0.104271\nmemfd_create_efault-32 1 0.152346\nmemfd_create_efault-32-no-syscallbuf 1 0.101308\nmlock_madvise-32 1 0.134032\nmlock_madvise-32-no-syscallbuf 1 0.117457\nmount_ns_execveat-32 1 0.182306\nmount_ns_execveat-32-no-syscallbuf 1 0.198207\nnetfilter_ipv6-32 1 0.148315\nnetfilter_ipv6-32-no-syscallbuf 1 0.127724\nopenat2-32 1 0.137687\nopenat2-32-no-syscallbuf 1 0.123855\nx86/patch_syscall_restart-32 1 0.127288\nx86/patch_syscall_restart-32-no-syscallbuf 1 0.115894\nperf_event_ioctl-32 1 0.123464\nperf_event_ioctl-32-no-syscallbuf 1 0.139612\npidfd_getfd-32 1 0.128887\npidfd_getfd-32-no-syscallbuf 1 0.129746\nprctl_anon_vma_name-32 1 0.156351\nprctl_anon_vma_name-32-no-syscallbuf 1 0.142877\nptrace_attach_syscall-32 1 0.199311\nptrace_attach_syscall-32-no-syscallbuf 1 0.183041\nptrace_sigchld-32 1 0.139781\nptrace_sigchld-32-no-syscallbuf 1 0.139409\nptrace_waiter_thread-32 1 0.164846\nptrace_waiter_thread-32-no-syscallbuf 1 0.12313\nsigframe_grow_stack-32 1 2.57634\nsigframe_grow_stack-32-no-syscallbuf 1 3.44717\nvfork_done-32 1 1.28647\nvfork_done-32-no-syscallbuf 1 1.25884\nvfork_setopts-32 1 0.119982\nvfork_setopts-32-no-syscallbuf 1 0.132373\nconcurrent_signals-32 1 1.68507\nconcurrent_signals-32-no-syscallbuf 1 1.74336\ncontext_switch_after_patch-32 1 0.17055\ncontext_switch_after_patch-32-no-syscallbuf 1 0.166858\nmprotect_checkpoint-32 1 5.38933\nmprotect_checkpoint-32-no-syscallbuf 1 5.27459\npack-32 1 0.46317\npack-32-no-syscallbuf 1 0.44023\nx86/rdtsc_interfering-32 1 0.0194198\nx86/rdtsc_interfering-32-no-syscallbuf 1 0.0188702\nseekticks_threads-32 1 2.5432\nseekticks_threads-32-no-syscallbuf 1 2.45435\nstep_into_lib-32 1 0.840179\nstep_into_lib-32-no-syscallbuf 1 0.772617\ntracee_unmap_vdso-32 1 0.0179555\ntracee_unmap_vdso-32-no-syscallbuf 1 0.0167012\nunicode-32 1 0.73177\nunicode-32-no-syscallbuf 1 0.74138\nwhen_threads-32 1 1.72537\nwhen_threads-32-no-syscallbuf 1 1.69476\nbreakpoint_print-32 1 1.26928\nbreakpoint_print-32-no-syscallbuf 1 1.31566\nchecksum_block_open-32 1 0.391778\nchecksum_block_open-32-no-syscallbuf 1 0.305321\nlarge_file-32 1 0.125391\nlarge_file-32-no-syscallbuf 1 0.107834\nnested_detach_stop-32 1 1.39362\nnested_detach_stop-32-no-syscallbuf 1 1.39936\ntransient_fault_replay_all-32 1 0.164634\ntransient_fault_replay_all-32-no-syscallbuf 1 0.181707\nvfork_done_clone-32 1 1.1347\nvfork_done_clone-32-no-syscallbuf 1 1.10141\n---\n"
  },
  {
    "path": "scripts/github-actions-build.sh",
    "content": "#!/bin/bash\n\nset +x # echo commands\nset -e # default to exiting on error\"\n\nuname -a\n\nEXTRA_PACKAGES=\nMACHINE_TYPE=`uname -m`\nif [ $MACHINE_TYPE == 'x86_64' ]; then\n  EXTRA_PACKAGES=g++-multilib\nfi\n\nsudo apt-get update -y\nsudo apt-get dist-upgrade -f -y\nsudo apt-get install -y $EXTRA_PACKAGES cmake g++ pkg-config zlib1g-dev git python-dev-is-python3 libacl1-dev ninja-build manpages-dev capnproto libcapnp-dev gdb lldb python3-pexpect libzstd1 libzstd-dev jq\n\nmkdir obj\ncd obj\ncmake -G Ninja -DCMAKE_BUILD_TYPE=DEBUG -Dstaticlibs=FALSE ..\nninja\n"
  },
  {
    "path": "scripts/github-actions-test.sh",
    "content": "#!/bin/bash\n\nset +x # echo commands\n\n# Enable perf events for rr\necho 0 | sudo tee /proc/sys/kernel/perf_event_paranoid > /dev/null\n# Enable ptrace-attach to any process. This lets us get more data when tests fail.\necho 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope > /dev/null\n# Disable AppArmor restrictions on user namespaces, which our tests need to use\n(echo 0 | sudo tee /proc/sys/kernel/apparmor_restrict_unprivileged_userns) > /dev/null || true\nlet halfproc=`nproc`/2\ncd obj\nmkdir -p Testing/Temporary\nmv ../scripts/github-actions-CTestCostData.txt Testing/Temporary/CTestCostData.txt\nctest -j$halfproc --verbose\n\nSTATUS=$?\nif [[ $STATUS != 0 ]]; then\n  mkdir $GITHUB_WORKSPACE/failed-tests\n  #cp -a Testing/Temporary/CTestCostData.txt $GITHUB_WORKSPACE/failed-tests/rr-test-ctestcostdata.txt\n  cd /tmp\n  rm rr-test-cpu-lock || true\n  for dir in rr-test-*; do\n    echo \"Packing test /tmp/$dir\"\n    $GITHUB_WORKSPACE/obj/bin/rr pack $dir/latest-trace\n    tar zcf $GITHUB_WORKSPACE/failed-tests/$dir.tar.gz $dir\n    rm -rf $dir\n  done\nfi\n\nexit $STATUS\n"
  },
  {
    "path": "scripts/reformat.sh",
    "content": "#!/bin/sh\n\nfind src -regex '.*\\.\\(c\\|h\\|cc\\)$'|xargs clang-format -style=file -i\n"
  },
  {
    "path": "scripts/rr-collect-symbols.py",
    "content": "#!/usr/bin/env python3\n\nimport errno\nimport glob\nimport os\nimport re\nimport shutil\nimport subprocess\nimport sys\nimport tempfile\nfrom urllib.request import urlretrieve\nfrom urllib.error import HTTPError, ContentTooShortError\n\n# Usage: rr-collect-symbols.py <trace-dir> [<url> | <path>]\n#\n# Given a <url>, downloads the zip/.tar.zst file at <url>, uncompresses it,\n# runs \"gunzip\" on any .gz files, and for any ELF files found whose build-ids\n# match the build-id of an ELF file in the trace, moves it into the trace.\n#\n# Given a <path>, which must contain a .build-id directory with the usual\n# structure (e.g. as Ubuntu and Fedora create under /usr/lib/debug), searches\n# the directory tree for any ELF files whose build-ids match the build-id of\n# an ELF file in the trace and copies them into the trace. <path> defaults to\n# \"/usr/lib/debug\", which will grab any available system debuginfo files\n# in Ubuntu and Fedora at least.\n#\n# This script assumes that the trace-dir has been packed via `rr pack` so all\n# relevant files actually appear in the trace-dir.\n# It also assumes rr is on the PATH.\n#\n# The debuginfo files are placed in the trace under a \"debug\" subdirectory,\n# in a \".build-id\" subdirectory with the usual structure.\n#\n# If a debuginfo file contains a .gnu_debugaltlink section then we also\n# attempt to find the referenced file and copy it into the trace with the\n# same file name as the .debug file, but with a .sup suffix.\n\nif len(sys.argv) < 2:\n    print(\"Usage: rr-collect-symbols.py <trace-dir> [<url> | <path>]\", file=sys.stderr)\n    sys.exit(1)\ntrace_dir = sys.argv[1]\n\nif len(sys.argv) < 3:\n    source = \"/usr/lib/debug\"\nelse:\n    source = sys.argv[2]\n\nrr_buildid = subprocess.Popen([\"rr\", \"buildid\"],\n                              stdin=subprocess.PIPE,\n                              stdout=subprocess.PIPE)\n\ndef build_id_for(file):\n    global rr_buildid\n    rr_buildid.stdin.write((\"%s\\n\"%file).encode('utf-8'))\n    try:\n        rr_buildid.stdin.flush()\n    except BrokenPipeError:\n        print(\"Can't write to rr, termination code %s\"%rr_buildid.returncode, file=sys.stderr)\n        sys.exit(2)\n    return rr_buildid.stdout.readline().rstrip().decode('utf-8')\n\naltref_regex = re.compile(rb\"^\\s+\\[\\s*0\\]\\s+(.*)\");\n\ndef find_altref(file):\n    proc = subprocess.Popen([\"readelf\", \"-p\", \".gnu_debugaltlink\", file], stdout=subprocess.PIPE, stderr=subprocess.DEVNULL)\n    try:\n        for line in proc.stdout:\n            m = altref_regex.match(line)\n            if m:\n                return m.group(1).rstrip()\n    finally:\n        proc.wait()\n    return None\n\ndef find_altref_for_trace_file(trace_file, altref):\n    proc = subprocess.Popen([\"rr\", \"filename\", trace_file], stdout=subprocess.PIPE)\n    try:\n        for line in proc.stdout:\n            file = line.rstrip()\n            altref_file = os.path.join(os.path.dirname(file), altref)\n            if os.path.isfile(altref_file):\n                return altref_file\n    finally:\n        proc.wait()\n    return None\n\ndef mkdir_p(path):\n    try:\n        os.makedirs(path)\n    except OSError as exc:\n        if exc.errno == errno.EEXIST and os.path.isdir(path):\n            pass\n        else:\n            raise\n\n# 'dst' must be a complete file name, not a directory.\ndef copy_file(src, dst):\n    try:\n        # Remove the destination file in case it's a hard link\n        # or owned by someone else.\n        os.remove(dst)\n    except:\n        pass\n    shutil.copy(src, dst)\n\n# 'dst' must be a complete file name, not a directory\ndef create_link(src, dst):\n    try:\n        # Remove the destination file in case it's wrong.\n        os.remove(dst)\n    except:\n        pass\n    os.symlink(src, dst)\n\ndef collect_trace_build_ids():\n    ret = {}\n    for file in glob.iglob(\"%s/mmap_*\"%trace_dir):\n        build_id = build_id_for(file)\n        if build_id:\n            ret[build_id] = True\n            altref = find_altref(file)\n            if altref:\n                altref_file = find_altref_for_trace_file(file, altref)\n                if not altref_file:\n                    print(\"WARNING: Can't find alt file %s for %s\"%(altref, file))\n                    continue\n                dir = \"%s/debug/.build-id/%s\"%(trace_dir, build_id[:2])\n                mkdir_p(dir)\n                copy_file(altref_file, \"%s/%s.sup\"%(dir, build_id[2:]))\n    return ret\n\ntrace_build_ids = collect_trace_build_ids()\n\ndef collect_archive(url):\n    is_tar_zst = url.endswith(\".tar.zst\")\n    tmp_dir = tempfile.mkdtemp(dir=trace_dir)\n    if is_tar_zst:\n        tmp_file_name = \"%s/archive.tar.zst\"%tmp_dir\n    else:\n        # Assume its a ZIP\n        tmp_file_name = \"%s/archive.zip\"%tmp_dir\n    try:\n        (file, headers) = urlretrieve(url, tmp_file_name)\n    except (HTTPError, ContentTooShortError) as exc:\n        print(\"Failed to load archive %s: %s\"%(url, exc), file=sys.stderr)\n        sys.exit(2)\n    if is_tar_zst:\n        subprocess.check_call([\"tar\", \"-C\", tmp_dir, \"-I\", \"zstd\", \"-xvf\", file])\n    else:\n        subprocess.check_call([\"unzip\", \"-d\", tmp_dir, file])\n    os.remove(file)\n\n    for root, dirs, files in os.walk(tmp_dir):\n        for name in files:\n            file = os.path.join(root, name)\n            if file.endswith(\".gz\"):\n                subprocess.check_call([\"gunzip\", file])\n                file = file[:-3]\n            build_id = build_id_for(file)\n            if build_id and build_id in trace_build_ids:\n                dir = \"%s/debug/.build-id/%s\"%(trace_dir, build_id[:2])\n                mkdir_p(dir)\n                dst = \"%s/%s.debug\"%(dir, build_id[2:])\n                os.rename(file, dst)\n            else:\n                os.remove(file)\n\n    shutil.rmtree(tmp_dir)\n\ndef collect_filesystem(path):\n    for root, dirs, files in os.walk(path):\n        for name in files:\n            file = os.path.join(root, name)\n            if not os.path.islink(file):\n                build_id = build_id_for(file)\n                if build_id and build_id in trace_build_ids:\n                    dir = \"%s/debug/.build-id/%s\"%(trace_dir, build_id[:2])\n                    mkdir_p(dir)\n                    copy_file(file, \"%s/%s.debug\"%(dir, build_id[2:]))\n                    altref = find_altref(file)\n                    if altref:\n                        altref = altref.decode('utf-8')\n                        altref_file = os.path.join(os.path.dirname(file), altref)\n                        copy_file(altref_file, \"%s/%s.sup\"%(dir, build_id[2:]))\n                        if altref.startswith(\"../../../.dwz/\"):\n                            mkdir_p(\"%s/.dwz\"%trace_dir)\n                            src = \"../debug/.build-id/%s/%s.sup\"%(build_id[:2], build_id[2:])\n                            create_link(src, \"%s/.dwz/%s\"%(trace_dir, altref[14:]))\n                        elif altref.startswith(\"../../.dwz/\"):\n                            mkdir_p(\"%s/debug/.dwz\"%trace_dir)\n                            src = \"../.build-id/%s/%s.sup\"%(build_id[:2], build_id[2:])\n                            create_link(src, \"%s/debug/.dwz/%s\"%(trace_dir, altref[11:]))\n                        elif altref.startswith(\"../.dwz/\"):\n                            mkdir_p(\"%s/debug/.build-id/.dwz\"%trace_dir)\n                            src = \"../%s/%s.sup\"%(build_id[:2], build_id[2:])\n                            create_link(src, \"%s/debug/.build-id/.dwz/%s\"%(trace_dir, altref[8:]))\n\nif re.search(\"^[^:/]+:\", source):\n    collect_archive(source)\nelse:\n    collect_filesystem(source)\n\nrr_buildid.terminate()\n"
  },
  {
    "path": "scripts/rr-gdb-script-host.py",
    "content": "#!/usr/bin/env python3\n\"\"\" rr-gdb-script-host.py <user-gdb-script> <primary binary name>\"\"\"\n# Performs a limited emulation of the runtime environment of gdb scripts so that\n# we can run them for `rr sources` to locate debug information.\nfrom typing import Optional, List, Callable, Type\nimport logging\nimport os\nimport signal\nimport sys\n\ndef strip_prefix(s: str, needle: str) -> Optional[str]:\n    if s.startswith(needle):\n        return s[len(needle):]\n\n    return None\n\ndef print_wrapper(*args, **kwargs):\n    # Don't allow the script to print to stdout and interfere\n    # with our communication with the rr process.\n    f = kwargs.get(\"file\")\n    if f is None or f == sys.stdout:\n        kwargs[\"file\"] = sys.stderr\n    print(*args, **kwargs)\n\nGdbNewObjfileEventCallback = Callable[[object], None]\n\nclass DebuggerExtensionCommand:\n    def __init__(self, *args, **kwargs):\n        logging.debug(\"DebuggerExtensionCommand(%s, %s)\" % (args, kwargs))\n\nclass GdbScriptHost:\n    \"\"\" The filename of the main symbol file \"\"\"\n    _filename: str = \"\"\n    \"\"\" The current value of the gdb dir \"\"\"\n    _dir: str = \"\"\n    \"\"\" The current value of debug-file-directory \"\"\"\n    debug_file_directory: str = \"/usr/lib/debug\"\n\n    new_objfile_events: List[GdbNewObjfileEventCallback] = []\n\n    def __init__(self, *args, **kwargs):\n        self._filename = args[0]\n\n    def show(self, cmd: str) -> Optional[str]:\n        cmd.rstrip()\n        if cmd == \"debug-file-directory\":\n            return self.debug_file_directory\n        if cmd == \"dir\":\n            return \"Source directories searched: %s:$cdir:$cwd\"%self._dir\n\n        return None\n\n    def set(self, cmd: str) -> str:\n        dfd = strip_prefix(cmd, \"debug-file-directory \")\n        if dfd:\n            self.debug_file_directory = dfd\n            # Prints nothing upon success.\n            return \"\"\n\n        # This seems to be the default error message.\n        return \"No symbol table is loaded.  Use the \\\"file\\\" command.\"\n\n    def execute_script(self, script: str):\n        gdb_api: GdbApiRoot = GdbApiRoot(self)\n        exec(script, {'gdb': gdb_api, \"print\": print_wrapper})\n\n    def new_objfile(self, f: str):\n        new_objfile: GdbNewObjfile = GdbNewObjfile(self, f)\n        new_objfile_event: GdbNewObjfileEvent = GdbNewObjfileEvent(self, new_objfile)\n        for callback in self.new_objfile_events:\n            callback(new_objfile_event)\n\nclass GdbApiObject(object):\n    def __init__(self, *args, **kwargs):\n        self.gdb = args[0]\n\n    def __getattr__(self, attr):\n        logging.warning(\"Accessing unsupported GDB api %s.%s\" % (self.__class__.__name__, attr))\n\nclass GdbProgspace(GdbApiObject):\n    filename: str\n\n    def __init__(self, *args, **kwargs):\n        GdbApiObject.__init__(self, *args, **kwargs)\n        self.filename = self.gdb._filename\n\nclass GdbNewObjfile(GdbApiObject):\n    filename: str\n    def __init__(self, *args, **kwargs):\n        GdbApiObject.__init__(self, *args, **kwargs)\n        self.filename = args[1]\n\nclass GdbNewObjfileEvent(GdbApiObject):\n    new_objfile: GdbNewObjfile\n\n    def __init__(self, *args, **kwargs):\n        GdbApiObject.__init__(self, *args, **kwargs)\n        self.new_objfile = args[1]\n\nclass GdbNewObjfileEvents(GdbApiObject):\n    def connect(self, c: GdbNewObjfileEventCallback):\n        logging.debug(\"EventRegistry.connect\")\n        self.gdb.new_objfile_events.append(c)\n\nclass GdbApiEvents(GdbApiObject):\n    _new_objfile: Optional[GdbNewObjfileEvents] = None\n\n    @property\n    def new_objfile(self) -> GdbNewObjfileEvents:\n        logging.debug(\"gdb.events.new_objfile\")\n        if self._new_objfile is None:\n            self._new_objfile = GdbNewObjfileEvents(self.gdb)\n        return self._new_objfile\n\nclass GdbApiRoot(GdbApiObject):\n    _events: Optional[GdbApiEvents] = None\n    _current_progspace: Optional[GdbProgspace] = None\n\n    def execute(self, command: str, from_tty: bool = False, to_string: bool = False) -> Optional[str]:\n        logging.debug(\"gdb.execute(\\\"%s\\\", from_tty=%s, to_string=%s)\" % (command, str(from_tty), str(to_string)))\n        if from_tty:\n            logging.warning(\"Unsupported gdb.execute with from_tty == True\")\n            return None\n\n        remainder = strip_prefix(command, \"show \")\n        if remainder:\n            r = self.gdb.show(remainder)\n            if to_string:\n                return r\n            else:\n                print(r, file=sys.stderr)\n                return None\n        remainder = strip_prefix(command, \"set \")\n        if remainder:\n            r = self.gdb.set(remainder)\n            if to_string:\n                return r\n            else:\n                print(r, file=sys.stderr)\n                return None\n        remainder = strip_prefix(command, \"dir \")\n        if remainder:\n            self.gdb._dir = remainder\n            s = \"Source directories searched: %s:$cdir:$cwd\"%remainder\n            if to_string:\n                return s\n            else:\n                print(s, file=sys.stderr)\n                return None\n\n        logging.warning(\"Unsupported gdb.execute \\\"%s\\\"\"%command)\n        return None\n\n    def lookup_global_symbol(self, s: str) -> Optional[object]:\n        #logging.debug(\"gdb.lookup_global_symbol(\\\"%s\\\")\"%s)\n        logging.warning(\"gdb.lookup_global_symbol(\\\"%s\\\") is not yet implemented, pretending we found something\"%s)\n        return object()\n\n    def current_progspace(self) -> GdbProgspace:\n        logging.debug(\"gdb.current_progspace()\")\n        if self._current_progspace is None:\n            self._current_progspace = GdbProgspace(self.gdb)\n        return self._current_progspace\n\n    @property\n    def events(self) -> GdbApiEvents:\n        logging.debug(\"gdb.events\")\n        if self._events is None:\n            self._events = GdbApiEvents(self.gdb)\n        return self._events\n\n    @property\n    def COMMAND_USER(self) -> int:\n        return 13\n\n    @property\n    def Command(self) -> Type[DebuggerExtensionCommand]:\n        return DebuggerExtensionCommand\n\nif __name__ == '__main__':\n    with open(sys.argv[1], 'r') as user_script_file:\n        user_script = user_script_file.read()\n        host = GdbScriptHost(sys.argv[2])\n        try:\n            host.execute_script(user_script)\n        except NameError as e:\n            if getattr(e, \"name\", None) == \"python\" or e == \"NameError: name 'python' is not defined\":\n                # This might be a gdb script that wraps a python script.\n                start = user_script.find(\"python\") + len(\"python\")\n                end = user_script.find(\"end\")\n                if end == -1:\n                    raise(e)\n                user_script = user_script[start:end]\n                try:\n                    host.execute_script(user_script)\n                except:\n                    raise(e)\n\n        print(\"%s\\n%s\" % (host.debug_file_directory, host._dir), flush=True)\n        for line in sys.stdin:\n            line = line.rstrip()\n            logging.debug(\"Processing %s\"%line)\n            host.new_objfile(line)\n            print(\"%s\\n%s\" % (host.debug_file_directory, host._dir), flush=True)\n"
  },
  {
    "path": "scripts/rr_completion",
    "content": "# vi:syntax=sh\n#\n# completion script for rr commands (to be sourced)\n\n_rr_subcmd_completion() {\n    local cmd=$1\n    local short_opts=$(rr help $cmd | sed -n 's/\\s*-\\([a-zA-Z]\\),.*/-\\1/p')\n    local long_opts=$(rr help $cmd | sed -n 's/.*--\\([^= ]*\\).*/--\\1/p')\n    echo \"$short_opts\" \"$long_opts\"\n}\n\n_rr_completion() {\n    COMPREPLY=()\n    local rr_commands=\"$(rr --list-commands | cut -s -d ' ' -f 3)\"\n\n    # completion for rr\n    if [ $COMP_CWORD -eq 1 ]; then\n        COMPREPLY=( $( compgen -W \"$rr_commands\" -- \"${COMP_WORDS[1]}\" ) )\n        return\n    fi\n\n    # completion for rr <command>'s options\n    local cmd=\"$(echo \"${COMP_WORDS[1]}\" | tr -d '[:space:]')\"\n\n    if [ \"$(echo $rr_commands | grep -w \"$cmd\")\" ] ; then\n        COMPREPLY=( $( compgen -W \"$(_rr_subcmd_completion \"$cmd\")\" -f -- \"${COMP_WORDS[COMP_CWORD]}\" ) )\n    fi\n}\ncomplete -F _rr_completion rr\n"
  },
  {
    "path": "scripts/rr_completion.zsh",
    "content": "#compdef rr\n\n_rr() {\n  # allow overridding rr with another command (e.g. if multiple versions are installed)\n  zstyle -s :completion${curcontext}options command rr\n  : ${rr:=rr}\n\n  _rr_subcommands() {\n    $rr --list-commands | cut -s -d ' ' -f 3\n  }\n  _rr_traces() {\n    $rr ls | grep -v '^cpu_lock$'\n  }\n\n  _arguments -C \\\n    '1:subcommand:($(_rr_subcommands))' \\\n    '*::arg:->args'\n\n  case $state in\n    args) ;;\n    *) return;;\n  esac\n\n  # different subcommands can have different options. show the appropriate options for each.\n  # this is not ideal; `reply=` forces zsh to rerun `rr help` each time you hit tab.\n  # the alternative though is rewriting half the code in _arguments.\n  zstyle -e ':completion:*:*:rr:*:options' command \\\n    'reply=( '${(q)service}' help ${words:#-*} )'\n\n  case $line[1] in\n    # complete a command, then delegate to that command's completion script\n    # -A means \"don't use _normal until we've completed a non-option\"\n    record) _arguments -A '-*' '1:command: _precommand' '*:: :_normal -p $service' --;;\n    replay|rerun|ps|sources|traceinfo|pack|dump) _arguments '*:trace:($(_rr_traces))' --;;\n    help) _arguments ':subcommand:($(_rr_subcommands))' --;;\n    explicit-sources|filename) _gnu_generic;;\n    *) _arguments --;\n  esac\n}\n"
  },
  {
    "path": "scripts/signal-rr-recording.sh",
    "content": "#!/usr/bin/env bash\n\nsignal=$1\nif [[ \"$signal\" == \"\" ]]; then\n    echo \"Usage: $0 <signal>\" >&2\n    echo \"Sends <signal> to all processes being recorded by rr\" >&2\n    exit 1\nfi\n\nfunction signal_descendants { pid=$1\n    for child in `ps -o pid= --ppid $pid`; do\n        echo Sending $signal to $child\n        kill -s $signal $child\n        signal_descendants $child\n    done\n}\n\nfor rr_pid in `pidof rr` ; do\n    if cat /proc/$rr_pid/cmdline | tr '\\0' '\\n' | head -n2 | tail -n1 | grep -qz '\\(^record$\\)\\|/'  ; then\n        signal_descendants $rr_pid\n    fi\ndone\n"
  },
  {
    "path": "scripts/update-gh-pages.sh",
    "content": "#!/usr/bin/env bash\n\nfunction fatal { why=$1;\n    echo \"[FATAL]\" $why >&2\n    exit 1\n}\n\nrev=HEAD\nif [[ $1 != \"\" ]]; then\n  rev=$1\nfi\nver=`git name-rev --name-only --tags $rev`\nif [[ $ver == undefined ]]; then\n  fatal \"No tag found\"\nfi\n\necho \"Updating repo ...\"\ngit checkout gh-pages || fatal \"Failed to checkout gh-pages branch.\"\n\nverfile=index.html\necho \"Patching $verfile with new version $ver ...\"\nsed -i \"s/<span class=ver>[^<]*</<span class=ver>$ver</g\" index.html\n\necho \"Showing diff ...\"\ngit diff -p -U8\necho -n \"Is this what you expected to see? [Y/n] \"\nread ok\nif [[ $ok != \"Y\" ]]; then\n    fatal \"Oops.  Aborting release by user request.\"\nfi\n\ngit commit -a -m \"Release $ver.\"\necho \"Done!  Publish the new version using 'git push'.\"\n"
  },
  {
    "path": "scripts/zen_workaround.py",
    "content": "#!/usr/bin/env python3\n\nimport argparse\nimport os\nimport struct\nimport sys\n\nimport array\nfrom os.path import join\nfrom fcntl import ioctl\nfrom enum import Enum\n\nparser = argparse.ArgumentParser()\ngroup = parser.add_mutually_exclusive_group()\ngroup.add_argument('--reset', action='store_true')\ngroup.add_argument('--check', action='store_true')\nargs = parser.parse_args()\n\n# MSRC001_1020: Load-Store Configuration\nMSR = 0xc0011020\n# Disable SpecLockMap\nBIT = 1 << 54\n\n\nEFIVARS_PATH   = '/sys/firmware/efi/efivars/'\nSecureBoot = Enum(\"SecureBoot\", \"enabled disabled checkfailed\")\ndef is_secure_boot_enabled():\n    if not os.path.isdir(EFIVARS_PATH):\n        return SecureBoot.checkfailed\n\n    files = [f for f in os.listdir(EFIVARS_PATH) if f.startswith(\"SecureBoot-\")]\n    var_path = join(EFIVARS_PATH, files[0])\n    attr = []\n    data = []\n    try:\n        if os.path.exists(var_path):\n            with open(var_path, 'rb') as fd:\n                buffer = fd.read()\n\n                attr = buffer[:4]\n                data = buffer[4:]\n        if int(data[0]) == 1:\n            return SecureBoot.enabled\n        else:\n            return SecureBoot.disabled\n    except:\n        return SecureBoot.checkfailed\n\n\nif not os.path.exists('/dev/cpu/0/msr'):\n    ret = os.system('modprobe msr')\n    if ret:\n        sys.exit(ret)\n\ndef read_msr(cpu):\n    try:\n        msr = os.open('/dev/cpu/{}/msr'.format(cpu), os.O_RDONLY)\n    except PermissionError as e:\n        sys.stderr.write(str(e) + '\\n')\n        print(\"Permission denied opening MSR for reading.\")\n        print(\"Try running as root / with sudo.\")\n        sys.exit(1)\n    try:\n        os.lseek(msr, MSR, os.SEEK_SET)\n        (val,) = struct.unpack('<q', os.read(msr, 8))\n        return val\n    except PermissionError as e:\n        sys.stderr.write(str(e) + '\\n')\n        print(\"Permission denied on reading from MSR.\")\n        sys.exit(1)\n    except OSError as e:\n        sys.stderr.write(str(e) + '\\n')\n        print(\"General error on reading from MSR.\")\n        sys.exit(1)\n    finally:\n        os.close(msr)\n\ncpus = [cpu for cpu in os.listdir('/dev/cpu') if cpu.isdigit()]\n\nif not args.check:\n    for cpu in cpus:\n        val = read_msr(cpu)\n        if args.reset:\n            if val & BIT == 0:\n                continue\n            val &= ~BIT\n        else:\n            if val & BIT:\n                continue\n            val |= BIT\n        try:\n            msr = os.open('/dev/cpu/{}/msr'.format(cpu), os.O_WRONLY)\n        except PermissionError:\n            sys.stderr.write(str(e) + '\\n')\n            print(\"Permission denied opening MSR for writing.\")\n            print(\"Try running as root / with sudo.\")\n            sys.exit(1)\n\n        try:\n            os.lseek(msr, MSR, os.SEEK_SET)\n            os.write(msr, struct.pack('<q', val))\n        except PermissionError as e:\n            check = is_secure_boot_enabled() \n            sys.stderr.write(str(e) + '\\n')\n            print(\"Permission denied writing to MSR.\")\n            if check == SecureBoot.enabled:\n                print(\"Secure Boot is enabled, which causes this error. Try disabling Secure Boot.\")\n            elif check == SecureBoot.disabled:\n                print(\"Secure Boot is disabled so that's not the problem.\")\n            print(\"You may want to use another approach, please see https://github.com/rr-debugger/rr/wiki/Zen.\")\n            sys.exit(1)\n        except OSError as e:\n            sys.stderr.write(str(e) + '\\n')\n            print(\"General error on writing to MSR.\")\n            sys.exit(1)\n        finally:\n            os.close(msr)\n\nssb_status = 'unknown'\nif not args.reset:\n    import ctypes\n    lib = ctypes.CDLL(None)\n    prctl = lib.prctl\n    prctl.restype = ctypes.c_int\n    prctl.argtypes = (ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong, ctypes.c_ulong)\n    PR_GET_SPECULATION_CTRL = 52\n    PR_SET_SPECULATION_CTRL = 53\n    PR_SPEC_STORE_BYPASS = 0\n    PR_SPEC_PRCTL = 1 << 0\n    PR_SPEC_DISABLE = 1 << 2\n    # When the kernel does per-process SSB mitigation via prctl or seccomp, it touches the same\n    # MSR that we changed, but does so based on a value of the MSR it got at boot time, so it\n    # effectively will reset the bit we just set if it wasn't already set at boot time.\n    # This doesn't happen when the SSB mitigation is either entirely on or off.\n    # This is specific to Zen and Zen+, because Zen 2 doesn't require the kernel to change the MSR.\n    # Check whether the kernel does per-process SSB mitigation, and if it does, enable it for this\n    # process.\n    ssb_mode = prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0)\n    if ssb_mode >= 0 and ssb_mode & PR_SPEC_PRCTL:\n        mitigated = (prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, PR_SPEC_DISABLE, 0, 0) == 0)\n        if not mitigated:\n            print('Failed to enable SSB mitigation')\n        else:\n            ssb_status = 'mitigated'\n    else:\n        ssb_status = 'immutable'\n\n\nmsrs = [read_msr(cpu) & BIT for cpu in cpus]\n\nif all(msr for msr in msrs):\n    if ssb_status in ('mitigated', 'immutable') or args.check:\n        print('Zen workaround in place')\n    else:\n        print('Zen workaround maybe in place.')\nelif args.reset or args.check:\n    if all(not msr for msr in msrs):\n        print('Zen workaround disabled')\n    elif args.reset:\n        print('Zen workaround somehow not entirely disabled?')\n    else:\n        print('Zen workaround not entirely enabled?')\nelse:\n    print('Zen workaround does not stick. Please see https://github.com/rr-debugger/rr/wiki/Zen')\n"
  },
  {
    "path": "scripts/zen_workaround.service",
    "content": "# systemd service for AMD Zen `rr` workaround\n# See https://github.com/rr-debugger/rr/wiki/Zen for more details\n# To install:\n#   - Save this file as `/etc/systemd/system/zen_workaround.service`\n#   - Download the `zen_workaround.py` script to a secure location, example:\n#     - sudo mkdir -p /usr/share/zen_workaround\n#     - cd /usr/share/zen_workaround\n#     - curl -L https://github.com/rr-debugger/rr/raw/master/scripts/zen_workaround.py | sudo tee -a zen_workaround.py >/dev/null\n#     - chmod +x ./zen_workaround.py\n#   - run `sudo systemctl enable zen_workaround` to enable on startup\n#   - run `sudo systemctl start zen_workaround` to manually start it immediately\n#   - run `systemctl status zen_workaround` to ensure that it completed successfully on your hardware\n\n[Unit]\nDescription           = Startup script for rr zen workaround\n\n[Service]\n# Step to actually run `zen_workaround.py`.\nExecStart             =+/usr/share/zen_workaround/zen_workaround.py\n\n# Only run this once, report it as \"(active)\" even after we've exited.\nType                  = oneshot\nRemainAfterExit       = yes\n\n[Install]\nWantedBy             = default.target\n"
  },
  {
    "path": "snap/snapcraft.yaml",
    "content": "name: rr\nbase: core20 # the base snap is the execution environment for this snap\nversion: git\nsummary: low-overhead record-replay debugging tool\ndescription: |\n  rr aspires to be your primary C/C++ debugging tool for Linux, replacing —\n  well, enhancing — gdb. You record a failure once, then debug the recording,\n  deterministically, as many times as you want. The same execution is\n  replayed every time.\n\n  rr also provides efficient reverse execution under gdb. Set breakpoints and\n  data watchpoints and quickly reverse-execute to where they were hit.\n\n  * Low overhead compared to other similar tools, especially on\n    mostly-single-threaded workloads\n  * Supports recording and replay of all kinds of applications:\n    Firefox, Chrome, QEMU, LibreOffice, Go programs, ...\n  * Record, replay and debug multiple-process workloads, including entire containers\n  * Works with gdb scripting and\n    [IDE integration](https://github.com/rr-debugger/rr/wiki/Using-rr-in-an-IDE)\n  * [Durable](http://robert.ocallahan.org/2017/06/new-rr-pack-command.html),\n    [compact](http://robert.ocallahan.org/2017/07/selecting-compression-algorithm-for-rr.html)\n    traces that can be \n    [ported](http://robert.ocallahan.org/2017/09/rr-trace-portability.html) between machines\n  * [Chaos mode](http://robert.ocallahan.org/2016/02/introducing-rr-chaos-mode.html)\n    to make intermittent bugs more reproducible \n\ngrade: stable # must be 'stable' to release into candidate/stable channels\nconfinement: classic\n\napps:\n  rr:\n    command: usr/bin/rr\n\nparts:\n  rr:\n    plugin: cmake\n    cmake-parameters:\n      - -DCMAKE_INSTALL_PREFIX=/usr\n    source: .\n    source-type: git\n    build-packages:\n      - g++\n      - g++-multilib\n      - gdb\n      - pkg-config\n      - coreutils\n      - python3-pexpect\n      - manpages-dev\n      - ninja-build\n      - capnproto\n      - libcapnp-dev\n      - zlib1g-dev\n      - libzstd-dev\n    stage-packages:\n      - libcapnp-0.7.0\n      - zlib1g\n      - libzstd1\n"
  },
  {
    "path": "src/AddressSpace.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"AddressSpace.h\"\n\n#include <limits.h>\n#include <linux/kdev_t.h>\n#include <linux/prctl.h>\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <limits>\n\n#include \"rr/rr.h\"\n\n#include \"preload/preload_interface.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"MonitoredSharedMemory.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic const uint8_t x86_breakpoint_insn[] = { 0xcc }; // int $3\nstatic const uint8_t arm64_breakpoint_insn[4] = {0x0, 0x0, 0x20, 0xd4}; // brk #0\n\nstatic const uint8_t *breakpoint_insn(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n    case x86_64:\n      return x86_breakpoint_insn;\n    case aarch64:\n      return arm64_breakpoint_insn;\n    default:\n      DEBUG_ASSERT(0 && \"Must define breakpoint insn for this architecture\");\n      return nullptr;\n  }\n}\n\n\n/**\n * Advance *str to skip leading blank characters.\n */\nstatic const char* trim_leading_blanks(const char* str) {\n  const char* trimmed = str;\n  while (isblank(*trimmed)) {\n    ++trimmed;\n  }\n  return trimmed;\n}\n\n/**\n * Returns true if a task in t's thread-group other than t is doing an exec.\n */\nstatic bool thread_group_in_exec(Task* t) {\n  if (!t->session().is_recording()) {\n    return false;\n  }\n  for (Task* tt : t->thread_group()->task_set()) {\n    if (tt == t || t->already_exited()) {\n      continue;\n    }\n    RecordTask* rt = static_cast<RecordTask*>(tt);\n    Event& ev = rt->ev();\n    if (ev.is_syscall_event() && ev.Syscall().is_exec()) {\n      return true;\n    }\n  }\n  return false;\n}\n\nKernelMapIterator::KernelMapIterator(Task* t, bool* ok)\n  : tid(t->tid) {\n  // See https://lkml.org/lkml/2016/9/21/423\n  ASSERT(t, !thread_group_in_exec(t)) << \"Task-group in execve, so reading \"\n                                         \"/proc/.../maps may trigger kernel \"\n                                         \"deadlock!\";\n  init(ok);\n}\n\nKernelMapIterator::~KernelMapIterator() {\n  if (maps_file) {\n    fclose(maps_file);\n  }\n}\n\nvoid KernelMapIterator::init(bool* ok) {\n  char maps_path[PATH_MAX];\n  sprintf(maps_path, \"/proc/%d/maps\", tid);\n  if (ok) {\n    *ok = true;\n  }\n  if (!(maps_file = fopen(maps_path, \"r\"))) {\n    if (ok) {\n      *ok = false;\n    } else {\n      FATAL() << \"Failed to open \" << maps_path;\n    }\n  }\n  ++*this;\n}\n\nvoid KernelMapIterator::operator++() {\n  if (!maps_file) {\n    return;\n  }\n\n  char line[PATH_MAX * 2];\n  if (!fgets(line, sizeof(line), maps_file)) {\n    fclose(maps_file);\n    maps_file = nullptr;\n    return;\n  }\n\n  uint64_t start, end, offset, inode;\n  int dev_major, dev_minor;\n  char flags[32];\n  int chars_scanned;\n  int nparsed = sscanf(line, \"%\" SCNx64 \"-%\" SCNx64 \" %31s %\" SCNx64\n                             \" %x:%x %\" SCNu64 \" %n\",\n                       &start, &end, flags, &offset, &dev_major, &dev_minor,\n                       &inode, &chars_scanned);\n  DEBUG_ASSERT(8 /*number of info fields*/ == nparsed ||\n               7 /*num fields if name is blank*/ == nparsed);\n\n  // trim trailing newline, if any\n  int last_char = strlen(line) - 1;\n  if (line[last_char] == '\\n') {\n    line[last_char] = 0;\n  }\n  raw_line = line;\n\n  const char* name = trim_leading_blanks(line + chars_scanned);\n#if defined(__i386__)\n  if (start > numeric_limits<uint32_t>::max() ||\n      end > numeric_limits<uint32_t>::max() ||\n      strcmp(name, \"[vsyscall]\") == 0) {\n    // We manually read the exe link here because\n    // this helper is used to set\n    // |t->vm()->exe_image()|, so we can't rely on\n    // that being correct yet.\n    char proc_exe[PATH_MAX];\n    char exe[PATH_MAX];\n    snprintf(proc_exe, sizeof(proc_exe), \"/proc/%d/exe\", tid);\n    ssize_t size = readlink(proc_exe, exe, sizeof(exe));\n    if (size < 0) {\n      FATAL() << \"readlink failed\";\n    }\n    FATAL() << \"Sorry, tracee \" << tid << \" has x86-64 image \" << exe\n            << \" and that's not supported with a 32-bit rr.\";\n  }\n#endif\n  int prot = (strchr(flags, 'r') ? PROT_READ : 0) |\n             (strchr(flags, 'w') ? PROT_WRITE : 0) |\n             (strchr(flags, 'x') ? PROT_EXEC : 0);\n  int f = (strchr(flags, 'p') ? MAP_PRIVATE : 0) |\n          (strchr(flags, 's') ? MAP_SHARED : 0);\n\n  string tmp_name;\n  if (strchr(name, '\\\\')) {\n    // Unescape any '\\012' sequences\n    while (*name) {\n      if (strncmp(name, \"\\\\012\", 4) == 0) {\n        tmp_name.push_back('\\n');\n        name += 4;\n      } else {\n        tmp_name.push_back(*name);\n        ++name;\n      }\n    }\n    name = tmp_name.c_str();\n  }\n\n  km = KernelMapping(start, end, name, MKDEV(dev_major, dev_minor), inode, prot,\n                     f, offset);\n}\n\nstatic KernelMapping read_kernel_mapping(pid_t tid, remote_ptr<void> addr) {\n  MemoryRange range(addr, 1);\n  bool ok;\n  KernelMapIterator it(tid, &ok);\n  if (!ok) {\n    return KernelMapping();\n  }\n  for (; !it.at_end(); ++it) {\n    const KernelMapping& km = it.current();\n    if (km.contains(range)) {\n      return km;\n    }\n  }\n  return KernelMapping();\n}\n\nKernelMapping AddressSpace::read_kernel_mapping(Task* t,\n                                                remote_ptr<void> addr) {\n  return rr::read_kernel_mapping(t->tid, addr);\n}\n\nKernelMapping AddressSpace::read_local_kernel_mapping(uint8_t* addr) {\n  return rr::read_kernel_mapping(getpid(), remote_ptr<void>((uintptr_t)addr));\n}\n\n/**\n * Cat the /proc/[t->tid]/maps file to stdout, line by line.\n */\nvoid AddressSpace::print_process_maps(Task* t) {\n  for (KernelMapIterator it(t); !it.at_end(); ++it) {\n    string line;\n    it.current(&line);\n    cerr << line << '\\n';\n  }\n}\n\nAddressSpace::Mapping::Mapping(const KernelMapping& map,\n                               const KernelMapping& recorded_map,\n                               EmuFile::shr_ptr emu_file,\n                               std::unique_ptr<struct stat> mapped_file_stat,\n                               void* local_addr,\n                               shared_ptr<MonitoredSharedMemory>&& monitored)\n    : map(map),\n      recorded_map(recorded_map),\n      emu_file(emu_file),\n      mapped_file_stat(std::move(mapped_file_stat)),\n      local_addr(static_cast<uint8_t*>(local_addr)),\n      monitored_shared_memory(std::move(monitored)),\n      flags(FLAG_NONE) {}\n\nstatic unique_ptr<struct stat> clone_stat(\n    const unique_ptr<struct stat>& other) {\n  return other ? unique_ptr<struct stat>(new struct stat(*other)) : nullptr;\n}\n\nAddressSpace::Mapping::Mapping(const Mapping& other)\n    : map(other.map),\n      recorded_map(other.recorded_map),\n      emu_file(other.emu_file),\n      mapped_file_stat(clone_stat(other.mapped_file_stat)),\n      local_addr(other.local_addr),\n      monitored_shared_memory(other.monitored_shared_memory),\n      flags(other.flags) {}\n\nAddressSpace::Mapping::~Mapping() {}\n\nAddressSpace::Mapping AddressSpace::Mapping::subrange(MemoryRange range,\n    std::function<KernelMapping(const KernelMapping&)> f) const {\n  Mapping mapping(\n        f(map.subrange(range.start(), range.end())),\n        f(recorded_map.subrange(range.start(), range.end())),\n        emu_file, clone_stat(mapped_file_stat),\n        local_addr ? local_addr + (range.start() - map.start()) : 0,\n        monitored_shared_memory\n            ? monitored_shared_memory->subrange(range.start() - map.start(),\n                                                range.size())\n            : nullptr);\n  mapping.flags = flags;\n  return mapping;\n}\n\nAddressSpace::~AddressSpace() {\n  for (auto& m : mem) {\n    if (m.second.local_addr) {\n      int ret = munmap(m.second.local_addr, m.second.map.size());\n      if (ret < 0) {\n        FATAL() << \"Can't munmap\";\n      }\n    }\n  }\n  session_->on_destroy(this);\n}\n\nstatic uint32_t find_offset_of_syscall_instruction_in(SupportedArch arch,\n                                                      uint8_t* vdso_data,\n                                                      size_t vdso_len) {\n  auto instruction = syscall_instruction(arch);\n  for (uint32_t i = 1; i < vdso_len - instruction.size(); ++i) {\n    if (memcmp(vdso_data + i, instruction.data(), instruction.size()) == 0) {\n      return i;\n    }\n  }\n  return 0;\n}\n\nuint32_t AddressSpace::offset_to_syscall_in_vdso[SupportedArch_MAX + 1];\n\nremote_code_ptr AddressSpace::find_syscall_instruction_in_vdso(Task* t) {\n  SupportedArch arch = t->arch();\n  if (!offset_to_syscall_in_vdso[arch]) {\n    if (!vdso_start_addr) {\n      return remote_code_ptr();\n    }\n    auto vdso_data = t->read_mem(vdso().start().cast<uint8_t>(), vdso().size());\n    offset_to_syscall_in_vdso[arch] = find_offset_of_syscall_instruction_in(\n        arch, vdso_data.data(), vdso_data.size());\n    ASSERT(t, offset_to_syscall_in_vdso[arch])\n        << \"No syscall instruction found in VDSO\";\n  }\n  return remote_code_ptr(\n      (vdso().start().cast<uint8_t>() + offset_to_syscall_in_vdso[arch])\n          .as_int());\n}\n\nstatic string rr_page_file_name(SupportedArch arch, const char** fname_out) {\n  string file_name;\n  const char *fname = nullptr;\n  switch (arch) {\n    case x86_64:\n    case aarch64:\n      fname = RRPAGE_LIB_FILENAME;\n      break;\n    case x86:\n#if defined(__x86_64__)\n      fname = RRPAGE_LIB_FILENAME_32;\n#else\n      fname = RRPAGE_LIB_FILENAME;\n#endif\n      break;\n  }\n  *fname_out = fname;\n\n  string path = find_helper_library(fname);\n  if (path.empty()) {\n    return path;\n  }\n  path += fname;\n  return path;\n}\n\nvoid AddressSpace::map_rr_page(AutoRemoteSyscalls& remote) {\n  int prot = PROT_EXEC | PROT_READ;\n  int flags = MAP_PRIVATE | MAP_FIXED;\n\n  Task* t = remote.task();\n  SupportedArch arch = t->arch();\n  const char* fname;\n  string path = rr_page_file_name(arch, &fname);\n  if (path.empty()) {\n    FATAL() << \"Failed to locate \" << fname << \"; needed by \"\n      << t->exe_path() << \" (\" << arch_name(arch) << \")\";\n  }\n\n  size_t offset_pages = t->session().is_recording() ?\n    RRPAGE_RECORD_PAGE_OFFSET : RRPAGE_REPLAY_PAGE_OFFSET;\n  size_t offset_bytes = offset_pages * PRELOAD_LIBRARY_PAGE_SIZE;\n\n  {\n    ScopedFd page(path.c_str(), O_RDONLY);\n    ASSERT(t, page.is_open()) << \"Failed to open rrpage library \" << path;\n    int child_fd = remote.infallible_send_fd_if_alive(page);\n    if (child_fd >= 0) {\n      if (t->session().is_recording()) {\n        remote.infallible_mmap_syscall_if_alive(rr_page_start() - offset_bytes, offset_bytes, prot, flags,\n                                                child_fd, 0);\n      }\n      remote.infallible_mmap_syscall_if_alive(rr_page_start(), PRELOAD_LIBRARY_PAGE_SIZE, prot, flags,\n                                              child_fd, offset_bytes);\n\n      struct stat fstat = t->stat_fd(child_fd);\n      string file_name = t->file_name_of_fd(child_fd);\n\n      remote.infallible_close_syscall_if_alive(child_fd);\n\n      map(t, rr_page_start(), PRELOAD_LIBRARY_PAGE_SIZE, prot, flags,\n          offset_bytes, file_name,\n          fstat.st_dev, fstat.st_ino);\n      mapping_flags_of(rr_page_start()) = Mapping::IS_RR_PAGE;\n      if (t->session().is_recording()) {\n        map(t, rr_page_start() - offset_bytes, offset_bytes, prot, flags,\n            0, file_name,\n            fstat.st_dev, fstat.st_ino);\n        mapping_flags_of(rr_page_start() - offset_bytes) = Mapping::IS_RR_VDSO_PAGE;\n      }\n    }\n  }\n\n  if (t->session().is_recording()) {\n    // brk() will not have been called yet so the brk area is empty.\n    brk_start = brk_end =\n        remote.infallible_syscall(syscall_number_for_brk(arch), 0);\n    ASSERT(t, !brk_end.is_null());\n  }\n}\n\nvector<uint8_t> AddressSpace::read_rr_page_for_recording(SupportedArch arch) {\n  const char* fname;\n  string path = rr_page_file_name(arch, &fname);\n  if (path.empty()) {\n    FATAL() << \"Failed to locate \" << fname;\n  }\n\n  ScopedFd page(path.c_str(), O_RDONLY);\n  vector<uint8_t> result;\n  result.resize(PRELOAD_LIBRARY_PAGE_SIZE);\n  ssize_t ret = read_to_end(page,\n    RRPAGE_RECORD_PAGE_OFFSET * PRELOAD_LIBRARY_PAGE_SIZE, result.data(),\n    result.size());\n  if (ret != static_cast<ssize_t>(result.size())) {\n    FATAL() << \"Failed to read full page from \" << path;\n  }\n  return result;\n}\n\nvoid AddressSpace::unmap_all_but_rr_mappings(AutoRemoteSyscalls& remote,\n    UnmapOptions options) {\n  vector<MemoryRange> unmaps;\n  for (const auto& m : maps()) {\n    // Do not attempt to unmap [vsyscall] --- it doesn't work.\n    if (m.map.start() != AddressSpace::rr_page_start() &&\n        m.map.start() != AddressSpace::preload_thread_locals_start() &&\n        !m.map.is_vsyscall() &&\n        (!options.exclude_vdso_vvar || (!m.map.is_vdso() && (m.map.is_vvar() || m.map.is_vvar_vclock())))) {\n      unmaps.push_back(m.map);\n    }\n  }\n  for (auto& m : unmaps) {\n    remote.infallible_syscall(syscall_number_for_munmap(remote.task()->arch()),\n                              m.start(), m.size());\n    unmap(remote.task(), m.start(), m.size());\n  }\n}\n\n/**\n * Must match generate_rr_page.py\n */\nstatic const AddressSpace::SyscallType entry_points[] = {\n  { AddressSpace::TRACED, AddressSpace::UNPRIVILEGED,\n    AddressSpace::RECORDING_AND_REPLAY },\n  { AddressSpace::TRACED, AddressSpace::PRIVILEGED,\n    AddressSpace::RECORDING_AND_REPLAY },\n  { AddressSpace::UNTRACED, AddressSpace::UNPRIVILEGED,\n    AddressSpace::RECORDING_AND_REPLAY },\n  { AddressSpace::UNTRACED, AddressSpace::UNPRIVILEGED,\n    AddressSpace::REPLAY_ONLY },\n  { AddressSpace::UNTRACED, AddressSpace::UNPRIVILEGED,\n    AddressSpace::RECORDING_ONLY },\n  { AddressSpace::UNTRACED, AddressSpace::PRIVILEGED,\n    AddressSpace::RECORDING_AND_REPLAY },\n  { AddressSpace::UNTRACED, AddressSpace::PRIVILEGED,\n    AddressSpace::REPLAY_ONLY },\n  { AddressSpace::UNTRACED, AddressSpace::PRIVILEGED,\n    AddressSpace::RECORDING_ONLY },\n  { AddressSpace::UNTRACED, AddressSpace::UNPRIVILEGED,\n    AddressSpace::REPLAY_ASSIST },\n};\n\nstatic int rr_page_syscall_stub_size(SupportedArch arch) {\n  int val = 0;\n  switch (arch) {\n    case x86:\n    case x86_64:\n      val = 3;\n      break;\n    case aarch64:\n      val = 8;\n      break;\n    default:\n      FATAL() << \"Syscall stub size not defined for this architecture\";\n  }\n  if (arch == NativeArch::arch()) {\n    DEBUG_ASSERT(val == RR_PAGE_SYSCALL_STUB_SIZE);\n  }\n  return val;\n}\n\nstatic int rr_page_syscall_instruction_end(SupportedArch arch) {\n  int val = 0;\n  switch (arch) {\n    case x86:\n    case x86_64:\n      val = 2;\n      break;\n    case aarch64:\n      val = 4;\n      break;\n    default:\n      FATAL() << \"Syscall stub size not defined for this architecture\";\n  }\n  if (arch == NativeArch::arch()) {\n    DEBUG_ASSERT(val == RR_PAGE_SYSCALL_INSTRUCTION_END);\n  }\n  return val;\n}\n\nstatic remote_code_ptr entry_ip_from_index(SupportedArch arch, size_t i) {\n  return remote_code_ptr(RR_PAGE_ADDR + rr_page_syscall_stub_size(arch) * i);\n}\n\nstatic remote_code_ptr exit_ip_from_index(SupportedArch arch, size_t i) {\n  return remote_code_ptr(RR_PAGE_ADDR + rr_page_syscall_stub_size(arch) * i +\n                         rr_page_syscall_instruction_end(arch));\n}\n\nremote_code_ptr AddressSpace::rr_page_syscall_exit_point(Traced traced,\n                                                         Privileged privileged,\n                                                         Enabled enabled,\n                                                         SupportedArch arch) {\n  for (auto& e : entry_points) {\n    if (e.traced == traced && e.privileged == privileged &&\n        e.enabled == enabled) {\n      return exit_ip_from_index(arch, &e - entry_points);\n    }\n  }\n  return nullptr;\n}\n\nremote_code_ptr AddressSpace::rr_page_syscall_entry_point(Traced traced,\n                                                          Privileged privileged,\n                                                          Enabled enabled,\n                                                          SupportedArch arch) {\n  for (auto& e : entry_points) {\n    if (e.traced == traced && e.privileged == privileged &&\n        e.enabled == enabled) {\n      return entry_ip_from_index(arch, &e - entry_points);\n    }\n  }\n  return nullptr;\n}\n\nconst AddressSpace::SyscallType* AddressSpace::rr_page_syscall_from_exit_point(\n    SupportedArch arch, remote_code_ptr ip) {\n  for (size_t i = 0; i < array_length(entry_points); ++i) {\n    if (exit_ip_from_index(arch, i) == ip) {\n      return &entry_points[i];\n    }\n  }\n  return nullptr;\n}\n\nconst AddressSpace::SyscallType* AddressSpace::rr_page_syscall_from_entry_point(\n    SupportedArch arch, remote_code_ptr ip) {\n  for (size_t i = 0; i < array_length(entry_points); ++i) {\n    if (entry_ip_from_index(arch, i) == ip) {\n      return &entry_points[i];\n    }\n  }\n  return nullptr;\n}\n\nvector<AddressSpace::SyscallType> AddressSpace::rr_page_syscalls() {\n  vector<SyscallType> result;\n  for (auto& e : entry_points) {\n    result.push_back(e);\n  }\n  return result;\n}\n\nvoid AddressSpace::save_auxv(Task* t) {\n  saved_auxv_ = read_auxv(t);\n  save_interpreter_base(t, saved_auxv());\n}\n\nvoid AddressSpace::save_interpreter_base(Task* t, std::vector<uint8_t> auxv) {\n  saved_interpreter_base_ = read_interpreter_base(auxv);\n  save_ld_path(t, saved_interpreter_base());\n}\n\nvoid AddressSpace::save_ld_path(Task* t, remote_ptr<void> interpreter_base) {\n  saved_ld_path_ = read_ld_path(t, interpreter_base);\n}\n\nvoid AddressSpace::read_mm_map(Task* t, NativeArch::prctl_mm_map* map) {\n  char buf[PATH_MAX+1024];\n  {\n    string proc_stat = t->proc_stat_path();\n    ScopedFd fd(proc_stat.c_str(), O_RDONLY);\n    memset(buf, 0, sizeof(buf));\n    int err = read_to_end(fd, 0, buf, sizeof(buf)-1);\n    if (err < 0) {\n      FATAL() << \"Failed to read /proc/<pid>/stat\";\n    }\n  }\n  // The last close-paren indicates the end of the comm and the\n  // start of the fixed-width area\n  char* fixed = strrchr(buf, ')');\n  // We don't change /proc/pid/exe, since we're unlikely to have CAP_SYS_ADMIN\n  map->exe_fd = -1;\n  // auxv is restored separately\n  map->auxv.val = 0;\n  map->auxv_size = 0;\n  // All of these fields of /proc/pid/stat, we don't use (currently)\n  char state;\n  pid_t ppid;\n  pid_t pgrp;\n  int session;\n  int tty_nr;\n  int tpgid;\n  unsigned int flags;\n  unsigned long minflt, cminflt, majflt, cmajflt, utime, stime;\n  long cutime, cstime, priority, nice, num_threads, itrealvalue;\n  unsigned long long starttime;\n  unsigned long vsize;\n  long rss;\n  unsigned long rsslim, kstkesp, kstskip, signal;\n  unsigned long blocked, sigignore, sigcatch, wchan, nswap, cnswap;\n  int exit_signal, processor;\n  unsigned int rt_priority, policy;\n  unsigned long long delayacct_blkio_ticks;\n  unsigned long guest_time;\n  long cguest_time;\n  int exit_code;\n  // See the proc(5) man page for the correct scan codes for these\n  size_t n = sscanf(fixed + 1,\n    // state ppid pgrp session tty_nr tpgid\n    \" %c %d %d %d %d %d\"\n    // flags minflt cminflt majflt cmajflt utime stime cutime cstime\n    \" %u %lu %lu %lu %lu %lu %lu %ld %ld\"\n    // priority nice num_threads itrealvalue starttime vsize rss\n    \" %ld %ld %ld %ld %llu %lu %ld\"\n    // rsslim startcode endcode startstack kstkesp kstskip signal\n    \" %lu %lu %lu %lu %lu %lu %lu\"\n    // blocked sigignore sigcatch wchan nswap cnswap exit_signal\n    \" %lu %lu %lu %lu %lu %lu %d\"\n    // processor rt_priority policy delayacct_blkio_ticks guest_time cguest_time\n    \" %d %u %u %llu %lu %ld \"\n    // start_data end_data start_brk arg_start arg_end env_start env_end exit_code\n    \" %lu %lu %lu %lu %lu %lu %lu %d\",\n    &state, &ppid, &pgrp, &session, &tty_nr, &tpgid,\n    &flags, &minflt, &cminflt, &majflt, &cmajflt, &utime, &stime, &cutime, &cstime,\n    &priority, &nice, &num_threads, &itrealvalue, &starttime, &vsize, &rss,\n    &rsslim, (unsigned long *)&map->start_code, (unsigned long *)&map->end_code,\n    (unsigned long *)&map->start_stack, &kstkesp, &kstskip, &signal,\n    &blocked, &sigignore, &sigcatch, &wchan, &nswap, &cnswap, &exit_signal,\n    &processor, &rt_priority, &policy, &delayacct_blkio_ticks, &guest_time,\n    &cguest_time, (unsigned long *)&map->start_data, (unsigned long *)&map->end_data,\n    (unsigned long *)&map->start_brk, (unsigned long *)&map->arg_start,\n    (unsigned long *)&map->arg_end, (unsigned long *)&map->env_start,\n    (unsigned long *)&map->env_end, &exit_code);\n  ASSERT(t, n == 50);\n  // Fill in brk end\n  ASSERT(t, map->start_brk == this->brk_start.as_int());\n  map->brk = this->brk_end.as_int();\n}\n\nvoid AddressSpace::post_exec_syscall(Task* t) {\n  // First locate a syscall instruction we can use for remote syscalls.\n  traced_syscall_ip_ = find_syscall_instruction_in_vdso(t);\n  privileged_traced_syscall_ip_ = nullptr;\n\n  do_breakpoint_fault_addr_ = nullptr;\n  stopping_breakpoint_table_ = nullptr;\n  stopping_breakpoint_table_entry_size_ = 0;\n\n  // Now remote syscalls work, we can open_mem_fd.\n  t->open_mem_fd();\n\n  // Set up AutoRemoteSyscalls again now that the mem-fd is open.\n  AutoRemoteSyscalls remote(t);\n  // Now we can set up the \"rr page\" at its fixed address. This gives\n  // us traced and untraced syscall instructions at known, fixed addresses.\n  map_rr_page(remote);\n  // Set up the preload_thread_locals shared area.\n  t->session().create_shared_mmap(remote, PRELOAD_THREAD_LOCALS_SIZE,\n                                  preload_thread_locals_start(),\n                                  \"preload_thread_locals\");\n  mapping_flags_of(preload_thread_locals_start()) |=\n      AddressSpace::Mapping::IS_THREAD_LOCALS;\n}\n\nvoid AddressSpace::brk(Task* t, remote_ptr<void> addr, int prot) {\n  LOG(debug) << \"brk(\" << addr << \")\";\n\n  remote_ptr<void> old_brk = ceil_page_size(brk_end);\n  remote_ptr<void> new_brk = ceil_page_size(addr);\n  if (old_brk < new_brk) {\n    map(t, old_brk, new_brk - old_brk, prot, MAP_ANONYMOUS | MAP_PRIVATE, 0,\n        \"[heap]\");\n  } else {\n    unmap(t, new_brk, old_brk - new_brk);\n  }\n  brk_end = addr;\n}\n\nstatic const char* stringify_flags(int flags) {\n  switch (flags) {\n    case AddressSpace::Mapping::FLAG_NONE:\n      return \"\";\n    case AddressSpace::Mapping::IS_SYSCALLBUF:\n      return \" [syscallbuf]\";\n    case AddressSpace::Mapping::IS_THREAD_LOCALS:\n      return \" [thread_locals]\";\n    case AddressSpace::Mapping::IS_PATCH_STUBS:\n      return \" [patch_stubs]\";\n    case AddressSpace::Mapping::IS_RR_PAGE:\n      return \" [rr_page]\";\n    case AddressSpace::Mapping::IS_RR_VDSO_PAGE:\n      return \" [rr_vdso_page]\";\n    default:\n      return \" [unknown_flags]\";\n  }\n}\n\nvoid AddressSpace::dump() const {\n  fprintf(stderr, \"  (heap: %p-%p)\\n\", (void*)brk_start.as_int(),\n          (void*)brk_end.as_int());\n  for (auto it = mem.begin(); it != mem.end(); ++it) {\n    const KernelMapping& m = it->second.map;\n    fprintf(stderr, \"%s%s\\n\", m.str().c_str(),\n            stringify_flags(it->second.flags));\n  }\n}\n\nSupportedArch AddressSpace::arch() const {\n  return (*task_set().begin())->arch();\n}\n\nBreakpointType AddressSpace::get_breakpoint_type_for_retired_insn(\n    remote_code_ptr ip) {\n  remote_code_ptr addr = ip.undo_executed_bkpt(arch());\n  return get_breakpoint_type_at_addr(addr);\n}\n\nBreakpointType AddressSpace::get_breakpoint_type_at_addr(remote_code_ptr addr) {\n  auto it = breakpoints.find(addr);\n  return it == breakpoints.end() ? BKPT_NONE : it->second.type();\n}\n\nbool AddressSpace::is_exec_watchpoint(remote_code_ptr addr) {\n  for (auto& kv : watchpoints) {\n    if (kv.first.contains(addr.to_data_ptr<void>()) &&\n        (kv.second.watched_bits() & EXEC_BIT)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool AddressSpace::is_breakpoint_in_private_read_only_memory(\n    remote_code_ptr addr) {\n  for (const auto& m : maps_containing_or_after(addr.to_data_ptr<void>())) {\n    if (m.map.start() >=\n        addr.increment_by_bkpt_insn_length(arch()).to_data_ptr<void>()) {\n      break;\n    }\n    if ((m.map.prot() & PROT_WRITE) || (m.map.flags() & MAP_SHARED)) {\n      return false;\n    }\n  }\n  return true;\n}\n\nvoid AddressSpace::replace_breakpoints_with_original_values(\n    uint8_t* dest, size_t length, remote_ptr<uint8_t> addr) {\n  for (auto& it : breakpoints) {\n    replace_in_buffer(MemoryRange(it.first.to_data_ptr<void>(), bkpt_instruction_length(arch())),\n                      it.second.original_data(),\n                      MemoryRange(addr, length), dest);\n  }\n}\n\nbool AddressSpace::is_breakpoint_instruction(Task* t, remote_code_ptr ip) {\n  bool ok = true;\n  uint8_t data[MAX_BKPT_INSTRUCTION_LENGTH];\n  t->read_bytes_helper(ip.to_data_ptr<uint8_t>(),\n    bkpt_instruction_length(t->arch()), data, &ok);\n  if (!ok) {\n    return false;\n  }\n  switch (t->arch()) {\n    case x86:\n    case x86_64:\n      return data[0] == 0xcc;\n    case aarch64:\n      return (data[0] & 0x1f) == 0 && (data[2] & 0xe0) == 0x20 &&\n             data[3] == 0xd4;\n    default:\n      DEBUG_ASSERT(0 && \"Must define breakpoint insn for this architecture\");\n      return false;\n  }\n}\n\nstatic void remove_range(set<MemoryRange>& ranges, const MemoryRange& range) {\n  if (ranges.empty()) {\n    return;\n  }\n\n  auto start = ranges.lower_bound(range);\n  // An earlier range might extend into range, so check for that.\n  if (start != ranges.begin()) {\n    --start;\n    if (start->end() <= range.start()) {\n      ++start;\n    }\n  }\n  auto end = start;\n  auto prev_end = start;\n  while (end != ranges.end() && end->start() < range.end()) {\n    prev_end = end;\n    ++end;\n  }\n  if (start == end) {\n    return;\n  }\n  MemoryRange start_range = *start;\n  MemoryRange end_range = *prev_end;\n  ranges.erase(start, end);\n  if (start_range.start() < range.start()) {\n    ranges.insert(MemoryRange(start_range.start(), range.start()));\n  }\n  if (range.end() < end_range.end()) {\n    ranges.insert(MemoryRange(range.end(), end_range.end()));\n  }\n}\n\nstatic void add_range(set<MemoryRange>& ranges, const MemoryRange& range) {\n  // Remove overlapping ranges\n  remove_range(ranges, range);\n  ranges.insert(range);\n  // We could coalesce adjacent ranges, but there's probably no need.\n}\n\nKernelMapping AddressSpace::map(Task* t, remote_ptr<void> addr,\n                                size_t num_bytes, int prot, int flags,\n                                off_t offset_bytes, const string& fsname,\n                                dev_t device, ino_t inode,\n                                unique_ptr<struct stat> mapped_file_stat,\n                                const KernelMapping* recorded_map,\n                                EmuFile::shr_ptr emu_file, void* local_addr,\n                                shared_ptr<MonitoredSharedMemory> monitored) {\n  LOG(debug) << \"mmap(\" << addr << \", \" << num_bytes << \", \" << HEX(prot)\n             << \", \" << HEX(flags) << \", \" << HEX(offset_bytes) << \")\";\n  num_bytes = ceil_page_size(num_bytes);\n  KernelMapping m(addr, addr + num_bytes, fsname, device, inode, prot, flags,\n                  offset_bytes);\n  if (!num_bytes) {\n    return m;\n  }\n\n  if (t->session().is_recording()) {\n    uint8_t bits = virtual_address_size(t->arch(), addr + num_bytes - 1);\n    // NB: Ignore addresses with no leading zeroes on 64 bit architectures\n    // (where they are in the kernel) but not on 32 bit x86 (where the\n    // 2-3GB range is available to userspace).\n    if (bits != 64) {\n      static_cast<RecordTask*>(t)->\n        trace_writer().note_virtual_address_size(bits);\n    }\n  }\n\n  remove_range(dont_fork, MemoryRange(addr, num_bytes));\n  remove_range(wipe_on_fork, MemoryRange(addr, num_bytes));\n\n  // The mmap() man page doesn't specifically describe\n  // what should happen if an existing map is\n  // \"overwritten\" by a new map (of the same resource).\n  // In testing, the behavior seems to be as if the\n  // overlapping region is unmapped and then remapped\n  // per the arguments to the second call.\n  unmap_internal(t, addr, num_bytes);\n\n  const KernelMapping& actual_recorded_map = recorded_map ? *recorded_map : m;\n  map_and_coalesce(t, m, actual_recorded_map, emu_file,\n                   std::move(mapped_file_stat),\n                   std::move(local_addr),\n                   std::move(monitored));\n\n  // During an emulated exec, we will explicitly map in a (copy of) the VDSO\n  // at the recorded address.\n  if (actual_recorded_map.is_vdso()) {\n    vdso_start_addr = addr;\n  }\n\n  if (MemoryRange(addr, num_bytes).contains(RR_PAGE_ADDR)) {\n    update_syscall_ips(t);\n  }\n\n  return m;\n}\n\ntemplate <typename Arch> void AddressSpace::at_preload_init_arch(Task* t) {\n  auto params = t->read_mem(\n      remote_ptr<rrcall_init_preload_params<Arch>>(t->regs().orig_arg1()));\n\n  if (t->session().is_recording()) {\n    ASSERT(t,\n           t->session().as_record()->use_syscall_buffer() ==\n               params.syscallbuf_enabled)\n        << \"Tracee thinks syscallbuf is \"\n        << (params.syscallbuf_enabled ? \"en\" : \"dis\")\n        << \"abled, but tracer thinks \"\n        << (t->session().as_record()->use_syscall_buffer() ? \"en\" : \"dis\")\n        << \"abled\";\n  } else {\n    if (params.breakpoint_table_entry_size == -1) {\n      do_breakpoint_fault_addr_ = params.breakpoint_instr_addr.rptr().as_int();\n    } else {\n      stopping_breakpoint_table_ = params.breakpoint_table.rptr().as_int();\n      stopping_breakpoint_table_entry_size_ =\n          params.breakpoint_table_entry_size;\n    }\n  }\n\n  if (!params.syscallbuf_enabled) {\n    return;\n  }\n\n  syscallbuf_enabled_ = true;\n\n  if (t->session().is_recording()) {\n    monkeypatch_state->patch_at_preload_init(static_cast<RecordTask*>(t));\n  }\n}\n\nvoid AddressSpace::at_preload_init(Task* t) {\n  RR_ARCH_FUNCTION(at_preload_init_arch, t->arch(), t);\n}\n\nconst AddressSpace::Mapping& AddressSpace::mapping_of(\n    remote_ptr<void> addr) const {\n  MemoryRange range(floor_page_size(addr), 1);\n  auto it = mem.find(range);\n  DEBUG_ASSERT(it != mem.end());\n  DEBUG_ASSERT(it->second.map.contains(range));\n  return it->second;\n}\nuint32_t& AddressSpace::mapping_flags_of(remote_ptr<void> addr) {\n  return const_cast<AddressSpace::Mapping&>(\n             static_cast<const AddressSpace*>(this)->mapping_of(addr))\n      .flags;\n}\n\nuint8_t* AddressSpace::local_mapping(remote_ptr<void> addr, size_t size) {\n  MemoryRange range(floor_page_size(addr), 1);\n  auto it = mem.find(range);\n  if (it == mem.end()) {\n    return nullptr;\n  }\n  DEBUG_ASSERT(it->second.map.contains(range));\n  const Mapping& map = it->second;\n  // Fall back to the slow path if we can't get the entire region\n  if (size > static_cast<size_t>(map.map.end() - addr)) {\n    return nullptr;\n  }\n  if (map.local_addr != nullptr) {\n    size_t offset = addr - map.map.start();\n    return static_cast<uint8_t*>(map.local_addr) + offset;\n  }\n  return nullptr;\n}\n\nvoid* AddressSpace::detach_local_mapping(remote_ptr<void> addr) {\n  auto m = const_cast<AddressSpace::Mapping&>(mapping_of(addr));\n  void* p = m.local_addr;\n  m.local_addr = nullptr;\n  return p;\n}\n\nbool AddressSpace::has_mapping(remote_ptr<void> addr) const {\n  if (addr + page_size() < addr) {\n    // Assume the last byte in the address space is never mapped; avoid overflow\n    return false;\n  }\n  MemoryRange m(floor_page_size(addr), 1);\n  auto it = mem.find(m);\n  return it != mem.end() && it->first.contains(m);\n}\n\nbool AddressSpace::has_rr_page() const {\n  MemoryRange m(RR_PAGE_ADDR, 1);\n  auto it = mem.find(m);\n  return it != mem.end() && (it->second.flags & Mapping::IS_RR_PAGE);\n}\n\nvoid AddressSpace::protect(Task* t, remote_ptr<void> addr, size_t num_bytes,\n                           int prot) {\n  LOG(debug) << \"mprotect(\" << addr << \", \" << num_bytes << \", \" << HEX(prot)\n             << \")\";\n\n  MemoryRange last_overlap;\n  auto protector = [this, prot, &last_overlap](Mapping m,\n                                               MemoryRange rem) {\n    LOG(debug) << \"  protecting (\" << rem << \") ...\";\n\n    remove_from_map(m.map);\n\n    // PROT_GROWSDOWN means that if this is a grows-down segment\n    // (which for us means \"stack\") then the change should be\n    // extended to the start of the segment.\n    // We don't try to handle the analogous PROT_GROWSUP, because we\n    // don't understand the idea of a grows-up segment.\n    remote_ptr<void> new_start;\n    if ((m.map.start() < rem.start()) && (prot & PROT_GROWSDOWN)) {\n      new_start = m.map.start();\n      LOG(debug) << \"  PROT_GROWSDOWN: expanded region down to \" << new_start;\n    } else {\n      new_start = rem.start();\n    }\n\n    LOG(debug) << \"  erased (\" << m.map << \")\";\n\n    // If the first segment we protect underflows the\n    // region, remap the underflow region with previous\n    // prot.\n    if (m.map.start() < new_start) {\n      Mapping underflow = m.subrange(MemoryRange(m.map.start(), new_start),\n          [](const KernelMapping& km) { return km; });\n      add_to_map(underflow);\n    }\n    // Remap the overlapping region with the new prot.\n    remote_ptr<void> new_end = min(rem.end(), m.map.end());\n\n    int new_prot = prot & (PROT_READ | PROT_WRITE | PROT_EXEC);\n    Mapping overlap = m.subrange(MemoryRange(new_start, new_end),\n        [new_prot](const KernelMapping& km) { return km.set_prot(new_prot); });\n    add_to_map(overlap);\n    last_overlap = overlap.map;\n\n    // If the last segment we protect overflows the\n    // region, remap the overflow region with previous\n    // prot.\n    if (new_end < m.map.end()) {\n      Mapping overflow = m.subrange(MemoryRange(new_end, m.map.end()),\n          [](const KernelMapping& km) { return km; });\n      add_to_map(overflow);\n    }\n  };\n  for_each_in_range(addr, num_bytes, protector, ITERATE_CONTIGUOUS);\n  if (last_overlap.size()) {\n    // All mappings that we altered which might need coalescing\n    // are adjacent to |last_overlap|.\n    coalesce_around(t, mem.find(last_overlap));\n  }\n}\n\nvoid AddressSpace::fixup_mprotect_growsdown_parameters(Task* t) {\n  ASSERT(t, !(t->regs().arg3() & PROT_GROWSUP));\n  if (t->regs().arg3() & PROT_GROWSDOWN) {\n    Registers r = t->regs();\n    if (r.arg1() == floor_page_size(r.arg1()) && has_mapping(r.arg1())) {\n      auto& km = mapping_of(r.arg1()).map;\n      if (km.flags() & MAP_GROWSDOWN) {\n        auto new_start = km.start();\n        r.set_arg2(remote_ptr<void>(r.arg1()) + size_t(r.arg2()) - new_start);\n        r.set_arg1(new_start);\n        r.set_arg3(r.arg3() & ~PROT_GROWSDOWN);\n        t->set_regs(r);\n      }\n    }\n  }\n}\n\nvoid AddressSpace::remap(Task* t, remote_ptr<void> old_addr,\n                         size_t old_num_bytes, remote_ptr<void> new_addr,\n                         size_t new_num_bytes, int flags) {\n  LOG(debug) << \"mremap(\" << old_addr << \", \" << old_num_bytes << \", \"\n             << new_addr << \", \" << new_num_bytes << \")\";\n  old_num_bytes = ceil_page_size(old_num_bytes);\n\n  Mapping mr = mapping_of(old_addr);\n  DEBUG_ASSERT(!mr.monitored_shared_memory);\n  KernelMapping km = mr.map.subrange(old_addr, min(mr.map.end(), old_addr + old_num_bytes));\n\n  unmap_internal(t, old_addr, old_num_bytes);\n  if (flags & MREMAP_DONTUNMAP) {\n    // This can only ever be an anonymous private mapping.\n    map(t, old_addr, old_num_bytes, km.prot(), km.flags(), 0, string());\n  }\n  if (0 == new_num_bytes) {\n    return;\n  }\n  new_num_bytes = ceil_page_size(new_num_bytes);\n\n  auto it = dont_fork.lower_bound(MemoryRange(old_addr, old_num_bytes));\n  if (it != dont_fork.end() && it->start() < old_addr + old_num_bytes) {\n    // mremap fails if some but not all pages are marked DONTFORK\n    DEBUG_ASSERT(*it == MemoryRange(old_addr, old_num_bytes));\n    remove_range(dont_fork, MemoryRange(old_addr, old_num_bytes));\n    add_range(dont_fork, MemoryRange(new_addr, new_num_bytes));\n  } else {\n    remove_range(dont_fork, MemoryRange(old_addr, old_num_bytes));\n    remove_range(dont_fork, MemoryRange(new_addr, new_num_bytes));\n  }\n\n  it = wipe_on_fork.lower_bound(MemoryRange(old_addr, old_num_bytes));\n  if (it != wipe_on_fork.end() && it->start() < old_addr + old_num_bytes) {\n    // hopefully mremap fails if some but not all pages are marked DONTFORK\n    DEBUG_ASSERT(*it == MemoryRange(old_addr, old_num_bytes));\n    remove_range(wipe_on_fork, MemoryRange(old_addr, old_num_bytes));\n    add_range(wipe_on_fork, MemoryRange(new_addr, new_num_bytes));\n  } else {\n    remove_range(wipe_on_fork, MemoryRange(old_addr, old_num_bytes));\n    remove_range(wipe_on_fork, MemoryRange(new_addr, new_num_bytes));\n  }\n\n  unmap_internal(t, new_addr, new_num_bytes);\n\n  remote_ptr<void> new_end = new_addr + new_num_bytes;\n  map_and_coalesce(t, km.set_range(new_addr, new_end),\n                   mr.recorded_map.set_range(new_addr, new_end), mr.emu_file,\n                   clone_stat(mr.mapped_file_stat), nullptr, nullptr);\n\n  if (MemoryRange(old_addr, old_num_bytes).contains(RR_PAGE_ADDR) ||\n      MemoryRange(new_addr, new_num_bytes).contains(RR_PAGE_ADDR)) {\n    update_syscall_ips(t);\n  }\n}\n\nvoid AddressSpace::remove_breakpoint(remote_code_ptr addr,\n                                     BreakpointType type) {\n  auto it = breakpoints.find(addr);\n  if (it == breakpoints.end() || it->second.unref(type) > 0) {\n    return;\n  }\n  destroy_breakpoint(it);\n}\n\nbool AddressSpace::add_breakpoint(remote_code_ptr addr, BreakpointType type) {\n  auto it = breakpoints.find(addr);\n  if (it == breakpoints.end()) {\n    uint8_t overwritten_data[MAX_BKPT_INSTRUCTION_LENGTH];\n    ssize_t bkpt_size = bkpt_instruction_length(arch());\n    // Grab a random task from the VM so we can use its\n    // read/write_mem() helpers.\n    Task* t = first_running_task();\n    if (!t ||\n        bkpt_size !=\n            t->read_bytes_fallible(addr.to_data_ptr<uint8_t>(),\n                                   bkpt_size, overwritten_data)) {\n      return false;\n    }\n    t->write_bytes_helper(addr.to_data_ptr<uint8_t>(), bkpt_size,\n                 breakpoint_insn(arch()), nullptr,\n                 Task::IS_BREAKPOINT_RELATED);\n\n    auto it_and_is_new = breakpoints.insert(make_pair(addr, Breakpoint()));\n    DEBUG_ASSERT(it_and_is_new.second);\n    memcpy(it_and_is_new.first->second.overwritten_data,\n      overwritten_data, sizeof(overwritten_data));\n    it = it_and_is_new.first;\n  }\n  it->second.ref(type);\n  return true;\n}\n\nvoid AddressSpace::remove_all_breakpoints() {\n  while (!breakpoints.empty()) {\n    destroy_breakpoint(breakpoints.begin());\n  }\n}\n\nvoid AddressSpace::suspend_breakpoint_at(remote_code_ptr addr) {\n  auto it = breakpoints.find(addr);\n  if (it != breakpoints.end()) {\n    Task* t = first_running_task();\n    if (t) {\n      t->write_bytes_helper(addr.to_data_ptr<uint8_t>(),\n        bkpt_instruction_length(arch()), it->second.overwritten_data);\n    }\n  }\n}\n\nvoid AddressSpace::restore_breakpoint_at(remote_code_ptr addr) {\n  auto it = breakpoints.find(addr);\n  if (it != breakpoints.end()) {\n    Task* t = first_running_task();\n    if (t) {\n      t->write_bytes_helper(addr.to_data_ptr<uint8_t>(),\n        bkpt_instruction_length(arch()),\n        breakpoint_insn(arch()));\n    }\n  }\n}\n\nint AddressSpace::access_bits_of(WatchType type) {\n  switch (type) {\n    case WATCH_EXEC:\n      return EXEC_BIT;\n    case WATCH_WRITE:\n      return WRITE_BIT;\n    case WATCH_READWRITE:\n      return READ_BIT | WRITE_BIT;\n    default:\n      FATAL() << \"Unknown watchpoint type \" << type;\n      return 0; // not reached\n  }\n}\n\n/**\n * We do not allow a watchpoint to watch the last byte of memory addressable\n * by rr. This avoids constructing a MemoryRange that wraps around.\n * For 64-bit builds this is no problem because addresses at the top of memory\n * are in kernel space. For 32-bit builds it seems impossible to map the last\n * page of memory in Linux so we should be OK there too.\n * Note that zero-length watchpoints are OK. configure_watch_registers just\n * ignores them.\n */\nstatic MemoryRange range_for_watchpoint(remote_ptr<void> addr,\n                                        size_t num_bytes) {\n  uintptr_t p = addr.as_int();\n  uintptr_t max_len = UINTPTR_MAX - p;\n  return MemoryRange(addr, min<uintptr_t>(num_bytes, max_len));\n}\n\nvoid AddressSpace::remove_watchpoint(remote_ptr<void> addr, size_t num_bytes,\n                                     WatchType type) {\n  auto it = watchpoints.find(range_for_watchpoint(addr, num_bytes));\n  if (it != watchpoints.end() &&\n      0 == it->second.unwatch(access_bits_of(type))) {\n    watchpoints.erase(it);\n  }\n  allocate_watchpoints();\n}\n\nbool AddressSpace::add_watchpoint(remote_ptr<void> addr, size_t num_bytes,\n                                  WatchType type) {\n  MemoryRange key = range_for_watchpoint(addr, num_bytes);\n  auto it = watchpoints.find(key);\n  if (it == watchpoints.end()) {\n    auto it_and_is_new =\n        watchpoints.insert(make_pair(key, Watchpoint(num_bytes)));\n    DEBUG_ASSERT(it_and_is_new.second);\n    it = it_and_is_new.first;\n    update_watchpoint_value(it->first, it->second);\n  }\n  it->second.watch(access_bits_of(type));\n  bool ok = allocate_watchpoints();\n  if (!ok) {\n    remove_watchpoint(addr, num_bytes, type);\n  }\n  return ok;\n}\n\nvoid AddressSpace::save_watchpoints() {\n  saved_watchpoints.push_back(watchpoints);\n}\n\nbool AddressSpace::restore_watchpoints() {\n  DEBUG_ASSERT(!saved_watchpoints.empty());\n  watchpoints = saved_watchpoints[saved_watchpoints.size() - 1];\n  saved_watchpoints.pop_back();\n  return allocate_watchpoints();\n}\n\nbool AddressSpace::update_watchpoint_value(const MemoryRange& range,\n                                           Watchpoint& watchpoint) {\n  Task* t = first_running_task();\n  if (!t) {\n    return false;\n  }\n  bool valid = true;\n  vector<uint8_t> value_bytes = watchpoint.value_bytes;\n  for (size_t i = 0; i < value_bytes.size(); ++i) {\n    value_bytes[i] = 0xFF;\n  }\n  remote_ptr<void> addr = range.start();\n  size_t num_bytes = range.size();\n  while (num_bytes > 0) {\n    ssize_t bytes_read = t->read_bytes_fallible(\n        addr, num_bytes, value_bytes.data() + (addr - range.start()));\n    if (bytes_read <= 0) {\n      valid = false;\n      // advance to next page and try to read more. We want to know\n      // when the valid part of a partially invalid watchpoint changes.\n      bytes_read =\n          min<size_t>(num_bytes, (floor_page_size(addr) + page_size()) - addr);\n    }\n    addr += bytes_read;\n    num_bytes -= bytes_read;\n  }\n\n  bool changed = valid != watchpoint.valid ||\n                 memcmp(value_bytes.data(), watchpoint.value_bytes.data(),\n                        value_bytes.size()) != 0;\n  watchpoint.valid = valid;\n  watchpoint.value_bytes = value_bytes;\n  return changed;\n}\n\nvoid AddressSpace::update_watchpoint_values(remote_ptr<void> start,\n                                            remote_ptr<void> end) {\n  MemoryRange r(start, end);\n  for (auto& it : watchpoints) {\n    if (it.first.intersects(r) &&\n        update_watchpoint_value(it.first, it.second)) {\n      it.second.changed = true;\n      // We do nothing to track kernel reads of read-write watchpoints...\n    }\n  }\n}\n\nstatic int DR_WATCHPOINT(int n) { return 1 << n; }\n\nstatic bool watchpoint_triggered(uintptr_t debug_status,\n                                 const vector<int8_t>& regs) {\n  for (auto reg : regs) {\n    if (debug_status & DR_WATCHPOINT(reg)) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool AddressSpace::notify_watchpoint_fired(uintptr_t debug_status,\n    remote_ptr<void> hit_addr,\n    remote_code_ptr address_of_singlestep_start) {\n  bool triggered = false;\n  for (auto& it : watchpoints) {\n    // On Skylake/4.14.13-300.fc27.x86_64 at least, we have observed a\n    // situation where singlestepping through the instruction before a hardware\n    // execution watchpoint causes singlestep completion *and* also reports the\n    // hardware execution watchpoint being triggered. The latter is incorrect.\n    // This could be a HW issue or a kernel issue. Work around it by ignoring\n    // triggered watchpoints that aren't on the instruction we just tried to\n    // execute.\n    bool write_triggered = (it.second.watched_bits() & WRITE_BIT) &&\n        update_watchpoint_value(it.first, it.second);\n    // Depending on the architecture the hardware may indicate hit watchpoints\n    // either by number, or by the address that triggered the watchpoint hit\n    // - support either.\n    bool read_triggered = false;\n    bool exec_triggered = false;\n    bool watchpoint_in_range = false;\n    if (is_x86ish(arch())) {\n      read_triggered = (it.second.watched_bits() & READ_BIT) &&\n        watchpoint_triggered(debug_status,\n                             it.second.debug_regs_for_exec_read);\n      exec_triggered = (it.second.watched_bits() & EXEC_BIT) &&\n        (address_of_singlestep_start.is_null() ||\n         it.first.start() == address_of_singlestep_start.to_data_ptr<void>()) &&\n         watchpoint_triggered(debug_status,\n                              it.second.debug_regs_for_exec_read);\n    } else {\n      // The reported address may not match our watchpoint exactly. The ARM\n      // manual specifies a number of conditions that apply to the address for\n      // various types of instructions (see D2.10.5, \"Determining the memory\n      // location that caused a Watchpoint exception\"), but at a minimum it is\n      // required that the reported address is in the same block as one of the\n      // addresses monitored by the watchpoint, where the block size is defined\n      // by DCZID_EL0.BS. So we construct a range spanning the whole block, then\n      // test that the range intersects a watchpoint range.\n      auto block_size = dczid_el0_block_size();\n      auto slop = hit_addr.as_int() % block_size;\n      auto hit_range = MemoryRange(hit_addr - slop, block_size);\n      watchpoint_in_range = it.first.intersects(hit_range);\n    }\n    if (write_triggered || read_triggered || exec_triggered || watchpoint_in_range) {\n      it.second.changed = true;\n      triggered = true;\n    }\n  }\n  return triggered;\n}\n\nvoid AddressSpace::notify_written(remote_ptr<void> addr, size_t num_bytes,\n                                  uint32_t flags) {\n  if (!(flags & Task::IS_BREAKPOINT_RELATED)) {\n    update_watchpoint_values(addr, addr + num_bytes);\n  }\n  session()->accumulate_bytes_written(num_bytes);\n}\n\nvoid AddressSpace::remove_all_watchpoints() {\n  watchpoints.clear();\n  allocate_watchpoints();\n}\n\nvoid AddressSpace::unmap(Task* t, remote_ptr<void> addr, ssize_t num_bytes) {\n  LOG(debug) << \"munmap(\" << addr << \", \" << num_bytes << \")\";\n  num_bytes = ceil_page_size(num_bytes);\n  if (!num_bytes) {\n    return;\n  }\n\n  remove_range(dont_fork, MemoryRange(addr, num_bytes));\n  remove_range(wipe_on_fork, MemoryRange(addr, num_bytes));\n\n  unmap_internal(t, addr, num_bytes);\n\n  if (MemoryRange(addr, num_bytes).contains(RR_PAGE_ADDR)) {\n    update_syscall_ips(t);\n  }\n}\n\nvoid AddressSpace::update_syscall_ips(Task* t) {\n  remote_code_ptr traced_syscall_in_rr_page = rr_page_syscall_entry_point(\n      TRACED, UNPRIVILEGED, RECORDING_AND_REPLAY, t->arch());\n  SupportedArch arch;\n  bool ok = true;\n  if (get_syscall_instruction_arch(t, traced_syscall_in_rr_page, &arch, &ok) &&\n      arch == t->arch()) {\n    // Even if our rr page has been removed, there might still be\n    // an rr-page-alike with a syscall in the right place (e.g. when recording rr replay).\n    traced_syscall_ip_ = traced_syscall_in_rr_page;\n  } else {\n    traced_syscall_ip_ = find_syscall_instruction_in_vdso(t);\n  }\n\n  remote_code_ptr privileged_traced_syscall_in_rr_page = rr_page_syscall_entry_point(\n      TRACED, PRIVILEGED, RECORDING_AND_REPLAY, t->arch());\n  ok = true;\n  if (get_syscall_instruction_arch(t, privileged_traced_syscall_in_rr_page, &arch, &ok) &&\n      arch == t->arch()) {\n    privileged_traced_syscall_ip_ = privileged_traced_syscall_in_rr_page;\n  } else {\n    // Only the syscall at the privileged address can be privileged.\n    privileged_traced_syscall_ip_ = nullptr;\n  }\n}\n\nvoid AddressSpace::unmap_internal(Task* t, remote_ptr<void> addr,\n                                  ssize_t num_bytes) {\n  LOG(debug) << \"munmap(\" << addr << \", \" << num_bytes << \")\";\n\n  if (MemoryRange(addr, num_bytes).contains(RR_DL_RUNTIME_RESOLVE_CLEAR_FIP) &&\n      monkeypatch_state) {\n    monkeypatch_state->unpatch_dl_runtime_resolves(\n      static_cast<RecordTask*>(t));\n  }\n\n  auto unmapper = [this](Mapping m, MemoryRange rem) {\n    LOG(debug) << \"  unmapping (\" << rem << \") ...\";\n\n    remove_from_map(m.map);\n\n    LOG(debug) << \"  erased (\" << m.map << \") ...\";\n\n    // If the first segment we unmap underflows the unmap\n    // region, remap the underflow region.\n    auto monitored = m.monitored_shared_memory;\n    if (m.map.start() < rem.start()) {\n      Mapping underflow(m.map.subrange(m.map.start(), rem.start()),\n                        m.recorded_map.subrange(m.map.start(), rem.start()),\n                        m.emu_file, clone_stat(m.mapped_file_stat),\n                        m.local_addr, std::move(monitored));\n      underflow.flags = m.flags;\n      add_to_map(underflow);\n    }\n    // If the last segment we unmap overflows the unmap\n    // region, remap the overflow region.\n    if (rem.end() < m.map.end()) {\n      Mapping overflow(\n          m.map.subrange(rem.end(), m.map.end()),\n          m.recorded_map.subrange(rem.end(), m.map.end()), m.emu_file,\n          clone_stat(m.mapped_file_stat),\n          m.local_addr ? m.local_addr + (rem.end() - m.map.start()) : 0,\n          m.monitored_shared_memory\n              ? m.monitored_shared_memory->subrange(rem.end() - m.map.start(),\n                                                    m.map.end() - rem.end())\n              : nullptr);\n      overflow.flags = m.flags;\n      add_to_map(overflow);\n    }\n\n    if (m.local_addr) {\n      auto addr = m.local_addr + (rem.start() - m.map.start());\n      auto size = std::min(rem.size(), m.map.size() - (rem.start() - m.map.start()));\n      int ret = munmap(addr, size);\n      if (ret < 0) {\n        FATAL() << \"Can't munmap\";\n      }\n    }\n  };\n  for_each_in_range(addr, num_bytes, unmapper);\n  update_watchpoint_values(addr, addr + num_bytes);\n}\n\nvoid AddressSpace::advise(Task*, remote_ptr<void> addr, ssize_t num_bytes,\n                          int advice) {\n  LOG(debug) << \"madvise(\" << addr << \", \" << num_bytes << \", \" << advice\n             << \")\";\n  num_bytes = ceil_page_size(num_bytes);\n\n  switch (advice) {\n    case MADV_DONTFORK:\n      add_range(dont_fork, MemoryRange(addr, num_bytes));\n      break;\n    case MADV_DOFORK:\n      remove_range(dont_fork, MemoryRange(addr, num_bytes));\n      break;\n    case MADV_WIPEONFORK:\n      add_range(wipe_on_fork, MemoryRange(addr, num_bytes));\n      break;\n    case MADV_KEEPONFORK:\n      remove_range(wipe_on_fork, MemoryRange(addr, num_bytes));\n      break;\n    default:\n      break;\n  }\n}\n\nvoid AddressSpace::did_fork_into(Task* t) {\n  // MADV_WIPEONFORK is inherited across fork and cleared on exec.\n  // We'll copy it here, then do the `dont_fork` unmappings, and then\n  // whatever survives in the new AddressSpace's wipe_on_fork gets wiped.\n  t->vm()->wipe_on_fork = wipe_on_fork;\n\n  for (auto& range : dont_fork) {\n    // During recording we execute MADV_DONTFORK so the forked child will\n    // have had its dontfork areas unmapped by the kernel already\n    if (!t->session().is_recording()) {\n      AutoRemoteSyscalls remote(t);\n      remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                                range.start(), range.size());\n    }\n    t->vm()->unmap(t, range.start(), range.size());\n  }\n\n  // Any ranges that were dropped were unmapped (and thus removed from\n  // wipe_on_fork), so now we can record anything that's left.\n  for (auto& range : t->vm()->wipe_on_fork) {\n    if (t->session().is_recording()) {\n      // Record that these mappings were wiped.\n      RecordTask* rt = static_cast<RecordTask*>(t);\n      rt->record_remote(range);\n    }\n  }\n}\n\nvoid AddressSpace::set_anon_name(Task* t, MemoryRange range, const std::string* name) {\n  bool saw_only_anonymous = true;\n  MemoryRange last_overlap;\n  auto setter = [this, t, &name, &saw_only_anonymous, &last_overlap](Mapping m, MemoryRange rem) {\n    if (!(m.map.flags() & MAP_ANONYMOUS) || !saw_only_anonymous) {\n      saw_only_anonymous = false;\n      return;\n    }\n    remove_from_map(m.map);\n\n    if (m.map.start() < rem.start()) {\n      Mapping underflow = m.subrange(MemoryRange(m.map.start(), rem.start()),\n          [](const KernelMapping& km) { return km; });\n      add_to_map(underflow);\n    }\n    // Remap the overlapping region with the new prot.\n    remote_ptr<void> new_end = min(rem.end(), m.map.end());\n\n    Mapping overlap;\n    if (!name && (m.map.flags() & MAP_SHARED)) {\n      // We're resetting the name to whatever the original name was.\n      string new_name = read_kernel_mapping(t, rem.start()).fsname();\n      overlap = m.subrange(MemoryRange(rem.start(), new_end),\n        [&new_name, t](const KernelMapping& km) {\n          if (km.fsname().empty() && !t->session().is_recording()) {\n            // record_map case\n            return km;\n          }\n          return km.set_fsname(new_name);\n        });\n    } else {\n      string new_name;\n      if (name) {\n        if (m.map.flags() & MAP_SHARED) {\n          new_name = \"[anon_shmem:\" + *name + \"]\";\n        } else {\n          new_name = \"[anon:\" + *name + \"]\";\n        }\n      }\n      overlap = m.subrange(MemoryRange(rem.start(), new_end),\n        [&new_name](const KernelMapping& km) { return km.set_fsname(new_name); });\n    }\n    add_to_map(overlap);\n    last_overlap = overlap.map;\n\n    // If the last segment we protect overflows the\n    // region, remap the overflow region with previous\n    // prot.\n    if (new_end < m.map.end()) {\n      Mapping overflow = m.subrange(MemoryRange(new_end, m.map.end()),\n          [](const KernelMapping& km) { return km; });\n      add_to_map(overflow);\n    }\n  };\n  for_each_in_range(range.start(), range.size(), setter, ITERATE_CONTIGUOUS);\n  if (last_overlap.size()) {\n    // All mappings that we altered which might need coalescing\n    // are adjacent to |last_overlap|.\n    coalesce_around(t, mem.find(last_overlap));\n  }\n}\n\nstatic string strip_deleted(const string& s) {\n  static const char deleted[] = \" (deleted)\";\n  ssize_t find_deleted = s.size() - (sizeof(deleted) - 1);\n  if (s.find(deleted) == size_t(find_deleted)) {\n    return s.substr(0, find_deleted);\n  }\n  return s;\n}\n\nstring KernelMapping::fsname_strip_deleted() const {\n  return strip_deleted(fsname_);\n}\n\nenum HandleHeap { TREAT_HEAP_AS_ANONYMOUS, RESPECT_HEAP };\n\nstatic bool normalized_file_names_equal(const KernelMapping& km1,\n                                        const KernelMapping& km2,\n                                        HandleHeap handle_heap) {\n  if (km1.is_stack() || km2.is_stack()) {\n    // The kernel seems to use \"[stack:<tid>]\" for any mapping area containing\n    // thread |tid|'s stack pointer. When the thread exits, the next read of\n    // the maps doesn't treat the area as stack at all. We don't want to track\n    // thread exits, so if one of the mappings is a stack, skip the name\n    // comparison. Device and inode numbers will still be checked.\n    return true;\n  }\n  if (handle_heap == TREAT_HEAP_AS_ANONYMOUS &&\n      (km1.is_heap() || km2.is_heap())) {\n    // The kernel's heuristics for treating an anonymous mapping as \"[heap]\"\n    // are obscure. Just skip the name check. Device and inode numbers will\n    // still be checked.\n    return true;\n  }\n  // We don't track when a file gets deleted, so it's possible for the kernel\n  // to have \" (deleted)\" when we don't.\n  return strip_deleted(km1.fsname()) == strip_deleted(km2.fsname());\n}\n\n/**\n * Return true iff |left| and |right| are located adjacently in memory\n * with the same metadata, and map adjacent locations of the same\n * underlying (real) device.\n */\nstatic bool is_adjacent_mapping(const KernelMapping& mleft,\n                                const KernelMapping& mright,\n                                HandleHeap handle_heap,\n                                int32_t flags_to_check = 0xFFFFFFFF) {\n  if (mleft.end() != mright.start()) {\n    return false;\n  }\n  if (((mleft.flags() ^ mright.flags()) & flags_to_check) ||\n      mleft.prot() != mright.prot()) {\n    return false;\n  }\n  if (!normalized_file_names_equal(mleft, mright, handle_heap)) {\n    return false;\n  }\n  if (mleft.device() != mright.device() || mleft.inode() != mright.inode()) {\n    return false;\n  }\n  if (mleft.is_real_device() &&\n      mleft.file_offset_bytes() + off_t(mleft.size()) !=\n          mright.file_offset_bytes()) {\n    return false;\n  }\n  return true;\n}\n\n/**\n * If |*left_m| and |right_m| are adjacent (see\n * |is_adjacent_mapping()|), write a merged segment descriptor to\n * |*left_m| and return true.  Otherwise return false.\n */\nstatic bool try_merge_adjacent(KernelMapping* left_m,\n                               const KernelMapping& right_m) {\n  if (is_adjacent_mapping(*left_m, right_m, TREAT_HEAP_AS_ANONYMOUS,\n                          KernelMapping::checkable_flags_mask)) {\n    *left_m = KernelMapping(left_m->start(), right_m.end(), left_m->fsname(),\n                            left_m->device(), left_m->inode(), right_m.prot(),\n                            right_m.flags(), left_m->file_offset_bytes());\n    return true;\n  }\n  return false;\n}\n\nstatic dev_t normalized_device_number(const KernelMapping& m) {\n  if (m.fsname().c_str()[0] != '/') {\n    return m.device();\n  }\n  // btrfs files can report the wrong device number in /proc/<pid>/maps, so\n  // restrict ourselves to checking whether the device number is != 0\n  if (m.device() != KernelMapping::NO_DEVICE) {\n    return (dev_t)-1;\n  }\n  return m.device();\n}\n\nstatic void assert_segments_match(Task* t, const KernelMapping& input_m,\n                                  const KernelMapping& km) {\n  KernelMapping m = input_m;\n  string err;\n  if (m.start() != km.start()) {\n    err = \"starts differ\";\n  } else if (m.end() != km.end()) {\n    err = \"ends differ\";\n  } else if ((m.prot() ^ km.prot()) & KernelMapping::checkable_prot_mask) {\n    err = \"prots differ\";\n  } else if ((m.flags() ^ km.flags()) & KernelMapping::checkable_flags_mask) {\n    err = \"flags differ\";\n  } else if (!normalized_file_names_equal(m, km, TREAT_HEAP_AS_ANONYMOUS) &&\n             !(km.is_heap() && m.fsname() == \"\") &&\n             !(m.is_heap() && km.fsname() == \"\") && !km.is_vdso()) {\n    // Due to emulated exec, the kernel may identify any of our anonymous maps\n    // as [heap] (or not).\n    // Kernels before 3.16 have a bug where any mapping at the original VDSO\n    // address is marked [vdso] even if the VDSO was unmapped and replaced by\n    // something else, so if the kernel reports [vdso] it may be spurious and\n    // we skip this check. See kernel commit\n    // a62c34bd2a8a3f159945becd57401e478818d51c.\n    err = \"filenames differ\";\n  } else if (normalized_device_number(m) != normalized_device_number(km)) {\n    err = \"devices_differ\";\n  } else if (m.inode() != km.inode()) {\n    err = \"inodes differ\";\n  }\n  if (err.size()) {\n    cerr << \"cached mmap:\" << endl;\n    t->vm()->dump();\n    cerr << \"/proc/\" << t->tid << \"/mmaps:\" << endl;\n    AddressSpace::print_process_maps(t);\n    ASSERT(t, false) << \"\\nCached mapping \" << m << \" should be \" << km << \"; \"\n                     << err;\n  }\n}\n\nvoid AddressSpace::ensure_replay_matches_single_recorded_mapping(Task* t, MemoryRange range) {\n  // The only case where we eagerly coalesced during recording but not replay should\n  // be where we mapped private memory beyond-end-of-file.\n  // Don't do an actual coalescing check here; we rely on the caller to tell us\n  // the range to coalesce.\n  ASSERT(t, range.start() == floor_page_size(range.start()));\n  ASSERT(t, range.end() == ceil_page_size(range.end()));\n\n  auto fixer = [this, t, range](Mapping mapping, MemoryRange) {\n    if (mapping.map == range) {\n      // Existing single mapping covers entire range; nothing to do.\n      return;\n    }\n\n    // These should be null during replay\n    ASSERT(t, !mapping.mapped_file_stat);\n    // These should not be in use for a beyond-end-of-file mapping\n    ASSERT(t, !mapping.local_addr);\n    // The mapping should be private\n    ASSERT(t, mapping.map.flags() & MAP_PRIVATE);\n    ASSERT(t, !mapping.emu_file);\n    ASSERT(t, !mapping.monitored_shared_memory);\n    // Flagged mappings shouldn't be coalescable ever\n    ASSERT(t, !mapping.flags);\n\n    if (!(mapping.map.flags() & MAP_ANONYMOUS)) {\n      // Direct-mapped piece. Turn it into an anonymous mapping.\n      vector<uint8_t> buffer;\n      buffer.resize(mapping.map.size());\n      t->read_bytes_helper(mapping.map.start(), buffer.size(), buffer.data());\n      {\n        AutoRemoteSyscalls remote(t);\n        remote.infallible_mmap_syscall_if_alive(mapping.map.start(), buffer.size(),\n            mapping.map.prot(), mapping.map.flags() | MAP_ANONYMOUS | MAP_FIXED, -1, 0);\n      }\n      t->write_bytes_helper(mapping.map.start(), buffer.size(), buffer.data());\n\n      // We replace the entire mapping even if part of it falls outside the desired range.\n      // That's OK, this replacement preserves behaviour, it's simpler, even if a bit\n      // less efficient in weird cases.\n      mem.erase(mapping.map);\n      KernelMapping anonymous_km(mapping.map.start(), mapping.map.end(),\n                                 string(), KernelMapping::NO_DEVICE, KernelMapping::NO_INODE,\n                                 mapping.map.prot(), mapping.map.flags() | MAP_ANONYMOUS);\n      Mapping new_mapping(anonymous_km, mapping.recorded_map);\n      mem[new_mapping.map] = new_mapping;\n    }\n  };\n  for_each_in_range(range.start(), range.size(), fixer);\n\n  coalesce_around(t, mem.find(range));\n}\n\nKernelMapping AddressSpace::vdso() const {\n  DEBUG_ASSERT(!vdso_start_addr.is_null());\n  return mapping_of(vdso_start_addr).map;\n}\n\n/**\n * Iterate over /proc/maps segments for a task and verify that the\n * task's cached mapping matches the kernel's (given a lenient fuzz\n * factor).\n */\nvoid AddressSpace::verify(Task* t) const {\n  ASSERT(t, task_set().end() != task_set().find(t));\n\n  if (thread_group_in_exec(t)) {\n    return;\n  }\n\n  LOG(debug) << \"Verifying address space for task \" << t->tid;\n\n  MemoryMap::const_iterator mem_it = mem.begin();\n  bool ok = false;\n  // Must pass ok parameter otherwise KernelMapIterator constructor will become\n  // infallible if /proc/[tid]/maps cannot be opened\n  KernelMapIterator kernel_it(t, &ok);\n  // checking at_end() is equivalent to checking if ok\n  if (kernel_it.at_end()) {\n    LOG(debug) << \"Task \" << t->tid << \" exited unexpectedly, ignoring\";\n    return;\n  }\n  while (!kernel_it.at_end() && mem_it != mem.end()) {\n    KernelMapping km = kernel_it.current();\n    ++kernel_it;\n    while (!kernel_it.at_end()) {\n      KernelMapping next_km = kernel_it.current();\n      if (!try_merge_adjacent(&km, next_km)) {\n        break;\n      }\n      ++kernel_it;\n    }\n\n    KernelMapping vm = mem_it->second.map;\n    ++mem_it;\n    while (mem_it != mem.end() && try_merge_adjacent(&vm, mem_it->second.map)) {\n      ++mem_it;\n    }\n\n    assert_segments_match(t, vm, km);\n  }\n\n  ASSERT(t, kernel_it.at_end() && mem_it == mem.end());\n}\n\n// Just a place that rr's AutoSyscall functionality can use as a syscall\n// instruction in rr's address space for use before we have exec'd.\nextern \"C\" {\n// Mark this as hidden, otherwise we might get the address of the GOT entry,\n// which could cause problems.\nextern char rr_syscall_addr __attribute__ ((visibility (\"hidden\")));\n}\nstatic void __attribute__((noinline, used)) fake_syscall() {\n  __asm__ __volatile__(\".global rr_syscall_addr\\n\\t\");\n#ifdef __i386__\n  __asm__ __volatile__(\"rr_syscall_addr: int $0x80\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\");\n#elif defined(__x86_64__)\n  __asm__ __volatile__(\"rr_syscall_addr: syscall\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\");\n#elif defined(__aarch64__)\n  __asm__ __volatile__(\"rr_syscall_addr: svc #0\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\");\n#endif\n}\n\nAddressSpace::AddressSpace(Task* t, const string& exe, uint32_t exec_count)\n    : exe(exe),\n      leader_tid_(t->rec_tid),\n      leader_serial(t->tuid().serial()),\n      exec_count(exec_count),\n      session_(&t->session()),\n      monkeypatch_state(t->session().is_recording() ? new Monkeypatcher()\n                                                    : nullptr),\n      syscallbuf_enabled_(false),\n      layout_randomization_disabled_(false),\n      do_breakpoint_fault_addr_(nullptr),\n      stopping_breakpoint_table_(nullptr),\n      stopping_breakpoint_table_entry_size_(0),\n      first_run_event_(0) {\n  // TODO: this is a workaround of\n  // https://github.com/rr-debugger/rr/issues/1113 .\n  if (session_->done_initial_exec()) {\n    populate_address_space(t);\n    DEBUG_ASSERT(!vdso_start_addr.is_null());\n  } else {\n    // Setup traced_syscall_ip_ now because we need to do AutoRemoteSyscalls\n    // (for open_mem_fd) before the first exec. We rely on the fact that we\n    // haven't execed yet, so the address space layout is the same.\n    traced_syscall_ip_ = remote_code_ptr((uintptr_t)&rr_syscall_addr);\n  }\n}\n\n// Does not copy the task set; the new AddressSpace will be for new tasks.\nAddressSpace::AddressSpace(Session* session, const AddressSpace& o,\n                           pid_t leader_tid, uint32_t leader_serial,\n                           uint32_t exec_count)\n    : exe(o.exe),\n      leader_tid_(leader_tid),\n      leader_serial(leader_serial),\n      exec_count(exec_count),\n      brk_start(o.brk_start),\n      brk_end(o.brk_end),\n      mem(o.mem),\n      shm_sizes(o.shm_sizes),\n      monitored_mem(o.monitored_mem),\n      dont_fork(o.dont_fork),\n      wipe_on_fork(o.wipe_on_fork),\n      session_(session),\n      vdso_start_addr(o.vdso_start_addr),\n      monkeypatch_state(o.monkeypatch_state\n                            ? new Monkeypatcher(*o.monkeypatch_state)\n                            : nullptr),\n      traced_syscall_ip_(o.traced_syscall_ip_),\n      privileged_traced_syscall_ip_(o.privileged_traced_syscall_ip_),\n      syscallbuf_enabled_(o.syscallbuf_enabled_),\n      layout_randomization_disabled_(o.layout_randomization_disabled_),\n      do_breakpoint_fault_addr_(o.do_breakpoint_fault_addr_),\n      stopping_breakpoint_table_(o.stopping_breakpoint_table_),\n      stopping_breakpoint_table_entry_size_(o.stopping_breakpoint_table_entry_size_),\n      saved_auxv_(o.saved_auxv_),\n      saved_interpreter_base_(o.saved_interpreter_base_),\n      saved_ld_path_(o.saved_ld_path_),\n      last_free_memory(o.last_free_memory),\n      first_run_event_(0) {\n  for (auto& m : mem) {\n    // The original address space continues to have exclusive ownership of\n    // all local mappings.\n    m.second.local_addr = nullptr;\n  }\n\n  for (auto& it : o.breakpoints) {\n    breakpoints.insert(make_pair(it.first, it.second));\n  }\n  for (auto& it : o.watchpoints) {\n    watchpoints.insert(make_pair(it.first, it.second));\n  }\n  if (session != o.session()) {\n    // Cloning into a new session means we're checkpointing.\n    first_run_event_ = o.first_run_event_;\n  }\n  // cloned tasks will automatically get cloned debug registers and\n  // cloned address-space memory, so we don't need to do any more work here.\n}\n\nbool AddressSpace::post_vm_clone(Task* t) {\n  if (has_mapping(preload_thread_locals_start()) &&\n      (mapping_flags_of(preload_thread_locals_start()) &\n       AddressSpace::Mapping::IS_THREAD_LOCALS) == 0) {\n    // The tracee already has a mapping at this address that doesn't belong to\n    // us. Don't touch it.\n    return false;\n  }\n\n  // Otherwise, the preload_thread_locals mapping is nonexistent or ours.\n  // Recreate it.\n  AutoRemoteSyscalls remote(t);\n  t->session().create_shared_mmap(remote, PRELOAD_THREAD_LOCALS_SIZE,\n                                  preload_thread_locals_start(),\n                                  \"preload_thread_locals\");\n  mapping_flags_of(preload_thread_locals_start()) |=\n      AddressSpace::Mapping::IS_THREAD_LOCALS;\n  return true;\n}\n\nstatic bool try_split_unaligned_range(MemoryRange& range, size_t bytes,\n                                      vector<MemoryRange>& result) {\n  if ((range.start().as_int() & (bytes - 1)) || range.size() < bytes) {\n    return false;\n  }\n  result.push_back(MemoryRange(range.start(), bytes));\n  range = MemoryRange(range.start() + bytes, range.end());\n  return true;\n}\n\nstatic vector<MemoryRange> split_range(const MemoryRange& range) {\n  vector<MemoryRange> result;\n  MemoryRange r = range;\n  while (r.size() > 0) {\n    if ((sizeof(void*) < 8 || !try_split_unaligned_range(r, 8, result)) &&\n        !try_split_unaligned_range(r, 4, result) &&\n        !try_split_unaligned_range(r, 2, result)) {\n      bool ret = try_split_unaligned_range(r, 1, result);\n      DEBUG_ASSERT(ret);\n    }\n  }\n  return result;\n}\n\nstatic void configure_watch_registers(vector<WatchConfig>& regs,\n                                      const MemoryRange& range, WatchType type,\n                                      vector<int8_t>* assigned_regs,\n                                      AddressSpace::WatchpointAlignment alignment) {\n  if (alignment == AddressSpace::UNALIGNED) {\n    regs.push_back(WatchConfig(range.start(), range.size(), type));\n    return;\n  }\n\n  // Zero-sized WatchConfigs return no ranges here, so are ignored.\n  auto split_ranges = split_range(range);\n\n  if (type == WATCH_WRITE && range.size() > 1) {\n    // We can suppress spurious write-watchpoint triggerings by checking\n    // whether memory values have changed. So we can sometimes conserve\n    // debug registers by upgrading an unaligned range to an aligned range\n    // of a larger size.\n    uintptr_t align;\n    if (range.size() <= 2) {\n      align = 2;\n    } else if (range.size() <= 4 || sizeof(void*) <= 4) {\n      align = 4;\n    } else {\n      align = 8;\n    }\n    remote_ptr<void> aligned_start(range.start().as_int() & ~(align - 1));\n    remote_ptr<void> aligned_end((range.end().as_int() + (align - 1)) &\n                                 ~(align - 1));\n    auto split = split_range(MemoryRange(aligned_start, aligned_end));\n    // If the aligned range doesn't reduce register usage, use the original\n    // split to avoid spurious triggerings\n    if (split.size() < split_ranges.size()) {\n      split_ranges = split;\n    }\n  }\n\n  for (auto& r : split_ranges) {\n    if (assigned_regs) {\n      assigned_regs->push_back(regs.size());\n    }\n    regs.push_back(WatchConfig(r.start(), r.size(), type));\n  }\n}\n\nvector<WatchConfig> AddressSpace::get_watchpoints_internal(\n    WatchpointFilter filter,\n    WatchpointAlignment alignment,\n    UpdateWatchpointRegisterAssignments update_watchpoint_register_assignments) {\n  vector<WatchConfig> result;\n  for (auto& kv : watchpoints) {\n    if (filter == CHANGED_WATCHPOINTS) {\n      if (!kv.second.changed) {\n        continue;\n      }\n      kv.second.changed = false;\n    }\n    vector<int8_t>* assigned_regs = nullptr;\n    if (update_watchpoint_register_assignments == UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS) {\n      kv.second.debug_regs_for_exec_read.clear();\n      assigned_regs = &kv.second.debug_regs_for_exec_read;\n    }\n    const MemoryRange& r = kv.first;\n    int watching = kv.second.watched_bits();\n    if (EXEC_BIT & watching) {\n      configure_watch_registers(result, r, WATCH_EXEC, assigned_regs, alignment);\n    }\n    if (READ_BIT & watching) {\n      configure_watch_registers(result, r, WATCH_READWRITE, assigned_regs, alignment);\n    } else if (WRITE_BIT & watching) {\n      configure_watch_registers(result, r, WATCH_WRITE, nullptr, alignment);\n    }\n  }\n  return result;\n}\n\nbool AddressSpace::has_any_watchpoint_changes() {\n  for (auto& kv : watchpoints) {\n    if (kv.second.changed) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool AddressSpace::has_exec_watchpoint_fired(remote_code_ptr addr) {\n  for (auto& kv : watchpoints) {\n    if (kv.second.changed && kv.second.exec_count > 0 &&\n        kv.first.start() == addr.to_data_ptr<void>()) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool AddressSpace::allocate_watchpoints() {\n  vector<WatchConfig> regs = get_watchpoints_internal(ALL_WATCHPOINTS, ALIGNED,\n      UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS);\n\n  if (task_set().empty()) {\n    // We can't validate the watchpoint set in this case\n    FATAL() << \"No tasks???\";\n  }\n  if ((*task_set().begin())->set_debug_regs(regs)) {\n    return true;\n  }\n\n  for (auto kv : watchpoints) {\n    kv.second.debug_regs_for_exec_read.clear();\n  }\n  return false;\n}\n\nstatic inline void assert_coalescable(Task* t,\n                                      const AddressSpace::Mapping& lower,\n                                      const AddressSpace::Mapping& higher) {\n  ASSERT(t, lower.emu_file == higher.emu_file);\n  ASSERT(t, lower.flags == higher.flags);\n  ASSERT(t,\n         (lower.local_addr == 0 && higher.local_addr == 0) ||\n             lower.local_addr + lower.map.size() == higher.local_addr);\n  ASSERT(t, !lower.monitored_shared_memory && !higher.monitored_shared_memory);\n}\n\nstatic bool is_coalescable(const AddressSpace::Mapping& mleft,\n                           const AddressSpace::Mapping& mright) {\n  if (!is_adjacent_mapping(mleft.map, mright.map, RESPECT_HEAP) ||\n      !is_adjacent_mapping(mleft.recorded_map, mright.recorded_map,\n                           RESPECT_HEAP)) {\n    return false;\n  }\n  return mleft.flags == mright.flags;\n}\n\nvoid AddressSpace::coalesce_around(Task* t, MemoryMap::iterator it) {\n  auto first_kv = it;\n  while (mem.begin() != first_kv) {\n    auto next = first_kv;\n    --first_kv;\n    if (!is_coalescable(first_kv->second, next->second)) {\n      first_kv = next;\n      break;\n    }\n    assert_coalescable(t, first_kv->second, next->second);\n  }\n  auto last_kv = it;\n  while (true) {\n    auto prev = last_kv;\n    ++last_kv;\n    if (mem.end() == last_kv ||\n        !is_coalescable(prev->second, last_kv->second)) {\n      last_kv = prev;\n      break;\n    }\n    assert_coalescable(t, prev->second, last_kv->second);\n  }\n  ASSERT(t, last_kv != mem.end());\n  if (first_kv == last_kv) {\n    LOG(debug) << \"  no mappings to coalesce\";\n    return;\n  }\n\n  Mapping new_m(first_kv->second.map.extend(last_kv->first.end()),\n                first_kv->second.recorded_map.extend(last_kv->first.end()),\n                first_kv->second.emu_file,\n                clone_stat(first_kv->second.mapped_file_stat),\n                first_kv->second.local_addr);\n  new_m.flags = first_kv->second.flags;\n  LOG(debug) << \"  coalescing \" << new_m.map;\n\n  // monitored-memory currently isn't coalescable so we don't need to\n  // adjust monitored_mem\n  mem.erase(first_kv, ++last_kv);\n\n  auto ins = mem.insert(MemoryMap::value_type(new_m.map, new_m));\n  DEBUG_ASSERT(ins.second); // key didn't already exist\n}\n\nvoid AddressSpace::destroy_breakpoint(BreakpointMap::const_iterator it) {\n  if (task_set().empty()) {\n    return;\n  }\n  Task* t = first_running_task();\n  if (!t) {\n    return;\n  }\n  auto ptr = it->first.to_data_ptr<uint8_t>();\n  auto data = it->second.overwritten_data;\n  if (bkpt_instruction_length(arch()) == 1) {\n    LOG(debug) << \"Writing back \" << HEX(data[0]) << \" at \" << ptr;\n  } else {\n    LOG(debug) << \"Writing back \" << bkpt_instruction_length(arch()) << \" bytes at \" << ptr;\n  }\n  t->write_bytes_helper(ptr, bkpt_instruction_length(arch()),\n    data, nullptr, Task::IS_BREAKPOINT_RELATED);\n  breakpoints.erase(it);\n}\n\nvoid AddressSpace::maybe_update_breakpoints(Task* t, remote_ptr<uint8_t> addr,\n                                            size_t len) {\n  if (!len) {\n    return;\n  }\n  for (auto& it : breakpoints) {\n    remote_ptr<uint8_t> bp_addr = it.first.to_data_ptr<uint8_t>();\n    if (addr <= bp_addr && bp_addr < addr + len - 1) {\n      // This breakpoint was overwritten. Note the new data and reset the\n      // breakpoint.\n      bool ok = true;\n      t->read_bytes_helper(bp_addr, bkpt_instruction_length(arch()),\n        &it.second.overwritten_data, &ok);\n      ASSERT(t, ok);\n      t->write_bytes_helper(bp_addr, bkpt_instruction_length(arch()),\n        breakpoint_insn(arch()));\n    }\n  }\n}\n\nvoid AddressSpace::for_each_in_range(\n    remote_ptr<void> addr, ssize_t num_bytes,\n    function<void(Mapping m, MemoryRange rem)> f, int how) {\n  remote_ptr<void> region_start = floor_page_size(addr);\n  remote_ptr<void> last_unmapped_end = region_start;\n  remote_ptr<void> region_end = ceil_page_size(addr + num_bytes);\n  while (last_unmapped_end < region_end) {\n    // Invariant: |rem| is always exactly the region of\n    // memory remaining to be examined for pages to be\n    // unmapped.\n    MemoryRange rem(last_unmapped_end, region_end);\n\n    // The next page to iterate may not be contiguous with\n    // the last one seen.\n    auto it = mem.lower_bound(rem);\n    if (mem.end() == it) {\n      LOG(debug) << \"  not found, done.\";\n      return;\n    }\n\n    // Don't make a reference here. |f| is allowed to erase Mappings.\n    MemoryRange range = it->first;\n    if (rem.end() <= range.start()) {\n      LOG(debug) << \"  mapping at \" << range.start() << \" out of range, done.\";\n      return;\n    }\n    if (ITERATE_CONTIGUOUS == how &&\n        !(range.start() < region_start || rem.start() == range.start())) {\n      LOG(debug) << \"  discontiguous mapping at \" << range.start() << \", done.\";\n      return;\n    }\n\n    f(it->second, rem);\n\n    // Maintain the loop invariant.\n    last_unmapped_end = range.end();\n  }\n}\n\nvoid AddressSpace::map_and_coalesce(\n    Task* t, const KernelMapping& m, const KernelMapping& recorded_map,\n    EmuFile::shr_ptr emu_file, unique_ptr<struct stat> mapped_file_stat,\n    void* local_addr, shared_ptr<MonitoredSharedMemory> monitored) {\n  LOG(debug) << \"  mapping \" << m;\n\n  if (monitored) {\n    monitored_mem.insert(m.start());\n  }\n  auto ins = mem.insert(MemoryMap::value_type(\n      m, Mapping(m, recorded_map, emu_file, std::move(mapped_file_stat),\n                 local_addr, std::move(monitored))));\n  coalesce_around(t, ins.first);\n\n  update_watchpoint_values(m.start(), m.end());\n}\n\nstatic bool could_be_stack(const KernelMapping& km) {\n  // On 4.1.6-200.fc22.x86_64 we observe that during exec of the rr_exec_stub\n  // during replay, when the process switches from 32-bit to 64-bit, the 64-bit\n  // registers seem truncated to 32 bits during the initial PTRACE_GETREGS so\n  // our sp looks wrong and /proc/<pid>/maps doesn't identify the region as\n  // stack.\n  // On stub execs there should only be one read-writable memory area anyway.\n  return km.prot() == (PROT_READ | PROT_WRITE) && km.fsname() == \"\" &&\n         km.device() == KernelMapping::NO_DEVICE &&\n         km.inode() == KernelMapping::NO_INODE;\n}\n\nstatic dev_t check_device(const KernelMapping& km) {\n  if (km.fsname().c_str()[0] != '/') {\n    return km.device();\n  }\n  // btrfs files can return the wrong device number in /proc/<pid>/maps\n  struct stat st;\n  int ret = stat(km.fsname().c_str(), &st);\n  if (ret < 0) {\n    return km.device();\n  }\n  return st.st_dev;\n}\n\nvoid AddressSpace::populate_address_space(Task* t) {\n  bool found_proper_stack = false;\n  for (KernelMapIterator it(t); !it.at_end(); ++it) {\n    auto& km = it.current();\n    if (km.is_stack()) {\n      found_proper_stack = true;\n    }\n  }\n\n  // If we're being recorded by rr, we'll see the outer rr's rr_page and\n  // preload_thread_locals. In post_exec() we'll remap those with our\n  // own mappings. That's OK because a) the rr_page contents are the same\n  // anyway and immutable and b) the preload_thread_locals page is only\n  // used by the preload library, and the preload library only knows about\n  // the inner rr. I.e. as far as the outer rr is concerned, the tracee is\n  // not doing syscall buffering.\n\n  int found_stacks = 0;\n  for (KernelMapIterator it(t); !it.at_end(); ++it) {\n    auto& km = it.current();\n    int flags = km.flags();\n    remote_ptr<void> start = km.start();\n    bool is_stack = found_proper_stack ? km.is_stack() : could_be_stack(km);\n    if (is_stack) {\n      ++found_stacks;\n      flags |= MAP_GROWSDOWN;\n      if (uses_invisible_guard_page()) {\n        // MAP_GROWSDOWN segments really occupy one additional page before\n        // the start address shown by /proc/<pid>/maps --- unless that page\n        // is already occupied by another mapping.\n        if (!has_mapping(start - page_size())) {\n          start -= page_size();\n        }\n      }\n    }\n\n    map(t, start, km.end() - start, km.prot(), flags, km.file_offset_bytes(),\n        km.fsname(), check_device(km), km.inode(), nullptr);\n  }\n  ASSERT(t, found_stacks == 1);\n}\n\nstatic MemoryRange adjust_range_for_stack_growth(const KernelMapping& km) {\n  remote_ptr<void> start = km.start();\n  remote_ptr<void> end = km.end();\n  if (km.flags() & MAP_GROWSDOWN) {\n    start = min(start, km.end() - AddressSpace::chaos_mode_min_stack_size());\n    // We actually must separate mappings from the stack by at least one page - otherwise the\n    // kernel might merge the VMA we're allocating with the stack! That actually can only happen\n    // under rr anyway, because we strip out the MAP_GROWSDOWN flag out of the mmap flags. This\n    // causes problems for glibc - in particular pthread_attr_getstack will open /proc/self/maps\n    // and fish around for the top of the initial thread's stack, and it will get the wrong value\n    // if the stack VMA is merged with the one above it.\n    start -= page_size();\n    end += page_size();\n  }\n  return MemoryRange(start, end);\n}\n\nstatic MemoryRange overlaps_excluded_range(const RecordSession& session, MemoryRange range) {\n  for (const auto& r : session.excluded_ranges()) {\n    if (r.intersects(range)) {\n      return r;\n    }\n  }\n  return MemoryRange();\n}\n\nstatic bool is_all_memory_excluded(const RecordSession& session) {\n  for (const auto& r : session.excluded_ranges()) {\n    if (r == MemoryRange::all()) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// Choose a 4TB range to exclude from random mappings. This makes room for\n// advanced trace analysis tools that require a large address range in tracees\n// that is never mapped.\nstatic MemoryRange choose_global_exclusion_range(const RecordSession* session) {\n  if (session && is_all_memory_excluded(*session)) {\n    return MemoryRange(nullptr, 0);\n  }\n  if (session && session->fixed_global_exclusion_range().size()) {\n    // For TSAN we have a hardcoded range stored in the session.\n    return session->fixed_global_exclusion_range();\n  }\n\n  const uint64_t range_size = uint64_t(4)*1024*1024*1024*1024;\n  while (true) {\n    int bits = addr_bits(x86_64);\n    uint64_t r = ((uint64_t)(uint32_t)random() << 32) | (uint32_t)random();\n    uint64_t r_addr = r & ((uint64_t(1) << bits) - 1);\n    r_addr = min(r_addr, (uint64_t(1) << bits) - range_size);\n    remote_ptr<void> addr = floor_page_size(remote_ptr<void>(r_addr));\n    MemoryRange ret(addr, (uintptr_t)range_size);\n    if (!session || !overlaps_excluded_range(*session, ret).size()) {\n      return ret;\n    }\n  }\n}\n\nMemoryRange AddressSpace::get_global_exclusion_range(const RecordSession* session) {\n  static MemoryRange global_exclusion_range = choose_global_exclusion_range(session);\n  return global_exclusion_range;\n}\n\nstatic const remote_ptr<void> addr_space_start(0x40000);\n\nremote_ptr<void> AddressSpace::chaos_mode_find_free_memory(RecordTask* t,\n                                                           size_t len, remote_ptr<void> hint) {\n  if (is_all_memory_excluded(t->session())) {\n    return nullptr;\n  }\n\n  MemoryRange global_exclusion_range = get_global_exclusion_range(&t->session());\n  // NB: Above RR_PAGE_ADDR is probably not free anyways, but if it somehow is\n  // don't hand it out again.\n  static MemoryRange rrpage_so_range = MemoryRange(remote_ptr<void>(RR_PAGE_ADDR - PRELOAD_LIBRARY_PAGE_SIZE),\n                                                   remote_ptr<void>(RR_PAGE_ADDR + PRELOAD_LIBRARY_PAGE_SIZE));\n  assert(rrpage_so_range.size() == 2 * PRELOAD_LIBRARY_PAGE_SIZE);\n\n  // Ignore the hint half the time.\n  if (hint && (random() & 1)) {\n    hint = nullptr;\n  }\n\n  remote_ptr<void> start = hint;\n  if (!start) {\n    // Half the time, try to allocate at a completely random address. The other\n    // half of the time, we'll try to allocate immediately before or after a\n    // randomly chosen existing mapping.\n    if (random() % 2) {\n      uint64_t r = ((uint64_t)(uint32_t)random() << 32) | (uint32_t)random();\n      start = floor_page_size(remote_ptr<void>(r & ((uint64_t(1) << addr_bits(t->arch())) - 1)));\n    } else {\n      ASSERT(t, !mem.empty());\n      int map_index = random() % mem.size();\n      int map_count = 0;\n      for (const auto& m : maps()) {\n        if (map_count == map_index) {\n          start = m.map.start();\n          break;\n        }\n        ++map_count;\n      }\n    }\n  }\n  // Reserve 3 pages at the end of userspace in case Monkeypatcher wants\n  // to allocate something there.\n  uint64_t reserve_area_for_monkeypatching = 3 * page_size();\n  remote_ptr<void> addr_space_end =\n    usable_address_space_end(t->arch()) - reserve_area_for_monkeypatching;\n  // Clamp start so that we're in the usable address space.\n  start = max(start, addr_space_start);\n  start = min(start, addr_space_end - len);\n\n  // Search the address space in one direction all the way to the end,\n  // then in the other direction.\n  int direction = (random() % 2) ? 1 : -1;\n  remote_ptr<void> addr;\n  for (int iteration = 0; iteration < 2; ++iteration) {\n    // Invariant: [addr, addr+len) is always in the usable address space\n    // [addr_space_start, addr_space_end).\n    addr = start;\n    while (true) {\n      // Look for any reserved address space that overlaps [addr, addr+len]\n      // and store any overlapping range here. If multiple reserved areas\n      // overlap, we just pick one arbitrarily.\n      MemoryRange overlapping_range;\n      Maps m = maps_containing_or_after(addr);\n      if (m.begin() != m.end()) {\n        MemoryRange range = adjust_range_for_stack_growth(m.begin()->map);\n        if (range.start() < addr + len) {\n          overlapping_range = range;\n        }\n      }\n      if (!overlapping_range.size()) {\n        MemoryRange r(addr, ceil_page_size(len));\n        if (r.intersects(rrpage_so_range)) {\n          overlapping_range = rrpage_so_range;\n        } else if (r.intersects(global_exclusion_range)) {\n          overlapping_range = global_exclusion_range;\n        } else if (!t->session().excluded_ranges().empty()) {\n          ASSERT(t, word_size(t->arch()) >= 8)\n            << \"Chaos mode with ASAN/TSAN not supported in 32-bit processes\";\n          MemoryRange excluded = overlaps_excluded_range(t->session(), r);\n          if (excluded.size()) {\n            overlapping_range = excluded;\n          }\n        }\n      }\n      if (!overlapping_range.size()) {\n        // No overlap and the range fits into our address space. Stop.\n        return addr;\n      }\n      if (direction == -1) {\n        // Try moving backwards to allocate just before the start of\n        // the overlapping range.\n        if (overlapping_range.start() < addr_space_start + len) {\n          break;\n        }\n        addr = overlapping_range.start() - len;\n      } else {\n        // Try moving forwards to allocate just after the end of\n        // the overlapping range.\n        if (overlapping_range.end() + len > addr_space_end) {\n          break;\n        }\n        addr = overlapping_range.end();\n      }\n    }\n\n    direction = -direction;\n  }\n\n  return nullptr;\n}\n\nremote_ptr<void> AddressSpace::find_free_memory(Task* t,\n                                                size_t required_space,\n                                                remote_ptr<void> after,\n                                                FindFreeMemoryPolicy policy) {\n  if (after < last_free_memory &&\n      policy == FindFreeMemoryPolicy::USE_LAST_FREE_HINT) {\n    // Search for free memory starting at the last place we finished\n    // our search. This is more efficient than starting at the beginning\n    // every time.\n    after = last_free_memory;\n  }\n  remote_ptr<void> addr_space_end = usable_address_space_end(t->arch());\n  ASSERT(t, required_space < UINT64_MAX - addr_space_end.as_int());\n\n  bool started_from_beginning = after.is_null();\n  while (true) {\n    auto maps = maps_starting_at(after);\n    auto current = maps.begin();\n    while (current != maps.end()) {\n      auto next = current;\n      ++next;\n      remote_ptr<void> end_of_free_space;\n      if (next == maps.end()) {\n        end_of_free_space = addr_space_end;\n      } else {\n        end_of_free_space = min(addr_space_end, next->map.start());\n      }\n      if (current->map.end() + required_space <= end_of_free_space) {\n        return current->map.end();\n      }\n      current = next;\n    }\n    if (started_from_beginning) {\n      return nullptr;\n    }\n    started_from_beginning = true;\n    after = addr_space_start;\n  }\n}\n\nvoid AddressSpace::add_stap_semaphore_range(Task* task, MemoryRange range) {\n  ASSERT(task, range.start() != range.end())\n    << \"Unexpected zero-length SystemTap semaphore range: \" << range;\n  ASSERT(task, (range.size() & 1) == 0)\n    << \"Invalid SystemTap semaphore range at \"\n    << range\n    << \": size is not a multiple of the size of a STap semaphore!\";\n\n  auto ptr = range.start().cast<uint16_t>(),\n       end = range.end().cast<uint16_t>();\n  for (; ptr < end; ++ptr) {\n    stap_semaphores.insert(ptr);\n  }\n}\n\nvoid AddressSpace::remove_stap_semaphore_range(Task* task, MemoryRange range) {\n  ASSERT(task, range.start() != range.end())\n    << \"Unexpected zero-length SystemTap semaphore range: \" << range;\n  ASSERT(task, (range.size() & 1) == 0)\n    << \"Invalid SystemTap semaphore range at \"\n    << range\n    << \": size is not a multiple of the size of a STap semaphore!\";\n\n  auto ptr = range.start().cast<uint16_t>(),\n       end = range.end().cast<uint16_t>();\n  for (; ptr < end; ++ptr) {\n    stap_semaphores.erase(ptr);\n  }\n}\n\nbool AddressSpace::is_stap_semaphore(remote_ptr<uint16_t> addr) {\n  return stap_semaphores.find(addr) != stap_semaphores.end();\n}\n\nvoid AddressSpace::fd_tables_changed() {\n  if (!session()->is_recording()) {\n    // All modifications are recorded during record\n    return;\n  }\n  if (!syscallbuf_enabled()) {\n    return;\n  }\n  DEBUG_ASSERT(task_set().size() != 0);\n  uint8_t fdt_uniform = true;\n  RecordTask* rt = static_cast<RecordTask*>(first_running_task());\n  if (!rt) {\n    return;\n  }\n  auto fdt = rt->fd_table();\n  for (auto* t : task_set()) {\n    if (t->fd_table() != fdt) {\n      fdt_uniform = false;\n    }\n  }\n  auto addr = REMOTE_PTR_FIELD(rt->preload_globals, fdt_uniform);\n  bool ok = true;\n  if (rt->read_mem(addr, &ok) != fdt_uniform) {\n    if (!ok) {\n      return;\n    }\n    rt->write_mem(addr, fdt_uniform);\n    rt->record_local(addr, sizeof(fdt_uniform), &fdt_uniform);\n  }\n}\n\nbool AddressSpace::range_is_private_mapping(const MemoryRange& range) const {\n  MemoryRange r = range;\n  while (r.size() > 0) {\n    if (!has_mapping(r.start())) {\n      return false;\n    }\n    const AddressSpace::Mapping& m = mapping_of(r.start());\n    if (!(m.map.flags() & MAP_PRIVATE)) {\n      return false;\n    }\n    if (m.map.end() >= r.end()) {\n      return true;\n    }\n    r = MemoryRange(m.map.end(), r.end());\n  }\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/AddressSpace.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_ADDRESS_SPACE_H_\n#define RR_ADDRESS_SPACE_H_\n\n#include <inttypes.h>\n#include <linux/kdev_t.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n\n#include <functional>\n#include <map>\n#include <memory>\n#include <set>\n#include <string>\n#include <vector>\n\n#include \"preload/preload_interface.h\"\n\n#include \"EmuFs.h\"\n#include \"HasTaskSet.h\"\n#include \"MemoryRange.h\"\n#include \"Monkeypatcher.h\"\n#include \"TaskishUid.h\"\n#include \"TraceStream.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"log.h\"\n#include \"remote_code_ptr.h\"\n#include \"util.h\"\n\nnamespace rr {\n\nclass AutoRemoteSyscalls;\nclass MonitoredSharedMemory;\nclass RecordSession;\nclass RecordTask;\nclass Session;\nclass Task;\n\n/**\n * Records information that the kernel knows about a mapping. This includes\n * everything returned through /proc/<pid>/maps but also information that\n * we know from observing mmap and mprotect calls.\n */\nclass KernelMapping : public MemoryRange {\npublic:\n  /**\n   * These are the flags we track internally to distinguish\n   * between adjacent segments.  For example, the kernel\n   * considers a NORESERVE anonymous mapping that's adjacent to\n   * a non-NORESERVE mapping distinct, even if all other\n   * metadata are the same.  See |is_adjacent_mapping()|.\n   */\n  static const int map_flags_mask = MAP_ANONYMOUS | MAP_NORESERVE |\n                                    MAP_PRIVATE | MAP_SHARED | MAP_STACK |\n                                    MAP_GROWSDOWN;\n  static const int checkable_flags_mask = MAP_PRIVATE | MAP_SHARED;\n  static const int checkable_prot_mask = PROT_READ | PROT_WRITE | PROT_EXEC;\n  static const dev_t NO_DEVICE = 0;\n  static const ino_t NO_INODE = 0;\n\n  KernelMapping() : device_(0), inode_(0), prot_(0), flags_(0), offset(0) {}\n  KernelMapping(remote_ptr<void> start, remote_ptr<void> end,\n                const std::string& fsname, dev_t device, ino_t inode, int prot,\n                int flags, off_t offset = 0)\n      : MemoryRange(start, end),\n        fsname_(fsname),\n        device_(device),\n        inode_(inode),\n        prot_(prot),\n        flags_(flags & map_flags_mask),\n        offset(offset) {\n    assert_valid();\n  }\n\n  KernelMapping(const KernelMapping& o)\n      : MemoryRange(o),\n        fsname_(o.fsname_),\n        device_(o.device_),\n        inode_(o.inode_),\n        prot_(o.prot_),\n        flags_(o.flags_),\n        offset(o.offset) {\n    assert_valid();\n  }\n  KernelMapping operator=(const KernelMapping& o) {\n    this->~KernelMapping();\n    new (this) KernelMapping(o);\n    return *this;\n  }\n\n  void assert_valid() const {\n    DEBUG_ASSERT(end() >= start());\n    DEBUG_ASSERT(size() % page_size() == 0);\n    DEBUG_ASSERT(!(flags_ & ~map_flags_mask));\n    DEBUG_ASSERT(offset % page_size() == 0);\n  }\n\n  KernelMapping extend(remote_ptr<void> end) const {\n    DEBUG_ASSERT(end >= MemoryRange::end());\n    return KernelMapping(start(), end, fsname_, device_, inode_, prot_, flags_,\n                         offset);\n  }\n  KernelMapping set_range(remote_ptr<void> start, remote_ptr<void> end) const {\n    return KernelMapping(start, end, fsname_, device_, inode_, prot_, flags_,\n                         offset);\n  }\n  KernelMapping subrange(remote_ptr<void> start, remote_ptr<void> end) const {\n    DEBUG_ASSERT(start >= MemoryRange::start() && end <= MemoryRange::end());\n    return KernelMapping(\n        start, end, fsname_, device_, inode_, prot_, flags_,\n        offset + (is_real_device() ? start - MemoryRange::start() : 0));\n  }\n  KernelMapping set_prot(int prot) const {\n    return KernelMapping(start(), end(), fsname_, device_, inode_, prot, flags_,\n                         offset);\n  }\n  KernelMapping set_fsname(const std::string& name) const {\n    return KernelMapping(start(), end(), name, device_, inode_, prot_, flags_,\n                         offset);\n  }\n\n  /**\n   * Dump a representation of |this| to a string in a format\n   * similar to the former part of /proc/[tid]/maps.\n  */\n  std::string str() const {\n    char str[200];\n    sprintf(str, \"%8p-%8p %c%c%c%c %08\" PRIx64 \" %02x:%02x %-10ld \",\n            (void*)start().as_int(), (void*)end().as_int(),\n            (PROT_READ & prot_) ? 'r' : '-', (PROT_WRITE & prot_) ? 'w' : '-',\n            (PROT_EXEC & prot_) ? 'x' : '-', (MAP_SHARED & flags_) ? 's' : 'p',\n            offset, (int)MAJOR(device()), (int)MINOR(device()), (long)inode());\n    return str + fsname();\n  }\n\n  const std::string& fsname() const { return fsname_; }\n  std::string fsname_strip_deleted() const;\n  dev_t device() const { return device_; }\n  ino_t inode() const { return inode_; }\n  int prot() const { return prot_; }\n  int flags() const { return flags_; }\n  uint64_t file_offset_bytes() const { return offset; }\n\n  /**\n   * Return true if this file is/was backed by an external\n   * device, as opposed to a transient RAM mapping.\n   */\n  bool is_real_device() const { return device() > NO_DEVICE; }\n  bool is_vdso() const { return fsname() == \"[vdso]\"; }\n  bool is_heap() const { return fsname() == \"[heap]\"; }\n  bool is_stack() const { return fsname().find(\"[stack\") == 0; }\n  bool is_vvar() const { return fsname() == \"[vvar]\"; }\n  bool is_vvar_vclock() const { return fsname() == \"[vvar_vclock]\"; }\n  bool is_vsyscall() const { return fsname() == \"[vsyscall]\"; }\n  bool is_named_anonymous() const {\n    return fsname().find(\"[anon:\") == 0 || fsname().find(\"[anon_shmem:\") == 0;\n  }\n\n  struct stat fake_stat() const {\n    struct stat fake_stat;\n    memset(&fake_stat, 0, sizeof(fake_stat));\n    fake_stat.st_dev = device();\n    fake_stat.st_ino = inode();\n    fake_stat.st_size = size();\n    return fake_stat;\n  }\n\nprivate:\n  // The kernel's name for the mapping, as per /proc/<pid>/maps. This must\n  // be exactly correct.\n  const std::string fsname_;\n  // Note that btrfs has weird behavior and /proc/.../maps can show a different\n  // device number to the device from stat()ing the file that was mapped.\n  // https://www.mail-archive.com/linux-btrfs@vger.kernel.org/msg57667.html\n  // We store here the device number obtained from fstat()ing the file.\n  // This also seems to be consistent with what we read from populate_address_space\n  // for the initial post-exec mappings. It is NOT consistent with what we get\n  // from reading /proc/.../maps for non-initial mappings.\n  dev_t device_;\n  ino_t inode_;\n  const int prot_;\n  const int flags_;\n  const uint64_t offset;\n};\ninline std::ostream& operator<<(std::ostream& o, const KernelMapping& m) {\n  o << m.str();\n  return o;\n}\n\n/**\n * Compare |a| and |b| so that \"subset\" lookups will succeed.  What\n * does that mean?  If |a| and |b| overlap (intersect), then this\n * comparator considers them equivalent.  That means that if |a|\n * represents one byte within a mapping |b|, then |a| and |b| will be\n * considered equivalent.\n *\n * If |a| and |b| don't overlap, return true if |a|'s start address is\n * less than |b|'s/\n */\nstruct MappingComparator {\n  bool operator()(const MemoryRange& a, const MemoryRange& b) const {\n    return !a.intersects(b) && a.start() < b.start();\n  }\n};\n\nenum BreakpointType {\n  BKPT_NONE = 0,\n  // Trap for internal rr purposes, f.e. replaying async\n  // signals.\n  BKPT_INTERNAL,\n  // Trap on behalf of a debugger user.\n  BKPT_USER,\n};\n\nenum WatchType {\n  // NB: these random-looking enumeration values are chosen to\n  // match the numbers programmed into x86 debug registers.\n  WATCH_EXEC = 0x00,\n  WATCH_WRITE = 0x01,\n  WATCH_READWRITE = 0x03\n};\n\nenum ArmWatchType {\n  ARM_WATCH_EXEC = 0x0,\n  ARM_WATCH_READ = 0x1,\n  ARM_WATCH_WRITE = 0x2,\n  ARM_WATCH_READWRITE = ARM_WATCH_READ | ARM_WATCH_WRITE\n};\n\nenum ArmPrivLevel {\n  ARM_PRIV_EL0 = 0x2\n};\n\nenum DebugStatus {\n  DS_WATCHPOINT_ANY = 0xf,\n  DS_SINGLESTEP = 1 << 14,\n};\n\n/**\n * A distinct watchpoint, corresponding to the information needed to\n * program a single hardware watchpoint.\n */\nstruct WatchConfig {\n  WatchConfig(remote_ptr<void> addr, size_t num_bytes, WatchType type)\n      : addr(addr), num_bytes(num_bytes), type(type) {}\n  remote_ptr<void> addr;\n  size_t num_bytes;\n  WatchType type;\n\n  bool operator==(const WatchConfig& other) const {\n    return addr == other.addr && num_bytes == other.num_bytes &&\n      type == other.type;\n  }\n  bool operator!=(const WatchConfig& other) const {\n    return !(*this == other);\n  }\n};\n\n/**\n * Models the address space for a set of tasks.  This includes the set\n * of mapped pages, and the resources those mappings refer to.\n */\nclass AddressSpace : public HasTaskSet {\n  friend class Session;\n  friend struct VerifyAddressSpace;\n\npublic:\n  class Mapping {\n  public:\n    Mapping(const KernelMapping& map, const KernelMapping& recorded_map,\n            EmuFile::shr_ptr emu_file = nullptr,\n            std::unique_ptr<struct stat> mapped_file_stat = nullptr,\n            void* local_addr = nullptr,\n            std::shared_ptr<MonitoredSharedMemory>&& monitored = nullptr);\n    ~Mapping();\n    Mapping(const Mapping&);\n    Mapping() : local_addr(nullptr), flags(0) {}\n    const Mapping& operator=(const Mapping& other) {\n      this->~Mapping();\n      new (this) Mapping(other);\n      return *this;\n    }\n    Mapping subrange(MemoryRange range,\n                     std::function<KernelMapping(const KernelMapping&)> f) const;\n\n    const KernelMapping map;\n    // The corresponding KernelMapping in the recording. During recording,\n    // equal to 'map'.\n    const KernelMapping recorded_map;\n    const EmuFile::shr_ptr emu_file;\n    std::unique_ptr<struct stat> mapped_file_stat;\n    // If this mapping has been mapped into the local address space,\n    // this is the address of the first byte of the equivalent local mapping.\n    // This mapping is always mapped as PROT_READ|PROT_WRITE regardless of the\n    // mapping's permissions in the tracee. Also note that it is the caller's\n    // responsibility to keep this alive at least as long as this mapping is\n    // present in the address space.\n    uint8_t* local_addr;\n    const std::shared_ptr<MonitoredSharedMemory> monitored_shared_memory;\n    // Flags indicate mappings that require special handling. Adjacent mappings\n    // may only be merged if their `flags` value agree.\n    enum : uint32_t {\n      FLAG_NONE = 0x0,\n      // This mapping represents a syscallbuf. It needs to handled specially\n      // during checksumming since its contents are not fully restored by the\n      // replay.\n      IS_SYSCALLBUF = 0x1,\n      // This mapping is used as our thread-local variable area for this\n      // address space\n      IS_THREAD_LOCALS = 0x2,\n      // This mapping is used for syscallbuf patch stubs\n      IS_PATCH_STUBS = 0x4,\n      // This mapping is the rr page\n      IS_RR_PAGE = 0x8,\n      // This mapping is the rr vdso page\n      IS_RR_VDSO_PAGE = 0x10,\n    };\n    uint32_t flags;\n  };\n\n  typedef std::map<MemoryRange, Mapping, MappingComparator> MemoryMap;\n  typedef std::shared_ptr<AddressSpace> shr_ptr;\n\n  virtual ~AddressSpace();\n\n  /**\n   * Call this after a successful execve syscall has completed. At this point\n   * it is safe to perform remote syscalls.\n   */\n  void post_exec_syscall(Task* t);\n\n  /**\n   * Change the program data break of this address space to\n   * |addr|. Only called during recording!\n   */\n  void brk(Task* t, remote_ptr<void> addr, int prot);\n\n  /**\n   * This can only be called during recording.\n   */\n  remote_ptr<void> current_brk() const {\n    DEBUG_ASSERT(!brk_end.is_null());\n    return brk_end;\n  }\n\n  /**\n   * Dump a representation of |this| to stderr in a format\n   * similar to /proc/[tid]/maps.\n   *\n   * XXX/ostream-ify me.\n   */\n  void dump() const;\n\n  /**\n   * Return tid of the first task for this address space.\n   */\n  pid_t leader_tid() const { return leader_tid_; }\n\n  /**\n   * Return AddressSpaceUid for this address space.\n   */\n  AddressSpaceUid uid() const {\n    return AddressSpaceUid(leader_tid_, leader_serial, exec_count);\n  }\n\n  Session* session() const { return session_; }\n\n  SupportedArch arch() const;\n\n  /**\n   * Return the path this address space was exec()'d with.\n   */\n  const std::string& exe_image() const { return exe; }\n\n  const std::string& interp_name() const { return interp_name_; }\n  void set_interp_name(std::string name) { interp_name_ = name; }\n\n  remote_ptr<void> interp_base() const { return interp_base_; }\n  void set_interp_base(remote_ptr<void> base) { interp_base_ = base; }\n\n  // Set anonymous region name as per PR_SET_VMA_ANON_NAME.\n  // Stops at the first unmapped memory page.\n  void set_anon_name(Task* t, MemoryRange range, const std::string* name);\n\n  /**\n   * Assuming the last retired instruction has raised a SIGTRAP\n   * and might be a breakpoint trap instruction, return the type\n   * of breakpoint set at |ip() - sizeof(breakpoint_insn)|, if\n   * one exists.  Otherwise return TRAP_NONE.\n   */\n  BreakpointType get_breakpoint_type_for_retired_insn(remote_code_ptr ip);\n\n  /**\n   * Return the type of breakpoint that's been registered for\n   * |addr|.\n   */\n  BreakpointType get_breakpoint_type_at_addr(remote_code_ptr addr);\n\n  /**\n   * Check if the user has placed a hardware EXEC watchpoint at addr.\n   */\n  bool is_exec_watchpoint(remote_code_ptr addr);\n\n  /**\n   * Returns true when the breakpoint at |addr| is in private\n   * non-writeable memory. When this returns true, the breakpoint can't be\n   * overwritten by the tracee without an intervening mprotect or mmap\n   * syscall.\n   */\n  bool is_breakpoint_in_private_read_only_memory(remote_code_ptr addr);\n\n  /**\n   * Return true if there's a breakpoint instruction at |ip|. This might\n   * be an explicit instruction, even if there's no breakpoint set via our API.\n   */\n  bool is_breakpoint_instruction(Task* t, remote_code_ptr ip);\n\n  /**\n   * The buffer |dest| of length |length| represents the contents of tracee\n   * memory at |addr|. Replace the bytes in |dest| that have been overwritten\n   * by breakpoints with the original data that was replaced by the breakpoints.\n   */\n  void replace_breakpoints_with_original_values(uint8_t* dest, size_t length,\n                                                remote_ptr<uint8_t> addr);\n\n  /**\n   * Map |num_bytes| into this address space at |addr|, with\n   * |prot| protection and |flags|.  The pages are (possibly\n   * initially) backed starting at |offset| of |res|. |fsname|, |device| and\n   * |inode| are values that will appear in the /proc/<pid>/maps entry.\n   * |mapped_file_stat| is a complete copy of the 'stat' data for the mapped\n   * file, or null if this isn't a file mapping or isn't during recording.\n   * |*recorded_map| is the mapping during recording, or null if the mapping\n   * during recording is known to be the same as the new map (e.g. because\n   * we are recording!).\n   * |local_addr| is the local address of the memory shared with the tracee,\n   * or null if it's not shared with the tracee. AddressSpace takes ownership\n   * of the shared memory and is responsible for unmapping it.\n   */\n  KernelMapping map(\n      Task* t, remote_ptr<void> addr, size_t num_bytes, int prot, int flags,\n      off_t offset_bytes, const std::string& fsname,\n      dev_t device = KernelMapping::NO_DEVICE,\n      ino_t inode = KernelMapping::NO_INODE,\n      std::unique_ptr<struct stat> mapped_file_stat = nullptr,\n      const KernelMapping* recorded_map = nullptr,\n      EmuFile::shr_ptr emu_file = nullptr, void* local_addr = nullptr,\n      std::shared_ptr<MonitoredSharedMemory> monitored = nullptr);\n\n  /**\n   * Return the mapping and mapped resource for the byte at address 'addr'.\n   * There must be such a mapping.\n   */\n  const Mapping& mapping_of(remote_ptr<void> addr) const;\n\n  /**\n   * Detach local mapping and return it.\n   */\n  void* detach_local_mapping(remote_ptr<void> addr);\n\n  /**\n   * Return a reference to the flags of the mapping at this address, allowing\n   * manipulation. There must exist a mapping at `addr`.\n   */\n  uint32_t& mapping_flags_of(remote_ptr<void> addr);\n\n  /**\n   * Return true if there is some mapping for the byte at 'addr'.\n   */\n  bool has_mapping(remote_ptr<void> addr) const;\n\n  /**\n   * If the given memory region is mapped into the local address space, obtain\n   * the local address from which the `size` bytes at `addr` can be accessed.\n   */\n  uint8_t* local_mapping(remote_ptr<void> addr, size_t size);\n\n  /**\n   * Return true if the rr page is mapped at its expected address.\n   */\n  bool has_rr_page() const;\n\n  /**\n   * Object that generates robust iterators through the memory map. The\n   * memory map can be updated without invalidating iterators, as long as\n   * Mappings are not added or removed.\n   */\n  class Maps {\n  public:\n    Maps(const AddressSpace& outer, remote_ptr<void> start)\n        : outer(outer), start(start) {}\n    class iterator {\n    public:\n      iterator(const iterator& it) = default;\n      const iterator& operator++() {\n        ptr = to_it()->second.map.end();\n        return *this;\n      }\n      bool operator==(const iterator& other) const {\n        return to_it() == other.to_it();\n      }\n      bool operator!=(const iterator& other) const { return !(*this == other); }\n      const Mapping* operator->() const { return &to_it()->second; }\n      const Mapping& operator*() const { return to_it()->second; }\n      iterator& operator=(const iterator& other) {\n        this->~iterator();\n        new (this) iterator(other);\n        return *this;\n      }\n\n    private:\n      friend class Maps;\n      iterator(const MemoryMap& outer, remote_ptr<void> ptr)\n          : outer(outer), ptr(ptr), at_end(false) {}\n      iterator(const MemoryMap& outer) : outer(outer), at_end(true) {}\n      MemoryMap::const_iterator to_it() const {\n        return at_end ? outer.end() : outer.lower_bound(MemoryRange(ptr, ptr));\n      }\n      const MemoryMap& outer;\n      remote_ptr<void> ptr;\n      bool at_end;\n    };\n    iterator begin() const { return iterator(outer.mem, start); }\n    iterator end() const { return iterator(outer.mem); }\n\n  private:\n    const AddressSpace& outer;\n    remote_ptr<void> start;\n  };\n  friend class Maps;\n  Maps maps() const { return Maps(*this, remote_ptr<void>()); }\n  Maps maps_starting_at(remote_ptr<void> start) { return Maps(*this, start); }\n  Maps maps_containing_or_after(remote_ptr<void> start) {\n    if (has_mapping(start)) {\n      return Maps(*this, mapping_of(start).map.start());\n    } else {\n      return Maps(*this, start);\n    }\n  }\n\n  const std::set<remote_ptr<void>>& monitored_addrs() const {\n    return monitored_mem;\n  }\n\n  /**\n   * Change the protection bits of [addr, addr + num_bytes) to\n   * |prot|.\n   */\n  void protect(Task* t, remote_ptr<void> addr, size_t num_bytes, int prot);\n\n  /**\n   * Fix up mprotect registers parameters to take account of PROT_GROWSDOWN.\n   */\n  void fixup_mprotect_growsdown_parameters(Task* t);\n\n  /**\n   * Move the mapping [old_addr, old_addr + old_num_bytes) to\n   * [new_addr, old_addr + new_num_bytes), preserving metadata.\n   */\n  void remap(Task* t, remote_ptr<void> old_addr, size_t old_num_bytes,\n             remote_ptr<void> new_addr, size_t new_num_bytes, int flags);\n\n  /**\n   * Notify that data was written to this address space by rr or\n   * by the kernel.\n   * |flags| can contain values from Task::WriteFlags.\n   */\n  void notify_written(remote_ptr<void> addr, size_t num_bytes, uint32_t flags);\n\n  /** Ensure a breakpoint of |type| is set at |addr|. */\n  bool add_breakpoint(remote_code_ptr addr, BreakpointType type);\n  /**\n   * Remove a |type| reference to the breakpoint at |addr|.  If\n   * the removed reference was the last, the breakpoint is\n   * destroyed.\n   */\n  void remove_breakpoint(remote_code_ptr addr, BreakpointType type);\n  /**\n   * Destroy all breakpoints in this VM, regardless of their\n   * reference counts.\n   */\n  void remove_all_breakpoints();\n\n  /**\n   * Temporarily remove the breakpoint at |addr|.\n   */\n  void suspend_breakpoint_at(remote_code_ptr addr);\n  /**\n   * Restore any temporarily removed breakpoint at |addr|.\n   */\n  void restore_breakpoint_at(remote_code_ptr addr);\n\n  /**\n   * Manage watchpoints.  Analogous to breakpoint-managing\n   * methods above, except that watchpoints can be set for an\n   * address range.\n   */\n  bool add_watchpoint(remote_ptr<void> addr, size_t num_bytes, WatchType type);\n  void remove_watchpoint(remote_ptr<void> addr, size_t num_bytes,\n                         WatchType type);\n  void remove_all_watchpoints();\n  std::vector<WatchConfig> all_watchpoints() {\n    return get_watchpoints_internal(ALL_WATCHPOINTS, UNALIGNED,\n      DONT_UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS);\n  }\n\n  /**\n   * Save all watchpoint state onto a stack.\n   */\n  void save_watchpoints();\n  /**\n   * Pop all watchpoint state from the saved-state stack.\n   */\n  bool restore_watchpoints();\n\n  /**\n   * Notify that at least one watchpoint was hit --- recheck them all.\n   * Returns true if any watchpoint actually triggered. Note that\n   * debug_status can indicate a hit watchpoint that doesn't actually\n   * trigger, because the value of a write-watchpoint did not change.\n   * Likewise, debug_status can indicate a watchpoint wasn't hit that\n   * actually was (because in some configurations, e.g. VMWare\n   * hypervisor with 32-bit x86 guest, debug_status watchpoint bits\n   * are known to not be set on singlestep).\n   */\n  bool notify_watchpoint_fired(uintptr_t debug_status,\n      remote_ptr<void> hit_addr,\n      remote_code_ptr address_of_singlestep_start);\n  /**\n   * Return true if any watchpoint has fired. Will keep returning true until\n   * consume_watchpoint_changes() is called.\n   */\n  bool has_any_watchpoint_changes();\n  /**\n   * Return true if an EXEC watchpoint has fired at addr since the last\n   * consume_watchpoint_changes.\n   */\n  bool has_exec_watchpoint_fired(remote_code_ptr addr);\n\n  /**\n   * Return all changed watchpoints in |watches| and clear their changed flags.\n   */\n  std::vector<WatchConfig> consume_watchpoint_changes() {\n    return get_watchpoints_internal(CHANGED_WATCHPOINTS, UNALIGNED,\n      DONT_UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS);\n  }\n\n  /**\n   * Get hardware watchpoint assignments.\n   */\n  std::vector<WatchConfig> get_hw_watchpoints() {\n    return get_watchpoints_internal(ALL_WATCHPOINTS, ALIGNED,\n      DONT_UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS);\n  }\n\n  void set_shm_size(remote_ptr<void> addr, size_t bytes) {\n    shm_sizes[addr] = bytes;\n  }\n  /**\n   * Dies if no shm size is registered for the address.\n   */\n  size_t get_shm_size(remote_ptr<void> addr) { return shm_sizes[addr]; }\n  void remove_shm_size(remote_ptr<void> addr) { shm_sizes.erase(addr); }\n\n  /**\n   * Make [addr, addr + num_bytes) inaccessible within this\n   * address space.\n   */\n  void unmap(Task* t, remote_ptr<void> addr, ssize_t num_bytes);\n\n  /**\n   * Notification of madvise call.\n   */\n  void advise(Task* t, remote_ptr<void> addr, ssize_t num_bytes, int advice);\n\n  /** Return the vdso mapping of this. */\n  KernelMapping vdso() const;\n  bool has_vdso() const { return has_mapping(vdso_start_addr); }\n\n  /**\n   * Verify that this cached address space matches what the\n   * kernel thinks it should be.\n   */\n  void verify(Task* t) const;\n\n  bool has_breakpoints() { return !breakpoints.empty(); }\n  bool has_watchpoints() { return !watchpoints.empty(); }\n\n  ScopedFd& mem_fd() { return child_mem_fd; }\n  void set_mem_fd(ScopedFd&& fd) { child_mem_fd = std::move(fd); }\n\n  ScopedFd& pagemap_fd() { return child_pagemap_fd; }\n  void set_pagemap_fd(ScopedFd&& fd) { child_pagemap_fd = std::move(fd); }\n\n  Monkeypatcher& monkeypatcher() {\n    DEBUG_ASSERT(monkeypatch_state);\n    return *monkeypatch_state;\n  }\n\n  void at_preload_init(Task* t);\n\n  /* The address of the syscall instruction from which traced syscalls made by\n   * the syscallbuf will originate. */\n  remote_code_ptr traced_syscall_ip() const { return traced_syscall_ip_; }\n  /* The address of the syscall instruction from which privileged traced\n   * syscalls made by the syscallbuf will originate. */\n  remote_code_ptr privileged_traced_syscall_ip() const {\n    return privileged_traced_syscall_ip_;\n  }\n\n  bool syscallbuf_enabled() const { return syscallbuf_enabled_; }\n  bool layout_randomization_disabled() const {\n    return layout_randomization_disabled_;\n  }\n  void disable_layout_randomization(bool disable) {\n    layout_randomization_disabled_ = disable;\n  }\n\n  /**\n   * We'll map a page of memory here into every exec'ed process for our own\n   * use.\n   */\n  static remote_ptr<void> rr_page_start() { return RR_PAGE_ADDR; }\n  static remote_ptr<void> rr_page_end() {\n    return rr_page_start() + PRELOAD_LIBRARY_PAGE_SIZE;\n  }\n\n  static remote_ptr<void> preload_thread_locals_start() {\n    return rr_page_start() + PRELOAD_LIBRARY_PAGE_SIZE;\n  }\n  static uint32_t preload_thread_locals_size() {\n    return PRELOAD_THREAD_LOCALS_SIZE;\n  }\n\n  enum Traced { TRACED, UNTRACED };\n  enum Privileged { PRIVILEGED, UNPRIVILEGED };\n  /**\n   * Depending on which entry point this is and whether or not we're recording\n   * or replaying, the instruction in the rr page, may be something other than\n   * a syscall. This enum encodes the combination of instructions for each entry\n   * point:\n   *\n   *      Enabled         | Record  | Replay\n   * ---------------------|---------|-------\n   * RECORDING_ONLY       | syscall | nop\n   * REPLAY_ONLY          | nop     | syscall\n   * RECORDING_AND_REPLAY | syscall | syscall\n   * REPLAY_ASSIST        | syscall | int3\n   *\n   * The REPLAY_ASSIST is used for a syscall that is untraced during record (so\n   * we can save the context switch penalty), but requires us to apply side\n   * effects during replay. The int3 lets the replayer stop and apply these\n   * at the appropriate point.\n   */\n  enum Enabled { RECORDING_ONLY, REPLAY_ONLY, RECORDING_AND_REPLAY, REPLAY_ASSIST };\n  static remote_code_ptr rr_page_syscall_exit_point(Traced traced,\n                                                    Privileged privileged,\n                                                    Enabled enabled,\n                                                    SupportedArch arch);\n  static remote_code_ptr rr_page_syscall_entry_point(Traced traced,\n                                                     Privileged privileged,\n                                                     Enabled enabled,\n                                                     SupportedArch arch);\n\n  struct SyscallType {\n    Traced traced;\n    Privileged privileged;\n    Enabled enabled;\n  };\n  static std::vector<SyscallType> rr_page_syscalls();\n  static const SyscallType* rr_page_syscall_from_exit_point(\n    SupportedArch arch, remote_code_ptr ip);\n  static const SyscallType* rr_page_syscall_from_entry_point(\n    SupportedArch arch, remote_code_ptr ip);\n\n  /**\n   * Return a pointer to 8 bytes of 0xFF.\n   * (Currently only set during record / not part of the ABI)\n   */\n  static remote_ptr<uint8_t> rr_page_record_ff_bytes() { return RR_PAGE_FF_BYTES; }\n\n  /**\n   * Locate a syscall instruction in t's VDSO (the real one, not our fake one).\n   * This gives us a way to execute remote syscalls without having to write\n   * a syscall instruction into executable tracee memory (which might not be\n   * possible with some kernels, e.g. PaX).\n   */\n  remote_code_ptr find_syscall_instruction_in_vdso(Task* t);\n\n  /**\n   * Task |t| just forked from this address space. Apply dont_fork and\n   * wipe_on_fork settings.\n   */\n  void did_fork_into(Task* t);\n\n  void set_first_run_event(FrameTime event) { first_run_event_ = event; }\n  FrameTime first_run_event() { return first_run_event_; }\n\n  const std::vector<uint8_t>& saved_auxv() { return saved_auxv_; }\n  void save_auxv(Task* t);\n\n  remote_ptr<void> saved_interpreter_base() { return saved_interpreter_base_; }\n  void save_interpreter_base(Task* t, std::vector<uint8_t> auxv);\n\n  std::string saved_ld_path() { return saved_ld_path_;}\n  void save_ld_path(Task* t, remote_ptr<void>);\n\n  void read_mm_map(Task* t, NativeArch::prctl_mm_map* map);\n\n  /**\n   * Reads the /proc/<pid>/maps entry for a specific address. Does no caching.\n   * If performed on a file in a btrfs file system, this may return the\n   * wrong device number! If you stick to anonymous or special file\n   * mappings, this should be OK.\n   */\n  KernelMapping read_kernel_mapping(Task* t, remote_ptr<void> addr);\n\n  /**\n   * Same as read_kernel_mapping, but reads rr's own memory map.\n   */\n  static KernelMapping read_local_kernel_mapping(uint8_t* addr);\n\n  static uint32_t chaos_mode_min_stack_size() { return 8 * 1024 * 1024; }\n\n  /* Returns null if we should return ENOMEM because there is no free space available. */\n  remote_ptr<void> chaos_mode_find_free_memory(RecordTask* t, size_t len, remote_ptr<void> hint);\n  enum class FindFreeMemoryPolicy {\n    /* Use the first free memory after `after` */\n    STRICT_SEARCH,\n    /* Optimize for speed by starting the search from the address of the last\n       area returned by find_free_memory (if greater than `after`). */\n    USE_LAST_FREE_HINT,\n  };\n  remote_ptr<void> find_free_memory(Task* t,\n      size_t len, remote_ptr<void> after = remote_ptr<void>(),\n      FindFreeMemoryPolicy policy = FindFreeMemoryPolicy::STRICT_SEARCH);\n\n  /**\n   * The return value indicates whether we (re)created the preload_thread_locals\n   * area.\n   */\n  bool post_vm_clone(Task* t);\n  /**\n   * TaskUid for the task whose locals are stored in the preload_thread_locals\n   * area.\n   */\n  const TaskUid& thread_locals_tuid() { return thread_locals_tuid_; }\n  void set_thread_locals_tuid(const TaskUid& tuid) {\n    thread_locals_tuid_ = tuid;\n  }\n\n  /**\n   * Call this when the memory at [addr,addr+len) was externally overwritten.\n   * This will attempt to update any breakpoints that may be set within the\n   * range (resetting them and storing the new value).\n   */\n  void maybe_update_breakpoints(Task* t, remote_ptr<uint8_t> addr, size_t len);\n\n  /**\n   * Call this to ensure that the mappings in `range` during replay has the same length\n   * is collapsed to a single mapping. The caller guarantees that all the\n   * mappings in the range can be coalesced (because they corresponded to a single\n   * mapping during recording).\n   * The end of the range might be in the middle of a mapping.\n   * The start of the range might also be in the middle of a mapping.\n   */\n  void ensure_replay_matches_single_recorded_mapping(Task* t, MemoryRange range);\n\n  /**\n   * Print process maps.\n   */\n  static void print_process_maps(Task* t);\n\n  void add_stap_semaphore_range(Task* t, MemoryRange range);\n  void remove_stap_semaphore_range(Task* t, MemoryRange range);\n  bool is_stap_semaphore(remote_ptr<uint16_t> addr);\n\n  bool legacy_breakpoint_mode() { return stopping_breakpoint_table_ != nullptr; }\n  remote_code_ptr do_breakpoint_fault_addr() { return do_breakpoint_fault_addr_; }\n  remote_code_ptr stopping_breakpoint_table() { return stopping_breakpoint_table_; }\n  int stopping_breakpoint_table_entry_size() { return stopping_breakpoint_table_entry_size_; }\n\n  // Also sets brk_ptr.\n  enum {\n    RRVDSO_PAGE_OFFSET = 2,\n    RRPAGE_RECORD_PAGE_OFFSET = 3,\n    RRPAGE_REPLAY_PAGE_OFFSET = 4\n  };\n\n  void map_rr_page(AutoRemoteSyscalls& remote);\n  static std::vector<uint8_t> read_rr_page_for_recording(SupportedArch arch);\n  struct UnmapOptions {\n    bool exclude_vdso_vvar;\n    UnmapOptions() : exclude_vdso_vvar(false) {}\n  };\n  void unmap_all_but_rr_mappings(AutoRemoteSyscalls& remote,\n                                 UnmapOptions options = UnmapOptions());\n\n  void erase_task(Task* t) {\n    this->HasTaskSet::erase_task(t);\n    if (task_set().size() != 0) {\n      fd_tables_changed();\n    }\n  }\n\n  /**\n   * Called when the set of different fd tables associated with tasks\n   * in this address space may have changed (e.g. a task changed its fd table,\n   * or a task got added or removed, etc).\n   */\n  void fd_tables_changed();\n\n  static MemoryRange get_global_exclusion_range(const RecordSession* session);\n\n  // Whether to return WatchConfigs consisting of only aligned locations\n  // suitable for hardware watchpoint registers.\n  enum WatchpointAlignment { UNALIGNED, ALIGNED };\n\n  // Returns true if the range is completely covered by private mappings\n  bool range_is_private_mapping(const MemoryRange& range) const;\n\n  /**\n   * When two processes share an address space (e.g. with vfork(2) or\n   * clone(2) CLONE_VM), and one process calls execve(2), we need to unmap\n   * that process's syscallbuf. This list is checked the next time a task\n   * in that address space runs to perform the unmapping\n   */\n  std::vector<MemoryRange> regions_pending_unmap;\n\nprivate:\n  struct Breakpoint;\n  typedef std::map<remote_code_ptr, Breakpoint> BreakpointMap;\n  class Watchpoint;\n\n  /**\n   * Called after a successful execve to set up the new AddressSpace.\n   * Also called once for the initial spawn.\n   */\n  AddressSpace(Task* t, const std::string& exe, uint32_t exec_count);\n  /**\n   * Called when an AddressSpace is cloned due to a fork() or a Session\n   * clone. After this, and the task is properly set up, post_vm_clone will\n   * be called.\n   */\n  AddressSpace(Session* session, const AddressSpace& o, pid_t leader_tid,\n               uint32_t leader_serial, uint32_t exec_count);\n\n  /**\n   * After an exec, populate the new address space of |t| with\n   * the existing mappings we find in /proc/maps.\n   */\n  void populate_address_space(Task* t);\n\n  void unmap_internal(Task* t, remote_ptr<void> addr, ssize_t num_bytes);\n  void update_syscall_ips(Task* t);\n\n  bool update_watchpoint_value(const MemoryRange& range,\n                               Watchpoint& watchpoint);\n  void update_watchpoint_values(remote_ptr<void> start, remote_ptr<void> end);\n  // Whether to handle all watchpoints or just data watchpoints whose data\n  // has changed. In the latter case we clear their changed status.\n  enum WatchpointFilter { ALL_WATCHPOINTS, CHANGED_WATCHPOINTS };\n  // Whether to update the watchpoint's assigned register list. Use\n  // UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS when we'll use the watchpoints\n  // to configure HW watchpoint registers.\n  enum UpdateWatchpointRegisterAssignments { UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS,\n      DONT_UPDATE_WATCHPOINT_REGISTER_ASSIGNMENTS };\n  std::vector<WatchConfig> get_watchpoints_internal(WatchpointFilter filter,\n        WatchpointAlignment alignment,\n        UpdateWatchpointRegisterAssignments update_watchpoint_register_assignments);\n\n  /**\n   * Construct a minimal set of watchpoints to be enabled based\n   * on |set_watchpoint()| calls, and program them for each task\n   * in this address space.\n   */\n  bool allocate_watchpoints();\n\n  /**\n   * Merge the mappings adjacent to |it| in memory that are\n   * semantically \"adjacent mappings\" of the same resource as\n   * well, for example have adjacent file offsets and the same\n   * prot and flags.\n   */\n  void coalesce_around(Task* t, MemoryMap::iterator it);\n\n  /**\n   * Erase |it| from |breakpoints| and restore any memory in\n   * this it may have overwritten.\n   */\n  void destroy_breakpoint(BreakpointMap::const_iterator it);\n\n  /**\n   * For each mapped segment overlapping [addr, addr +\n   * num_bytes), call |f|.  Pass |f| the overlapping mapping,\n   * the mapped resource, and the range of addresses remaining\n   * to be iterated over.\n   *\n   * Pass |ITERATE_CONTIGUOUS| to stop iterating when the last\n   * contiguous mapping after |addr| within the region is seen.\n   * Default is to iterate all mappings in the region.\n   *\n   * The callback takes parameters by value to avoid dangling\n   * references if the memory map is modified inside the callback.\n   */\n  enum { ITERATE_DEFAULT, ITERATE_CONTIGUOUS };\n  void for_each_in_range(\n      remote_ptr<void> addr, ssize_t num_bytes,\n      std::function<void(Mapping m, MemoryRange rem)> f,\n      int how = ITERATE_DEFAULT);\n\n  /**\n   * Map |m| of |r| into this address space, and coalesce any\n   * mappings of |r| that are adjacent to |m|.\n   */\n  void map_and_coalesce(Task* t, const KernelMapping& m,\n                        const KernelMapping& recorded_map,\n                        EmuFile::shr_ptr emu_file,\n                        std::unique_ptr<struct stat> mapped_file_stat,\n                        void* local_addr,\n                        std::shared_ptr<MonitoredSharedMemory> monitored);\n\n  void remove_from_map(const MemoryRange& range) {\n    mem.erase(range);\n    monitored_mem.erase(range.start());\n  }\n  void add_to_map(const Mapping& m) {\n    mem[m.map] = m;\n    if (m.monitored_shared_memory) {\n      monitored_mem.insert(m.map.start());\n    }\n  }\n\n  /**\n   * Call this only during recording.\n   */\n  template <typename Arch> void at_preload_init_arch(Task* t);\n\n  enum { EXEC_BIT = 1 << 0, READ_BIT = 1 << 1, WRITE_BIT = 1 << 2 };\n\n  /** Return the access bits above needed to watch |type|. */\n  static int access_bits_of(WatchType type);\n\n  /**\n   * Represents a refcount set on a particular address.  Because there\n   * can be multiple refcounts of multiple types set on a single\n   * address, Breakpoint stores explicit USER and INTERNAL breakpoint\n   * refcounts.  Clients adding/removing breakpoints at this addr must\n   * call ref()/unref() as appropriate.\n   */\n  struct Breakpoint {\n    Breakpoint() : internal_count(0), user_count(0) {}\n    Breakpoint(const Breakpoint& o) = default;\n    // AddressSpace::destroy_all_breakpoints() can cause this\n    // destructor to be invoked while we have nonzero total\n    // refcount, so the most we can DEBUG_ASSERT is that the refcounts\n    // are valid.\n    ~Breakpoint() { DEBUG_ASSERT(internal_count >= 0 && user_count >= 0); }\n\n    void ref(BreakpointType which) {\n      DEBUG_ASSERT(internal_count >= 0 && user_count >= 0);\n      ++*counter(which);\n    }\n    int unref(BreakpointType which) {\n      DEBUG_ASSERT(internal_count > 0 || user_count > 0);\n      --*counter(which);\n      DEBUG_ASSERT(internal_count >= 0 && user_count >= 0);\n      return internal_count + user_count;\n    }\n\n    BreakpointType type() const {\n      // NB: USER breakpoints need to be processed before\n      // INTERNAL ones.  We want to give the debugger a\n      // chance to dispatch commands before we attend to the\n      // internal rr business.  So if there's a USER \"ref\"\n      // on the breakpoint, treat it as a USER breakpoint.\n      return user_count > 0 ? BKPT_USER : BKPT_INTERNAL;\n    }\n\n    uint8_t* original_data() { return overwritten_data; }\n\n    // \"Refcounts\" of breakpoints set at |addr|.  The breakpoint\n    // object must be unique since we have to save the overwritten\n    // data, and we can't enforce the order in which breakpoints\n    // are set/removed.\n    int internal_count, user_count;\n    uint8_t overwritten_data[MAX_BKPT_INSTRUCTION_LENGTH];\n\n    int* counter(BreakpointType which) {\n      DEBUG_ASSERT(BKPT_INTERNAL == which || BKPT_USER == which);\n      int* p = BKPT_USER == which ? &user_count : &internal_count;\n      DEBUG_ASSERT(*p >= 0);\n      return p;\n    }\n  };\n\n  // XXX one is tempted to merge Breakpoint and Watchpoint into a single\n  // entity, but the semantics are just different enough that separate\n  // objects are easier for now.\n  /**\n   * Track the watched accesses of a contiguous range of memory\n   * addresses.\n   */\n  class Watchpoint {\n  public:\n    Watchpoint(size_t num_bytes)\n        : exec_count(0),\n          read_count(0),\n          write_count(0),\n          value_bytes(num_bytes),\n          valid(false),\n          changed(false) {}\n    Watchpoint(const Watchpoint&) = default;\n    ~Watchpoint() { assert_valid(); }\n\n    void watch(int which) {\n      assert_valid();\n      exec_count += (EXEC_BIT & which) != 0;\n      read_count += (READ_BIT & which) != 0;\n      write_count += (WRITE_BIT & which) != 0;\n    }\n    int unwatch(int which) {\n      assert_valid();\n      if (EXEC_BIT & which) {\n        DEBUG_ASSERT(exec_count > 0);\n        --exec_count;\n      }\n      if (READ_BIT & which) {\n        DEBUG_ASSERT(read_count > 0);\n        --read_count;\n      }\n      if (WRITE_BIT & which) {\n        DEBUG_ASSERT(write_count > 0);\n        --write_count;\n      }\n      return exec_count + read_count + write_count;\n    }\n\n    int watched_bits() const {\n      return (exec_count > 0 ? EXEC_BIT : 0) | (read_count > 0 ? READ_BIT : 0) |\n             (write_count > 0 ? WRITE_BIT : 0);\n    }\n\n    void assert_valid() const {\n      DEBUG_ASSERT(exec_count >= 0 && read_count >= 0 && write_count >= 0);\n    }\n\n    // Watchpoints stay alive until all watched access typed have\n    // been cleared.  We track refcounts of each watchable access\n    // separately.\n    int exec_count, read_count, write_count;\n    // Debug registers allocated for read/exec access checking.\n    // Write watchpoints are always triggered by checking for actual memory\n    // value changes. Read/exec watchpoints can't be triggered that way, so\n    // we look for these registers being triggered instead.\n    std::vector<int8_t> debug_regs_for_exec_read;\n    std::vector<uint8_t> value_bytes;\n    bool valid;\n    bool changed;\n  };\n\n  // All breakpoints set in this VM.\n  BreakpointMap breakpoints;\n  /* Path of the real executable image this address space was\n   * exec()'d with. */\n  std::string exe;\n  /* Path of the interpreter, if any, of exe. */\n  std::string interp_name_;\n  /* Base address of the interpreter (might be null!) */\n  remote_ptr<void> interp_base_;\n  /* Pid of first task for this address space */\n  pid_t leader_tid_;\n  /* Serial number of first task for this address space */\n  uint32_t leader_serial;\n  uint32_t exec_count;\n  // Only valid during recording\n  remote_ptr<void> brk_start;\n  /* Current brk. Not necessarily page-aligned. */\n  remote_ptr<void> brk_end;\n  /* All segments mapped into this address space. */\n  MemoryMap mem;\n  /* Sizes of SYSV shm segments, by address. We use this to determine the size\n   * of memory regions unmapped via shmdt(). */\n  std::map<remote_ptr<void>, size_t> shm_sizes;\n  std::set<remote_ptr<void>> monitored_mem;\n  /* madvise DONTFORK regions */\n  std::set<MemoryRange> dont_fork;\n  /* madvise WIPEONFORK regions */\n  std::set<MemoryRange> wipe_on_fork;\n  // The session that created this.  We save a ref to it so that\n  // we can notify it when we die.\n  Session* session_;\n  // tid of the task whose thread-locals are in preload_thread_locals\n  TaskUid thread_locals_tuid_;\n  /* First mapped byte of the vdso. */\n  remote_ptr<void> vdso_start_addr;\n  // The monkeypatcher that's handling this address space.\n  std::unique_ptr<Monkeypatcher> monkeypatch_state;\n  // The watchpoints set for tasks in this VM.  Watchpoints are\n  // programmed per Task, but we track them per address space on\n  // behalf of debuggers that assume that model.\n  std::map<MemoryRange, Watchpoint> watchpoints;\n  std::vector<std::map<MemoryRange, Watchpoint>> saved_watchpoints;\n  // Tracee memory is read and written through this fd, which is\n  // opened for the tracee's magic /proc/[tid]/mem device.  The\n  // advantage of this over ptrace is that we can access it even\n  // when the tracee isn't at a ptrace-stop.  It's also\n  // theoretically faster for large data transfers, which rr can\n  // do often.\n  //\n  // Users of child_mem_fd should fall back to ptrace-based memory\n  // access when child_mem_fd is not open.\n  ScopedFd child_mem_fd;\n  remote_code_ptr traced_syscall_ip_;\n  remote_code_ptr privileged_traced_syscall_ip_;\n  bool syscallbuf_enabled_;\n  bool layout_randomization_disabled_;\n\n  remote_code_ptr do_breakpoint_fault_addr_;\n  // These fields are deprecated and have been replaced by the\n  // breakpoint_value mechanism. They are retained for replayability\n  // of old traces.\n  remote_code_ptr stopping_breakpoint_table_;\n  int stopping_breakpoint_table_entry_size_;\n\n  std::vector<uint8_t> saved_auxv_;\n  remote_ptr<void> saved_interpreter_base_;\n  std::string saved_ld_path_;\n\n  remote_ptr<void> last_free_memory;\n\n  /**\n   * The time of the first event that ran code for a task in this address space.\n   * 0 if no such event has occurred.\n   */\n  FrameTime first_run_event_;\n\n  std::set<remote_ptr<uint16_t>> stap_semaphores;\n\n  /**\n   * For each architecture, the offset of a syscall instruction with that\n   * architecture's VDSO, or 0 if not known.\n   */\n  static uint32_t offset_to_syscall_in_vdso[SupportedArch_MAX + 1];\n\n  /**\n   * Ensure that the cached mapping of |t| matches /proc/maps,\n   * using adjacent-map-merging heuristics that are as lenient\n   * as possible given the data available from /proc/maps.\n   */\n  static void check_segment_iterator(void* vasp, Task* t,\n                                     const struct map_iterator_data* data);\n\n  AddressSpace operator=(const AddressSpace&) = delete;\n\n  ScopedFd child_pagemap_fd;\n};\n\n/**\n * The following helper is used to iterate over a tracee's memory\n * map.\n */\nclass KernelMapIterator {\npublic:\n  KernelMapIterator(Task* t, bool* ok = nullptr);\n  KernelMapIterator(pid_t tid, bool* ok = nullptr) : tid(tid) { init(ok); }\n  ~KernelMapIterator();\n\n  // It's very important to keep in mind that btrfs files can have the wrong\n  // device number!\n  const KernelMapping& current(std::string* raw_line = nullptr) {\n    if (raw_line) {\n      *raw_line = this->raw_line;\n    }\n    return km;\n  }\n  bool at_end() { return !maps_file; }\n  void operator++();\n\nprivate:\n  void init(bool* ok = nullptr);\n\n  pid_t tid;\n  FILE* maps_file;\n  std::string raw_line;\n  KernelMapping km;\n};\n\n} // namespace rr\n\n#endif /* RR_ADDRESS_SPACE_H_ */\n"
  },
  {
    "path": "src/AutoRemoteSyscalls.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"AutoRemoteSyscalls.h\"\n\n#include <limits.h>\n#include <linux/net.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n\n#include <sstream>\n\n#include \"rr/rr.h\"\n\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"ReplaySession.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"record_signal.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n/**\n * The ABI of the socketcall syscall is a nightmare; the first arg to\n * the kernel is the sub-operation, and the second argument is a\n * pointer to the args.  The args depend on the sub-op.\n */\ntemplate <typename Arch> struct socketcall_args {\n  typename Arch::signed_long args[3];\n} __attribute__((packed));\n\nvoid AutoRestoreMem::init(const void* mem, ssize_t num_bytes) {\n  ASSERT(remote.task(),\n         remote.enable_mem_params() == AutoRemoteSyscalls::ENABLE_MEMORY_PARAMS)\n      << \"Memory parameters were disabled\";\n\n  len = num_bytes;\n  saved_sp = remote.regs().sp();\n\n  remote.regs().set_sp(remote.regs().sp() - len);\n  remote.task()->set_regs(remote.regs());\n  if (remote.task()->is_exiting()) {\n    // Leave addr == nullptr\n    return;\n  }\n\n  addr = remote.regs().sp();\n\n  data.resize(len);\n  bool ok = true;\n  remote.task()->read_bytes_helper(addr, len, data.data(), &ok);\n  if (mem) {\n    remote.task()->write_bytes_helper(addr, len, mem, &ok);\n  }\n  if (!ok) {\n    addr = nullptr;\n  }\n}\n\nAutoRestoreMem::~AutoRestoreMem() {\n  DEBUG_ASSERT(saved_sp == remote.regs().sp() + len);\n\n  if (addr) {\n    // XXX what should we do if this task was sigkilled but the address\n    // space is used by other live tasks?\n    remote.task()->write_bytes_helper(addr, len, data.data());\n  }\n  remote.regs().set_sp(remote.regs().sp() + len);\n  remote.task()->set_regs(remote.regs());\n}\n\nstatic bool is_SIGTRAP_default_and_unblocked(Task* t) {\n  if (!t->session().is_recording()) {\n    return true;\n  }\n  RecordTask* rt = static_cast<RecordTask*>(t);\n  return rt->sig_disposition(SIGTRAP) == SIGNAL_DEFAULT &&\n         !rt->is_sig_blocked(SIGTRAP);\n}\n\nAutoRemoteSyscalls::AutoRemoteSyscalls(Task* t,\n                                       MemParamsEnabled enable_mem_params)\n    : t(t),\n      initial_regs(t->regs()),\n      initial_ip(t->ip()),\n      initial_sp(t->regs().sp()),\n      initial_at_seccomp(t->ptrace_event() == PTRACE_EVENT_SECCOMP),\n      restore_wait_status(t->status()),\n      new_tid_(-1),\n      scratch_mem_was_mapped(false),\n      use_singlestep_path(false),\n      enable_mem_params_(enable_mem_params),\n      restore_sigmask(false),\n      need_sigpending_renable(false),\n      need_desched_event_reenable(false) {\n  if (initial_at_seccomp) {\n    // This should only ever happen during recording - we don't use the\n    // seccomp traps during replay.\n    ASSERT(t, t->session().is_recording());\n  }\n  // We support two paths for syscalls:\n  // -- a fast path using a privileged untraced syscall and PTRACE_SINGLESTEP.\n  // This only requires a single task-wait.\n  // -- a slower path using a privileged traced syscall and PTRACE_SYSCALL/\n  // PTRACE_CONT via Task::enter_syscall(). This requires 2 or 3 task-waits\n  // depending on whether the seccomp event fires before the syscall-entry\n  // event.\n  // Use the slow path when running under rr, because the rr recording us\n  // needs to see and trace these tracee syscalls, and if they're untraced by\n  // us they're also untraced by the outer rr.\n  // Use the slow path if SIGTRAP is blocked or ignored because otherwise\n  // the PTRACE_SINGLESTEP will cause the kernel to unblock it.\n  setup_path(t->vm()->has_rr_page() && !running_under_rr() &&\n             is_SIGTRAP_default_and_unblocked(t));\n  if (enable_mem_params == ENABLE_MEMORY_PARAMS) {\n    maybe_fix_stack_pointer();\n  }\n  if (t->status().is_syscall() && t->regs().syscall_may_restart()) {\n    // VERY rare corner case alert: It is possible for the following sequence\n    // of events to occur:\n    //\n    // 1. Thread A is in a blocking may-restart syscall and gets interrupted by a tg-targeted signal\n    // 2. Thread B dequeues the signal\n    // 3. Thread A is in the syscall-exit-stop with TIF_SIGPENDING set (with registers indicating syscall restart)\n    // 4. We get here to perform an AutoRemoteSyscall\n    // 5. During AutoRemoteSyscall, TIF_SIGPENDING gets cleared on return to userspace\n    // 6. We finish the AutoRemoteSyscall and re-apply the registers.\n    // 7. ... As a result, the kernel does not check whether it needs to perform the\n    ///   syscall-restart register adjustment because TIF_SIGPENDING is not set.\n    // 8. The -ERESTART error code leaks to userspace.\n    //\n    // Arguably this is a kernel bug, but it's not clear how the behavior should be changed.\n    //\n    // To work around this, we forcibly re-enable TIF_SIGPENDING when cleaning up\n    // AutoRemoteSyscall (see below).\n    need_sigpending_renable = true;\n  }\n  if (t->session().is_recording()) {\n    RecordTask *rt = static_cast<RecordTask*>(t);\n    sig_set_t signals_to_block = 0;\n\n    if (rt->schedule_frozen) {\n      // If we're explicitly controlling the schedule, make sure not to accidentally run\n      // any signals that we were not meant to be able to see.\n      memset(&signals_to_block, 0xff, sizeof(sig_set_t));\n    }\n    if (desched_event_armed(rt)) {\n      // If the desched event is enabled, we need to disable it, so that we don't get\n      // the desched signal interrupting the syscall we're trying to make. We also\n      // need to mask it, so that if there's a pending desched signal from before\n      // we disable it, we don't accidently steal it.\n      signals_to_block |= signal_bit(rt->session().syscallbuf_desched_sig());\n      need_desched_event_reenable = true;\n      disarm_desched_event(rt);\n    }\n\n    if (signals_to_block) {\n      restore_sigmask = true;\n      sigmask_to_restore = rt->get_sigmask();\n      // Ignore the process dying here - we'll notice later.\n      (void)rt->set_sigmask(signals_to_block | sigmask_to_restore);\n    }\n  }\n}\n\nvoid AutoRemoteSyscalls::setup_path(bool enable_singlestep_path) {\n#if defined(__aarch64__)\n  // XXXkhuey this fast path doesn't work on AArch64 yet, go slow instead\n  enable_singlestep_path = false;\n#endif\n\n  if (!replaced_bytes.empty()) {\n    // XXX what to do here to clean up if the task died unexpectedly?\n    t->write_mem(remote_ptr<uint8_t>(initial_regs.ip().to_data_ptr<uint8_t>()),\n                 replaced_bytes.data(), replaced_bytes.size());\n  }\n\n  remote_code_ptr syscall_ip;\n  use_singlestep_path = enable_singlestep_path;\n  if (use_singlestep_path) {\n    syscall_ip = AddressSpace::rr_page_syscall_entry_point(\n        AddressSpace::UNTRACED, AddressSpace::PRIVILEGED,\n        AddressSpace::RECORDING_AND_REPLAY, t->arch());\n  } else {\n    syscall_ip = t->vm()->traced_syscall_ip();\n  }\n  initial_regs.set_ip(syscall_ip);\n\n  // We need to make sure to clear any breakpoints or other alterations of\n  // the syscall instruction we're using. Note that the tracee may have set its\n  // own breakpoints or otherwise modified the instruction, so suspending our\n  // own breakpoint is insufficient.\n  std::vector<uint8_t> syscall = rr::syscall_instruction(t->arch());\n  bool ok = true;\n  replaced_bytes =\n      t->read_mem(initial_regs.ip().to_data_ptr<uint8_t>(), syscall.size(), &ok);\n  if (!ok) {\n    // The task died\n    return;\n  }\n  if (replaced_bytes == syscall) {\n    replaced_bytes.clear();\n  } else {\n    t->write_mem(initial_regs.ip().to_data_ptr<uint8_t>(), syscall.data(),\n                 syscall.size(), &ok);\n  }\n}\n\nstatic bool is_usable_area(const KernelMapping& km) {\n  return (km.prot() & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE) &&\n         (km.flags() & MAP_PRIVATE);\n}\n\nvoid AutoRemoteSyscalls::maybe_fix_stack_pointer() {\n  if (!t->session().done_initial_exec()) {\n    return;\n  }\n\n  remote_ptr<void> last_stack_byte = t->regs().sp() - 1;\n  if (t->vm()->has_mapping(last_stack_byte)) {\n    auto m = t->vm()->mapping_of(last_stack_byte);\n    if (is_usable_area(m.map) && m.map.start() + 2048 <= t->regs().sp()) {\n      // 'sp' is in a stack region and there's plenty of space there. No need\n      // to fix anything.\n      return;\n    }\n  }\n\n  MemoryRange found_stack;\n  for (const auto& m : t->vm()->maps()) {\n    if (is_usable_area(m.map)) {\n      found_stack = m.map;\n      break;\n    }\n  };\n\n  if (found_stack.start().is_null()) {\n    AutoRemoteSyscalls remote(t, DISABLE_MEMORY_PARAMS);\n    found_stack =\n        MemoryRange(remote.infallible_mmap_syscall_if_alive(\n                        remote_ptr<void>(), 4096, PROT_READ | PROT_WRITE,\n                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0),\n                    4096);\n    ASSERT(t, !found_stack.start().is_null())\n      << \"Tracee unexpectedly died here\";\n    scratch_mem_was_mapped = true;\n  }\n\n  fixed_sp = found_stack.end();\n  DEBUG_ASSERT(!fixed_sp.is_null());\n  initial_regs.set_sp(fixed_sp);\n}\n\nAutoRemoteSyscalls::~AutoRemoteSyscalls() { restore_state_to(t); }\n\nvoid AutoRemoteSyscalls::restore_state_to(Task* t) {\n  // Check if the task was unexpectedly killed via SIGKILL or equivalent.\n  bool is_exiting = !t->is_stopped() || t->ptrace_event() == PTRACE_EVENT_EXIT ||\n    t->was_reaped();\n\n  // Unmap our scatch region if required\n  if (scratch_mem_was_mapped && !is_exiting) {\n    AutoRemoteSyscalls remote(t, DISABLE_MEMORY_PARAMS);\n    remote.infallible_syscall(syscall_number_for_munmap(arch()),\n                              fixed_sp - 4096, 4096);\n  }\n  if (!replaced_bytes.empty()) {\n    // XXX how to clean up if the task died and the address space is shared with live task?\n    t->write_mem(remote_ptr<uint8_t>(initial_regs.ip().to_data_ptr<uint8_t>()),\n                 replaced_bytes.data(), replaced_bytes.size());\n  }\n  auto regs = initial_regs;\n  regs.set_ip(initial_ip);\n  regs.set_sp(initial_sp);\n  if (is_exiting) {\n    // Don't restore status; callers need to see the task is exiting.\n    // And the other stuff we don't below won't work.\n    // But do restore registers so it looks like the exit happened in a clean state.\n    t->set_regs(regs);\n    return;\n  }\n\n  if (t->arch() == aarch64 && regs.syscall_may_restart()) {\n    // On AArch64, the kernel restarts aborted syscalls using an internal `orig_x0`.\n    // This gets overwritten everytime we make a syscall so we need to restore it\n    // if we are at a syscall that may restart.\n    // The kernel `orig_x0` isn't accessible from ptrace AFAICT but fortunately\n    // it does **NOT** get reset on syscall exit so we can actually set it's value\n    // just by making a dummy syscall with the correct x0 value.\n    auto restart_res = regs.syscall_result();\n    regs.set_ip(t->vm()->traced_syscall_ip());\n    // This can be any side-effect-free syscall that doesn't care about arg1.\n    // The kernel sets its `orig_x0` no matter whether the syscall actually needs it.\n    regs.set_syscallno(rr::ARM64Arch::getpid);\n    regs.set_arg1(regs.orig_arg1());\n    t->set_regs(regs);\n    if (t->enter_syscall(aarch64, true)) {\n      if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        // Tracee died unexpectedly, there is nothing more we can do.\n        // Do not restore the status, we want callers to see that the task died.\n        return;\n      }\n    }\n    regs.set_ip(initial_ip);\n    regs.set_syscallno(regs.original_syscallno());\n    regs.set_syscall_result(restart_res);\n  }\n  // If we were sitting at a seccomp trap, try to get back there by resuming\n  // here. Since the original register contents caused a seccomp trap,\n  // re-running the syscall with the same registers should put us right back\n  // to this same seccomp trap.\n  if (initial_at_seccomp && t->ptrace_event() != PTRACE_EVENT_SECCOMP) {\n    regs.set_ip(initial_ip.decrement_by_syscall_insn_length(t->arch()));\n    regs.set_syscallno(regs.original_syscallno());\n    t->set_regs(regs);\n    RecordTask* rt = static_cast<RecordTask*>(t);\n    while (true) {\n      if (!rt->resume_execution(RESUME_CONT, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        // Tracee died unexpectedly, there is nothing more we can do.\n        // Do not restore the status, we want callers to see that the task died.\n        return;\n      }\n      if (rt->ptrace_event())\n        break;\n      rt->stash_sig();\n    }\n    ASSERT(rt, rt->ptrace_event() == PTRACE_EVENT_SECCOMP);\n  } else {\n    // Restore stomped registers.\n    t->set_regs(regs);\n  }\n  t->set_status(restore_wait_status);\n  if (restore_sigmask) {\n    static_cast<RecordTask*>(t)->set_sigmask(sigmask_to_restore);\n  }\n  if (need_desched_event_reenable) {\n    arm_desched_event(static_cast<RecordTask*>(t));\n  }\n  if (need_sigpending_renable) {\n    // The purpose of this PTRACE_INTERRUPT is to re-enable TIF_SIGPENDING on\n    // the tracee, without forcing any actual signals on it. Since PTRACE_INTERRUPT\n    // needs to be able to interrupt re-startable system calls, it is required\n    // to set TIF_SIGPENDING, but the fact that this works is of course a very\n    // deep implementation detail.\n    // If this fails then the tracee must be dead or no longer traced, in which\n    // case we no longer care about its TIF_SIGPENDING status.\n    t->do_ptrace_interrupt();\n  }\n}\n\nstatic bool ignore_signal(Task* t) {\n  int sig = t->stop_sig();\n  if (!sig) {\n    return false;\n  }\n  if (t->session().is_replaying()) {\n    if (ReplaySession::is_ignored_signal(sig)) {\n      return true;\n    }\n  } else if (t->session().is_recording()) {\n    auto rt = static_cast<RecordTask*>(t);\n    if (sig != rt->session().syscallbuf_desched_sig()) {\n      rt->stash_sig();\n    }\n    return true;\n  }\n  siginfo_t siginfo;\n  errno = 0;\n  t->fallible_ptrace(PTRACE_GETSIGINFO, nullptr, &siginfo);\n  if (errno) {\n    ASSERT(t, false) << \"Unexpected signal \" << signal_name(sig);\n  } else {\n    ASSERT(t, false) << \"Unexpected signal \" << siginfo;\n  }\n  return false;\n}\n\nlong AutoRemoteSyscalls::syscall_base(int syscallno, Registers& callregs) {\n  SupportedArch arch = t->arch();\n  LOG(debug) << \"syscall \" << syscall_name(syscallno, arch) << \" \" << callregs;\n\n  if (t->is_exiting()) {\n    LOG(debug) << \"Task is dying, don't try anything.\";\n    ASSERT(t, t->stopped_or_unexpected_exit()) << \"Already seen exit event\";\n    return -ESRCH;\n  }\n\n  if ((int)callregs.arg1() == SIGTRAP && use_singlestep_path &&\n      (is_sigaction_syscall(syscallno, arch) ||\n       is_rt_sigaction_syscall(syscallno, arch) ||\n       is_signal_syscall(syscallno, arch))) {\n    // Don't use the fast path if we're about to set up a signal handler\n    // for SIGTRAP!\n    LOG(debug) << \"Disabling singlestep path due to SIGTRAP sigaction\";\n    setup_path(false);\n    callregs.set_ip(initial_regs.ip());\n  }\n\n  callregs.set_original_syscallno(syscallno);\n  callregs.set_syscallno(syscallno);\n  t->set_regs(callregs);\n\n  bool from_seccomp = initial_at_seccomp && t->ptrace_event() == PTRACE_EVENT_SECCOMP;\n  if (use_singlestep_path && !from_seccomp) {\n    while (true) {\n      if (!t->resume_execution(RESUME_SINGLESTEP, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        // Tracee was killed, there is nothing more we can do.\n        ASSERT(t, t->stopped_or_unexpected_exit()) << \"Couldn't singlestep\";\n        return -ESRCH;\n      }\n      LOG(debug) << \"Used singlestep path; status=\" << t->status();\n      // When a PTRACE_EVENT_EXIT is returned we don't update registers\n      if (t->ip() != callregs.ip()) {\n        // We entered the syscall, so stop now\n        break;\n      }\n      if (t->stop_sig() == SIGTRAP && t->get_siginfo().si_code == TRAP_TRACE) {\n        // On aarch64, if we were previously in a syscall-exit stop, continuing\n        // with PTRACE_SINGLESTEP will result in incurring a trap upon execution\n        // of the first instruction in userspace. Ignore such a trap.\n        continue;\n      }\n      if (ignore_signal(t)) {\n        // We were interrupted by a signal before we even entered the syscall\n        continue;\n      }\n      ASSERT(t, false) << \"Unexpected status \" << t->status();\n    }\n  } else {\n    if (from_seccomp) {\n      LOG(debug) << \"Skipping enter_syscall - already at seccomp stop\";\n    } else {\n      if (!t->enter_syscall(arch, true)) {\n        // Tracee was killed, there is nothing more we can do.\n        // Ensure callers see the task death status.\n        ASSERT(t, t->stopped_or_unexpected_exit()) << \"couldn't enter syscall\";\n        return -ESRCH;\n      }\n      LOG(debug) << \"Used enter_syscall; status=\" << t->status();\n    }\n    if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n      // Tracee was killed, there is nothing more we can do.\n      // Ensure callers see the task death status.\n      ASSERT(t, t->stopped_or_unexpected_exit()) << \"couldn't resume syscall\";\n      return -ESRCH;\n    }\n    LOG(debug) << \"syscall exit status=\" << t->status();\n  }\n  while (true) {\n    if (t->status().is_syscall() ||\n        (t->stop_sig() == SIGTRAP &&\n         is_kernel_trap(t->get_siginfo().si_code))) {\n      // If we got a SIGTRAP then we assume that's our singlestep and we're\n      // done.\n      break;\n    }\n    if (is_clone_syscall(syscallno, arch) &&\n        t->clone_syscall_is_complete(&new_tid_, arch)) {\n      if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        // Tracee was killed, there is nothing more we can do.\n        ASSERT(t, t->stopped_or_unexpected_exit()) << \"Couldn't resume clone\";\n        return -ESRCH;\n      }\n      LOG(debug) << \"got clone event; new status=\" << t->status();\n      continue;\n    }\n    if (ignore_signal(t)) {\n      if (t->regs().syscall_may_restart()) {\n        if (!t->enter_syscall(arch, true)) {\n          // Tracee was killed, there is nothing more we can do.\n          ASSERT(t, t->stopped_or_unexpected_exit()) << \"Couldn't restart\";\n          return -ESRCH;\n        }\n        LOG(debug) << \"signal ignored; restarting syscall, status=\"\n                   << t->status();\n        if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n          // Tracee was killed, there is nothing more we can do.\n          ASSERT(t, t->stopped_or_unexpected_exit()) << \"Couldn't resume restart\";\n          return -ESRCH;\n        }\n        LOG(debug) << \"syscall exit status=\" << t->status();\n        continue;\n      }\n      LOG(debug) << \"signal ignored\";\n      // We have been notified of a signal after a non-interruptible syscall\n      // completed. Don't continue, we're done here.\n      break;\n    }\n    ASSERT(t, false) << \"Unexpected status \" << t->status();\n    break;\n  }\n\n  LOG(debug) << \"done, result=\" << t->regs().syscall_result();\n  return t->regs().syscall_result();\n}\n\nSupportedArch AutoRemoteSyscalls::arch() const { return t->arch(); }\n\ntemplate <typename Arch>\nstatic void write_socketcall_args(Task* t, remote_ptr<void> remote_mem,\n                                  typename Arch::signed_long arg1,\n                                  typename Arch::signed_long arg2,\n                                  typename Arch::signed_long arg3,\n                                  bool* ok) {\n  socketcall_args<Arch> sc_args = { { arg1, arg2, arg3 } };\n  t->write_mem(remote_mem.cast<socketcall_args<Arch>>(), sc_args, ok);\n}\n\ntemplate <typename Arch>\nstruct fd_message {\n  // Unfortunately we need to send at least one byte of data in our\n  // message for it to work\n  char data;\n  typename Arch::iovec msgdata;\n  char cmsgbuf[Arch::cmsg_space(sizeof(int))];\n  typename Arch::msghdr msg;\n  // XXX: Could make this conditional on Arch\n  socketcall_args<Arch> socketcall;\n  void init(remote_ptr<fd_message<Arch>> base) {\n    data = 0;\n    msgdata.iov_base = REMOTE_PTR_FIELD(base, data);\n    msgdata.iov_len = 1;\n    memset(&msg, 0, sizeof(msg));\n    msg.msg_control = REMOTE_PTR_FIELD(base, cmsgbuf);\n    msg.msg_controllen = sizeof(cmsgbuf);\n    msg.msg_iov = REMOTE_PTR_FIELD(base, msgdata);\n    msg.msg_iovlen = 1;\n  }\n  fd_message(remote_ptr<fd_message<Arch>> base) {\n    init(base);\n  }\n  fd_message() {\n    init((uintptr_t)this);\n  }\n  remote_ptr<fd_message<Arch>> remote_this() {\n    return msgdata.iov_base.rptr().as_int();\n  }\n  remote_ptr<typename Arch::msghdr> remote_msg() {\n    return REMOTE_PTR_FIELD(remote_this(), msg);\n  }\n  remote_ptr<socketcall_args<Arch>> remote_sc_args() {\n    return REMOTE_PTR_FIELD(remote_this(), socketcall);\n  }\n  remote_ptr<int> remote_cmsgdata() {\n    return REMOTE_PTR_FIELD(remote_this(), cmsgbuf).as_int() +\n      sizeof(typename Arch::cmsghdr);\n  }\n};\n\ntemplate <typename Arch>\nstatic long child_sendmsg(AutoRemoteSyscalls& remote, int child_sock, int fd) {\n  AutoRestoreMem remote_buf(remote, nullptr, sizeof(fd_message<Arch>));\n  fd_message<Arch> msg(remote_buf.get().cast<fd_message<Arch>>());\n  // Pull the puppet strings to have the child send its fd\n  // to us.  Similarly to above, we DONT_WAIT on the\n  // call to finish, since it's likely not defined whether the\n  // sendmsg() may block on our recvmsg()ing what the tracee\n  // sent us (in which case we would deadlock with the tracee).\n  // We call sendmsg on child socket, but first we have to prepare a lot of\n  // data.\n  auto cmsg = reinterpret_cast<typename Arch::cmsghdr*>(msg.cmsgbuf);\n  cmsg->cmsg_len = Arch::cmsg_len(sizeof(fd));\n  cmsg->cmsg_level = SOL_SOCKET;\n  cmsg->cmsg_type = SCM_RIGHTS;\n  *static_cast<int*>(Arch::cmsg_data(cmsg)) = fd;\n\n  if (has_socketcall_syscall(Arch::arch())) {\n    socketcall_args<Arch> sc_args = { { child_sock, (typename Arch::signed_long)msg.remote_msg().as_int(), 0 } };\n    msg.socketcall = sc_args;\n  }\n\n  bool ok = true;\n  remote.task()->write_bytes_helper(remote_buf.get().cast<char>(),\n    sizeof(msg), &msg, &ok);\n\n  if (!ok) {\n    return -ESRCH;\n  }\n  if (!has_socketcall_syscall(Arch::arch())) {\n    return remote.syscall(Arch::sendmsg, child_sock, msg.remote_msg(), 0);\n  }\n  return remote.syscall(Arch::socketcall, SYS_SENDMSG, msg.remote_sc_args());\n}\n\ntemplate <typename Arch>\nstatic long child_recvmsg(AutoRemoteSyscalls& remote, int child_sock) {\n  AutoRestoreMem remote_buf(remote, nullptr, sizeof(fd_message<Arch>));\n  fd_message<Arch> msg(remote_buf.get().cast<fd_message<Arch>>());\n  bool ok = true;\n\n  if (has_socketcall_syscall(Arch::arch())) {\n    socketcall_args<Arch> sc_args = { { child_sock,\n      (typename Arch::signed_long)msg.remote_msg().as_int(), 0 } };\n    msg.socketcall = sc_args;\n  }\n\n  remote.task()->write_bytes_helper(remote_buf.get().cast<char>(),\n    sizeof(msg), &msg, &ok);\n\n  if (!ok) {\n    ASSERT(remote.task(), errno == ESRCH || errno == EIO)\n        << \"Error writing \" << remote_buf.get() << \" in \" << remote.task()->tid;\n    LOG(debug) << \"Failed to write memory\";\n    return -ESRCH;\n  }\n  int ret = 0;\n  if (has_socketcall_syscall(Arch::arch())) {\n    ret = remote.syscall(Arch::socketcall, SYS_RECVMSG, msg.remote_sc_args());\n  } else {\n    ret = remote.syscall(Arch::recvmsg, child_sock, msg.remote_msg(), 0);\n  }\n  if (ret < 0) {\n    LOG(debug) << \"Failed to recvmsg \" << ret;\n    return ret;\n  }\n\n  typename Arch::msghdr msghdr =\n      remote.task()->read_mem(msg.remote_msg(), &ok);\n  if (!ok) {\n    ASSERT(remote.task(), errno == ESRCH || errno == EIO);\n    LOG(debug) << \"Failed to read msghdr\";\n    return -ESRCH;\n  }\n  ASSERT(remote.task(), !(msghdr.msg_flags & MSG_CTRUNC))\n      << \"Control message was truncated; error in receiving fd in \"\n         \"AutoRemoteSyscalls::child_recvmsg(). msghdr.msg_flags: \"\n      << HEX(msghdr.msg_flags) << \"\\n\"\n      << \"This error has been most likely caused by a process\\n\"\n      << \"exceeding the max allowed open files limit set by\\n\"\n      << \"Linux. Please consult `man 1 ulimit' and `man 1 prlimit' to\\n\"\n      << \"learn how the max open files limit may be changed/checked.\\n\"\n      << \"As usual, always carefully think through all implications of\\n\"\n      << \"changing the process limits on your programs before making any\\n\"\n      << \"changes.\\n\\n\"\n      << \"If the above Assertion still fails, then (a) The limit you set was\\n\"\n      << \"not high enough, or (b) the program could be opening files in an\\n\"\n      << \"unbounded fashion, or (c) there is some other reason why socket\\n\"\n      << \"control messages are being truncated and file descriptors cannot be\\n\"\n      << \"received via SCM_RIGHTS.\";\n\n  int their_fd = remote.task()->read_mem(msg.remote_cmsgdata(), &ok);\n  if (!ok) {\n    ASSERT(remote.task(), errno == ESRCH || errno == EIO);\n    LOG(debug) << \"Failed to read msg\";\n    return -ESRCH;\n  }\n  return their_fd;\n}\n\n#define MAX_FDS_READ 2\n\n// Try to read a single-character message from `sock`. Will collect\n// up to MAX_FDS_READ fds in an SCM_RIGHTS control message and return those\n// fds. Returns an empty vector if reading the message fails.\nstatic vector<ScopedFd> maybe_receive_fds(ScopedFd& sock, bool blocking = true) {\n  vector<ScopedFd> ret;\n  struct msghdr msg;\n  memset(&msg, 0, sizeof(msg));\n  char ch;\n  struct iovec iov = { &ch, 1 };\n  msg.msg_iov = &iov;\n  msg.msg_iovlen = 1;\n  char cmsgbuf[(CMSG_SPACE(MAX_FDS_READ * sizeof(int)))];\n  msg.msg_control = cmsgbuf;\n  msg.msg_controllen = sizeof(cmsgbuf);\n  int flags = MSG_CMSG_CLOEXEC;\n  if (!blocking) {\n    flags |= MSG_DONTWAIT;\n  }\n  if (recvmsg(sock, &msg, flags) < 0) {\n    return ret;\n  }\n\n  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);\n  if (!cmsg || cmsg->cmsg_level != SOL_SOCKET ||\n      cmsg->cmsg_type != SCM_RIGHTS) {\n    FATAL() << \"Invalid cmsg\";\n  }\n  int num_fds = (cmsg->cmsg_len - CMSG_LEN(0))/sizeof(int);\n  for (int i = 0; i < num_fds; i++) {\n    int fd;\n    memcpy(&fd, CMSG_DATA(cmsg) + i*sizeof(int), sizeof(int));\n    DEBUG_ASSERT(fd >= 0);\n    ret.push_back(ScopedFd(fd));\n  }\n  return ret;\n}\n\nstatic void sendmsg_socket(ScopedFd& sock, int fd_to_send)\n{\n  fd_message<NativeArch> msg;\n\n  struct msghdr *msgp = (struct msghdr*)&msg.msg;\n  struct cmsghdr* cmsg = CMSG_FIRSTHDR(msgp);\n  cmsg->cmsg_level = SOL_SOCKET;\n  cmsg->cmsg_type = SCM_RIGHTS;\n  cmsg->cmsg_len = CMSG_LEN(sizeof(fd_to_send));\n  *(int*)CMSG_DATA(cmsg) = fd_to_send;\n\n  if (0 > sendmsg(sock, msgp, 0)) {\n    FATAL() << \"Failed to send fd\";\n  }\n}\n\nstatic Task* thread_group_leader_for_fds(Task* t) {\n  for (Task* tt : t->fd_table()->task_set()) {\n    if (tt->tgid() == tt->rec_tid && !tt->seen_ptrace_exit_event()) {\n      return tt;\n    }\n  }\n  return nullptr;\n}\n\ntemplate <typename Arch> ScopedFd AutoRemoteSyscalls::retrieve_fd_arch(int fd) {\n  ScopedFd ret;\n  if (!pid_fd.is_open()) {\n    // Try to use pidfd_getfd to get the fd without round-tripping to the tracee.\n    // pidfd_getfd requires a threadgroup leader, so find one if we can.\n    Task* tg_leader_for_fds = thread_group_leader_for_fds(t);\n    if (tg_leader_for_fds) {\n      // N.B.: pidfd_open fds are always cloexec\n      pid_fd = ScopedFd(::syscall(NativeArch::pidfd_open, tg_leader_for_fds->tid, 0));\n      ASSERT(t, pid_fd.is_open() || errno == ENOSYS)\n        << \"Error in pidfd_open errno=\" << errno_name(errno);\n    }\n  }\n  if (pid_fd.is_open()) {\n    ret = ScopedFd(::syscall(NativeArch::pidfd_getfd, pid_fd.get(), fd, 0));\n    if (ret.is_open()) {\n      return ret;\n    }\n    if (errno == EBADF) {\n      // This can happen when the child was unexpectedly killed.\n      return ret;\n    }\n    ASSERT(t, errno == ENOSYS) << \"Failed in pidfd_getfd errno=\" << errno_name(errno);\n  }\n\n  // Clear out any pending message in the socket.\n  maybe_receive_fds(task()->session().tracee_socket_receiver_fd(), false);\n\n  long child_syscall_result =\n      child_sendmsg<Arch>(*this, task()->session().tracee_fd_number(), fd);\n  if (child_syscall_result == -ESRCH) {\n    return ret;\n  }\n  ASSERT(t, child_syscall_result > 0) << \"Failed to sendmsg() in tracee; err=\"\n                                      << errno_name(-child_syscall_result);\n  vector<ScopedFd> fds = maybe_receive_fds(task()->session().tracee_socket_fd());\n  ASSERT(t, !fds.empty()) << \"Failed to receive fd\";\n  ASSERT(t, fds.size() == 1);\n  return std::move(fds[0]);\n}\n\nScopedFd AutoRemoteSyscalls::retrieve_fd(int fd) {\n  RR_ARCH_FUNCTION(retrieve_fd_arch, arch(), fd);\n}\n\ntemplate <typename Arch> int AutoRemoteSyscalls::send_fd_arch(const ScopedFd &our_fd) {\n  if (!our_fd.is_open()) {\n    return -EBADF;\n  }\n\n  // Clear out any pending message from the socket.\n  maybe_receive_fds(task()->session().tracee_socket_receiver_fd(), false);\n\n  LOG(debug) << \"Sending fd \" << our_fd.get() << \" via socket fd \" << task()->session().tracee_socket_fd().get();\n  sendmsg_socket(task()->session().tracee_socket_fd(), our_fd.get());\n\n  long child_syscall_result =\n      child_recvmsg<Arch>(*this, task()->session().tracee_fd_number());\n  // If the child died before reading the message from the socket,\n  // the message will still be in the socket buffer and will be received\n  // the next time we try to send something to a tracee. That's why\n  // before using tracee_socket_receiver_fd we need to drain up to one message\n  // from it.\n  ASSERT(t, child_syscall_result >= 0 || child_syscall_result == -ESRCH)\n    << \"Failed to recvmsg() in tracee; err=\" << errno_name(-child_syscall_result);\n  return child_syscall_result;\n}\n\nint AutoRemoteSyscalls::send_fd(const ScopedFd &our_fd) {\n  RR_ARCH_FUNCTION(send_fd_arch, arch(), our_fd);\n}\n\nvoid AutoRemoteSyscalls::infallible_close_syscall_if_alive(int child_fd) {\n  infallible_syscall_if_alive(syscall_number_for_close(arch()), child_fd);\n}\n\nint AutoRemoteSyscalls::infallible_send_fd_if_alive(const ScopedFd &our_fd) {\n  int child_fd = send_fd(our_fd);\n  ASSERT(t, child_fd >= 0 || (child_fd == -ESRCH && !t->session().is_replaying()))\n    << \"Failed to send fd; err=\" << errno_name(-child_fd);\n  return child_fd;\n}\n\nvoid AutoRemoteSyscalls::infallible_send_fd_dup(const ScopedFd& our_fd, int dup_to, int dup3_flags) {\n  int remote_fd = infallible_send_fd_if_alive(our_fd);\n  ASSERT(t, remote_fd >= 0);\n  if (remote_fd != dup_to) {\n    long ret = infallible_syscall(syscall_number_for_dup3(arch()), remote_fd,\n                                  dup_to, dup3_flags);\n    ASSERT(task(), ret == dup_to);\n    infallible_close_syscall_if_alive(remote_fd);\n  }\n}\n\nremote_ptr<void> AutoRemoteSyscalls::infallible_mmap_syscall_if_alive(\n    remote_ptr<void> addr, size_t length, int prot, int flags, int child_fd,\n    uint64_t offset_bytes) {\n  ASSERT(t, offset_bytes % page_size() == 0)\n    << \"mmap offset (\" << offset_bytes << \") must be multiple of page size (\"\n    << page_size() << \")\";\n  // The first syscall argument is called \"arg 1\", so\n  // our syscall-arg-index template parameter starts\n  // with \"1\".\n  remote_ptr<void> ret =\n      has_mmap2_syscall(arch())\n          ? infallible_syscall_ptr_if_alive(syscall_number_for_mmap2(arch()), addr,\n                                            length, prot, flags, child_fd,\n                                            (off_t)offset_bytes / 4096)\n          : infallible_syscall_ptr_if_alive(syscall_number_for_mmap(arch()), addr,\n                                            length, prot, flags, child_fd,\n                                            offset_bytes);\n  if (flags & MAP_FIXED) {\n    if (ret) {\n      ASSERT(t, addr == ret) << \"MAP_FIXED at \" << addr << \" but got \" << ret;\n    } else {\n      if (!t->vm()->has_mapping(addr)) {\n        KernelMapping km = t->vm()->read_kernel_mapping(t, addr);\n        if (km.size()) {\n          ASSERT(t, km.start() == addr && km.size() == ceil_page_size(length));\n          // The mapping was created. Pretend this call succeeded.\n          ret = addr;\n        }\n      }\n    }\n  }\n  return ret;\n}\n\nbool AutoRemoteSyscalls::infallible_munmap_syscall_if_alive(\n    remote_ptr<void> addr, size_t length) {\n  long ret = infallible_syscall_if_alive(syscall_number_for_munmap(arch()),\n                                         addr, length);\n  if (ret) {\n    if (t->vm()->has_mapping(addr)) {\n      KernelMapping km = t->vm()->read_kernel_mapping(t, addr);\n      if (!km.size()) {\n        // The unmap happened but the task must have died before\n        // reporting the status.\n        ret = 0;\n      }\n    }\n  }\n  return !ret;\n}\n\nint64_t AutoRemoteSyscalls::infallible_lseek_syscall(int fd, int64_t offset,\n                                                     int whence) {\n  switch (arch()) {\n    case x86: {\n      AutoRestoreMem mem(*this, &offset, sizeof(int64_t));\n      infallible_syscall(syscall_number_for__llseek(arch()), fd, offset >> 32,\n                         offset, mem.get(), whence);\n      return t->read_mem(mem.get().cast<int64_t>());\n    }\n    case x86_64:\n    case aarch64:\n      return infallible_syscall(syscall_number_for_lseek(arch()), fd, offset,\n                                whence);\n    default:\n      ASSERT(t, false) << \"Unknown arch\";\n      return -1;\n  }\n}\n\nbool AutoRemoteSyscalls::check_syscall_result(long ret, int syscallno, bool allow_death) {\n  if (word_size(t->arch()) == 4) {\n    // Sign-extend ret because it can be a 32-bit negative errno\n    ret = (int)ret;\n  }\n  if (ret == -ESRCH && allow_death && !t->session().is_replaying()) {\n    return true;\n  }\n  if (-4096 < ret && ret < 0) {\n    string extra_msg;\n    if (is_open_syscall(syscallno, arch())) {\n      extra_msg = \" opening \" + t->read_c_str(t->regs().arg1());\n    } else if (is_openat_syscall(syscallno, arch()) || is_openat2_syscall(syscallno, arch())) {\n      extra_msg = \" opening \" + t->read_c_str(t->regs().arg2());\n    } else if (is_mremap_syscall(syscallno, arch())) {\n      AddressSpace::print_process_maps(t);\n    } else if (is_mmap_syscall(syscallno, arch())) {\n      AddressSpace::print_process_maps(t);\n      if ((t->regs().arg4() & MAP_ANONYMOUS) == 0) {\n        extra_msg = \" mmapping \" + t->file_name_of_fd(t->regs().arg5());\n      }\n    }\n    ASSERT(t, false) << \"Syscall \" << syscall_name(syscallno, arch())\n                     << \" failed with errno \" << errno_name(-ret) << extra_msg\n                     << \" arg1=0x\" << hex << t->regs().arg1() << \" arg2=0x\" << t->regs().arg2()\n                     << \" arg3=0x\" << hex << t->regs().arg3() << \" arg4=0x\" << t->regs().arg4()\n                     << \" arg5=0x\" << hex << t->regs().arg5() << \" arg6=0x\" << t->regs().arg6();\n  }\n  return false;\n}\n\nvoid AutoRemoteSyscalls::finish_direct_mmap(\n                               remote_ptr<void> rec_addr, size_t length,\n                               int prot, int flags,\n                               const string& backing_file_name,\n                               int backing_file_open_flags,\n                               off_t backing_offset_bytes,\n                               struct stat& real_file, string& real_file_name) {\n  int fd;\n\n  LOG(debug) << \"directly mmap'ing \" << length << \" bytes of \"\n             << backing_file_name << \" at offset \"\n             << HEX(backing_offset_bytes);\n\n  ASSERT(task(), !(flags & MAP_GROWSDOWN));\n\n  /* Open in the tracee the file that was mapped during\n   * recording. */\n  {\n    AutoRestoreMem child_str(*this, backing_file_name.c_str());\n    if (word_size(t->arch()) == 4) {\n      backing_file_open_flags |= RR_LARGEFILE_32;\n    }\n    fd = infallible_syscall(syscall_number_for_openat(arch()), -1,\n                            child_str.get().as_int(),\n                            backing_file_open_flags);\n  }\n  /* And mmap that file. */\n  infallible_mmap_syscall_if_alive(rec_addr, length,\n                          /* (We let SHARED|WRITEABLE\n                          * mappings go through while\n                          * they're not handled properly,\n                          * but we shouldn't do that.) */\n                          prot, (flags & ~MAP_SYNC) | MAP_FIXED, fd,\n                          /* MAP_SYNC is used to request direct mapping\n                          * (DAX) from the filesystem for persistent\n                          * memory devices (requires\n                          * MAP_SHARED_VALIDATE). Drop it for the\n                          * backing file. */\n                          backing_offset_bytes);\n\n  // While it's open, grab the link reference.\n  real_file = task()->stat_fd(fd);\n  real_file_name = task()->file_name_of_fd(fd);\n\n  /* Don't leak the tmp fd.  The mmap doesn't need the fd to\n   * stay open. */\n  infallible_close_syscall_if_alive(fd);\n}\n\n\n} // namespace rr\n"
  },
  {
    "path": "src/AutoRemoteSyscalls.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_AUTO_REMOTE_SYSCALLS_H_\n#define RR_AUTO_REMOTE_SYSCALLS_H_\n\n#include <string.h>\n\n#include <vector>\n\n#include \"Registers.h\"\n#include \"ScopedFd.h\"\n#include \"Task.h\"\n\nnamespace rr {\n\nclass AutoRemoteSyscalls;\nclass Task;\n\n/**\n * Helpers to make remote syscalls on behalf of a Task.  Usage looks\n * like\n *\n *    AutoRemoteSyscalls remote(t); // prepare remote syscalls\n *    remote.syscall(syscall_number_for_open(remote.arch()), ...); // make\n *syscalls\n *    ...\n *    // when |remote| goes out of scope, remote syscalls are finished\n */\n\n/**\n * Cookie used to restore stomped memory, usually prepared as the\n * argument to a remote syscall.\n */\nclass AutoRestoreMem {\npublic:\n  /**\n   * Write |mem| into address space of the Task prepared for\n   * remote syscalls in |remote|, in such a way that the write\n   * will be undone.  The address of the reserved mem space is\n   * available via |get|.\n   * If |mem| is null, data is not written, only the space is reserved.\n   */\n  AutoRestoreMem(AutoRemoteSyscalls& remote, const void* mem, ssize_t num_bytes)\n      : remote(remote) {\n    init(mem, num_bytes);\n  }\n\n  /**\n   * Convenience constructor for pushing a C string |str|, including\n   * the trailing '\\0' byte.\n   */\n  AutoRestoreMem(AutoRemoteSyscalls& remote, const char* str) : remote(remote) {\n    init((const uint8_t*)str, strlen(str) + 1 /*null byte*/);\n  }\n\n  ~AutoRestoreMem();\n\n  /**\n   * Get a pointer to the reserved memory.\n   * Returns null if we failed.\n   */\n  remote_ptr<void> get() const { return addr; }\n\n  /**\n   * Return size of reserved memory buffer.\n   */\n  size_t size() const { return data.size(); }\n\nprivate:\n  void init(const void* mem, ssize_t num_bytes);\n\n  AutoRemoteSyscalls& remote;\n  /* Address of tmp mem. */\n  remote_ptr<void> addr;\n  /* Saved data. */\n  std::vector<uint8_t> data;\n  /* (We keep this around for error checking.) */\n  remote_ptr<void> saved_sp;\n  /* Length of tmp mem. */\n  size_t len;\n\n  AutoRestoreMem& operator=(const AutoRestoreMem&) = delete;\n  AutoRestoreMem(const AutoRestoreMem&) = delete;\n  void* operator new(size_t) = delete;\n  void operator delete(void*) = delete;\n};\n\n/**\n * RAII helper to prepare a Task for remote syscalls and undo any\n * preparation upon going out of scope. Note that this restores register\n * values when going out of scope, so *all* changes to Task's register\n * state are lost.\n */\nclass AutoRemoteSyscalls {\npublic:\n  enum MemParamsEnabled { ENABLE_MEMORY_PARAMS, DISABLE_MEMORY_PARAMS };\n\n  /**\n   * Prepare |t| for a series of remote syscalls.\n   *\n   * NBBB!  Before preparing for a series of remote syscalls,\n   * the caller *must* ensure the callee will not receive any\n   * signals.  This code does not attempt to deal with signals.\n   */\n  AutoRemoteSyscalls(Task* t,\n                     MemParamsEnabled enable_mem_params = ENABLE_MEMORY_PARAMS);\n  /**\n   * Undo in |t| any preparations that were made for a series of\n   * remote syscalls.\n   */\n  ~AutoRemoteSyscalls();\n\n  /**\n   * If t's stack pointer doesn't look valid, temporarily adjust it to\n   * the top of *some* stack area.\n   */\n  void maybe_fix_stack_pointer();\n\n  /**\n   * \"Initial\" registers saved from the target task.\n   *\n   * NB: a non-const reference is returned because some power\n   * users want to update the registers that are restored after\n   * finishing remote syscalls.  Perhaps these users should be\n   * fixed, or you should just be careful.\n   */\n  Registers& regs() { return initial_regs; }\n\n  /**\n   * Undo any preparations to make remote syscalls in the context of |t|.\n   *\n   * This is usually called automatically by the destructor;\n   * don't call it directly unless you really know what you'd\n   * doing.  *ESPECIALLY* don't call this on a |t| other than\n   * the one passed to the constructor, unless you really know\n   * what you're doing.\n   */\n  void restore_state_to(Task* t);\n\n  /**\n   * Make |syscallno| with variadic |args| (limited to 6 on\n   * x86).  Return the raw kernel return value.\n   * Returns -ESRCH if the process dies or has died.\n   */\n  template <typename... Rest> long syscall(int syscallno, Rest... args) {\n    Registers callregs = regs();\n    // The first syscall argument is called \"arg 1\", so\n    // our syscall-arg-index template parameter starts\n    // with \"1\".\n    return syscall_helper<1>(syscallno, callregs, args...);\n  }\n\n  // Aborts on all errors.\n  // DEPRECATED. Use infallible_syscall_if_alive instead.\n  template <typename... Rest>\n  long infallible_syscall(int syscallno, Rest... args) {\n    Registers callregs = regs();\n    // The first syscall argument is called \"arg 1\", so\n    // our syscall-arg-index template parameter starts\n    // with \"1\".\n    long ret = syscall_helper<1>(syscallno, callregs, args...);\n    check_syscall_result(ret, syscallno, false);\n    return ret;\n  }\n\n  // Aborts on all errors other than -ESRCH. Aborts on -ESRCH\n  // if this is a replay task (they should never unexpectedly die).\n  template <typename... Rest>\n  long infallible_syscall_if_alive(int syscallno, Rest... args) {\n    Registers callregs = regs();\n    // The first syscall argument is called \"arg 1\", so\n    // our syscall-arg-index template parameter starts\n    // with \"1\".\n    long ret = syscall_helper<1>(syscallno, callregs, args...);\n    check_syscall_result(ret, syscallno);\n    return ret;\n  }\n\n  /** Returns null if the tracee is dead */\n  template <typename... Rest>\n  remote_ptr<void> infallible_syscall_ptr_if_alive(int syscallno, Rest... args) {\n    Registers callregs = regs();\n    long ret = syscall_helper<1>(syscallno, callregs, args...);\n    check_syscall_result(ret, syscallno);\n    return ret == -ESRCH ? 0 : ret;\n  }\n\n  /**\n   * Remote mmap syscalls are common and non-trivial due to the need to\n   * select either mmap2 or mmap.\n   * Returns null if the process died (or was already dead) without\n   * creating the map. \"Dead\" includes reaching PTRACE_EVENT_EXIT.\n   * If the mapping is FIXED and no mapping currently exists at the address,\n   * and the syscall creates the mapping but the process dies before returning\n   * success, we fix the result to indicate that the syscall succeeded.\n   * Creating FIXED mappings in areas free according to AddressSpace is the only\n   * reliable way to keep AddressSpace in sync with reality in the event of\n   * unexpected process death racing with this operation.\n   */\n  remote_ptr<void> infallible_mmap_syscall_if_alive(remote_ptr<void> addr, size_t length,\n                                                    int prot, int flags, int child_fd,\n                                                    uint64_t offset_bytes);\n\n  /**\n   * Returns false if the process died (or was already dead) without\n   * unmapping the area. \"Dead\" includes reaching PTRACE_EVENT_EXIT.\n   * If a mapping currently exists at the address, and the syscall unmaps\n   * the mapping but the process dies before returning success, we fix\n   * the result to indicate that the syscall succeeded.\n   */\n  bool infallible_munmap_syscall_if_alive(remote_ptr<void> addr, size_t length);\n\n  /** TODO replace with infallible_lseek_syscall_if_alive */\n  int64_t infallible_lseek_syscall(int fd, int64_t offset, int whence);\n\n  /** Close the fd in the child. If the child died, just ignore that. */\n  void infallible_close_syscall_if_alive(int child_fd);\n\n  /** The Task in the context of which we're making syscalls. */\n  Task* task() const { return t; }\n\n  /**\n   * A small helper to get at the Task's arch.\n   * Out-of-line to avoid including Task.h here.\n   */\n  SupportedArch arch() const;\n\n  /**\n   * Arranges for 'fd' to be transmitted to this process and returns\n   * our opened version of it.\n   * Returns a closed fd if the process dies or has died.\n   */\n  ScopedFd retrieve_fd(int fd);\n\n  /**\n   * Arranges for 'fd' to be transmitted to the tracee and returns\n   * a file descriptor in the tracee that corresponds to the same file\n   * description.\n   * Returns a negative value if this fails.\n   */\n  int send_fd(const ScopedFd &fd);\n\n  /**\n   * Arranges for 'fd' to be transmitted to the tracee and returns\n   * a file descriptor in the tracee that corresponds to the same file\n   * description.\n   * Aborts if that fails.\n   * Returns -ESRCH if the tracee is dead (and is not replaying)\n   */\n  int infallible_send_fd_if_alive(const ScopedFd& our_fd);\n\n  /**\n   * `send_fd` the given file descriptor, making sure that it ends up as fd\n   * `dup_to`, (dup'ing it there and closing the original if necessary)\n   * TODO replace with infallible_send_fd_dup_if_alive\n   */\n  void infallible_send_fd_dup(const ScopedFd& our_fd, int dup_to, int dup3_flags);\n\n  /**\n   * Remotely invoke in |t| the specified syscall with the given\n   * arguments.  The arguments must of course be valid in |t|,\n   * and no checking of that is done by this function.\n   *\n   * The syscall is finished in |t| and the result is returned.\n   */\n  long syscall_base(int syscallno, Registers& callregs);\n\n  MemParamsEnabled enable_mem_params() { return enable_mem_params_; }\n\n  /**\n   * When the syscall is 'clone', this will be recovered from the\n   * PTRACE_EVENT_FORK/VFORK/CLONE.\n   */\n  pid_t new_tid() { return new_tid_; }\n\n  /* Do the open/mmap/close dance for a particular file */\n  void finish_direct_mmap(remote_ptr<void> rec_addr, size_t length,\n                          int prot, int flags,\n                          const std::string& backing_file_name,\n                          int backing_file_open_flags,\n                          off_t backing_offset_bytes,\n                          struct stat& real_file, std::string& real_file_name);\n\n  // Calling this with allow_death false is DEPRECATED.\n  // Returns true iff session was not replaying and allow_death is true and process is not alive (-ESRCH)\n  bool check_syscall_result(long ret, int syscallno, bool allow_death = true);\n\nprivate:\n  void setup_path(bool enable_singlestep_path);\n\n  /**\n   * \"Recursively\" build the set of syscall registers in\n   * |callregs|.  |Index| is the syscall arg that will be set to\n   * |arg|, and |args| are the remaining arguments.\n   */\n  template <int Index, typename T, typename... Rest>\n  long syscall_helper(int syscallno, Registers& callregs, T arg, Rest... args) {\n    callregs.set_arg<Index>(arg);\n    return syscall_helper<Index + 1>(syscallno, callregs, args...);\n  }\n  /**\n   * \"Recursion\" \"base case\": no more arguments to build, so\n   * just make the syscall and return the kernel return value.\n   */\n  template <int Index> long syscall_helper(int syscallno, Registers& callregs) {\n    return syscall_base(syscallno, callregs);\n  }\n\n  template <typename Arch> ScopedFd retrieve_fd_arch(int fd);\n  template <typename Arch> int send_fd_arch(const ScopedFd &fd);\n\n  Task* t;\n  Registers initial_regs;\n  remote_code_ptr initial_ip;\n  remote_ptr<void> initial_sp;\n  bool initial_at_seccomp;\n  remote_ptr<void> fixed_sp;\n  std::vector<uint8_t> replaced_bytes;\n  WaitStatus restore_wait_status;\n  ScopedFd pid_fd;\n\n  pid_t new_tid_;\n  /* Whether we had to mmap a scratch region because none was found */\n  bool scratch_mem_was_mapped;\n  bool use_singlestep_path;\n\n  MemParamsEnabled enable_mem_params_;\n\n  bool restore_sigmask;\n  sig_set_t sigmask_to_restore;\n\n  bool need_sigpending_renable;\n  bool need_desched_event_reenable;\n\n  AutoRemoteSyscalls& operator=(const AutoRemoteSyscalls&) = delete;\n  AutoRemoteSyscalls(const AutoRemoteSyscalls&) = delete;\n};\n\n} // namespace rr\n\n#endif // RR_AUTO_REMOTE_SYSCALLS_H_\n"
  },
  {
    "path": "src/BpfMapMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_BPF_MAP_MONITOR_H_\n#define RR_BPF_MAP_MONITOR_H_\n\n#include \"FileMonitor.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor attached to BPF map fds to record their key and value size.\n */\nclass BpfMapMonitor : public FileMonitor {\npublic:\n  BpfMapMonitor(uint64_t key_size, uint64_t value_size) : key_size_(key_size), value_size_(value_size) {}\n\n  virtual Type type() override { return BpfMap; }\n\n  uint64_t key_size() const { return key_size_; }\n  uint64_t value_size() const { return value_size_; }\n\nprivate:\n  uint64_t key_size_;\n  uint64_t value_size_;\n};\n\n} // namespace rr\n\n#endif /* RR_BPF_MAP_MONITOR_H_ */\n"
  },
  {
    "path": "src/BreakpointCondition.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_BREAKPOINT_CONDITION_H_\n#define RR_BREAKPOINT_CONDITION_H_\n\nnamespace rr {\n\nclass ReplayTask;\n\nclass BreakpointCondition {\npublic:\n  virtual ~BreakpointCondition() {}\n  virtual bool evaluate(ReplayTask* t) const = 0;\n};\n\n} // namespace rr\n\n#endif // RR_BREAKPOINT_CONDITION_H_\n"
  },
  {
    "path": "src/BuildidCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <iostream>\n\n#include \"log.h\"\n#include \"Command.h\"\n#include \"ElfReader.h\"\n#include \"ScopedFd.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass BuildidCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  BuildidCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static BuildidCommand singleton;\n};\n\nBuildidCommand BuildidCommand::singleton(\n  \"buildid\",\n  \" rr buildid\\n\"\n  \"  Accepts paths on stdin, prints buildids on stdout. Will terminate when\\n\"\n  \"  either an empty line or an invalid path is provided.\\n\");\n\nint BuildidCommand::run(vector<string>& args) {\n  if (!args.empty()) {\n    fprintf(stderr, \"Unexpected arguments!\");\n    return 1;\n  }\n\n  string input;\n  while (getline(cin, input)) {\n    if (input.empty()) {\n      break;\n    }\n\n    ScopedFd fd = ScopedFd(input.c_str(), O_RDONLY, 0);\n    if (!fd.is_open()) {\n      LOG(error) << \"Failed to open `\" << input << \"`\";\n      return 1;\n    }\n\n    ElfFileReader reader(fd);\n    auto buildid = reader.read_buildid();\n    fprintf(stdout, \"%s\\n\", buildid.c_str());\n  }\n\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/CPUFeaturesCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Command.h\"\n#include \"GdbServer.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass CPUFeaturesCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  CPUFeaturesCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static CPUFeaturesCommand singleton;\n};\n\nCPUFeaturesCommand CPUFeaturesCommand::singleton(\n    \"cpufeatures\",\n    \" rr cpufeatures\\n\"\n    \"  Print `rr record` command line options that will limit the tracee\\n\"\n    \"  to CPU features this machine supports.\\n\"\n    \"  Useful for trace portability: run `rr cpufeatures` on the machine\\n\"\n    \"  you plan to replay on, then add those command-line parameters to\\n\"\n    \"  `rr record` on the recording machine.\\n\");\n\nint CPUFeaturesCommand::run(vector<string>& args) {\n  while (parse_global_option(args)) {\n  }\n\n  CPUIDData features = cpuid(CPUID_GETFEATURES, 0);\n  CPUIDData extended_features = cpuid(CPUID_GETEXTENDEDFEATURES, 0);\n  CPUIDData features_xsave = cpuid(CPUID_GETXSAVE, 1);\n  fprintf(stdout, \"--disable-cpuid-features 0x%x,0x%x \"\n          \"--disable-cpuid-features-ext 0x%x,0x%x,0x%x \"\n          \"--disable-cpuid-features-xsave 0x%x\\n\",\n          ~features.ecx, ~features.edx,\n          ~extended_features.ebx, ~extended_features.ecx,\n          ~extended_features.edx, ~features_xsave.eax);\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/CPUIDBugDetector.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"CPUIDBugDetector.h\"\n#include \"Event.h\"\n#include \"Flags.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"kernel_abi.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n#if defined(__i386__) || defined(__x86_64__)\nextern \"C\" int cpuid_loop(int iterations);\nvoid CPUIDBugDetector::run_detection_code() {\n  // Call cpuid_loop to generate trace data we can use to detect\n  // the cpuid rcb undercount bug. This generates 4 geteuid\n  // calls which should have 2 rcbs between each of the\n  // 3 consecutive pairs.\n  cpuid_loop(4);\n}\n#else\n// Other platforms don't have cpuid, but keep the calling code clean, by\n// just making this a no-op there.\nvoid CPUIDBugDetector::run_detection_code() {}\n#endif\n\nstatic bool rcb_counts_ok(ReplayTask* t, uint64_t prev, uint64_t current) {\n  uint32_t expected_count = 2 + PerfCounters::ticks_for_direct_call(t);\n  if (current - prev == expected_count) {\n    return true;\n  }\n  if (!Flags::get().suppress_environment_warnings) {\n    fprintf(\n        stderr,\n        \"\\n\"\n        \"rr: Warning: You appear to be running in a VMWare guest with a bug\\n\"\n        \"    where a conditional branch instruction between two CPUID \"\n        \"instructions\\n\"\n        \"    sometimes fails to be counted by the conditional branch \"\n        \"performance\\n\"\n        \"    counter. Work around this problem by adding\\n\"\n        \"        monitor_control.disable_hvsim_clusters = true\\n\"\n        \"    to your .vmx file.\\n\"\n        \"\\n\");\n  }\n  return false;\n}\n\nvoid CPUIDBugDetector::notify_reached_syscall_during_replay(ReplayTask* t) {\n  // We only care about events that happen before the first exec,\n  // when our detection code runs.\n  if (!is_x86ish(t->arch())) {\n    return;\n  }\n  if (t->session().done_initial_exec()) {\n    return;\n  }\n  const Event& ev = t->current_trace_frame().event();\n  if (!is_geteuid32_syscall(ev.Syscall().number, t->arch()) &&\n      !is_geteuid_syscall(ev.Syscall().number, t->arch())) {\n    return;\n  }\n  uint64_t trace_rcb_count = t->current_trace_frame().ticks();\n  uint64_t actual_rcb_count = t->tick_count();\n  if (trace_rcb_count_at_last_geteuid32 > 0 && !detected_cpuid_bug) {\n    if (!rcb_counts_ok(t, trace_rcb_count_at_last_geteuid32, trace_rcb_count) ||\n        !rcb_counts_ok(t, actual_rcb_count_at_last_geteuid32, actual_rcb_count)) {\n      detected_cpuid_bug = true;\n    }\n  }\n  trace_rcb_count_at_last_geteuid32 = trace_rcb_count;\n  actual_rcb_count_at_last_geteuid32 = actual_rcb_count;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/CPUIDBugDetector.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_CPUID_BUG_DETECTOR_H_\n#define RR_CPUID_BUG_DETECTOR_H_\n\n#include <stdint.h>\n\nnamespace rr {\n\nclass ReplayTask;\n\n/**\n * Helper to detect when the \"CPUID can cause rcbs to be lost\" bug is present.\n * See http://robert.ocallahan.org/2014/09/vmware-cpuid-conditional-branch.html\n *\n * This bug is caused by VMM optimizations described in\n * https://www.usenix.org/system/files/conference/atc12/atc12-final158.pdf\n * that cause instruction sequences related to CPUID to be optimized,\n * eliminating the user-space execution of a conditional branch between two\n * CPUID instructions (in some circumstances).\n */\nclass CPUIDBugDetector {\npublic:\n  CPUIDBugDetector()\n      : trace_rcb_count_at_last_geteuid32(0),\n        actual_rcb_count_at_last_geteuid32(0),\n        detected_cpuid_bug(false) {}\n  /**\n   * Call this in the context of the first spawned process to run the\n   * code that triggers the bug.\n   */\n  static void run_detection_code();\n  /**\n   * Call this when task t enters a traced syscall during replay.\n   */\n  void notify_reached_syscall_during_replay(ReplayTask* t);\n\nprivate:\n  uint64_t trace_rcb_count_at_last_geteuid32;\n  uint64_t actual_rcb_count_at_last_geteuid32;\n  bool detected_cpuid_bug;\n};\n\n} // namespace rr\n\n#endif /* RR_CPUID_BUG_DETECTOR_H_ */\n"
  },
  {
    "path": "src/CPUs.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"CPUs.h\"\n\n#include <sched.h>\n#include <unistd.h>\n\n#include <filesystem>\n#include <fstream>\n#include <istream>\n#include <sstream>\n#include <string>\n\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic bool hybrid_cpu_arch_parse_cpus(const filesystem::path& dir,\n                                       CPUGroup* group) {\n  ifstream file(dir / \"cpus\");\n  if (!file.good()) {\n    LOG(warn) << \"File \" << dir.string() << \"/cpus not found\";\n    return false;\n  }\n  ostringstream sstr;\n  sstr << file.rdbuf();\n  string s = sstr.str();\n  while (!s.empty() && s[s.size() - 1] == '\\n') {\n    s.resize(s.size() - 1);\n  }\n  if (s.empty()) {\n    LOG(info) << \"File \" << dir.string() << \"/cpus is empty after trimming.\";\n    return false;\n  }\n  size_t dash = s.find('-');\n  if (dash == string::npos) {\n    size_t end;\n    group->start_cpu = stoi(s, &end);\n    if (end != s.size()) {\n      LOG(warn) << \"Bad CPU index\";\n      return false;\n    }\n    group->end_cpu = group->start_cpu + 1;\n    return true;\n  }\n  size_t end;\n  group->start_cpu = stoi(s.substr(0, dash), &end);\n  if (end != dash) {\n    LOG(warn) << \"Bad CPU index\";\n    return false;\n  }\n  int last_cpu = stoi(s.substr(dash + 1), &end);\n  if (end != s.size() - (dash + 1)) {\n    LOG(warn) << \"Bad end CPU index\";\n    return false;\n  }\n  group->end_cpu = last_cpu + 1;\n  return true;\n}\n\nstatic bool hybrid_cpu_arch_parse_type(const filesystem::path& dir,\n                                       CPUGroup* group) {\n  // See https://github.com/torvalds/linux/blob/master/tools/perf/Documentation/intel-hybrid.txt\n  ifstream file(dir / \"type\");\n  if (!file.good()) {\n    LOG(warn) << \"File \" << dir.string() << \"/type not found\";\n    return false;\n  }\n  ostringstream sstr;\n  sstr << file.rdbuf();\n  string s = sstr.str();\n  while (!s.empty() && s[s.size() - 1] == '\\n') {\n    s.resize(s.size() - 1);\n  }\n  size_t end;\n  group->type = stoi(s, &end);\n  if (end != s.size()) {\n    LOG(warn) << \"Bad type\";\n    return false;\n  }\n  return true;\n}\n\n// Returns an empty list on many (all?) systems that aren't using hybrid cores.\n// In that case, assume all CPUs have the same microarch.\nstatic vector<CPUGroup> hybrid_cpu_arch_groups() {\n  vector<CPUGroup> result;\n  filesystem::path dir_path = \"/sys/devices\";\n  if (!filesystem::is_directory(dir_path)) {\n    return result;\n  }\n  for (const auto& entry : filesystem::directory_iterator(dir_path)) {\n    auto file_name = entry.path().filename().string();\n    if (file_name.find(\"cpu_\") != 0) {\n      continue;\n    }\n    CPUGroup group;\n    group.name = file_name.substr(4);\n    if (!hybrid_cpu_arch_parse_cpus(entry.path(), &group)) {\n      continue;\n    }\n    if (!hybrid_cpu_arch_parse_type(entry.path(), &group)) {\n      continue;\n    }\n    if (group.name == \"core\") {\n      group.kind = CPUGroup::P_CORE;\n    } else if (group.name == \"atom\" || group.name == \"lowpower\") {\n      group.kind = CPUGroup::E_CORE;\n    } else {\n      group.kind = CPUGroup::UNKNOWN;\n    }\n    result.push_back(std::move(group));\n  }\n  return result;\n}\n\nconst CPUs& CPUs::get() {\n  static CPUs singleton;\n  return singleton;\n}\n\nstd::vector<int> CPUs::initial_affinity() const {\n  std::vector<int> result;\n  for (int i = 0; i < CPU_SETSIZE; ++i) {\n    if (CPU_ISSET(i, &initial_affinity_)) {\n      result.push_back(i);\n    }\n  }\n  return result;\n}\n\nbool CPUs::set_affinity_to_cpu(int cpu) {\n  DEBUG_ASSERT(cpu >= 0);\n\n  cpu_set_t mask;\n  CPU_ZERO(&mask);\n  CPU_SET(cpu, &mask);\n  if (0 > sched_setaffinity(0, sizeof(mask), &mask)) {\n    if (errno == EINVAL) {\n      return false;\n    }\n    FATAL() << \"Couldn't bind to CPU \" << cpu;\n  }\n  return true;\n}\n\nvoid CPUs::restore_initial_affinity(pid_t tid) const {\n  int ret = sched_setaffinity(tid, sizeof(initial_affinity_), &initial_affinity_);\n  if (ret < 0) {\n    FATAL() << \"restore_initial_affinity failed\";\n  }\n}\n\nCPUs::CPUs() {\n  // sched_getaffinity intersects the task's `cpu_mask`\n  // (/proc/.../status Cpus_allowed_list) with `cpu_active_mask`\n  // which is almost the same as /sys/devices/system/cpu/online\n  int ret = sched_getaffinity(0, sizeof(initial_affinity_), &initial_affinity_);\n  if (ret < 0) {\n    FATAL() << \"failed to get initial affinity\";\n  }\n  cpu_groups_ = hybrid_cpu_arch_groups();\n}\n\n}\n\n"
  },
  {
    "path": "src/CPUs.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_CPUS_H_\n#define RR_CPUS_H_\n\n#include <sched.h>\n\n#include <string>\n#include <vector>\n\nnamespace rr {\n\nstruct BindCPU {\n  enum Mode {\n    // Bind to any core.\n    ANY,\n    // Perfer high-performance core if CPU affinity settings allow.\n    PREFER_PERF_CORE,\n    // Bind to a specified core unconditionally.\n    SPECIFIED_CORE,\n    // Don't bind.\n    UNBOUND,\n  };\n\n  explicit BindCPU(Mode mode) : mode(mode) {}\n  explicit BindCPU(int specified_core)\n    : mode(SPECIFIED_CORE), specified_core(specified_core) {}\n\n  Mode mode;\n  int specified_core;\n};\n\nstruct CPUGroup {\n  enum Kind { P_CORE, E_CORE, UNKNOWN };\n\n  int start_cpu;\n  // Exclusive\n  int end_cpu;\n  std::string name;\n  // PERF_TYPE_RAW or something else usable in the perf-attr\n  // event_type field.\n  int type;\n  Kind kind;\n};\n\nclass CPUs {\npublic:\n  static const CPUs& get();\n\n  // Returns the CPU indices in the initial affinity mask, in increasing order.\n  std::vector<int> initial_affinity() const;\n  static bool set_affinity_to_cpu(int cpu);\n  // Restore the initial affinity mask to the given tid.\n  // If unspecified, defaults to this thread.\n  void restore_initial_affinity(pid_t tid = 0) const;\n\n  // Returns the CPU group list. May be empty on systems where that\n  // information is not available or relevant.\n  const std::vector<CPUGroup>& cpu_groups() const { return cpu_groups_; }\n\nprivate:\n  CPUs();\n\n  cpu_set_t initial_affinity_;\n  std::vector<CPUGroup> cpu_groups_;\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "src/Command.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define _BSD_SOURCE\n\n#include \"Command.h\"\n\n#include <stdio.h>\n#include <string.h>\n\n#include <algorithm>\n\n#include \"TraceStream.h\"\n#include \"core.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nbool ParsedOption::verify_valid_int(int64_t min, int64_t max) const {\n  if (int_value < min || int_value > max) {\n    fprintf(\n        stderr,\n        \"Value %s for parameter %s was not valid (allowed range %lld-%lld)\\n\",\n        value.c_str(), arg.c_str(), (long long)min, (long long)max);\n    return false;\n  }\n  return true;\n}\n\nstatic vector<Command*>* command_list;\n\nCommand::Command(const char* name, const char* help) : name(name), help(help) {\n  if (!command_list) {\n    command_list = new vector<Command*>();\n  }\n  command_list->push_back(this);\n}\n\nCommand* Command::command_for_name(const std::string& name) {\n  for (auto& it : *command_list) {\n    if (strcmp(it->name, name.c_str()) == 0) {\n      return it;\n    }\n  }\n  return nullptr;\n}\n\nbool Command::less_than_by_name(Command* c1, Command* c2) {\n  return strcmp(c1->name, c2->name) < 0;\n}\n\nvoid Command::print_help_all(FILE* out) {\n  vector<Command*> cmds;\n  for (auto& it : *command_list) {\n    if (!it->help) {\n      continue;\n    }\n    cmds.push_back(it);\n  }\n\n  sort(cmds.begin(), cmds.end(), less_than_by_name);\n\n  for (auto& it : cmds) {\n    const char* c = strchr(it->help, '\\n');\n    if (c) {\n      fprintf(out, \"%.*s\\n\", (int)(c - it->help), it->help);\n    } else {\n      fputs(it->help, out);\n    }\n  }\n}\n\nvoid Command::print_help(FILE* out) {\n  if (help) {\n    fputs(help, out);\n    print_global_options(out);\n  } else {\n    print_usage(out);\n  }\n}\n\nstatic bool consume_args(std::vector<std::string>& args, size_t count) {\n  args.erase(args.begin(), args.begin() + count);\n  return true;\n}\n\nstatic void assign_param(ParsedOption* opt, const char* s) {\n  opt->value = s;\n  opt->int_value = INT64_MIN;\n  if (!opt->value.empty()) {\n    char* end;\n    int64_t v = strtoll(s, &end, 0);\n    if (*end == 0) {\n      opt->int_value = v;\n    }\n  }\n}\n\nbool Command::parse_option(std::vector<std::string>& args,\n                           const OptionSpec* option_specs, size_t count,\n                           ParsedOption* out) {\n  if (args.size() == 0 || args[0][0] != '-') {\n    return false;\n  }\n\n  out->arg = args[0];\n\n  for (size_t i = 0; i < count; ++i) {\n    if (args[0][1] == option_specs[i].short_name && args[0][1] >= 32) {\n      out->short_name = option_specs[i].short_name;\n      switch (option_specs[i].param) {\n        case NO_PARAMETER:\n          if (args[0][2] == 0) {\n            return consume_args(args, 1);\n          }\n          return false;\n        case HAS_PARAMETER:\n          if (args[0][2] == '=') {\n            assign_param(out, args[0].c_str() + 3);\n            return consume_args(args, 1);\n          }\n          if (args[0][2] != 0) {\n            assign_param(out, args[0].c_str() + 2);\n            return consume_args(args, 1);\n          }\n          if (args.size() >= 2) {\n            assign_param(out, args[1].c_str());\n            return consume_args(args, 2);\n          }\n          return false;\n        default:\n          DEBUG_ASSERT(0 && \"Unknown parameter type\");\n      }\n    } else if (args[0][1] == '-') {\n      size_t equals = args[0].find('=');\n      size_t cmp_len = (equals == string::npos ? 9999 : equals) - 2;\n      if (cmp_len >= strlen(option_specs[i].long_name) &&\n          strncmp(args[0].c_str() + 2, option_specs[i].long_name, cmp_len) == 0) {\n        out->short_name = option_specs[i].short_name;\n        switch (option_specs[i].param) {\n          case NO_PARAMETER:\n            return consume_args(args, 1);\n          case HAS_PARAMETER:\n            if (equals == string::npos) {\n              if (args.size() >= 2) {\n                assign_param(out, args[1].c_str());\n                return consume_args(args, 2);\n              }\n              return false;\n            }\n            assign_param(out, args[0].c_str() + equals + 1);\n            return consume_args(args, 1);\n          default:\n            DEBUG_ASSERT(0 && \"Unknown parameter type\");\n        }\n      }\n    }\n  }\n\n  return false;\n}\n\nbool Command::verify_not_option(std::vector<std::string>& args) {\n  if (args.size() > 0 && args[0][0] == '-') {\n    if (args[0].length() == 2 && args[0][1] == '-') {\n      args.erase(args.begin());\n      return true;\n    }\n    fprintf(stderr, \"Invalid option %s\\n\", args[0].c_str());\n    return false;\n  }\n  return true;\n}\n\nbool Command::parse_optional_trace_dir(vector<string>& args, string* out) {\n  if (!verify_not_option(args)) {\n    return false;\n  }\n  if (args.size() > 0) {\n    *out = args[0];\n    args.erase(args.begin());\n  } else {\n    *out = string();\n  }\n  return true;\n}\n\nbool Command::parse_literal(std::vector<std::string>& args, const char* lit) {\n  if (args.size() > 0 && args[0] == lit) {\n    args.erase(args.begin());\n    return true;\n  } else {\n    return false;\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Command.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_COMMAND_H_\n#define RR_COMMAND_H_\n\n#ifndef _DEFAULT_SOURCE\n#define _DEFAULT_SOURCE 1\n#endif\n\n#include <stdint.h>\n#include <stdio.h>\n\n#include <memory>\n#include <string>\n#include <vector>\n\nnamespace rr {\n\nclass TraceReader;\n\nenum OptionParameters { NO_PARAMETER, HAS_PARAMETER };\nstruct OptionSpec {\n  char short_name;\n  const char* long_name;\n  OptionParameters param;\n};\nstruct ParsedOption {\n  char short_name;\n  std::string arg;\n  std::string value;\n  int64_t int_value;\n  bool verify_valid_int(int64_t min = INT64_MIN + 1,\n                        int64_t max = INT64_MAX) const;\n};\n\n/**\n * rr command-line commands. Objects of this class must be static, since\n * they are expected to be immortal.\n */\nclass Command {\npublic:\n  static Command* command_for_name(const std::string& name);\n  static void print_help_all(FILE* out);\n\n  /* Runs the command with the given parameters. Returns an exit code. */\n  virtual int run(std::vector<std::string>& args) = 0;\n  void print_help(FILE* out);\n\n  static bool verify_not_option(std::vector<std::string>& args);\n  static bool parse_optional_trace_dir(std::vector<std::string>& args,\n                                       std::string* out);\n  static bool parse_option(std::vector<std::string>& args,\n                           const OptionSpec* option_specs, size_t count,\n                           ParsedOption* out);\n  template <size_t N>\n  static bool parse_option(std::vector<std::string>& args,\n                           const OptionSpec (&option_specs)[N],\n                           ParsedOption* out) {\n    return parse_option(args, option_specs, N, out);\n  }\n  static bool parse_literal(std::vector<std::string>& args, const char* lit);\n\nprotected:\n  Command(const char* name, const char* help);\n  virtual ~Command() {}\n\n  static bool less_than_by_name(Command* c1, Command* c2);\n\n  const char* name;\n  const char* help;\n};\n\n} // namespace rr\n\n#endif // RR_COMMAND_H_\n"
  },
  {
    "path": "src/CompressedReader.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"CompressedReader.h\"\n\n#include <brotli/decode.h>\n#include <fcntl.h>\n#include <stdint.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"CompressedWriter.h\"\n#include \"core.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nCompressedReader::CompressedReader(const string& filename)\n    : fd(new ScopedFd(filename.c_str(), O_CLOEXEC | O_RDONLY | O_LARGEFILE)) {\n  fd_offset = 0;\n  error = !fd->is_open();\n  if (error) {\n    eof = false;\n  } else {\n    char ch;\n    eof = pread(*fd, &ch, 1, fd_offset) == 0;\n  }\n  buffer_read_pos = 0;\n  buffer_skip_bytes = 0;\n  have_saved_state = false;\n}\n\nCompressedReader::CompressedReader(const CompressedReader& other) {\n  fd = other.fd;\n  fd_offset = other.fd_offset;\n  error = other.error;\n  eof = other.eof;\n  buffer_read_pos = other.buffer_read_pos;\n  buffer_skip_bytes = other.buffer_skip_bytes;\n  buffer = other.buffer;\n  have_saved_state = false;\n  DEBUG_ASSERT(!other.have_saved_state);\n}\n\nCompressedReader::~CompressedReader() { close(); }\n\nstatic bool read_all(const ScopedFd& fd, size_t size, void* data,\n                     uint64_t* offset) {\n  ssize_t ret = read_to_end(fd, *offset, data, size);\n  if (ret == (ssize_t)size) {\n    *offset += size;\n    return true;\n  }\n  return false;\n}\n\nstatic bool do_decompress(std::vector<uint8_t>& compressed,\n                          std::vector<uint8_t>& uncompressed) {\n  size_t out_size = uncompressed.size();\n  return BrotliDecoderDecompress(compressed.size(), compressed.data(),\n                                 &out_size, uncompressed.data()) ==\n             BROTLI_DECODER_RESULT_SUCCESS &&\n         out_size == uncompressed.size();\n}\n\nbool CompressedReader::get_buffer(const uint8_t** data, size_t* size) {\n  process_skip();\n\n  if (error) {\n    return false;\n  }\n\n  if (buffer_read_pos >= buffer.size() && !eof) {\n    if (!refill_buffer()) {\n      return false;\n    }\n    DEBUG_ASSERT(buffer_read_pos < buffer.size());\n  }\n\n  *data = &buffer[buffer_read_pos];\n  *size = buffer.size() - buffer_read_pos;\n  return true;\n}\n\nvoid CompressedReader::process_skip() {\n  while (buffer_skip_bytes > 0 && !error) {\n    if (buffer_read_pos < buffer.size()) {\n      size_t amount = std::min(buffer_skip_bytes, buffer.size() - buffer_read_pos);\n      buffer_skip_bytes -= amount;\n      buffer_read_pos += amount;\n      continue;\n    }\n\n    if (!refill_buffer(&buffer_skip_bytes)) {\n      return;\n    }\n  }\n}\n\nbool CompressedReader::read(void* data, size_t size) {\n  process_skip();\n\n  while (size > 0) {\n    if (error) {\n      return false;\n    }\n\n    if (buffer_read_pos < buffer.size()) {\n      size_t amount = std::min(size, buffer.size() - buffer_read_pos);\n      memcpy(data, &buffer[buffer_read_pos], amount);\n      size -= amount;\n      data = static_cast<char*>(data) + amount;\n      buffer_read_pos += amount;\n      continue;\n    }\n\n    if (!refill_buffer()) {\n      return false;\n    }\n  }\n  return true;\n}\n\nbool CompressedReader::refill_buffer(size_t* skip_bytes) {\n  if (have_saved_state && !have_saved_buffer) {\n    std::swap(buffer, saved_buffer);\n    have_saved_buffer = true;\n  }\n\n  while (true) {\n    CompressedWriter::BlockHeader header;\n    if (!read_all(*fd, sizeof(header), &header, &fd_offset)) {\n      error = true;\n      return false;\n    }\n\n    if (skip_bytes && *skip_bytes >= header.uncompressed_length) {\n      fd_offset += header.compressed_length;\n      *skip_bytes -= header.uncompressed_length;\n      char ch;\n      if (pread(*fd, &ch, 1, fd_offset) == 0) {\n        eof = true;\n        return false;\n      }\n      continue;\n    }\n\n    std::vector<uint8_t> compressed_buf;\n    compressed_buf.resize(header.compressed_length);\n    if (!read_all(*fd, compressed_buf.size(), &compressed_buf[0], &fd_offset)) {\n      error = true;\n      return false;\n    }\n\n    char ch;\n    if (pread(*fd, &ch, 1, fd_offset) == 0) {\n      eof = true;\n    }\n\n    buffer.resize(header.uncompressed_length);\n    buffer_read_pos = 0;\n    if (!do_decompress(compressed_buf, buffer)) {\n      error = true;\n      return false;\n    }\n\n    return true;\n  }\n}\n\nvoid CompressedReader::rewind() {\n  DEBUG_ASSERT(!have_saved_state);\n  fd_offset = 0;\n  buffer_read_pos = 0;\n  buffer_skip_bytes = 0;\n  buffer.clear();\n  eof = false;\n}\n\nvoid CompressedReader::close() { fd = nullptr; }\n\nvoid CompressedReader::save_state() {\n  DEBUG_ASSERT(!have_saved_state);\n  process_skip();\n  have_saved_state = true;\n  have_saved_buffer = false;\n  saved_fd_offset = fd_offset;\n  saved_buffer_read_pos = buffer_read_pos;\n}\n\nvoid CompressedReader::restore_state() {\n  DEBUG_ASSERT(have_saved_state);\n  have_saved_state = false;\n  if (saved_fd_offset < fd_offset) {\n    eof = false;\n  }\n  fd_offset = saved_fd_offset;\n  if (have_saved_buffer) {\n    std::swap(buffer, saved_buffer);\n    saved_buffer.clear();\n  }\n  buffer_read_pos = saved_buffer_read_pos;\n  buffer_skip_bytes = 0;\n}\n\nvoid CompressedReader::discard_state() {\n  DEBUG_ASSERT(have_saved_state);\n  have_saved_state = false;\n  if (have_saved_buffer) {\n    saved_buffer.clear();\n  }\n}\n\nuint64_t CompressedReader::uncompressed_bytes() const {\n  uint64_t offset = 0;\n  uint64_t uncompressed_bytes = 0;\n  CompressedWriter::BlockHeader header;\n  while (read_all(*fd, sizeof(header), &header, &offset)) {\n    uncompressed_bytes += header.uncompressed_length;\n    offset += header.compressed_length;\n  }\n  return uncompressed_bytes;\n}\n\nuint64_t CompressedReader::compressed_bytes() const {\n  return lseek(*fd, 0, SEEK_END);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/CompressedReader.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_COMPRESSED_READER_H_\n#define RR_COMPRESSED_READER_H_\n\n#include <pthread.h>\n#include <stdint.h>\n\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"ScopedFd.h\"\n\nnamespace rr {\n\n/**\n * CompressedReader opens an input file written by CompressedWriter\n * and reads data from it. Currently data is decompressed by the thread that\n * calls read().\n */\nclass CompressedReader {\npublic:\n  CompressedReader(const std::string& filename);\n  CompressedReader(const CompressedReader& aOther);\n  ~CompressedReader();\n  bool good() const { return !error; }\n  bool at_end() const {\n    const_cast<CompressedReader*>(this)->process_skip();\n    return eof && buffer_read_pos == buffer.size();\n  }\n  // Returns true if successful. Otherwise there's an error and good()\n  // will be false.\n  bool read(void* data, size_t size);\n  // Returns pointer/size of some buffered data. Does not change the state.\n  // Returns zero size if at EOF.\n  bool get_buffer(const uint8_t** data, size_t* size);\n  // Advances the read position by the given size.\n  void skip(size_t size) {\n    buffer_skip_bytes += size;\n  }\n  void rewind();\n  void close();\n\n  /**\n   * Save the current position. Nested saves are not allowed.\n   */\n  void save_state();\n  /**\n   * Restore previously saved position.\n   */\n  void restore_state();\n  /**\n   * Discard saved position\n   */\n  void discard_state();\n\n  /**\n   * Gathers stats on the file stream. These are independent of what's\n   * actually been read.\n   */\n  uint64_t uncompressed_bytes() const;\n  uint64_t compressed_bytes() const;\n\nprotected:\n  void process_skip();\n  bool refill_buffer(size_t* skip_bytes = nullptr);\n\n  /* Our fd might be the dup of another fd, so we can't rely on its current file\n     position.\n     Instead track the current position in fd_offset and use pread. */\n  uint64_t fd_offset;\n  std::shared_ptr<ScopedFd> fd;\n  bool error;\n  bool eof;\n  std::vector<uint8_t> buffer;\n  // within `buffer`\n  size_t buffer_read_pos;\n  size_t buffer_skip_bytes;\n\n  bool have_saved_state;\n  bool have_saved_buffer;\n  uint64_t saved_fd_offset;\n  std::vector<uint8_t> saved_buffer;\n  size_t saved_buffer_read_pos;\n};\n\n} // namespace rr\n\n#endif /* RR_COMPRESSED_READER_H_ */\n"
  },
  {
    "path": "src/CompressedWriter.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"CompressedWriter.h\"\n\n#include <brotli/encode.h>\n#include <fcntl.h>\n#include <signal.h>\n#include <stdint.h>\n#include <string.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"core.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n/* See\n * http://robert.ocallahan.org/2017/07/selecting-compression-algorithm-for-rr.html\n */\nstatic const int BROTLI_LEVEL = 5;\n\nvoid* CompressedWriter::compression_thread_callback(void* p) {\n  static_cast<CompressedWriter*>(p)->compression_thread();\n  return nullptr;\n}\n\nCompressedWriter::CompressedWriter(const string& filename, size_t block_size,\n                                   uint32_t num_threads)\n    : fd(filename.c_str(),\n         O_CLOEXEC | O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE, 0400) {\n  this->block_size = block_size;\n  threads.resize(num_threads);\n  thread_pos.resize(num_threads);\n  buffer.resize(block_size * (num_threads + 2));\n  pthread_mutex_init(&mutex, nullptr);\n  pthread_cond_init(&cond, nullptr);\n\n  for (uint32_t i = 0; i < num_threads; ++i) {\n    thread_pos[i] = UINT64_MAX;\n  }\n  next_thread_pos = 0;\n  next_thread_end_pos = 0;\n  closing = false;\n  write_error = false;\n\n  producer_reserved_pos = 0;\n  producer_reserved_write_pos = 0;\n  producer_reserved_upto_pos = 0;\n  error = false;\n  if (fd < 0) {\n    error = true;\n    return;\n  }\n\n  // Make sure the compression threads block all signals\n  sigset_t set;\n  sigset_t old_mask;\n  sigfillset(&set);\n  sigprocmask(SIG_BLOCK, &set, &old_mask);\n  // Hold the lock so threads don't inspect the 'threads' array\n  // until we've finished initializing it.\n  pthread_mutex_lock(&mutex);\n  for (uint32_t i = 0; i < num_threads; ++i) {\n    while (true) {\n      int err = pthread_create(&threads[i], nullptr, compression_thread_callback, this);\n      if (err == EAGAIN) {\n        sched_yield(); // Give other processes a chance to exit.\n        continue;\n      } else if (err != 0) {\n        SAFE_FATAL(err, \"Failed to create compression threads!\");\n      }\n      break;\n    }\n    size_t last_slash = filename.rfind('/');\n    string thread_name =\n        string(\"compress \") + (last_slash == string::npos\n                                   ? filename\n                                   : filename.substr(last_slash + 1));\n    pthread_setname_np(threads[i], thread_name.substr(0, 15).c_str());\n  }\n  pthread_mutex_unlock(&mutex);\n  sigprocmask(SIG_SETMASK, &old_mask, nullptr);\n}\n\nCompressedWriter::~CompressedWriter() {\n  close();\n  pthread_mutex_destroy(&mutex);\n  pthread_cond_destroy(&cond);\n}\n\nvoid CompressedWriter::write(const void* data, size_t size) {\n  while (!error && size > 0) {\n    uint64_t reservation_size =\n        producer_reserved_upto_pos - producer_reserved_write_pos;\n    if (reservation_size == 0) {\n      update_reservation(WAIT);\n      continue;\n    }\n    size_t buf_offset = (size_t)(producer_reserved_write_pos % buffer.size());\n    size_t amount = min(buffer.size() - buf_offset,\n                        (size_t)min<uint64_t>(reservation_size, size));\n    memcpy(&buffer[buf_offset], data, amount);\n    producer_reserved_write_pos += amount;\n    data = static_cast<const char*>(data) + amount;\n    size -= amount;\n  }\n\n  if (!error &&\n      producer_reserved_write_pos - producer_reserved_pos >=\n          buffer.size() / 2) {\n    update_reservation(NOWAIT);\n  }\n}\n\nvoid CompressedWriter::update_reservation(WaitFlag wait_flag) {\n  pthread_mutex_lock(&mutex);\n\n  next_thread_end_pos = producer_reserved_write_pos;\n  producer_reserved_pos = producer_reserved_write_pos;\n\n  // Wake up threads that might be waiting to consume data.\n  pthread_cond_broadcast(&cond);\n\n  while (!error) {\n    if (write_error) {\n      error = true;\n      break;\n    }\n\n    uint64_t completed_pos = next_thread_pos;\n    for (uint32_t i = 0; i < thread_pos.size(); ++i) {\n      completed_pos = min(completed_pos, thread_pos[i]);\n    }\n    producer_reserved_upto_pos = completed_pos + buffer.size();\n    if (producer_reserved_pos < producer_reserved_upto_pos ||\n        wait_flag == NOWAIT) {\n      break;\n    }\n\n    pthread_cond_wait(&cond, &mutex);\n  }\n\n  pthread_mutex_unlock(&mutex);\n}\n\nvoid CompressedWriter::compression_thread() {\n  pthread_mutex_lock(&mutex);\n\n  int thread_index;\n  pthread_t self = pthread_self();\n  for (thread_index = 0; threads[thread_index] != self; ++thread_index) {\n  }\n\n  // Add slop for incompressible data\n  vector<uint8_t> outputbuf;\n  outputbuf.resize((size_t)(block_size * 1.1) + sizeof(BlockHeader));\n  BlockHeader* header = reinterpret_cast<BlockHeader*>(&outputbuf[0]);\n\n  while (true) {\n    if (!write_error && next_thread_pos < next_thread_end_pos &&\n        (closing || next_thread_pos + block_size <= next_thread_end_pos)) {\n      thread_pos[thread_index] = next_thread_pos;\n      next_thread_pos = min(next_thread_end_pos, next_thread_pos + block_size);\n      // header->uncompressed_length must be <= block_size,\n      // therefore fits in a size_t.\n      header->uncompressed_length =\n          (size_t)(next_thread_pos - thread_pos[thread_index]);\n\n      pthread_mutex_unlock(&mutex);\n      header->compressed_length =\n          do_compress(thread_pos[thread_index], header->uncompressed_length,\n                      &outputbuf[sizeof(BlockHeader)],\n                      outputbuf.size() - sizeof(BlockHeader));\n      pthread_mutex_lock(&mutex);\n\n      if (header->compressed_length == 0) {\n        write_error = true;\n      }\n\n      // wait until we're the next thread that needs to write\n      while (!write_error) {\n        bool other_thread_write_first = false;\n        for (uint32_t i = 0; i < thread_pos.size(); ++i) {\n          if (thread_pos[i] < thread_pos[thread_index]) {\n            other_thread_write_first = true;\n          }\n        }\n        if (!other_thread_write_first) {\n          break;\n        }\n        pthread_cond_wait(&cond, &mutex);\n      }\n\n      if (!write_error) {\n        pthread_mutex_unlock(&mutex);\n        write_all(fd, &outputbuf[0],\n                  sizeof(BlockHeader) + header->compressed_length);\n        pthread_mutex_lock(&mutex);\n      }\n\n      thread_pos[thread_index] = UINT64_MAX;\n      // do a broadcast because we might need to unblock\n      // the producer thread or a compressor thread waiting\n      // for us to write.\n      pthread_cond_broadcast(&cond);\n      continue;\n    }\n\n    if (closing && (write_error || next_thread_pos == next_thread_end_pos)) {\n      break;\n    }\n\n    pthread_cond_wait(&cond, &mutex);\n  }\n\n  pthread_mutex_unlock(&mutex);\n}\n\nvoid CompressedWriter::close(Sync sync) {\n  if (!fd.is_open()) {\n    return;\n  }\n\n  update_reservation(NOWAIT);\n\n  pthread_mutex_lock(&mutex);\n  closing = true;\n  pthread_cond_broadcast(&cond);\n  pthread_mutex_unlock(&mutex);\n\n  for (auto i = threads.begin(); i != threads.end(); ++i) {\n    pthread_join(*i, nullptr);\n  }\n\n  if (sync == SYNC) {\n    if (fsync(fd) < 0) {\n      error = true;\n    }\n  }\n\n  if (write_error) {\n    error = true;\n  }\n\n  fd.close();\n}\n\nsize_t CompressedWriter::do_compress(uint64_t offset, size_t length,\n                                     uint8_t* outputbuf, size_t outputbuf_len) {\n  BrotliEncoderState* state = BrotliEncoderCreateInstance(NULL, NULL, NULL);\n  if (!state) {\n    DEBUG_ASSERT(0 && \"BrotliEncoderCreateInstance failed\");\n  }\n  if (!BrotliEncoderSetParameter(state, BROTLI_PARAM_QUALITY, BROTLI_LEVEL)) {\n    DEBUG_ASSERT(0 && \"Brotli initialization failed\");\n  }\n\n  size_t ret = 0;\n  while (length > 0) {\n    size_t buf_offset = (size_t)(offset % buffer.size());\n    size_t amount = min(length, buffer.size() - buf_offset);\n    const uint8_t* in = &buffer[buf_offset];\n    if (!BrotliEncoderCompressStream(state, BROTLI_OPERATION_PROCESS, &amount,\n                                     &in, &outputbuf_len, &outputbuf, &ret)) {\n      DEBUG_ASSERT(0 && \"Brotli compression failed\");\n    }\n    size_t consumed = in - &buffer[buf_offset];\n    offset += consumed;\n    length -= consumed;\n  }\n  size_t zero = 0;\n  if (!BrotliEncoderCompressStream(state, BROTLI_OPERATION_FINISH, &zero, NULL,\n                                   &outputbuf_len, &outputbuf, &ret)) {\n    DEBUG_ASSERT(0 && \"Brotli compression failed\");\n  }\n\n  BrotliEncoderDestroyInstance(state);\n  return ret;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/CompressedWriter.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_COMPRESSED_WRITER_H_\n#define RR_COMPRESSED_WRITER_H_\n\n#include <pthread.h>\n#include <stdint.h>\n\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"ScopedFd.h\"\n\nnamespace rr {\n\n/**\n * CompressedWriter opens an output file and writes compressed blocks to it.\n * Blocks of a fixed but unspecified size (currently 1MB) are compressed.\n * Each block of compressed data is written to the file preceded by two\n * 32-bit words: the size of the compressed data (excluding block header)\n * and the size of the uncompressed data, in that order. See BlockHeader below.\n *\n * We use multiple threads to perform compression. The threads are\n * responsible for the actual data writes. The thread that creates the\n * CompressedWriter is the \"producer\" thread and must also be the caller of\n * 'write'. The producer thread may block in 'write' if 'buffer_size' bytes are\n * being compressed.\n *\n * Each data block is compressed independently using zlib.\n */\nclass CompressedWriter {\npublic:\n  CompressedWriter(const std::string& filename, size_t buffer_size,\n                   uint32_t num_threads);\n  ~CompressedWriter();\n  // Call only on producer thread\n  bool good() const { return !error; }\n  // Call only on producer thread.\n  void write(const void* data, size_t size);\n  enum Sync { DONT_SYNC, SYNC };\n  // Call only on producer thread\n  void close(Sync sync = DONT_SYNC);\n\n  struct BlockHeader {\n    uint32_t compressed_length;\n    uint32_t uncompressed_length;\n  };\n\nprotected:\n  enum WaitFlag { WAIT, NOWAIT };\n  void update_reservation(WaitFlag wait_flag);\n\n  static void* compression_thread_callback(void* p);\n  void compression_thread();\n  size_t do_compress(uint64_t offset, size_t length, uint8_t* outputbuf,\n                     size_t outputbuf_len);\n\n  // Immutable while threads are running\n  ScopedFd fd;\n  int block_size;\n  pthread_mutex_t mutex;\n  pthread_cond_t cond;\n  std::vector<pthread_t> threads;\n\n  // Carefully shared...\n  std::vector<uint8_t> buffer;\n\n  // BEGIN protected by 'mutex'\n  /* position in output stream that this thread is currently working on,\n   * or UINT64_MAX if it's idle */\n  std::vector<uint64_t> thread_pos;\n  /* position in output stream of data to dispatch to next thread */\n  uint64_t next_thread_pos;\n  /* position in output stream of end of data ready to dispatch */\n  uint64_t next_thread_end_pos;\n  bool closing;\n  bool write_error;\n  // END protected by 'mutex'\n\n  /* producer thread only */\n  /* Areas in the buffer that have been reserved for write() */\n  uint64_t producer_reserved_pos;\n  uint64_t producer_reserved_write_pos;\n  uint64_t producer_reserved_upto_pos;\n  bool error;\n};\n\n} // namespace rr\n\n#endif /* RR_COMPRESSED_WRITER_H_ */\n"
  },
  {
    "path": "src/ContextSwitchEvent.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ContextSwitchEvent.h\"\n\n#include <fcntl.h>\n#include <linux/perf_event.h>\n#include <signal.h>\n#include <stdint.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#include <optional>\n#include <string>\n\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic volatile int sigio_count;\n\nstatic void sigio_handler(int, siginfo_t*, void*) {\n  sigio_count += 1;\n}\n\nstatic bool can_use_switch_records() {\n  struct perf_event_attr attr;\n  memset(&attr, 0, sizeof(attr));\n  attr.size = sizeof(attr);\n  attr.type = PERF_TYPE_SOFTWARE;\n  attr.config = PERF_COUNT_SW_DUMMY;\n  attr.sample_period = 1;\n  attr.watermark = 1;\n  // We can't easily check PERF_RECORD_SWITCH directly\n  // because there's no reliable way (as far as I know) to\n  // force a context switch but still recover if no signal is\n  // generated. So we test that generating a PERF_RECORD_MMAP\n  // raises a signal instead.\n  attr.mmap_data = 1;\n  attr.wakeup_watermark = 1;\n  attr.exclude_kernel = 1;\n  attr.exclude_guest = 1;\n  attr.disabled = 1;\n\n  ScopedFd fd(syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0));\n  if (!fd.is_open()) {\n    LOG(warn) << \"Couldn't open a dummy event\";\n    return false;\n  }\n\n  PerfCounterBuffers buffers;\n  buffers.allocate(fd, page_size(), 0);\n\n  int ret = fcntl(fd, F_SETFL, FASYNC);\n  if (ret < 0) {\n    FATAL() << \"Can't make fd async\";\n  }\n  struct f_owner_ex own;\n  own.type = F_OWNER_TID;\n  own.pid = syscall(SYS_gettid);\n  ret = fcntl(fd, F_SETOWN_EX, &own);\n  if (ret < 0) {\n    FATAL() << \"Failed to fcntl(SETOWN_EX)\";\n  }\n\n  struct sigaction sa;\n  struct sigaction old_sa;\n  sa.sa_sigaction = sigio_handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  ret = sigaction(SIGIO, &sa, &old_sa);\n  if (ret < 0) {\n    FATAL() << \"Failed to install sighandler\";\n  }\n\n  sigio_count = 0;\n  ret = ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);\n  if (ret < 0) {\n    FATAL() << \"Failed to enable event\";\n  }\n  void* p = mmap(nullptr, 1, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  if (p == MAP_FAILED) {\n    FATAL() << \"Failed to mmap\";\n  }\n  ret = ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);\n  if (ret < 0) {\n    FATAL() << \"Failed to disable event\";\n  }\n\n  ret = munmap(p, 1);\n  if (ret < 0) {\n    FATAL() << \"Failed to munmap\";\n  }\n  ret = sigaction(SIGIO, &old_sa, nullptr);\n  if (ret < 0) {\n    FATAL() << \"Failed to clean up sighandler\";\n  }\n\n  if (sigio_count == 0) {\n    // Old kernel\n    LOG(info) << \"PERF_RECORD_MMAP watermark failed to deliver signal\";\n    return false;\n  }\n  if (sigio_count > 1) {\n    FATAL() << \"Invalid SIGIO count\";\n  }\n\n  return true;\n}\n\nstatic ContextSwitchEventStrategy init_strategy() {\n  if (has_effective_caps(uint64_t(1) << CAP_SYS_ADMIN) ||\n      has_effective_caps(uint64_t(1) << CAP_PERFMON)) {\n    return ContextSwitchEventStrategy::STRATEGY_SW_CONTEXT_SWITCHES;\n  }\n  optional<int> perf_event_paranoid = read_perf_event_paranoid();\n  if (perf_event_paranoid.has_value() && *perf_event_paranoid <= 1) {\n    return ContextSwitchEventStrategy::STRATEGY_SW_CONTEXT_SWITCHES;\n  }\n\n  if (can_use_switch_records()) {\n    return ContextSwitchEventStrategy::STRATEGY_RECORD_SWITCH;\n  }\n\n  string paranoid_value = \"unknown\";\n  if (perf_event_paranoid.has_value()) {\n    paranoid_value = std::to_string(*perf_event_paranoid);\n  }\n  CLEAN_FATAL() <<\n      \"rr needs /proc/sys/kernel/perf_event_paranoid <= 1, but it is \"\n          << paranoid_value << \".\\n\"\n          << \"Change it to 1, or use 'rr record -n' (slow).\\n\"\n          << \"Consider putting 'kernel.perf_event_paranoid = 1' in /etc/sysctl.d/10-rr.conf.\\n\"\n          << \"See 'man 8 sysctl', 'man 5 sysctl.d' (systemd systems)\\n\"\n          << \"and 'man 5 sysctl.conf' (non-systemd systems) for more details.\";\n  return ContextSwitchEventStrategy::STRATEGY_SW_CONTEXT_SWITCHES;\n}\n\nContextSwitchEventStrategy ContextSwitchEvent::strategy() {\n  static ContextSwitchEventStrategy strat = init_strategy();\n  return strat;\n}\n\nbool ContextSwitchEvent::init(ScopedFd tracee_fd) {\n  tracee_fd_ = std::move(tracee_fd);\n  if (strategy() == ContextSwitchEventStrategy::STRATEGY_RECORD_SWITCH) {\n    mmap_buffer = make_unique<PerfCounterBuffers>();\n    bool ok = false;\n    mmap_buffer->allocate(tracee_fd_, page_size(), 0, &ok);\n    return ok;\n  }\n  return true;\n}\n\nvoid ContextSwitchEvent::drain_events() {\n  if (mmap_buffer) {\n    while (auto packet = mmap_buffer->next_packet()) {\n    }\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ContextSwitchEvent.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_CONTEXT_SWITCH_EVENT_H_\n#define RR_CONTEXT_SWITCH_EVENT_H_\n\n#include <stdint.h>\n\n#include <memory>\n\n#include \"PerfCounterBuffers.h\"\n#include \"ScopedFd.h\"\n#include \"preload/preload_interface.h\"\n\nnamespace rr {\n\n/**\n * For syscall buffering, we need to interrupt a tracee when it would block.\n * We do this by configuring a perf event to detect when the tracee is subject\n * to a context switch. When the perf event fires, it delivers a signal to the\n * tracee. The tracee syscallbuf code allocates the event fd and rr retrieves\n * it. We do it that way because both the tracee and rr need access to the\n * event fd.\n *\n * We can use `PERF_COUNT_SW_CONTEXT_SWITCHES` as the event. This is easy but\n * since it's a kernel event, unprivileged rr can't use it when\n * `perf_event_paranoid` is >= 2.\n *\n * Alternatively we can configure a dummy event and observe `PERF_RECORD_SWITCH`\n * records. This works with unprivileged rr when `perf_event_paranoid` == 2.\n * To trigger a signal when we get a `PERF_RECORD_SWITCH`, we set\n * `wakeup_watermark` so that appending any record to the ring buffer triggers\n * a wakeup. This requries configuring a ring buffer per tracee task; we can't\n * use a single ring buffer for multiple tracees, since when a tracee blocks\n * we need to send a signal directly to that specific tracee, not any others\n * and not rr. (We could deliver to rr and have rr interrupt the right tracee\n * but that would be slow.)\n * Unfortunately, in Linux kernels before 6.10, `watermark_wakeup` doesn't\n * trigger signals associated with the event fd. This bug was fixed in 6.10.\n *\n * So this class manages all the necessary logic. In particular we have to figure\n * out which strategy to use. We prefer to use `PERF_COUNT_SW_CONTEXT_SWITCHES`\n * if possible since we don't have to allocate ring buffers for those, so we'll\n * first check if that works. If it doesn't, we'll test if `PERF_RECORD_SWITCH`\n * works properly. If it doesn't, we produce the right error message and abort.\n * Then, if we're using `PERF_RECORD_SWITCH`, we need to allocate the ring buffer\n * and configure `wakeup_watermark`.\n */\nclass ContextSwitchEvent {\npublic:\n  bool init(ScopedFd tracee_fd);\n\n  ScopedFd& tracee_fd() { return tracee_fd_; }\n\n  // We need to determine the strategy before we configure syscallbuf to create\n  // its tracee perf event fds.\n  static ContextSwitchEventStrategy strategy();\n\n  void drain_events();\n\nprivate:\n  // The fd retrieved from the tracee task that created it.\n  ScopedFd tracee_fd_;\n  // If we're using `PERF_RECORD_SWITCH` records, the\n  // buffer we're using to trigger the watermark-wakeups.\n  std::unique_ptr<PerfCounterBuffers> mmap_buffer;\n};\n\n} // namespace rr\n\n#endif /* RR_CONTEXT_SWITCH_EVENT_H_ */\n"
  },
  {
    "path": "src/DebuggerExtensionCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"DebuggerExtensionCommand.h\"\n\n#include \"ReplayTask.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic SimpleDebuggerExtensionCommand elapsed_time(\n    \"elapsed-time\",\n    \"Print elapsed time (in seconds) since the start of the trace, in the\"\n    \" 'record' timeline.\",\n    [](GdbServer&, Task* t, const vector<string>&) {\n      if (!t->session().is_replaying()) {\n        return DebuggerExtensionCommandHandler::cmd_end_diversion();\n      }\n\n      ReplayTask* replay_t = static_cast<ReplayTask*>(t);\n      double elapsed_time = replay_t->current_trace_frame().monotonic_time() -\n                            replay_t->session().get_trace_start_time();\n\n      return string(\"Elapsed Time (s): \") + to_string(elapsed_time);\n    });\n\nstatic SimpleDebuggerExtensionCommand when(\n    \"when\", \"Print the number of the last completely replayed rr event.\",\n    [](GdbServer&, Task* t, const vector<string>&) {\n      if (!t->session().is_replaying()) {\n        return DebuggerExtensionCommandHandler::cmd_end_diversion();\n      }\n      // The current event has not been completely replayed, so\n      // we report the number of the previuos event.\n      return string(\"Completed event: \") +\n             to_string(\n                 static_cast<ReplayTask*>(t)->current_trace_frame().time() - 1);\n    });\n\nstatic SimpleDebuggerExtensionCommand when_ticks(\n    \"when-ticks\", \"Print the current rr tick count for the current thread.\",\n    [](GdbServer&, Task* t, const vector<string>&) {\n      if (!t->session().is_replaying()) {\n        return DebuggerExtensionCommandHandler::cmd_end_diversion();\n      }\n      return string(\"Current tick: \") + to_string(t->tick_count());\n    });\n\nstatic SimpleDebuggerExtensionCommand when_tid(\n    \"when-tid\", \"Print the real tid for the current thread.\",\n    [](GdbServer&, Task* t, const vector<string>&) {\n      if (!t->session().is_replaying()) {\n        return DebuggerExtensionCommandHandler::cmd_end_diversion();\n      }\n      return string(\"Current tid: \") + to_string(t->tid);\n    });\n\nstatic std::vector<ReplayTimeline::Mark> back_stack;\nstatic ReplayTimeline::Mark current_history_cp;\nstatic std::vector<ReplayTimeline::Mark> forward_stack;\nstatic SimpleDebuggerExtensionCommand rr_history_push(\n    \"rr-history-push\", \"Push an entry into the rr history.\",\n    [](GdbServer& gdb_server, Task* t, const vector<string>&) {\n      if (!gdb_server.timeline()) {\n        return string(\"Command requires a full debugging session.\");\n      }\n      if (!t->session().is_replaying()) {\n        // Don't create new history state inside a diversion\n        return string();\n      }\n      if (current_history_cp) {\n        back_stack.push_back(current_history_cp);\n      }\n      current_history_cp = gdb_server.timeline()->mark();\n      forward_stack.clear();\n      return string();\n    });\nstatic SimpleDebuggerExtensionCommand back(\n    \"back\", \"Go back one entry in the rr history.\",\n    [](GdbServer& gdb_server, Task* t, const vector<string>&) {\n      if (!gdb_server.timeline()) {\n        return string(\"Command requires a full debugging session.\");\n      }\n      if (!t->session().is_replaying()) {\n        return DebuggerExtensionCommandHandler::cmd_end_diversion();\n      }\n      if (back_stack.size() == 0) {\n        return string(\"Can't go back. No more history entries.\");\n      }\n      forward_stack.push_back(current_history_cp);\n      current_history_cp = back_stack.back();\n      back_stack.pop_back();\n      gdb_server.timeline()->seek_to_mark(current_history_cp);\n      return string();\n    });\nstatic SimpleDebuggerExtensionCommand forward(\n    \"forward\", \"Go forward one entry in the rr history.\",\n    [](GdbServer& gdb_server, Task* t, const vector<string>&) {\n      if (!gdb_server.timeline()) {\n        return string(\"Command requires a full debugging session.\");\n      }\n      if (!t->session().is_replaying()) {\n        return DebuggerExtensionCommandHandler::cmd_end_diversion();\n      }\n      if (forward_stack.size() == 0) {\n        return string(\"Can't go forward. No more history entries.\");\n      }\n      back_stack.push_back(current_history_cp);\n      current_history_cp = forward_stack.back();\n      forward_stack.pop_back();\n      gdb_server.timeline()->seek_to_mark(current_history_cp);\n      return string();\n    });\n\nstatic int gNextCheckpointId = 0;\n\nstring invoke_checkpoint(GdbServer& gdb_server, Task*,\n                         const vector<string>& args) {\n  if (!gdb_server.timeline()) {\n    return string(\"Command requires a full debugging session.\");\n  }\n  const string& where = args[0];\n  if (gdb_server.in_debuggee_end_state) {\n    return string(\"The program is not being run.\");\n  }\n  int checkpoint_id = ++gNextCheckpointId;\n  GdbServer::Checkpoint::Explicit e;\n  if (gdb_server.timeline()->can_add_checkpoint()) {\n    e = GdbServer::Checkpoint::EXPLICIT;\n  } else {\n    e = GdbServer::Checkpoint::NOT_EXPLICIT;\n  }\n  gdb_server.checkpoints[checkpoint_id] = GdbServer::Checkpoint(\n      *gdb_server.timeline(), gdb_server.last_continue_task, e, where);\n  return string(\"Checkpoint \") + to_string(checkpoint_id) + \" at \" + where;\n}\nstatic SimpleDebuggerExtensionCommand checkpoint(\n  \"checkpoint\",\n  \"create a checkpoint representing a point in the execution\\n\"\n  \"use the 'restart' command to return to the checkpoint\",\n  invoke_checkpoint);\n\nstring invoke_delete_checkpoint(GdbServer& gdb_server, Task*,\n                                const vector<string>& args) {\n  if (args.size() < 1) {\n    return \"'delete checkpoint' requires an argument\";\n  }\n  if (!gdb_server.timeline()) {\n    return string(\"Command requires a full debugging session.\");\n  }\n  char* endptr;\n  long id = strtol(args[0].c_str(), &endptr, 10);\n  if (*endptr) {\n    return string(\"Invalid checkpoint number \") + args[0] + \".\";\n  }\n  auto it = gdb_server.checkpoints.find(id);\n  if (it != gdb_server.checkpoints.end()) {\n    if (it->second.is_explicit == GdbServer::Checkpoint::EXPLICIT) {\n      gdb_server.timeline()->remove_explicit_checkpoint(it->second.mark);\n    }\n    gdb_server.checkpoints.erase(it);\n    return string(\"Deleted checkpoint \") + to_string(id) + \".\";\n  } else {\n    return string(\"No checkpoint number \") + to_string(id) + \".\";\n  }\n}\nstatic SimpleDebuggerExtensionCommand delete_checkpoint(\n  \"delete checkpoint\",\n  \"remove a checkpoint created with the 'checkpoint' command\",\n  invoke_delete_checkpoint);\n\nstring invoke_info_checkpoints(GdbServer& gdb_server, Task*,\n                               const vector<string>&) {\n  if (gdb_server.checkpoints.size() == 0) {\n    return \"No checkpoints.\";\n  }\n  string out = \"ID\\tWhen\\tWhere\";\n  for (auto& c : gdb_server.checkpoints) {\n    out += string(\"\\n\") + to_string(c.first) + \"\\t\" +\n           to_string(c.second.mark.time()) + \"\\t\" + c.second.where;\n  }\n  return out;\n}\nstatic SimpleDebuggerExtensionCommand info_checkpoints(\n  \"info checkpoints\",\n  \"list all checkpoints created with the 'checkpoint' command\",\n  invoke_info_checkpoints);\n\nvoid DebuggerExtensionCommand::init_auto_args() {\n  static __attribute__((unused)) int dummy = []() {\n    checkpoint.add_auto_arg(\"rr-where\");\n    return 0;\n  }();\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/DebuggerExtensionCommand.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_DEBUGGER_EXTENSION_COMMAND_H_\n#define RR_DEBUGGER_EXTENSION_COMMAND_H_\n\n#include \"DebuggerExtensionCommandHandler.h\"\n#include \"GdbServer.h\"\n\n#include <sstream>\n#include <string>\n#include <vector>\n\nnamespace rr {\n\nclass DebuggerExtensionCommand {\nprotected:\n  DebuggerExtensionCommand(const std::string& cmd_name, const std::string& documentation)\n      : cmd_name(cmd_name), documentation(documentation) {\n    DebuggerExtensionCommandHandler::register_command(*this);\n  }\n\npublic:\n  virtual ~DebuggerExtensionCommand() {}\n\n  const std::string& name() const { return cmd_name; }\n  const std::string& docs() const { return documentation; }\n\n  /**\n   * Handle the RR Cmd and return a string response to be echo'd\n   * to the user.\n   *\n   * NOTE: args[0] is the command name\n   */\n  virtual std::string invoke(GdbServer& gdb_server, Task* t,\n                             const std::vector<std::string>& args) = 0;\n\n  /**\n   * When called, gdb will automatically run gdb.execute() on this string and\n   * pass it as an argument to the rr command. This is useful to pass gdb\n   * state alongside the command invocation.\n   */\n  void add_auto_arg(const std::string& auto_arg) {\n    cmd_auto_args.push_back(auto_arg);\n  }\n\n  const std::vector<std::string>& auto_args() const { return cmd_auto_args; }\n\n  /**\n   * Setup all the automatic auto_args for our commands.\n   */\n  static void init_auto_args();\n\nprivate:\n  const std::string cmd_name;\n  const std::string documentation;\n  std::vector<std::string> cmd_auto_args;\n};\n\nclass SimpleDebuggerExtensionCommand : public DebuggerExtensionCommand {\npublic:\n  SimpleDebuggerExtensionCommand(\n      const std::string& cmd_name, const std::string& documentation,\n      const std::function<std::string(\n          GdbServer&, Task* t, const std::vector<std::string>&)>& invoker)\n      : DebuggerExtensionCommand(cmd_name, documentation), invoker(invoker) {}\n\n  virtual std::string invoke(GdbServer& gdb_server, Task* t,\n                             const std::vector<std::string>& args) override {\n    return invoker(gdb_server, t, args);\n  }\n\n  std::function<std::string(GdbServer&, Task* t,\n                            const std::vector<std::string>&)>\n      invoker;\n};\n\n} // namespace rr\n\n#endif /* RR_DEBUGGER_EXTENSION_COMMAND_H_ */\n"
  },
  {
    "path": "src/DebuggerExtensionCommandHandler.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"DebuggerExtensionCommandHandler.h\"\n#include \"DebuggerExtensionCommand.h\"\n#include \"log.h\"\n\n#include <sstream>\n#include <vector>\n\nusing namespace std;\n\nnamespace rr {\n\n// HashMap would be better here but the unordered_map API is annoying\n// and linear search is fine.\nstatic vector<DebuggerExtensionCommand*>* debugger_command_list;\n\nstatic void print_python_string_array(ostream& out, const std::vector<std::string>& strs) {\n  out << \"[\";\n  for (size_t i = 0; i < strs.size(); i++) {\n    if (i > 0) {\n      out << \", \";\n    }\n    out << \"'\" << strs[i] << \"'\";\n  }\n  out << \"]\";\n}\n\nstatic void gdb_macro_binding(ostream& out, const DebuggerExtensionCommand& cmd) {\n  out << \"python RRCmd('\" << cmd.name() << \"', \";\n  print_python_string_array(out, cmd.auto_args());\n  out << \")\\n\";\n  if (!cmd.docs().empty()) {\n    out << \"document \" << cmd.name() << \"\\n\" << cmd.docs() << \"\\nend\\n\";\n  }\n}\n\nstatic const char shared_python[] = R\"Delimiter(\ndef hex_unescape(string):\n    str_len = len(string)\n    if str_len % 2: # check for unexpected string length\n        return \"\"\n    result = bytearray()\n    try:\n        pos = 0\n        while pos < str_len:\n            hex_char = string[pos:pos+2]\n            result.append(int(hex_char, 16))\n            pos += 2\n    except: # check for unexpected string value\n        return \"\"\n    return result.decode('utf-8')\n\ndef hex_escape(string):\n    result = \"\"\n    for curr_char in string.encode('utf-8'):\n        if isinstance(curr_char, str):\n            curr_char = ord(curr_char)\n        result += format(curr_char, '02x')\n    return result\n)Delimiter\";\n\nstring DebuggerExtensionCommandHandler::gdb_macros() {\n  DebuggerExtensionCommand::init_auto_args();\n  stringstream ss;\n  ss << R\"Delimiter(set python print-stack full\npython\nimport re\n)Delimiter\"\n    << shared_python\n    << R\"Delimiter(\nclass RRWhere(gdb.Command):\n    \"\"\"Helper to get the location for checkpoints/history. Used by auto-args\"\"\"\n    def __init__(self):\n        gdb.Command.__init__(self, 'rr-where',\n                             gdb.COMMAND_USER, gdb.COMPLETE_NONE, False)\n\n    def invoke(self, arg, from_tty):\n#Get the symbol name from 'frame 0' in the format:\n# '#0  0x00007f9d81a04c46 in _dl_start (arg=0x7ffee1f1c740) at rtld.c:356\n# 356 in rtld.c'\n        try:\n            rv = gdb.execute('frame 0', to_string=True)\n        except:\n            rv = \"???\" # This may occurs if we're not running\n        m = re.match(r\"#0\\w*(.*)\", rv);\n        if m:\n            rv = m.group(1)\n        else:\n            rv = rv + \"???\"\n        gdb.write(rv)\n\nRRWhere()\n\nclass RRDenied(gdb.Command):\n    \"\"\"Helper to prevent use of breaking commands. Used by auto-args\"\"\"\n    def __init__(self):\n        gdb.Command.__init__(self, 'rr-denied',\n                             gdb.COMMAND_USER, gdb.COMPLETE_NONE, False)\n\n    def invoke(self, arg, from_tty):\n        raise gdb.GdbError(\"Execution of '\" + arg + \"' is not possible in recorded executions.\")\n\nRRDenied()\n\nclass RRCmd(gdb.Command):\n    def __init__(self, name, auto_args):\n        gdb.Command.__init__(self, name,\n                             gdb.COMMAND_USER, gdb.COMPLETE_NONE, False)\n        self.cmd_name = name\n        self.auto_args = auto_args\n\n    def invoke(self, arg, from_tty):\n        args = gdb.string_to_argv(arg)\n        self.rr_cmd(args)\n\n    def rr_cmd(self, args):\n        # Ensure gdb tells rr its current thread\n        curr_thread = gdb.selected_thread()\n        cmd_prefix = (\"maint packet qRRCmd:%s:%d\"%\n            (self.cmd_name, -1 if curr_thread is None else curr_thread.ptid[1]))\n        arg_strs = []\n        for auto_arg in self.auto_args:\n            arg_strs.append(\":\" + hex_escape(gdb.execute(auto_arg, to_string=True)))\n        for arg in args:\n            arg_strs.append(\":\" + hex_escape(arg))\n        rv = gdb.execute(cmd_prefix + ''.join(arg_strs), to_string=True);\n        rv_match = re.search('received: \"(.*)\"', rv, re.MULTILINE);\n        if not rv_match:\n            gdb.write(\"Response error: \" + rv)\n            return\n        response = hex_unescape(rv_match.group(1))\n        if response != '\\n':\n            gdb.write(response)\n\ndef history_push(p):\n    # ensure any output (e.g. produced by breakpoint commands running during our\n    # processing, that were triggered by the stop we've been notified for)\n    # is echoed as normal.\n    gdb.execute(\"rr-history-push\")\n\nrr_suppress_run_hook = False\n\nclass RRHookRun(gdb.Command):\n    def __init__(self):\n        gdb.Command.__init__(self, 'rr-hook-run',\n                             gdb.COMMAND_USER, gdb.COMPLETE_NONE, False)\n        \n    def invoke(self, arg, from_tty):  \n      thread = int(gdb.parse_and_eval(\"$_thread\"))\n      if thread != 0 and not rr_suppress_run_hook:\n        gdb.execute(\"stepi\")\n     \nclass RRSetSuppressRunHook(gdb.Command):\n    def __init__(self):\n        gdb.Command.__init__(self, 'rr-set-suppress-run-hook',\n                             gdb.COMMAND_USER, gdb.COMPLETE_NONE, False)\n        \n    def invoke(self, arg, from_tty):\n      rr_suppress_run_hook = arg == '1'\n\nRRHookRun()\nRRSetSuppressRunHook()\n\n#Automatically push an history entry when the program execution stops\n#(signal, breakpoint).This is fired before an interactive prompt is shown.\n#Disabled for now since it's not fully working.\ngdb.events.stop.connect(history_push)\n\nend\n)Delimiter\";\n\n  if (debugger_command_list) {\n    for (auto& it : *debugger_command_list) {\n      gdb_macro_binding(ss, *it);\n    }\n  }\n\n  ss << string(R\"Delimiter(\ndefine hookpost-back\nmaintenance flush register-cache\nframe\nend\n\ndefine hookpost-forward\nmaintenance flush register-cache\nframe\nend\n)Delimiter\");\n\n  return ss.str();\n}\n\nstatic void lldb_macro_binding(ostream& def_stream, ostream& call_stream,\n                               const string* module_name,\n                               const DebuggerExtensionCommand& cmd) {\n  string func_name = \"rr_command_\";\n  for (char ch : cmd.name()) {\n    if (ch == ' ') {\n      // We don't support commands with spaces in LLDB yet\n      return;\n    }\n    if (ch == '-') {\n      ch = '_';\n    }\n    func_name.push_back(ch);\n  }\n  def_stream << \"def \" << func_name << \"(debugger, command, exe_ctx, result, internal_dict):\\n\";\n  if (!cmd.docs().empty()) {\n    def_stream << \"    \\\"\\\"\\\"\" << cmd.docs() << \"\\\"\\\"\\\"\\n\";\n  }\n  def_stream << \"    cmd_name = '\" << cmd.name() << \"'\\n\"\n             << \"    auto_args = \";\n  print_python_string_array(def_stream, cmd.auto_args());\n  def_stream << \"\\n\"\n             << \"    command_impl(debugger, command, exe_ctx, result, cmd_name, auto_args)\\n\"\n             << \"\\n\";\n  call_stream << \"    debugger.HandleCommand('command script add -f \";\n  if (module_name) {\n    call_stream << *module_name << \".\";\n  }\n  call_stream << func_name << \" \" << cmd.name() << \"')\\n\";\n}\n\nDebuggerExtensionCommandHandler::LldbCommands\nDebuggerExtensionCommandHandler::lldb_python_macros(const string* module_name) {\n  DebuggerExtensionCommand::init_auto_args();\n  stringstream ss;\n  ss << R\"Delimiter(import lldb\nimport re\nimport shlex\n)Delimiter\"\n     << shared_python\n     << R\"Delimiter(\ndef run_command_and_get_output(debugger, command):\n    result = lldb.SBCommandReturnObject()\n    debugger.GetCommandInterpreter().HandleCommand(command, result)\n    assert result.Succeeded()\n    return result.GetOutput()\n\ndef command_impl(debugger, command, exe_ctx, result, cmd_name, auto_args):\n    interpreter = debugger.GetCommandInterpreter()\n    args = shlex.split(command)\n    # Ensure lldb tells rr its current thread\n    curr_thread = exe_ctx.thread\n    cmd_prefix = (\"process plugin packet send qRRCmd:%s:%d\"%\n        (cmd_name, -1 if curr_thread is None else curr_thread.GetThreadID()))\n    arg_strs = []\n    for auto_arg in auto_args:\n        arg_strs.append(\":\" + hex_escape(run_command_and_get_output(debugger, auto_arg)))\n    for arg in args:\n        arg_strs.append(\":\" + hex_escape(arg))\n    rv = run_command_and_get_output(debugger, cmd_prefix + ''.join(arg_strs));\n    rv_match = re.search('response: (.*)$', rv, re.MULTILINE);\n    if not rv_match:\n        result.SetError(None, \"Invalid response: %s\" % rv)\n        return\n    response = hex_unescape(rv_match.group(1))\n    result.Print(response.strip())\n\n)Delimiter\";\n\n  stringstream call_stream;\n  if (debugger_command_list) {\n    for (auto& it : *debugger_command_list) {\n      lldb_macro_binding(ss, call_stream, module_name, *it);\n    }\n  }\n  LldbCommands cmds;\n  cmds.toplevel_definitions = ss.str();\n  cmds.run_on_startup = call_stream.str();\n  return cmds;\n}\n\n/*static*/ DebuggerExtensionCommand* DebuggerExtensionCommandHandler::command_for_name(const string& name) {\n  if (!debugger_command_list) {\n    return nullptr;\n  }\n  for (auto& it : *debugger_command_list) {\n    if (it->name() == name) {\n      return it;\n    }\n  }\n  return nullptr;\n}\n\nvoid DebuggerExtensionCommandHandler::register_command(DebuggerExtensionCommand& cmd) {\n  LOG(debug) << \"registering command: \" << cmd.name();\n  if (!debugger_command_list) {\n    debugger_command_list = new vector<DebuggerExtensionCommand*>();\n  }\n  debugger_command_list->push_back(&cmd);\n}\n\n// applies the simplest two hex character by byte encoding\nstatic string hex_escape(const string& str) {\n  stringstream ss;\n  ss << hex;\n  const size_t len = str.size();\n  const char *data = str.data();\n  for (size_t i = 0; i < len; i++) {\n    int chr = (uint8_t)data[i];\n    if (chr < 16) {\n      ss << \"0\";\n    }\n    ss << chr;\n  }\n  return ss.str();\n}\n// undo the two hex character byte encoding,\n// in case of error returns an empty string\nstatic string hex_unescape(const string& str) {\n  const size_t len = str.size();\n  // check for unexpected string length\n  if (len % 2) {\n    return \"\";\n  }\n  stringstream ss;\n  for (size_t i = 0; i < len; i += 2) {\n    string substr = str.substr(i, 2);\n    const char *hex_str = substr.c_str();\n    char *ptr = nullptr;\n    ss << (char)strtoul(hex_str, &ptr, 16);\n    // check for unexpected character\n    if (*ptr) {\n      return \"\";\n    }\n  }\n  return ss.str();\n}\n\n/* static */ string DebuggerExtensionCommandHandler::process_command(GdbServer& gdb_server,\n                                                       Task* t,\n                                                       const GdbRequest::RRCmd& rr_cmd) {\n  vector<string> args;\n  for (const auto& arg : rr_cmd.args) {\n    args.push_back(hex_unescape(arg));\n  }\n\n  DebuggerExtensionCommand* cmd = command_for_name(rr_cmd.name);\n  if (!cmd) {\n    return hex_escape(string() + \"Command '\" + rr_cmd.name + \"' not found.\\n\");\n  }\n  LOG(debug) << \"invoking command: \" << cmd->name();\n  Task* target = t->session().find_task(rr_cmd.target_tid);\n  \n  // perhaps not the best option, but better than a nullptr\n  if (target == nullptr) target = t;\n  \n  string resp = cmd->invoke(gdb_server, target, args);\n\n  if (resp == DebuggerExtensionCommandHandler::cmd_end_diversion()) {\n    LOG(debug) << \"cmd must run outside of diversion (\" << resp << \")\";\n    return resp;\n  }\n\n  LOG(debug) << \"cmd response: \" << resp;\n  return hex_escape(resp + \"\\n\");\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/DebuggerExtensionCommandHandler.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_DEBUGGER_EXTENSION_COMMAND_HANDLER_H_\n#define RR_DEBUGGER_EXTENSION_COMMAND_HANDLER_H_\n\n#include <string>\n\n#include \"GdbServerConnection.h\"\n\nnamespace rr {\n\nclass DebuggerExtensionCommand;\nclass GdbServer;\nclass Task;\n\n/**\n * rr extends debuggers (GDB, LLDB) with custom commands such as `when`.\n * This class manages those commands.\n */\nclass DebuggerExtensionCommandHandler {\npublic:\n  // Declare any registered command with supporting\n  // wrapper code --- GDB script.\n  static std::string gdb_macros();\n\n  // Declare any registered command with supporting\n  // wrapper code --- LLDB Python script.\n  struct LldbCommands {\n    std::string toplevel_definitions;\n    // 2-space-indented code to run on startup.\n    std::string run_on_startup;\n  };\n  static LldbCommands lldb_python_macros(const string* module_name);\n\n  static void register_command(DebuggerExtensionCommand& cmd);\n\n  /**\n   * Process an incoming debugger payload of the following form:\n   *   <command name>:<arg1>:<arg2>:...\n   *\n   * NOTE: RR Command are typically sent with the qRRCmd: prefix which\n   * should of been striped already.\n   */\n  static std::string process_command(GdbServer& gdb_server, Task* t,\n                                     const GdbRequest::RRCmd& rr_cmd);\n\n  static DebuggerExtensionCommand* command_for_name(const std::string& name);\n\n  /**\n   * Special return value for commands that immediately end a diversion session\n   */\n  static std::string cmd_end_diversion() {\n    return std::string(\"RRCmd_EndDiversion\");\n  }\n\nprivate:\n};\n\n} // namespace rr\n\n#endif /* RR_DEBUGGER_EXTENSION_COMMAND_HANDLER_H_ */\n"
  },
  {
    "path": "src/DiversionSession.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"DiversionSession.h\"\n\n#include <linux/prctl.h>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"ReplaySession.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nDiversionSession::DiversionSession(BindCPU cpu_binding) :\n  emu_fs(EmuFs::create()), fake_timer_counter(uint64_t(1) << 60), cpu_binding_(cpu_binding) {}\n\nDiversionSession::~DiversionSession() {\n  // We won't permanently leak any OS resources by not ensuring\n  // we've cleaned up here, but sessions can be created and\n  // destroyed many times, and we don't want to temporarily hog\n  // resources.\n  kill_all_tasks();\n  DEBUG_ASSERT(tasks().size() == 0 && vms().size() == 0);\n  DEBUG_ASSERT(emu_fs->size() == 0);\n}\n\nstatic void finish_emulated_syscall_with_ret(Task* t, long ret) {\n  t->finish_emulated_syscall();\n  Registers r = t->regs();\n  r.set_syscall_result(ret);\n  t->set_regs(r);\n}\n\n/**\n * Execute the syscall contained in |t|'s current register set.  The\n * return value of the syscall is set for |t|'s registers, to be\n * returned to the tracee task.\n */\nstatic void execute_syscall(Task* t) {\n  t->finish_emulated_syscall();\n\n  AutoRemoteSyscalls remote(t);\n  remote.syscall(remote.regs().original_syscallno(), remote.regs().arg1(),\n                 remote.regs().arg2(), remote.regs().arg3(),\n                 remote.regs().arg4(), remote.regs().arg5(),\n                 remote.regs().arg6());\n  remote.regs().set_syscall_result(t->regs().syscall_result());\n}\n\nuint64_t DiversionSession::next_timer_counter() {\n  uint64_t value = fake_timer_counter;\n  fake_timer_counter += 1 << 20; // 1M cycles\n  return value;\n}\n\ntemplate <typename Arch>\nstatic void process_syscall_arch(Task* t, int syscallno) {\n  LOG(debug) << \"Processing \" << syscall_name(syscallno, Arch::arch());\n\n  if (syscallno == Arch::ioctl && t->is_desched_event_syscall()) {\n    // The arm/disarm-desched ioctls are emulated as no-ops.\n    // However, because the rr preload library expects these\n    // syscalls to succeed and aborts if they don't, we fudge a\n    // \"0\" return value.\n    finish_emulated_syscall_with_ret(t, 0);\n    return;\n  }\n\n  if (syscallno == t->session().syscall_number_for_rrcall_rdtsc()) {\n    uint64_t rdtsc_value = static_cast<DiversionSession*>(&t->session())->next_timer_counter();\n    LOG(debug) << \"Faking rrcall_rdtsc syscall with value \" << rdtsc_value;\n    remote_ptr<uint64_t> out_param(t->regs().arg1());\n    t->write_mem(out_param, rdtsc_value);\n    finish_emulated_syscall_with_ret(t, 0);\n    return;\n  }\n\n  switch (syscallno) {\n    // We blacklist these syscalls because the params include\n    // namespaced identifiers that are different in replay than\n    // recording, and during replay they may refer to different,\n    // live resources.  For example, if a recorded tracees kills\n    // one of its threads, then during replay that killed pid\n    // might refer to a live process outside the tracee tree.  We\n    // don't want diversion tracees randomly shooting down other\n    // processes!\n    //\n    // We optimistically assume that filesystem operations were\n    // intended by the user.\n    //\n    // There's a potential problem with \"fd confusion\": in the\n    // diversion tasks, fds returned from open() during replay are\n    // emulated.  But those fds may accidentally refer to live fds\n    // in the task fd table.  So write()s etc may not be writing\n    // to the file the tracee expects.  However, the only real fds\n    // that leak into tracees are the stdio fds, and there's not\n    // much harm that can be caused by accidental writes to them.\n    case Arch::ipc:\n    case Arch::kill:\n    case Arch::rt_sigqueueinfo:\n    case Arch::rt_tgsigqueueinfo:\n    case Arch::tgkill:\n    case Arch::tkill:\n    // fork/vfork/clone are likely to lead to disaster because we only\n    // ever allow a single task to run.\n    case Arch::fork:\n    case Arch::vfork:\n    case Arch::clone: {\n      LOG(debug) << \"Suppressing syscall \"\n                 << syscall_name(syscallno, t->arch());\n      Registers r = t->regs();\n      r.set_syscall_result(-ENOSYS);\n      t->set_regs(r);\n      return;\n    }\n\n    case Arch::prctl: {\n      Registers r = t->regs();\n      int op = r.arg1();\n      if (op == PR_SET_TSC) {\n        LOG(debug) << \"Suppressing syscall \"\n                   << syscall_name(syscallno, t->arch());\n        r.set_syscall_result(-ENOSYS);\n        t->set_regs(r);\n        return;\n      }\n      break;\n    }\n\n    case Arch::gettid: {\n      auto tid = t->own_namespace_tid();\n      LOG(debug) << \"Emulating gettid with \" << tid;\n      Registers r = t->regs();\n      r.set_syscall_result(tid);\n      t->set_regs(r);\n      return;\n    }\n\n    case Arch::getpid: {\n      auto pid = t->thread_group()->tgid_own_namespace;\n      LOG(debug) << \"Emulating getpid with \" << pid;\n      Registers r = t->regs();\n      r.set_syscall_result(pid);\n      t->set_regs(r);\n      return;\n    }\n  }\n\n  LOG(debug) << \"Executing syscall \" << syscall_name(syscallno, t->arch());\n  execute_syscall(t);\n}\n\nstatic void process_syscall(Task* t, int syscallno){\n  RR_ARCH_FUNCTION(process_syscall_arch, t->arch(), t, syscallno)\n}\n\nstatic bool maybe_handle_task_exit(Task* t, TaskContext* context,\n                                   DiversionSession::DiversionResult* result) {\n  if (t->ptrace_event() != PTRACE_EVENT_EXIT && !t->was_reaped()) {\n    return false;\n  }\n  t->did_kill();\n  t->detach();\n  delete t;\n  // This is now a dangling pointer, so clear it.\n  context->task = nullptr;\n  result->status = DiversionSession::DIVERSION_EXITED;\n  result->break_status.task_context = *context;\n  result->break_status.task_exit = true;\n  return true;\n}\n\n/**\n * Advance execution until either a signal is received (including a SIGTRAP\n * generated by a single-step) or a syscall is made.\n */\nDiversionSession::DiversionResult DiversionSession::diversion_step(\n    Task* t, RunCommand command, int signal_to_deliver) {\n  DEBUG_ASSERT(command != RUN_SINGLESTEP_FAST_FORWARD);\n  assert_fully_initialized();\n\n  DiversionResult result;\n  TaskContext context(t);\n\n  // An exit might have occurred while processing a previous syscall.\n  if (maybe_handle_task_exit(t, &context, &result)) {\n    return result;\n  }\n\n  t->set_in_diversion(true);\n\n  while (true) {\n    switch (command) {\n      case RUN_CONTINUE: {\n        LOG(debug) << \"Continuing to next syscall\";\n        bool ok = t->resume_execution(RESUME_SYSEMU, RESUME_WAIT,\n                                      RESUME_UNLIMITED_TICKS, signal_to_deliver);\n        ASSERT(t, ok) << \"Tracee was killed unexpectedly\";\n        break;\n      }\n      case RUN_SINGLESTEP: {\n        LOG(debug) << \"Stepping to next insn/syscall\";\n        bool ok = t->resume_execution(RESUME_SYSEMU_SINGLESTEP, RESUME_WAIT,\n                                      RESUME_UNLIMITED_TICKS, signal_to_deliver);\n        ASSERT(t, ok) << \"Tracee was killed unexpectedly\";\n        break;\n      }\n      default:\n        FATAL() << \"Illegal run command \" << command;\n    }\n\n    if (maybe_handle_task_exit(t, &context, &result)) {\n      return result;\n    }\n\n    result.status = DIVERSION_CONTINUE;\n    if (t->stop_sig()) {\n      LOG(debug) << \"Pending signal: \" << t->get_siginfo();\n      result.break_status = diagnose_debugger_trap(t, command);\n      if (t->stop_sig() == SIGTRAP &&\n          !result.break_status.breakpoint_hit &&\n          result.break_status.watchpoints_hit.empty() &&\n          !result.break_status.singlestep_complete) {\n        result.break_status.signal = unique_ptr<siginfo_t>(new siginfo_t(t->get_siginfo()));\n        result.break_status.signal->si_signo = t->stop_sig();\n      } else if (t->stop_sig() == SIGSEGV) {\n        auto special_instruction = special_instruction_at(t, t->ip());\n        if (special_instruction.opcode == SpecialInstOpcode::X86_RDTSC) {\n          size_t len = special_instruction_len(special_instruction.opcode);\n          uint64_t rdtsc_value = next_timer_counter();\n          LOG(debug) << \"Faking RDTSC instruction with value \" << rdtsc_value;\n          Registers r = t->regs();\n          r.set_ip(r.ip() + len);\n          r.set_ax((uint32_t)rdtsc_value);\n          r.set_dx(rdtsc_value >> 32);\n          t->set_regs(r);\n          result.break_status = BreakStatus();\n          continue;\n        } else if (special_instruction.opcode == SpecialInstOpcode::ARM_MRS_CNTVCT_EL0 ||\n                   special_instruction.opcode == SpecialInstOpcode::ARM_MRS_CNTVCTSS_EL0) {\n          size_t len = special_instruction_len(special_instruction.opcode);\n          uint64_t cntvct_value = next_timer_counter();\n          Registers r = t->regs();\n          r.set_ip(r.ip() + len);\n          if (special_instruction.regno != 31) {\n            r.set_x(special_instruction.regno, cntvct_value);\n          }\n          t->set_regs(r);\n          result.break_status = BreakStatus();\n          continue;\n        } else if (special_instruction.opcode == SpecialInstOpcode::ARM_MRS_CNTFRQ_EL0) {\n          size_t len = special_instruction_len(special_instruction.opcode);\n          Registers r = t->regs();\n          r.set_ip(r.ip() + len);\n          if (special_instruction.regno != 31) {\n            r.set_x(special_instruction.regno, cntfrq());\n          }\n          t->set_regs(r);\n          result.break_status = BreakStatus();\n          continue;\n        }\n      }\n      LOG(debug) << \"Diversion break at ip=\" << (void*)t->ip().register_value()\n                 << \"; break=\" << result.break_status.breakpoint_hit\n                 << \", watch=\" << !result.break_status.watchpoints_hit.empty()\n                 << \", singlestep=\" << result.break_status.singlestep_complete;\n      ASSERT(t,\n             !result.break_status.singlestep_complete ||\n                 command == RUN_SINGLESTEP);\n      return result;\n    }\n    break;\n  }\n\n  if (t->status().is_syscall()) {\n    t->apply_syscall_entry_regs();\n  }\n\n  process_syscall(t, t->regs().original_syscallno());\n  check_for_watchpoint_changes(t, result.break_status);\n  return result;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/DiversionSession.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_DIVERSION_SESSION_H_\n#define RR_DIVERSION_SESSION_H_\n\n#include \"EmuFs.h\"\n#include \"Session.h\"\n\nnamespace rr {\n\nclass ReplaySession;\n\n/**\n * A DiversionSession lets you run task(s) forward without replay.\n * Clone a ReplaySession to a DiversionSession to execute some arbitrary\n * code for its side effects.\n *\n * Diversion allows tracees to execute freely, as in \"recorder\"\n * mode, but doesn't attempt to record any data.  Diverter\n * emulates the syscalls it's able to (such as writes to stdio fds),\n * and essentially ignores the syscalls it doesn't know how to\n * implement.  Tracees can easily get into inconsistent states within\n * diversion mode, and no attempt is made to detect or rectify that.\n *\n * Diverter mode is designed to support short-lived diversions from\n * \"replayer\" sessions, as required to support gdb's |call foo()|\n * feature.  A diversion is created for the call frame, then discarded\n * when the call finishes (loosely speaking).\n */\nclass DiversionSession final : public Session {\npublic:\n  DiversionSession(BindCPU cpu_binding);\n\n  typedef std::shared_ptr<DiversionSession> shr_ptr;\n\n  ~DiversionSession();\n\n  EmuFs& emufs() const { return *emu_fs; }\n\n  enum DiversionStatus {\n    // Some execution was done. diversion_step() can be called again.\n    DIVERSION_CONTINUE,\n    // All tracees are dead. diversion_step() should not be called again.\n    DIVERSION_EXITED\n  };\n  struct DiversionResult {\n    DiversionStatus status;\n    BreakStatus break_status;\n  };\n  /**\n   * Try make progress in this diversion session. Run task t if possible.\n   */\n  DiversionResult diversion_step(Task* t, RunCommand command = RUN_CONTINUE,\n                                 int signal_to_deliver = 0);\n\n  virtual DiversionSession* as_diversion() override { return this; }\n  virtual BindCPU cpu_binding() const override { return cpu_binding_; }\n\n  void set_tracee_fd_number(int fd_number) { tracee_socket_fd_number = fd_number; }\n  void on_create(Task *t) override { this->Session::on_create(t); }\n\n  uint64_t next_timer_counter();\n\nprivate:\n  friend class ReplaySession;\n\n  std::shared_ptr<EmuFs> emu_fs;\n  uint64_t fake_timer_counter;\n  BindCPU cpu_binding_;\n};\n\n} // namespace rr\n\n#endif // RR_DIVERSION_SESSION_H_\n"
  },
  {
    "path": "src/DumpCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"DumpCommand.h\"\n\n#include <arpa/inet.h>\n#include <inttypes.h>\n#include <netinet/in.h>\n#include <sys/socket.h>\n\n#include <limits>\n#include <unordered_map>\n\n#include \"preload/preload_interface.h\"\n\n#include \"AddressSpace.h\"\n#include \"Command.h\"\n#include \"TraceStream.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass DumpCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  DumpCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static DumpCommand singleton;\n};\n\nDumpCommand DumpCommand::singleton(\n    \"dump\",\n    \" rr dump [OPTIONS] [<trace_dir>] [<event-spec>...]\\n\"\n    \"  Event specs can be either an event number like `127', or a range\\n\"\n    \"  like `1000-5000', or `end' for the last record in the trace.\\n\"\n    \"  By default, all events are dumped.\\n\"\n    \"  -b, --syscallbuf           dump syscallbuf contents\\n\"\n    \"  -e, --task-events          dump task events\\n\"\n    \"  -m, --recorded-metadata    dump recorded data metadata\\n\"\n    \"  -p, --mmaps                dump mmap data\\n\"\n    \"  -r, --raw                  dump trace frames in a more easily\\n\"\n    \"                             machine-parseable format instead of the\\n\"\n    \"                             default human-readable format\\n\"\n    \"  -s, --statistics           dump statistics about the trace\\n\"\n    \"  -t, --tid=<pid>            dump events only for the specified tid\\n\");\n\nstatic bool parse_dump_arg(vector<string>& args, DumpFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = {\n    { 0, \"socket-addresses\", NO_PARAMETER },\n    { 'b', \"syscallbuf\", NO_PARAMETER },\n    { 'e', \"task-events\", NO_PARAMETER },\n    { 'm', \"recorded-metadata\", NO_PARAMETER },\n    { 'p', \"mmaps\", NO_PARAMETER },\n    { 'r', \"raw\", NO_PARAMETER },\n    { 's', \"statistics\", NO_PARAMETER },\n    { 't', \"tid\", HAS_PARAMETER },\n  };\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 'b':\n      flags.dump_syscallbuf = true;\n      break;\n    case 'e':\n      flags.dump_task_events = true;\n      break;\n    case 'm':\n      flags.dump_recorded_data_metadata = true;\n      break;\n    case 'p':\n      flags.dump_mmaps = true;\n      break;\n    case 'r':\n      flags.raw_dump = true;\n      break;\n    case 's':\n      flags.dump_statistics = true;\n      break;\n    case 't':\n      if (!opt.verify_valid_int(1, INT32_MAX)) {\n        return false;\n      }\n      flags.only_tid = opt.int_value;\n      break;\n    case 0:\n      flags.dump_socket_addrs = true;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown option\");\n  }\n  return true;\n}\n\nstatic void dump_syscallbuf_data(TraceReader& trace, FILE* out,\n                                 const TraceFrame& frame,\n                                 const DumpFlags& flags) {\n  if (frame.event().type() != EV_SYSCALLBUF_FLUSH) {\n    return;\n  }\n  TraceReader::RawData buf;\n  bool ok = trace.read_raw_data_for_frame(buf);\n  if (!ok) {\n    FATAL() << \"Can't read raw-data record for syscallbuf\";\n  }\n  size_t bytes_remaining = buf.data.size() - trace.syscallbuf_hdr_size();\n  auto flush_hdr = reinterpret_cast<const syscallbuf_hdr*>(buf.data.data());\n  if (flush_hdr->num_rec_bytes > bytes_remaining) {\n    CLEAN_FATAL() << \"Malformed trace file (bad recorded-bytes count)\";\n  }\n  if (flags.raw_dump) {\n    fprintf(out, \"  \");\n    for (unsigned long i = 0; i < sizeof(syscallbuf_hdr); ++i) {\n      fprintf(out, \"%2.2x\", *(buf.data.data() + (uintptr_t)i));\n    }\n    fprintf(out, \"\\n\");\n  }\n  bytes_remaining = flush_hdr->num_rec_bytes;\n\n  auto record_ptr = reinterpret_cast<const uint8_t*>(flush_hdr) + trace.syscallbuf_hdr_size();\n  auto end_ptr = record_ptr + bytes_remaining;\n  while (record_ptr < end_ptr) {\n    auto record = reinterpret_cast<const struct syscallbuf_record*>(record_ptr);\n    // Buffered syscalls always use the task arch\n    fprintf(out, \"  { syscall:'%s', ret:0x%lx, size:0x%lx%s%s }\\n\",\n            syscall_name(record->syscallno, frame.regs().arch()).c_str(),\n            (long)record->ret, (long)record->size,\n            record->desched ? \", desched:1\" : \"\",\n            record->replay_assist ? \", replay_assist:1\" : \"\");\n    if (flags.raw_dump) {\n      fprintf(out, \"  \");\n      for (unsigned long i = 0; i < record->size; ++i) {\n        fprintf(out, \"%2.2x\", *(record_ptr + (uintptr_t)i));\n      }\n      fprintf(out, \"\\n\");\n    }\n    if (record->size < sizeof(*record)) {\n      CLEAN_FATAL() << \"Malformed trace file (bad record size)\";\n    }\n    record_ptr += stored_record_size(record->size);\n  }\n  if (flags.dump_mmaps) {\n    for (auto& record : frame.event().SyscallbufFlush().mprotect_records) {\n      fprintf(out, \"  { start:%p, size:%\" PRIx64 \", prot:'%s' }\\n\",\n              (void*)record.start, record.size, prot_flags_string(record.prot).c_str());\n      if (flags.raw_dump) {\n        fprintf(out, \"  \");\n        for (unsigned long i = 0; i < sizeof(record); ++i) {\n          fprintf(out, \"%2.2x\", *(reinterpret_cast<const uint8_t*>(&record) + (uintptr_t)i));\n        }\n        fprintf(out, \"\\n\");\n      }\n    }\n  }\n}\n\nstatic void print_socket_addr(FILE* out, const struct NativeArch::sockaddr_storage& sa) {\n  char buf[256];\n  auto sockaddr = reinterpret_cast<const struct sockaddr_storage*>(&sa);\n  switch (sockaddr->ss_family) {\n    case AF_INET: {\n      auto sockaddr_in = reinterpret_cast<const struct sockaddr_in*>(sockaddr);\n      if (inet_ntop(AF_INET, &sockaddr_in->sin_addr, buf, sizeof(buf) - 1)) {\n        fprintf(out, \"%s:%d\", buf, sockaddr_in->sin_port);\n      } else {\n        FATAL();\n      }\n      break;\n    }\n    case AF_INET6: {\n      auto sockaddr_in6 = reinterpret_cast<const struct sockaddr_in6*>(sockaddr);\n      if (inet_ntop(AF_INET6, &sockaddr_in6->sin6_addr, buf, sizeof(buf) - 1)) {\n        fprintf(out, \"%s:%d\", buf, sockaddr_in6->sin6_port);\n      } else {\n        FATAL();\n      }\n      break;\n    }\n    default:\n      fputs(\"<Unknown socket family>\", out);\n      break;\n  }\n}\n\nstatic void dump_socket_addrs(FILE* out, const TraceFrame& frame) {\n  if (frame.event().type() != EV_SYSCALL) {\n    return;\n  }\n\n  auto syscall = frame.event().Syscall();\n  if (syscall.socket_addrs) {\n    fputs(\"  Local socket address '\", out);\n    print_socket_addr(out, (*syscall.socket_addrs.get())[0]);\n    fputs(\"' Remote socket address '\", out);\n    print_socket_addr(out, (*syscall.socket_addrs.get())[1]);\n    fputs(\"'\\n\", out);\n  }\n}\n\nstatic void dump_task_event(FILE* out, const TraceTaskEvent& event) {\n  switch (event.type()) {\n    case TraceTaskEvent::CLONE:\n      fprintf(out, \"  TraceTaskEvent::CLONE tid=%d parent=%d clone_flags=0x%x\\n\",\n          event.tid(), event.parent_tid(), event.clone_flags());\n      break;\n    case TraceTaskEvent::EXEC:\n      fprintf(out, \"  TraceTaskEvent::EXEC tid=%d file=%s\\n\", event.tid(),\n          event.file_name().c_str());\n      break;\n    case TraceTaskEvent::EXIT:\n      fprintf(out, \"  TraceTaskEvent::EXIT tid=%d status=%d\\n\", event.tid(),\n          event.exit_status().get());\n      break;\n    case TraceTaskEvent::DETACH:\n      fprintf(out, \"  TraceTaskEvent::DETACH tid=%d\\n\", event.tid());\n      break;\n    default:\n      FATAL() << \"Unknown TraceTaskEvent\";\n      break;\n  }\n}\n\n/**\n * Dump all events from the current to trace that match |spec| to\n * |out|.  |spec| has the following syntax: /\\d+(-\\d+)?/, expressing\n * either a single event number of a range, and may be null to\n * indicate \"dump all events\".\n *\n * This function is side-effect-y, in that the trace file isn't\n * rewound in between matching each spec.  Therefore specs should be\n * constructed so as to match properly on a serial linear scan; that\n * is, they should comprise disjoint and monotonically increasing\n * event sets.  No attempt is made to enforce this or normalize specs.\n */\nstatic void dump_events_matching(TraceReader& trace, const DumpFlags& flags,\n                                 FILE* out, const string* spec,\n                                 const unordered_multimap<FrameTime, TraceTaskEvent>& task_events) {\n\n  uint32_t start = 0, end = numeric_limits<uint32_t>::max();\n  bool only_end = false;\n\n  if (spec && *spec == \"end\") {\n    only_end = true;\n  } else {\n    // Try to parse the \"range\" syntax '[start]-[end]'.\n    if (spec && 2 > sscanf(spec->c_str(), \"%u-%u\", &start, &end)) {\n      // Fall back on assuming the spec is a single event\n      // number, however it parses out with atoi().\n      start = end = atoi(spec->c_str());\n    }\n  }\n\n  bool process_raw_data =\n      flags.dump_syscallbuf || flags.dump_recorded_data_metadata;\n  while (!trace.at_end()) {\n    auto frame = trace.read_frame(start);\n    if (end < frame.time()) {\n      return;\n    }\n    if (only_end ? trace.at_end() :\n         (start <= frame.time() && frame.time() <= end &&\n           (!flags.only_tid || flags.only_tid == frame.tid()))) {\n      if (flags.raw_dump) {\n        frame.dump_raw(out);\n      } else {\n        frame.dump(out);\n      }\n      if (flags.dump_syscallbuf) {\n        dump_syscallbuf_data(trace, out, frame, flags);\n      }\n      if (flags.dump_task_events) {\n        auto range = task_events.equal_range(frame.time());\n        for (auto it = range.first; it != range.second; ++it) {\n          dump_task_event(out, it->second);\n        }\n      }\n\n      while (true) {\n        TraceReader::MappedData data;\n        bool found;\n        KernelMapping km =\n            trace.read_mapped_region(&data, &found, TraceReader::DONT_VALIDATE);\n        if (!found) {\n          break;\n        }\n        if (flags.dump_mmaps) {\n          char prot_flags[] = \"rwxp\";\n          if (!(km.prot() & PROT_READ)) {\n            prot_flags[0] = '-';\n          }\n          if (!(km.prot() & PROT_WRITE)) {\n            prot_flags[1] = '-';\n          }\n          if (!(km.prot() & PROT_EXEC)) {\n            prot_flags[2] = '-';\n          }\n          if (km.flags() & MAP_SHARED) {\n            prot_flags[3] = 's';\n          }\n          const char* fsname = km.fsname().c_str();\n          if (data.source == TraceReader::SOURCE_ZERO) {\n            static const char source_zero[] = \"<ZERO>\";\n            fsname = source_zero;\n          }\n          fprintf(out, \"  { map_file:\\\"%s\\\", addr:%p, length:%p, \"\n                       \"prot_flags:\\\"%s\\\", file_offset:0x%llx, \"\n                       \"device:%lld, inode:%lld, \"\n                       \"data_file:\\\"%s\\\", data_offset:0x%llx, \"\n                       \"file_size:0x%llx }\\n\",\n                  fsname, (void*)km.start().as_int(), (void*)km.size(),\n                  prot_flags, (long long)km.file_offset_bytes(),\n                  (long long)km.device(), (long long)km.inode(),\n                  data.file_name.c_str(), (long long)data.data_offset_bytes,\n                  (long long)data.file_size_bytes);\n        }\n      }\n\n      TraceReader::RawDataMetadata data;\n      while (process_raw_data && trace.read_raw_data_metadata_for_frame(data)) {\n        if (flags.dump_recorded_data_metadata) {\n          fprintf(out, \"  { tid:%d, addr:%p, length:%p\", data.rec_tid,\n                  (void*)data.addr.as_int(), (void*)data.size);\n          if (!data.holes.empty()) {\n            fputs(\", holes:[\", out);\n            bool first = true;\n            for (auto& h : data.holes) {\n              if (!first) {\n                fputs(\", \", out);\n              }\n              first = false;\n              fprintf(out, \"%p-%p\", (void*)h.offset, (void*)(h.offset + h.size));\n            }\n            fputs(\"]\", out);\n          }\n          fputs(\" }\\n\", out);\n        }\n      }\n      if (flags.dump_socket_addrs) {\n        dump_socket_addrs(out, frame);\n      }\n      if (!flags.raw_dump) {\n        fprintf(out, \"}\\n\");\n      }\n    } else {\n      while (true) {\n        TraceReader::MappedData data;\n        KernelMapping km = trace.read_mapped_region(&data, nullptr,\n                                                    TraceReader::DONT_VALIDATE);\n        if (km.size() == 0) {\n          break;\n        }\n      }\n      TraceReader::RawDataMetadata data;\n      while (process_raw_data && trace.read_raw_data_metadata_for_frame(data)) {\n      }\n    }\n  }\n}\n\nstatic void dump_statistics(const TraceReader& trace, FILE* out) {\n  uint64_t uncompressed = trace.uncompressed_bytes();\n  uint64_t compressed = trace.compressed_bytes();\n  fprintf(out, \"// Uncompressed bytes %\" PRIu64 \", compressed bytes %\" PRIu64\n               \", ratio %.2fx\\n\",\n          uncompressed, compressed, double(uncompressed) / compressed);\n}\n\nvoid dump(const string& trace_dir, const DumpFlags& flags,\n          const vector<string>& specs, FILE* out) {\n  TraceReader trace(trace_dir);\n\n  if (flags.raw_dump) {\n    fprintf(out, \"global_time tid reason ticks \"\n                 \"hw_interrupts page_faults instructions \"\n                 \"eax ebx ecx edx esi edi ebp orig_eax esp eip eflags\\n\");\n  }\n\n  unordered_multimap<FrameTime, TraceTaskEvent> task_events;\n  FrameTime last_time = 0;\n  while (true) {\n    FrameTime time;\n    TraceTaskEvent r = trace.read_task_event(&time);\n    if (time < last_time) {\n      FATAL() << \"TraceTaskEvent times non-monotonic\";\n    }\n    if (r.type() == TraceTaskEvent::NONE) {\n      break;\n    }\n    task_events.insert(make_pair(time, r));\n    last_time = time;\n  }\n\n  if (specs.size() > 0) {\n    for (size_t i = 0; i < specs.size(); ++i) {\n      dump_events_matching(trace, flags, out, &specs[i], task_events);\n    }\n  } else {\n    // No specs => dump all events.\n    dump_events_matching(trace, flags, out, nullptr /*all events*/, task_events);\n  }\n\n  if (flags.dump_statistics) {\n    dump_statistics(trace, out);\n  }\n}\n\nint DumpCommand::run(vector<string>& args) {\n  DumpFlags flags;\n\n  while (parse_dump_arg(args, flags)) {\n  }\n\n  string trace_dir;\n  if (!parse_optional_trace_dir(args, &trace_dir)) {\n    print_help(stderr);\n    return 1;\n  }\n\n  dump(trace_dir, flags, args, stdout);\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/DumpCommand.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_DUMP_COMMAND_H_\n#define RR_DUMP_COMMAND_H_\n\n#ifndef _DEFAULT_SOURCE\n#define _DEFAULT_SOURCE 1\n#endif\n\n#include <stdio.h>\n\n#include <memory>\n#include <string>\n#include <vector>\n\nnamespace rr {\n\nstruct DumpFlags {\n  bool dump_syscallbuf;\n  bool dump_recorded_data_metadata;\n  bool dump_mmaps;\n  bool dump_task_events;\n  bool raw_dump;\n  bool dump_statistics;\n  bool dump_socket_addrs;\n  int only_tid;\n\n  DumpFlags()\n      : dump_syscallbuf(false),\n        dump_recorded_data_metadata(false),\n        dump_mmaps(false),\n        dump_task_events(false),\n        raw_dump(false),\n        dump_statistics(false),\n        dump_socket_addrs(false),\n        only_tid(0) {}\n};\n\nvoid dump(const std::string& trace_dir, const DumpFlags& flags,\n          const std::vector<std::string>& specs, FILE* out);\n\n} // namespace rr\n\n#endif // RR_DUMP_COMMAND_H_\n"
  },
  {
    "path": "src/Dwarf.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Dwarf.h\"\n\n#include <string.h>\n\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstruct Dwarf32 {\n  typedef uint32_t Offset;\n  static const uint8_t EntrySize = 4;\n  struct CompilationUnitPreamble {\n    uint32_t unit_length;\n  };\n};\nstruct Dwarf64 {\n  typedef uint64_t Offset;\n  static const uint8_t EntrySize = 8;\n  struct __attribute__((packed)) CompilationUnitPreamble {\n    uint32_t magic; /* 0xffffffff */\n    uint64_t unit_length;\n  };\n};\n\ntemplate <typename D> struct  __attribute__((packed)) Dwarf4CompilationUnitHeader {\n  typedef D Size;\n  typename D::CompilationUnitPreamble preamble;\n  uint16_t version;\n  typename D::Offset debug_abbrev_offset;\n  uint8_t address_size;\n\n  void install_dwo_id(DwarfCompilationUnit* unit) const {\n    unit->set_dwo_id(0);\n  }\n};\n\ntemplate <typename D> struct  __attribute__((packed)) Dwarf5CompilationUnitHeader {\n  typedef D Size;\n  typename D::CompilationUnitPreamble preamble;\n  uint16_t version;\n  uint8_t unit_type;\n  uint8_t address_size;\n  typename D::Offset debug_abbrev_offset;\n\n  void install_dwo_id(DwarfCompilationUnit* unit) const {\n    unit->set_dwo_id(0);\n  }\n};\n\ntemplate <typename D> struct  __attribute__((packed)) Dwarf5SkeletonSplitCompilationUnitHeader {\n  typedef D Size;\n  typename D::CompilationUnitPreamble preamble;\n  uint16_t version;\n  uint8_t unit_type;\n  uint8_t address_size;\n  typename D::Offset debug_abbrev_offset;\n  uint64_t dwo_id;\n\n  void install_dwo_id(DwarfCompilationUnit* unit) const {\n    unit->set_dwo_id(dwo_id);\n  }\n};\n\ntemplate <typename D> struct  __attribute__((packed)) Dwarf2LineNumberTableHeader {\n  typedef D Size;\n  typename D::CompilationUnitPreamble preamble;\n  uint16_t version;\n  typename D::Offset header_length;\n  uint8_t minimum_instruction_length;\n  uint8_t default_is_stmt;\n  int8_t line_base;\n  uint8_t line_range;\n  uint8_t opcode_base;\n\n  bool read_directories(const DwarfCompilationUnit& cu,\n                        DwarfSpan span,\n                        const DebugStrSpans& debug_str,\n                        std::vector<const char*>& directories,\n                        std::vector<DwarfSourceFile>& files) const;\n};\n\ntemplate <typename D> struct  __attribute__((packed)) Dwarf4LineNumberTableHeader {\n  typedef D Size;\n  typename D::CompilationUnitPreamble preamble;\n  uint16_t version;\n  typename D::Offset header_length;\n  uint8_t minimum_instruction_length;\n  uint8_t maximum_operations_per_instruction;\n  uint8_t default_is_stmt;\n  int8_t line_base;\n  uint8_t line_range;\n  uint8_t opcode_base;\n\n  bool read_directories(const DwarfCompilationUnit& cu,\n                        DwarfSpan span,\n                        const DebugStrSpans& debug_str,\n                        std::vector<const char*>& directories,\n                        std::vector<DwarfSourceFile>& files) const;\n};\n\ntemplate <typename D> struct  __attribute__((packed)) Dwarf5LineNumberTableHeader {\n  typedef D Size;\n  typename D::CompilationUnitPreamble preamble;\n  uint16_t version;\n  uint8_t address_size;\n  uint8_t segment_selector_size;\n  typename D::Offset header_length;\n  uint8_t minimum_instruction_length;\n  uint8_t maximum_operations_per_instruction;\n  uint8_t default_is_stmt;\n  int8_t line_base;\n  uint8_t line_range;\n  uint8_t opcode_base;\n\n  bool read_directories(const DwarfCompilationUnit& cu,\n                        DwarfSpan span,\n                        const DebugStrSpans& debug_str,\n                        std::vector<const char*>& directories,\n                        std::vector<DwarfSourceFile>& files) const;\n};\n\nuint64_t DwarfSpan::read_uleb(bool* ok) {\n  uint64_t ret = 0;\n  int shift = 0;\n  while (start < end) {\n    uint8_t b = *start;\n    ++start;\n    ret |= (b & 0x7f) << shift;\n    if (!(b & 0x80)) {\n      return ret;\n    }\n    shift += 7;\n    if (shift >= 64) {\n      *ok = false;\n      return 0;\n    }\n  }\n  *ok = false;\n  return 0;\n}\n\nDwarfSpan DwarfSpan::read_leb_ref(bool* ok) {\n  DwarfSpan ret(*this);\n  while (start < end) {\n    if (!(*start & 0x80)) {\n      ++start;\n      ret.end = start;\n      return ret;\n    }\n    ++start;\n  }\n  *ok = false;\n  return ret;\n}\n\nconst char* DwarfSpan::read_null_terminated_string(bool* ok) {\n  const void* p = memchr(start, 0, size());\n  if (!p) {\n    LOG(warn) << \"String was not null-terminated\";\n    *ok = false;\n    return nullptr;\n  }\n  const char* ret = reinterpret_cast<const char*>(start);\n  start = static_cast<const uint8_t*>(p) + 1;\n  return ret;\n}\n\nDwarfAbbrev* DwarfAbbrevSet::lookup(uint64_t code) {\n  auto it = abbrevs.find(code);\n  if (it != abbrevs.end()) {\n    return it->second.get();\n  }\n\n  while (!remaining_span.empty()) {\n    bool ok = true;\n    uint64_t abbrev_code = remaining_span.read_uleb(&ok);\n    unique_ptr<DwarfAbbrev> abbrev(new DwarfAbbrev);\n    abbrev->tag = (DWTag)remaining_span.read_uleb(&ok);\n    abbrev->children = (DWChildren)remaining_span.read_value<uint8_t>(&ok);\n    auto abbrev_raw = abbrev.get();\n    while (true) {\n      uint64_t name = remaining_span.read_uleb(&ok);\n      DWForm form = (DWForm)remaining_span.read_uleb(&ok);\n      if (!name && !form) {\n        break;\n      }\n      DwarfSpan constant;\n      if (form == DW_FORM_implicit_const) {\n        constant = remaining_span.read_leb_ref(&ok);\n      }\n      abbrev->attributes.push_back({ name, form, constant });\n    }\n    if (!ok) {\n      LOG(warn) << \"Invalid DWARF abbrev table!\";\n      return nullptr;\n    }\n    abbrevs.insert(make_pair(abbrev_code, std::move(abbrev)));\n    if (code == abbrev_code) {\n      return abbrev_raw;\n    }\n  }\n\n  return nullptr;\n}\n\nDwarfAbbrevSet& DwarfAbbrevs::lookup(uint64_t offset) {\n  auto it = abbrevs.find(offset);\n  if (it != abbrevs.end()) {\n    return *it->second;\n  }\n\n  unique_ptr<DwarfAbbrevSet> set(new DwarfAbbrevSet(debug_abbrev.subspan(offset)));\n  auto set_raw = set.get();\n  abbrevs.insert(make_pair(offset, std::move(set)));\n  return *set_raw;\n}\n\nstatic DwarfAbbrev null_abbrev;\n\nDwarfDIE::DwarfDIE(DwarfSpan span, DwarfAbbrevSet& abbrevs, uint8_t dwarf_size, uint8_t address_size, bool* ok)\n  : address_size(address_size), dwarf_size(dwarf_size) {\n  uint64_t code = span.read_uleb(ok);\n  if (!*ok) {\n    return;\n  }\n  if (code == 0) {\n    abbrev = &null_abbrev;\n    return;\n  }\n  abbrev = abbrevs.lookup(code);\n  if (!abbrev) {\n    LOG(warn) << \"No abbrev found for DIE\";\n    *ok = false;\n    return;\n  }\n  attr_span = span;\n}\n\nstatic size_t form_size(DWForm form, size_t address_size, size_t dwarf_size, DwarfSpan* span, bool* ok) {\n  if (form == DW_FORM_indirect) {\n    form = (DWForm)span->read_uleb(ok);\n    if (!*ok) {\n      return 0;\n    }\n  }\n  if (form == DW_FORM_udata) {\n    auto before = span->size();\n    DwarfSpan a_span(*span);\n    a_span.read_uleb(ok);\n    if (!*ok) {\n      return 0;\n    }\n    return before - a_span.size();\n  }\n  switch (form) {\n    case DW_FORM_addr: return address_size;\n    case DW_FORM_addrx: return dwarf_size;\n    case DW_FORM_data1: return 1;\n    case DW_FORM_data2: return 2;\n    case DW_FORM_data4: return 4;\n    case DW_FORM_data8: return 8;\n    case DW_FORM_data16: return 16;\n    case DW_FORM_flag: return 1;\n    case DW_FORM_strp: return dwarf_size;\n    case DW_FORM_line_strp: return dwarf_size;\n    case DW_FORM_strx: return dwarf_size;\n    case DW_FORM_strx1: return 1;\n    case DW_FORM_strx2: return 2;\n    case DW_FORM_strx3: return 3;\n    case DW_FORM_strx4: return 4;\n    case DW_FORM_string: {\n      auto before = span->size();\n      DwarfSpan a_span(*span);\n      a_span.read_null_terminated_string(ok);\n      if (!*ok) {\n        return 0;\n      }\n      return before - a_span.size();\n    }\n    case DW_FORM_sec_offset: return dwarf_size;\n    case DW_FORM_flag_present: return 0;\n    case DW_FORM_implicit_const: return 0;\n    case DW_FORM_rnglistx: return dwarf_size;\n    case DW_FORM_strp_sup: return dwarf_size;\n    case DW_FORM_GNU_strp_alt: return dwarf_size;\n    default:\n      LOG(warn) << \"form \" << form << \" not supported!\";\n      *ok = false;\n      return 0;\n  }\n}\n\nDwarfSpan DwarfDIE::find_attribute(DWAttr attr, DWForm* form, bool* ok) const {\n  DwarfSpan span = attr_span;\n  for (auto& a : abbrev->attributes) {\n    size_t size = form_size(a.form, address_size, dwarf_size, &span, ok);\n    DwarfSpan a_span = span.consume(size);\n    if (a.name == attr) {\n      *form = a.form;\n      if (a.form == DW_FORM_implicit_const) {\n        a_span = a.constant;\n      }\n      return a_span;\n    }\n  }\n  return DwarfSpan();\n}\n\nstatic uint64_t decode_unsigned_literal(DwarfSpan span, bool* ok) {\n  int shift = 0;\n  uint64_t ret = 0;\n  while (!span.empty()) {\n    if (shift >= 64) {\n      LOG(warn) << \"Literal too large\";\n      *ok = false;\n      return 0;\n    }\n    ret |= (uint64_t)span.read_value<uint8_t>(ok) << shift;\n    shift += 8;\n  }\n  return ret;\n}\n\nstatic int64_t decode_section_ptr(DwarfSpan span, DWForm form, bool* ok) {\n  switch (form) {\n    case DW_FORM_data1:\n    case DW_FORM_data2:\n    case DW_FORM_data4:\n    case DW_FORM_data8:\n    case DW_FORM_sec_offset: {\n      uint64_t ret = decode_unsigned_literal(span, ok);\n      if (ret > INT64_MAX) {\n        LOG(warn) << \"section ptr out of range\";\n        *ok = false;\n        return 0;\n      }\n      return ret;\n    }\n    default:\n      LOG(warn) << \"Unknown section ptr form \" << form;\n      *ok = false;\n      return 0;\n  }\n}\n\nstatic uint64_t decode_unsigned(DwarfSpan span, DWForm form, bool* ok) {\n  switch (form) {\n    case DW_FORM_data1:\n    case DW_FORM_data2:\n    case DW_FORM_data4:\n    case DW_FORM_data8: {\n      return decode_unsigned_literal(span, ok);\n    }\n    case DW_FORM_udata: {\n      return span.read_uleb(ok);\n    }\n    default:\n      LOG(warn) << \"Unknown unsigned form \" << form;\n      *ok = false;\n      return 0;\n  }\n}\n\nstatic const char* decode_string(const DwarfCompilationUnit& cu, DwarfSpan span, DWForm form, const DebugStrSpans& debug_strs, bool* ok) {\n  switch (form) {\n    case DW_FORM_strp: {\n      uint64_t offset = decode_unsigned_literal(span, ok);\n      if (!*ok) {\n        return nullptr;\n      }\n      return debug_strs.debug_str.subspan(offset).read_null_terminated_string(ok);\n    }\n    case DW_FORM_strp_sup:\n    case DW_FORM_GNU_strp_alt: {\n      uint64_t offset = decode_unsigned_literal(span, ok);\n      if (!*ok) {\n        return nullptr;\n      }\n      return debug_strs.debug_str_sup.subspan(offset).read_null_terminated_string(ok);\n    }\n    case DW_FORM_line_strp: {\n      uint64_t offset = decode_unsigned_literal(span, ok);\n      if (!*ok) {\n        return nullptr;\n      }\n      return debug_strs.debug_line_str.subspan(offset).read_null_terminated_string(ok);\n    }\n    case DW_FORM_strx:\n    case DW_FORM_strx1:\n    case DW_FORM_strx2:\n    case DW_FORM_strx3:\n    case DW_FORM_strx4: {\n      uint64_t index = decode_unsigned_literal(span, ok) * cu.entry_size() + cu.str_offsets_base();\n      if (!*ok) {\n        return nullptr;\n      }\n      uint64_t offset = cu.read_entry_sized_value(debug_strs.debug_str_offsets.subspan(index), ok);\n      if (!*ok) {\n        return nullptr;\n      }\n      return debug_strs.debug_str.subspan(offset).read_null_terminated_string(ok);\n    }\n    case DW_FORM_string:\n      return span.read_null_terminated_string(ok);\n    default:\n      LOG(warn) << \"Unknown string form \" << form;\n      *ok = false;\n      return 0;\n  }\n}\n\nint64_t DwarfDIE::section_ptr_attr(DWAttr attr, bool* ok) const {\n  DWForm form;\n  auto span = find_attribute(attr, &form, ok);\n  if (span.empty() || !*ok) {\n    return -1;\n  }\n  return decode_section_ptr(span, form, ok);\n}\n\nuint64_t DwarfDIE::unsigned_attr(DWAttr attr, bool* found, bool* ok) const {\n  DWForm form;\n  auto span = find_attribute(attr, &form, ok);\n  if (span.empty() || !*ok) {\n    *found = false;\n    return 0;\n  }\n  *found = true;\n  return decode_unsigned(span, form, ok);\n}\n\nconst char* DwarfDIE::string_attr(const DwarfCompilationUnit& cu, DWAttr attr, const DebugStrSpans& debug_strs, bool* ok) const {\n  DWForm form;\n  auto span = find_attribute(attr, &form, ok);\n  if (span.empty() || !*ok) {\n    return nullptr;\n  }\n  return decode_string(cu, span, form, debug_strs, ok);\n}\n\nDwarfCompilationUnit DwarfCompilationUnit::next(DwarfSpan* debug_info, DwarfAbbrevs& abbrevs, bool* ok) {\n  DwarfCompilationUnit ret;\n  uint32_t word = DwarfSpan(*debug_info).read_value<uint32_t>(ok);\n  if (!*ok) {\n    return ret;\n  }\n  if (word == 0xFFFFFFFF) {\n    ret.init_size<Dwarf64>(debug_info, abbrevs, ok);\n  } else {\n    ret.init_size<Dwarf32>(debug_info, abbrevs, ok);\n  }\n  return ret;\n}\n\ntemplate <typename D> void DwarfCompilationUnit::init_size(DwarfSpan* debug_info, DwarfAbbrevs& abbrevs, bool* ok) {\n  auto h = DwarfSpan(*debug_info).read<Dwarf4CompilationUnitHeader<D>>(ok);\n  if (!*ok) {\n    return;\n  }\n  if (2 <= h->version && h->version <= 4) {\n    init<Dwarf4CompilationUnitHeader<D>>(debug_info, abbrevs, ok);\n  } else if (h->version == 5) {\n    auto hh = DwarfSpan(*debug_info).read<Dwarf5CompilationUnitHeader<D>>(ok);\n    if (!*ok) {\n      return;\n    }\n    if (hh->unit_type == DW_UT_skeleton || hh->unit_type == DW_UT_split_compile) {\n      init<Dwarf5SkeletonSplitCompilationUnitHeader<D>>(debug_info, abbrevs, ok);\n    } else {\n      init<Dwarf5CompilationUnitHeader<D>>(debug_info, abbrevs, ok);\n    }\n  } else {\n    LOG(warn) << \"Unknown compilation unit version \" << h->version;\n    *ok = false;\n  }\n}\n\ntemplate <typename H> void DwarfCompilationUnit::init(DwarfSpan* debug_info, DwarfAbbrevs& abbrevs, bool* ok) {\n  DwarfSpan span(*debug_info);\n  auto h = span.read<H>(ok);\n  if (!*ok) {\n    return;\n  }\n  uint64_t length = h->preamble.unit_length;\n  if (length >= UINT64_MAX - 12) {\n    LOG(warn) << \"Invalid CU length\";\n    *ok = false;\n    return;\n  }\n  debug_info->consume(length + sizeof(h->preamble));\n  DwarfAbbrevSet& abbrev_set = abbrevs.lookup(h->debug_abbrev_offset);\n  die_ = make_unique<DwarfDIE>(span, abbrev_set, sizeof(typename H::Size::Offset), h->address_size, ok);\n  if (!*ok) {\n    return;\n  }\n  if (die_->tag() != DW_TAG_compile_unit &&\n      die_->tag() != DW_TAG_partial_unit &&\n      die_->tag() != DW_TAG_skeleton_unit) {\n    LOG(warn) << \"CU DIE is not DW_TAG_compilation_unit/DW_TAG_partial_unit/DW_TAG_skeleton_unit!\";\n    *ok = false;\n    return;\n  }\n  entry_size_ = H::Size::EntrySize;\n  h->install_dwo_id(this);\n}\n\nuint64_t DwarfCompilationUnit::read_entry_sized_value(DwarfSpan span, bool* ok) const {\n  if (entry_size() == 4) {\n    return span.read_value<uint32_t>(ok);\n  } else if (entry_size() == 8) {\n    return span.read_value<uint64_t>(ok);\n  } else {\n    LOG(warn) << \"Unknown entry size \" << entry_size();\n    *ok = false;\n    return 0;\n  }\n}\n\nDwarfLineNumberTable::DwarfLineNumberTable(const DwarfCompilationUnit& cu, DwarfSpan span, const DebugStrSpans& debug_str, bool* ok) {\n  uint32_t word = DwarfSpan(span).read_value<uint32_t>(ok);\n  if (!*ok) {\n    return;\n  }\n  if (word == 0xFFFFFFFF) {\n    init_size<Dwarf64>(cu, span, debug_str, ok);\n  } else {\n    init_size<Dwarf32>(cu, span, debug_str, ok);\n  }\n}\n\ntemplate <typename D> void DwarfLineNumberTable::init_size(const DwarfCompilationUnit& cu, DwarfSpan span, const DebugStrSpans& debug_str, bool* ok) {\n  auto h = DwarfSpan(span).read<Dwarf2LineNumberTableHeader<D>>(ok);\n  if (!*ok) {\n    return;\n  }\n  if (2 <= h->version && h->version <= 3) {\n    init<Dwarf2LineNumberTableHeader<D>>(cu, span, debug_str, ok);\n  } else if (h->version == 4) {\n    init<Dwarf4LineNumberTableHeader<D>>(cu, span, debug_str, ok);\n  } else if (h->version == 5) {\n    init<Dwarf5LineNumberTableHeader<D>>(cu, span, debug_str, ok);\n  } else {\n    LOG(warn) << \"Unknown compilation unit version \" << h->version;\n    *ok = false;\n  }\n}\n\nstatic bool read_dwarf2_directories(DwarfSpan span, std::vector<const char*>& directories, std::vector<DwarfSourceFile>& files) {\n  bool ok = true;\n  directories.push_back(nullptr);\n  while (true) {\n    const char* dir = span.read_null_terminated_string(&ok);\n    if (!ok) {\n      return ok;\n    }\n    if (!*dir) {\n      break;\n    }\n    directories.push_back(dir);\n  }\n  files.push_back({ 0, nullptr });\n  while (true) {\n    const char* file = span.read_null_terminated_string(&ok);\n    if (!ok) {\n      return ok;\n    }\n    if (!*file) {\n      break;\n    }\n    uint64_t dir = span.read_uleb(&ok);\n    if (dir >= directories.size()) {\n      LOG(warn) << \"Invalid directory index, bailing\";\n      return false;\n    }\n    span.read_uleb(&ok); // timestamp\n    span.read_uleb(&ok); // length\n    if (!ok) {\n      return ok;\n    }\n    files.push_back({ dir, file });\n  }\n\n  return ok;\n}\n\ntemplate<typename T>\nbool Dwarf2LineNumberTableHeader<T>::read_directories(const DwarfCompilationUnit&,\n                                                      DwarfSpan span,\n                                                      const DebugStrSpans&,\n                                                      std::vector<const char*>& directories,\n                                                      std::vector<DwarfSourceFile>& files) const {\n  return read_dwarf2_directories(span, directories, files);\n}\n\ntemplate<typename T>\nbool Dwarf4LineNumberTableHeader<T>::read_directories(const DwarfCompilationUnit&,\n                                                      DwarfSpan span,\n                                                      const DebugStrSpans&,\n                                                      std::vector<const char*>& directories,\n                                                      std::vector<DwarfSourceFile>& files) const {\n  return read_dwarf2_directories(span, directories, files);\n}\n\nstruct FileEntryFormat {\n  DWLnct content_type;\n  DWForm form;\n};\n\ntemplate<typename T>\nbool Dwarf5LineNumberTableHeader<T>::read_directories(const DwarfCompilationUnit& cu,\n                                                      DwarfSpan span,\n                                                      const DebugStrSpans& debug_str,\n                                                      std::vector<const char*>& directories,\n                                                      std::vector<DwarfSourceFile>& files) const {\n  bool ok = true;\n  uint64_t directory_entry_format_count = span.read_uleb(&ok);\n  if (!ok) {\n    return ok;\n  }\n\n  bool seen_lnct_path = false;\n  std::vector<FileEntryFormat> directory_formats;\n  for (uint64_t i = 0; i < directory_entry_format_count; ++i) {\n    DWLnct content_type = (DWLnct)span.read_uleb(&ok);\n    if (!ok) {\n      return ok;\n    }\n    if (content_type == DW_LNCT_path) {\n      if (seen_lnct_path) {\n        LOG(warn) << \"DW_LNCT_path appears twice in directories!\";\n        return false;\n      }\n      seen_lnct_path = true;\n    }\n\n    DWForm form = (DWForm)span.read_uleb(&ok);\n    if (!ok) {\n      return ok;\n    }\n    directory_formats.push_back({ content_type, form });\n  }\n\n  if (!seen_lnct_path) {\n    LOG(warn) << \"DW_LNCT_path does not appear in directories\";\n    return false;\n  }\n\n  uint64_t directories_count = span.read_uleb(&ok);\n  if (!ok) {\n    return ok;\n  }\n\n  for (uint64_t i = 0; i < directories_count; ++i) {\n    for (auto format: directory_formats) {\n      switch (format.content_type) {\n        case DW_LNCT_path: {\n          size_t size = form_size(format.form, address_size, Size::EntrySize, &span, &ok);\n          DwarfSpan a_span = span.consume(size);\n          auto directory = decode_string(cu, a_span, format.form, debug_str, &ok);\n          if (!ok) {\n            return ok;\n          }\n          directories.push_back(directory);\n          break;\n        }\n        default:\n          LOG(warn) << \"Unknown DW_LNCT \" << format.content_type << \" for directory\";\n          return false;\n      }\n    }\n  }\n\n  uint64_t file_entry_format_count = span.read_uleb(&ok);\n  if (!ok) {\n    return ok;\n  }\n\n  seen_lnct_path = false;\n  std::vector<FileEntryFormat> file_formats;\n  for (uint64_t i = 0; i < file_entry_format_count; ++i) {\n    DWLnct content_type = (DWLnct)span.read_uleb(&ok);\n    if (!ok) {\n      return ok;\n    }\n    if (content_type == DW_LNCT_path) {\n      if (seen_lnct_path) {\n        LOG(warn) << \"DW_LNCT_path appears twice in files!\";\n        return false;\n      }\n      seen_lnct_path = true;\n    }\n\n    DWForm form = (DWForm)span.read_uleb(&ok);\n    if (!ok) {\n      return ok;\n    }\n    file_formats.push_back({ content_type, form });\n  }\n\n  if (!seen_lnct_path) {\n    LOG(warn) << \"DW_LNCT_path does not appear in files\";\n    return false;\n  }\n\n  uint64_t files_count = span.read_uleb(&ok);\n  if (!ok) {\n    return ok;\n  }\n\n  for (uint64_t i = 0; i < files_count; ++i) {\n    uint64_t directory_index = 0;\n    const char* file_path = NULL;\n    for (auto format: file_formats) {\n      switch (format.content_type) {\n        case DW_LNCT_path: {\n          size_t size = form_size(format.form, address_size, Size::EntrySize, &span, &ok);\n          DwarfSpan a_span = span.consume(size);\n          file_path = decode_string(cu, a_span, format.form, debug_str, &ok);\n          if (!ok) {\n            return ok;\n          }\n          break;\n        }\n        case DW_LNCT_directory_index: {\n          size_t size = form_size(format.form, address_size, Size::EntrySize, &span, &ok);\n          DwarfSpan a_span = span.consume(size);\n          directory_index = decode_unsigned(a_span, format.form, &ok);\n          if (!ok) {\n            return ok;\n          }\n          break;\n        }\n        case DW_LNCT_md5: {\n          if (format.form != DW_FORM_data16) {\n            LOG(warn) << \"md5 has unexpected form \" << format.form;\n            return false;\n          }\n          size_t size = form_size(format.form, address_size, Size::EntrySize, &span, &ok);\n          span.consume(size);\n          break;\n        }\n        default:\n          LOG(warn) << \"Unknown DW_LNCT \" << format.content_type << \" for file\";\n          return false;\n      }\n    }\n\n    files.push_back({ directory_index, file_path });\n  }\n\n  return true;\n}\n\ntemplate <typename H> void DwarfLineNumberTable::init(const DwarfCompilationUnit& cu,\n                                                      DwarfSpan span,\n                                                      const DebugStrSpans& debug_str,\n                                                      bool* ok) {\n  auto h = span.read<H>(ok);\n  if (!*ok) {\n    return;\n  }\n  for (uint8_t i = 1; i < h->opcode_base; ++i) {\n    span.read_uleb(ok);\n  }\n  if (!*ok) {\n    return;\n  }\n  *ok = h->read_directories(cu, span, debug_str, directories_, file_names_);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Dwarf.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_DWARF_H_\n#define RR_DWARF_H_\n\n#include <stdint.h>\n\n#include <memory>\n#include <unordered_map>\n#include <vector>\n\n#include \"cpp_supplement.h\"\n\nnamespace rr {\n\nenum DWTag {\n  DW_TAG_null = 0,\n  DW_TAG_compile_unit = 0x11,\n  DW_TAG_partial_unit = 0x3c,\n  DW_TAG_skeleton_unit = 0x4a,\n};\n\nenum DWAttr {\n  DW_AT_name = 0x03,\n  DW_AT_stmt_list = 0x10,\n  DW_AT_comp_dir = 0x1b,\n  DW_AT_str_offsets_base = 0x72,\n  DW_AT_dwo_name = 0x76,\n  DW_AT_GNU_dwo_name = 0x2130,\n  DW_AT_GNU_dwo_id = 0x2131,\n};\n\nenum DWChildren {\n  DW_CHILDREN_no = 0x00,\n  DW_CHILDREN_yes = 0x01\n};\n\nenum DWForm {\n  DW_FORM_addr = 0x01,\n  DW_FORM_block2 = 0x03,\n  DW_FORM_block4 = 0x04,\n  DW_FORM_data2 = 0x05,\n  DW_FORM_data4 = 0x06,\n  DW_FORM_data8 = 0x07,\n  DW_FORM_string = 0x08,\n  DW_FORM_data1 = 0x0b,\n  DW_FORM_flag = 0x0c,\n  DW_FORM_strp = 0x0e,\n  DW_FORM_udata= 0x0f,\n  DW_FORM_indirect = 0x16,\n  DW_FORM_sec_offset = 0x17,\n  DW_FORM_flag_present = 0x19,\n  DW_FORM_strx = 0x1a,\n  DW_FORM_addrx = 0x1b,\n  DW_FORM_strp_sup = 0x1d,\n  DW_FORM_data16 = 0x1e,\n  DW_FORM_line_strp = 0x1f,\n  DW_FORM_implicit_const = 0x21,\n  DW_FORM_rnglistx = 0x23,\n  DW_FORM_strx1 = 0x25,\n  DW_FORM_strx2 = 0x26,\n  DW_FORM_strx3 = 0x27,\n  DW_FORM_strx4 = 0x28,\n  DW_FORM_GNU_strp_alt = 0x1f21,\n};\n\nenum DWLnct {\n  DW_LNCT_path = 0x1,\n  DW_LNCT_directory_index = 0x2,\n  DW_LNCT_md5 = 0x5,\n};\n\nenum DWUt {\n  DW_UT_compile = 0x01,\n  DW_UT_skeleton = 0x04,\n  DW_UT_split_compile = 0x05,\n};\n\nclass DwarfSpan {\npublic:\n  DwarfSpan(const uint8_t* start, const uint8_t* end) : start(start), end(end) {}\n  DwarfSpan(const DwarfSpan& other) = default;\n  DwarfSpan& operator=(const DwarfSpan& other) = default;\n  DwarfSpan() : start(nullptr), end(nullptr) {}\n  size_t size() const { return end - start; }\n  uint64_t read_uleb(bool* ok);\n  DwarfSpan read_leb_ref(bool* ok);\n  const char* read_null_terminated_string(bool* ok);\n  template <typename T> const T* read(bool *ok) {\n    if (size() < sizeof(T)) {\n      *ok = false;\n      return nullptr;\n    }\n    auto ret = reinterpret_cast<const T*>(start);\n    start += sizeof(T);\n    return ret;\n  }\n  template <typename T> T read_value(bool *ok) {\n    const T* r = read<T>(ok);\n    return r ? *r : T();\n  }\n  bool empty() {\n    return start == end;\n  }\n  DwarfSpan subspan(uint64_t offset, uint64_t sz = UINT64_MAX) const {\n    DwarfSpan ret(*this);\n    if (size() <= offset) {\n      ret.start = end;\n      return ret;\n    }\n    ret.start += offset;\n    if (ret.size() <= sz) {\n      return ret;\n    }\n    ret.end = ret.start + sz;\n    return ret;\n  }\n  DwarfSpan consume(uint64_t sz) {\n    DwarfSpan ret(*this);\n    if (size() <= sz) {\n      start = end;\n      return ret;\n    }\n    ret.end = ret.start + sz;\n    start = ret.end;\n    return ret;\n  }\nprivate:\n  const uint8_t* start;\n  const uint8_t* end;\n};\n\nstruct DebugStrSpans {\n  DwarfSpan debug_str;\n  DwarfSpan debug_str_sup;\n  DwarfSpan debug_str_offsets;\n  DwarfSpan debug_line_str;\n};\n\nstruct DwarfAbbrevAttribute {\n  uint64_t name;\n  DWForm form;\n  DwarfSpan constant; // DWARF5\n};\n\nstruct DwarfAbbrev {\n  DwarfAbbrev() : tag(DW_TAG_null), children(DW_CHILDREN_no) {}\n  std::vector<DwarfAbbrevAttribute> attributes;\n  DWTag tag;\n  DWChildren children;\n};\n\nclass DwarfAbbrevSet {\npublic:\n  DwarfAbbrevSet(DwarfSpan span) : remaining_span(span) {}\n  DwarfAbbrev* lookup(uint64_t code);\nprivate:\n  std::unordered_map<uint64_t, std::unique_ptr<DwarfAbbrev>> abbrevs;\n  DwarfSpan remaining_span;\n};\n\nclass DwarfAbbrevs {\npublic:\n  DwarfAbbrevs(DwarfSpan debug_abbrev) : debug_abbrev(debug_abbrev) {}\n  DwarfAbbrevSet& lookup(uint64_t offset);\nprivate:\n  DwarfSpan debug_abbrev;\n  std::unordered_map<uint64_t, std::unique_ptr<DwarfAbbrevSet>> abbrevs;\n};\n\nclass DwarfCompilationUnit;\n\nclass DwarfDIE {\npublic:\n  DwarfDIE(DwarfSpan span, DwarfAbbrevSet& abbrevs, uint8_t dwarf_size, uint8_t address_size, bool* ok);\n  DWTag tag() const { return abbrev->tag; }\n  // Returns empty span if not found\n  DwarfSpan find_attribute(DWAttr attr, DWForm* form, bool* ok) const;\n  // Returns -1 if no attr\n  int64_t section_ptr_attr(DWAttr attr, bool* ok) const;\n  // Sets *found to false if not found.\n  uint64_t unsigned_attr(DWAttr attr, bool* found, bool* ok) const;\n  // Returns nullptr if no attr\n  const char* string_attr(const DwarfCompilationUnit& unit, DWAttr attr, const DebugStrSpans& debug_str, bool* ok) const;\nprivate:\n  DwarfAbbrev* abbrev;\n  DwarfSpan attr_span;\n  uint8_t address_size;\n  uint8_t dwarf_size;\n};\n\nclass DwarfCompilationUnit {\npublic:\n  // Consumes debug_info span and leaves rest behind\n  static DwarfCompilationUnit next(DwarfSpan* debug_info, DwarfAbbrevs& abbrevs, bool* ok);\n  const DwarfDIE& die() const { return *die_; }\n  uint64_t dwo_id() const { return dwo_id_; }\n  void set_dwo_id(uint64_t dwo_id) { dwo_id_ = dwo_id; }\n  uint64_t str_offsets_base() const { return str_offsets_base_; }\n  void set_str_offsets_base(uint64_t str_offsets_base) { str_offsets_base_ = str_offsets_base; }\n  uint8_t entry_size() const { return entry_size_; }\n  uint64_t read_entry_sized_value(DwarfSpan span, bool* ok) const;\nprivate:\n  DwarfCompilationUnit() {}\n  template <typename D> void init_size(DwarfSpan* debug_info, DwarfAbbrevs& abbrevs, bool* ok);\n  template <typename H> void init(DwarfSpan* debug_info, DwarfAbbrevs& abbrevs, bool* ok);\n  std::unique_ptr<DwarfDIE> die_;\n  uint64_t dwo_id_;\n  uint64_t str_offsets_base_;\n  uint8_t entry_size_;\n};\n\nstruct DwarfSourceFile {\n  uint64_t directory_index;\n  const char* file_name;\n};\n\nclass DwarfLineNumberTable {\npublic:\n  DwarfLineNumberTable(const DwarfCompilationUnit& cu, DwarfSpan span, const DebugStrSpans& debug_strs, bool* ok);\n  // Null directory pointer means \"compilation dir\". The first entry is null.\n  const std::vector<const char*>& directories() const { return directories_; }\n  // Null file name means \"compilation unit name\". The first entry is null.\n  const std::vector<DwarfSourceFile>& file_names() const { return file_names_; }\nprivate:\n  template <typename D> void init_size(const DwarfCompilationUnit& cu, DwarfSpan span, const DebugStrSpans& debug_strs, bool* ok);\n  template <typename H> void init(const DwarfCompilationUnit& cu, DwarfSpan span, const DebugStrSpans& debug_strs, bool* ok);\n  std::vector<const char*> directories_;\n  std::vector<DwarfSourceFile> file_names_;\n};\n\n} // namespace rr\n\n#endif /* RR_DWARF_H_ */\n"
  },
  {
    "path": "src/ElfReader.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ElfReader.h\"\n\n#include <elf.h>\n#include <endian.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n#include <zlib.h>\n#ifdef ZSTD\n#include <zstd.h>\n#endif\n\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass ElfReaderImplBase {\npublic:\n  ElfReaderImplBase(ElfReader& r) : r(r), ok_(false) {}\n  virtual ~ElfReaderImplBase() {}\n  virtual SymbolTable read_symbols(const char* symtab, const char* strtab) = 0;\n  virtual DynamicSection read_dynamic() = 0;\n  virtual Debuglink read_debuglink() = 0;\n  virtual Debugaltlink read_debugaltlink() = 0;\n  virtual string read_buildid() = 0;\n  virtual string read_interp() = 0;\n  virtual bool addr_to_phdr(uintptr_t addr, PhdrInfo& phdr) = 0;\n  virtual SectionOffsets find_section_file_offsets(const char* name) = 0;\n  virtual const vector<uint8_t>* decompress_section(SectionOffsets offsets) = 0;\n  bool ok() { return ok_; }\n\nprotected:\n  ElfReader& r;\n  vector<unique_ptr<vector<uint8_t>>> decompressed_sections;\n  bool ok_;\n};\n\ntemplate <typename Arch> class ElfReaderImpl : public ElfReaderImplBase {\npublic:\n  ElfReaderImpl(ElfReader& r);\n  virtual SymbolTable read_symbols(const char* symtab,\n                                   const char* strtab) override;\n  virtual DynamicSection read_dynamic() override;\n  virtual Debuglink read_debuglink() override;\n  virtual Debugaltlink read_debugaltlink() override;\n  virtual string read_buildid() override;\n  virtual string read_interp() override;\n  virtual bool addr_to_phdr(uintptr_t addr, PhdrInfo& phdr) override;\n  virtual SectionOffsets find_section_file_offsets(const char* name) override;\n  virtual const vector<uint8_t>* decompress_section(SectionOffsets offsets) override;\n\nprivate:\n  const typename Arch::ElfShdr* find_section(const char* n);\n  const typename Arch::ElfPhdr* find_programheader(uint32_t pt);\n\n  const typename Arch::ElfEhdr* elfheader;\n  const typename Arch::ElfPhdr* programheader;\n  const typename Arch::ElfShdr* sections;\n  size_t programheader_size;\n  size_t sections_size;\n  vector<char> section_names;\n};\n\ntemplate <typename Arch>\nunique_ptr<ElfReaderImplBase> elf_reader_impl_arch(ElfReader& r) {\n  return unique_ptr<ElfReaderImplBase>(new ElfReaderImpl<Arch>(r));\n}\n\nunique_ptr<ElfReaderImplBase> elf_reader_impl(ElfReader& r,\n                                              SupportedArch arch) {\n  RR_ARCH_FUNCTION(elf_reader_impl_arch, arch, r);\n}\n\ntemplate <typename Arch>\nElfReaderImpl<Arch>::ElfReaderImpl(ElfReader& r) : ElfReaderImplBase(r) {\n  elfheader = r.read<typename Arch::ElfEhdr>(0);\n  if (!elfheader || memcmp(elfheader, ELFMAG, SELFMAG) != 0 ||\n      elfheader->e_ident[EI_CLASS] != Arch::elfclass ||\n      elfheader->e_ident[EI_DATA] != Arch::elfendian ||\n      elfheader->e_machine != Arch::elfmachine ||\n      elfheader->e_shentsize != sizeof(typename Arch::ElfShdr) ||\n      elfheader->e_phentsize != sizeof(typename Arch::ElfPhdr) ||\n      elfheader->e_shstrndx >= elfheader->e_shnum) {\n    LOG(debug) << \"Invalid ELF file: invalid header\";\n    return;\n  }\n\n  programheader =\n      r.read<typename Arch::ElfPhdr>(elfheader->e_phoff, elfheader->e_phnum);\n  if (!programheader) {\n    LOG(debug) << \"Invalid ELF file: no program headers\";\n    return;\n  }\n  programheader_size = elfheader->e_phnum;\n\n  sections =\n      r.read<typename Arch::ElfShdr>(elfheader->e_shoff, elfheader->e_shnum);\n  if (!sections || !elfheader->e_shnum) {\n    LOG(debug) << \"Invalid ELF file: no sections\";\n    return;\n  }\n  sections_size = elfheader->e_shnum;\n\n  auto& section_names_section = sections[elfheader->e_shstrndx];\n  const char* section_names_ptr = r.read<char>(section_names_section.sh_offset,\n                                               section_names_section.sh_size);\n  if (!section_names_ptr || !section_names_section.sh_size) {\n    LOG(debug) << \"Invalid ELF file: can't read section names\";\n    return;\n  }\n  // Ensure final 0\n  section_names.resize(section_names_section.sh_size);\n  memcpy(section_names.data(), section_names_ptr, section_names.size());\n  section_names[section_names.size() - 1] = 0;\n\n  ok_ = true;\n}\n\ntemplate <typename Arch>\nconst typename Arch::ElfPhdr* ElfReaderImpl<Arch>::find_programheader(uint32_t pt) {\n  const typename Arch::ElfPhdr* ph = nullptr;\n\n  for (size_t i = 0; i < programheader_size; ++i) {\n    auto& p = programheader[i];\n    if (p.p_type == pt) {\n      ph = &p;\n    }\n  }\n\n  if (!ph) {\n    LOG(debug) << \"Missing program header \" << pt;\n  }\n  return ph;\n}\n\ntemplate <typename Arch>\nconst typename Arch::ElfShdr* ElfReaderImpl<Arch>::find_section(const char* n) {\n  const typename Arch::ElfShdr* section = nullptr;\n\n  for (size_t i = 0; i < sections_size; ++i) {\n    auto& s = sections[i];\n    if (s.sh_name >= section_names.size()) {\n      LOG(debug) << \"Invalid ELF file: invalid name offset for section \" << i;\n      continue;\n    }\n    const char* name = section_names.data() + s.sh_name;\n    if (strcmp(name, n) == 0) {\n      if (section) {\n        LOG(debug) << \"Invalid ELF file: duplicate symbol section \" << n;\n        return nullptr;\n      }\n      section = &s;\n    }\n  }\n\n  if (!section) {\n    LOG(debug) << \"Missing section \" << n;\n  }\n  return section;\n}\n\ntemplate <typename Arch>\nSectionOffsets ElfReaderImpl<Arch>::find_section_file_offsets(\n    const char* name) {\n  SectionOffsets offsets = { 0, 0, false };\n  const typename Arch::ElfShdr* section = find_section(name);\n  if (!section) {\n    return offsets;\n  }\n  offsets.start = section->sh_offset;\n  offsets.end = section->sh_offset + section->sh_size;\n  offsets.compressed = !!(section->sh_flags & SHF_COMPRESSED);\n  return offsets;\n}\n\ntemplate <typename Arch>\nconst vector<uint8_t>* ElfReaderImpl<Arch>::decompress_section(SectionOffsets offsets) {\n  bool zlib = false;\n  __attribute__((unused)) bool zstd = false;\n  DEBUG_ASSERT(offsets.compressed);\n  auto hdr = r.read<typename Arch::ElfChdr>(offsets.start);\n  if (!hdr) {\n    LOG(warn) << \"section at \" << offsets.start\n              << \" is marked compressed but is too small\";\n    return nullptr;\n  }\n\n  size_t decompressed_size = 0;\n  if (hdr->ch_type == ELFCOMPRESS_ZLIB || hdr->ch_type == ELFCOMPRESS_ZSTD) {\n    decompressed_size = hdr->ch_size;\n    offsets.start += sizeof(typename Arch::ElfChdr);\n    if (hdr->ch_type == ELFCOMPRESS_ZLIB) {\n      zlib = true;\n    } else {\n      zstd = true;\n    }\n  } else {\n    auto legacy_hdr = r.read_bytes(offsets.start, 4);\n    if (!memcmp(\"ZLIB\", legacy_hdr, 4)) {\n      auto be_size = r.read<uint64_t>(offsets.start + 4);\n      decompressed_size = be64toh(*be_size);\n      offsets.start += 12;\n      zlib = true;\n    } else {\n      LOG(warn) << \"section at \" << offsets.start\n                << \" is marked compressed but uses unrecognized\"\n                << \" type \" << HEX(hdr->ch_type);\n      return nullptr;\n    }\n  }\n\n  unique_ptr<vector<uint8_t>> v(new vector<uint8_t>());\n  v->resize(decompressed_size);\n\n  if (zlib) {\n    z_stream stream;\n    memset(&stream, 0, sizeof(stream));\n    int result = inflateInit(&stream);\n    if (result != Z_OK) {\n      FATAL() << \"inflateInit failed!\";\n      return nullptr;\n    }\n\n    stream.avail_in = offsets.end - offsets.start;\n    stream.next_in = (unsigned char*)r.read_bytes(offsets.start, stream.avail_in);\n    stream.next_out = &v->front();\n    stream.avail_out = v->size();\n    result = inflate(&stream, Z_FINISH);\n    if (result != Z_STREAM_END) {\n      FATAL() << \"inflate failed!\";\n      return nullptr;\n    }\n\n    result = inflateEnd(&stream);\n    if (result != Z_OK) {\n      FATAL() << \"inflateEnd failed!\";\n      return nullptr;\n    }\n#ifdef ZSTD\n  } else if (zstd) {\n    size_t compressed_size = offsets.end - offsets.start;\n    size_t size = ZSTD_decompress(&v->front(), v->size(),\n                                  r.read_bytes(offsets.start, compressed_size), compressed_size);\n    if (size != v->size()) {\n      FATAL() << \"zstd decompression failed\";\n    }\n#endif\n  } else {\n    FATAL() << \"Unrecognized compression algorithm\";\n  }\n\n  decompressed_sections.push_back(std::move(v));\n  return decompressed_sections.back().get();\n}\n\ntemplate <typename Arch>\nSymbolTable ElfReaderImpl<Arch>::read_symbols(const char* symtab,\n                                              const char* strtab) {\n  SymbolTable result;\n  if (!ok()) {\n    return result;\n  }\n\n  const typename Arch::ElfShdr* symbols = find_section(symtab);\n  if (!symbols) {\n    return result;\n  }\n  const typename Arch::ElfShdr* strings = find_section(strtab);\n  if (!strings) {\n    return result;\n  }\n\n  if (symbols->sh_entsize != sizeof(typename Arch::ElfSym)) {\n    LOG(debug) << \"Invalid ELF file: incorrect symbol size \"\n               << symbols->sh_entsize;\n    return result;\n  }\n  if (symbols->sh_size % symbols->sh_entsize) {\n    LOG(debug) << \"Invalid ELF file: incorrect symbol section size \"\n               << symbols->sh_size;\n    return result;\n  }\n  if (strings->sh_size == 0) {\n    LOG(debug) << \"Invalid ELF file: empty string table\";\n    return result;\n  }\n\n  size_t symbol_list_size = symbols->sh_size / symbols->sh_entsize;\n  auto symbol_list = r.read<typename Arch::ElfSym>(\n      symbols->sh_offset, symbol_list_size);\n  if (!symbol_list) {\n    LOG(debug) << \"Invalid ELF file: can't read symbols \" << symtab;\n    return result;\n  }\n  auto strtab_ptr = r.read<char>(strings->sh_offset, strings->sh_size);\n  if (!strtab_ptr) {\n    LOG(debug) << \"Invalid ELF file: can't read strings \" << strtab;\n    return result;\n  }\n  result.strtab.resize(strings->sh_size);\n  memcpy(result.strtab.data(), strtab_ptr, result.strtab.size());\n  result.strtab[result.strtab.size() - 1] = 0;\n  result.symbols.resize(symbol_list_size);\n  for (size_t i = 0; i < symbol_list_size; ++i) {\n    auto& s = symbol_list[i];\n    if (s.st_shndx >= sections_size) {\n      // Don't leave this entry uninitialized\n      result.symbols[i] = SymbolTable::Symbol(0, 0);\n      continue;\n    }\n    result.symbols[i] = SymbolTable::Symbol(s.st_value, s.st_name);\n  }\n  return result;\n}\n\ntemplate <typename Arch> DynamicSection ElfReaderImpl<Arch>::read_dynamic() {\n  DynamicSection result;\n  if (!ok()) {\n    return result;\n  }\n\n  const typename Arch::ElfShdr* dynamic = find_section(\".dynamic\");\n  if (!dynamic) {\n    return result;\n  }\n  const typename Arch::ElfShdr* dynstr = find_section(\".dynstr\");\n  if (!dynstr) {\n    return result;\n  }\n\n  if (dynamic->sh_entsize != sizeof(typename Arch::ElfDyn)) {\n    LOG(debug) << \"Invalid ELF file: incorrect .dynamic size \"\n               << dynamic->sh_entsize;\n    return result;\n  }\n  if (!dynamic->sh_size) {\n    return result;\n  }\n  if (dynamic->sh_size % dynamic->sh_entsize) {\n    LOG(debug) << \"Invalid ELF file: incorrect .dynamic section size \"\n               << dynamic->sh_size;\n    return result;\n  }\n  if (dynstr->sh_size == 0) {\n    LOG(debug) << \"Invalid ELF file: empty string table\";\n    return result;\n  }\n\n  size_t dyn_list_size = dynamic->sh_size / dynamic->sh_entsize;\n  auto dyn_list = r.read<typename Arch::ElfDyn>(\n      dynamic->sh_offset, dyn_list_size);\n  if (!dyn_list) {\n    LOG(debug) << \"Invalid ELF file: can't read .dynamic\";\n    return result;\n  }\n  auto strtab = r.read<char>(dynstr->sh_offset, dynstr->sh_size);\n  if (!strtab) {\n    LOG(debug) << \"Invalid ELF file: can't read .dynstr\";\n    return result;\n  }\n  result.strtab.resize(dynstr->sh_size);\n  memcpy(result.strtab.data(), strtab, result.strtab.size());\n  result.strtab[result.strtab.size() - 1] = 0;\n  result.entries.resize(dyn_list_size);\n  for (size_t i = 0; i < dyn_list_size; ++i) {\n    auto& s = dyn_list[i];\n    result.entries[i] = DynamicSection::Entry(s.d_tag, s.d_val);\n  }\n  return result;\n}\n\nstatic bool null_terminated(const char* p, size_t size, string& out) {\n  size_t len = strnlen(p, size);\n  if (len == size) {\n    LOG(warn) << \"Invalid file name\";\n    return false;\n  }\n  out = string(p, len);\n  return true;\n}\n\ntemplate <typename Arch> Debuglink ElfReaderImpl<Arch>::read_debuglink() {\n  Debuglink result;\n  if (!ok()) {\n    return result;\n  }\n\n  const typename Arch::ElfShdr* debuglink = find_section(\".gnu_debuglink\");\n  if (!debuglink) {\n    return result;\n  }\n  if (debuglink->sh_size < 8) {\n    LOG(warn) << \"Invalid ELF file: unexpected .gnu_debuglink length\";\n    return result;\n  }\n\n  size_t crc_offset = debuglink->sh_size - 4;\n  if (!r.read_into(debuglink->sh_offset + crc_offset, &result.crc)) {\n    LOG(warn) << \"Invalid ELF file: can't read .gnu_debuglink crc checksum\";\n    return result;\n  }\n\n  const char* file_name = r.read<char>(debuglink->sh_offset, crc_offset);\n  if (!file_name) {\n    LOG(warn) << \"Invalid ELF file: can't read .gnu_debuglink file_name\";\n    return result;\n  }\n\n  null_terminated(file_name, crc_offset, result.file_name);\n  return result;\n}\n\ntemplate <typename Arch> Debugaltlink ElfReaderImpl<Arch>::read_debugaltlink() {\n  Debugaltlink result;\n  if (!ok()) {\n    return result;\n  }\n\n  const typename Arch::ElfShdr* debuglink = find_section(\".gnu_debugaltlink\");\n  if (!debuglink) {\n    return result;\n  }\n  // Last 20 bytes are the build ID of the target file. Ignore for now.\n  if (debuglink->sh_size < 21) {\n    LOG(warn) << \"Invalid ELF file: unexpected .gnu_debugaltlink length\";\n    return result;\n  }\n\n  size_t build_id_offset = debuglink->sh_size - 20;\n  const char* file_name = r.read<char>(debuglink->sh_offset, build_id_offset);\n  if (!file_name) {\n    LOG(warn) << \"Invalid ELF file: can't read .gnu_debugaltlink file_name\";\n    return result;\n  }\n\n  null_terminated(file_name, build_id_offset, result.file_name);\n  return result;\n}\n\ntemplate <typename Arch>\nstring ElfReaderImpl<Arch>::read_buildid() {\n  string result;\n  if (!ok()) {\n    return result;\n  }\n\n  for (size_t i = 0; i < sections_size; ++i) {\n    auto& s = sections[i];\n    if (s.sh_type != SHT_NOTE) {\n      continue;\n    }\n\n    auto offset = s.sh_offset;\n    auto nhdr = r.read<typename Arch::ElfNhdr>(offset);\n    if (!nhdr) {\n      LOG(error) << \"Failed to read ELF note\";\n      return result;\n    }\n    offset += sizeof(*nhdr);\n\n    char name[4] = { 0 };\n    if (!(nhdr->n_namesz == 4 &&\n          r.read_into(offset, &name) &&\n          memcmp(\"GNU\", name, 4) == 0 &&\n          nhdr->n_descsz > 0)) {\n      continue;\n    }\n    // Note members are 4 byte aligned, twiddle bits to round up if necessary.\n    offset += (nhdr->n_namesz + 3) & ~0x3;\n\n    if (nhdr->n_type != NT_GNU_BUILD_ID) {\n      continue;\n    }\n\n    const uint8_t* id = r.read<uint8_t>(offset, nhdr->n_descsz);\n    if (!id) {\n      LOG(error) << \"Failed to read ELF note contents\";\n      return result;\n    }\n\n    result.reserve(nhdr->n_descsz);\n    for (unsigned i = 0; i < nhdr->n_descsz; ++i) {\n      char byte[3] = { 0 };\n      snprintf(&byte[0], 3, \"%02x\", id[i]);\n      result.append(byte);\n    }\n\n    break;\n  }\n\n  return result;\n}\n\ntemplate <typename Arch>\nstring ElfReaderImpl<Arch>::read_interp() {\n  string result;\n  if (!ok()) {\n    return result;\n  }\n\n  const typename Arch::ElfPhdr* ph = find_programheader(PT_INTERP);\n  if (!ph) {\n    return result;\n  }\n\n  const char* file_name = r.read<char>(ph->p_offset, ph->p_filesz);\n  if (!file_name) {\n    LOG(warn) << \"Invalid ELF file: can't read PT_INTERP\";\n    return result;\n  }\n\n  null_terminated(file_name, ph->p_filesz, result);\n  return result;\n}\n\ntemplate <typename Arch>\nbool ElfReaderImpl<Arch>::addr_to_phdr(uintptr_t addr, PhdrInfo& phdr) {\n  for (size_t i = 0; i < programheader_size; ++i) {\n    auto& p = programheader[i];\n    if (p.p_type == PT_LOAD && addr >= p.p_vaddr &&\n        addr - p.p_vaddr < p.p_memsz) {\n      phdr.vaddr = p.p_vaddr;\n      phdr.offset = p.p_offset;\n      phdr.filesz = p.p_filesz;\n      phdr.flags = p.p_flags;\n      return true;\n    }\n  }\n\n  return false;\n}\n\nElfReader::ElfReader(SupportedArch arch) : arch_(arch), map(nullptr), size(0) {}\n\nElfReader::~ElfReader() {}\n\nElfReaderImplBase& ElfReader::impl() {\n  if (!impl_) {\n    impl_ = elf_reader_impl(*this, arch_);\n  }\n  return *impl_;\n}\n\nSymbolTable ElfReader::read_symbols(const char* symtab, const char* strtab) {\n  return impl().read_symbols(symtab, strtab);\n}\n\nDynamicSection ElfReader::read_dynamic() { return impl().read_dynamic(); }\n\nDebuglink ElfReader::read_debuglink() { return impl().read_debuglink(); }\n\nDebugaltlink ElfReader::read_debugaltlink() { return impl().read_debugaltlink(); }\n\nSectionOffsets ElfReader::find_section_file_offsets(const char* name) {\n  return impl().find_section_file_offsets(name);\n}\n\nDwarfSpan ElfReader::dwarf_section(const char* name, bool known_to_be_compressed) {\n  SectionOffsets offsets = impl().find_section_file_offsets(name);\n  offsets.compressed |= known_to_be_compressed;\n  if (offsets.start && offsets.compressed) {\n    auto decompressed = impl().decompress_section(offsets);\n    return DwarfSpan(decompressed->data(), decompressed->data() + decompressed->size());\n  }\n  return DwarfSpan(map + offsets.start, map + offsets.end);\n}\n\nstring ElfReader::read_buildid() { return impl().read_buildid(); }\nstring ElfReader::read_interp() { return impl().read_interp(); }\n\nbool ElfReader::addr_to_phdr(uintptr_t addr, PhdrInfo& phdr) {\n  return impl().addr_to_phdr(addr, phdr);\n}\n\nbool ElfReader::ok() { return impl().ok(); }\n\nElfFileReader::ElfFileReader(ScopedFd& fd, SupportedArch arch) : ElfReader(arch) {\n  struct stat st;\n  if (fstat(fd, &st) < 0) {\n    FATAL() << \"Can't stat fd\";\n  }\n  if (st.st_size > 0) {\n    map = static_cast<uint8_t*>(mmap(nullptr, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0));\n    if (map == MAP_FAILED) {\n      FATAL() << \"Can't map fd\";\n    }\n  }\n  size = st.st_size;\n}\n\nElfFileReader::~ElfFileReader() {\n  if (map) {\n    munmap(map, size);\n  }\n}\n\nScopedFd ElfFileReader::open_debug_file(const std::string& elf_file_name) {\n  if (elf_file_name.empty() || elf_file_name[0] != '/') {\n    return ScopedFd();\n  }\n\n  Debuglink debuglink = read_debuglink();\n  if (debuglink.file_name.empty()) {\n    return ScopedFd();\n  }\n\n  size_t last_slash = elf_file_name.find_last_of('/');\n  string debug_path = \"/usr/lib/debug/\";\n  debug_path += elf_file_name.substr(0, last_slash) + '/' + debuglink.file_name;\n  ScopedFd debug_fd(debug_path.c_str(), O_RDONLY);\n  if (!debug_fd.is_open()) {\n    return ScopedFd();\n  }\n\n  // Verify that the CRC checksum matches, in case the debuginfo and text file\n  // are in separate packages that are out of sync.\n  uint32_t crc = 0xffffffff;\n  while (true) {\n    unsigned char buf[4096];\n    ssize_t ret = ::read(debug_fd.get(), buf, sizeof(buf));\n    if (ret < 0) {\n      if (errno != EINTR) {\n        LOG(debug) << \"Error reading \" << debug_path;\n        return ScopedFd();\n      }\n    } else if (ret == 0) {\n      break;\n    } else {\n      crc = update_crc32(crc, buf, ret);\n    }\n  }\n\n  if ((crc ^ 0xffffffff) == debuglink.crc) {\n    return debug_fd;\n  }\n  return ScopedFd();\n}\n\nSupportedArch ElfFileReader::identify_arch(ScopedFd& fd) {\n  /**\n   * This code is quite lax. That's OK because this is only used to create\n   * a specific ElfReaderImpl, which does much more thorough checking of the\n   * header.\n   */\n  static const int header_prefix_size = 20;\n  char buf[header_prefix_size];\n  ssize_t ret = read_to_end(fd, 0, buf, sizeof(buf));\n  if (ret != (ssize_t)sizeof(buf) || buf[5] != 1) {\n    return NativeArch::arch();\n  }\n  switch (buf[18] | (buf[19] << 8)) {\n    case 0x03:\n      return x86;\n    case 0x3e:\n      return x86_64;\n    default:\n      return NativeArch::arch();\n  }\n}\n\nbool ElfFileReader::is_x32_abi(__attribute__((unused)) ScopedFd& fd) {\n#if defined(__x86_64__)\n  static const int header_prefix_size = 20;\n  char buf[header_prefix_size];\n  ssize_t ret = read_to_end(fd, 0, buf, sizeof(buf));\n  if (ret != (ssize_t)sizeof(buf) || buf[5] != 1) {\n    // Who knows what this is.\n    return false;\n  }\n  if ((buf[18] | (buf[19] << 8)) == 0x3e) {\n    // x32 ABI programs declare themselves with the amd64 architecture but\n    // only 4 byte wide pointers.\n    return buf[4] == 1;\n  }\n#endif\n\n  return false;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ElfReader.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_ELF_READER_H_\n#define RR_ELF_READER_H_\n\n#include <string.h>\n\n#include <memory>\n#include <vector>\n\n#include \"Dwarf.h\"\n#include \"ScopedFd.h\"\n#include \"kernel_abi.h\"\n\nnamespace rr {\n\nclass ElfReaderImplBase;\n\nclass SymbolTable {\npublic:\n  const char* name(size_t i) const {\n    size_t offset = symbols[i].name_index;\n    return offset < strtab.size() ? &strtab[offset] : nullptr;\n  }\n  bool is_name(size_t i, const char* name) const {\n    size_t offset = symbols[i].name_index;\n    return offset < strtab.size() && strcmp(&strtab[offset], name) == 0;\n  }\n  uintptr_t addr(size_t i) const { return symbols[i].addr; }\n  size_t size() const { return symbols.size(); }\n\n  struct Symbol {\n    Symbol(uintptr_t addr, size_t name_index)\n        : addr(addr), name_index(name_index) {}\n    Symbol() {}\n    uintptr_t addr;\n    size_t name_index;\n  };\n  std::vector<Symbol> symbols;\n  // Last character is always null  map = static_cast<uint8_t*>(fd);\n\n  std::vector<char> strtab;\n};\n\nclass DynamicSection {\npublic:\n  struct Entry {\n  public:\n    Entry(uint64_t tag, uint64_t val) : tag(tag), val(val) {}\n    Entry() {}\n    uint64_t tag;\n    uint64_t val;\n  };\n\n  std::vector<Entry> entries;\n  // Last character is always null\n  std::vector<char> strtab;\n};\n\nclass Debuglink {\npublic:\n  std::string file_name;\n  uint32_t crc;\n};\n\nclass Debugaltlink {\npublic:\n  std::string file_name;\n};\n\nstruct SectionOffsets {\n  uint64_t start;\n  uint64_t end;\n  bool compressed;\n};\n\nstruct PhdrInfo {\n  uint64_t vaddr;\n  uint64_t offset;\n  uint64_t filesz;\n  uint64_t flags;\n};\n\nclass ElfReader {\npublic:\n  ElfReader(SupportedArch arch);\n  virtual ~ElfReader();\n  const void* read_bytes(size_t offset, size_t size) {\n    if (offset + size > this->size) {\n      return nullptr;\n    }\n    return map + offset;\n  }\n  template <typename T> const T* read(size_t offset, size_t count = 1) {\n    return static_cast<const T*>(read_bytes(offset, sizeof(T)*count));\n  }\n  template <typename T> bool read_into(size_t offset, T* out) {\n    auto r = read<T>(offset);\n    if (!r) {\n      return false;\n    }\n    memcpy(out, r, sizeof(*out));\n    return true;\n  }\n  bool ok();\n  SymbolTable read_symbols(const char* symtab, const char* strtab);\n  DynamicSection read_dynamic();\n  Debuglink read_debuglink();\n  Debugaltlink read_debugaltlink();\n  std::string read_buildid();\n  std::string read_interp();\n  // Returns true if ELF address |addr| is mapped from a program header in the\n  // ELF file, and sets the fields of |phdr| to the program header fields.\n  // Returns false if no program header maps to |addr|. |addr| is an address\n  // indicated by the ELF file, not its relocated address in memory.\n  bool addr_to_phdr(uintptr_t addr, PhdrInfo& phdr);\n  SectionOffsets find_section_file_offsets(const char* name);\n  DwarfSpan dwarf_section(const char* name, bool known_to_be_compressed = false);\n  SupportedArch arch() const { return arch_; }\nprivate:\n  ElfReaderImplBase& impl();\n  std::unique_ptr<ElfReaderImplBase> impl_;\n  SupportedArch arch_;\nprotected:\n  uint8_t* map;\n  size_t size;\n};\n\nclass ElfFileReader : public ElfReader {\npublic:\n  ElfFileReader(ScopedFd& fd, SupportedArch arch);\n  ElfFileReader(ScopedFd& fd) : ElfFileReader(fd, identify_arch(fd)) {}\n  ~ElfFileReader();\n  // Finds and opens the debug file corresponding to this reader.\n  // |elf_file_name| is the name of the file already opened by this reader.\n  ScopedFd open_debug_file(const std::string& elf_file_name);\n\n  static SupportedArch identify_arch(ScopedFd& fd);\n  static bool is_x32_abi(ScopedFd& fd);\n};\n\n} // namespace rr\n\n#endif /* RR_ELF_READER_H_ */\n"
  },
  {
    "path": "src/EmuFs.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"EmuFs.h\"\n\n#include <syscall.h>\n#include <sys/mman.h>\n#include <linux/fs.h>\n\n#include <fstream>\n#include <sstream>\n#include <string>\n\n// muslc defines those, but we want a typedef instead\n#if defined(loff_t)\ntypedef loff_t __musl_loff_t;\n#undef loff_t\ntypedef __musl_loff_t loff_t;\n#endif\n\n#include \"AddressSpace.h\"\n#include \"ReplaySession.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nEmuFile::~EmuFile() {\n  LOG(debug) << \"    EmuFs::~File(einode:\" << inode_ << \")\";\n  owner.destroyed_file(*this);\n}\n\nEmuFile::shr_ptr EmuFile::clone(EmuFs& owner) {\n  auto f = EmuFile::create(owner, orig_path.c_str(), device(), inode(), size_);\n\n  // We could try using FICLONE but tmpfs doesn't support that yet so let's just\n  // not bother for now.\n\n  // Avoid copying holes.\n  vector<uint8_t> buf;\n  uint64_t offset = 0;\n  while (offset < size_) {\n    ssize_t ret = lseek(fd(), offset, SEEK_HOLE);\n    if (ret < 0) {\n      ret = size_;\n    } else {\n      if (uint64_t(ret) < offset) {\n        FATAL() << \"lseek returned hole before requested offset\";\n      }\n    }\n    uint64_t hole = ret;\n    // Copy data\n    while (offset < hole) {\n      loff_t off_in = offset;\n      loff_t off_out = offset;\n      ssize_t ncopied = syscall(NativeArch::copy_file_range, file.get(), &off_in,\n                                f->fd().get(), &off_out, hole - offset, 0);\n      if (ncopied >= 0) {\n        if (ncopied == 0) {\n          FATAL() << \"Didn't copy anything\";\n        }\n        offset += ncopied;\n        continue;\n      }\n\n      ssize_t amount = min<uint64_t>(hole - offset, 4*1024*1024);\n      buf.resize(amount);\n      ret = pread64(fd(), buf.data(), amount, offset);\n      if (ret <= 0) {\n        FATAL() << \"Couldn't read all the data\";\n      }\n      ssize_t written = pwrite_all_fallible(f->fd(), buf.data(), ret, offset);\n      if (written < ret) {\n        FATAL() << \"Couldn't write all the data\";\n      }\n      offset += written;\n    }\n    if (offset < size_) {\n      // Look for the end of the hole, if any\n      ret = lseek(fd(), offset, SEEK_DATA);\n      if (ret < 0) {\n        if (errno != ENXIO) {\n          FATAL() << \"Couldn't find data\";\n        }\n        break;\n      }\n      if (uint64_t(ret) <= offset) {\n        FATAL() << \"Zero sized hole? Got \" << ret << \" expected \" << offset;\n      }\n      // Skip the hole\n      offset = ret;\n    }\n  }\n\n  return f;\n}\n\nstring EmuFile::proc_path() const {\n  stringstream ss;\n  ss << \"/proc/\" << getpid() << \"/fd/\" << fd().get();\n  return ss.str();\n}\n\nvoid EmuFile::update(dev_t device, ino_t inode, uint64_t size) {\n  DEBUG_ASSERT(device_ == device && inode_ == inode);\n  ensure_size(size);\n}\n\nvoid EmuFile::ensure_size(uint64_t size) {\n  if (size_ < size) {\n    resize_shmem_segment(file, size);\n    size_ = size;\n  }\n}\n\nstd::string make_temp_name(const string& orig_path, dev_t orig_device,\n                           ino_t orig_inode)\n{\n  stringstream name;\n  name << \"rr-emufs-\" << getpid() << \"-dev-\" << orig_device\n       << \"-inode-\" << orig_inode << \"-\" << orig_path;\n  // The linux man page for memfd_create says the length limit for the name\n  // argument is 249 bytes, evidently because it prepends \"memfd:\" to the\n  // parameter before using it.\n  return name.str().substr(0, 249);\n}\n\n/*static*/ EmuFile::shr_ptr EmuFile::create(EmuFs& owner,\n                                            const string& orig_path,\n                                            dev_t orig_device, ino_t orig_inode,\n                                            uint64_t orig_file_size) {\n  string real_name = make_temp_name(orig_path, orig_device, orig_inode);\n  ScopedFd fd(open_memory_file(real_name));\n  if (!fd.is_open()) {\n    FATAL() << \"Failed to create shmem segment for \" << real_name;\n  }\n  resize_shmem_segment(fd, orig_file_size);\n\n  shr_ptr f(new EmuFile(owner, std::move(fd), orig_path, real_name, orig_device,\n                        orig_inode, orig_file_size));\n\n  LOG(debug) << \"created emulated file for \" << orig_path << \" as \"\n             << real_name;\n  return f;\n}\n\nEmuFile::EmuFile(EmuFs& owner, ScopedFd&& fd, const string& orig_path,\n                 const string& real_path, dev_t orig_device, ino_t orig_inode,\n                 uint64_t orig_file_size)\n    : orig_path(orig_path),\n      tmp_path(real_path),\n      file(std::move(fd)),\n      owner(owner),\n      size_(orig_file_size),\n      device_(orig_device),\n      inode_(orig_inode) {}\n\nEmuFile::shr_ptr EmuFs::at(const KernelMapping& recorded_map) const {\n  return files.at(FileId(recorded_map)).lock();\n}\n\nbool EmuFs::has_file_for(const KernelMapping& recorded_map) const {\n  return files.find(FileId(recorded_map)) != files.end();\n}\n\nEmuFile::shr_ptr EmuFs::clone_file(EmuFile::shr_ptr file) {\n  DEBUG_ASSERT(file);\n  auto c = file->clone(*this);\n  files[FileId(*file)] = c;\n  return c;\n}\n\nEmuFile::shr_ptr EmuFs::get_or_create(const KernelMapping& recorded_km) {\n  FileId id(recorded_km);\n  auto it = files.find(id);\n  uint64_t min_file_size =\n    recorded_km.file_offset_bytes() + recorded_km.size();\n  if (it != files.end()) {\n    it->second.lock()->update(recorded_km.device(), recorded_km.inode(),\n                              min_file_size);\n    return it->second.lock();\n  }\n  auto vf = EmuFile::create(*this, recorded_km.fsname(), recorded_km.device(),\n                            recorded_km.inode(), min_file_size);\n  files[id] = vf;\n  return vf;\n}\n\nEmuFile::shr_ptr EmuFs::find(dev_t device, ino_t inode) {\n  FileId id(device, inode);\n  auto it = files.find(id);\n  if (it == files.end()) {\n    return EmuFile::shr_ptr();\n  }\n  return it->second.lock();\n}\n\nvoid EmuFs::log() const {\n  LOG(error) << \"EmuFs \" << this << \" with \" << files.size() << \" files:\";\n  for (auto& kv : files) {\n    auto file = kv.second.lock();\n    LOG(error) << \"  \" << file->emu_path();\n  }\n}\n\n/*static*/ EmuFs::shr_ptr EmuFs::create() { return shr_ptr(new EmuFs()); }\n\nEmuFs::EmuFs() {}\n\nFileId::FileId(const KernelMapping& recorded_map)\n    : device(recorded_map.device()), inode(recorded_map.inode()) {}\n\nFileId::FileId(const EmuFile& emu_file)\n    : device(emu_file.device()), inode(emu_file.inode()) {}\n\n} // namespace rr\n"
  },
  {
    "path": "src/EmuFs.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_EMUFS_H_\n#define RR_EMUFS_H_\n\n#include <map>\n#include <memory>\n#include <string>\n#include <vector>\n\n#include \"ScopedFd.h\"\n\nnamespace rr {\n\nclass AddressSpace;\nclass EmuFs;\nclass KernelMapping;\nclass ReplaySession;\nclass Session;\nclass Task;\n\n/**\n * Implement an \"emulated file system\" consisting of files that were\n * mmap'd shared during recording.  These files require special\n * treatment because (i) they were most likely modified during\n * recording, so (ii) the original file contents only exist as\n * snapshots in the trace, but (iii) all mappings of the file must\n * point at the same underlying resource, so that modifications are\n * seen by all mappees.\n *\n * The rr EmuFs creates \"emulated files\" in shared memory during\n * replay.  Each efile is uniquely identified at a given event in the\n * trace by |(edev, einode)| (i.e., the recorded device ID and inode).\n * \"What about inode recycling\", you're probably thinking to yourself.\n * This scheme can cope with inode recycling, given a very important\n * assumption discussed below.\n *\n * Why is inode recycling not a problem?  Assume that an mmap'd file\n * F_0 at trace time t_0 has the same (device, inode) ID as a\n * different file F_1 at trace time t_1.  By definition, if the inode\n * ID was recycled in [t_0, t_1), then all references to F_0 must have\n * been dropped in that interval.  A corollary of that is that all\n * memory mappings of F_0 must have been fully unmapped in the\n * interval.  As per the first long comment in |gc()| below, an\n * emulated file can only be \"live\" during replay if some tracee still\n * has a mapping of it.  Tracees' mappings of emulated files is a\n * subset of the ways they can create references to real files during\n * recording.  Therefore the event during replay that drops the last\n * reference to the emulated F_0 must be a tracee unmapping of F_0.\n *\n * So as long as we GC emulated F_0 at the event of its fatal\n * unmapping, the lifetimes of emulated F_0 and emulated F_1 must be\n * disjoint.  And F_0 being GC'd at that point is the important\n * assumption mentioned above.\n */\n\nclass EmuFile;\nstruct FileId {\n  FileId(const KernelMapping& recorded_map);\n  FileId(const EmuFile& emu_file);\n  FileId(dev_t device, ino_t inode)\n      : device(device), inode(inode) {}\n  bool operator==(const FileId& other) const {\n    return (device == other.device && inode == other.inode);\n  }\n  bool operator<(const FileId& other) const {\n    return device < other.device ||\n            (device == other.device && inode < other.inode);\n  }\n  dev_t device;\n  ino_t inode;\n};\n\n/**\n * A file within an EmuFs.  The file is real, but it's mapped to file\n * ID that was recorded during replay.\n */\nclass EmuFile {\npublic:\n  typedef std::shared_ptr<EmuFile> shr_ptr;\n\n  ~EmuFile();\n\n  /**\n   * Return the fd of the real file backing this.\n   */\n  const ScopedFd& fd() const { return file; }\n\n  /**\n   * Return a pathname referring to the fd of this in this\n   * tracer's address space.  For example, \"/proc/12345/fd/5\".\n   */\n  std::string proc_path() const;\n\n  /**\n   * Return the path of the original file from recording, the\n   * one this is emulating.\n   */\n  const std::string emu_path() const { return orig_path; }\n\n  const std::string real_path() const { return tmp_path; }\n\n  dev_t device() const { return device_; }\n  ino_t inode() const { return inode_; }\n\n  void ensure_size(uint64_t size);\n\nprivate:\n  friend class EmuFs;\n\n  EmuFile(EmuFs& owner, ScopedFd&& fd, const std::string& orig_path,\n          const std::string& real_path, dev_t device, ino_t inode,\n          uint64_t file_size);\n\n  /**\n   * Return a copy of this file.  See |create()| for the meaning\n   * of |fs_tag|.\n   */\n  shr_ptr clone(EmuFs& owner);\n\n  /**\n   * Ensure that the emulated file is sized to match a later\n   * stat() of it.\n   */\n  void update(dev_t device, ino_t inode, uint64_t size);\n\n  /**\n   * Create a new emulated file for |orig_path| that will\n   * emulate the recorded attributes |est|.  |tag| is used to\n   * uniquely identify this file among multiple EmuFs's that\n   * might exist concurrently in this tracer process.\n   */\n  static shr_ptr create(EmuFs& owner, const std::string& orig_path,\n                        dev_t orig_device, ino_t orig_inode,\n                        uint64_t orig_file_size);\n\n  std::string orig_path;\n  std::string tmp_path;\n  ScopedFd file;\n  EmuFs& owner;\n  uint64_t size_;\n  dev_t device_;\n  ino_t inode_;\n\n  EmuFile(const EmuFile&) = delete;\n  EmuFile operator=(const EmuFile&) = delete;\n};\n\nclass EmuFs {\npublic:\n  typedef std::shared_ptr<EmuFs> shr_ptr;\n\n  /**\n   * Return the EmuFile for |recorded_map|, which must exist or this won't\n   * return.\n   */\n  EmuFile::shr_ptr at(const KernelMapping& recorded_map) const;\n\n  bool has_file_for(const KernelMapping& recorded_map) const;\n\n  EmuFile::shr_ptr clone_file(EmuFile::shr_ptr emu_file);\n\n  /**\n   * Return an emulated file representing the recorded shared mapping\n   * |recorded_km|.\n   */\n  EmuFile::shr_ptr get_or_create(const KernelMapping& recorded_km);\n\n  /**\n   * Return an already-existing emulated file for the given device/inode.\n   * Returns null if not found.\n   */\n  EmuFile::shr_ptr find(dev_t device, ino_t inode);\n\n  /**\n   * Dump information about this emufs to the \"error\" log.\n   */\n  void log() const;\n\n  size_t size() const { return files.size(); }\n\n  /** Create and return a new emufs. */\n  static shr_ptr create();\n\n  void destroyed_file(EmuFile& emu_file) { files.erase(FileId(emu_file)); }\n\nprivate:\n  EmuFs();\n\n  typedef std::map<FileId, std::weak_ptr<EmuFile>> FileMap;\n\n  FileMap files;\n\n  EmuFs(const EmuFs&) = delete;\n  EmuFs& operator=(const EmuFs&) = delete;\n};\n\n} // namespace rr\n\n#endif // RR_EMUFS_H\n"
  },
  {
    "path": "src/Event.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Event.h\"\n\n#include <syscall.h>\n\n#include <sstream>\n#include <string>\n\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nEvent::Event(const Event& o) : event_type(o.event_type) {\n  switch (event_type) {\n    case EV_DESCHED:\n      new (&Desched()) DeschedEvent(o.Desched());\n      return;\n    case EV_PATCH_SYSCALL:\n      new (&PatchSyscall()) PatchSyscallEvent(o.PatchSyscall());\n      return;\n    case EV_SCHED:\n      new (&Sched()) SchedEvent(o.Sched());\n      return;\n    case EV_SIGNAL:\n    case EV_SIGNAL_DELIVERY:\n    case EV_SIGNAL_HANDLER:\n      new (&Signal()) SignalEvent(o.Signal());\n      return;\n    case EV_SYSCALL:\n    case EV_SYSCALL_INTERRUPTION:\n      new (&Syscall()) SyscallEvent(o.Syscall());\n      return;\n    case EV_SYSCALLBUF_FLUSH:\n      new (&SyscallbufFlush()) SyscallbufFlushEvent(o.SyscallbufFlush());\n      return;\n    default:\n      return;\n  }\n}\n\nEvent::~Event() {\n  switch (event_type) {\n    case EV_DESCHED:\n      Desched().~DeschedEvent();\n      return;\n    case EV_PATCH_SYSCALL:\n      PatchSyscall().~PatchSyscallEvent();\n      return;\n    case EV_SIGNAL:\n    case EV_SIGNAL_DELIVERY:\n    case EV_SIGNAL_HANDLER:\n      Signal().~SignalEvent();\n      return;\n    case EV_SYSCALL:\n    case EV_SYSCALL_INTERRUPTION:\n      Syscall().~SyscallEvent();\n      return;\n    case EV_SYSCALLBUF_FLUSH:\n      SyscallbufFlush().~SyscallbufFlushEvent();\n      return;\n    default:\n      return;\n  }\n}\n\nEvent& Event::operator=(const Event& o) {\n  if (this == &o) {\n    return *this;\n  }\n  this->~Event();\n  new (this) Event(o);\n  return *this;\n}\n\nbool Event::record_regs() const {\n  switch (type()) {\n    case EV_INSTRUCTION_TRAP:\n    case EV_PATCH_SYSCALL:\n    case EV_SCHED:\n    case EV_SYSCALL:\n    case EV_SIGNAL:\n    case EV_SIGNAL_DELIVERY:\n    case EV_SIGNAL_HANDLER:\n      return true;\n    default:\n      return false;\n  }\n}\n\nbool Event::record_extra_regs() const {\n  switch (type()) {\n    case EV_SYSCALL: {\n      const SyscallEvent& sys_ev = Syscall();\n      // sigreturn/rt_sigreturn restores register state\n      // execve sets everything under the sun, and\n      // pkey_alloc modifies the PKRU register.\n      return sys_ev.state == EXITING_SYSCALL &&\n             (is_sigreturn(sys_ev.number, sys_ev.arch()) ||\n              sys_ev.is_exec() ||\n              is_pkey_alloc_syscall(sys_ev.number, sys_ev.arch()));\n    }\n    case EV_SIGNAL:\n      // Record extra regs so we can deliver the signal at the\n      // right time even when GP regs and ticks values are unchanged\n      // but extra regs have changed.\n      return true;\n    case EV_SIGNAL_HANDLER:\n      // entering a signal handler seems to clear FP/SSE regs,\n      // so record these effects.\n      return true;\n    default:\n      return false;\n  }\n}\n\nbool Event::has_ticks_slop() const {\n  switch (type()) {\n    case EV_SYSCALLBUF_ABORT_COMMIT:\n    case EV_SYSCALLBUF_FLUSH:\n    case EV_SYSCALLBUF_RESET:\n    case EV_DESCHED:\n    case EV_GROW_MAP:\n      return true;\n    default:\n      return false;\n  }\n}\n\nbool Event::is_signal_event() const {\n  switch (event_type) {\n    case EV_SIGNAL:\n    case EV_SIGNAL_DELIVERY:\n    case EV_SIGNAL_HANDLER:\n      return true;\n    default:\n      return false;\n  }\n}\n\nbool Event::is_syscall_event() const {\n  switch (event_type) {\n    case EV_SYSCALL:\n    case EV_SYSCALL_INTERRUPTION:\n      return true;\n    default:\n      return false;\n  }\n}\n\nstring Event::str() const {\n  stringstream ss;\n  ss << type_name();\n  switch (event_type) {\n    case EV_SIGNAL:\n    case EV_SIGNAL_DELIVERY:\n    case EV_SIGNAL_HANDLER:\n      ss << \": \" << signal_name(Signal().siginfo.si_signo) << \"(\"\n         << (const char*)(Signal().deterministic == DETERMINISTIC_SIG ? \"det\"\n                                                                      : \"async\")\n         << \")\";\n      break;\n    case EV_SYSCALL:\n    case EV_SYSCALL_INTERRUPTION:\n      ss << \": \" << syscall_name(Syscall().number, Syscall().regs.arch());\n      break;\n    default:\n      // No auxiliary information.\n      break;\n  }\n  return ss.str();\n}\n\nvoid Event::transform(EventType new_type) {\n  switch (event_type) {\n    case EV_SIGNAL:\n      DEBUG_ASSERT(EV_SIGNAL_DELIVERY == new_type);\n      break;\n    case EV_SIGNAL_DELIVERY:\n      DEBUG_ASSERT(EV_SIGNAL_HANDLER == new_type);\n      break;\n    case EV_SYSCALL:\n      DEBUG_ASSERT(EV_SYSCALL_INTERRUPTION == new_type);\n      break;\n    case EV_SYSCALL_INTERRUPTION:\n      DEBUG_ASSERT(EV_SYSCALL == new_type);\n      break;\n    default:\n      FATAL() << \"Can't transform immutable \" << *this << \" into \" << new_type;\n  }\n  event_type = new_type;\n}\n\nstd::string Event::type_name() const {\n  switch (event_type) {\n    case EV_SENTINEL:\n      return \"(none)\";\n#define CASE(_t)                                                               \\\n  case EV_##_t:                                                                \\\n    return #_t\n      CASE(EXIT);\n      CASE(NOOP);\n      CASE(SCHED);\n      CASE(SECCOMP_TRAP);\n      CASE(INSTRUCTION_TRAP);\n      CASE(SYSCALLBUF_FLUSH);\n      CASE(SYSCALLBUF_ABORT_COMMIT);\n      CASE(SYSCALLBUF_RESET);\n      CASE(PATCH_SYSCALL);\n      CASE(GROW_MAP);\n      CASE(DESCHED);\n      CASE(SIGNAL);\n      CASE(SIGNAL_DELIVERY);\n      CASE(SIGNAL_HANDLER);\n      CASE(SYSCALL);\n      CASE(SYSCALL_INTERRUPTION);\n      CASE(TRACE_TERMINATION);\n#undef CASE\n    default:\n      FATAL() << \"Unknown event type \" << event_type;\n      return \"\"; // not reached\n  }\n}\n\nconst char* state_name(SyscallState state) {\n  switch (state) {\n#define CASE(_id)                                                              \\\n  case _id:                                                                    \\\n    return #_id\n    CASE(NO_SYSCALL);\n    CASE(ENTERING_SYSCALL_PTRACE);\n    CASE(ENTERING_SYSCALL);\n    CASE(PROCESSING_SYSCALL);\n    CASE(EXITING_SYSCALL);\n#undef CASE\n    default:\n      return \"???state\";\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Event.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_EVENT_H_\n#define RR_EVENT_H_\n\n#include <sys/types.h>\n\n#include <memory>\n#include <ostream>\n#include <stack>\n#include <string>\n#include <vector>\n\n#include \"MemoryRange.h\"\n#include \"Registers.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"preload/preload_interface.h\"\n\nstruct syscallbuf_record;\n\nnamespace rr {\n\n/**\n * During recording, sometimes we need to ensure that an iteration of\n * RecordSession::record_step schedules the same task as in the previous\n * iteration. The PREVENT_SWITCH value indicates that this is required.\n * For example, the futex operation FUTEX_WAKE_OP modifies userspace\n * memory; those changes are only recorded after the system call completes;\n * and they must be replayed before we allow a context switch to a woken-up\n * task (because the kernel guarantees those effects are seen by woken-up\n * tasks).\n * Entering a potentially blocking system call must use ALLOW_SWITCH, or\n * we risk deadlock. Most non-blocking system calls could use PREVENT_SWITCH\n * or ALLOW_SWITCH; for simplicity we use ALLOW_SWITCH to indicate a call could\n * block and PREVENT_SWITCH otherwise.\n * Note that even if a system call uses PREVENT_SWITCH, as soon as we've\n * recorded the completion of the system call, we can switch to another task.\n */\nenum Switchable { PREVENT_SWITCH, ALLOW_SWITCH };\n\n/**\n * Events serve two purposes: tracking Task state during recording, and\n * being stored in traces to guide replay. Some events are only used during\n * recording and are never actually stored in traces (and are thus irrelevant\n * to replay).\n */\nenum EventType {\n  EV_UNASSIGNED,\n  EV_SENTINEL,\n  // TODO: this is actually a pseudo-pseudosignal: it will never\n  // appear in a trace, but is only used to communicate between\n  // different parts of the recorder code that should be\n  // refactored to not have to do that.\n  EV_NOOP,\n  EV_DESCHED,\n  EV_SECCOMP_TRAP,\n  EV_SYSCALL_INTERRUPTION,\n  // Not stored in trace, but synthesized when we reach the end of the trace.\n  EV_TRACE_TERMINATION,\n\n  // Events present in traces:\n\n  // No associated data.\n  EV_EXIT,\n  // Scheduling signal interrupted the trace.\n  EV_SCHED,\n  // A disabled RDTSC or CPUID instruction.\n  EV_INSTRUCTION_TRAP,\n  // Recorded syscallbuf data for one or more buffered syscalls.\n  EV_SYSCALLBUF_FLUSH,\n  EV_SYSCALLBUF_ABORT_COMMIT,\n  // The syscallbuf was reset to the empty state. We record this event\n  // later than it really happens, because during replay we must proceed to\n  // the event *after* a syscallbuf flush and then reset the syscallbuf,\n  // to ensure we don't reset it while preload code is still using the data.\n  EV_SYSCALLBUF_RESET,\n  // Syscall was entered, the syscall instruction was patched, and the\n  // syscall was aborted. Resume execution at the patch.\n  EV_PATCH_SYSCALL,\n  // Map memory pages due to a (future) memory access. This is associated\n  // with a mmap entry for the new pages.\n  EV_GROW_MAP,\n  // Use .signal.\n  EV_SIGNAL,\n  EV_SIGNAL_DELIVERY,\n  EV_SIGNAL_HANDLER,\n  // Use .syscall.\n  EV_SYSCALL,\n\n  EV_LAST\n};\n\n/**\n * Desched events track the fact that a tracee's desched-event\n * notification fired during a may-block buffered syscall, which rr\n * interprets as the syscall actually blocking (for a potentially\n * unbounded amount of time).  After the syscall exits, rr advances\n * the tracee to where the desched is \"disarmed\" by the tracee.\n */\nstruct DeschedEvent {\n  /** Desched of |rec|. */\n  DeschedEvent(remote_ptr<const struct syscallbuf_record> rec) : rec(rec) {}\n  // Record of the syscall that was interrupted by a desched\n  // notification.  It's legal to reference this memory /while\n  // the desched is being processed only/, because |t| is in the\n  // middle of a desched, which means it's successfully\n  // allocated (but not yet committed) this syscall record.\n  remote_ptr<const struct syscallbuf_record> rec;\n};\n\nstruct PatchSyscallEvent {\n  PatchSyscallEvent() : patch_trapping_instruction(false),\n    patch_after_syscall(false), patch_vsyscall(false) {}\n  // If true, this patch is for a trapping instruction, not a real syscall\n  bool patch_trapping_instruction;\n  // If true, this patch event comes after a syscall (whereas usually they\n  // come before). We assume the trace has put us in the correct place\n  // and don't try to execute any code to reach this event.\n  bool patch_after_syscall;\n  // If true, this patch is for the caller of a vsyscall entry point\n  bool patch_vsyscall;\n};\n\n/**\n * Sched events track points at which context switches happen that are not\n * otherwise associated with an rr event.\n * Also used to record the point at which a tracee is SIGKILLed, which\n * may require special handling if in the syscallbuf.\n */\nstruct SchedEvent {\n  SchedEvent(remote_code_ptr in_syscallbuf_syscall_hook)\n    : in_syscallbuf_syscall_hook(in_syscallbuf_syscall_hook) {}\n  // If this SchedEvent represents the tracee being SIGKILLed,\n  // and syscall buffering is enabled, this contains the address\n  // of the 'syscall_hook' function, otherwise zero.\n  remote_code_ptr in_syscallbuf_syscall_hook;\n};\n\nstruct SyscallbufFlushEvent {\n  SyscallbufFlushEvent() {}\n  std::vector<mprotect_record> mprotect_records;\n};\n\nenum SignalDeterministic { NONDETERMINISTIC_SIG = 0, DETERMINISTIC_SIG = 1 };\nenum SignalResolvedDisposition {\n  DISPOSITION_FATAL = 0,\n  DISPOSITION_USER_HANDLER = 1,\n  DISPOSITION_IGNORED = 2,\n};\nstruct SignalEvent {\n  /**\n   * Signal |signo| is the signum, and |deterministic| is true\n   * for deterministically-delivered signals (see\n   * record_signal.cc).\n   */\n  SignalEvent(const siginfo_t& siginfo, SignalDeterministic deterministic,\n              SignalResolvedDisposition disposition)\n      : siginfo(siginfo),\n        deterministic(deterministic),\n        disposition(disposition) {}\n\n  // Signal info\n  siginfo_t siginfo;\n  // True if this signal will be deterministically raised as the\n  // side effect of retiring an instruction during replay, for\n  // example |load $r 0x0| deterministically raises SIGSEGV.\n  SignalDeterministic deterministic;\n  SignalResolvedDisposition disposition;\n};\n\n/**\n * Syscall events track syscalls through entry into the kernel,\n * processing in the kernel, and exit from the kernel.\n *\n * This also models interrupted syscalls.  During recording, only\n * descheduled buffered syscalls /push/ syscall interruptions; all\n * others are detected at exit time and transformed into syscall\n * interruptions from the original, normal syscalls.\n *\n * Normal system calls (interrupted or not) record two events: ENTERING_SYSCALL\n * and EXITING_SYSCALL. If the process exits before the syscall exit (because\n * this is an exit/exit_group syscall or the process gets SIGKILL), there's no\n * syscall exit event.\n *\n * When PTRACE_SYSCALL is used, there will be three events:\n * ENTERING_SYSCALL_PTRACE to run the process until it gets into the kernel,\n * then ENTERING_SYSCALL and EXITING_SYSCALL. We need three events to handle\n * PTRACE_SYSCALL with clone/fork/vfork and execve. The tracee must run to\n * the ENTERING_SYSCALL_PTRACE state, allow a context switch so the ptracer\n * can modify tracee registers, then perform ENTERING_SYSCALL (which actually\n * creates the new task or does the exec), allow a context switch so the\n * ptracer can modify the new task or post-exec state in a PTRACE_EVENT_EXEC/\n * CLONE/FORK/VFORK, then perform EXITING_SYSCALL to get into the correct\n * post-syscall state.\n *\n * When PTRACE_SYSEMU is used, there will only be one event: an\n * ENTERING_SYSCALL_PTRACE.\n */\nenum SyscallState {\n  // Not present in trace. Just a dummy value.\n  NO_SYSCALL,\n  // Run to the given register state and enter the kernel but don't\n  // perform any system call processing yet.\n  ENTERING_SYSCALL_PTRACE,\n  // Run to the given register state and enter the kernel, if not already\n  // there due to a ENTERING_SYSCALL_PTRACE, and then perform the initial part\n  // of the system call (any work required before issuing a during-system-call\n  // ptrace event).\n  ENTERING_SYSCALL,\n  // Not present in trace.\n  PROCESSING_SYSCALL,\n  // Already in the kernel. Perform the final part of the system call and exit\n  // with the recorded system call result.\n  EXITING_SYSCALL\n};\n\nstruct OpenedFd {\n  std::string path;\n  int fd;\n  dev_t device;\n  ino_t inode;\n};\n\nstruct SyscallEvent {\n  /** Syscall |syscallno| is the syscall number. */\n  SyscallEvent(int syscallno, SupportedArch arch)\n      : arch_(arch),\n        regs(arch),\n        desched_rec(nullptr),\n        write_offset(-1),\n        state(NO_SYSCALL),\n        number(syscallno),\n        switchable(PREVENT_SWITCH),\n        is_restart(false),\n        failed_during_preparation(false),\n        in_sysemu(false),\n        should_retry_patch(false) {}\n\n  std::string syscall_name() const { return rr::syscall_name(number, arch()); }\n\n  SupportedArch arch() const { return arch_; }\n  /** Change the architecture for this event. */\n  void set_arch(SupportedArch a) { arch_ = a; }\n\n  bool is_exec() const {\n    return is_execve_syscall(number, arch()) || is_execveat_syscall(number, arch());\n  }\n\n  SupportedArch arch_;\n  // The original (before scratch is set up) arguments to the\n  // syscall passed by the tracee.  These are used to detect\n  // restarted syscalls.\n  Registers regs;\n  // If this is a descheduled buffered syscall, points at the\n  // record for that syscall.\n  remote_ptr<const struct syscallbuf_record> desched_rec;\n\n  // Extra data for specific syscalls.\n  // -1 to indicate there isn't a write offset.\n  int64_t write_offset;\n  std::vector<int> exec_fds_to_close;\n  std::vector<OpenedFd> opened;\n  std::shared_ptr<std::array<typename NativeArch::sockaddr_storage, 2>> socket_addrs;\n  // Memory ranges affected by an madvise(). If empty, a successful madvise affected\n  // the range indicated by its parameters, and an unsuccessful madvise affected\n  // nothing.\n  std::vector<MemoryRange> madvise_ranges;\n\n  SyscallState state;\n  // Syscall number.\n  int number;\n  // Records the switchable state when this syscall was prepared\n  Switchable switchable;\n  // True when this syscall was restarted after a signal interruption.\n  bool is_restart;\n  // True when this syscall failed during preparation: syscall entry events\n  // that were interrupted by a user seccomp filter forcing SIGSYS or errno,\n  // and clone system calls that failed. These system calls failed no matter\n  // what the syscall-result register says.\n  bool failed_during_preparation;\n  // Syscall is being emulated via PTRACE_SYSEMU.\n  bool in_sysemu;\n  // True if we should retry patching on exit from this syscall\n  bool should_retry_patch;\n};\n\nstruct syscall_interruption_t {\n  syscall_interruption_t(){};\n};\nstatic const syscall_interruption_t interrupted;\n\n/**\n * Sum type for all events (well, a C++ approximation thereof).  An\n * Event always has a defined EventType.  It can be down-casted to\n * one of the leaf types above iff the type tag is correct.\n */\nstruct Event {\n  Event() : event_type(EV_UNASSIGNED) {}\n  Event(const DeschedEvent& ev) : event_type(EV_DESCHED), desched(ev) {}\n  Event(EventType type, const SignalEvent& ev) : event_type(type), signal(ev) {}\n  Event(const SyscallbufFlushEvent& ev)\n      : event_type(EV_SYSCALLBUF_FLUSH), syscallbuf_flush(ev) {}\n  Event(const SyscallEvent& ev) : event_type(EV_SYSCALL), syscall(ev) {}\n  Event(const syscall_interruption_t&, const SyscallEvent& ev)\n      : event_type(EV_SYSCALL_INTERRUPTION), syscall(ev) {}\n  Event(const Event& o);\n  ~Event();\n  Event& operator=(const Event& o);\n\n  DeschedEvent& Desched() {\n    DEBUG_ASSERT(EV_DESCHED == event_type);\n    return desched;\n  }\n  const DeschedEvent& Desched() const {\n    DEBUG_ASSERT(EV_DESCHED == event_type);\n    return desched;\n  }\n\n  PatchSyscallEvent& PatchSyscall() {\n    DEBUG_ASSERT(EV_PATCH_SYSCALL == event_type);\n    return patch;\n  }\n  const PatchSyscallEvent& PatchSyscall() const {\n    DEBUG_ASSERT(EV_PATCH_SYSCALL == event_type);\n    return patch;\n  }\n\n  SchedEvent& Sched() {\n    DEBUG_ASSERT(is_sched_event());\n    return sched_;\n  }\n  const SchedEvent& Sched() const {\n    DEBUG_ASSERT(is_sched_event());\n    return sched_;\n  }\n\n  SyscallbufFlushEvent& SyscallbufFlush() {\n    DEBUG_ASSERT(EV_SYSCALLBUF_FLUSH == event_type);\n    return syscallbuf_flush;\n  }\n  const SyscallbufFlushEvent& SyscallbufFlush() const {\n    DEBUG_ASSERT(EV_SYSCALLBUF_FLUSH == event_type);\n    return syscallbuf_flush;\n  }\n\n  SignalEvent& Signal() {\n    DEBUG_ASSERT(is_signal_event());\n    return signal;\n  }\n  const SignalEvent& Signal() const {\n    DEBUG_ASSERT(is_signal_event());\n    return signal;\n  }\n\n  SyscallEvent& Syscall() {\n    DEBUG_ASSERT(is_syscall_event());\n    return syscall;\n  }\n  const SyscallEvent& Syscall() const {\n    DEBUG_ASSERT(is_syscall_event());\n    return syscall;\n  }\n\n  bool record_regs() const;\n\n  bool record_extra_regs() const;\n\n  bool has_ticks_slop() const;\n\n  /**\n   * Return true if this is one of the indicated type of events.\n   */\n  bool is_signal_event() const;\n  bool is_sched_event() const {\n    return event_type == EV_SCHED;\n  }\n  bool is_syscall_event() const;\n  bool is_syscallbuf_flush_event() const {\n    return event_type == EV_SYSCALLBUF_FLUSH;\n  }\n\n  /** Return a string describing this. */\n  std::string str() const;\n\n  /**\n   * Dynamically change the type of this.  Only a small number\n   * of type changes are allowed.\n   */\n  void transform(EventType new_type);\n\n  /** Return the current type of this. */\n  EventType type() const { return event_type; }\n\n  /** Return a string naming |ev|'s type. */\n  std::string type_name() const;\n\n  static Event noop() { return Event(EV_NOOP); }\n  static Event trace_termination() { return Event(EV_TRACE_TERMINATION); }\n  static Event instruction_trap() { return Event(EV_INSTRUCTION_TRAP); }\n  static Event patch_syscall() {\n    auto ev = Event(EV_PATCH_SYSCALL);\n    ev.PatchSyscall().patch_after_syscall = false;\n    ev.PatchSyscall().patch_vsyscall = false;\n    ev.PatchSyscall().patch_trapping_instruction = false;\n    return ev;\n  }\n  static Event sched() {\n    auto ev = Event(EV_SCHED);\n    ev.Sched().in_syscallbuf_syscall_hook = remote_code_ptr();\n    return ev;\n  }\n  static Event seccomp_trap() { return Event(EV_SECCOMP_TRAP); }\n  static Event syscallbuf_abort_commit() {\n    return Event(EV_SYSCALLBUF_ABORT_COMMIT);\n  }\n  static Event syscallbuf_reset() { return Event(EV_SYSCALLBUF_RESET); }\n  static Event grow_map() { return Event(EV_GROW_MAP); }\n  static Event exit() { return Event(EV_EXIT); }\n  static Event sentinel() { return Event(EV_SENTINEL); }\n\nprivate:\n  Event(EventType type) : event_type(type) {}\n\n  EventType event_type;\n  union {\n    DeschedEvent desched;\n    PatchSyscallEvent patch;\n    SchedEvent sched_;\n    SignalEvent signal;\n    SyscallEvent syscall;\n    SyscallbufFlushEvent syscallbuf_flush;\n  };\n};\n\ninline static std::ostream& operator<<(std::ostream& o, const Event& ev) {\n  return o << ev.str();\n}\n\nconst char* state_name(SyscallState state);\n\n} // namespace rr\n\n#endif // EVENT_H_\n"
  },
  {
    "path": "src/ExportImportCheckpoints.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ExportImportCheckpoints.h\"\n\n#include <fcntl.h>\n#include <sys/resource.h>\n#include <sys/socket.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/un.h>\n\n#include <sstream>\n\n#include \"log.h\"\n#include \"main.h\"\n#include \"WaitManager.h\"\n\nusing namespace std;\n\n/* Clients connect to the checkpoints socket and may send a one-byte command.\n   Currently the only valid command value is 0: create a checkpoint.\n*/\n\nnamespace rr {\n\nbool parse_export_checkpoints(const string& arg, FrameTime& export_checkpoints_event,\n                              int& export_checkpoints_count, string& export_checkpoints_socket) {\n  size_t first_comma = arg.find(',');\n  if (first_comma == string::npos) {\n    fprintf(stderr, \"Missing <NUM> parameter for --export-checkpoints\");\n    return false;\n  }\n  size_t second_comma = arg.find(',', first_comma + 1);\n  if (second_comma == string::npos) {\n    fprintf(stderr, \"Missing <FILE> parameter for --export-checkpoints\");\n    return false;\n  }\n  char* endptr;\n  string event_str = arg.substr(0, first_comma);\n  export_checkpoints_event = strtoul(event_str.c_str(), &endptr, 0);\n  if (*endptr) {\n    fprintf(stderr, \"Invalid <EVENT> for --export-checkpoints: %s\\n\", event_str.c_str());\n    return false;\n  }\n  string num_str = arg.substr(first_comma + 1, second_comma - (first_comma + 1));\n  export_checkpoints_count = strtoul(num_str.c_str(), &endptr, 0);\n  if (*endptr) {\n    fprintf(stderr, \"Invalid <NUM> for --export-checkpoints: %s\\n\", num_str.c_str());\n    return false;\n  }\n  export_checkpoints_socket = arg.substr(second_comma + 1);\n  return true;\n}\n\nScopedFd bind_export_checkpoints_socket(int count, const string& socket_file_name) {\n  unlink(socket_file_name.c_str());\n\n  ScopedFd sock = ScopedFd(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));\n  if (!sock.is_open()) {\n    FATAL() << \"Can't create Unix socket \" << socket_file_name;\n  }\n  if (socket_file_name.size() + 1 > sizeof(sockaddr_un::sun_path)) {\n    FATAL() << \"Socket file name \" << socket_file_name << \" too long\";\n  }\n  int reuse = 1;\n  int ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));\n  if (ret < 0) {\n    FATAL() << \"Failed to set SO_REUSEADDR\";\n  }\n  sockaddr_un addr;\n  addr.sun_family = AF_UNIX;\n  strcpy(addr.sun_path, socket_file_name.c_str());\n  ret = ::bind(sock, (const sockaddr*)&addr, sizeof(addr));\n  if (ret < 0) {\n    FATAL() << \"Can't bind Unix socket \" << socket_file_name;\n  }\n  ret = listen(sock, count);\n  if (ret < 0) {\n    FATAL() << \"Can't listen on Unix socket \" << socket_file_name;\n  }\n  return sock;\n}\n\nstatic void send_all(ScopedFd& sock, const void* vbuf, size_t count) {\n  const char* buf = static_cast<const char*>(vbuf);\n  while (count > 0) {\n    ssize_t ret = send(sock, buf, count, 0);\n    if (ret <= 0) {\n      FATAL() << \"Failed to send complete message\";\n    }\n    count -= ret;\n    buf += ret;\n  }\n}\n\nstatic void recv_all(ScopedFd& sock, void* vbuf, size_t count) {\n  char* buf = static_cast<char*>(vbuf);\n  while (count > 0) {\n    ssize_t ret = recv(sock, buf, count, 0);\n    if (ret <= 0) {\n      FATAL() << \"Failed to recv complete message\";\n    }\n    count -= ret;\n    buf += ret;\n  }\n}\n\nstatic void setup_child_fds(vector<int> fds, CommandForCheckpoint& command_for_checkpoint) {\n  command_for_checkpoint.exit_notification_fd = ScopedFd(fds[0]);\n  for (int our_fd = 0; our_fd < 3; ++our_fd) {\n    // We deliberately don't set CLOEXEC here since we might want these\n    // to be inherited.\n    int ret = dup2(fds[our_fd + 1], our_fd);\n    if (ret < 0) {\n      FATAL() << \"Can't dup over stdin/stdout/stderr\";\n    }\n    close(fds[our_fd + 1]);\n  }\n\n  for (size_t i = 4; i < fds.size(); ++i) {\n    command_for_checkpoint.fds.push_back(ScopedFd(fds[i]));\n  }\n}\n\nstatic void set_title(const vector<string>& args) {\n  string line = \"rr:\";\n  for (auto& a : args) {\n    line += ' ';\n    line += a;\n  }\n\n  char* arg0 = saved_argv0();\n  size_t space = saved_argv0_space() - 1;\n  if (space < 3) {\n    return;\n  }\n  // To simplify things, instead of moving the environment around when the new command is too long,\n  // we just truncate it.\n  if (line.size() > space) {\n    line[space - 3] = line[space - 2] = line[space - 1] = '.';\n    line.resize(space);\n  }\n  memcpy(arg0, line.data(), line.size());\n  memset(arg0 + line.size(), 0, space - line.size());\n}\n\nCommandForCheckpoint export_checkpoints(ReplaySession::shr_ptr session, int count, ScopedFd& sock,\n    const std::string&) {\n  if (!session->can_clone()) {\n    FATAL() << \"Can't create checkpoints at this time, aborting: \" << session->current_frame_time();\n  }\n\n  CommandForCheckpoint command_for_checkpoint;\n\n  vector<pid_t> children;\n  for (int i = 0; i < count; ++i) {\n    ScopedFd client = ScopedFd(accept4(sock, nullptr, nullptr, SOCK_CLOEXEC));\n    if (!client.is_open()) {\n      FATAL() << \"Failed to accept client connection\";\n    }\n\n    ssize_t priority;\n    recv_all(client, &priority, sizeof(priority));\n    ssize_t ret = setpriority(PRIO_PROCESS, 0, priority);\n    if (ret < 0) {\n      if (errno == EACCES) {\n        LOG(warn) << \"Failed to increase priority\";\n      } else {\n        FATAL() << \"Failed setpriority\";\n      }\n    }\n\n    size_t fds_size;\n    recv_all(client, &fds_size, sizeof(fds_size));\n\n    // Do the SCM_RIGHTS dance to receive file descriptors\n    msghdr msg;\n    memset(&msg, 0, sizeof(msg));\n    char dummy_buf;\n    iovec iov = { &dummy_buf, 1 };\n    msg.msg_iov = &iov;\n    msg.msg_iovlen = 1;\n    vector<uint8_t> cbuf;\n    size_t data_len = sizeof(int)*fds_size;\n    cbuf.resize(CMSG_SPACE(data_len));\n    msg.msg_control = cbuf.data();\n    msg.msg_controllen = cbuf.size();\n    ret = recvmsg(client, &msg, MSG_CMSG_CLOEXEC);\n    if (ret != 1) {\n      FATAL() << \"Failed to read fds\";\n    }\n    cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);\n    if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS || cmsg->cmsg_len != CMSG_LEN(data_len)) {\n      FATAL() << \"Invalid cmsg metadata\";\n    }\n    vector<int> fds_data;\n    fds_data.resize(fds_size);\n    memcpy(fds_data.data(), CMSG_DATA(cmsg), data_len);\n\n    size_t arg_count;\n    recv_all(client, &arg_count, sizeof(arg_count));\n    vector<string> args;\n    for (size_t i = 0; i < arg_count; ++i) {\n      size_t arg_size;\n      recv_all(client, &arg_size, sizeof(arg_size));\n      vector<char> arg;\n      arg.resize(arg_size);\n      recv_all(client, arg.data(), arg_size);\n      args.push_back(string(arg.data(), arg.size()));\n    }\n\n    ReplaySession::shr_ptr checkpoint = session->clone();\n    int parent_to_child_fds[2];\n    ret = pipe(parent_to_child_fds);\n    if (ret < 0) {\n      FATAL() << \"Can't pipe\";\n    }\n    ScopedFd parent_to_child_read(parent_to_child_fds[0]);\n    ScopedFd parent_to_child_write(parent_to_child_fds[1]);\n\n    checkpoint->prepare_to_detach_tasks();\n\n    // We need to create a new control socket for the child, we can't use the shared control socket\n    // safely in multiple processes.\n    int sockets[2];\n    ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sockets);\n    if (ret < 0) {\n      FATAL() << \"socketpair failed\";\n    }\n    ScopedFd new_tracee_socket(sockets[0]);\n    ScopedFd new_tracee_socket_receiver(sockets[1]);\n\n    pid_t child = fork();\n    if (!child) {\n      set_title(args);\n      session->forget_tasks();\n      command_for_checkpoint.args = std::move(args);\n      command_for_checkpoint.session = std::move(checkpoint);\n      setup_child_fds(fds_data, command_for_checkpoint);\n      char ch;\n      ret = read(parent_to_child_read, &ch, 1);\n      if (ret != 1) {\n        FATAL() << \"Failed to read parent notification\";\n      }\n      command_for_checkpoint.session->reattach_tasks(std::move(new_tracee_socket),\n        std::move(new_tracee_socket_receiver));\n      return command_for_checkpoint;\n    }\n    children.push_back(child);\n\n    checkpoint->detach_tasks(child, new_tracee_socket_receiver);\n    ret = write(parent_to_child_write, \"x\", 1);\n    if (ret != 1) {\n      FATAL() << \"Failed to write parent notification\";\n    }\n    for (auto d : fds_data) {\n      close(d);\n    }\n  }\n\n  // Wait for and reap all children\n  for (size_t i = 0; i < children.size(); ++i) {\n    WaitResult result = WaitManager::wait_exit(WaitOptions(children[i]));\n    if (result.code != WAIT_OK) {\n      FATAL() << \"Failed to wait for child \" << children[i];\n    }\n  }\n\n  return command_for_checkpoint;\n}\n\nvoid notify_normal_exit(ScopedFd& exit_notification_fd) {\n  ssize_t ret = write(exit_notification_fd, \"\", 1);\n  if (ret != 1) {\n    FATAL() << \"Can't send exit notification\";\n  }\n}\n\nint invoke_checkpoint_command(const string& socket_file_name,\n    vector<string> args, vector<ScopedFd> fds) {\n  ScopedFd sock = ScopedFd(socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0));\n  if (!sock.is_open()) {\n    FATAL() << \"Can't create Unix socket \" << socket_file_name;\n  }\n  if (socket_file_name.size() + 1 > sizeof(sockaddr_un::sun_path)) {\n    FATAL() << \"Socket file name \" << socket_file_name << \" too long\";\n  }\n  sockaddr_un addr;\n  addr.sun_family = AF_UNIX;\n  strcpy(addr.sun_path, socket_file_name.c_str());\n  while (true) {\n    ssize_t ret = connect(sock, (const sockaddr*)&addr, sizeof(addr));\n    if (ret < 0) {\n      // We might try to connect between the socket being bound and listen()ed on\n      if (errno == ENOENT || errno == ECONNREFUSED) {\n        sleep(1);\n        continue;\n      }\n      FATAL() << \"Can't connect socket \" << socket_file_name;\n    }\n    break;\n  }\n\n  ssize_t ret = getpriority(PRIO_PROCESS, 0);\n  if (ret < 0) {\n    FATAL() << \"Failed getpriority\";\n  }\n  send_all(sock, &ret, sizeof(ret));\n\n  size_t total_fds = 4 + fds.size();\n  send_all(sock, &total_fds, sizeof(total_fds));\n\n  int exit_notification_pipe_fds[2];\n  ret = pipe(exit_notification_pipe_fds);\n  if (ret < 0) {\n    FATAL() << \"Failed pipe\";\n  }\n\n  // Do the SCM_RIGHTS dance to send file descriptors.\n  msghdr msg;\n  memset(&msg, 0, sizeof(msg));\n  char ch = 'x';\n  iovec iov = { &ch, 1 };\n  msg.msg_iov = &iov;\n  msg.msg_iovlen = 1;\n  vector<uint8_t> cbuf;\n  size_t data_len = sizeof(int)*total_fds;\n  cbuf.resize(CMSG_SPACE(data_len));\n  msg.msg_control = cbuf.data();\n  msg.msg_controllen = cbuf.size();\n  cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);\n  cmsg->cmsg_level = SOL_SOCKET;\n  cmsg->cmsg_type = SCM_RIGHTS;\n  cmsg->cmsg_len = CMSG_LEN(data_len);\n  char* cmsg_data = (char*)CMSG_DATA(cmsg);\n  vector<int> int_fds;\n  int_fds.push_back(exit_notification_pipe_fds[1]);\n  int_fds.push_back(0);\n  int_fds.push_back(1);\n  int_fds.push_back(2);\n  for (auto& fd : fds) {\n    int_fds.push_back(fd);\n  }\n  memcpy(cmsg_data, int_fds.data(), sizeof(int)*int_fds.size());\n  ret = sendmsg(sock, &msg, 0);\n  if (ret != 1) {\n    FATAL() << \"Can't send file descriptors\";\n  }\n  close(exit_notification_pipe_fds[1]);\n  // Close stdin but keep stdout/stderr open in case we need to print something ourselves.\n  close(0);\n\n  size_t arg_count = args.size();\n  send_all(sock, &arg_count, sizeof(arg_count));\n  for (auto& arg : args) {\n    size_t arg_size = arg.size();\n    send_all(sock, &arg_size, sizeof(arg_size));\n    send_all(sock, arg.data(), arg_size);\n  }\n\n  ret = read(exit_notification_pipe_fds[0], &ch, 1);\n  if (ret < 0) {\n    FATAL() << \"Can't read from notification pipe\";\n  }\n  if (ret == 0) {\n    // abnormal termination\n    return 1;\n  }\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ExportImportCheckpoints.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_EXPORT_IMPORT_CHECKPOINTS_H_\n#define RR_EXPORT_IMPORT_CHECKPOINTS_H_\n\n#include \"ReplaySession.h\"\n\n#include <string>\n#include <vector>\n\nnamespace rr {\n\nbool parse_export_checkpoints(const std::string& arg, FrameTime& export_checkpoints_event,\n                              int& export_checkpoints_count, std::string& export_checkpoints_socket);\n\n/* Bind the socket so clients can try to connect to it and block. */\nScopedFd bind_export_checkpoints_socket(int count, const std::string& socket_file_name);\n\n/* A command to run on the checkpoint */\nstruct CommandForCheckpoint {\n  std::vector<std::string> args;\n  std::vector<ScopedFd> fds;\n  ReplaySession::shr_ptr session;\n  ScopedFd exit_notification_fd;\n};\n\n/* Export checkpoints from the given session.\n   This function will return `count` + 1 times; the first `count` times in a forked child\n   with a valid CommandForCheckpoint with a nonnull `session`; the last time with a null\n   `session` when all forked children have exited and been reaped.\n   For the child returns, stdin/stdout/stderr will have been rebound to fds passed in over\n   the socket.\n*/\nCommandForCheckpoint export_checkpoints(ReplaySession::shr_ptr session, int count, ScopedFd& sock,\n    const std::string& socket_file_name);\n\n/* After performing the CommandForCheckpoint, notify that we have exited normally. */\nvoid notify_normal_exit(ScopedFd& exit_notification_fd);\n\n/* Invoke a command on a checkpoint. stdin/stdout/stderr and the args and fds\n   are passed to the exporter process, then we wait for it to complete and exit, and return\n   an appropriate exit code.\n*/\nint invoke_checkpoint_command(const std::string& socket_file_name,\n    std::vector<std::string> args, std::vector<ScopedFd> fds = std::vector<ScopedFd>());\n\n} // namespace rr\n\n#endif /* RR_EXPORT_IMPORT_CHECKPOINTS_H_ */\n"
  },
  {
    "path": "src/ExtraRegisters.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ExtraRegisters.h\"\n\n#include <string.h>\n\n#include \"GdbServerRegister.h\"\n#include \"ReplayTask.h\"\n#include \"core.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n// This is the byte offset at which the ST0-7 register data begins\n// with an xsave (or fxsave) block.\nstatic const int st_regs_offset = 32;\n// NB: each STx register holds 10 bytes of actual data, but each\n// occupies 16 bytes of space within (f)xsave, presumably for\n// alignment purposes.\nstatic const int st_reg_space = 16;\n\n// Byte offset at which the XMM0-15 register data begins with (f)xsave.\nstatic const int xmm_regs_offset = 160;\nstatic const int xmm_reg_space = 16;\n\nstatic const uint8_t fxsave_387_ctrl_offsets[] = {\n  // The Intel documentation says that the following layout is only valid in\n  // 32-bit mode, or when fxsave is executed in 64-bit mode without an\n  // appropriate REX prefix.  The kernel seems to only use fxsave with the\n  // REX prefix, so one would think these offsets would be different.  But\n  // GDB seems happy to use these offsets, so that's what we use too.\n  0,  // DREG_64_FCTRL\n  2,  // DREG_64_FSTAT\n  4,  // DREG_64_FTAG\n  12, // DREG_64_FISEG\n  8,  // DREG_64_FIOFF\n  20, // DREG_64_FOSEG\n  16, // DREG_64_FOOFF\n  6,  // DREG_64_FOP\n};\n\nstatic const int fip_offset = 8;\nstatic const int fop_offset = 6;\nstatic const int fdp_offset = 16;\nstatic const int mxcsr_offset = 24;\n\nstruct RegData {\n  int offset;\n  int size;\n  int xsave_feature_bit;\n\n  RegData(int offset = -1, int size = 0)\n      : offset(offset), size(size), xsave_feature_bit(-1) {}\n};\n\nstatic bool reg_in_range(GdbServerRegister regno, GdbServerRegister low, GdbServerRegister high,\n                         int offset_base, int offset_stride, int size,\n                         RegData* out) {\n  if (regno < low || regno > high) {\n    return false;\n  }\n  out->offset = offset_base + offset_stride * (regno - low);\n  out->size = size;\n  return true;\n}\n\nstatic constexpr int AVX_FEATURE_BIT = 2;\nstatic constexpr int AVX_OPMASK_FEATURE_BIT = 5;\nstatic constexpr int AVX_ZMM_HI256_FEATURE_BIT = 6;\nstatic constexpr int AVX_ZMM_HI16_FEATURE_BIT = 7;\nstatic constexpr int PKRU_FEATURE_BIT = 9;\n\nstatic const uint64_t PKRU_FEATURE_MASK = 1 << PKRU_FEATURE_BIT;\n\nstatic const size_t xsave_header_offset = 512;\nstatic const size_t xsave_header_size = 64;\nstatic const size_t xsave_header_end = xsave_header_offset + xsave_header_size;\nstruct RegisterDescriptor {\n  // Feature bits given by CPUID\n  int8_t feature;\n  // Width in bytes in the xsave area\n  int8_t size;\n  // If the registers described by this descriptor is laid out in Hi16 ranges,\n  // value can be non-zero.\n  int8_t hi16_offset;\n  // Range of registers described by descriptor\n  GdbServerRegister base;\n  GdbServerRegister end_inclusive;\n  // The stride of the register (how far between the start of this register to\n  // the next register of the same type, in the xsave area)\n  int stride;\n\n  int register_offset(GdbServerRegister reg) const noexcept {\n    DEBUG_ASSERT(reg >= base && reg < (base + 16));\n    const auto& layout = xsave_native_layout();\n    return layout.feature_layouts[feature].offset + hi16_offset +\n           (reg - base) * stride;\n  }\n\n  bool describes_register(GdbServerRegister gdb_register) const {\n    // compare end first because we search table linerarly.\n    return gdb_register <= end_inclusive && gdb_register >= base;\n  }\n};\n\n/**\n * These descriptors describe the layout of the XSAVE area for avx2 and\n * avx512 extensions. where the actual contents for the registers get read from.\n * `RegisterDescriptor::feature` is used to index into `XSaveFeatureLayout` to\n * get the base offset for a particular range.\n *\n * Register ranges in the xsave area that differ is the Hi16 ones.\n * In these ranges, the registers are laid out like [xmmN, ymmN, zmmN],\n * instead of [xmm0..N], [ymm0..N]. So to get e.g. zmm18 we need 3 offsets;\n * 1. offset to the sub-region of xsave for [xmmN, ymmN, zmmN] are found (N>15)\n * 2. offset to where register-range N=18 begins, e.g. [xmm18, ymm18, zmm18]\n * 3. offset to where zmm begins; which is 32 bytes.\n */\nstatic constexpr std::array<RegisterDescriptor, 6> register_config_lookup_table{\n  { { AVX_FEATURE_BIT, 16, 0, DREG_64_YMM0H,\n      GdbServerRegister(DREG_64_YMM15H), 16 },\n    { AVX_ZMM_HI16_FEATURE_BIT, 16, 0, DREG_64_XMM16,\n      GdbServerRegister(DREG_64_XMM31), 64 },\n    { AVX_ZMM_HI16_FEATURE_BIT, 16, 16, DREG_64_YMM16H,\n      GdbServerRegister(DREG_64_YMM31H), 64 },\n    { AVX_ZMM_HI256_FEATURE_BIT, 32, 0, DREG_64_ZMM0H,\n      GdbServerRegister(DREG_64_ZMM15H), 32 },\n    { AVX_ZMM_HI16_FEATURE_BIT, 32, 32, DREG_64_ZMM16H,\n      GdbServerRegister(DREG_64_ZMM31H), 64 },\n    { AVX_OPMASK_FEATURE_BIT, 8, 0, DREG_64_K0,\n      GdbServerRegister(DREG_64_K7), 8 } }\n};\n\n// Every range of registers (except K0-7) are 16 registers long. We use this\n// fact to build a lookup table, for the AVX2 and AVX512 registers.\nstatic bool reg_is_avx2_or_512(GdbServerRegister reg, RegData& out) noexcept {\n  if (reg < DREG_64_YMM0H || reg > DREG_64_K7) {\n    return false;\n  }\n\n  for (const auto& descriptor : register_config_lookup_table) {\n    if (descriptor.describes_register(reg)) {\n      out.xsave_feature_bit = descriptor.feature;\n      out.size = descriptor.size;\n      out.offset = descriptor.register_offset(reg);\n      return true;\n    }\n  }\n  FATAL() << \"Unknown AVX512F register: \" << reg;\n  return true;\n}\n\n// Return the size and data location of register |regno|.\n// If we can't read the register, returns -1 in 'offset'.\nstatic RegData xsave_register_data(SupportedArch arch, GdbServerRegister regno) {\n  // Check regno is in range, and if it's 32-bit then convert it to the\n  // equivalent 64-bit register.\n  switch (arch) {\n    case x86:\n      // Convert regno to the equivalent 64-bit version since the XSAVE layout\n      // is compatible\n      if (regno >= DREG_XMM0 && regno <= DREG_XMM7) {\n        regno = (GdbServerRegister)(regno - DREG_XMM0 + DREG_64_XMM0);\n        break;\n      }\n      if (regno >= DREG_YMM0H && regno <= DREG_YMM7H) {\n        regno = (GdbServerRegister)(regno - DREG_YMM0H + DREG_64_YMM0H);\n        break;\n      }\n      if (regno >= DREG_ZMM0H && regno <= DREG_ZMM7H) {\n        regno = (GdbServerRegister)(regno - DREG_ZMM0H + DREG_64_ZMM0H);\n        break;\n      }\n      if (regno >= DREG_K0 && regno <= DREG_K7) {\n        regno = (GdbServerRegister)(regno - DREG_K0 + DREG_64_K0);\n        break;\n      }\n      if (regno == DREG_MXCSR) {\n        regno = DREG_64_MXCSR;\n      } else if (regno == DREG_PKRU) {\n        regno = DREG_64_PKRU;\n      } else if (regno < DREG_FIRST_FXSAVE_REG || regno > DREG_LAST_FXSAVE_REG) {\n        return RegData();\n      } else {\n        regno = (GdbServerRegister)(regno - DREG_FIRST_FXSAVE_REG +\n                              DREG_64_FIRST_FXSAVE_REG);\n      }\n      break;\n    case x86_64:\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n      return RegData();\n  }\n\n  RegData result;\n  if (reg_in_range(regno, DREG_64_ST0, DREG_64_ST7, st_regs_offset,\n                   st_reg_space, 10, &result)) {\n    return result;\n  }\n  if (reg_in_range(regno, DREG_64_XMM0, DREG_64_XMM15, xmm_regs_offset,\n                   xmm_reg_space, 16, &result)) {\n    return result;\n  }\n\n  if (reg_is_avx2_or_512(regno, result)) {\n    return result;\n  }\n\n  if (regno == DREG_64_PKRU) {\n    const XSaveLayout& layout = xsave_native_layout();\n    if (PKRU_FEATURE_BIT > layout.feature_layouts.size()) {\n      return RegData();\n    }\n\n    const XSaveFeatureLayout& fl = layout.feature_layouts[PKRU_FEATURE_BIT];\n    result.offset = fl.offset;\n    // NB: the PKRU *region* may be 8 bytes to maintain alignment but the\n    // PKRU *register* is only the first 4 bytes.\n    result.size = 4;\n    result.xsave_feature_bit = PKRU_FEATURE_BIT;\n    return result;\n  }\n\n  if (regno < DREG_64_FIRST_FXSAVE_REG || regno > DREG_64_LAST_FXSAVE_REG) {\n    return RegData();\n  }\n  if (regno == DREG_64_MXCSR) {\n    return RegData(24, 4);\n  }\n  DEBUG_ASSERT(regno >= DREG_64_FCTRL && regno <= DREG_64_FOP);\n  // NB: most of these registers only occupy 2 bytes of space in\n  // the (f)xsave region, but gdb's default x86 target\n  // config expects us to send back 4 bytes of data for\n  // each.\n  return RegData(fxsave_387_ctrl_offsets[regno - DREG_64_FCTRL], 4);\n}\n\nstatic const uint64_t* xsave_features(const vector<uint8_t>& data) {\n  // If this is just FXSAVE(64) data then we we have no XSAVE header and no\n  // XSAVE(64) features enabled.\n  return data.size() < xsave_header_offset + xsave_header_size\n             ? nullptr\n             : reinterpret_cast<const uint64_t*>(data.data() +\n                                                 xsave_header_offset);\n\n}\n\nstatic uint64_t* xsave_features(vector<uint8_t>& data) {\n  // If this is just FXSAVE(64) data then we we have no XSAVE header and no\n  // XSAVE(64) features enabled.\n  return data.size() < xsave_header_offset + xsave_header_size\n             ? nullptr\n             : reinterpret_cast<uint64_t*>(data.data() + xsave_header_offset);\n}\n\nsize_t ExtraRegisters::read_register(uint8_t* buf, GdbServerRegister regno,\n                                     bool* defined) const {\n  if (format_ == NT_FPR) {\n    if (arch() != aarch64) {\n      *defined = false;\n      return 0;\n    }\n\n    RegData reg_data;\n    if (DREG_V0 <= regno && regno <= DREG_V31) {\n      reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, vregs[0]) +\n        ((regno - DREG_V0) * 16), 16);\n    } else if (regno == DREG_FPSR) {\n      reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, fpsr),\n                         sizeof(uint32_t));\n    } else if (regno == DREG_FPCR) {\n      reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, fpcr),\n                         sizeof(uint32_t));\n    } else {\n      *defined = false;\n      return 0;\n    }\n\n    DEBUG_ASSERT(size_t(reg_data.offset + reg_data.size) <= data_.size());\n    *defined = true;\n    memcpy(buf, data_.data() + reg_data.offset, reg_data.size);\n    return reg_data.size;\n  }\n\n  if (format_ != XSAVE) {\n    *defined = false;\n    return 0;\n  }\n\n  auto reg_data = xsave_register_data(arch(), regno);\n  if (reg_data.offset < 0 || empty()) {\n    *defined = false;\n    return reg_data.size;\n  }\n\n  DEBUG_ASSERT(reg_data.size > 0);\n\n  *defined = true;\n\n  // Apparently before any AVX registers are used, the feature bit is not set\n  // in the XSAVE data, so we'll just return 0 for them here.\n  const uint64_t* xsave_features_ = xsave_features(data_);\n  if (reg_data.xsave_feature_bit >= 0 &&\n      (!xsave_features_ ||\n       !(*xsave_features_ & (1 << reg_data.xsave_feature_bit)))) {\n    memset(buf, 0, reg_data.size);\n  } else {\n    DEBUG_ASSERT(size_t(reg_data.offset + reg_data.size) <= data_.size());\n    memcpy(buf, data_.data() + reg_data.offset, reg_data.size);\n  }\n  return reg_data.size;\n}\n\nbool ExtraRegisters::write_register(GdbServerRegister regno, const void* value,\n                                    size_t value_size) {\n  if (format_ == NT_FPR) {\n    if (arch() != aarch64) {\n      return false;\n    }\n\n    RegData reg_data;\n    if (DREG_V0 <= regno && regno <= DREG_V31) {\n      reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, vregs[0]) +\n        ((regno - DREG_V0) * 16), 16);\n    } else if (regno == DREG_FPSR) {\n      reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, fpsr),\n                         sizeof(uint32_t));\n    } else if (regno == DREG_FPCR) {\n      reg_data = RegData(offsetof(ARM64Arch::user_fpsimd_state, fpcr),\n                         sizeof(uint32_t));\n    } else {\n      return false;\n    }\n\n    DEBUG_ASSERT(reg_data.size > 0);\n    if ((size_t)reg_data.size != value_size) {\n      LOG(warn) << \"Register \" << regno << \"has mismatched sizes (\"\n                << reg_data.size << \" vs \" << value_size << \")\";\n      return false;\n    }\n\n    DEBUG_ASSERT(size_t(reg_data.offset + reg_data.size) <= data_.size());\n    memcpy(data_.data() + reg_data.offset, value, value_size);\n    return true;\n  }\n\n  if (format_ != XSAVE) {\n    return false;\n  }\n\n  auto reg_data = xsave_register_data(arch(), regno);\n  if (reg_data.offset < 0 || empty()) {\n    return false;\n  }\n\n  DEBUG_ASSERT(reg_data.size > 0);\n  if ((size_t)reg_data.size != value_size) {\n    LOG(warn) << \"Register \" << regno << \"has mismatched sizes (\"\n              << reg_data.size << \" vs \" << value_size << \")\";\n    return false;\n  }\n\n  if (reg_data.xsave_feature_bit >= 0) {\n    uint64_t* xsave_features_ = xsave_features(data_);\n    if (!xsave_features_) {\n      return false;\n    }\n\n    *xsave_features_ |= (1 << reg_data.xsave_feature_bit);\n  }\n\n  memcpy(data_.data() + reg_data.offset, value, value_size);\n  return true;\n}\n\nstatic const int xinuse_offset = 512;\n\nuint64_t ExtraRegisters::read_xinuse(bool* defined) const {\n  uint64_t ret;\n  if (format_ != XSAVE || data_.size() < 512 + sizeof(ret)) {\n    *defined = false;\n    return 0;\n  }\n\n  memcpy(&ret, data_.data() + xinuse_offset, sizeof(ret));\n  return ret;\n}\n\nuint64_t ExtraRegisters::read_fip(bool* defined) const {\n  if (format_ != XSAVE) {\n    *defined = false;\n    return 0;\n  }\n\n  uint64_t ret;\n  memcpy(&ret, data_.data() + fip_offset, sizeof(ret));\n  return ret;\n}\n\nuint16_t ExtraRegisters::read_fop(bool* defined) const {\n  if (format_ != XSAVE) {\n    *defined = false;\n    return 0;\n  }\n\n  uint16_t ret;\n  memcpy(&ret, data_.data() + fop_offset, sizeof(ret));\n  return ret;\n}\n\nuint32_t ExtraRegisters::read_mxcsr(bool* defined) const {\n  if (format_ != XSAVE) {\n    *defined = false;\n    return 0;\n  }\n\n  uint32_t ret;\n  memcpy(&ret, data_.data() + mxcsr_offset, sizeof(ret));\n  return ret;\n}\n\nbool ExtraRegisters::clear_fip_fdp() {\n  if (format_ != XSAVE) {\n    return false;\n  }\n\n  bool ret = false;\n  uint64_t v;\n  memcpy(&v, data_.data() + fip_offset, sizeof(v));\n  if (v != 0) {\n    ret = true;\n    memset(data_.data() + fip_offset, 0, 8);\n  }\n  memcpy(&v, data_.data() + fdp_offset, sizeof(v));\n  if (v != 0) {\n    ret = true;\n    memset(data_.data() + fdp_offset, 0, 8);\n  }\n  return ret;\n}\n\nvoid ExtraRegisters::validate(Task* t) {\n  if (format_ != XSAVE) {\n    return;\n  }\n\n  ASSERT(t, data_.size() >= 512);\n  uint32_t offset = 512;\n  if (data_.size() > offset) {\n    ASSERT(t, data_.size() >= offset + 64);\n    offset += 64;\n    const uint64_t* features = xsave_features(data_);\n    if (features && (*features & (1 << AVX_FEATURE_BIT))) {\n      ASSERT(t, data_.size() >= offset + 256);\n    }\n  }\n}\n\nstatic size_t get_full_value(const ExtraRegisters& r, GdbServerRegister low, GdbServerRegister hi,\n                             uint8_t buf[128]) {\n  bool defined = false;\n  size_t len = r.read_register(buf, low, &defined);\n  DEBUG_ASSERT(defined && len <= 64);\n  if (hi != GdbServerRegister(0)) {\n    size_t len2 = r.read_register(buf + len, hi, &defined);\n    if (defined) {\n      DEBUG_ASSERT(len == len2);\n      len += len2;\n    }\n  }\n  return len;\n}\n\nstatic string reg_to_string(const ExtraRegisters& r, GdbServerRegister low, GdbServerRegister hi) {\n  uint8_t buf[128];\n  size_t len = get_full_value(r, low, hi, buf);\n  bool printed_digit = false;\n  char out_buf[257];\n  char* p = out_buf;\n  for (int i = len - 1; i >= 0; --i) {\n    if (!printed_digit && !buf[i] && i > 0) {\n      continue;\n    }\n    p += sprintf(p, printed_digit ? \"%02x\" : \"%x\", buf[i]);\n    printed_digit = true;\n  }\n  return out_buf;\n}\n\nstatic void print_reg(const ExtraRegisters& r, GdbServerRegister low, GdbServerRegister hi,\n                      const char* name, FILE* f) {\n  string out = reg_to_string(r, low, hi);\n  fprintf(f, \"%s:0x%s\", name, out.c_str());\n}\n\nstatic void print_regs(const ExtraRegisters& r, GdbServerRegister low, GdbServerRegister hi,\n                       int num_regs, const char* name_base, FILE* f) {\n  for (int i = 0; i < num_regs; ++i) {\n    char buf[80];\n    sprintf(buf, \"%s%d\", name_base, i);\n    print_reg(r, (GdbServerRegister)(low + i),\n              hi == GdbServerRegister(0) ? hi : (GdbServerRegister)(hi + i), buf, f);\n    if (i < num_regs - 1) {\n      fputc(' ', f);\n    }\n  }\n}\n\nvoid ExtraRegisters::print_register_file_compact(FILE* f) const {\n  switch (arch_) {\n    case x86:\n      print_regs(*this, DREG_ST0, GdbServerRegister(0), 8, \"st\", f);\n      fputc(' ', f);\n      print_regs(*this, DREG_XMM0, DREG_YMM0H, 8, \"ymm\", f);\n      break;\n    case x86_64:\n      print_regs(*this, DREG_64_ST0, GdbServerRegister(0), 8, \"st\", f);\n      fputc(' ', f);\n      print_regs(*this, DREG_64_XMM0, DREG_64_YMM0H, 16, \"ymm\", f);\n      break;\n    case aarch64:\n      DEBUG_ASSERT(format_ == NT_FPR);\n      print_regs(*this, DREG_V0, GdbServerRegister(0), 32, \"v\", f);\n      fputc(' ', f);\n      print_reg(*this, DREG_FPSR, GdbServerRegister(0), \"fpsr\", f);\n      fputc(' ', f);\n      print_reg(*this, DREG_FPCR, GdbServerRegister(0), \"fpcr\", f);\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n      break;\n  }\n}\n\nstatic X86Arch::user_fpregs_struct convert_fxsave_to_x86_fpregs(\n    const X86Arch::user_fpxregs_struct& buf) {\n  X86Arch::user_fpregs_struct result;\n\n  for (int i = 0; i < 8; ++i) {\n    memcpy(reinterpret_cast<uint8_t*>(result.st_space) + i * 10,\n           &buf.st_space[i * 4], 10);\n  }\n\n  result.cwd = buf.cwd | 0xffff0000;\n  result.swd = buf.swd | 0xffff0000;\n  // XXX Computing the correct twd is a pain. It probably doesn't matter to us\n  // in practice.\n  result.twd = 0;\n  result.fip = buf.fip;\n  result.fcs = buf.fcs;\n  result.foo = buf.foo;\n  result.fos = buf.fos;\n\n  return result;\n}\n\nstatic void convert_x86_fpregs_to_fxsave(const X86Arch::user_fpregs_struct& buf,\n                                         X86Arch::user_fpxregs_struct* result) {\n  for (int i = 0; i < 8; ++i) {\n    memcpy(&result->st_space[i * 4],\n           reinterpret_cast<const uint8_t*>(buf.st_space) + i * 10, 10);\n  }\n\n  result->cwd = buf.cwd;\n  result->swd = buf.swd;\n  // XXX Computing the correct twd is a pain. It probably doesn't matter to us\n  // in practice.\n  result->fip = buf.fip;\n  result->fcs = buf.fcs;\n  result->foo = buf.foo;\n  result->fos = buf.fos;\n}\n\ntemplate <typename T> static vector<uint8_t> to_vector(const T& v) {\n  vector<uint8_t> result;\n  result.resize(sizeof(T));\n  memcpy(result.data(), &v, sizeof(T));\n  return result;\n}\n\nstatic uint32_t features_used(const uint8_t* data) {\n  uint64_t features;\n  memcpy(&features, data + xsave_header_offset, sizeof(features));\n  return features;\n}\n\ntemplate <typename Arch>\nbool memcpy_fpr_regs_arch(std::vector<uint8_t>& dest, const uint8_t* src,\n                          size_t data_size) {\n  if (data_size != sizeof(typename Arch::user_fpregs_struct)) {\n    LOG(error) << \"Invalid FPR data length: \" << data_size << \" for architecture \" <<\n      arch_name(Arch::arch()) << \", expected \" << sizeof(typename Arch::user_fpregs_struct);\n    return false;\n  }\n  dest.resize(sizeof(typename Arch::user_fpregs_struct));\n  memcpy(dest.data(), src, sizeof(typename Arch::user_fpregs_struct));\n  return true;\n}\n\nbool memcpy_fpr_regs_arch(SupportedArch arch, std::vector<uint8_t>& dest,\n                          const uint8_t* src, size_t data_size) {\n  RR_ARCH_FUNCTION(memcpy_fpr_regs_arch, arch, dest, src, data_size)\n}\n\nbool ExtraRegisters::set_to_raw_data(SupportedArch a, Format format,\n                                     const uint8_t* data, size_t data_size,\n                                     const XSaveLayout& layout) {\n  arch_ = a;\n  format_ = NONE;\n\n  if (format == NONE) {\n    return true;\n  } else if (format == NT_FPR) {\n    if (!memcpy_fpr_regs_arch(a, data_, data, data_size)) {\n      return false;\n    }\n    format_ = NT_FPR;\n    return true;\n  }\n\n  if (format != XSAVE) {\n    LOG(error) << \"Unknown ExtraRegisters format: \" << format;\n    return false;\n  }\n  format_ = XSAVE;\n\n  // Now we have to convert from the input XSAVE format to our\n  // native XSAVE format. Be careful to handle possibly-corrupt input data.\n\n  const XSaveLayout& native_layout = xsave_native_layout();\n  if (data_size != layout.full_size) {\n    LOG(error) << \"Invalid XSAVE data length: \" << data_size << \", expected \"\n               << layout.full_size;\n    return false;\n  }\n  data_.resize(native_layout.full_size);\n  DEBUG_ASSERT(data_.size() >= xsave_header_offset);\n  if (layout.full_size < xsave_header_offset) {\n    LOG(error) << \"Invalid XSAVE layout size: \" << layout.full_size;\n    return false;\n  }\n  memcpy(data_.data(), data, xsave_header_offset);\n  memset(data_.data() + xsave_header_offset, 0,\n         data_.size() - xsave_header_offset);\n\n  // Check for unsupported features being used\n  if (layout.full_size >= xsave_header_end) {\n    uint64_t features = features_used(data);\n    /* Mask off the PKRU bit unconditionally here.\n     * We want traces that are recorded on machines with PKRU but\n     * that don't actually use PKRU to be replayable on machines\n     * without PKRU. Linux, however, sets the PKRU register to\n     * 0x55555554 (only the default key is allowed to access memory),\n     * while the default hardware value is 0, so in some sense\n     * PKRU is always in use.\n     *\n     * There are three classes of side effects of the pkey feature.\n     * 1. The direct effects of syscalls such as pkey_alloc/pkey_mprotect\n     *    on registers.\n     * 2. Traps generated by the CPU when the protection keys are violated.\n     * 3. The RDPKRU instruction writing to EAX.\n     *\n     * The first two are replayed exactly by rr. The latter will trigger\n     * SIGILL on any machine without PKRU, which is no different from\n     * any other new CPU instruction that doesn't have its own XSAVE\n     * feature bit. So ignore the PKRU bit here and leave users on their\n     * own with respect to RDPKRU.\n     */\n    features &= ~PKRU_FEATURE_MASK;\n    if (features & ~native_layout.supported_feature_bits) {\n      LOG(error) << \"Unsupported CPU features found: got \" << HEX(features)\n                 << \" (\" << xsave_feature_string(features)\n                 << \"), supported: \"\n                 << HEX(native_layout.supported_feature_bits)\n                 << \" (\"\n                 << xsave_feature_string(native_layout.supported_feature_bits)\n                 << \"); Consider using `rr cpufeatures` and \"\n                 << \"`rr record --disable-cpuid-features-(ext)`\";\n      return false;\n    }\n  }\n\n  if (native_layout.full_size < xsave_header_end) {\n    // No XSAVE supported here, we're done!\n    return true;\n  }\n  if (layout.full_size < xsave_header_end) {\n    // Degenerate XSAVE format without an actual XSAVE header. Assume x87+XMM\n    // are in use.\n    uint64_t assume_features_used = 0x3;\n    memcpy(data_.data() + xsave_header_offset, &assume_features_used,\n           sizeof(assume_features_used));\n    return true;\n  }\n\n  uint64_t features = features_used(data);\n  // OK, now both our native layout and the input layout are using the full\n  // XSAVE header. Copy each optional and present area into the right place\n  // in our struct.\n  for (size_t i = 2; i < 64; ++i) {\n    if (features & (uint64_t(1) << i)) {\n      if (i >= layout.feature_layouts.size()) {\n        LOG(error) << \"Invalid feature \" << i << \" beyond max layout \"\n                   << layout.feature_layouts.size();\n        return false;\n      }\n      const XSaveFeatureLayout& feature = layout.feature_layouts[i];\n      if (uint64_t(feature.offset) + feature.size > layout.full_size) {\n        LOG(error) << \"Invalid feature region: \" << feature.offset << \"+\"\n                   << feature.size << \" > \" << layout.full_size;\n        return false;\n      }\n      if (i >= native_layout.feature_layouts.size()) {\n        if (i == PKRU_FEATURE_BIT) {\n          // The native arch doesn't support PKRU.\n          // This must be during replay, and as the comments above explain,\n          // it's OK to not set PKRU during replay on a pre-PKRU CPU, so\n          // we can just ignore this.\n          features &= ~PKRU_FEATURE_MASK;\n          continue;\n        } else {\n          LOG(error) << \"Invalid feature \" << i << \" beyond max layout \"\n                     << layout.feature_layouts.size();\n          return false;\n        }\n      }\n      const XSaveFeatureLayout& native_feature =\n          native_layout.feature_layouts[i];\n      if (native_feature.size == 0 && i == PKRU_FEATURE_BIT) {\n        // See the above comment about PKRU.\n        features &= ~PKRU_FEATURE_MASK;\n        continue;\n      }\n      if (feature.size != native_feature.size) {\n        LOG(error) << \"Feature \" << i << \" has wrong size \" << feature.size\n                   << \", expected \" << native_feature.size;\n        return false;\n      }\n      // The CPU should guarantee these\n      DEBUG_ASSERT(native_feature.offset > 0);\n      DEBUG_ASSERT(native_feature.offset + native_feature.size <=\n                   native_layout.full_size);\n      memcpy(data_.data() + native_feature.offset, data + feature.offset,\n             feature.size);\n    }\n  }\n\n  // Copy the header. Make sure to use our updated `features`.\n  memcpy(data_.data() + xsave_header_offset, &features, sizeof(features));\n  memcpy(data_.data() + xsave_header_offset + sizeof(features),\n         data + xsave_header_offset + sizeof(features),\n         xsave_header_size - sizeof(features));\n\n  return true;\n}\n\nvector<uint8_t> ExtraRegisters::get_user_fpregs_struct(\n    SupportedArch arch) const {\n  switch (arch) {\n    case x86:\n      DEBUG_ASSERT(format_ == XSAVE);\n      DEBUG_ASSERT(data_.size() >= sizeof(X86Arch::user_fpxregs_struct));\n      return to_vector(convert_fxsave_to_x86_fpregs(\n          *reinterpret_cast<const X86Arch::user_fpxregs_struct*>(\n              data_.data())));\n    case x86_64:\n      DEBUG_ASSERT(format_ == XSAVE);\n      DEBUG_ASSERT(data_.size() >= sizeof(X64Arch::user_fpregs_struct));\n      return to_vector(\n          *reinterpret_cast<const X64Arch::user_fpregs_struct*>(data_.data()));\n    case aarch64:\n      DEBUG_ASSERT(format_ == NT_FPR);\n      DEBUG_ASSERT(data_.size() == sizeof(ARM64Arch::user_fpregs_struct));\n      return to_vector(\n          *reinterpret_cast<const ARM64Arch::user_fpregs_struct*>(data_.data()));\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n      return vector<uint8_t>();\n  }\n}\n\nvoid ExtraRegisters::set_user_fpregs_struct(Task* t, SupportedArch arch,\n                                            void* data, size_t size) {\n  switch (arch) {\n    case x86:\n      DEBUG_ASSERT(format_ == XSAVE);\n      ASSERT(t, size >= sizeof(X86Arch::user_fpregs_struct));\n      ASSERT(t, data_.size() >= sizeof(X86Arch::user_fpxregs_struct));\n      convert_x86_fpregs_to_fxsave(\n          *static_cast<X86Arch::user_fpregs_struct*>(data),\n          reinterpret_cast<X86Arch::user_fpxregs_struct*>(data_.data()));\n      return;\n    case x86_64:\n      DEBUG_ASSERT(format_ == XSAVE);\n      ASSERT(t, data_.size() >= sizeof(X64Arch::user_fpregs_struct));\n      ASSERT(t, size >= sizeof(X64Arch::user_fpregs_struct));\n      memcpy(data_.data(), data, sizeof(X64Arch::user_fpregs_struct));\n      return;\n    case aarch64:\n      DEBUG_ASSERT(format_ == NT_FPR);\n      ASSERT(t, size >= sizeof(ARM64Arch::user_fpregs_struct));\n      ASSERT(t, data_.size() >= sizeof(ARM64Arch::user_fpregs_struct));\n      memcpy(data_.data(), data, sizeof(ARM64Arch::user_fpregs_struct));\n      return;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n  }\n}\n\nX86Arch::user_fpxregs_struct ExtraRegisters::get_user_fpxregs_struct() const {\n  DEBUG_ASSERT(format_ == XSAVE);\n  DEBUG_ASSERT(arch_ == x86);\n  DEBUG_ASSERT(data_.size() >= sizeof(X86Arch::user_fpxregs_struct));\n  return *reinterpret_cast<const X86Arch::user_fpxregs_struct*>(data_.data());\n}\n\nvoid ExtraRegisters::set_user_fpxregs_struct(\n    Task* t, const X86Arch::user_fpxregs_struct& regs) {\n  ASSERT(t, format_ == XSAVE);\n  ASSERT(t, arch_ == x86);\n  ASSERT(t, data_.size() >= sizeof(X86Arch::user_fpxregs_struct));\n  memcpy(data_.data(), &regs, sizeof(regs));\n}\n\nstatic void set_word(SupportedArch arch, vector<uint8_t>& v, GdbServerRegister r,\n                     int word) {\n  RegData d = xsave_register_data(arch, r);\n  DEBUG_ASSERT(d.size == 4);\n  DEBUG_ASSERT(d.offset + d.size <= (int)v.size());\n  DEBUG_ASSERT(-1 == d.xsave_feature_bit);\n  *reinterpret_cast<int*>(v.data() + d.offset) = word;\n}\n\nvoid ExtraRegisters::reset() {\n  memset(data_.data(), 0, data_.size());\n  if (is_x86ish(arch())) {\n    DEBUG_ASSERT(format_ == XSAVE);\n    if (arch() == x86_64) {\n      set_word(arch(), data_, DREG_64_MXCSR, 0x1f80);\n      set_word(arch(), data_, DREG_64_FCTRL, 0x37f);\n    } else {\n      set_word(arch(), data_, DREG_MXCSR, 0x1f80);\n      set_word(arch(), data_, DREG_FCTRL, 0x37f);\n    }\n    uint64_t xinuse;\n    if (data_.size() >= xinuse_offset + sizeof(xinuse)) {\n      memcpy(&xinuse, data_.data() + xinuse_offset, sizeof(xinuse));\n\n      /* We have observed (Skylake, Linux 4.10) the system setting XINUSE's 0 bit\n      * to indicate x87-in-use, at times unrelated to x87 actually being used.\n      * Work around this by setting the bit unconditionally after exec.\n      */\n      xinuse |= 1;\n\n      /* If the system supports the PKRU feature, the PKRU feature bit must be\n      * set in order to get the kernel to properly update the PKRU register\n      * value. If this is not set, it has been observed that the PKRU register\n      * may occasionally contain \"stale\" values, particularly after involuntary\n      * context switches.\n      * Avoid this issue by setting the bit if the feature is supported by the\n      * CPU.\n      */\n      if (xcr0() & PKRU_FEATURE_MASK) {\n        RegData d = xsave_register_data(arch(), arch() == x86_64 ? DREG_64_PKRU : DREG_PKRU);\n        DEBUG_ASSERT(d.xsave_feature_bit == PKRU_FEATURE_BIT);\n        DEBUG_ASSERT(d.offset + d.size <= (int)data_.size());\n        *reinterpret_cast<int*>(data_.data() + d.offset) = 0x55555554;\n        xinuse |= PKRU_FEATURE_MASK;\n      }\n\n      memcpy(data_.data() + xinuse_offset, &xinuse, sizeof(xinuse));\n    }\n  } else {\n    DEBUG_ASSERT(format_ == NT_FPR);\n    DEBUG_ASSERT(arch() == aarch64 &&\n      \"Ensure that nothing is required here for your architecture.\");\n  }\n}\n\nstatic void compare_regs(const ExtraRegisters& reg1,\n                         const ExtraRegisters& reg2,\n                         GdbServerRegister low, GdbServerRegister hi,\n                         int num_regs, const char* name_base,\n                         Registers::Comparison& result) {\n  for (int i = 0; i < num_regs; ++i) {\n    GdbServerRegister this_low = (GdbServerRegister)(low + i);\n    GdbServerRegister this_hi = hi == GdbServerRegister(0) ? hi : (GdbServerRegister)(hi + i);\n    uint8_t buf1[128];\n    size_t len1 = get_full_value(reg1, this_low, this_hi, buf1);\n    uint8_t buf2[128];\n    size_t len2 = get_full_value(reg2, this_low, this_hi, buf2);\n    DEBUG_ASSERT(len1 == len2);\n\n    if (!memcmp(buf1, buf2, len1)) {\n      continue;\n    }\n\n    ++result.mismatch_count;\n    if (result.store_mismatches) {\n      char regname[80];\n      sprintf(regname, \"%s%d\", name_base, i);\n      result.mismatches.push_back({regname, reg_to_string(reg1, this_low, this_hi),\n          reg_to_string(reg2, this_low, this_hi)});\n    }\n  }\n}\n\nvoid ExtraRegisters::compare_internal(const ExtraRegisters& reg2,\n  Registers::Comparison& result) const {\n  const GdbServerRegister NOT_PRESENT = GdbServerRegister(0);\n  if (arch() != reg2.arch()) {\n    FATAL() << \"Can't compare register files with different archs\";\n  }\n\n  if (format() == NONE || reg2.format() == NONE) {\n    // Not enough data to check anything\n    return;\n  }\n  if (format() != reg2.format()) {\n    FATAL() << \"Can't compare register files with different formats\";\n  }\n  bool avx_present = false;\n  if (format() == XSAVE) {\n    avx_present = !!(xsave_native_layout().supported_feature_bits & (1 << AVX_FEATURE_BIT));\n  }\n\n  switch (arch()) {\n    case x86:\n      compare_regs(*this, reg2, DREG_ST0, NOT_PRESENT, 8, \"st\", result);\n      compare_regs(*this, reg2, DREG_XMM0, avx_present ? DREG_YMM0H : NOT_PRESENT, 8, \"ymm\", result);\n      break;\n    case x86_64:\n      compare_regs(*this, reg2, DREG_64_ST0, NOT_PRESENT, 8, \"st\", result);\n      compare_regs(*this, reg2, DREG_64_XMM0, avx_present ? DREG_64_YMM0H : NOT_PRESENT, 8, \"ymm\", result);\n      break;\n    case aarch64:\n      DEBUG_ASSERT(format_ == NT_FPR);\n      compare_regs(*this, reg2, DREG_V0, NOT_PRESENT, 32, \"v\", result);\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n      break;\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ExtraRegisters.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_EXTRA_REGISTERS_H_\n#define RR_EXTRA_REGISTERS_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <vector>\n\n#include \"GdbServerRegister.h\"\n#include \"Registers.h\"\n#include \"kernel_abi.h\"\n\nnamespace rr {\n\nclass ReplayTask;\nstruct XSaveLayout;\n\n/**\n * An ExtraRegisters object contains values for all user-space-visible\n * registers other than those in Registers.\n *\n * Task is responsible for creating meaningful values of this class.\n *\n * The only reason this class has an arch() is to enable us to\n * interpret GdbServerRegister.\n */\nclass ExtraRegisters {\npublic:\n  // Create empty (uninitialized/unknown registers) value\n  ExtraRegisters(SupportedArch arch = x86)\n      : format_(NONE), arch_(arch) {}\n  enum Format { NONE,\n  /**\n   * The XSAVE format is x86(_64) only.\n   * On a x86 64-bit kernel, these structures are initialized by an XSAVE64 or\n   * FXSAVE64.\n   * On a x86 32-bit kernel, they are initialized by an XSAVE or FXSAVE.\n   *\n   * The layouts are basically the same in the first 512 bytes --- an\n   * FXSAVE(64) area. The differences are:\n   * -- On a 64-bit kernel, registers XMM8-XMM15 are saved, but on a 32-bit\n   * kernel they are not (that space is reserved).\n   * -- On a 64-bit kernel, bytes 8-15 store a 64-bit \"FPU IP\" address,\n   * but on a 32-bit kernel they store \"FPU IP/CS\". Likewise,\n   * bytes 16-23 store \"FPU DP\" or \"FPU DP/DS\".\n   * We basically ignore these differences. If gdb requests 32-bit-specific\n   * registers, we return them, assuming that the data there is valid.\n   *\n   * XSAVE/XSAVE64 have extra information after the first 512 bytes, which we\n   * currently save and restore but do not otherwise use. If the data record\n   * has more than 512 bytes then it's an XSAVE(64) area, otherwise it's just\n   * the FXSAVE(64) area.\n   *\n   * The data always uses our CPU's native XSAVE layout. When reading a trace,\n   * we need to convert from the trace's CPU's XSAVE layout to our layout.\n   */\n  XSAVE,\n  /**\n   * Stores the content of the NT_FPREGS regset. The format depends on the\n   * architecture. It is given by Arch::user_fpregs_struct for the appropriate\n   * architecture.\n   */\n  NT_FPR };\n\n  // Set values from raw data, with the given XSAVE layout. Returns false\n  // if this could not be done.\n  bool set_to_raw_data(SupportedArch a, Format format, const uint8_t* data,\n                       size_t data_size, const XSaveLayout& layout);\n  Format format() const { return format_; }\n  SupportedArch arch() const { return arch_; }\n  const std::vector<uint8_t> data() const { return data_; }\n  int data_size() const { return data_.size(); }\n  const uint8_t* data_bytes() const { return data_.data(); }\n  bool empty() const { return data_.empty(); }\n\n  /**\n   * Read XSAVE `xinuse` field\n   */\n  uint64_t read_xinuse(bool* defined) const;\n\n  /**\n   * Read FIP field\n   */\n  uint64_t read_fip(bool* defined) const;\n\n  /**\n   * Read FOP field\n   */\n  uint16_t read_fop(bool* defined) const;\n\n  /**\n   * Read MXCSR field\n   */\n  uint32_t read_mxcsr(bool* defined) const;\n\n  /**\n   * Clear FIP and FDP registers if they're present.\n   * Returns true if the registers changed.\n   */\n  bool clear_fip_fdp();\n\n  /**\n   * Like |Registers::read_register()|, except attempts to read\n   * the value of an \"extra register\" (floating point / vector).\n   */\n  size_t read_register(uint8_t* buf, GdbServerRegister regno, bool* defined) const;\n\n  /**\n   * Like |Registers::write_register()|, except attempts to write\n   * the value of an \"extra register\" (floating point / vector).\n   */\n  bool write_register(GdbServerRegister regno, const void* value, size_t value_size);\n\n  /**\n   * Get a user_fpregs_struct for a particular Arch from these ExtraRegisters.\n   */\n  std::vector<uint8_t> get_user_fpregs_struct(SupportedArch arch) const;\n\n  /**\n   * Update registers from a user_fpregs_struct.\n   */\n  void set_user_fpregs_struct(Task* t, SupportedArch arch, void* data,\n                              size_t size);\n\n  /**\n   * Get a user_fpxregs_struct for from these ExtraRegisters.\n   */\n  X86Arch::user_fpxregs_struct get_user_fpxregs_struct() const;\n\n  /**\n   * Update registers from a user_fpxregs_struct.\n   */\n  void set_user_fpxregs_struct(Task* t,\n                               const X86Arch::user_fpxregs_struct& regs);\n\n  void print_register_file_compact(FILE* f) const;\n\n  /**\n   * Reset to post-exec initial state\n   */\n  void reset();\n\n  void validate(Task* t);\n\n  /**\n   * Return true if |reg1| matches |reg2|.  Passing EXPECT_MISMATCHES\n   * indicates that the caller is using this as a general register\n   * compare and nothing special should be done if the register files\n   * mismatch.  Passing LOG_MISMATCHES will log the registers that don't\n   * match.  Passing BAIL_ON_MISMATCH will additionally abort on\n   * mismatch.\n   * This is conservative; we only return false if we have enough\n   * information to verify that the registers definitely don't match.\n   * The register files must have the same arch.\n   */\n  Registers::Comparison compare_with(const ExtraRegisters& reg2) const {\n    Registers::Comparison result;\n    compare_internal(reg2, result);\n    return result;\n  }\n\n  bool matches(const ExtraRegisters& reg2) const {\n    Registers::Comparison result;\n    result.store_mismatches = false;\n    compare_internal(reg2, result);\n    return !result.mismatch_count;\n  }\n\nprivate:\n  friend class Task;\n\n  void compare_internal(const ExtraRegisters& reg2, Registers::Comparison& result) const;\n\n  Format format_;\n  SupportedArch arch_;\n  std::vector<uint8_t> data_;\n};\n\n} // namespace rr\n\n#endif /* RR_EXTRA_REGISTERS_H_ */\n"
  },
  {
    "path": "src/FdTable.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"FdTable.h\"\n\n#include <limits.h>\n\n#include <unordered_set>\n#include <utility>\n\n#include \"rr/rr.h\"\n\n#include \"AddressSpace.h\"\n#include \"RecordTask.h\"\n#include \"ReplayTask.h\"\n#include \"Session.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nFdTable::shr_ptr FdTable::create(Task* t) {\n  shr_ptr fds(new FdTable(t->session().syscallbuf_fds_disabled_size()));\n  fds->insert_task(t);\n  return fds;\n}\n\nvoid FdTable::insert_task(Task* t) {\n  HasTaskSet::insert_task(t);\n  ++vms[t->vm().get()];\n}\n\nvoid FdTable::erase_task(Task* t) {\n  if (task_set().find(t) == task_set().end()) {\n    return;\n  }\n  HasTaskSet::erase_task(t);\n  auto it = vms.find(t->vm().get());\n  if (it == vms.end()) {\n    FATAL() << \"Lost track of VM already?\";\n  }\n  --it->second;\n  if (!it->second) {\n    vms.erase(it);\n  }\n}\n\nvoid FdTable::add_monitor(Task* t, int fd, FileMonitor* monitor) {\n  // In the future we could support multiple monitors on an fd, but we don't\n  // need to yet.\n  FileMonitor* current = get_monitor(fd);\n  if (current) {\n    ASSERT(t, false) << \"Task \" << t->rec_tid << \" already monitoring fd \"\n      << fd << \" \" << file_monitor_type_name(current->type());\n  }\n  if (fd >= syscallbuf_fds_disabled_size && fds.count(fd) == 0) {\n    fd_count_beyond_limit++;\n  }\n  fds[fd] = FileMonitor::shr_ptr(monitor);\n  update_syscallbuf_fds_disabled(fd);\n}\n\nvoid FdTable::replace_monitor(Task* t, int fd, FileMonitor* monitor) {\n  if (!is_monitoring(fd)) {\n    add_monitor(t, fd, monitor);\n  } else {\n    fds[fd] = FileMonitor::shr_ptr(monitor);\n  }\n}\n\nbool FdTable::is_rr_fd(int fd) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return false;\n  }\n  return it->second->is_rr_fd();\n}\n\nbool FdTable::emulate_ioctl(int fd, RecordTask* t, uint64_t* result) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return false;\n  }\n  return it->second->emulate_ioctl(t, result);\n}\n\nbool FdTable::emulate_fcntl(int fd, RecordTask* t, uint64_t* result) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return false;\n  }\n  return it->second->emulate_fcntl(t, result);\n}\n\nbool FdTable::emulate_read(int fd, RecordTask* t,\n                           const std::vector<FileMonitor::Range>& ranges,\n                           FileMonitor::LazyOffset& offset, uint64_t* result) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return false;\n  }\n  return it->second->emulate_read(t, ranges, offset, result);\n}\n\nvoid FdTable::filter_getdents(int fd, RecordTask* t) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return;\n  }\n  it->second->filter_getdents(t);\n}\n\nSwitchable FdTable::will_write(Task* t, int fd) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return ALLOW_SWITCH;\n  }\n  return it->second->will_write(t);\n}\n\nvoid FdTable::did_write(Task* t, int fd,\n                        const std::vector<FileMonitor::Range>& ranges,\n                        FileMonitor::LazyOffset& offset) {\n  auto it = fds.find(fd);\n  if (it != fds.end()) {\n    it->second->did_write(t, ranges, offset);\n  }\n}\n\nvoid FdTable::did_dup(FdTable* table, int from, int to) {\n  if (table->fds.count(from)) {\n    if (to >= syscallbuf_fds_disabled_size && fds.count(to) == 0) {\n      fd_count_beyond_limit++;\n    }\n    fds[to] = table->fds[from];\n  } else {\n    if (to >= syscallbuf_fds_disabled_size && fds.count(to) > 0) {\n      fd_count_beyond_limit--;\n    }\n    fds.erase(to);\n  }\n  update_syscallbuf_fds_disabled(to);\n}\n\nvoid FdTable::did_close(int fd) {\n  LOG(debug) << \"Close fd \" << fd;\n  if (fd >= syscallbuf_fds_disabled_size && fds.count(fd) > 0) {\n    fd_count_beyond_limit--;\n  }\n  fds.erase(fd);\n  update_syscallbuf_fds_disabled(fd);\n}\n\nFileMonitor* FdTable::get_monitor(int fd) {\n  auto it = fds.find(fd);\n  if (it == fds.end()) {\n    return nullptr;\n  }\n  return it->second.get();\n}\n\nstatic syscallbuf_fd_classes join_fd_classes_over_tasks(AddressSpace* vm, int fd,\n    int syscallbuf_fds_disabled_size) {\n  syscallbuf_fd_classes cls = FD_CLASS_UNTRACED;\n  for (Task* t : vm->task_set()) {\n    auto table = t->fd_table();\n    if (table->is_monitoring(fd)) {\n      if (cls != FD_CLASS_UNTRACED) {\n        return FD_CLASS_TRACED;\n      }\n      cls = table->get_monitor(fd)->get_syscallbuf_class();\n    } else if (fd >= syscallbuf_fds_disabled_size - 1 &&\n        table->count_beyond_limit() > 0) {\n      return FD_CLASS_TRACED;\n    }\n  }\n  return cls;\n}\n\nvoid FdTable::update_syscallbuf_fds_disabled(int fd) {\n  DEBUG_ASSERT(fd >= 0);\n  DEBUG_ASSERT(task_set().size() > 0);\n\n  // It's possible for tasks with different VMs to share this fd table.\n  // But tasks with the same VM might have different fd tables...\n  for (auto address_space : vms) {\n    RecordTask* rt = nullptr;\n    if (address_space.first->task_set().empty()) {\n      FATAL() << \"Address space must have at least one task\";\n    }\n    for (Task* t : address_space.first->task_set()) {\n      if (!t->session().is_recording()) {\n        // We could return but we want to check that all our\n        // AddressSpaces have tasks (i.e. aren't dead/dangling)\n        break;\n      }\n      rt = static_cast<RecordTask*>(t);\n      if (!rt->already_exited()) {\n        break;\n      }\n      rt = nullptr;\n    }\n    if (rt && !rt->preload_globals.is_null()) {\n      if (fd >= syscallbuf_fds_disabled_size) {\n        fd = syscallbuf_fds_disabled_size - 1;\n      }\n      char disable = (char)join_fd_classes_over_tasks(address_space.first, fd,\n          syscallbuf_fds_disabled_size);\n      auto addr =\n          REMOTE_PTR_FIELD(rt->preload_globals, syscallbuf_fd_class[0]) + fd;\n      rt->write_mem(addr, disable);\n      rt->record_local(addr, &disable);\n    }\n  }\n}\n\nvoid FdTable::init_syscallbuf_fds_disabled(Task* t) {\n  if (!t->session().is_recording()) {\n    return;\n  }\n  RecordTask* rt = static_cast<RecordTask*>(t);\n\n  ASSERT(rt, has_task(rt));\n\n  if (rt->preload_globals.is_null()) {\n    return;\n  }\n\n  vector<char> disabled;\n  disabled.resize(syscallbuf_fds_disabled_size, 0);\n\n  // It's possible that some tasks in this address space have a different\n  // FdTable. We need to disable syscallbuf for an fd if any tasks for this\n  // address space are monitoring the fd.\n  for (Task* vm_t : rt->vm()->task_set()) {\n    for (auto& it : vm_t->fd_table()->fds) {\n      int fd = it.first;\n      DEBUG_ASSERT(fd >= 0);\n      if (fd >= syscallbuf_fds_disabled_size) {\n        fd = syscallbuf_fds_disabled_size - 1;\n      }\n      if (disabled[fd] == FD_CLASS_UNTRACED) {\n        disabled[fd] = it.second->get_syscallbuf_class();\n      } else {\n        disabled[fd] = FD_CLASS_TRACED;\n      }\n    }\n  }\n\n  auto addr = REMOTE_PTR_FIELD(t->preload_globals, syscallbuf_fd_class[0]);\n  rt->write_mem(addr, disabled.data(), syscallbuf_fds_disabled_size);\n  rt->record_local(addr, disabled.data(), syscallbuf_fds_disabled_size);\n}\n\nvoid FdTable::close_after_exec(ReplayTask* t, const vector<int>& fds_to_close) {\n  ASSERT(t, has_task(t));\n\n  for (auto fd : fds_to_close) {\n    did_close(fd);\n  }\n}\n\nstatic bool is_fd_open(Task* t, int fd) {\n  char path[PATH_MAX];\n  sprintf(path, \"/proc/%d/fd/%d\", t->tid, fd);\n  struct stat st;\n  return 0 == lstat(path, &st);\n}\n\nvector<int> FdTable::fds_to_close_after_exec(RecordTask* t) {\n  ASSERT(t, has_task(t));\n\n  vector<int> fds_to_close;\n  for (auto& it : fds) {\n    if (!is_fd_open(t, it.first)) {\n      fds_to_close.push_back(it.first);\n    }\n  }\n  for (auto fd : fds_to_close) {\n    did_close(fd);\n  }\n  return fds_to_close;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/FdTable.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_FD_TABLE_H_\n#define RR_FD_TABLE_H_\n\n#include <memory>\n#include <unordered_map>\n#include <vector>\n\n#include \"FileMonitor.h\"\n#include \"HasTaskSet.h\"\n\nnamespace rr {\n\nclass AddressSpace;\nclass RecordTask;\nclass ReplayTask;\nclass Task;\n\nclass FdTable final : public HasTaskSet {\npublic:\n  typedef std::shared_ptr<FdTable> shr_ptr;\n\n  void add_monitor(Task* t, int fd, FileMonitor* monitor);\n  void replace_monitor(Task* t, int fd, FileMonitor* monitor);\n  bool emulate_ioctl(int fd, RecordTask* t, uint64_t* result);\n  bool emulate_fcntl(int fd, RecordTask* t, uint64_t* result);\n  bool emulate_read(int fd, RecordTask* t,\n                    const std::vector<FileMonitor::Range>& ranges,\n                    FileMonitor::LazyOffset& offset, uint64_t* result);\n  void filter_getdents(int fd, RecordTask* t);\n  bool is_rr_fd(int fd);\n  Switchable will_write(Task* t, int fd);\n  void did_write(Task* t, int fd, const std::vector<FileMonitor::Range>& ranges,\n                 FileMonitor::LazyOffset& offset);\n  void did_dup(int from, int to) {\n    did_dup(this, from, to);\n  }\n  void did_dup(FdTable* table, int from, int to);\n  void did_close(int fd);\n\n  shr_ptr clone() const {\n    return shr_ptr(new FdTable(*this));\n  }\n\n  static shr_ptr create(Task* t);\n\n  bool is_monitoring(int fd) const { return fds.count(fd) > 0; }\n  uint32_t count_beyond_limit() const { return fd_count_beyond_limit; }\n\n  FileMonitor* get_monitor(int fd);\n\n  /**\n   * Regenerate syscallbuf_fds_disabled in task |t|.\n   * Called during initialization of the preload library.\n   */\n  void init_syscallbuf_fds_disabled(Task* t);\n\n  /**\n   * Get list of fds that have been closed after |t| has done an execve.\n   * Rather than tracking CLOEXEC flags (which would be complicated), we just\n   * scan /proc/<pid>/fd during recording and note any monitored fds that have\n   * been closed.\n   * This also updates our table to match reality.\n   */\n  std::vector<int> fds_to_close_after_exec(RecordTask* t);\n\n  /**\n   * Close fds in list after an exec.\n   */\n  void close_after_exec(ReplayTask* t, const std::vector<int>& fds_to_close);\n\n  // Used to optimize ReplayTask's find_free_file_descriptor\n  int last_free_fd() const { return last_free_fd_; }\n  void set_last_free_fd(int last_free_fd) { last_free_fd_ = last_free_fd; }\n\n  void insert_task(Task* t) override;\n  void erase_task(Task* t) override;\n\nprivate:\n  explicit FdTable(uint32_t syscallbuf_fds_disabled_size)\n    : syscallbuf_fds_disabled_size(syscallbuf_fds_disabled_size),\n      fd_count_beyond_limit(0), last_free_fd_(0) {}\n  // Does not call the base-class copy constructor because\n  // we don't want to copy the task set; the new FdTable will\n  // be for new tasks.\n  FdTable(const FdTable& other) : fds(other.fds),\n    syscallbuf_fds_disabled_size(other.syscallbuf_fds_disabled_size),\n    fd_count_beyond_limit(other.fd_count_beyond_limit),\n    last_free_fd_(other.last_free_fd_) {}\n\n  void update_syscallbuf_fds_disabled(int fd);\n\n  std::unordered_map<int, FileMonitor::shr_ptr> fds;\n  std::unordered_map<AddressSpace*, int> vms;\n  // Currently this is only used during recording, so we could use\n  // SYSCALLBUF_FDS_DISABLED_SIZE directly and not bother tracking it in\n  // the trace header, but to make things less fragile in case we ever need to\n  // know it during replay, we track it here.\n  int syscallbuf_fds_disabled_size;\n  // Number of elements of `fds` that are >= syscallbuf_fds_disabled_size.\n  // Only used during recording.\n  uint32_t fd_count_beyond_limit;\n  // Only used during recording.\n  int last_free_fd_;\n};\n\n} // namespace rr\n\n#endif /* RR_FD_TABLE_H_ */\n"
  },
  {
    "path": "src/FileMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"FileMonitor.h\"\n\n#include <linux/limits.h>\n\n#include <rr/rr.h>\n\n#include <vector>\n\n#include \"RecordTask.h\"\n#include \"ReplayTask.h\"\n#include \"Session.h\"\n#include \"log.h\"\n\nnamespace rr {\nusing namespace std;\n\ntemplate <typename Arch>\nstatic bool is_implicit_offset_syscall_arch(int syscallno) {\n  return syscallno == Arch::writev || syscallno == Arch::write ||\n         syscallno == Arch::readv || syscallno == Arch::read;\n}\n\ntemplate <typename Arch>\nstatic bool is_write_syscall_arch(int syscallno) {\n  return syscallno == Arch::writev || syscallno == Arch::write ||\n         syscallno == Arch::pwrite64 || syscallno == Arch::pwritev;\n}\n\nstatic bool is_implicit_offset_syscall(SupportedArch arch, int syscallno) {\n  RR_ARCH_FUNCTION(is_implicit_offset_syscall_arch, arch, syscallno);\n}\n\ntemplate <typename Arch>\nstatic int64_t retrieve_offset_arch(Task* t, int syscallno,\n                                    const Registers& regs) {\n  switch (syscallno) {\n    case Arch::pwrite64:\n    case Arch::pwritev:\n    case Arch::pread64:\n    case Arch::preadv: {\n      if (sizeof(typename Arch::unsigned_word) == 4) {\n        return regs.arg4() | (uint64_t(regs.arg5_signed()) << 32);\n      }\n      return regs.arg4_signed();\n    }\n    case Arch::readv:\n    case Arch::read:\n    case Arch::writev:\n    case Arch::write: {\n      ASSERT(t, t->session().is_recording())\n          << \"Can only read a file descriptor's offset while recording\";\n      int fd = regs.orig_arg1_signed();\n      int64_t offset = t->fd_offset(fd);\n      return is_write_syscall_arch<Arch>(syscallno) ?\n        // The pos we just read, was after the write completed. Luckily, we do\n        // know how many bytes were written.\n        offset - regs.syscall_result() :\n        offset;\n    }\n    default: {\n      ASSERT(t, false) << \"Can not retrieve offset for this system call.\";\n      return -1;\n    }\n  }\n}\n\nstatic int64_t retrieve_offset(Task* t, int syscallno, const Registers& regs) {\n  RR_ARCH_FUNCTION(retrieve_offset_arch, t->arch(), t, syscallno, regs);\n}\n\nint64_t FileMonitor::LazyOffset::retrieve(bool needed_for_replay) {\n  bool is_replay = t->session().is_replaying();\n  bool is_implicit_offset = is_implicit_offset_syscall(t->arch(), syscallno);\n  ASSERT(t, needed_for_replay || !is_replay);\n  // There is no way we can figure out this information now, so retrieve it\n  // from the trace (we record it below under the same circumstance).\n  if (is_replay && is_implicit_offset) {\n    return static_cast<ReplayTask*>(t)\n        ->current_trace_frame()\n        .event()\n        .Syscall()\n        .write_offset;\n  }\n  int64_t offset = retrieve_offset(t, syscallno, regs);\n  if (needed_for_replay && is_implicit_offset) {\n    static_cast<RecordTask*>(t)->ev().Syscall().write_offset = offset;\n  }\n  return offset;\n}\n\n#define CASE(v) case FileMonitor::v: return #v\nstd::string file_monitor_type_name(FileMonitor::Type t) {\n  switch (t) {\n    CASE(Base);\n    CASE(MagicSaveData);\n    CASE(Mmapped);\n    CASE(Preserve);\n    CASE(ProcFd);\n    CASE(ProcMem);\n    CASE(Stdio);\n    CASE(VirtualPerfCounter);\n    CASE(NonvirtualPerfCounter);\n    CASE(SysCpu);\n    CASE(ProcStat);\n    CASE(RRPage);\n    CASE(ODirect);\n    CASE(BpfMap);\n    CASE(PidFd);\n    default:\n      FATAL() << \"Unknown type \" << (int)t;\n      return \"\";\n  }\n}\n\n}\n"
  },
  {
    "path": "src/FileMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_FILE_MONITOR_H_\n#define RR_FILE_MONITOR_H_\n\nclass Task;\n\n#include <stdint.h>\n#include <stdlib.h>\n\n#include <memory>\n#include <vector>\n\n#include \"preload/preload_interface.h\"\n#include \"util.h\"\n\nnamespace rr {\n\nclass RecordTask;\nclass Registers;\n\nclass FileMonitor {\npublic:\n  typedef std::shared_ptr<FileMonitor> shr_ptr;\n\n  virtual ~FileMonitor() {}\n\n  enum Type {\n    Base,\n    MagicSaveData,\n    Mmapped,\n    Preserve,\n    ProcFd,\n    ProcMem,\n    Stdio,\n    VirtualPerfCounter,\n    NonvirtualPerfCounter,\n    SysCpu,\n    ProcStat,\n    RRPage,\n    ODirect,\n    BpfMap,\n    PidFd,\n  };\n\n  virtual Type type() { return Base; }\n\n  /**\n   * Overriding this to return true will cause close() (and related fd-smashing\n   * operations such as dup2) to return EBADF, and hide it from the tracee's\n   * /proc/pid/fd/\n   */\n  virtual bool is_rr_fd() { return false; }\n\n  /**\n   * Notification that task |t| is about to write |data| bytes of length\n   * |length| to the file.\n   * In general writes can block, and concurrent blocking writes to the same\n   * file may race so that the kernel performs writes out of order\n   * with respect to will_write notifications.\n   * If it is known that the write cannot block (or that blocking all of rr\n   * on it is OK), this notification can return PREVENT_SWITCH to make the\n   * write a blocking write. This ensures that writes are performed in the order\n   * of will_write notifications.\n   */\n  virtual Switchable will_write(Task*) { return ALLOW_SWITCH; }\n  /**\n   * Notification that task |t| wrote to the file descriptor.\n   * Due to races, if will_write did not return PREVENT_SWITCH, it's possible\n   * that the data in the buffers is not what was actually written.\n   */\n  struct Range {\n    remote_ptr<void> data;\n    size_t length;\n    Range(remote_ptr<void> data, size_t length) : data(data), length(length) {}\n  };\n\n  /**\n   * Encapsulates the offset at which to read or write. Computing this may be\n   * an expensive operation if the offset is implicit (i.e. is taken from the\n   * file descriptor), so we only do it if we actually need to look at the\n   * offset.\n   */\n  class LazyOffset {\n  public:\n    LazyOffset(Task* t, const Registers& regs, int64_t syscallno)\n        : t(t), regs(regs), syscallno(syscallno) {}\n    int64_t retrieve(bool needed_for_replay);\n\n  private:\n    Task* t;\n    const Registers& regs;\n    int64_t syscallno;\n  };\n\n  virtual void did_write(Task*, const std::vector<Range>&, LazyOffset&) {}\n\n  /**\n   * Return true if the ioctl should be fully emulated. If so the result\n   * is stored in the last parameter.\n   * Only called during recording.\n   */\n  virtual bool emulate_ioctl(RecordTask*, uint64_t*) { return false; }\n\n  /**\n   * Return true if the fcntl should be fully emulated. If so the\n   * result is stored in the last parameter.\n   * Only called during recording.\n   */\n  virtual bool emulate_fcntl(RecordTask*, uint64_t*) { return false; }\n\n  /**\n   * Return true if the read should be fully emulated. If so the\n   * result is stored in the last parameter. The emulation should write to the\n   * task's memory ranges.\n   * Only called during recording.\n   */\n  virtual bool emulate_read(RecordTask*, const std::vector<Range>&, LazyOffset&,\n                            uint64_t*) {\n    return false;\n  }\n\n  /**\n   * Allows the FileMonitor to rewrite the output of a getdents/getdents64 call\n   * if desired.\n   */\n  virtual void filter_getdents(RecordTask*) {}\n\n  virtual enum syscallbuf_fd_classes get_syscallbuf_class() {\n    return FD_CLASS_TRACED;\n  }\n};\n\nstd::string file_monitor_type_name(FileMonitor::Type t);\n\n} // namespace rr\n\n#endif /* RR_FILE_MONITOR_H_ */\n"
  },
  {
    "path": "src/FileNameCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <unordered_set>\n\n#include \"AddressSpace.h\"\n#include \"Command.h\"\n#include \"TraceStream.h\"\n#include \"core.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass FileNameCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  FileNameCommand(const char* name, const char* help) : Command(name, help) {}\n  bool parse_file_name(vector<string>& args, string* out);\n\n  static FileNameCommand singleton;\n};\n\nFileNameCommand FileNameCommand::singleton(\n    \"filename\",\n    \" rr filename <trace_file_name>\\n\"\n    \"  Prints the original filename for a given trace file name.\\n\");\n\nstatic void print_original_file_name(const string& trace_dir,\n                                     const string& file_name, FILE* out) {\n  TraceReader trace(trace_dir);\n  unordered_set<string> original_files;\n  string full_file_name = trace.dir() + \"/\" + file_name;\n  while (true) {\n    TraceReader::MappedData data;\n    bool found;\n    KernelMapping km = trace.read_mapped_region(\n        &data, &found, TraceReader::VALIDATE, TraceReader::ANY_TIME);\n    if (!found) {\n      break;\n    }\n    if (data.source == TraceReader::SOURCE_FILE &&\n        data.file_name == full_file_name && !km.fsname().empty() &&\n        original_files.find(km.fsname()) == original_files.end()) {\n      fprintf(out, \"%s\\n\", km.fsname().c_str());\n      original_files.insert(km.fsname());\n    }\n  }\n}\n\nbool FileNameCommand::parse_file_name(vector<string>& args, string* out) {\n  if (args.empty() || !verify_not_option(args)) {\n    return false;\n  }\n  *out = args[0];\n  args.erase(args.begin());\n  return true;\n}\n\nint FileNameCommand::run(vector<string>& args) {\n  string file_name;\n  if (!parse_file_name(args, &file_name) || !args.empty()) {\n    print_help(stderr);\n    return 1;\n  }\n\n  string trace_dir;\n  size_t last_slash = file_name.rfind('/');\n  if (last_slash == string::npos) {\n    trace_dir = \".\";\n  } else {\n    trace_dir = file_name.substr(0, last_slash);\n    file_name = file_name.substr(last_slash + 1);\n  }\n  print_original_file_name(trace_dir, file_name, stdout);\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Flags.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Flags.h\"\n\nnamespace rr {\n\nFlags& Flags::get_for_init() { return singleton; }\n\nFlags Flags::singleton;\n\n} // namespace rr\n"
  },
  {
    "path": "src/Flags.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_FLAGS_H_\n#define RR_FLAGS_H_\n\n#include <stdint.h>\n#include <unistd.h>\n\n#include <string>\n\n#include \"Ticks.h\"\n#include \"TraceFrame.h\"\n\nnamespace rr {\n\n/**\n * Command line arguments for rr\n */\nstruct Flags {\n  enum { CHECKSUM_NONE = -3, CHECKSUM_SYSCALL = -2, CHECKSUM_ALL = -1 };\n  /* When to generate or check memory checksums. One of CHECKSUM_NONE,\n   * CHECKSUM_SYSCALL or CHECKSUM_ALL, or a positive integer representing the\n   * event time at which to start checksumming.\n   */\n  FrameTime checksum;\n\n  enum {\n    DUMP_ON_ALL = 10000,\n    DUMP_ON_RDTSC = 10001,\n    DUMP_ON_NONE = -DUMP_ON_ALL\n  };\n  int dump_on;\n\n  enum { DUMP_AT_NONE = -1 };\n  /* time at which to create memory dump */\n  FrameTime dump_at; // global time\n\n  // Force rr to do some things that it otherwise wouldn't, for\n  // example launching an emergency debugger when the output\n  // doesn't seem to be a tty.\n  bool force_things;\n\n  // Force rr to assume that the terminal is non-interactive, disabling e.g.\n  // the interactive emergency debugger. If used with --force-things, this\n  // option prevails.\n  bool non_interactive;\n\n  /* Mark the trace global time along with tracee writes to\n   * stdio. */\n  bool mark_stdio;\n\n  // Check that cached mmaps match /proc/maps after each event.\n  bool check_cached_mmaps;\n\n  // Suppress warnings related to environmental features outside rr's\n  // control.\n  bool suppress_environment_warnings;\n\n  // Any warning or error that would be printed is treated as fatal\n  bool fatal_errors_and_warnings;\n\n  // Pretend CPUID faulting support doesn't exist\n  bool disable_cpuid_faulting;\n\n  // Don't listen for PTRACE_EVENT_EXIT events, to test how rr handles\n  // missing PTRACE_EVENT_EXITs.\n  bool disable_ptrace_exit_events;\n\n  // User override for architecture detection, e.g. when running\n  // under valgrind.\n  std::string forced_uarch;\n\n  // User override for the path to page files and other resources.\n  std::string resource_path;\n\n  Flags()\n      : checksum(CHECKSUM_NONE),\n        dump_on(DUMP_ON_NONE),\n        dump_at(DUMP_AT_NONE),\n        force_things(false),\n        mark_stdio(false),\n        check_cached_mmaps(false),\n        suppress_environment_warnings(false),\n        fatal_errors_and_warnings(false),\n        disable_cpuid_faulting(false),\n        disable_ptrace_exit_events(false) {}\n\n  static const Flags& get() { return singleton; }\n\n  /**\n   * Get a reference that can be used to initialize the global Flags.\n   */\n  static Flags& get_for_init();\n\nprivate:\n  static Flags singleton;\n};\n\n} // namespace rr\n\n#endif /* RR_FLAGS_H_ */\n"
  },
  {
    "path": "src/GdbInitCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Command.h\"\n#include \"GdbServer.h\"\n#include \"launch_debugger.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass GdbInitCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  GdbInitCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static GdbInitCommand singleton;\n};\n\nGdbInitCommand GdbInitCommand::singleton(\"gdbinit\", \" rr gdbinit\\n\");\n\nint GdbInitCommand::run(vector<string>& args) {\n  while (parse_global_option(args)) {\n  }\n\n  fputs(gdb_init_script().c_str(), stdout);\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/GdbServer.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"GdbServer.h\"\n\n#include <elf.h>\n#include <limits.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/sysmacros.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <algorithm>\n#include <limits>\n#include <map>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"BreakpointCondition.h\"\n#include \"ElfReader.h\"\n#include \"Event.h\"\n#include \"DebuggerExtensionCommandHandler.h\"\n#include \"GdbServerExpression.h\"\n#include \"GdbServerRegister.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"ScopedFd.h\"\n#include \"StringVectorToCharArray.h\"\n#include \"Task.h\"\n#include \"ThreadGroup.h\"\n#include \"TraceField.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"launch_debugger.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n/**\n * The \"outermost\" saved register state is associated with the diversion.\n * \"Restoring\" it exits the diversion and restores all state of the tracee.\n */\nconst int DIVERSION_SAVED_REGISTER_STATE = 1;\n\n/**\n * If non-empty, the trace fields to print when singlestepping a diversion\n * session. Only intended for debugging rr itself.\n */\nconst string DIVERSION_SINGLESTEP_PRINT = \"\";\n\nGdbServer::ConnectionFlags::ConnectionFlags()\n  : dbg_port(-1),\n    keep_listening(false),\n    serve_files(false),\n    debugger_params_write_pipe(nullptr) {}\n\nstatic ExtendedTaskId extended_task_id(Task* t) {\n  return ExtendedTaskId(t->thread_group()->tguid(), t->tuid());\n}\n\nGdbServer::GdbServer(std::unique_ptr<GdbServerConnection>& connection,\n                     Task* t, ReplayTimeline* timeline,\n                     const Target& target)\n    : dbg(std::move(connection)),\n      debuggee_tguid(t->thread_group()->tguid()),\n      target(target),\n      last_continue_task(extended_task_id(t)),\n      last_query_task(extended_task_id(t)),\n      final_event(UINT32_MAX),\n      in_debuggee_end_state(false),\n      failed_restart(false),\n      stop_replaying_to_target(nullptr),\n      interrupt_pending(false),\n      exit_sigkill_pending(false),\n      timeline_(timeline),\n      emergency_debug_session(timeline ? nullptr : &t->session()),\n      file_scope_pid(0) {\n  memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n}\n\n/**\n * Attempt to find the value of |regname| (a DebuggerRegister\n * name), and if so (i) write it to |buf|; (ii)\n * set |*defined = true|; (iii) return the size of written\n * data.  If |*defined == false|, the value of |buf| is\n * meaningless.\n *\n * This helper can fetch the values of both general-purpose\n * and \"extra\" registers.\n *\n * NB: |buf| must be large enough to hold the largest register\n * value that can be named by |regname|.\n */\nstatic size_t get_reg(const Registers& regs, const ExtraRegisters& extra_regs,\n                      uint8_t* buf, GdbServerRegister regname, bool* defined) {\n  size_t num_bytes = regs.read_register(buf, regname, defined);\n  if (!*defined) {\n    num_bytes = extra_regs.read_register(buf, regname, defined);\n  }\n  return num_bytes;\n}\n\nstatic bool set_reg(Task* target, const GdbServerRegisterValue& reg) {\n  if (!reg.defined) {\n    return false;\n  }\n\n  Registers regs = target->regs();\n  if (regs.write_register(reg.name, reg.value, reg.size)) {\n    target->set_regs(regs);\n    return true;\n  }\n\n  auto extra_regs_p = target->extra_regs_fallible();\n  ASSERT(target, extra_regs_p) << \"Task died\";\n  ExtraRegisters extra_regs = *extra_regs_p;\n  if (extra_regs.write_register(reg.name, reg.value, reg.size)) {\n    target->set_extra_regs(extra_regs);\n    return true;\n  }\n\n  LOG(warn) << \"Unhandled register name \" << reg.name;\n  return false;\n}\n\n/**\n * Return the register |which|, which may not have a defined value.\n */\nGdbServerRegisterValue GdbServer::get_reg(const Registers& regs,\n                                    const ExtraRegisters& extra_regs,\n                                    GdbServerRegister which) {\n  GdbServerRegisterValue reg;\n  memset(&reg, 0, sizeof(reg));\n  reg.name = which;\n  reg.size = rr::get_reg(regs, extra_regs, &reg.value[0], which, &reg.defined);\n  return reg;\n}\n\nstatic bool matches_threadid(const ExtendedTaskId& tid,\n                             const GdbThreadId& target) {\n  return (target.pid <= 0 || target.pid == tid.tguid.tid()) &&\n         (target.tid <= 0 || target.tid == tid.tuid.tid());\n}\n\nstatic bool matches_threadid(Task* t, const GdbThreadId& target) {\n  return matches_threadid(extended_task_id(t), target);\n}\n\nstatic WatchType watchpoint_type(GdbRequestType req) {\n  switch (req) {\n    case DREQ_SET_HW_BREAK:\n    case DREQ_REMOVE_HW_BREAK:\n      return WATCH_EXEC;\n    case DREQ_SET_WR_WATCH:\n    case DREQ_REMOVE_WR_WATCH:\n      return WATCH_WRITE;\n    case DREQ_REMOVE_RDWR_WATCH:\n    case DREQ_SET_RDWR_WATCH:\n    // NB: x86 doesn't support read-only watchpoints (who would\n    // ever want to use one?) so we treat them as readwrite\n    // watchpoints and hope that gdb can figure out what's going\n    // on.  That is, if a user ever tries to set a read\n    // watchpoint.\n    case DREQ_REMOVE_RD_WATCH:\n    case DREQ_SET_RD_WATCH:\n      return WATCH_READWRITE;\n    default:\n      FATAL() << \"Unknown dbg request \" << req;\n      return WatchType(-1); // not reached\n  }\n}\n\nstatic void maybe_singlestep_for_event(Task* t, GdbRequest* req) {\n  ReplayTask* rt = t->as_replay();\n  if (!rt) {\n    return;\n  }\n  if (trace_instructions_up_to_event(\n          rt->session().current_trace_frame().time())) {\n    fputs(\"Stepping: \", stderr);\n    t->regs().print_register_file_compact(stderr);\n    fprintf(stderr, \" ticks:%\" PRId64 \"\\n\", t->tick_count());\n    *req = GdbRequest(DREQ_CONT);\n    req->suppress_debugger_stop = true;\n    req->cont().actions.push_back(\n        GdbContAction(ACTION_STEP,\n          extended_task_id(t).to_debugger_thread_id()));\n  }\n}\n\nvoid GdbServer::dispatch_regs_request(const Registers& regs,\n                                      const ExtraRegisters& extra_regs) {\n  const auto& registers = target_registers(regs.arch());\n  vector<GdbServerRegisterValue> rs;\n  rs.reserve(registers.size());\n  for (const auto r : registers) {\n    rs.push_back(get_reg(regs, extra_regs, r));\n  }\n  dbg->reply_get_regs(rs);\n}\n\nclass GdbBreakpointCondition : public BreakpointCondition {\npublic:\n  GdbBreakpointCondition(const vector<vector<uint8_t>>& bytecodes) {\n    for (auto& b : bytecodes) {\n      expressions.push_back(GdbServerExpression(b.data(), b.size()));\n    }\n  }\n  virtual bool evaluate(ReplayTask* t) const override {\n    for (auto& e : expressions) {\n      GdbServerExpression::Value v;\n      // Break if evaluation fails or the result is nonzero\n      if (!e.evaluate(t, &v) || v.i != 0) {\n        return true;\n      }\n    }\n    return false;\n  }\n\nprivate:\n  vector<GdbServerExpression> expressions;\n};\n\nstatic unique_ptr<BreakpointCondition> breakpoint_condition(\n    const GdbRequest& request) {\n  if (request.watch().conditions.empty()) {\n    return nullptr;\n  }\n  return unique_ptr<BreakpointCondition>(\n      new GdbBreakpointCondition(request.watch().conditions));\n}\n\nstatic bool search_memory(Task* t, const MemoryRange& where,\n                          const vector<uint8_t>& find,\n                          remote_ptr<void>* result) {\n  vector<uint8_t> buf;\n  buf.resize(page_size() + find.size() - 1);\n  for (const auto& m : t->vm()->maps()) {\n    MemoryRange r = MemoryRange(m.map.start(), m.map.end() + find.size() - 1)\n                        .intersect(where);\n    // We basically read page by page here, but we read past the end of the\n    // page to handle the case where a found string crosses page boundaries.\n    // This approach isn't great for handling long search strings but gdb's find\n    // command isn't really suited to that.\n    // Reading page by page lets us avoid problems where some pages in a\n    // mapping aren't readable (e.g. reading beyond end of file).\n    while (r.size() >= find.size()) {\n      ssize_t nread = t->read_bytes_fallible(\n          r.start(), std::min(buf.size(), r.size()), buf.data());\n      if (nread >= ssize_t(find.size())) {\n        void* found = memmem(buf.data(), nread, find.data(), find.size());\n        if (found) {\n          *result = r.start() + (static_cast<uint8_t*>(found) - buf.data());\n          return true;\n        }\n      }\n      r = MemoryRange(\n          std::min(r.end(), floor_page_size(r.start()) + page_size()), r.end());\n    }\n  }\n  return false;\n}\n\nstatic bool is_in_patch_stubs(Task* t, remote_code_ptr ip) {\n  auto p = ip.to_data_ptr<void>();\n  return t->vm()->has_mapping(p) &&\n         (t->vm()->mapping_flags_of(p) & AddressSpace::Mapping::IS_PATCH_STUBS);\n}\n\nvoid GdbServer::maybe_intercept_mem_request(Task* target, const GdbRequest& req,\n                                            vector<uint8_t>* result) {\n  DEBUG_ASSERT(req.mem_.len >= result->size());\n  /* Crazy hack!\n   * When gdb tries to read the word at the top of the stack, and we're in our\n   * dynamically-generated stub code, tell it the value is zero, so that gdb's\n   * stack-walking code doesn't find a bogus value that it treats as a return\n   * address and sets a breakpoint there, potentially corrupting program data.\n   * gdb sometimes reads a whole block of memory around the stack pointer so\n   * handle cases where the top-of-stack word is contained in a larger range.\n   */\n  size_t size = word_size(target->arch());\n  if (target->regs().sp().as_int() >= req.mem_.addr &&\n      target->regs().sp().as_int() + size <= req.mem_.addr + result->size() &&\n      is_in_patch_stubs(target, target->ip())) {\n    memset(result->data() + target->regs().sp().as_int() - req.mem_.addr, 0,\n           size);\n  }\n}\n\nstatic vector<GdbServerConnection::ThreadInfo> thread_info(const Session& session) {\n  vector<GdbServerConnection::ThreadInfo> threads;\n  for (auto& kv : session.tasks()) {\n    threads.push_back({\n      extended_task_id(kv.second),\n      kv.second->regs().ip().register_value()\n    });\n  }\n  return threads;\n}\n\nvoid GdbServer::notify_stop_internal(const Session& session,\n                                     ExtendedTaskId which, int sig,\n                                     const string& reason) {\n  dbg->notify_stop(which, sig, thread_info(session), reason);\n}\n\nvoid GdbServer::dispatch_debugger_request(Session& session,\n                                          const GdbRequest& req,\n                                          ReportState state) {\n  DEBUG_ASSERT(!req.is_resume_request());\n\n  // These requests don't require a target task.\n  switch (req.type) {\n    case DREQ_RESTART:\n      DEBUG_ASSERT(false);\n      return; // unreached\n    case DREQ_GET_CURRENT_THREAD:\n      dbg->reply_get_current_thread(last_continue_task);\n      return;\n    case DREQ_GET_OFFSETS:\n      /* TODO */\n      dbg->reply_get_offsets();\n      return;\n    case DREQ_GET_THREAD_LIST: {\n      vector<ExtendedTaskId> tids;\n      if (state != REPORT_THREADS_DEAD && !failed_restart) {\n        for (auto& kv : session.tasks()) {\n          tids.push_back(extended_task_id(kv.second));\n        }\n      }\n      dbg->reply_get_thread_list(tids);\n      return;\n    }\n    case DREQ_INTERRUPT:\n      notify_stop_internal(session, last_continue_task, 0);\n      memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n      last_query_task = last_continue_task;\n      return;\n    case DREQ_GET_EXEC_FILE: {\n      // We shouldn't normally receive this since we try to pass the exe file\n      // name on gdb's command line, but the user might start gdb manually\n      // and this is easy to support in case some other debugger or\n      // configuration needs it.\n      Task* t = nullptr;\n      if (req.target.tid) {\n        ThreadGroup* tg = session.find_thread_group(req.target.tid);\n        if (tg) {\n          t = *tg->task_set().begin();\n        }\n      } else {\n        t = session.find_task(last_continue_task.tuid);\n      }\n      if (t) {\n        dbg->reply_get_exec_file(t->vm()->exe_image());\n      } else {\n        dbg->reply_get_exec_file(string());\n      }\n      return;\n    }\n    case DREQ_FILE_SETFS:\n      // Only the filesystem as seen by the remote stub is supported currently\n      file_scope_pid = req.file_setfs().pid;\n      dbg->reply_setfs(0);\n      return;\n    case DREQ_FILE_OPEN:\n      // We only support reading files\n      if (req.file_open().flags == O_RDONLY) {\n        Task* t = session.find_task(last_continue_task.tuid);\n        int fd = open_file(session, t, req.file_open().file_name);\n        dbg->reply_open(fd, fd >= 0 ? 0 : ENOENT);\n      } else {\n        dbg->reply_open(-1, EACCES);\n      }\n      return;\n    case DREQ_FILE_PREAD: {\n      GdbRequest::FilePread read_req = req.file_pread();\n      {\n        auto it = files.find(read_req.fd);\n        if (it != files.end()) {\n          size_t size = min<uint64_t>(read_req.size, 1024 * 1024);\n          vector<uint8_t> data;\n          data.resize(size);\n          ssize_t bytes =\n              read_to_end(it->second, read_req.offset, data.data(), size);\n          dbg->reply_pread(data.data(), bytes, bytes >= 0 ? 0 : -errno);\n          return;\n        }\n      }\n      {\n        auto it = memory_files.find(read_req.fd);\n        if (it != memory_files.end() && timeline_) {\n          // Search our mmap stream for a record that can satisfy this request\n          TraceReader tmp_reader(timeline_->current_session().trace_reader());\n          tmp_reader.rewind();\n          while (true) {\n            TraceReader::MappedData data;\n            bool found;\n            KernelMapping km = tmp_reader.read_mapped_region(\n                &data, &found, TraceReader::DONT_VALIDATE, TraceReader::ANY_TIME);\n            if (!found)\n              break;\n            if (it->second == FileId(km)) {\n              if (data.source != TraceReader::SOURCE_FILE) {\n                LOG(warn) << \"Not serving file because it is not a file source\";\n                break;\n              }\n              ScopedFd fd(data.file_name.c_str(), O_RDONLY);\n              vector<uint8_t> data;\n              data.resize(read_req.size);\n              LOG(debug) << \"Reading \" << read_req.size << \" bytes at offset \" <<\n                read_req.offset;\n              ssize_t bytes =\n                  read_to_end(fd, read_req.offset, data.data(), read_req.size);\n              if (bytes < (ssize_t)read_req.size) {\n                LOG(warn) << \"Requested \" << read_req.size << \" bytes but only got \" << bytes;\n              }\n              dbg->reply_pread(data.data(), bytes, bytes >= 0 ? 0 : -errno);\n              return;\n            }\n          }\n          LOG(warn) << \"No mapping found\";\n        }\n      }\n      LOG(warn) << \"Unknown file descriptor requested\";\n      dbg->reply_pread(nullptr, 0, EIO);\n      return;\n    }\n    case DREQ_FILE_CLOSE: {\n      {\n        auto it = files.find(req.file_close().fd);\n        if (it != files.end()) {\n          files.erase(it);\n          dbg->reply_close(0);\n          return;\n        }\n      } {\n        auto it = memory_files.find(req.file_close().fd);\n        if (it != memory_files.end()) {\n          memory_files.erase(it);\n          dbg->reply_close(0);\n          return;\n        }\n      }\n      LOG(warn) << \"Unable to find file descriptor for close\";\n      dbg->reply_close(EBADF);\n      return;\n    }\n    default:\n      /* fall through to next switch stmt */\n      break;\n  }\n\n  bool is_query = req.type != DREQ_SET_CONTINUE_THREAD;\n  Task* target =\n      req.target.tid > 0\n          ? session.find_task(req.target.tid)\n          : session.find_task(is_query ? last_query_task.tuid : last_continue_task.tuid);\n  if (target) {\n    if (is_query) {\n      last_query_task = extended_task_id(target);\n    } else {\n      last_continue_task = extended_task_id(target);\n    }\n  }\n  // These requests query or manipulate which task is the\n  // target, so it's OK if the task doesn't exist.\n  switch (req.type) {\n    case DREQ_GET_IS_THREAD_ALIVE:\n      dbg->reply_get_is_thread_alive(target != nullptr);\n      return;\n    case DREQ_GET_THREAD_EXTRA_INFO:\n      dbg->reply_get_thread_extra_info(target->name());\n      return;\n    case DREQ_SET_CONTINUE_THREAD:\n      dbg->reply_select_thread(target != nullptr);\n      return;\n    case DREQ_SET_QUERY_THREAD:\n      dbg->reply_select_thread(target != nullptr);\n      return;\n    default:\n      // fall through to next switch stmt\n      break;\n  }\n\n  // These requests require a valid target task.  We don't trust\n  // the debugger to use the information provided above to only\n  // query valid tasks.\n  if (!target) {\n    dbg->notify_no_such_thread(req);\n    return;\n  }\n  switch (req.type) {\n    case DREQ_GET_AUXV: {\n      dbg->reply_get_auxv(target->vm()->saved_auxv());\n      return;\n    }\n    case DREQ_GET_MEM:\n    case DREQ_GET_MEM_BINARY: {\n      vector<uint8_t> mem;\n      uintptr_t end = req.mem().addr + req.mem().len;\n      if (end < req.mem().addr) {\n        // Overflow\n        dbg->reply_get_mem(mem);\n        return;\n      }\n      mem.resize(req.mem().len);\n\n      if (!session.is_diversion() &&\n          read_debugger_mem(target->thread_group()->tguid(),\n              MemoryRange(req.mem().addr, req.mem().len), mem.data())) {\n      } else {\n        ssize_t nread = target->read_bytes_fallible(req.mem().addr, req.mem().len,\n                                                    mem.data());\n        mem.resize(max(ssize_t(0), nread));\n      }\n      target->vm()->replace_breakpoints_with_original_values(\n          mem.data(), mem.size(), req.mem().addr);\n      maybe_intercept_mem_request(target, req, &mem);\n      dbg->reply_get_mem(mem);\n      return;\n    }\n    case DREQ_SET_MEM:\n    case DREQ_SET_MEM_BINARY: {\n      // gdb has been observed to send requests of length 0 at\n      // odd times\n      // (e.g. before sending the magic write to create a checkpoint)\n      if (req.mem().len == 0) {\n        dbg->reply_set_mem(true);\n        return;\n      }\n      uintptr_t end = req.mem().addr + req.mem().len;\n      if (end < req.mem().addr) {\n        // Overflow\n        dbg->reply_set_mem(false);\n        return;\n      }\n      // If an address is recognised as belonging to a SystemTap semaphore it's\n      // because it was detected by the audit library during recording and\n      // pre-incremented.\n      if (target->vm()->is_stap_semaphore(req.mem().addr)) {\n        LOG(info) << \"Suppressing write to SystemTap semaphore\";\n        dbg->reply_set_mem(true);\n        return;\n      }\n      // We only allow the debugger to write memory if the\n      // memory will be written to an diversion session.\n      // Arbitrary writes to replay sessions cause\n      // divergence.\n      if (!session.is_diversion()) {\n        if (write_debugger_mem(target->thread_group()->tguid(),\n                MemoryRange(req.mem().addr, req.mem().len),\n                req.mem().data.data())) {\n          dbg->reply_set_mem(true);\n          return;\n        }\n\n        LOG(error) << \"Attempt to write memory outside diversion session\";\n        dbg->reply_set_mem(false);\n        return;\n      }\n      LOG(debug) << \"Writing \" << req.mem().len << \" bytes to \"\n                 << HEX(req.mem().addr);\n      // TODO fallible\n      target->write_bytes_helper(req.mem().addr, req.mem().len,\n                                 req.mem().data.data());\n      dbg->reply_set_mem(true);\n      return;\n    }\n    case DREQ_SEARCH_MEM_BINARY: {\n      remote_ptr<void> addr;\n      bool found =\n          search_memory(target, MemoryRange(req.mem().addr, req.mem().len),\n                        req.mem().data, &addr);\n      dbg->reply_search_mem_binary(found, addr);\n      return;\n    }\n    case DREQ_MEM_INFO: {\n      ASSERT(target, req.mem().len == 1);\n      MemoryRange range;\n      int prot;\n      if (debugger_mem_region(target->thread_group()->tguid(), req.mem().addr,\n          &prot, &range)) {\n        dbg->reply_mem_info(range, prot, \"\");\n        return;\n      }\n      if (target->vm()->has_mapping(req.mem().addr)) {\n        AddressSpace::Mapping m = target->vm()->mapping_of(req.mem().addr);\n        dbg->reply_mem_info(m.recorded_map, m.recorded_map.prot(),\n                            m.recorded_map.fsname());\n      } else {\n        AddressSpace::Maps maps = target->vm()->maps();\n        remote_ptr<void> last_end;\n        remote_ptr<void> next_start;\n        for (auto it : maps) {\n          if (it.recorded_map.start() > req.mem().addr) {\n            next_start = it.recorded_map.start();\n            break;\n          }\n          last_end = it.recorded_map.end();\n        }\n        if (next_start.is_null()) {\n          next_start = usable_address_space_end(target->arch());\n        }\n        dbg->reply_mem_info(MemoryRange(last_end, next_start), 0, string());\n      }\n      return;\n    }\n    case DREQ_MEM_ALLOC: {\n      remote_ptr<void> addr = allocate_debugger_mem(target->thread_group()->tguid(),\n          req.mem_alloc().size, req.mem_alloc().prot);\n      if (!addr.is_null() && session.is_diversion()) {\n        map_debugger_mem(*session.as_diversion(), target->thread_group()->tguid(),\n            addr);\n      }\n      dbg->reply_mem_alloc(addr);\n      return;\n    }\n    case DREQ_MEM_FREE: {\n      size_t size = free_debugger_mem(target->thread_group()->tguid(), req.mem_free().address);\n      if (size && session.is_diversion()) {\n        unmap_debugger_mem(*session.as_diversion(), target->thread_group()->tguid(),\n            req.mem_free().address, size);\n      }\n      dbg->reply_mem_free(size);\n      return;\n    }\n    case DREQ_GET_REG: {\n      GdbServerRegisterValue reg =\n          get_reg(target->regs(), *target->extra_regs_fallible(), req.reg().name);\n      dbg->reply_get_reg(reg);\n      return;\n    }\n    case DREQ_GET_REGS: {\n      dispatch_regs_request(target->regs(), *target->extra_regs_fallible());\n      return;\n    }\n    case DREQ_SET_REG: {\n      if (!session.is_diversion()) {\n        // gdb sets orig_eax to -1 during a restart. For a\n        // replay session this is not correct (we might be\n        // restarting from an rr checkpoint inside a system\n        // call, and we must not tamper with replay state), so\n        // just ignore it.\n        if ((target->arch() == x86 && req.reg().name == DREG_ORIG_EAX) ||\n            (target->arch() == x86_64 && req.reg().name == DREG_ORIG_RAX)) {\n          dbg->reply_set_reg(true);\n          return;\n        }\n        LOG(error) << \"Attempt to write register outside diversion session\";\n        dbg->reply_set_reg(false);\n        return;\n      }\n      if (!set_reg(target, req.reg())) {\n        LOG(warn) << \"Attempt to set register \" << req.reg().name << \" failed\";\n      }\n      dbg->reply_set_reg(true /*currently infallible*/);\n      return;\n    }\n    case DREQ_GET_STOP_REASON: {\n      dbg->reply_get_stop_reason(last_continue_task, stop_siginfo.si_signo,\n                                 thread_info(session));\n      return;\n    }\n    case DREQ_SET_SW_BREAK: {\n      ASSERT(target, req.watch().kind == bkpt_instruction_length(target->arch()))\n          << \"Debugger setting bad breakpoint insn\";\n      // Mirror all breakpoint/watchpoint sets/unsets to the target process\n      // if it's not part of the timeline (i.e. it's a diversion).\n      if (!timeline_) {\n        dbg->reply_watchpoint_request(false);\n        return;\n      }\n      ReplayTask* replay_task =\n          timeline_->current_session().find_task(target->tuid());\n      bool ok = timeline_->add_breakpoint(replay_task, req.watch().addr,\n                                        breakpoint_condition(req));\n      if (ok && &session != &timeline_->current_session()) {\n        bool diversion_ok =\n            target->vm()->add_breakpoint(req.watch().addr, BKPT_USER);\n        ASSERT(target, diversion_ok);\n      }\n      dbg->reply_watchpoint_request(ok);\n      return;\n    }\n    case DREQ_SET_HW_BREAK:\n    case DREQ_SET_RD_WATCH:\n    case DREQ_SET_WR_WATCH:\n    case DREQ_SET_RDWR_WATCH: {\n      if (!timeline_) {\n        dbg->reply_watchpoint_request(false);\n        return;\n      }\n      ReplayTask* replay_task =\n          timeline_->current_session().find_task(target->tuid());\n      bool ok = timeline_->add_watchpoint(\n          replay_task, req.watch().addr, req.watch().kind,\n          watchpoint_type(req.type), breakpoint_condition(req));\n      if (ok && &session != &timeline_->current_session()) {\n        bool diversion_ok = target->vm()->add_watchpoint(\n            req.watch().addr, req.watch().kind, watchpoint_type(req.type));\n        ASSERT(target, diversion_ok);\n      }\n      dbg->reply_watchpoint_request(ok);\n      return;\n    }\n    case DREQ_REMOVE_SW_BREAK: {\n      if (!timeline_) {\n        dbg->reply_watchpoint_request(true);\n        return;\n      }\n      ReplayTask* replay_task =\n          timeline_->current_session().find_task(target->tuid());\n      timeline_->remove_breakpoint(replay_task, req.watch().addr);\n      if (&session != &timeline_->current_session()) {\n        target->vm()->remove_breakpoint(req.watch().addr, BKPT_USER);\n      }\n      dbg->reply_watchpoint_request(true);\n      return;\n    }\n    case DREQ_REMOVE_HW_BREAK:\n    case DREQ_REMOVE_RD_WATCH:\n    case DREQ_REMOVE_WR_WATCH:\n    case DREQ_REMOVE_RDWR_WATCH: {\n      if (!timeline_) {\n        dbg->reply_watchpoint_request(true);\n        return;\n      }\n      ReplayTask* replay_task =\n          timeline_->current_session().find_task(target->tuid());\n      timeline_->remove_watchpoint(replay_task, req.watch().addr,\n                                   req.watch().kind, watchpoint_type(req.type));\n      if (&session != &timeline_->current_session()) {\n        target->vm()->remove_watchpoint(req.watch().addr, req.watch().kind,\n                                        watchpoint_type(req.type));\n      }\n      dbg->reply_watchpoint_request(true);\n      return;\n    }\n    case DREQ_READ_SIGINFO: {\n      vector<uint8_t> si_bytes;\n      si_bytes.resize(req.mem().len);\n      memset(si_bytes.data(), 0, si_bytes.size());\n      memcpy(si_bytes.data(), &stop_siginfo,\n             min(si_bytes.size(), sizeof(stop_siginfo)));\n      dbg->reply_read_siginfo(si_bytes);\n      return;\n    }\n    case DREQ_WRITE_SIGINFO:\n      LOG(warn) << \"WRITE_SIGINFO request outside of diversion session\";\n      dbg->reply_write_siginfo();\n      return;\n    case DREQ_SAVE_REGISTER_STATE: {\n      int state_index = DIVERSION_SAVED_REGISTER_STATE + 1;\n      while (saved_register_states.find(state_index) != saved_register_states.end()) {\n        ++state_index;\n      }\n      SavedRegisters& regs = saved_register_states[state_index];\n      regs.regs = target->regs();\n      regs.extra_regs = *target->extra_regs_fallible();\n      dbg->reply_save_register_state(true, state_index);\n      return;\n    }\n    case DREQ_RESTORE_REGISTER_STATE: {\n      if (!session.is_diversion()) {\n        LOG(error) << \"RESTORE_REGISTER_STATE request outside of diversion session\";\n        dbg->reply_restore_register_state(false);\n        return;\n      }\n      int state_index = req.restore_register_state().state_index;\n      auto it = saved_register_states.find(state_index);\n      if (it == saved_register_states.end()) {\n        LOG(error) << \"Unknown register state\";\n        dbg->reply_restore_register_state(false);\n        return;\n      }\n      target->set_regs(it->second.regs);\n      target->set_extra_regs(it->second.extra_regs);\n      saved_register_states.erase(it);\n      dbg->reply_restore_register_state(true);\n      return;\n    }\n    case DREQ_RR_CMD:\n      dbg->reply_rr_cmd(\n          DebuggerExtensionCommandHandler::process_command(*this, target, req.rr_cmd()));\n      return;\n#ifdef PROC_SERVICE_H\n    case DREQ_QSYMBOL: {\n      // When gdb sends \"qSymbol::\", it means that gdb is ready to\n      // respond to symbol requests.  This can be sent multiple times\n      // during the course of a session -- gdb sends it whenever\n      // something in the inferior has changed, making it possible\n      // that previous failed symbol lookups could now succeed.  In\n      // response to a qSymbol request from gdb, we either send back a\n      // qSymbol response, requesting the address of a symbol; or we\n      // send back OK.  We have to do this as an ordinary response and\n      // maintain our own state explicitly, as opposed to simply\n      // reading another packet from gdb, because when gdb looks up a\n      // symbol it might send other requests that must be served.  So,\n      // we keep a copy of the symbol names, and an iterator into this\n      // copy.  When gdb sends a plain \"qSymbol::\" packet, because gdb\n      // has detected some change in the inferior state that might\n      // enable more symbol lookups, we restart the iterator.\n      if (!thread_db) {\n        thread_db =\n            std::unique_ptr<ThreadDb>(new ThreadDb(debuggee_tguid.tid()));\n      }\n\n      const string& name = req.sym().name;\n      if (req.sym().has_address) {\n        // Got a response holding a previously-requested symbol's name\n        // and address.\n        thread_db->register_symbol(name, req.sym().address);\n      } else if (name == \"\") {\n        // Plain \"qSymbol::\" request.\n        symbols =\n            thread_db->get_symbols_and_clear_map(target->thread_group().get());\n        symbols_iter = symbols.begin();\n      }\n\n      if (symbols_iter == symbols.end()) {\n        dbg->qsymbols_finished();\n      } else {\n        string symbol = *symbols_iter++;\n        dbg->send_qsymbol(symbol);\n      }\n      return;\n    }\n    case DREQ_TLS: {\n      if (!thread_db) {\n        thread_db =\n            std::unique_ptr<ThreadDb>(new ThreadDb(debuggee_tguid.tid()));\n      }\n      remote_ptr<void> address;\n      bool ok = thread_db->get_tls_address(target->thread_group().get(),\n                                           target->rec_tid, req.tls().offset,\n                                           req.tls().load_module, &address);\n      dbg->reply_tls_addr(ok, address);\n      return;\n    }\n#endif\n    default:\n      FATAL() << \"Unknown debugger request \" << req.type;\n  }\n}\n\nstatic bool any_action_targets_match(const ExtendedTaskId& thread,\n                                     const vector<GdbContAction>& actions) {\n  return any_of(actions.begin(), actions.end(), [&thread](GdbContAction action) {\n    return matches_threadid(thread, action.target);\n  });\n}\n\nstatic Task* find_first_task_matching_target(\n    const Session& session, const vector<GdbContAction>& actions) {\n  const Session::TaskMap& tasks = session.tasks();\n  auto it = find_first_of(\n      tasks.begin(), tasks.end(),\n      actions.begin(), actions.end(),\n      [](Session::TaskMap::value_type task_pair, GdbContAction action) {\n        return matches_threadid(task_pair.second, action.target);\n      });\n  return it != tasks.end() ? it->second : nullptr;\n}\n\nbool GdbServer::diverter_process_debugger_requests(\n    DiversionSession& diversion_session, uint32_t& diversion_refcount,\n    GdbRequest* req) {\n  while (true) {\n    *req = dbg->get_request();\n\n    if (req->is_resume_request()) {\n      const vector<GdbContAction>& actions = req->cont().actions;\n      DEBUG_ASSERT(actions.size() > 0);\n      // GDB may ask us to resume more than one task, so we have to\n      // choose one. We give priority to the task last resumed, as\n      // this is likely to be the context in which GDB is executing\n      // code; selecting any other task runs the risk of resuming\n      // replay, denying the diverted code an opportunity to complete\n      // and end the diversion session.\n      if (!any_action_targets_match(last_continue_task, actions)) {\n        // If none of the resumption targets match the task last\n        // resumed, we simply choose any matching task. This ensures\n        // that GDB (and the user) can choose an arbitrary thread to\n        // serve as the context of the code being evaluated.\n        // TODO: maybe it makes sense to try and select the matching\n        // task that was most recently resumed, or possibly the\n        // matching task with an event in the replay trace nearest to\n        // 'now'.\n        Task* task =\n            find_first_task_matching_target(diversion_session, actions);\n        DEBUG_ASSERT(task != nullptr);\n        last_continue_task = extended_task_id(task);\n      }\n      return diversion_refcount > 0;\n    }\n\n    switch (req->type) {\n      case DREQ_RESTART:\n      case DREQ_DETACH:\n        diversion_refcount = 0;\n        return false;\n\n      case DREQ_READ_SIGINFO: {\n        LOG(debug) << \"Adding ref to diversion session\";\n        ++diversion_refcount;\n        // TODO: maybe share with replayer.cc?\n        vector<uint8_t> si_bytes;\n        si_bytes.resize(req->mem().len);\n        memset(si_bytes.data(), 0, si_bytes.size());\n        dbg->reply_read_siginfo(si_bytes);\n        continue;\n      }\n\n      case DREQ_RESTORE_REGISTER_STATE: {\n        int state_index = req->restore_register_state().state_index;\n        if (state_index == DIVERSION_SAVED_REGISTER_STATE) {\n          diversion_refcount = 0;\n          dbg->reply_restore_register_state(true);\n          // This request does not need to be retried outside the diversion\n          *req = GdbRequest(DREQ_NONE);\n          return false;\n        }\n        break;\n      }\n\n      case DREQ_SET_QUERY_THREAD: {\n        if (req->target.tid) {\n          Task* next = diversion_session.find_task(req->target.tid);\n          if (next) {\n            last_query_task = extended_task_id(next);\n          }\n        }\n        break;\n      }\n\n      case DREQ_WRITE_SIGINFO:\n        LOG(debug) << \"Removing reference to diversion session ...\";\n        DEBUG_ASSERT(diversion_refcount > 0);\n        --diversion_refcount;\n        if (diversion_refcount == 0) {\n          LOG(debug) << \"  ... dying at next continue request\";\n        }\n        dbg->reply_write_siginfo();\n        continue;\n\n      case DREQ_RR_CMD: {\n        DEBUG_ASSERT(req->type == DREQ_RR_CMD);\n        Task* task = diversion_session.find_task(last_continue_task.tuid);\n        if (task) {\n          std::string reply =\n              DebuggerExtensionCommandHandler::process_command(*this, task, req->rr_cmd());\n          // Certain commands cause the diversion to end immediately\n          // while other commands must work within a diversion.\n          if (reply == DebuggerExtensionCommandHandler::cmd_end_diversion()) {\n            diversion_refcount = 0;\n            return false;\n          }\n          dbg->reply_rr_cmd(reply);\n          continue;\n        } else {\n          diversion_refcount = 0;\n          return false;\n        }\n        break;\n      }\n\n      default:\n        break;\n    }\n    dispatch_debugger_request(diversion_session, *req, REPORT_NORMAL);\n  }\n}\n\nstatic bool is_last_thread_exit(const BreakStatus& break_status) {\n  // The task set may be empty if the task has already exited.\n  return break_status.task_exit &&\n         break_status.task_context.thread_group->task_set().size() <= 1;\n}\n\nstatic Task* is_in_exec(ReplayTimeline* timeline) {\n  if (!timeline) {\n    return nullptr;\n  }\n  Task* t = timeline->current_session().current_task();\n  if (!t) {\n    return nullptr;\n  }\n  return timeline->current_session().next_step_is_successful_exec_syscall_exit()\n             ? t\n             : nullptr;\n}\n\nvoid GdbServer::maybe_notify_stop(const Session& session,\n                                  const GdbRequest& req,\n                                  const BreakStatus& break_status) {\n  bool do_stop = false;\n  stringstream reason;\n  if (!break_status.watchpoints_hit.empty()) {\n    do_stop = true;\n    memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n    stop_siginfo.si_signo = SIGTRAP;\n    remote_ptr<void> watch_addr = break_status.watchpoints_hit[0].addr;\n    bool any_hw_break = false;\n    for (const auto& w : break_status.watchpoints_hit) {\n      if (w.type == WATCH_EXEC) {\n        any_hw_break = true;\n      }\n    }\n    if (dbg->hwbreak_supported() && any_hw_break) {\n      reason << \"hwbreak:;\";\n    } else if (watch_addr) {\n      reason << \"watch:\" << std::hex << watch_addr.as_int() << \";\";\n    }\n    LOG(debug) << \"Stopping for watchpoint at \" << watch_addr;\n  }\n  if (break_status.breakpoint_hit || break_status.singlestep_complete) {\n    do_stop = true;\n    memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n    stop_siginfo.si_signo = SIGTRAP;\n    if (break_status.breakpoint_hit) {\n      if (dbg->swbreak_supported()) {\n        reason << \"swbreak:;\";\n      }\n      LOG(debug) << \"Stopping for breakpoint\";\n    } else {\n      LOG(debug) << \"Stopping for singlestep\";\n    }\n  }\n  if (break_status.signal) {\n    do_stop = true;\n    stop_siginfo = *break_status.signal;\n    LOG(debug) << \"Stopping for signal \" << stop_siginfo;\n  }\n  if (is_last_thread_exit(break_status)) {\n    if (break_status.task_context.session->is_diversion()) {\n      // If the last task of a diversion session has exited, we need\n      // to make sure GDB knows it's unrecoverable. There's no good\n      // way to do this: a stop is insufficient, but an inferior exit\n      // typically signals the end of a debugging session. Using the\n      // latter approach appears to work, but stepping through GDB's\n      // processing of the event seems to indicate it isn't really\n      // supposed to. FIXME.\n      LOG(debug) << \"Last task of diversion exiting. \"\n                 << \"Notifying exit with synthetic SIGKILL\";\n      dbg->notify_exit_signal(SIGKILL);\n      return;\n    } else if (dbg->features().reverse_execution) {\n      do_stop = true;\n      memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n      if (req.cont().run_direction == RUN_FORWARD) {\n        // The exit of the last task in a thread group generates a fake SIGKILL,\n        // when reverse-execution is enabled, because users often want to run\n        // backwards from the end of the task.\n        stop_siginfo.si_signo = SIGKILL;\n        LOG(debug) << \"Stopping for synthetic SIGKILL\";\n      } else {\n        // The start of the debuggee task-group should trigger a silent stop.\n        stop_siginfo.si_signo = 0;\n        // Documented as \"has reached the end (or the beginning when executing\n        // backward) of the log\"\n        reason << \"replaylog:begin;\";\n        LOG(debug) << \"Stopping at start of execution while running backwards\";\n      }\n    }\n  }\n  Task* t = break_status.task();\n  Task* in_exec_task = is_in_exec(timeline_);\n  if (in_exec_task) {\n    do_stop = true;\n    memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n    t = in_exec_task;\n    LOG(debug) << \"Stopping at exec\";\n  }\n  if (do_stop && t->thread_group()->tguid() == debuggee_tguid) {\n    /* Notify the debugger and process any new requests\n     * that might have triggered before resuming. */\n    notify_stop_internal(session, extended_task_id(t), stop_siginfo.si_signo,\n                         reason.str());\n    last_query_task = last_continue_task = extended_task_id(t);\n  }\n}\n\nstatic RunCommand compute_run_command_from_actions(Task* t,\n                                                   const GdbRequest& req,\n                                                   int* signal_to_deliver) {\n  for (auto& action : req.cont().actions) {\n    if (matches_threadid(t, action.target)) {\n      // We can only run task |t|; neither diversion nor replay sessions\n      // support running multiple threads. So even if gdb tells us to continue\n      // multiple threads, we don't do that.\n      *signal_to_deliver = action.signal_to_deliver;\n      return action.type == ACTION_STEP ? RUN_SINGLESTEP : RUN_CONTINUE;\n    }\n  }\n  // gdb told us to run (or step) some thread that's not |t|, without resuming\n  // |t|. It sometimes does this even though its target thread is entering a\n  // blocking syscall and |t| must run before gdb's target thread can make\n  // progress. So, allow |t| to run anyway.\n  *signal_to_deliver = 0;\n  return RUN_CONTINUE;\n}\n\nstruct AllowedTasks {\n  TaskUid task; // tid 0 means 'any member of debuggee_tguid'\n  RunCommand command;\n};\nstatic RunCommand compute_run_command_for_reverse_exec(\n    Session& session, const ThreadGroupUid& debuggee_tguid,\n    const GdbRequest& req, vector<AllowedTasks>& allowed_tasks) {\n  // Singlestep if any of the actions request singlestepping.\n  RunCommand result = RUN_CONTINUE;\n  for (auto& action : req.cont().actions) {\n    if (action.target.pid > 0 && action.target.pid != debuggee_tguid.tid()) {\n      continue;\n    }\n    AllowedTasks allowed;\n    allowed.command = RUN_CONTINUE;\n    if (action.type == ACTION_STEP) {\n      allowed.command = result = RUN_SINGLESTEP;\n    }\n    if (action.target.tid > 0) {\n      Task* t = session.find_task(action.target.tid);\n      if (t) {\n        allowed.task = t->tuid();\n      }\n    }\n    allowed_tasks.push_back(allowed);\n  }\n  return result;\n}\n\n/**\n * Create a new diversion session using |replay| session as the\n * template.  The |replay| session isn't mutated.\n *\n * Execution begins in the new diversion session under the control of\n * |dbg| starting with initial thread target |task|.  The diversion\n * session ends at the request of |dbg|, and |req| returns the first\n * request made that wasn't handled by the diversion session.  That\n * is, the first request that should be handled by |replay| upon\n * resuming execution in that session.\n */\nGdbRequest GdbServer::divert(ReplaySession& replay) {\n  GdbRequest req;\n  LOG(debug) << \"Starting debugging diversion for \" << &replay;\n\n  if (timeline_) {\n    // Ensure breakpoints and watchpoints are applied before we fork the\n    // diversion, to ensure the diversion is consistent with the timeline\n    // breakpoint/watchpoint state.\n    timeline_->apply_breakpoints_and_watchpoints();\n  }\n  DiversionSession::shr_ptr diversion_session = replay.clone_diversion();\n  uint32_t diversion_refcount = 1;\n  ExtendedTaskId saved_query_task = last_query_task;\n  ExtendedTaskId saved_continue_task = last_continue_task;\n\n  for (const auto& dbg_mem : debugger_mem) {\n    for (const auto& region : dbg_mem.second.regions) {\n      map_debugger_mem(*diversion_session, dbg_mem.first, region.first.start());\n    }\n  }\n\n  vector<TraceField> fields;\n  if (!DIVERSION_SINGLESTEP_PRINT.empty()) {\n    parse_trace_fields(DIVERSION_SINGLESTEP_PRINT, &fields);\n  }\n\n  while (true) {\n    if (!diverter_process_debugger_requests(*diversion_session,\n                                           diversion_refcount, &req)) {\n      read_back_debugger_mem(*diversion_session);\n      break;\n    }\n\n    DEBUG_ASSERT(req.is_resume_request());\n\n    if (req.cont().run_direction == RUN_BACKWARD) {\n      // We don't support reverse execution in a diversion. Just issue\n      // an immediate stop.\n      notify_stop_internal(*diversion_session, last_continue_task, 0);\n      memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n      last_query_task = last_continue_task;\n      continue;\n    }\n\n    Task* t = diversion_session->find_task(last_continue_task.tuid);\n    DEBUG_ASSERT(t != nullptr);\n\n    int signal_to_deliver = 0;\n    RunCommand command = DIVERSION_SINGLESTEP_PRINT.empty() ? \n        compute_run_command_from_actions(t, req, &signal_to_deliver) : RUN_SINGLESTEP;\n    auto result =\n        diversion_session->diversion_step(t, command, signal_to_deliver);\n\n    if (result.status == DiversionSession::DIVERSION_EXITED) {\n      diversion_refcount = 0;\n      maybe_notify_stop(*diversion_session, req, result.break_status);\n      if (timeline_) {\n        // gdb assumes that the process is gone and all its\n        // breakpoints have gone with it. It will set new breakpoints.\n        timeline_->remove_breakpoints_and_watchpoints();\n      }\n      req = GdbRequest(DREQ_NONE);\n      // Deliberately not reading back debugger mem\n      break;\n    }\n\n    DEBUG_ASSERT(result.status == DiversionSession::DIVERSION_CONTINUE);\n\n    if (!DIVERSION_SINGLESTEP_PRINT.empty() && result.break_status.singlestep_complete) {\n      print_trace_fields(t->as_replay(), 0, 0, false, fields, stdout);\n      continue;\n    }\n\n    maybe_notify_stop(*diversion_session, req, result.break_status);\n  }\n\n  LOG(debug) << \"... ending debugging diversion\";\n  DEBUG_ASSERT(diversion_refcount == 0);\n\n  diversion_session->kill_all_tasks();\n\n  last_query_task = saved_query_task;\n  last_continue_task = saved_continue_task;\n  return req;\n}\n\n/**\n * Reply to debugger requests until the debugger asks us to resume\n * execution, detach, restart, or interrupt.\n */\nGdbRequest GdbServer::process_debugger_requests(ReportState state) {\n  while (true) {\n    GdbRequest req = dbg->get_request();\n    req.suppress_debugger_stop = false;\n    try_lazy_reverse_singlesteps(req);\n\n    if (req.type == DREQ_READ_SIGINFO) {\n      vector<uint8_t> si_bytes;\n      si_bytes.resize(req.mem().len);\n      memset(si_bytes.data(), 0, si_bytes.size());\n      memcpy(si_bytes.data(), &stop_siginfo,\n             min(si_bytes.size(), sizeof(stop_siginfo)));\n      dbg->reply_read_siginfo(si_bytes);\n\n      if (!timeline_) {\n        continue;\n      }\n      // READ_SIGINFO is usually the start of a diversion. It can also be\n      // triggered by \"print $_siginfo\" but that is rare so we just assume it's\n      // a diversion start; if \"print $_siginfo\" happens we'll print the correct\n      // siginfo and then incorrectly start a diversion and go haywire :-(.\n      // Ideally we'd come up with a better way to detect diversions so that\n      // \"print $_siginfo\" works.\n      req = divert(timeline_->current_session());\n      if (req.type == DREQ_NONE) {\n        continue;\n      }\n      // Carry on to process the request that was rejected by\n      // the diversion session\n    }\n\n    if (req.type == DREQ_SAVE_REGISTER_STATE && timeline_) {\n      dbg->reply_save_register_state(true, DIVERSION_SAVED_REGISTER_STATE);\n      req = divert(timeline_->current_session());\n      if (req.type == DREQ_NONE) {\n        continue;\n      }\n      // Carry on to process the request that was rejected by\n      // the diversion session\n    }\n\n    if (req.is_resume_request()) {\n      Task* t = current_session().find_task(last_continue_task.tuid);\n      if (t) {\n        maybe_singlestep_for_event(t, &req);\n      }\n      return req;\n    }\n\n    if (req.type == DREQ_INTERRUPT) {\n      LOG(debug) << \"  request to interrupt\";\n      return req;\n    }\n\n    if (req.type == DREQ_RESTART) {\n      // Debugger client requested that we restart execution\n      // from the beginning.  Restart our debug session.\n      LOG(debug) << \"  request to restart at event \" << req.restart().param;\n      return req;\n    }\n    if (req.type == DREQ_DETACH) {\n      LOG(debug) << \"  debugger detached\";\n      dbg->reply_detach();\n      return req;\n    }\n\n    dispatch_debugger_request(current_session(), req, state);\n  }\n}\n\nvoid GdbServer::try_lazy_reverse_singlesteps(GdbRequest& req) {\n  if (!timeline_) {\n    return;\n  }\n\n  ReplayTimeline::Mark now;\n  bool need_seek = false;\n  ReplayTask* t = timeline_->current_session().current_task();\n  while (t && req.type == DREQ_CONT &&\n         req.cont().run_direction == RUN_BACKWARD &&\n         req.cont().actions.size() == 1 &&\n         req.cont().actions[0].type == ACTION_STEP &&\n         req.cont().actions[0].signal_to_deliver == 0 &&\n         matches_threadid(t, req.cont().actions[0].target) &&\n         !req.suppress_debugger_stop) {\n    if (!now) {\n      now = timeline_->mark();\n    }\n    ReplayTimeline::Mark previous = timeline_->lazy_reverse_singlestep(now, t);\n    if (!previous) {\n      break;\n    }\n\n    now = previous;\n    need_seek = true;\n    BreakStatus break_status;\n    break_status.task_context = TaskContext(t);\n    break_status.singlestep_complete = true;\n    LOG(debug) << \"  using lazy reverse-singlestep\";\n    maybe_notify_stop(timeline_->current_session(), req, break_status);\n\n    while (true) {\n      req = dbg->get_request();\n      req.suppress_debugger_stop = false;\n      if (req.type != DREQ_GET_REGS) {\n        break;\n      }\n      LOG(debug) << \"  using lazy reverse-singlestep registers\";\n      dispatch_regs_request(now.regs(), now.extra_regs());\n    }\n  }\n\n  if (need_seek) {\n    timeline_->seek_to_mark(now);\n  }\n}\n\nbool GdbServer::detach_or_restart(const GdbRequest& req, ContinueOrStop* s) {\n  if (DREQ_RESTART == req.type) {\n    restart_session(req);\n    *s = CONTINUE_DEBUGGING;\n    return true;\n  }\n  if (DREQ_DETACH == req.type) {\n    *s = STOP_DEBUGGING;\n    return true;\n  }\n  return false;\n}\n\nGdbServer::ContinueOrStop GdbServer::handle_exited_state(\n    GdbRequest& last_resume_request) {\n  // TODO return real exit code, if it's useful.\n  dbg->notify_exit_code(0);\n  if (timeline_) {\n    final_event = timeline_->current_session().trace_reader().time();\n  }\n  while (true) {\n    GdbRequest req = process_debugger_requests(REPORT_THREADS_DEAD);\n    ContinueOrStop s;\n    if (detach_or_restart(req, &s)) {\n      last_resume_request = GdbRequest();\n      return s;\n    }\n    if (req.type == DREQ_INTERRUPT) {\n      // Ignore this. Sometimes LLDB seems to send it automatically\n      // after the task has exited, before we detach I guess.\n      continue;\n    }\n    FATAL() << \"Received continue/interrupt request after end-of-trace: \"\n            << req.type;\n  }\n}\n\nReplayTask* GdbServer::require_timeline_current_task() {\n  if (!timeline_) {\n    FATAL() << \"Timeline required here\";\n  }\n  ReplayTask* t = timeline_->current_session().current_task();\n  if (!t) {\n    FATAL() << \"Expected current task but none found; expected task with tid \"\n      << timeline_->current_session().current_trace_frame().tid()\n      << \" at event \" << timeline_->current_session().current_frame_time();\n  }\n  return t;\n}\n\nGdbServer::ContinueOrStop GdbServer::debug_one_step(\n    GdbRequest& last_resume_request) {\n  if (!timeline_) {\n    FATAL() << \"Timeline required here\";\n  }\n\n  ReplayResult result;\n  GdbRequest req;\n\n  if (in_debuggee_end_state) {\n    // Treat the state where the last thread is about to exit like\n    // termination.\n    req = process_debugger_requests();\n    // If it's a forward execution request, fake the exited state.\n    if (req.is_resume_request() && req.cont().run_direction == RUN_FORWARD) {\n      if (interrupt_pending) {\n        // Just process this. We're getting it after a restart.\n      } else {\n        return handle_exited_state(last_resume_request);\n      }\n    } else {\n      if (req.type != DREQ_DETACH) {\n        in_debuggee_end_state = false;\n      }\n    }\n    // Otherwise (e.g. detach, restart, interrupt or reverse-exec) process\n    // the request as normal.\n  } else if (!interrupt_pending || last_resume_request.type == DREQ_NONE) {\n    req = process_debugger_requests();\n  } else {\n    req = last_resume_request;\n  }\n\n  ContinueOrStop s;\n  if (detach_or_restart(req, &s)) {\n    last_resume_request = GdbRequest();\n    return s;\n  }\n\n  if (req.is_resume_request()) {\n    last_resume_request = req;\n  } else {\n    DEBUG_ASSERT(req.type == DREQ_INTERRUPT);\n    interrupt_pending = true;\n    req = last_resume_request;\n    DEBUG_ASSERT(req.is_resume_request());\n  }\n\n  if (interrupt_pending) {\n    Task* t = require_timeline_current_task();\n    if (t->thread_group()->tguid() == debuggee_tguid) {\n      interrupt_pending = false;\n      notify_stop_internal(timeline_->current_session(),\n          extended_task_id(t), in_debuggee_end_state ? SIGKILL : 0);\n      memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n      return CONTINUE_DEBUGGING;\n    }\n  }\n\n  if (exit_sigkill_pending) {\n    Task* t = require_timeline_current_task();\n    if (t->thread_group()->tguid() == debuggee_tguid) {\n      exit_sigkill_pending = false;\n      if (req.cont().run_direction == RUN_FORWARD) {\n        notify_stop_internal(timeline_->current_session(),\n            extended_task_id(t), SIGKILL);\n        memset(&stop_siginfo, 0, sizeof(stop_siginfo));\n        return CONTINUE_DEBUGGING;\n      }\n    }\n  }\n\n  if (req.cont().run_direction == RUN_FORWARD) {\n    if (is_in_exec(timeline_) &&\n        require_timeline_current_task()->thread_group()->tguid() ==\n            debuggee_tguid) {\n      // Don't go any further forward. maybe_notify_stop will generate a\n      // stop.\n      result = ReplayResult();\n    } else {\n      int signal_to_deliver;\n      RunCommand command = compute_run_command_from_actions(\n          require_timeline_current_task(), req, &signal_to_deliver);\n      // Ignore gdb's |signal_to_deliver|; we just have to follow the replay.\n      result = timeline_->replay_step_forward(command);\n    }\n    if (result.status == REPLAY_EXITED) {\n      return handle_exited_state(last_resume_request);\n    }\n  } else {\n    vector<AllowedTasks> allowed_tasks;\n    // Convert the tids in GdbContActions into TaskUids to avoid issues\n    // if tids get reused.\n    RunCommand command = compute_run_command_for_reverse_exec(\n        timeline_->current_session(), debuggee_tguid, req, allowed_tasks);\n    auto stop_filter = [&](ReplayTask* t, const BreakStatus &break_status) -> bool {\n      if (t->thread_group()->tguid() != debuggee_tguid) {\n        return false;\n      }\n\n      // don't stop for a signal that has been specified by QPassSignal\n      if (break_status.signal && dbg->is_pass_signal(break_status.signal->si_signo)) {\n        LOG(debug) << \"Filtering out event for signal \" << break_status.signal->si_signo;\n        return false;\n      }\n\n      // If gdb's requested actions don't allow the task to run, we still\n      // let it run (we can't do anything else, since we're replaying), but\n      // we won't report stops in that task.\n      for (auto& a : allowed_tasks) {\n        if (a.task.tid() == 0 || a.task == t->tuid()) {\n          return true;\n        }\n      }\n      return false;\n    };\n\n    auto interrupt_check = [&]() { return dbg->sniff_packet(); };\n    switch (command) {\n      case RUN_CONTINUE:\n        result = timeline_->reverse_continue(stop_filter, interrupt_check);\n        break;\n      case RUN_SINGLESTEP: {\n        Task* t = timeline_->current_session().find_task(last_continue_task.tuid);\n        DEBUG_ASSERT(t);\n        result = timeline_->reverse_singlestep(\n            last_continue_task.tuid, t->tick_count(), stop_filter, interrupt_check);\n        break;\n      }\n      default:\n        DEBUG_ASSERT(0 && \"Unknown RunCommand\");\n    }\n\n    if (result.status == REPLAY_EXITED) {\n      return handle_exited_state(last_resume_request);\n    }\n  }\n  if (!req.suppress_debugger_stop) {\n    maybe_notify_stop(timeline_->current_session(),\n        req, result.break_status);\n  }\n  if (req.cont().run_direction == RUN_FORWARD &&\n      is_last_thread_exit(result.break_status) &&\n      result.break_status.task_context.thread_group->tguid() == debuggee_tguid) {\n    in_debuggee_end_state = true;\n  }\n  return CONTINUE_DEBUGGING;\n}\n\nstatic bool target_event_reached(const ReplayTimeline& timeline,\n                                 const GdbServer::Target& target,\n                                 const ReplayResult& result) {\n  if (target.event == -1) {\n    return is_last_thread_exit(result.break_status) &&\n      (target.pid <= 0 || result.break_status.task_context.thread_group->tgid == target.pid);\n  } else {\n    return timeline.current_session().current_trace_frame().time() > target.event;\n  }\n}\n\nstatic bool at_target(ReplayTimeline& timeline,\n                      const GdbServer::Target& target,\n                      volatile bool* stop_replaying_to_target,\n                      const ReplayResult& result) {\n  // Don't launch the debugger for the initial rr fork child.\n  // No one ever wants that to happen.\n  if (!timeline.current_session().done_initial_exec()) {\n    return false;\n  }\n  Task* t = timeline.current_session().current_task();\n  if (!t) {\n    return false;\n  }\n  bool target_is_exit = target.event == -1;\n  if (!(timeline.can_add_checkpoint() || target_is_exit)) {\n    return false;\n  }\n  if (stop_replaying_to_target && *stop_replaying_to_target) {\n    return true;\n  }\n  // When we decide to create the debugger, we may end up\n  // creating a checkpoint.  In that case, we want the\n  // checkpoint to retain the state it had *before* we started\n  // replaying the next frame.  Otherwise, the TraceIfstream\n  // will be one frame ahead of its tracee tree.\n  //\n  // So we make the decision to create the debugger based on the\n  // frame we're *about to* replay, without modifying the\n  // TraceIfstream.\n  // NB: we'll happily attach to whichever task within the\n  // group happens to be scheduled here.  We don't take\n  // \"attach to process\" to mean \"attach to thread-group\n  // leader\".\n  return target_event_reached(timeline, target, result) &&\n         (!target.pid || t->tgid() == target.pid) &&\n         (!target.require_exec || t->execed()) &&\n         // Ensure we're at the start of processing an event. We don't\n         // want to attach while we're finishing an exec() since that's a\n         // slightly confusing state for ReplayTimeline's reverse execution.\n         (!timeline.current_session().current_step_key().in_execution() || target_is_exit);\n}\n\n/**\n * The trace has reached the event at which the user wanted to start debugging.\n * Set up the appropriate state.\n */\nvoid GdbServer::activate_debugger() {\n  if (!timeline_) {\n    FATAL() << \"Should only be called with a timeline\";\n  }\n  TraceFrame next_frame = timeline_->current_session().current_trace_frame();\n  FrameTime completed_event = next_frame.time() - 1;\n  Task* t = require_timeline_current_task();\n  if (target.event || target.pid) {\n    if (stop_replaying_to_target && *stop_replaying_to_target) {\n      fprintf(stderr, \"\\a\\n\"\n                      \"--------------------------------------------------\\n\"\n                      \" ---> Interrupted; attached to NON-TARGET process %d at event %llu.\\n\"\n                      \"--------------------------------------------------\\n\",\n              t->tgid(), (long long)completed_event);\n    } else if (target.event >= 0) {\n      fprintf(stderr, \"\\a\\n\"\n                      \"--------------------------------------------------\\n\"\n                      \" ---> Reached target process %d at event %llu.\\n\"\n                      \"--------------------------------------------------\\n\",\n              t->tgid(), (long long)completed_event);\n    } else {\n      ASSERT(t, target.event == -1);\n      fprintf(stderr, \"\\a\\n\"\n                      \"--------------------------------------------------\\n\"\n                      \" ---> Reached exit of target process %d at event %llu.\\n\"\n                      \"--------------------------------------------------\\n\",\n              t->tgid(), (long long)completed_event);\n      exit_sigkill_pending = true;\n    }\n  }\n\n  // Store the current tgid and event as the \"execution target\"\n  // for the next replay session, if we end up restarting.  This\n  // allows us to determine if a later session has reached this\n  // target without necessarily replaying up to this point.\n  target.pid = t->tgid();\n  target.require_exec = false;\n  target.event = completed_event;\n\n  last_query_task = last_continue_task = extended_task_id(t);\n\n  // Have the \"checkpoint\" be the original replay\n  // session, and then switch over to using the cloned\n  // session.  The cloned tasks will look like children\n  // of the clonees, so this scheme prevents |pstree|\n  // output from getting /too/ far out of whack.\n  const char* where = \"???\";\n  if (timeline_->can_add_checkpoint()) {\n    debugger_restart_checkpoint =\n        Checkpoint(*timeline_, last_continue_task, Checkpoint::EXPLICIT, where);\n  } else {\n    debugger_restart_checkpoint = Checkpoint(*timeline_, last_continue_task,\n                                             Checkpoint::NOT_EXPLICIT, where);\n  }\n}\n\nstatic FrameTime compute_time_from_ticks(ReplayTimeline& timeline, Ticks target) {\n  ReplaySession &session = timeline.current_session();\n  Task* task = session.current_task();\n  FrameTime current_time = session.current_frame_time();\n  TraceReader tmp_reader(session.trace_reader());\n  FrameTime last_time = current_time;\n  if (session.ticks_at_start_of_current_event() > target) {\n    tmp_reader.rewind();\n    FrameTime task_time;\n    // EXEC and CLONE reset the ticks counter. Find the first event\n    // where the tuid matches our current task.\n    // We'll always hit at least one CLONE/EXEC event for a task\n    // (we can't debug the time before the initial exec)\n    // but set this to 0 anyway to silence compiler warnings.\n    FrameTime ticks_start_time = 0;\n    while (true) {\n      TraceTaskEvent r = tmp_reader.read_task_event(&task_time);\n      if (task_time >= current_time) {\n        break;\n      }\n      if (r.type() == TraceTaskEvent::CLONE || r.type() == TraceTaskEvent::EXEC) {\n        if (r.tid() == task->tuid().tid()) {\n          ticks_start_time = task_time;\n        }\n      }\n    }\n    // Forward the frame reader to the current event\n    last_time = ticks_start_time + 1;\n    while (true) {\n      TraceFrame frame = tmp_reader.read_frame();\n      if (frame.time() >= ticks_start_time) {\n        break;\n      }\n    }\n  } else if (target < session.current_trace_frame().ticks()) {\n    // The target tick is entirely within the current frame.\n    // If not handled here, the below loop might otherwise skip over\n    // it if the next frame is for another tid.\n    return last_time;\n  }\n  \n  while (true) {\n    if (tmp_reader.at_end()) {\n      return -1;\n    }\n    TraceFrame frame = tmp_reader.read_frame();\n    if (frame.tid() == task->tuid().tid() && target < frame.ticks()) {\n      break;\n    }\n    last_time = frame.time() + 1;\n  }\n  return last_time;\n}\n\nvoid GdbServer::restart_session(const GdbRequest& req) {\n  DEBUG_ASSERT(req.type == DREQ_RESTART);\n  DEBUG_ASSERT(dbg);\n\n  failed_restart = false;\n  in_debuggee_end_state = false;\n  if (!timeline_) {\n    failed_restart = true;\n    dbg->notify_restart_failed();\n    return;\n  }\n\n  timeline_->remove_breakpoints_and_watchpoints();\n\n  Checkpoint checkpoint_to_restore;\n  if (req.restart().type == RESTART_FROM_CHECKPOINT) {\n    auto it = checkpoints.find(req.restart().param);\n    if (it == checkpoints.end()) {\n      cout << \"Checkpoint \" << req.restart().param_str << \" not found.\\n\";\n      cout << \"Valid checkpoints:\";\n      for (auto& c : checkpoints) {\n        cout << \" \" << c.first;\n      }\n      cout << \"\\n\";\n      failed_restart = true;\n      dbg->notify_restart_failed();\n      return;\n    }\n    checkpoint_to_restore = it->second;\n  } else if (req.restart().type == RESTART_FROM_PREVIOUS) {\n    checkpoint_to_restore = debugger_restart_checkpoint;\n  } else if (req.restart().type == RESTART_FROM_TICKS) {\n    Ticks ticks = req.restart().param;\n    FrameTime time = compute_time_from_ticks(*timeline_, ticks);\n    if (time == -1) {\n      cout << \"No event found matching specified ticks target.\\n\";\n      failed_restart = true;\n      dbg->notify_restart_failed();\n      return;\n    }\n    timeline_->seek_to_ticks(time, ticks);\n  }\n\n  interrupt_pending = true;\n\n  if (checkpoint_to_restore.mark) {\n    timeline_->seek_to_mark(checkpoint_to_restore.mark);\n    last_query_task = last_continue_task =\n        checkpoint_to_restore.last_continue_task;\n    if (debugger_restart_checkpoint.is_explicit == Checkpoint::EXPLICIT) {\n      timeline_->remove_explicit_checkpoint(debugger_restart_checkpoint.mark);\n    }\n    debugger_restart_checkpoint = checkpoint_to_restore;\n    if (timeline_->can_add_checkpoint()) {\n      timeline_->add_explicit_checkpoint();\n    }\n    return;\n  }\n\n  if (req.restart().type == RESTART_FROM_EVENT) {\n    // Note that we don't reset the target pid; we intentionally keep targeting\n    // the same process no matter what is running when we hit the event.\n    target.event = req.restart().param;\n    target.event = min(final_event - 1, target.event);\n    timeline_->seek_to_before_event(target.event);\n    ReplayResult result;\n    do {\n      result = timeline_->replay_step_forward(RUN_CONTINUE);\n      // We should never reach the end of the trace without hitting the stop\n      // condition below.\n      DEBUG_ASSERT(result.status != REPLAY_EXITED);\n      if (is_last_thread_exit(result.break_status) &&\n          result.break_status.task_context.thread_group->tgid == target.pid) {\n        // Debuggee task is about to exit. Stop here.\n        in_debuggee_end_state = true;\n        break;\n      }\n    } while (!at_target(*timeline_, target, stop_replaying_to_target, result));\n  }\n  activate_debugger();\n}\n\nvoid GdbServer::serve_replay(std::shared_ptr<ReplaySession> session,\n                             const Target& target,\n                             volatile bool* stop_replaying_to_target,\n                             DebuggerType debugger_type,\n                             const ConnectionFlags& flags) {\n  ReplayTimeline timeline(std::move(session));\n\n  ReplayResult result;\n  do {\n    result = timeline.replay_step_forward(RUN_CONTINUE);\n    if (result.status == REPLAY_EXITED) {\n      LOG(info) << \"Debugger was not launched before end of trace\";\n      return;\n    }\n  } while (!at_target(timeline, target, stop_replaying_to_target, result));\n\n  unsigned short port = flags.dbg_port > 0 ? flags.dbg_port : getpid();\n  // Don't probe if the user specified a port.  Explicitly\n  // selecting a port is usually done by scripts, which would\n  // presumably break if a different port were to be selected by\n  // rr (otherwise why would they specify a port in the first\n  // place).  So fail with a clearer error message.\n  auto probe = flags.dbg_port > 0 ? DONT_PROBE : PROBE_PORT;\n  Task* t = timeline.current_session().current_task();\n  OpenedSocket listen_socket = open_socket(flags.dbg_host, port, probe);\n  if (flags.debugger_params_write_pipe) {\n    DebuggerParams params;\n    memset(&params, 0, sizeof(params));\n    strncpy(params.exe_image, t->vm()->exe_image().c_str(),\n            sizeof(params.exe_image) - 1);\n    params.socket_domain = listen_socket.domain;\n    strncpy(params.host, listen_socket.host.c_str(), sizeof(params.host) - 1);\n    params.port = listen_socket.port;\n\n    ssize_t nwritten =\n        write(*flags.debugger_params_write_pipe, &params, sizeof(params));\n    DEBUG_ASSERT(nwritten == sizeof(params));\n  } else {\n    vector<string> cmd = debugger_launch_command(t, listen_socket.domain,\n        listen_socket.host, listen_socket.port, flags.serve_files,\n        flags.debugger_name, debugger_type);\n    fprintf(stderr, \"Launch debugger with\\n  %s\\n\", to_shell_string(cmd).c_str());\n  }\n\n  if (flags.debugger_params_write_pipe) {\n    flags.debugger_params_write_pipe->close();\n  }\n\n  FrameTime first_run_event = std::max(t->vm()->first_run_event(),\n    t->thread_group()->first_run_event());\n  if (first_run_event) {\n    timeline.set_reverse_execution_barrier_event(first_run_event);\n  }\n\n  do {\n    LOG(debug) << \"initializing debugger connection\";\n    auto connection = GdbServerConnection::await_connection(t, listen_socket.fd,\n      debugger_type);\n\n    GdbServer server(connection, timeline.current_session().current_task(),\n                     &timeline, target);\n    server.activate_debugger();\n\n    GdbRequest last_resume_request;\n    while (server.debug_one_step(last_resume_request) == CONTINUE_DEBUGGING) {\n    }\n\n    timeline.remove_breakpoints_and_watchpoints();\n  } while (flags.keep_listening);\n\n  LOG(debug) << \"debugger server exiting ...\";\n}\n\nstatic ScopedFd generate_fake_proc_maps(Task* t) {\n  TempFile file = create_temporary_file(\"rr-fake-proc-maps-XXXXXX\");\n  unlink(file.name.c_str());\n\n  int fd = dup(file.fd);\n  if (fd < 0) {\n    FATAL() << \"Cannot dup\";\n  }\n  FILE* f = fdopen(fd, \"w\");\n\n\n  int addr_min_width = word_size(t->arch()) == 8 ? 10 : 8;\n  for (AddressSpace::Maps::iterator it = t->vm()->maps().begin();\n       it != t->vm()->maps().end(); ++it) {\n    // If this is the mapping just before the rr page and it's still librrpage,\n    // merge this mapping with the subsequent one. We'd like gdb to treat\n    // librrpage as the vdso, but it'll only do so if the entire vdso is one\n    // mapping.\n    auto m = *it;\n    uintptr_t map_end = (long long)m.recorded_map.end().as_int();\n    if (m.recorded_map.end() == t->vm()->rr_page_start()) {\n      auto it2 = it;\n      if (++it2 != t->vm()->maps().end()) {\n        auto m2 = *it2;\n        if (m2.flags & AddressSpace::Mapping::IS_RR_PAGE) {\n          // Extend this mapping\n          map_end += PRELOAD_LIBRARY_PAGE_SIZE;\n          // Skip the rr page\n          ++it;\n        }\n      }\n    }\n\n    int len =\n        fprintf(f, \"%0*llx-%0*llx %s%s%s%s %08llx %02x:%02x %lld\",\n                addr_min_width, (long long)m.recorded_map.start().as_int(),\n                addr_min_width, (long long)map_end,\n                (m.recorded_map.prot() & PROT_READ) ? \"r\" : \"-\",\n                (m.recorded_map.prot() & PROT_WRITE) ? \"w\" : \"-\",\n                (m.recorded_map.prot() & PROT_EXEC) ? \"x\" : \"-\",\n                (m.recorded_map.flags() & MAP_SHARED) ? \"s\" : \"p\",\n                (long long)m.recorded_map.file_offset_bytes(),\n                major(m.recorded_map.device()), minor(m.recorded_map.device()),\n                (long long)m.recorded_map.inode());\n    while (len < 72) {\n      fputc(' ', f);\n      ++len;\n    }\n    fputc(' ', f);\n\n    string name;\n    const string& fsname = m.recorded_map.fsname();\n    for (size_t i = 0; i < fsname.size(); ++i) {\n      if (fsname[i] == '\\n') {\n        name.append(\"\\\\012\");\n      } else {\n        name.push_back(fsname[i]);\n      }\n    }\n    fputs(name.c_str(), f);\n    fputc('\\n', f);\n  }\n  if (ferror(f) || fclose(f)) {\n    FATAL() << \"Can't write\";\n  }\n\n  return std::move(file.fd);\n}\n\nstatic bool is_ld_mapping(string map_name) {\n  char ld_start[] = \"ld-\";\n  size_t matchpos = map_name.find_last_of('/');\n  string fname = map_name.substr(matchpos == string::npos ? 0 : matchpos + 1);\n  return memcmp(fname.c_str(), ld_start,\n                sizeof(ld_start)-1) == 0;\n}\n\nstatic bool is_likely_interp(string fsname) {\n#ifdef __aarch64__\n  return fsname == \"/lib/ld-linux-aarch64.so.1\";\n#else\n  return fsname == \"/lib64/ld-linux-x86-64.so.2\" || fsname == \"/lib/ld-linux.so.2\";\n#endif\n}\n\n#ifndef __BIONIC__\nstatic remote_ptr<void> base_addr_from_rendezvous(Task* t, string fname)\n{\n  remote_ptr<void> interpreter_base = t->vm()->saved_interpreter_base();\n  if (!interpreter_base || !t->vm()->has_mapping(interpreter_base)) {\n    return nullptr;\n  }\n  string ld_path = t->vm()->saved_ld_path();\n  if (ld_path.length() == 0) {\n    FATAL() << \"Failed to retrieve interpreter name with interpreter_base=\" << interpreter_base;\n  }\n  ScopedFd ld(ld_path.c_str(), O_RDONLY);\n  if (ld < 0) {\n    FATAL() << \"Open failed: \" << ld_path;\n  }\n  ElfFileReader reader(ld);\n  auto syms = reader.read_symbols(\".dynsym\", \".dynstr\");\n  static const char r_debug[] = \"_r_debug\";\n  bool found = false;\n  uintptr_t r_debug_offset = 0;\n  for (size_t i = 0; i < syms.size(); ++i) {\n    if (!syms.is_name(i, r_debug)) {\n      continue;\n    }\n    r_debug_offset = syms.addr(i);\n    found = true;\n  }\n  if (!found) {\n    return nullptr;\n  }\n  bool ok = true;\n  remote_ptr<NativeArch::r_debug> r_debug_remote = interpreter_base.as_int()+r_debug_offset;\n  remote_ptr<NativeArch::link_map> link_map = t->read_mem(REMOTE_PTR_FIELD(r_debug_remote, r_map), &ok);\n  while (ok && link_map != nullptr) {\n    if (fname == t->read_c_str(t->read_mem(REMOTE_PTR_FIELD(link_map, l_name), &ok), &ok)) {\n      remote_ptr<void> result = t->read_mem(REMOTE_PTR_FIELD(link_map, l_addr), &ok);\n      return ok ? result : nullptr;\n    }\n    link_map = t->read_mem(REMOTE_PTR_FIELD(link_map, l_next), &ok);\n  }\n  return nullptr;\n}\n#endif\n\nint GdbServer::open_file(Session& session, Task* continue_task, const std::string& file_name) {\n  // XXX should we require file_scope_pid == 0 here?\n  ScopedFd contents;\n\n  if (file_name.empty()) {\n    return -1;\n  }\n\n  LOG(debug) << \"Trying to open \" << file_name;\n\n  if (file_name.substr(0, 6) == \"/proc/\") {\n    char* tid_end;\n    long tid = strtol(file_name.c_str() + 6, &tid_end, 10);\n    if (*tid_end != '/') {\n      return -1;\n    }\n    if (!strncmp(tid_end, \"/task/\", 6)) {\n      tid = strtol(tid_end + 6, &tid_end, 10);\n      if (*tid_end != '/') {\n        return -1;\n      }\n    }\n    if (tid != (pid_t)tid) {\n      return -1;\n    }\n    Task* t = session.find_task(tid);\n    if (!t) {\n      return -1;\n    }\n    if (!strcmp(tid_end, \"/maps\")) {\n      contents = generate_fake_proc_maps(t);\n    } else {\n      return -1;\n    }\n  } else if (file_name == continue_task->vm()->interp_name()) {\n    remote_ptr<void> interp_base = continue_task->vm()->interp_base();\n    auto m = continue_task->vm()->mapping_of(interp_base);\n    LOG(debug) << \"Found dynamic linker as memory mapping \" << m.recorded_map;\n    int ret_fd = 0;\n    while (files.find(ret_fd) != files.end() ||\n           memory_files.find(ret_fd) != memory_files.end()) {\n      ++ret_fd;\n    }\n    memory_files.insert(make_pair(ret_fd, FileId(m.recorded_map)));\n    return ret_fd;\n  } else {\n    // See if we can find the file by serving one of our mappings\n    std::string normalized_file_name = file_name;\n    normalize_file_name(normalized_file_name);\n    for (const auto& m : continue_task->vm()->maps()) {\n      // The dynamic linker is generally a symlink that is resolved by the\n      // kernel when the process image gets loaded. We add a special case to\n      // substitute the correct mapping, so gdb can find the dynamic linker\n      // rendezvous structures.\n      // Use our old hack for ld from before we read PT_INTERP for backwards\n      // compat with older traces.\n      if (m.recorded_map.fsname().compare(0, normalized_file_name.length(), normalized_file_name) == 0\n          || m.map.fsname().compare(0, normalized_file_name.length(), normalized_file_name) == 0\n          || (is_ld_mapping(m.recorded_map.fsname()) &&\n              is_likely_interp(normalized_file_name)))\n      {\n        int ret_fd = 0;\n        while (files.find(ret_fd) != files.end() ||\n               memory_files.find(ret_fd) != memory_files.end()) {\n          ++ret_fd;\n        }\n        LOG(debug) << \"Found as memory mapping \" << m.recorded_map;\n        memory_files.insert(make_pair(ret_fd, FileId(m.recorded_map)));\n        return ret_fd;\n      }\n    }\n    // Last ditch attempt: Dig through the tracee's libc rendezvous struct to\n    // see if we can find this file by a different name (e.g. if it was opened\n    // via symlink)\n#ifndef __BIONIC__\n    remote_ptr<void> base = base_addr_from_rendezvous(continue_task, file_name);\n    if (base != nullptr && continue_task->vm()->has_mapping(base)) {\n      int ret_fd = 0;\n      while (files.find(ret_fd) != files.end() ||\n              memory_files.find(ret_fd) != memory_files.end()) {\n        ++ret_fd;\n      }\n      memory_files.insert(make_pair(ret_fd, FileId(continue_task->vm()->mapping_of(base).recorded_map)));\n      return ret_fd;\n    }\n#endif\n    LOG(debug) << \"... not found\";\n    return -1;\n   }\n\n  int ret_fd = 0;\n  while (files.find(ret_fd) != files.end()) {\n    ++ret_fd;\n  }\n  files.insert(make_pair(ret_fd, std::move(contents)));\n  return ret_fd;\n}\n\nstatic void remove_trailing_guard_pages(ReplaySession::MemoryRanges& ranges) {\n  remote_ptr<void> ptr;\n  while (true) {\n    auto it = ranges.lower_bound(MemoryRange(ptr, 1));\n    if (it == ranges.end()) {\n      return;\n    }\n    MemoryRange r = *it;\n    ranges.erase(it);\n    remote_ptr<void> end = floor_page_size(r.end() - 1);\n    if (end > r.start()) {\n      ranges.insert(MemoryRange(r.start(), end));\n    }\n    ptr = end;\n  }\n}\n\nremote_ptr<void> GdbServer::allocate_debugger_mem(ThreadGroupUid tguid, size_t size,\n    int prot) {\n  if (!timeline_) {\n    return nullptr;\n  }\n\n  auto it = debugger_mem.find(tguid);\n  if (it == debugger_mem.end()) {\n    it = debugger_mem.insert(make_pair(tguid, DebuggerMem())).first;\n    it->second.free_memory = timeline_->current_session().\n        always_free_address_space(ReplaySession::FAST);\n    remove_trailing_guard_pages(it->second.free_memory);\n    it->second.did_get_accurate_free_memory = false;\n  }\n  DebuggerMem& dbg_mem = it->second;\n\n  if (size >= (1 << 30)) {\n    return nullptr;\n  }\n  size = ceil_page_size(size);\n  while (true) {\n    for (auto it = dbg_mem.free_memory.begin();\n         it != dbg_mem.free_memory.end(); ++it) {\n      if (it->size() >= size + page_size()) {\n        MemoryRange r = *it;\n        dbg_mem.free_memory.erase(it);\n        // Skip guard page\n        remote_ptr<void> result = r.start() + page_size();\n        if (r.end() > result + size) {\n          dbg_mem.free_memory.insert(MemoryRange(result + size, r.end()));\n        }\n        DebuggerMemRegion& region =\n            dbg_mem.regions[MemoryRange(result, size)];\n        region.values.resize(size, 0);\n        region.prot = prot;\n        return result;\n      }\n    }\n\n    if (dbg_mem.did_get_accurate_free_memory) {\n      LOG(warn) << \"Can't allocate free memory for debugger\";\n      return nullptr;\n    }\n    dbg_mem.did_get_accurate_free_memory = true;\n    dbg_mem.free_memory = timeline_->current_session().\n        always_free_address_space(ReplaySession::ACCURATE);\n    for (const auto& kv : dbg_mem.regions) {\n      ReplaySession::delete_range(dbg_mem.free_memory,\n          MemoryRange(kv.first.start() - page_size(),\n                      kv.second.values.size() + page_size()));\n    }\n  }\n}\n\nstatic void coalesce_free_memory(ReplaySession::MemoryRanges& ranges,\n                                 remote_ptr<void> addr) {\n  if (addr.is_null()) {\n    return;\n  }\n  auto before = ranges.find(MemoryRange(addr - 1, 1));\n  if (before == ranges.end() || before->end() != addr) {\n    return;\n  }\n  MemoryRange before_range = *before;\n  ranges.erase(before);\n\n  auto after = ranges.find(MemoryRange(addr, 1));\n  if (after == ranges.end()) {\n    return;\n  }\n  MemoryRange after_range = *after;\n  ranges.erase(after);\n\n  ranges.insert(MemoryRange(before_range.start(), after_range.end()));\n}\n\nsize_t GdbServer::free_debugger_mem(ThreadGroupUid tguid, remote_ptr<void> addr) {\n  auto it = debugger_mem.find(tguid);\n  if (it == debugger_mem.end()) {\n    return 0;\n  }\n  DebuggerMem& dbg_mem = it->second;\n  auto region_it = dbg_mem.regions.find(MemoryRange(addr, 1));\n  if (region_it == dbg_mem.regions.end() || region_it->first.start() != addr) {\n    return 0;\n  }\n\n  size_t ret = region_it->first.size();\n  MemoryRange freed(addr - page_size(), region_it->first.end());\n  dbg_mem.free_memory.insert(freed);\n  coalesce_free_memory(dbg_mem.free_memory, freed.start());\n  coalesce_free_memory(dbg_mem.free_memory, freed.end());\n\n  dbg_mem.regions.erase(region_it);\n  return ret;\n}\n\nbool GdbServer::read_debugger_mem(ThreadGroupUid tguid, MemoryRange range,\n    uint8_t* values) {\n  auto it = debugger_mem.find(tguid);\n  if (it == debugger_mem.end()) {\n    return false;\n  }\n  DebuggerMem& dbg_mem = it->second;\n  auto region_it = dbg_mem.regions.lower_bound(range);\n  if (region_it == dbg_mem.regions.end() || range.end() <= region_it->first.start()) {\n    return false;\n  }\n  if (!region_it->first.contains(range)) {\n    FATAL() << \"Debugger read beyond bounds of region, no idea what's going on\";\n  }\n  size_t offset = range.start() - region_it->first.start();\n  memcpy(values, region_it->second.values.data() + offset, range.size());\n  return true;\n}\n\nbool GdbServer::write_debugger_mem(ThreadGroupUid tguid, MemoryRange range,\n    const uint8_t* values) {\n  auto it = debugger_mem.find(tguid);\n  if (it == debugger_mem.end()) {\n    return false;\n  }\n  DebuggerMem& dbg_mem = it->second;\n  auto region_it = dbg_mem.regions.lower_bound(range);\n  if (region_it == dbg_mem.regions.end() || range.end() <= region_it->first.start()) {\n    return false;\n  }\n  if (!region_it->first.contains(range)) {\n    FATAL() << \"Debugger write beyond bounds of region, no idea what's going on\";\n  }\n  size_t offset = range.start() - region_it->first.start();\n  memcpy(region_it->second.values.data() + offset, values, range.size());\n  return true;\n}\n\nvoid GdbServer::map_debugger_mem(DiversionSession& session,\n                                 ThreadGroupUid tguid, remote_ptr<void> addr) {\n  for (const auto& dbg_mem : debugger_mem) {\n    if (!addr.is_null() && tguid != dbg_mem.first) {\n      continue;\n    }\n    ThreadGroup* tg = session.find_thread_group(dbg_mem.first);\n    if (!tg || tg->task_set().empty()) {\n      // Threadgroup doesn't exist or is somehow empty at this point in time\n      continue;\n    }\n\n    Task* t = *tg->task_set().begin();\n    AddressSpace::shr_ptr vm = (*tg->task_set().begin())->vm();\n    AutoRemoteSyscalls remote(t);\n    for (const auto& region : dbg_mem.second.regions) {\n      remote_ptr<void> start = region.first.start();\n      if (!addr.is_null() && addr != start) {\n        continue;\n      }\n      size_t size = region.second.values.size();\n      // Mask debugger-provided prot bits here just in case someone\n      // tries to do something silly/dangerous/malicious.\n      int prot = region.second.prot & (PROT_READ | PROT_WRITE | PROT_EXEC);\n      int flags = MAP_PRIVATE | MAP_ANONYMOUS;\n      remote.infallible_mmap_syscall_if_alive(start, size, prot, flags, -1, 0);\n      vm->map(t, start, size, prot, flags, 0, \"\");\n      t->write_bytes_helper(start, size, region.second.values.data());\n    }\n  }\n}\n\nvoid GdbServer::unmap_debugger_mem(DiversionSession& session,\n                                   ThreadGroupUid tguid, remote_ptr<void> addr,\n                                   size_t size) {\n  ThreadGroup* tg = session.find_thread_group(tguid);\n  if (!tg || tg->task_set().empty()) {\n    // Threadgroup doesn't exist or is somehow empty at this point in time\n    return;\n  }\n\n  Task* t = *tg->task_set().begin();\n  AddressSpace::shr_ptr vm = (*tg->task_set().begin())->vm();\n  AutoRemoteSyscalls remote(t);\n  remote.infallible_munmap_syscall_if_alive(addr, size);\n  vm->unmap(t, addr, size);\n}\n\nvoid GdbServer::read_back_debugger_mem(DiversionSession& session) {\n  for (auto& dbg_mem : debugger_mem) {\n    ThreadGroup* tg = session.find_thread_group(dbg_mem.first);\n    if (!tg || tg->task_set().empty()) {\n      // Threadgroup doesn't exist or is somehow empty at this point in time\n      continue;\n    }\n\n    Task* t = *tg->task_set().begin();\n    AddressSpace::shr_ptr vm = (*tg->task_set().begin())->vm();\n    for (auto& region : dbg_mem.second.regions) {\n      remote_ptr<void> start = region.first.start();\n      size_t size = region.second.values.size();\n      t->read_bytes_helper(start, size, region.second.values.data());\n    }\n  }\n}\n\nconst vector<GdbServerRegister>& GdbServer::target_registers(\n    SupportedArch arch) {\n  if (!register_description.empty()) {\n    return register_description;\n  }\n\n  const auto add_range = [&](GdbServerRegister start, GdbServerRegister end_inclusive) {\n    for (auto reg = start; reg <= end_inclusive; reg = GdbServerRegister(reg + 1)) {\n      register_description.push_back(reg);\n    }\n  };\n\n  bool have_PKU = dbg->cpu_features() & GdbServerConnection::CPU_PKU;\n  bool have_AVX = dbg->cpu_features() & GdbServerConnection::CPU_AVX;\n  bool have_AVX512 = dbg->cpu_features() & GdbServerConnection::CPU_AVX512;\n  switch (arch) {\n    case x86: {\n      add_range(GdbServerRegister(0), GdbServerRegister(DREG_ORIG_EAX));\n\n      if (have_AVX) {\n        add_range(GdbServerRegister::DREG_YMM0H,\n                  GdbServerRegister(DREG_YMM7H));\n      }\n\n      if (have_AVX512) {\n        add_range(GdbServerRegister::DREG_ZMM0H,\n                  GdbServerRegister(DREG_K7));\n      }\n\n      if (have_PKU) {\n        register_description.push_back(DREG_PKRU);\n      }\n      break;\n    }\n    case x86_64: {\n      add_range(GdbServerRegister(0), GdbServerRegister(DREG_GS_BASE));\n      if (have_AVX) {\n        add_range(GdbServerRegister::DREG_64_YMM0H,\n                  GdbServerRegister(DREG_64_YMM15H));\n      }\n      if (have_AVX512) {\n        add_range(GdbServerRegister::DREG_64_XMM16,\n                  GdbServerRegister(DREG_64_K7));\n      }\n      if (have_PKU) {\n        register_description.push_back(DREG_64_PKRU);\n      }\n      break;\n    }\n    case aarch64:\n      add_range(GdbServerRegister::DREG_X0,\n                GdbServerRegister::DREG_NUM_LINUX_AARCH64);\n      break;\n    default:\n      FATAL() << \"Unknown architecture\";\n  }\n  return register_description;\n}\n\nbool GdbServer::debugger_mem_region(ThreadGroupUid tguid, remote_ptr<void> addr,\n    int* prot, MemoryRange* mem_range) {\n  auto it = debugger_mem.find(tguid);\n  if (it == debugger_mem.end()) {\n    return false;\n  }\n  DebuggerMem& dbg_mem = it->second;\n  auto region_it = dbg_mem.regions.find(MemoryRange(addr, 1));\n  if (region_it == dbg_mem.regions.end()) {\n    return false;\n  }\n  *prot = region_it->second.prot;\n  *mem_range = region_it->first;\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/GdbServer.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_GDB_SERVER_H_\n#define RR_GDB_SERVER_H_\n\n#include <map>\n#include <memory>\n#include <string>\n#include <unordered_map>\n#include <vector>\n\n#include \"AddressSpace.h\"\n#include \"DiversionSession.h\"\n#include \"GdbServerConnection.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTimeline.h\"\n#include \"ScopedFd.h\"\n#ifdef PROC_SERVICE_H\n#include \"ThreadDb.h\"\n#endif\n#include \"TraceFrame.h\"\n\nnamespace rr {\n\nclass GdbServer {\n  // Not ideal but we can't inherit friend from DebuggerExtensionCommand\n  friend std::string invoke_checkpoint(GdbServer&, Task*,\n                                       const std::vector<std::string>&);\n  friend std::string invoke_delete_checkpoint(GdbServer&, Task*,\n                                              const std::vector<std::string>&);\n  friend std::string invoke_info_checkpoints(GdbServer&, Task*,\n                                             const std::vector<std::string>&);\n\npublic:\n  struct Target {\n    Target() : pid(0), require_exec(false), event(0) {}\n    // Target process to debug, or 0 to just debug the first process\n    pid_t pid;\n    // If true, wait for the target process to exec() before attaching debugger\n    bool require_exec;\n    // Wait until at least 'event' has elapsed before attaching\n    FrameTime event;\n  };\n\n  struct ConnectionFlags {\n    // -1 to let GdbServer choose the port, a positive integer to select a\n    // specific port to listen on. If keep_listening is on, wait for another\n    // debugger connection after the first one is terminated.\n    int dbg_port;\n    std::string dbg_host;\n    bool keep_listening;\n    bool serve_files;\n    // If non-null, then when the gdbserver is set up, we write its connection\n    // parameters through this pipe. GdbServer::launch_gdb is passed the\n    // other end of this pipe to exec gdb with the parameters.\n    ScopedFd* debugger_params_write_pipe;\n    // Name of the debugger to suggest. Only used if debugger_params_write_pipe\n    // is null.\n    std::string debugger_name;\n\n    ConnectionFlags();\n  };\n\n  /**\n   * Serve the replay of 'session'.\n   * When `stop_replaying_to_target` is non-null, setting it to true\n   * (e.g. in a signal handler) will interrupt the replay.\n   * Returns only when the debugger disconnects.\n   */\n  static void serve_replay(std::shared_ptr<ReplaySession> session,\n                           const Target& target,\n                           volatile bool* stop_replaying_to_target,\n                           DebuggerType debugger_type,\n                           const ConnectionFlags& flags);\n\n  /**\n   * Return the register |which|, which may not have a defined value.\n   */\n  static GdbServerRegisterValue get_reg(const Registers& regs,\n                                  const ExtraRegisters& extra_regs,\n                                  GdbServerRegister which);\n\n  // Null if this is an emergency debug session.\n  ReplayTimeline* timeline() { return timeline_; }\n\n  static void serve_emergency_debugger(\n        std::unique_ptr<GdbServerConnection> dbg, Task* t) {\n    GdbServer(dbg, t, nullptr, Target()).process_debugger_requests();\n  }\n\nprivate:\n  GdbServer(std::unique_ptr<GdbServerConnection>& connection, Task* t,\n            ReplayTimeline* timeline, const Target& target);\n\n  Session& current_session() {\n    return timeline_ ? timeline_->current_session() :\n        *emergency_debug_session;\n  }\n  ReplayTask* require_timeline_current_task();\n\n  void dispatch_regs_request(const Registers& regs,\n                             const ExtraRegisters& extra_regs);\n  enum ReportState { REPORT_NORMAL, REPORT_THREADS_DEAD };\n  void maybe_intercept_mem_request(Task* target, const GdbRequest& req,\n                                   std::vector<uint8_t>* result);\n  /**\n   * Process the single debugger request |req| inside the session |session|.\n   *\n   * Callers should implement any special semantics they want for\n   * particular debugger requests before calling this helper, to do\n   * generic processing.\n   */\n  void dispatch_debugger_request(Session& session, const GdbRequest& req,\n                                 ReportState state);\n  void activate_debugger();\n  void restart_session(const GdbRequest& req);\n  GdbRequest process_debugger_requests(ReportState state = REPORT_NORMAL);\n  enum ContinueOrStop { CONTINUE_DEBUGGING, STOP_DEBUGGING };\n  bool detach_or_restart(const GdbRequest& req, ContinueOrStop* s);\n  ContinueOrStop handle_exited_state(GdbRequest& last_resume_request);\n  ContinueOrStop debug_one_step(GdbRequest& last_resume_request);\n  /**\n   * If 'req' is a reverse-singlestep, try to obtain the resulting state\n   * directly from ReplayTimeline's mark database. If that succeeds,\n   * report the singlestep break status to gdb and process any get-registers\n   * requests. Repeat until we get a request that isn't reverse-singlestep\n   * or get-registers, returning that request in 'req'.\n   * During reverse-next commands, gdb tends to issue a series of\n   * reverse-singlestep/get-registers pairs, and this makes those much\n   * more efficient by avoiding having to actually reverse-singlestep the\n   * session.\n   */\n  void try_lazy_reverse_singlesteps(GdbRequest& req);\n\n  /**\n   * Process debugger requests made in |diversion_session| until action needs\n   * to be taken by the caller (a resume-execution request is received).\n   * The received request is returned through |req|.\n   * Returns true if diversion should continue, false if it should end.\n   */\n  bool diverter_process_debugger_requests(DiversionSession& diversion_session,\n                                          uint32_t& diversion_refcount,\n                                          GdbRequest* req);\n  /**\n   * Create a new diversion session using |replay| session as the\n   * template.  The |replay| session isn't mutated.\n   *\n   * Execution begins in the new diversion session under the control of\n   * |dbg| starting with initial thread target |task|.  The diversion\n   * session ends at the request of |dbg|, and |divert| returns the first\n   * request made that wasn't handled by the diversion session.  That\n   * is, the first request that should be handled by |replay| upon\n   * resuming execution in that session.\n   */\n  GdbRequest divert(ReplaySession& replay);\n\n  /**\n   * If |break_status| indicates a stop that we should report to gdb,\n   * report it. |req| is the resume request that generated the stop.\n   */\n  void maybe_notify_stop(const Session& session,\n                         const GdbRequest& req,\n                         const BreakStatus& break_status);\n\n  void notify_stop_internal(const Session& session,\n                            ExtendedTaskId which, int sig,\n                            const std::string& reason = std::string());\n\n  /**\n   * Return the checkpoint stored as |checkpoint_id| or nullptr if there\n   * isn't one.\n   */\n  ReplaySession::shr_ptr get_checkpoint(int checkpoint_id);\n\n  /**\n   * Handle GDB file open requests. If we can serve this read request, add\n   * an entry to `files` with the file contents and return our internal\n   * file descriptor.\n   */\n  int open_file(Session& session, Task *continue_task, const std::string& file_name);\n\n  /**\n   * Allocates debugger-owned memory region.\n   * We pretend this memory exists in all sessions, but it actually only\n   * exists in diversion sessions. When there is no diversion session,\n   * we divert reads and writes to it to our internal storage.\n   * During a diversion, the diversion session is the source of truth\n   * and all reads and writes should go directly to the session.\n   * If the diversion exits normally we update the memory values from\n   * the diversion session, but if it crashes, we don't.\n   */\n  remote_ptr<void> allocate_debugger_mem(ThreadGroupUid tguid,\n                                         size_t size, int prot);\n  /**\n   * Frees a debugger-owned memory region. Returns 0\n   * if there is no such region, otherwise returns the size\n   * of the freed region.\n   */\n  size_t free_debugger_mem(ThreadGroupUid tguid, remote_ptr<void> addr);\n  // If the address is in debugger memory, return its size and prot and\n  // return true.\n  // Otherwise returns false.\n  bool debugger_mem_region(ThreadGroupUid tguid, remote_ptr<void> addr, int* prot,\n                           MemoryRange* mem_range);\n  // Read from debugger memory. Returns false if the range is not in debugger memory.\n  // Fatal error if the range partially overlaps debugger memory.\n  // Don't call this if the session is a diversion, read from the diversion directly\n  // since it has the values.\n  bool read_debugger_mem(ThreadGroupUid tguid, MemoryRange range, uint8_t* values);\n  // Write to debugger memory. Returns false if the range is not in debugger memory.\n  // Fatal error if the range partially overlaps debugger memory.\n  // Don't call this if the session is a diversion, write to the diversion directly\n  // since it has the values.\n  bool write_debugger_mem(ThreadGroupUid tguid, MemoryRange range, const uint8_t* values);\n  // Add mappings of the debugger memory to the session.\n  // If `addr` is null then all mappings are added, otherwise only mappings\n  // at that address are added.\n  void map_debugger_mem(DiversionSession& session, ThreadGroupUid tguid,\n                        remote_ptr<void> addr);\n  // Unmap mapping of a specific debugger memory region from the session.\n  void unmap_debugger_mem(DiversionSession& session,\n                          ThreadGroupUid tguid, remote_ptr<void> addr,\n                          size_t size);\n  // Read back the contents of all debugger memory regions from the session.\n  void read_back_debugger_mem(DiversionSession& session);\n\n  // Get the last GdbServerRegister for \"this\" arch. If it hasn't be determined, configure it.\n  const vector<GdbServerRegister>& target_registers(SupportedArch arch);\n\n  // dbg is never null.\n  std::unique_ptr<GdbServerConnection> dbg;\n  // The ThreadGroupUid of the task being debugged.\n  // This should really not be needed and should go away so we can debug\n  // multiple processes.\n  ThreadGroupUid debuggee_tguid;\n  // What we were trying to reach.\n  Target target;\n  // ThreadDb for debuggee ThreadGroup\n#ifdef PROC_SERVICE_H\n  std::unique_ptr<ThreadDb> thread_db;\n#endif\n  // The last continued task.\n  ExtendedTaskId last_continue_task;\n  // The last queried task.\n  ExtendedTaskId last_query_task;\n  FrameTime final_event;\n  // siginfo for last notified stop.\n  siginfo_t stop_siginfo;\n  bool in_debuggee_end_state;\n  // True when a restart was attempted but didn't succeed.\n  bool failed_restart;\n  // Set to true when the user has interrupted replaying to a target event.\n  volatile bool* stop_replaying_to_target;\n  // True when a DREQ_INTERRUPT has been received but not handled, or when\n  // we've restarted and want the first continue to be interrupted immediately.\n  bool interrupt_pending;\n  // True when a user has run to exit before attaching the debugger.\n  bool exit_sigkill_pending;\n\n  // Exactly one of the following two pointers is null.\n  ReplayTimeline* timeline_;\n  Session* emergency_debug_session;\n\n  struct Checkpoint {\n    enum Explicit { EXPLICIT, NOT_EXPLICIT };\n    Checkpoint(ReplayTimeline& timeline, ExtendedTaskId last_continue_task, Explicit e,\n               const std::string& where)\n        : last_continue_task(last_continue_task), is_explicit(e), where(where) {\n      if (e == EXPLICIT) {\n        mark = timeline.add_explicit_checkpoint();\n      } else {\n        mark = timeline.mark();\n      }\n    }\n    Checkpoint() : is_explicit(NOT_EXPLICIT) {}\n    ReplayTimeline::Mark mark;\n    ExtendedTaskId last_continue_task;\n    Explicit is_explicit;\n    std::string where;\n  };\n  // |debugger_restart_mark| is the point where we will restart from with\n  // a no-op debugger \"run\" command.\n  Checkpoint debugger_restart_checkpoint;\n\n  // gdb checkpoints, indexed by ID\n  std::map<int64_t, Checkpoint> checkpoints;\n\n  // Set of symbols to look up, for qSymbol.\n  std::set<std::string> symbols;\n  // Iterator into |symbols|.\n  std::set<std::string>::iterator symbols_iter;\n\n  // Contents of opened files. Maps our internal file descriptor to a real\n  // file descriptor. Exposing our real file descriptor values is probably a\n  // bad idea.\n  std::map<int, ScopedFd> files;\n  std::map<int, FileId> memory_files;\n  // The pid for gdb's last vFile:setfs\n  pid_t file_scope_pid;\n\n  // LLDB wants to allocate memory in tracees. Instead of modifying tracee ReplaySessions,\n  // we store the memory outside the session and copy it into DiversionSessions as needed.\n  struct DebuggerMemRegion {\n    std::vector<uint8_t> values;\n    int prot;\n  };\n  struct DebuggerMem {\n    std::map<MemoryRange, DebuggerMemRegion, MappingComparator> regions;\n    // Virtual memory ranges that are never used by any tracee, also excluding\n    // memory used by debugger_mem and guard pages.\n    ReplaySession::MemoryRanges free_memory;\n    bool did_get_accurate_free_memory;\n  };\n  // Maps from tgid to the DebuggerMem.\n  std::unordered_map<ThreadGroupUid, DebuggerMem> debugger_mem;\n\n  struct SavedRegisters {\n    Registers regs;\n    ExtraRegisters extra_regs;\n  };\n  std::unordered_map<int, SavedRegisters> saved_register_states;\n\n  vector<GdbServerRegister> register_description;\n};\n\n} // namespace rr\n\n#endif /* RR_GDB_SERVER_H_ */\n"
  },
  {
    "path": "src/GdbServerConnection.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define REVERSE_EXECUTION\n\n/**\n * Much of this implementation is based on the documentation at\n *\n * http://sourceware.org/gdb/onlinedocs/gdb/Packets.html\n * See also\n * https://github.com/llvm/llvm-project/blob/main/lldb/docs/lldb-gdb-remote.txt\n */\n\n#include \"GdbServerConnection.h\"\n\n#include <errno.h>\n#include <inttypes.h>\n#include <limits.h>\n#include <poll.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <sys/mman.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include <iomanip>\n#include <sstream>\n#include <vector>\n\n#include \"DebuggerExtensionCommandHandler.h\"\n#include \"ReplaySession.h\"\n#include \"ScopedFd.h\"\n#include \"TargetDescription.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic const char INTERRUPT_CHAR = '\\x03';\n\n#define UNHANDLED_REQ()                                                        \\\n  write_packet(\"\");                                                            \\\n  LOG(info)\n\nconst GdbThreadId GdbThreadId::ANY(0, 0);\nconst GdbThreadId GdbThreadId::ALL(-1, -1);\n\n#ifdef DEBUG\nstatic bool request_needs_immediate_response(const GdbRequest* req) {\n  switch (req->type) {\n    case DREQ_NONE:\n    case DREQ_CONT:\n      return false;\n    default:\n      return true;\n  }\n}\n#endif\n\nGdbServerConnection::GdbServerConnection(ThreadGroupUid tguid,\n  DebuggerType debugger_type, const Features& features)\n    : tguid(tguid),\n      cpu_features_(0),\n      debugger_type(debugger_type),\n      no_ack(false),\n      features_(features),\n      connection_alive_(true),\n      multiprocess_supported_(false),\n      hwbreak_supported_(false),\n      swbreak_supported_(false),\n      list_threads_in_stop_reply_(false),\n      target_description(nullptr) {\n#ifndef REVERSE_EXECUTION\n  features_.reverse_execution = false;\n#endif\n}\n\nstatic uint32_t get_cpu_features(SupportedArch arch) {\n  uint32_t cpu_features;\n  switch (arch) {\n    case x86:\n    case x86_64: {\n      cpu_features = arch == x86_64 ? GdbServerConnection::CPU_X86_64 : 0;\n      unsigned int AVX_cpuid_flags = AVX_FEATURE_FLAG | OSXSAVE_FEATURE_FLAG;\n      auto cpuid_data = cpuid(CPUID_GETEXTENDEDFEATURES, 0);\n      if ((cpuid_data.ecx & PKU_FEATURE_FLAG) == PKU_FEATURE_FLAG) {\n        // PKU (Skylake) implies AVX (Sandy Bridge).\n        cpu_features |= GdbServerConnection::CPU_PKU;\n      }\n\n      if ((cpuid_data.ebx & AVX_512_FOUNDATION_FLAG) == AVX_512_FOUNDATION_FLAG) {\n        cpu_features |= GdbServerConnection::CPU_AVX512 | GdbServerConnection::CPU_AVX;\n        break;\n      }\n\n      cpuid_data = cpuid(CPUID_GETFEATURES, 0);\n      // We're assuming here that AVX support on the system making the recording\n      // is the same as the AVX support during replay. But if that's not true,\n      // rr is totally broken anyway.\n      if ((cpuid_data.ecx & AVX_cpuid_flags) == AVX_cpuid_flags) {\n        cpu_features |= GdbServerConnection::CPU_AVX;\n      }\n      break;\n    }\n    case aarch64:\n      cpu_features = GdbServerConnection::CPU_AARCH64;\n      break;\n    default:\n      FATAL() << \"Unknown architecture\";\n      return 0;\n  }\n\n  LOG(debug) << \"cpu features \" << std::hex << cpu_features;\n\n  return cpu_features;\n}\n\nunique_ptr<GdbServerConnection> GdbServerConnection::await_connection(\n    Task* t, ScopedFd& listen_fd,  DebuggerType debugger_type,\n    const GdbServerConnection::Features& features) {\n  auto dbg = unique_ptr<GdbServerConnection>(\n    new GdbServerConnection(t->thread_group()->tguid(), debugger_type, features));\n  dbg->set_cpu_features(t->arch());\n  dbg->await_debugger(listen_fd);\n  return dbg;\n}\n\nvoid GdbServerConnection::await_debugger(ScopedFd& listen_fd) {\n  sock_fd = ScopedFd(accept(listen_fd, nullptr, nullptr));\n  // We might restart this debugging session, so don't set the\n  // socket fd CLOEXEC.\n}\n\n/**\n * Poll for data to or from gdb, waiting |timeoutMs|.  0 means \"don't\n * wait\", and -1 means \"wait forever\".  Return true if data is ready.\n */\nstatic bool poll_socket(const ScopedFd& sock_fd, short events, int timeoutMs) {\n  struct pollfd pfd;\n  memset(&pfd, 0, sizeof(pfd));\n  pfd.fd = sock_fd;\n  pfd.events = events;\n\n  int ret = poll(&pfd, 1, timeoutMs);\n  if (ret < 0 && errno != EINTR) {\n    LOG(info) << \"debugger socket has been closed\";\n  }\n  return ret > 0;\n}\n\nstatic bool poll_incoming(const ScopedFd& sock_fd, int timeoutMs) {\n  return poll_socket(sock_fd, POLLIN /* TODO: |POLLERR */, timeoutMs);\n}\n\nstatic void poll_outgoing(const ScopedFd& sock_fd, int timeoutMs) {\n  poll_socket(sock_fd, POLLOUT /* TODO: |POLLERR */, timeoutMs);\n}\n\n/**\n * read() incoming data exactly one time, successfully.  May block.\n */\nvoid GdbServerConnection::read_data_once() {\n  ssize_t nread;\n  /* Wait until there's data, instead of busy-looping on\n   * EAGAIN. */\n  poll_incoming(sock_fd, -1 /* wait forever */);\n  uint8_t buf[4096];\n  nread = read(sock_fd, buf, sizeof(buf));\n  if (nread <= 0) {\n    LOG(info) << \"Could not read data from debugger socket, \"\n                 \"marking connection as closed\";\n    connection_alive_ = false;\n  } else {\n    inbuf.insert(inbuf.end(), buf, buf + nread);\n  }\n}\n\nvoid GdbServerConnection::write_flush() {\n  size_t write_index = 0;\n\n  outbuf.push_back(0);\n  LOG(debug) << \"write_flush: '\" << outbuf.data() << \"'\";\n  outbuf.pop_back();\n\n  while (write_index < outbuf.size()) {\n    ssize_t nwritten;\n\n    poll_outgoing(sock_fd, -1 /*wait forever*/);\n    nwritten = write(sock_fd, outbuf.data() + write_index,\n                     outbuf.size() - write_index);\n    if (nwritten < 0) {\n      LOG(info) << \"Could not write data to debugger socket, \"\n                   \"marking connection as closed\";\n      connection_alive_ = false;\n      outbuf.clear();\n      return;\n    } else {\n      write_index += nwritten;\n    }\n  }\n  outbuf.clear();\n}\n\nvoid GdbServerConnection::write_data_raw(const uint8_t* data, ssize_t len) {\n  outbuf.insert(outbuf.end(), data, data + len);\n}\n\nvoid GdbServerConnection::write_hex(unsigned long hex) {\n  char buf[32];\n  size_t len;\n\n  len = snprintf(buf, sizeof(buf) - 1, \"%02lx\", hex);\n  write_data_raw((uint8_t*)buf, len);\n}\n\nvoid GdbServerConnection::write_packet_bytes(const uint8_t* data, size_t num_bytes) {\n  uint8_t checksum;\n  size_t i;\n\n  write_data_raw((uint8_t*)\"$\", 1);\n  for (i = 0, checksum = 0; i < num_bytes; ++i) {\n    checksum += data[i];\n  }\n  write_data_raw((uint8_t*)data, num_bytes);\n  write_data_raw((uint8_t*)\"#\", 1);\n  write_hex(checksum);\n}\n\nvoid GdbServerConnection::write_packet(const char* data) {\n  return write_packet_bytes((const uint8_t*)data, strlen(data));\n}\n\nvoid GdbServerConnection::write_binary_packet(const char* pfx, const uint8_t* data,\n                                              ssize_t num_bytes) {\n  ssize_t pfx_num_chars = strlen(pfx);\n  vector<uint8_t> buf;\n  buf.resize(2 * num_bytes + pfx_num_chars + 1);\n  ssize_t buf_num_bytes = 0;\n  int i;\n\n  memcpy((char*)buf.data(), pfx, pfx_num_chars);\n  buf_num_bytes += pfx_num_chars;\n\n  for (i = 0; i < num_bytes; ++i) {\n    uint8_t b = data[i];\n\n    if (buf_num_bytes + 2 > ssize_t(buf.size())) {\n      break;\n    }\n    switch (b) {\n      case '#':\n      case '$':\n      case '}':\n      case '*':\n        buf.data()[buf_num_bytes++] = '}';\n        buf.data()[buf_num_bytes++] = b ^ 0x20;\n        break;\n      default:\n        buf.data()[buf_num_bytes++] = b;\n        break;\n    }\n  }\n\n  LOG(debug) << \" ***** NOTE: writing binary data, upcoming debug output may \"\n                \"be truncated\";\n  return write_packet_bytes(buf.data(), buf_num_bytes);\n}\n\nstatic string string_to_hex(const string& s) {\n  stringstream sstr;\n  for (char ch : s) {\n    char buf[16];\n    sprintf(buf, \"%02x\", ch);\n    sstr << buf;\n  }\n  return sstr.str();\n}\n\nvoid GdbServerConnection::write_hex_bytes_packet(const char* prefix,\n                                           const uint8_t* bytes, size_t len) {\n  if (prefix[0] == '\\0' && 0 == len) {\n    write_packet(\"\");\n    return;\n  }\n\n  ssize_t pfx_num_chars = strlen(prefix);\n  vector<char> buf;\n  buf.resize(pfx_num_chars + 2 * len + 1);\n  memcpy(buf.data(), prefix, pfx_num_chars);\n  for (size_t i = 0; i < len; ++i) {\n    unsigned long b = bytes[i];\n    snprintf(&buf.data()[pfx_num_chars + 2 * i], 3, \"%02lx\", b);\n  }\n  write_packet(buf.data());\n}\n\nvoid GdbServerConnection::write_hex_bytes_packet(const uint8_t* bytes, size_t len) {\n  write_hex_bytes_packet(\"\", bytes, len);\n}\n\nstatic void parser_assert(bool cond) {\n  if (!cond) {\n    fputs(\"Failed to parse debugger request\\n\", stderr);\n    DEBUG_ASSERT(false);\n    exit(2);\n  }\n}\n\nstatic string decode_ascii_encoded_hex_str(const char* encoded) {\n  ssize_t enc_len = strlen(encoded);\n  parser_assert(enc_len % 2 == 0);\n  string str;\n  for (int i = 0; i < enc_len / 2; ++i) {\n    char enc_byte[] = { encoded[2 * i], encoded[2 * i + 1], '\\0' };\n    char* endp;\n    int c = strtol(enc_byte, &endp, 16);\n    parser_assert(c < 128);\n    str += static_cast<char>(c);\n  }\n  return str;\n}\n\nbool GdbServerConnection::skip_to_packet_start() {\n  ssize_t end = -1;\n  /* XXX we want memcspn() here ... */\n  for (size_t i = 0; i < inbuf.size(); ++i) {\n    if (inbuf[i] == '$' || inbuf[i] == INTERRUPT_CHAR) {\n      end = i;\n      break;\n    }\n  }\n\n  if (end < 0) {\n    /* Discard all read bytes, which we don't care\n     * about. */\n    inbuf.clear();\n    return false;\n  }\n  /* Discard bytes up to start-of-packet. */\n  inbuf.erase(inbuf.begin(), inbuf.begin() + end);\n\n  parser_assert(1 <= inbuf.size());\n  parser_assert('$' == inbuf[0] || INTERRUPT_CHAR == inbuf[0]);\n  return true;\n}\n\nbool GdbServerConnection::sniff_packet() {\n  if (skip_to_packet_start()) {\n    /* We've already seen a (possibly partial) packet. */\n    return true;\n  }\n  parser_assert(inbuf.empty());\n  return poll_incoming(sock_fd, 0 /*don't wait*/);\n}\n\nvoid GdbServerConnection::read_packet() {\n  /* Read and discard bytes until we see the start of a\n   * packet.\n   *\n   * NB: we're ignoring \"+/-\" responses from gdb.  There doesn't\n   * seem to be any sane reason why we would send a damaged\n   * packet to gdb over TCP, then see a \"-\" reply from gdb and\n   * somehow magically fix our bug that led to the malformed\n   * packet in the first place.\n   */\n  while (!skip_to_packet_start() && connection_alive_) {\n    read_data_once();\n  }\n\n  if (!connection_alive_) {\n    return;\n  }\n\n  if (inbuf[0] == INTERRUPT_CHAR) {\n    /* Interrupts are kind of an ugly duckling in the gdb\n     * protocol ... */\n    packetend = 1;\n    return;\n  }\n\n  /* Read until we see end-of-packet. */\n  size_t checkedlen = 0;\n  while (true) {\n    uint8_t* p = (uint8_t*)memchr(inbuf.data() + checkedlen, '#',\n                                  inbuf.size() - checkedlen);\n    if (p) {\n      packetend = p - inbuf.data();\n      break;\n    }\n    checkedlen = inbuf.size();\n    read_data_once();\n    if (!connection_alive_) {\n      return;\n    }\n  }\n\n  /* NB: we're ignoring the gdb packet checksums here too.  If\n   * gdb is corrupted enough to garble a checksum over TCP, it's\n   * not really clear why asking for the packet again might make\n   * the bug go away. */\n  parser_assert('$' == inbuf[0] && packetend < inbuf.size());\n\n  /* Acknowledge receipt of the packet. */\n  if (!no_ack) {\n    write_data_raw((uint8_t*)\"+\", 1);\n    write_flush();\n  }\n}\n\nstatic void read_hex_data(const char* payload, const char* payload_end,\n                          vector<uint8_t>& data) {\n  data.clear();\n  char buf[3] = { 0, 0, 0 };\n  while (payload + 2 <= payload_end) {\n    buf[0] = *payload++;\n    buf[1] = *payload++;\n    char* endp;\n    int value = strtol(buf, &endp, 16);\n    parser_assert(endp == buf + 2);\n    data.push_back(value);\n  }\n}\n\nstatic void read_binary_data(const uint8_t* payload, const uint8_t* payload_end,\n                             vector<uint8_t>& data) {\n  data.clear();\n  while (payload < payload_end) {\n    uint8_t b = *payload++;\n    if ('}' == b) {\n      parser_assert(payload < payload_end);\n      b = 0x20 ^ *payload++;\n    }\n    data.push_back(b);\n  }\n}\n\n/**\n * Parse and return a gdb thread-id from |str|.  |endptr| points to\n * the character just after the last character in the thread-id.  It\n * may be nullptr.\n */\nstatic GdbThreadId parse_threadid(const char* str, char** endptr) {\n  GdbThreadId t;\n  char* endp;\n  bool multiprocess = false;\n\n  if ('p' == *str) {\n    multiprocess = true;\n    ++str;\n  }\n  t.pid = strtol(str, &endp, 16);\n  parser_assert(endp);\n\n  /* terminators (single process, no PID or TID, depending on 'p' prefix) */ \n  if (*endp == '\\0' || *endp == ';' || *endp == ',') {\n    if (multiprocess) {\n      t.tid = -1;\n    } else {\n      t.tid = t.pid;\n      t.pid = -1;\n    }\n  /* multiprocess syntax \"<pid>.<tid>\" */\n  } else if (*endp == '.') {\n    str = endp + 1;\n    t.tid = strtol(str, &endp, 16);\n  }\n\n  parser_assert(*endp == '\\0' || *endp == ';' || *endp == ',');\n\n  *endptr = endp;\n  return t;\n}\n\nvoid GdbServerConnection::write_xfer_response(const void* data, size_t size,\n                                        uint64_t offset, uint64_t len) {\n  if (offset > size) {\n    write_packet(\"E01\");\n    return;\n  }\n  if (offset == size) {\n    write_packet(\"l\");\n    return;\n  }\n  if (offset + len < size) {\n    write_binary_packet(\"m\", static_cast<const uint8_t*>(data) + offset, len);\n    return;\n  }\n  write_binary_packet(\"l\", static_cast<const uint8_t*>(data) + offset,\n                      size - offset);\n}\n\nstatic string read_target_desc(const char* file_name) {\n#ifdef __BIONIC__\n  const char* share_path = \"usr/share/rr/\";\n#else\n  const char* share_path = \"share/rr/\";\n#endif\n  string path = resource_path() + share_path + string(file_name);\n  stringstream ss;\n  FILE* f = fopen(path.c_str(), \"r\");\n  if (f == NULL) {\n      FATAL() << \"Failed to load target description file: \" << file_name;\n  }\n  while (true) {\n    int ch = getc(f);\n    if (ch == EOF) {\n      break;\n    }\n    ss << (char)ch;\n  }\n  fclose(f);\n  return ss.str();\n}\n\nbool GdbServerConnection::xfer(const char* name, char* args) {\n  const char* mode = args;\n  args = strchr(args, ':');\n  parser_assert(args);\n  *args++ = '\\0';\n\n  if (strcmp(mode, \"read\") && strcmp(mode, \"write\")) {\n    write_packet(\"\");\n    return false;\n  }\n\n  const char* annex = args;\n  args = strchr(args, ':');\n  parser_assert(args);\n  *args++ = '\\0';\n\n  uint64_t offset = strtoul(args, &args, 16);\n\n  uint64_t len = 0;\n  if (!strcmp(mode, \"read\")) {\n    parser_assert(',' == *args++);\n    len = strtoul(args, &args, 16);\n    parser_assert(!*args);\n  } else {\n    parser_assert(*args == ':');\n    ++args;\n  }\n\n  LOG(debug) << \"debugger asks us to transfer \" << name << \" mode=\" << mode\n             << \", annex=\" << annex << \", offset=\" << offset << \" len=\" << len;\n\n  if (!strcmp(name, \"auxv\")) {\n    if (strcmp(annex, \"\")) {\n      write_packet(\"E00\");\n      return false;\n    }\n    if (strcmp(mode, \"read\")) {\n      write_packet(\"\");\n      return false;\n    }\n\n    req = GdbRequest(DREQ_GET_AUXV);\n    req.target = query_thread;\n    // XXX handle offset/len here!\n    return true;\n  }\n\n  if (!strcmp(name, \"exec-file\")) {\n    if (strcmp(mode, \"read\")) {\n      write_packet(\"\");\n      return false;\n    }\n\n    req = GdbRequest(DREQ_GET_EXEC_FILE);\n    req.target.pid = req.target.tid = strtoul(annex, nullptr, 16);\n    // XXX handle offset/len here!\n    return true;\n  }\n\n  if (!strcmp(name, \"siginfo\")) {\n    if (strcmp(annex, \"\")) {\n      write_packet(\"E00\");\n      return false;\n    }\n    if (!strcmp(mode, \"read\")) {\n      req = GdbRequest(DREQ_READ_SIGINFO);\n      req.target = query_thread;\n      req.mem().addr = offset;\n      req.mem().len = len;\n      return true;\n    }\n\n    req = GdbRequest(DREQ_WRITE_SIGINFO);\n    req.target = query_thread;\n    return true;\n  }\n\n  if (!strcmp(name, \"features\")) {\n    if (strcmp(mode, \"read\")) {\n      write_packet(\"\");\n      return false;\n    }\n\n    const auto desc = strcmp(annex, \"\") && strcmp(annex, \"target.xml\") ? read_target_desc(annex) : target_description->to_xml();\n    write_xfer_response(desc.c_str(), desc.size(), offset, len);\n    return false;\n  }\n\n  write_packet(\"\");\n  return false;\n}\n\n/**\n * Format |value| into |buf| in the manner gdb expects.  |buf| must\n * point at a buffer with at least |1 + 2*DBG_MAX_REG_SIZE| bytes\n * available.  Fewer bytes than that may be written, but |buf| is\n * guaranteed to be null-terminated.\n */\nstatic size_t print_reg_value(const GdbServerRegisterValue& reg, char* buf) {\n  parser_assert(reg.size <= GdbServerRegisterValue::MAX_SIZE);\n  if (reg.defined) {\n    /* gdb wants the register value in native endianness.\n     * reg.value read in native endianness is exactly that.\n     */\n    for (size_t i = 0; i < reg.size; ++i) {\n      snprintf(&buf[2 * i], 3, \"%02lx\", (unsigned long)reg.value[i]);\n    }\n  } else {\n    for (size_t i = 0; i < reg.size; ++i) {\n      strcpy(&buf[2 * i], \"xx\");\n    }\n  }\n  return reg.size * 2;\n}\n\n/**\n * Read the encoded register value in |strp| into |reg|.  |strp| may\n * be mutated.\n */\nstatic void read_reg_value(char** strp, GdbServerRegisterValue* reg) {\n  char* str = *strp;\n\n  if ('x' == str[0]) {\n    reg->defined = false;\n    reg->size = 0;\n    return;\n  }\n\n  reg->defined = true;\n  reg->size = strlen(str) / 2;\n  for (size_t i = 0; i < reg->size; ++i) {\n    char tmp = str[2];\n    str[2] = '\\0';\n\n    reg->value[i] = strtoul(str, &str, 16);\n    parser_assert('\\0' == *str);\n\n    str[0] = tmp;\n  }\n\n  *strp = str;\n}\n\nbool GdbServerConnection::query(char* payload) {\n  const char* name;\n  char* args;\n\n  args = strchr(payload, ':');\n  if (args) {\n    *args++ = 0;\n  }\n  name = payload;\n\n  if (strstr(name, \"RRCmd\") == name) {\n    LOG(debug) << \"debugger requests rr cmd: \" << name;\n    req = GdbRequest(DREQ_RR_CMD);\n    parser_assert(args && *args);\n    char* endp = strchr(args, ':');\n    parser_assert(endp);\n    *endp = 0;\n    req.rr_cmd_.name = string(args);\n    args = endp + 1;\n    req.rr_cmd_.target_tid = strtol(args, &endp, 10);\n    if (*endp) {\n      parser_assert(*endp == ':');\n      args = endp + 1;\n      while (args) {\n        endp = strchr(args, ':');\n        if (endp) {\n          *endp++ = 0;\n        }\n        req.rr_cmd_.args.emplace_back(args);\n        args = endp;\n      }\n    }\n    return true;\n  }\n  if (!strcmp(name, \"C\")) {\n    LOG(debug) << \"debugger requests current thread ID\";\n    req = GdbRequest(DREQ_GET_CURRENT_THREAD);\n    return true;\n  }\n  if (!strcmp(name, \"Attached\")) {\n    LOG(debug) << \"debugger asks if this is a new or existing process\";\n    /* Tell gdb this is an existing process; it might be\n     * (see emergency_debug()). */\n    write_packet(\"1\");\n    return false;\n  }\n  if (!strcmp(name, \"fThreadInfo\")) {\n    LOG(debug) << \"debugger asks for thread list\";\n    req = GdbRequest(DREQ_GET_THREAD_LIST);\n    return true;\n  }\n  if (!strcmp(name, \"sThreadInfo\")) {\n    write_packet(\"l\"); /* \"end of list\" */\n    return false;\n  }\n  if (!strcmp(name, \"GetTLSAddr\")) {\n    LOG(debug) << \"debugger asks for TLS addr\";\n    req = GdbRequest(DREQ_TLS);\n    req.target = parse_threadid(args, &args);\n    parser_assert(*args == ',');\n    ++args;\n    size_t offset = strtoul(args, &args, 16);\n    parser_assert(*args == ',');\n    ++args;\n    remote_ptr<void> load_module = strtoul(args, &args, 16);\n    parser_assert(*args == '\\0');\n    req.tls().offset = offset;\n    req.tls().load_module = load_module;\n    return true;\n  }\n  if (!strcmp(name, \"Offsets\")) {\n    LOG(debug) << \"debugger asks for section offsets\";\n    req = GdbRequest(DREQ_GET_OFFSETS);\n    req.target = query_thread;\n    return true;\n  }\n  if (!strcmp(name, \"Supported\")) {\n    /* TODO process these */\n    LOG(debug) << \"debugger supports \" << args;\n\n    multiprocess_supported_ = strstr(args, \"multiprocess+\") != nullptr;\n    hwbreak_supported_ = strstr(args, \"hwbreak+\") != nullptr;\n    swbreak_supported_ = strstr(args, \"swbreak+\") != nullptr;\n\n    stringstream supported;\n    // Encourage gdb to use very large packets since we support any packet size\n    supported << \"PacketSize=1048576\"\n                 \";QStartNoAckMode+\"\n                 \";qXfer:features:read+\"\n                 \";qXfer:auxv:read+\"\n                 \";qXfer:exec-file:read+\"\n                 \";qXfer:siginfo:read+\"\n                 \";qXfer:siginfo:write+\"\n                 \";multiprocess+\"\n                 \";hwbreak+\"\n                 \";swbreak+\"\n                 \";ConditionalBreakpoints+\"\n                 \";vContSupported+\"\n                 \";QPassSignals+\";\n    if (features().reverse_execution) {\n      supported << \";ReverseContinue+\"\n                   \";ReverseStep+\";\n    }\n    write_packet(supported.str().c_str());\n    return false;\n  }\n  if (!strcmp(name, \"Symbol\")) {\n#ifdef PROC_SERVICE_H\n    LOG(debug) << \"debugger is ready for symbol lookups\";\n    const char* colon = strchr(args, ':');\n    parser_assert(colon != nullptr);\n    req = GdbRequest(DREQ_QSYMBOL);\n    if (*args == ':') {\n      req.sym().has_address = false;\n    } else {\n      req.sym().has_address = true;\n      req.sym().address = strtoul(args, &args, 16);\n    }\n    parser_assert(*args == ':');\n    ++args;\n    req.sym().name = decode_ascii_encoded_hex_str(args);\n    return true;\n#else\n    LOG(debug) << \"debugger is ready for symbol lookups, but we don't support them\";\n    write_packet(\"\");\n    return false;\n#endif\n  }\n  if (strstr(name, \"ThreadExtraInfo\") == name) {\n    // ThreadExtraInfo is a special snowflake that\n    // delimits its args with ','.\n    parser_assert(!args);\n    args = payload;\n    args = 1 + strchr(args, ',' /*sic*/);\n\n    req = GdbRequest(DREQ_GET_THREAD_EXTRA_INFO);\n    req.target = parse_threadid(args, &args);\n    parser_assert('\\0' == *args);\n    return true;\n  }\n  if (!strcmp(name, \"TStatus\")) {\n    LOG(debug) << \"debugger asks for trace status\";\n    /* XXX from the docs, it appears that we should reply\n     * with \"T0\" here.  But if we do, gdb keeps bothering\n     * us with trace queries.  So pretend we don't know\n     * what it's talking about. */\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"Xfer\")) {\n    name = args;\n    args = strchr(args, ':');\n    parser_assert(args);\n    *args++ = '\\0';\n\n    return xfer(name, args);\n  }\n  if (!strcmp(name, \"Search\")) {\n    name = args;\n    args = strchr(args, ':');\n    if (args) {\n      *args++ = '\\0';\n    }\n    if (!strcmp(name, \"memory\") && args) {\n      req = GdbRequest(DREQ_SEARCH_MEM_BINARY);\n      req.target = query_thread;\n      req.mem().addr = strtoul(args, &args, 16);\n      parser_assert(';' == *args++);\n      req.mem().len = strtoull(args, &args, 16);\n      parser_assert(';' == *args++);\n      read_binary_data((const uint8_t*)args, inbuf.data() + packetend,\n                       req.mem().data);\n\n      LOG(debug) << \"debugger searching memory (addr=\" << HEX(req.mem().addr)\n                 << \", len=\" << req.mem().len << \")\";\n      return true;\n    }\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"MemoryRegionInfo\") && args &&\n      debugger_type == DebuggerType::LLDB) {\n    req = GdbRequest(DREQ_MEM_INFO);\n    req.target = query_thread;\n    req.mem().addr = strtoul(args, &args, 16);\n    parser_assert(!*args);\n    req.mem().len = 1;\n    LOG(debug) << \"debugger requesting mem info (addr=\"\n        << HEX(req.mem().addr) << \")\";\n    return true;\n  }\n\n  // Packets that we intentionally don't support\n\n  if (!strcmp(name, \"P\")) {\n    /* The docs say not to use this packet ... */\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"HostInfo\") && debugger_type == DebuggerType::LLDB) {\n    // lldb-server sends a reply like\n    // triple:7838365f36342d2d6c696e75782d676e75;ptrsize:8;distribution_id:6665646f7261;\n    // watchpoint_exceptions_received:after;endian:little;os_version:6.6.13;\n    // os_build:362e362e31332d3230302e666333392e7838365f3634;\n    // os_kernel:233120534d5020505245454d50545f44594e414d494320536174204a616e2032302031383a30333a3238205554432032303234;\n    // hostname:6c6f63616c686f73742e6c6f63616c646f6d61696e\n    // So far there is no benefit for handling it AFAICT.\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"VAttachOrWaitSupported\") && debugger_type == DebuggerType::LLDB) {\n    // We don't handle vAttach and variants.\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"ProcessInfo\") && debugger_type == DebuggerType::LLDB) {\n    // lldb-server sends a reply like\n    // pid:3663df;parent-pid:3663de;real-uid:3e8;real-gid:3e8;effective-uid:3e8;effective-gid:3e8;\n    // triple:7838365f36342d2d6c696e75782d676e75;ostype:linux;endian:little;ptrsize:8\n    // Currently we don't have the parent PID or uids, so we're\n    // not going to handle this.\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"StructuredDataPlugins\") && debugger_type == DebuggerType::LLDB) {\n    // This isn't documented and lldb-server doesn't support it\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"ShlibInfoAddr\") && debugger_type == DebuggerType::LLDB) {\n    // This isn't documented and lldb-server doesn't seem to support it\n    write_packet(\"\");\n    return false;\n  }\n\n  UNHANDLED_REQ() << \"Unhandled debugger query: q\" << name;\n  return false;\n}\n\n// LLDB QThreadSuffixSupported extension\nvoid GdbServerConnection::parse_thread_suffix_threadid(char* payload, GdbThreadId* out) {\n  if (debugger_type != DebuggerType::LLDB) {\n    return;\n  }\n  char* semicolon = strrchr(payload, ';');\n  if (!semicolon) {\n    return;\n  }\n  if (!semicolon[1]) {\n    semicolon[0] = 0;\n    semicolon = strrchr(payload, ';');\n    if (!semicolon) {\n      return;\n    }\n  }\n  if (strncmp(semicolon + 1, \"thread:\", 7)) {\n    return;\n  }\n  char* endptr;\n  *out = parse_threadid(semicolon + 8, &endptr);\n  *semicolon = 0;\n}\n\nbool GdbServerConnection::set_var(char* payload) {\n  GdbThreadId target = query_thread;\n  parse_thread_suffix_threadid(payload, &target);\n\n  char* args = strchr(payload, ':');\n  if (args) {\n    *args++ = '\\0';\n  }\n  const char* name = payload;\n\n  if (!strcmp(name, \"StartNoAckMode\")) {\n    write_packet(\"OK\");\n    no_ack = true;\n    return false;\n  }\n  if (!strncmp(name, \"PassSignals\", sizeof(\"PassSignals\"))) {\n    pass_signals.clear();\n    while (*args != '\\0') {\n      char *next = nullptr;\n      int sig = std::strtol(args, &next, 16);\n      parser_assert(next != nullptr);\n\n      LOG(debug) << \"registered \" << sig << \" by QPassSignal\";\n      pass_signals.insert(sig);\n\n      args = next;\n      if (*args == '\\0') {\n        break;\n      }\n\n      parser_assert(*args == ';');\n      args++;\n    }\n\n    write_packet(\"OK\");\n    return false;\n  }\n  if (!strcmp(name, \"ListThreadsInStopReply\") &&\n      debugger_type == DebuggerType::LLDB) {\n    write_packet(\"OK\");\n    list_threads_in_stop_reply_ = true;\n    return false;\n  }\n\n  if (!strcmp(name, \"ThreadSuffixSupported\") &&\n      debugger_type == DebuggerType::LLDB) {\n    write_packet(\"OK\");\n    return false;\n  }\n  if (!strcmp(name, \"EnableErrorStrings\") &&\n      debugger_type == DebuggerType::LLDB) {\n    // We don't support human-readable error strings.\n    write_packet(\"\");\n    return false;\n  }\n  if (!strcmp(name, \"SaveRegisterState\") &&\n      debugger_type == DebuggerType::LLDB) {\n    req = GdbRequest(DREQ_SAVE_REGISTER_STATE);\n    req.target = target;\n    return true;\n  }\n  if (!strcmp(name, \"RestoreRegisterState\") &&\n      debugger_type == DebuggerType::LLDB) {\n    req = GdbRequest(DREQ_RESTORE_REGISTER_STATE);\n    req.target = target;\n    char* end;\n    req.restore_register_state().state_index = strtol(args, &end, 16);\n    parser_assert(!*end || *end == ';');\n    return true;\n  }\n\n  UNHANDLED_REQ() << \"Unhandled debugger set: Q\" << name;\n  return false;\n}\n\nbool GdbServerConnection::process_underscore(char* payload) {\n  char* args = payload + 1;\n\n  switch (payload[0]) {\n    case 'M': {\n      if (debugger_type != DebuggerType::LLDB) {\n        break;\n      }\n      char* end = nullptr;\n      req = GdbRequest(DREQ_MEM_ALLOC);\n      req.mem_alloc().size = strtol(args, &end, 16);\n      parser_assert(*end == ',');\n      int prot = 0;\n      ++end;\n      if (*end == 'r') {\n        prot |= PROT_READ;\n        ++end;\n      }\n      if (*end == 'w') {\n        prot |= PROT_WRITE;\n        ++end;\n      }\n      if (*end == 'x') {\n        prot |= PROT_EXEC;\n      }\n      req.mem_alloc().prot = prot;\n      return true;\n    }\n    case 'm': {\n      if (debugger_type != DebuggerType::LLDB) {\n        break;\n      }\n      char* end = nullptr;\n      req = GdbRequest(DREQ_MEM_FREE);\n      req.mem_free().address = strtol(args, &end, 16);\n      parser_assert(!*end);\n      return true;\n    }\n    default:\n      break;\n  }\n\n  UNHANDLED_REQ() << \"Unhandled debugger request: _\" << payload;\n  return false;\n}\n\nvoid GdbServerConnection::consume_request() {\n  req = GdbRequest();\n  write_flush();\n}\n\nbool GdbServerConnection::process_bpacket(char* payload) {\n  if (strcmp(payload, \"c\") == 0) {\n    req = GdbRequest(DREQ_CONT);\n    req.cont().run_direction = RUN_BACKWARD;\n    req.cont().actions.push_back(GdbContAction(ACTION_CONTINUE, resume_thread));\n    return true;\n  } else if (strcmp(payload, \"s\") == 0) {\n    req = GdbRequest(DREQ_CONT);\n    req.cont().run_direction = RUN_BACKWARD;\n    req.cont().actions.push_back(GdbContAction(ACTION_STEP, resume_thread));\n    return true;\n  } else {\n    UNHANDLED_REQ() << \"Unhandled debugger bpacket: b\" << payload;\n    return false;\n  }\n}\n\nstatic int gdb_open_flags_to_system_flags(int64_t flags) {\n  int ret;\n  switch (flags & 3) {\n    case 0:\n      ret = O_RDONLY;\n      break;\n    case 1:\n      ret = O_WRONLY;\n      break;\n    case 2:\n      ret = O_RDWR;\n      break;\n    default:\n      parser_assert(false);\n      return 0;\n  }\n  parser_assert(!(flags & ~int64_t(3 | 0x8 | 0x200 | 0x400 | 0x800)));\n  if (flags & 0x8) {\n    ret |= O_APPEND;\n  }\n  if (flags & 0x200) {\n    ret |= O_CREAT;\n  }\n  if (flags & 0x400) {\n    ret |= O_TRUNC;\n  }\n  if (flags & 0x800) {\n    ret |= O_EXCL;\n  }\n  return ret;\n}\n\nbool GdbServerConnection::process_vpacket(char* payload) {\n  const char* name;\n  char* args;\n\n  args = strchr(payload, ';');\n  if (args) {\n    *args++ = '\\0';\n  }\n  name = payload;\n\n  if (!strcmp(\"Cont\", name)) {\n    vector<GdbContAction> actions;\n    bool has_default_action = false;\n    GdbContAction default_action;\n\n    while (args) {\n      char* cmd = args;\n      while (*args != ':' && *args != ';') {\n        if (!*args) {\n          args = nullptr;\n          break;\n        }\n        ++args;\n      }\n      bool is_default = true;\n      GdbThreadId target;\n      if (args) {\n        if (*args == ':') {\n          is_default = false;\n          *args = '\\0';\n          target = parse_threadid(args + 1, &args);\n        }\n        args = strchr(args, ';');\n        if (args) {\n          *args = '\\0';\n          ++args;\n        }\n      }\n\n      GdbActionType action;\n      int signal_to_deliver = 0;\n      char* endptr = NULL;\n      switch (cmd[0]) {\n        case 'C':\n          action = ACTION_CONTINUE;\n          signal_to_deliver = strtol(cmd + 1, &endptr, 16);\n          break;\n        case 'c':\n          action = ACTION_CONTINUE;\n          break;\n        case 'S':\n          action = ACTION_STEP;\n          signal_to_deliver = strtol(cmd + 1, &cmd, 16);\n          break;\n        case 's':\n          action = ACTION_STEP;\n          break;\n        default:\n          UNHANDLED_REQ() << \"Unhandled vCont command \" << cmd << \"(\" << args\n                          << \")\";\n          return false;\n      }\n      if (endptr && *endptr) {\n        UNHANDLED_REQ() << \"Unhandled vCont command parameters \" << cmd;\n        return false;\n      }\n      if (is_default) {\n        if (has_default_action) {\n          UNHANDLED_REQ()\n              << \"Unhandled vCont command with multiple default actions\";\n          return false;\n        }\n        has_default_action = true;\n        default_action =\n            GdbContAction(action, GdbThreadId::ALL, signal_to_deliver);\n      } else {\n        actions.push_back(GdbContAction(action, target, signal_to_deliver));\n      }\n    }\n\n    if (has_default_action) {\n      actions.push_back(default_action);\n    }\n    req = GdbRequest(DREQ_CONT);\n    req.cont().run_direction = RUN_FORWARD;\n    req.cont().actions = std::move(actions);\n    return true;\n  }\n\n  if (!strcmp(\"Cont?\", name)) {\n    LOG(debug) << \"debugger queries which continue commands we support\";\n    write_packet(\"vCont;c;C;s;S;\");\n    return false;\n  }\n\n  if (!strcmp(\"Kill\", name)) {\n    // We can't kill tracees or replay can diverge.  We\n    // assume that this kill request is being made because\n    // a \"vRun\" restart is coming right up.  We know how\n    // to implement vRun, so we'll ignore this one.\n    LOG(debug) << \"debugger asks us to kill tracee(s); ignoring\";\n    write_packet(\"OK\");\n    return false;\n  }\n\n  if (!strcmp(\"Run\", name)) {\n    req = GdbRequest(DREQ_RESTART);\n\n    const char* filename = args;\n    args = strchr(args, ';');\n    if (args) {\n      *args++ = '\\0';\n    }\n    if (strlen(filename)) {\n      FATAL() << \"debugger wants us to run the exe image `\" << filename\n              << \"', but we don't support that.\";\n    }\n    if (!args) {\n      req.restart().type = RESTART_FROM_PREVIOUS;\n      return true;\n    }\n    const char* arg1 = args;\n    args = strchr(args, ';');\n    if (args) {\n      *args++ = 0;\n      LOG(debug) << \"Ignoring extra parameters \" << args;\n    }\n    string event_str = decode_ascii_encoded_hex_str(arg1);\n    char* endp;\n    if (event_str[0] == 'c') {\n      int64_t param = strtoll(event_str.c_str() + 1, &endp, 0);\n      req.restart().type = RESTART_FROM_CHECKPOINT;\n      req.restart().param_str = event_str.substr(1);\n      req.restart().param = param;\n      LOG(debug) << \"next replayer restarting from checkpoint \"\n                 << param;\n    } else if (event_str[0] == 't') {\n      int64_t param = strtoll(event_str.c_str() + 1, &endp, 0);\n      req.restart().type = RESTART_FROM_TICKS;\n      req.restart().param_str = event_str.substr(1);\n      req.restart().param = param;\n      LOG(debug) << \"next replayer restarting from tick count \"\n                 << param;\n    } else {\n      req.restart().type = RESTART_FROM_EVENT;\n      req.restart().param = strtoll(event_str.c_str(), &endp, 0);\n      LOG(debug) << \"next replayer advancing to event \" << req.restart().param;\n    }\n    if (!endp || *endp != '\\0') {\n      LOG(debug) << \"Couldn't parse event string `\" << event_str << \"'\"\n                 << \"; restarting from previous\";\n      req.restart().type = RESTART_FROM_PREVIOUS;\n      req.restart().param = -1;\n    }\n    return true;\n  }\n\n  if (name == strstr(name, \"File:\")) {\n    char* operation = payload + 5;\n    if (operation == strstr(operation, \"open:\")) {\n      char* file_name_end = strchr(operation + 5, ',');\n      parser_assert(file_name_end != nullptr);\n      *file_name_end = 0;\n      req = GdbRequest(DREQ_FILE_OPEN);\n      req.file_open().file_name = decode_ascii_encoded_hex_str(operation + 5);\n      char* flags_end;\n      int64_t flags = strtol(file_name_end + 1, &flags_end, 16);\n      parser_assert(*flags_end == ',');\n      req.file_open().flags = gdb_open_flags_to_system_flags(flags);\n      char* mode_end;\n      int64_t mode = strtol(flags_end + 1, &mode_end, 16);\n      parser_assert(*mode_end == 0);\n      parser_assert((mode & ~(int64_t)0777) == 0);\n      req.file_open().mode = mode;\n      return true;\n    } else if (operation == strstr(operation, \"close:\")) {\n      char* endptr;\n      int64_t fd = strtol(operation + 6, &endptr, 16);\n      parser_assert(*endptr == 0);\n      req = GdbRequest(DREQ_FILE_CLOSE);\n      req.file_close().fd = fd;\n      parser_assert(req.file_close().fd == fd);\n      return true;\n    } else if (operation == strstr(operation, \"pread:\")) {\n      char* fd_end;\n      int64_t fd = strtol(operation + 6, &fd_end, 16);\n      parser_assert(*fd_end == ',');\n      req = GdbRequest(DREQ_FILE_PREAD);\n      req.file_pread().fd = fd;\n      parser_assert(req.file_pread().fd == fd);\n      char* size_end;\n      int64_t size = strtol(fd_end + 1, &size_end, 16);\n      parser_assert(*size_end == ',');\n      parser_assert(size >= 0);\n      req.file_pread().size = size;\n      char* offset_end;\n      int64_t offset = strtol(size_end + 1, &offset_end, 16);\n      parser_assert(*offset_end == 0);\n      parser_assert(offset >= 0);\n      req.file_pread().offset = offset;\n      return true;\n    } else if (operation == strstr(operation, \"setfs:\")) {\n      char* endptr;\n      int64_t pid = strtol(operation + 6, &endptr, 16);\n      parser_assert(*endptr == 0);\n      req = GdbRequest(DREQ_FILE_SETFS);\n      req.file_setfs().pid = pid;\n      parser_assert(req.file_setfs().pid == pid);\n      return true;\n    } else {\n      write_packet(\"\");\n      return false;\n    }\n  }\n\n  UNHANDLED_REQ() << \"Unhandled debugger vpacket: v\" << name;\n  return false;\n}\n\nstatic string to_string(const vector<uint8_t>& bytes, size_t max_len) {\n  stringstream ss;\n  for (size_t i = 0; i < bytes.size(); ++i) {\n    if (i >= max_len) {\n      ss << \"...\";\n      break;\n    }\n    char buf[3];\n    sprintf(buf, \"%02x\", bytes[i]);\n    ss << buf;\n  }\n  return ss.str();\n}\n\nbool GdbServerConnection::process_packet() {\n  parser_assert(\n      INTERRUPT_CHAR == inbuf[0] ||\n      ('$' == inbuf[0] && (uint8_t*)memchr(inbuf.data(), '#', inbuf.size()) ==\n                              inbuf.data() + packetend));\n\n  if (INTERRUPT_CHAR == inbuf[0]) {\n    LOG(debug) << \"debugger requests interrupt\";\n    req = GdbRequest(DREQ_INTERRUPT);\n    inbuf.erase(inbuf.begin());\n    return true;\n  }\n\n  char request = inbuf[1];\n  char* payload = (char*)&inbuf[2];\n  inbuf[packetend] = '\\0';\n  LOG(debug) << \"raw request \" << request << payload;\n\n  bool ret;\n  switch (request) {\n    case 'b':\n      ret = process_bpacket(payload);\n      break;\n    case 'c':\n      LOG(debug) << \"debugger is asking to continue\";\n      req = GdbRequest(DREQ_CONT);\n      req.cont().run_direction = RUN_FORWARD;\n      req.cont().actions.push_back(GdbContAction(ACTION_CONTINUE));\n      ret = true;\n      break;\n    case 'D':\n      LOG(debug) << \"debugger is detaching from us\";\n      req = GdbRequest(DREQ_DETACH);\n      ret = true;\n      break;\n    case 'g':\n      req = GdbRequest(DREQ_GET_REGS);\n      req.target = query_thread;\n      parse_thread_suffix_threadid(payload, &req.target);\n      LOG(debug) << \"debugger requests registers in thread \"\n          << req.target;\n      ret = true;\n      break;\n    case 'G':\n      /* XXX we can't let gdb spray registers in general,\n       * because it may cause replay to diverge.  But some\n       * writes may be OK.  Let's see how far we can get\n       * with ignoring these requests. */\n      write_packet(\"\");\n      ret = false;\n      break;\n    case 'H':\n      if ('c' == *payload++) {\n        req = GdbRequest(DREQ_SET_CONTINUE_THREAD);\n      } else {\n        req = GdbRequest(DREQ_SET_QUERY_THREAD);\n      }\n      req.target = parse_threadid(payload, &payload);\n      parser_assert('\\0' == *payload);\n\n      LOG(debug) << \"debugger selecting \" << req.target;\n\n      ret = true;\n      break;\n    case 'j':\n      // Prefer to avoid implementing any JSON-formatted-output\n      // packets unless we have to\n      write_packet(\"\");\n      ret = false;\n      break;\n    case 'k':\n      LOG(info) << \"debugger requests kill, exiting\";\n      write_packet(\"OK\");\n      exit(0);\n    case 'm':\n      req = GdbRequest(DREQ_GET_MEM);\n      req.target = query_thread;\n      req.mem().addr = strtoul(payload, &payload, 16);\n      parser_assert(',' == *payload++);\n      req.mem().len = strtoul(payload, &payload, 16);\n      parser_assert('\\0' == *payload);\n\n      LOG(debug) << \"debugger requests memory (addr=\" << HEX(req.mem().addr)\n                 << \", len=\" << req.mem().len << \")\";\n\n      ret = true;\n      break;\n    case 'M':\n      req = GdbRequest(DREQ_SET_MEM);\n      req.target = query_thread;\n      req.mem().addr = strtoul(payload, &payload, 16);\n      parser_assert(',' == *payload++);\n      req.mem().len = strtoul(payload, &payload, 16);\n      parser_assert(':' == *payload++);\n      read_hex_data(payload, reinterpret_cast<const char*>(inbuf.data() + packetend),\n                    req.mem().data);\n      parser_assert(req.mem().len == req.mem().data.size());\n\n      LOG(debug) << \"debugger setting memory (addr=\" << HEX(req.mem().addr)\n                 << \", len=\" << req.mem().len\n                 << \", data=\" << to_string(req.mem().data, 32) << \")\";\n\n      ret = true;\n      break;\n    case 'p':\n      req = GdbRequest(DREQ_GET_REG);\n      req.target = query_thread;\n      parse_thread_suffix_threadid(payload, &req.target);\n      req.reg().name = GdbServerRegister(strtoul(payload, &payload, 16));\n      parser_assert('\\0' == *payload);\n      LOG(debug) << \"debugger requests register value (\" << req.reg().name\n          << \") in thread \" << req.target;\n      ret = true;\n      break;\n    case 'P':\n      req = GdbRequest(DREQ_SET_REG);\n      req.target = query_thread;\n      parse_thread_suffix_threadid(payload, &req.target);\n      req.reg().name = GdbServerRegister(strtoul(payload, &payload, 16));\n      parser_assert('=' == *payload++);\n\n      read_reg_value(&payload, &req.reg());\n\n      parser_assert('\\0' == *payload);\n      LOG(debug) << \"debugger requests set register value (\" << req.reg().name\n          << \") in thread \" << req.target;\n\n      ret = true;\n      break;\n    case 'q':\n      ret = query(payload);\n      break;\n    case 'Q':\n      ret = set_var(payload);\n      break;\n    case 'T':\n      req = GdbRequest(DREQ_GET_IS_THREAD_ALIVE);\n      req.target = parse_threadid(payload, &payload);\n      parser_assert('\\0' == *payload);\n      LOG(debug) << \"debugger wants to know if \" << req.target << \" is alive\";\n      ret = true;\n      break;\n    case 'v':\n      ret = process_vpacket(payload);\n      break;\n    case 'x':\n      req = GdbRequest(DREQ_GET_MEM_BINARY);\n      req.target = query_thread;\n      req.mem().addr = strtoul(payload, &payload, 16);\n      parser_assert(',' == *payload++);\n      req.mem().len = strtoul(payload, &payload, 16);\n      parser_assert(!*payload);\n      LOG(debug) << \"debugger requests binary memory (addr=\" << HEX(req.mem().addr)\n                 << \", len=\" << req.mem().len << \")\";\n      ret = true;\n      break;\n    case 'X':\n      req = GdbRequest(DREQ_SET_MEM_BINARY);\n      req.target = query_thread;\n      req.mem().addr = strtoul(payload, &payload, 16);\n      parser_assert(',' == *payload++);\n      req.mem().len = strtoul(payload, &payload, 16);\n      parser_assert(':' == *payload++);\n      read_binary_data((const uint8_t*)payload, inbuf.data() + packetend,\n                       req.mem().data);\n      parser_assert(req.mem().len == req.mem().data.size());\n\n      LOG(debug) << \"debugger setting memory (addr=\" << HEX(req.mem().addr)\n                 << \", len=\" << req.mem().len\n                 << \", data=\" << to_string(req.mem().data, 32) << \")\";\n\n      ret = true;\n      break;\n    case 'z':\n    case 'Z': {\n      int type = strtol(payload, &payload, 16);\n      parser_assert(',' == *payload++);\n      if (!(0 <= type && type <= 4)) {\n        LOG(warn) << \"Unknown watch type \" << type;\n        write_packet(\"\");\n        ret = false;\n        break;\n      }\n      req = GdbRequest(GdbRequestType(\n          type + (request == 'Z' ? DREQ_SET_SW_BREAK : DREQ_REMOVE_SW_BREAK)));\n      req.watch().addr = strtoul(payload, &payload, 16);\n      parser_assert(',' == *payload);\n      payload++;\n      req.watch().kind = strtoul(payload, &payload, 16);\n      if (';' == *payload) {\n        ++payload;\n        while ('X' == *payload) {\n          ++payload;\n          int len = strtol(payload, &payload, 16);\n          parser_assert(',' == *payload);\n          payload++;\n          vector<uint8_t> bytes;\n          for (int i = 0; i < len; ++i) {\n            parser_assert(payload[0] && payload[1]);\n            char tmp = payload[2];\n            payload[2] = '\\0';\n            bytes.push_back(strtol(payload, &payload, 16));\n            parser_assert('\\0' == *payload);\n            payload[0] = tmp;\n          }\n          req.watch().conditions.push_back(std::move(bytes));\n        }\n      }\n      parser_assert('\\0' == *payload);\n\n      LOG(debug) << \"debugger requests \" << ('Z' == request ? \"set\" : \"remove\")\n                 << \"breakpoint (addr=\" << HEX(req.watch().addr)\n                 << \", len=\" << req.watch().kind << \")\";\n\n      ret = true;\n      break;\n    }\n    case '!':\n      LOG(debug) << \"debugger requests extended mode\";\n      write_packet(\"OK\");\n      ret = false;\n      break;\n    case '?':\n      LOG(debug) << \"debugger requests stop reason\";\n      req = GdbRequest(DREQ_GET_STOP_REASON);\n      req.target = query_thread;\n      ret = true;\n      break;\n    case '_':\n      ret = process_underscore(payload);\n      break;\n    default:\n      UNHANDLED_REQ() << \"Unhandled debugger request '\" << inbuf[1] << \"'\";\n      ret = false;\n  }\n  /* Erase the newly processed packet from the input buffer. The checksum\n   * after the '#' will be skipped later as we look for the next packet start.\n   */\n  inbuf.erase(inbuf.begin(), inbuf.begin() + packetend + 1);\n\n  /* If we processed the request internally, consume it. */\n  if (!ret) {\n    consume_request();\n  }\n  return ret;\n}\n\nvoid GdbServerConnection::notify_no_such_thread(const GdbRequest& req) {\n  DEBUG_ASSERT(req.target == this->req.target && req.type == this->req.type);\n\n  /* '10' is the errno ECHILD.  We use it as a magic code to\n   * notify the user that the thread that was the target of this\n   * request has died, and either gdb didn't notice that, or rr\n   * didn't notify gdb.  Either way, the user should restart\n   * their debugging session. */\n  LOG(error) << \"Targeted thread no longer exists; this is the result of \"\n                \"either a debugger or\\n\"\n                \"rr bug.  Please restart your debugging session and avoid \"\n                \"doing whatever\\n\"\n                \"triggered this bug.\";\n  write_packet(\"E10\");\n  consume_request();\n}\n\nvoid GdbServerConnection::notify_restart() {\n  DEBUG_ASSERT(DREQ_RESTART == req.type);\n\n  // These threads may not exist at the first trace-stop after\n  // restart.  The gdb client should reset this state, but help\n  // it out just in case.\n  resume_thread = GdbThreadId::ANY;\n  query_thread = GdbThreadId::ANY;\n\n  req = GdbRequest();\n}\n\nGdbRequest GdbServerConnection::get_request() {\n  if (DREQ_RESTART == req.type) {\n    LOG(debug) << \"consuming RESTART request\";\n    notify_restart();\n    // gdb wants to be notified with a stop packet when\n    // the process \"relaunches\".  In rr's case, the\n    // traceee may be very far away from process creation,\n    // but that's OK.\n    req = GdbRequest(DREQ_GET_STOP_REASON);\n    req.target = query_thread;\n    return req;\n  }\n\n/* Can't ask for the next request until you've satisfied the\n * current one, for requests that need an immediate\n * response. */\n#ifdef DEBUG\n  DEBUG_ASSERT(!request_needs_immediate_response(&req));\n#endif\n\n  if (!sniff_packet() && req.is_resume_request()) {\n    /* There's no new request data available and the debugger has\n     * already asked us to resume.  OK, do that (or keep\n     * doing that) now. */\n    return req;\n  }\n\n  while (true) {\n    /* There's either new request data, or we have nothing\n     * to do.  Either way, block until we read a complete\n     * packet from the debugger. */\n    read_packet();\n\n    if (!connection_alive_) {\n      return req = GdbRequest(DREQ_DETACH);\n    }\n\n    if (process_packet()) {\n      /* We couldn't process the packet internally,\n       * so the target has to do something. */\n      return req;\n    }\n    /* The packet we got was \"internal\", debugger details.\n     * Nothing for the target to do yet.  Keep waiting. */\n  }\n}\n\nvoid GdbServerConnection::notify_exit_code(int code) {\n  char buf[64];\n\n  DEBUG_ASSERT(req.is_resume_request() || req.type == DREQ_INTERRUPT);\n\n  snprintf(buf, sizeof(buf) - 1, \"W%02x\", code);\n  write_packet(buf);\n\n  consume_request();\n}\n\nvoid GdbServerConnection::notify_exit_signal(int sig) {\n  char buf[64];\n\n  DEBUG_ASSERT(req.is_resume_request() || req.type == DREQ_INTERRUPT);\n\n  snprintf(buf, sizeof(buf) - 1, \"X%02x\", sig);\n  write_packet(buf);\n\n  consume_request();\n}\n\n/**\n * Translate linux-x86 |sig| to gdb's internal numbering.  Translation\n * made according to gdb/include/gdb/signals.def.\n */\nstatic int to_gdb_signum(int sig) {\n  switch (sig) {\n    case 0:\n      return 0;\n    case SIGHUP:\n      return 1;\n    case SIGINT:\n      return 2;\n    case SIGQUIT:\n      return 3;\n    case SIGILL:\n      return 4;\n    case SIGTRAP:\n      return 5;\n    case SIGABRT /*case SIGIOT*/:\n      return 6;\n    case SIGBUS:\n      return 10;\n    case SIGFPE:\n      return 8;\n    case SIGKILL:\n      return 9;\n    case SIGUSR1:\n      return 30;\n    case SIGSEGV:\n      return 11;\n    case SIGUSR2:\n      return 31;\n    case SIGPIPE:\n      return 13;\n    case SIGALRM:\n      return 14;\n    case SIGTERM:\n      return 15;\n    /* gdb hasn't heard of SIGSTKFLT, so this is\n     * arbitrarily made up.  SIGDANGER just sounds cool.*/\n    case SIGSTKFLT:\n      return 38 /*GDB_SIGNAL_DANGER*/;\n    /*case SIGCLD*/ case SIGCHLD:\n      return 20;\n    case SIGCONT:\n      return 19;\n    case SIGSTOP:\n      return 17;\n    case SIGTSTP:\n      return 18;\n    case SIGTTIN:\n      return 21;\n    case SIGTTOU:\n      return 22;\n    case SIGURG:\n      return 16;\n    case SIGXCPU:\n      return 24;\n    case SIGXFSZ:\n      return 25;\n    case SIGVTALRM:\n      return 26;\n    case SIGPROF:\n      return 27;\n    case SIGWINCH:\n      return 28;\n    /*case SIGPOLL*/ case SIGIO:\n      return 23;\n    case SIGPWR:\n      return 32;\n    case SIGSYS:\n      return 12;\n    case 32:\n      return 77;\n    default:\n      if (33 <= sig && sig <= 63) {\n        /* GDB_SIGNAL_REALTIME_33 is numbered 45, hence this offset. */\n        return sig + 12;\n      }\n      if (64 <= sig && sig <= 127) {\n        /* GDB_SIGNAL_REALTIME_64 is numbered 78, hence this offset. */\n        return sig + 14;\n      }\n      LOG(warn) << \"Unknown signal \" << sig;\n      return 143; // GDB_SIGNAL_UNKNOWN\n  }\n}\n\nvoid GdbServerConnection::send_stop_reply_packet(ExtendedTaskId thread, int sig,\n                                                 const vector<ThreadInfo>& threads,\n                                                 const string& reason) {\n  if (sig < 0) {\n    write_packet(\"E01\");\n    return;\n  }\n  stringstream sstr;\n  sstr << \"T\" << std::setfill('0') << std::setw(2) << std::hex\n      << to_gdb_signum(sig) << std::setw(0);\n  sstr << \"thread:\" << format_thread_id(thread) << \";\" << reason;\n  if (list_threads_in_stop_reply_) {\n    sstr << \"threads:\";\n    bool first = true;\n    for (const auto& thread : threads) {\n      if (thread.id.tguid != tguid) {\n        continue;\n      }\n      if (!first) {\n        sstr << \",\";\n      }\n      first = false;\n      sstr << thread.id.tuid.tid();\n    }\n    sstr << \";thread-pcs:\";\n    first = true;\n    for (const auto& thread : threads) {\n      if (thread.id.tguid != tguid) {\n        continue;\n      }\n      if (!first) {\n        sstr << \",\";\n      }\n      first = false;\n      sstr << thread.pc;\n    }\n    sstr << \";\";\n  }\n\n  write_packet(sstr.str().c_str());\n}\n\nvoid GdbServerConnection::notify_stop(ExtendedTaskId thread, int sig,\n                                      const vector<ThreadInfo>& threads,\n                                      const string& reason) {\n  DEBUG_ASSERT(req.is_resume_request() || req.type == DREQ_INTERRUPT);\n\n  // don't pass this signal to gdb if it is specified not to\n  if (pass_signals.find(to_gdb_signum(sig)) != pass_signals.end()) {\n    LOG(debug) << \"discarding stop notification for signal \" << sig \n                << \" on thread \" << thread << \" as specified by QPassSignal\";\n\n    return;\n  }\n\n  if (tguid != thread.tguid) {\n    LOG(debug) << \"ignoring stop of \" << thread\n               << \" because we're debugging tgid \" << tguid.tid();\n    // Re-use the existing continue request to advance to\n    // the next stop we're willing to tell gdb about.\n    return;\n  }\n\n  send_stop_reply_packet(thread, sig, threads, reason);\n\n  // This isn't documented in the gdb remote protocol, but if we\n  // don't do this, gdb will sometimes continue to send requests\n  // for the previously-stopped thread when it obviously intends\n  // to be making requests about the stopped thread.\n  // To make things even better, gdb expects different behavior\n  // for forward continue/interrupt and reverse continue.\n  if (req.is_resume_request() && req.cont().run_direction == RUN_BACKWARD) {\n    LOG(debug) << \"Setting query/resume_thread to ANY after reverse continue\";\n    query_thread = resume_thread = GdbThreadId::ANY;\n  } else {\n    LOG(debug) << \"Setting query/resume_thread to \" << thread\n               << \" after forward continue or interrupt\";\n    query_thread = resume_thread = thread.to_debugger_thread_id();\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::notify_restart_failed() {\n  DEBUG_ASSERT(DREQ_RESTART == req.type);\n\n  // TODO: it's not known by this author whether gdb knows how\n  // to recover from a failed \"run\" request.\n  write_packet(\"E01\");\n\n  consume_request();\n}\n\nstring GdbServerConnection::format_thread_id(ExtendedTaskId thread) {\n  char buf[32];\n  if (multiprocess_supported_) {\n    snprintf(buf, sizeof(buf), \"p%x.%x\", thread.tguid.tid(),\n             thread.tuid.tid());\n  } else {\n    snprintf(buf, sizeof(buf), \"%x\", thread.tuid.tid());\n  }\n  return buf;\n}\n\nvoid GdbServerConnection::reply_get_current_thread(ExtendedTaskId thread) {\n  DEBUG_ASSERT(DREQ_GET_CURRENT_THREAD == req.type);\n\n  write_packet((\"QC\" + format_thread_id(thread)).c_str());\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_auxv(const vector<uint8_t>& auxv) {\n  DEBUG_ASSERT(DREQ_GET_AUXV == req.type);\n\n  if (!auxv.empty()) {\n    write_binary_packet(\"l\", auxv.data(), auxv.size());\n  } else {\n    write_packet(\"E01\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_exec_file(const string& exec_file) {\n  DEBUG_ASSERT(DREQ_GET_EXEC_FILE == req.type);\n\n  if (!exec_file.empty()) {\n    write_binary_packet(\"l\",\n                        reinterpret_cast<const uint8_t*>(exec_file.c_str()),\n                        exec_file.size());\n  } else {\n    write_packet(\"E01\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_is_thread_alive(bool alive) {\n  DEBUG_ASSERT(DREQ_GET_IS_THREAD_ALIVE == req.type);\n\n  write_packet(alive ? \"OK\" : \"E01\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_thread_extra_info(const string& info) {\n  DEBUG_ASSERT(DREQ_GET_THREAD_EXTRA_INFO == req.type);\n\n  LOG(debug) << \"thread extra info: '\" << info.c_str() << \"'\";\n  write_hex_bytes_packet((const uint8_t*)info.c_str(), 1 + info.length());\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_select_thread(bool ok) {\n  DEBUG_ASSERT(DREQ_SET_CONTINUE_THREAD == req.type ||\n               DREQ_SET_QUERY_THREAD == req.type);\n\n  if (ok && DREQ_SET_CONTINUE_THREAD == req.type) {\n    resume_thread = req.target;\n  } else if (ok && DREQ_SET_QUERY_THREAD == req.type) {\n    query_thread = req.target;\n  }\n  write_packet(ok ? \"OK\" : \"E01\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_mem(const vector<uint8_t>& mem) {\n  DEBUG_ASSERT(DREQ_GET_MEM == req.type || DREQ_GET_MEM_BINARY == req.type);\n  DEBUG_ASSERT(mem.size() <= req.mem().len);\n\n  if (DREQ_GET_MEM == req.type) {\n    if (req.mem().len > 0 && mem.size() == 0) {\n      write_packet(\"E01\");\n    } else {\n      write_hex_bytes_packet(mem.data(), mem.size());\n    }\n  } else {\n    if (debugger_type == DebuggerType::LLDB) {\n      if (!req.mem().len) {\n        write_packet(\"OK\");\n      } else if (!mem.size()) {\n        write_packet(\"E01\");\n      } else {\n        write_binary_packet(\"\", mem.data(), mem.size());\n      }\n    } else {\n      if (!req.mem().len) {\n        write_packet(\"b\");\n      } else if (!mem.size()) {\n        write_packet(\"E01\");\n      } else {\n        write_binary_packet(\"b\", mem.data(), mem.size());\n      }\n    }\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_set_mem(bool ok) {\n  DEBUG_ASSERT(DREQ_SET_MEM == req.type || DREQ_SET_MEM_BINARY == req.type);\n\n  write_packet(ok ? \"OK\" : \"E01\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_mem_alloc(remote_ptr<void> addr) {\n  DEBUG_ASSERT(DREQ_MEM_ALLOC == req.type);\n\n  if (addr.is_null()) {\n    write_packet(\"E01\");\n  } else {\n    char buf[256];\n    sprintf(buf, \"%llx\", (long long)addr.as_int());\n    write_packet(buf);\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_mem_free(bool ok) {\n  DEBUG_ASSERT(DREQ_MEM_FREE == req.type);\n\n  write_packet(ok ? \"OK\" : \"E01\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_search_mem_binary(\n      bool found, remote_ptr<void> addr) {\n  DEBUG_ASSERT(DREQ_SEARCH_MEM_BINARY == req.type);\n\n  if (found) {\n    char buf[256];\n    sprintf(buf, \"1,%llx\", (long long)addr.as_int());\n    write_packet(buf);\n  } else {\n    write_packet(\"0\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_mem_info(MemoryRange range,\n                                         int prot,\n                                         const string& fs_name) {\n  DEBUG_ASSERT(DREQ_MEM_INFO == req.type);\n\n  stringstream sstr;\n  sstr << hex << \"start:\" << range.start().as_int()\n    << \";size:\" << range.size() << \";\";\n\n  string permissions;\n  if (prot & PROT_READ) {\n    permissions += 'r';\n  }\n  if (prot & PROT_WRITE) {\n    permissions += 'w';\n  }\n  if (prot & PROT_EXEC) {\n    permissions += 'x';\n  }\n  if (!permissions.empty()) {\n    sstr << \"permissions:\" << permissions << \";\";\n  }\n  if (!fs_name.empty()) {\n    sstr << \"name:\" << string_to_hex(fs_name) << \";\";\n  }\n\n  write_packet(sstr.str().c_str());\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_offsets(/* TODO */) {\n  DEBUG_ASSERT(DREQ_GET_OFFSETS == req.type);\n\n  /* XXX FIXME TODO */\n  write_packet(\"\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_reg(const GdbServerRegisterValue& reg) {\n  char buf[2 * GdbServerRegisterValue::MAX_SIZE + 1];\n\n  DEBUG_ASSERT(DREQ_GET_REG == req.type);\n\n  print_reg_value(reg, buf);\n  write_packet(buf);\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_regs(const vector<GdbServerRegisterValue>& file) {\n  std::unique_ptr<char[]> buf(\n      new char[file.size() * 2 * GdbServerRegisterValue::MAX_SIZE + 1]);\n\n  DEBUG_ASSERT(DREQ_GET_REGS == req.type);\n\n  size_t offset = 0;\n  for (auto& reg : file) {\n    offset += print_reg_value(reg, &buf[offset]);\n  }\n  write_packet(buf.get());\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_set_reg(bool ok) {\n  DEBUG_ASSERT(DREQ_SET_REG == req.type);\n\n  // TODO: what happens if we're forced to reply to a\n  // set-register request with |ok = false|, leading us to\n  // pretend not to understand the packet?  If, later, an\n  // experimental session needs the set-register request will it\n  // not be sent?\n  //\n  // We can't reply with an error packet here because gdb thinks\n  // that failed set-register requests are catastrophic.\n  write_packet(ok ? \"OK\" : \"\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_stop_reason(ExtendedTaskId which, int sig,\n                                                const std::vector<ThreadInfo>& threads) {\n  DEBUG_ASSERT(DREQ_GET_STOP_REASON == req.type);\n\n  send_stop_reply_packet(which, sig, threads, string());\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_get_thread_list(const vector<ExtendedTaskId>& threads) {\n  DEBUG_ASSERT(DREQ_GET_THREAD_LIST == req.type);\n  if (threads.empty()) {\n    write_packet(\"l\");\n  } else {\n    stringstream sstr;\n    sstr << 'm';\n    for (size_t i = 0; i < threads.size(); ++i) {\n      const ExtendedTaskId& t = threads[i];\n      if (tguid != t.tguid) {\n        continue;\n      }\n      if (multiprocess_supported_) {\n        sstr << 'p' << setw(2) << setfill('0') << hex << t.tguid.tid() << dec << '.'\n            << setw(2) << setfill('0') << hex << t.tuid.tid() << ',';\n      } else {\n        sstr << setw(2) << setfill('0') << hex << t.tuid.tid() << ',';\n      }\n    }\n\n    string str = sstr.str();\n    /* Overwrite the trailing ',' */\n    str.back() = 0;\n    write_packet(str.c_str());\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_watchpoint_request(bool ok) {\n  DEBUG_ASSERT(DREQ_WATCH_FIRST <= req.type && req.type <= DREQ_WATCH_LAST);\n\n  write_packet(ok ? \"OK\" : \"E01\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_detach() {\n  DEBUG_ASSERT(DREQ_DETACH <= req.type);\n\n  write_packet(\"OK\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_read_siginfo(const vector<uint8_t>& si_bytes) {\n  DEBUG_ASSERT(DREQ_READ_SIGINFO == req.type);\n\n  if (si_bytes.empty()) {\n    write_packet(\"E01\");\n  } else {\n    write_binary_packet(\"l\", si_bytes.data(), si_bytes.size());\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_write_siginfo(/* TODO*/) {\n  DEBUG_ASSERT(DREQ_WRITE_SIGINFO == req.type);\n\n  write_packet(\"E01\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_rr_cmd(const std::string& text) {\n  DEBUG_ASSERT(DREQ_RR_CMD == req.type);\n\n  write_packet(text.c_str());\n\n  consume_request();\n}\n\nvoid GdbServerConnection::send_qsymbol(const std::string& name) {\n  DEBUG_ASSERT(DREQ_QSYMBOL == req.type);\n\n  const void* data = static_cast<const void*>(name.c_str());\n  write_hex_bytes_packet(\"qSymbol:\", static_cast<const uint8_t*>(data),\n                         name.length());\n\n  consume_request();\n}\n\nvoid GdbServerConnection::qsymbols_finished() {\n  DEBUG_ASSERT(DREQ_QSYMBOL == req.type);\n\n  write_packet(\"OK\");\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_tls_addr(bool ok, remote_ptr<void> address) {\n  DEBUG_ASSERT(DREQ_TLS == req.type);\n\n  if (ok) {\n    char buf[256];\n    sprintf(buf, \"%llx\", (long long)address.as_int());\n    write_packet(buf);\n  } else {\n    write_packet(\"E01\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_setfs(int err) {\n  DEBUG_ASSERT(DREQ_FILE_SETFS == req.type);\n  if (err) {\n    send_file_error_reply(err);\n  } else {\n    write_packet(\"F0\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_open(int fd, int err) {\n  DEBUG_ASSERT(DREQ_FILE_OPEN == req.type);\n  if (err) {\n    send_file_error_reply(err);\n  } else {\n    char buf[32];\n    sprintf(buf, \"F%x\", fd);\n    write_packet(buf);\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_pread(const uint8_t* bytes, ssize_t len, int err) {\n  DEBUG_ASSERT(DREQ_FILE_PREAD == req.type);\n  if (err) {\n    send_file_error_reply(err);\n  } else {\n    char buf[32];\n    sprintf(buf, \"F%llx;\", (long long)len);\n    write_binary_packet(buf, bytes, len);\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_close(int err) {\n  DEBUG_ASSERT(DREQ_FILE_CLOSE == req.type);\n  if (err) {\n    send_file_error_reply(err);\n  } else {\n    write_packet(\"F0\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::send_file_error_reply(int system_errno) {\n  int gdb_err;\n  switch (system_errno) {\n    case EPERM:\n      gdb_err = 1;\n      break;\n    case ENOENT:\n      gdb_err = 2;\n      break;\n    case EINTR:\n      gdb_err = 4;\n      break;\n    case EBADF:\n      gdb_err = 9;\n      break;\n    case EACCES:\n      gdb_err = 13;\n      break;\n    case EFAULT:\n      gdb_err = 14;\n      break;\n    case EBUSY:\n      gdb_err = 16;\n      break;\n    case EEXIST:\n      gdb_err = 17;\n      break;\n    case ENODEV:\n      gdb_err = 19;\n      break;\n    case ENOTDIR:\n      gdb_err = 20;\n      break;\n    case EISDIR:\n      gdb_err = 21;\n      break;\n    case EINVAL:\n      gdb_err = 22;\n      break;\n    case ENFILE:\n      gdb_err = 23;\n      break;\n    case EMFILE:\n      gdb_err = 24;\n      break;\n    case EFBIG:\n      gdb_err = 27;\n      break;\n    case ENOSPC:\n      gdb_err = 28;\n      break;\n    case ESPIPE:\n      gdb_err = 29;\n      break;\n    case EROFS:\n      gdb_err = 30;\n      break;\n    case ENAMETOOLONG:\n      gdb_err = 91;\n      break;\n    default:\n      gdb_err = 9999;\n      break;\n  }\n  char buf[32];\n  sprintf(buf, \"F-01,%x\", gdb_err);\n  write_packet(buf);\n}\n\nvoid GdbServerConnection::reply_save_register_state(bool ok, int state_index) {\n  DEBUG_ASSERT(DREQ_SAVE_REGISTER_STATE == req.type);\n\n  if (ok) {\n    char buf[256];\n    sprintf(buf, \"%llx\", (long long)state_index);\n    write_packet(buf);\n  } else {\n    write_packet(\"E01\");\n  }\n\n  consume_request();\n}\n\nvoid GdbServerConnection::reply_restore_register_state(bool ok) {\n  DEBUG_ASSERT(DREQ_RESTORE_REGISTER_STATE == req.type);\n\n  write_packet(ok ? \"OK\" : \"E01\");\n\n  consume_request();\n}\n\nbool GdbServerConnection::is_connection_alive() { return connection_alive_; }\n\nbool GdbServerConnection::is_pass_signal(int sig) { return pass_signals.find(to_gdb_signum(sig)) != pass_signals.end(); }\n\nvoid GdbServerConnection::set_cpu_features(SupportedArch arch) {\n  cpu_features_ = get_cpu_features(arch);\n  DEBUG_ASSERT(target_description == nullptr &&\n               \"Target description already created\");\n  target_description = std::make_unique<TargetDescription>(arch, cpu_features_);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/GdbServerConnection.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_GDB_CONNECTION_H_\n#define RR_GDB_CONNECTION_H_\n\n#include <stddef.h>\n#include <sys/types.h>\n\n#include <memory>\n#include <ostream>\n#include <string>\n#include <unordered_set>\n#include <vector>\n\n#include \"GdbServerRegister.h\"\n#include \"Registers.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTimeline.h\"\n#include \"ScopedFd.h\"\n#include \"TargetDescription.h\"\n#include \"TaskishUid.h\"\n#include \"core.h\"\n#include \"launch_debugger.h\"\n\nnamespace rr {\n\n/**\n * Descriptor for task, that carries both the pid (thread-group ID)\n * and the thread ID. On Linux the thread ID is unique in rr's pid namespace\n * *at a specific point in time*. Thread IDs can potentially be reused\n * over long periods of time.\n * Also has special `ANY` and `ALL` values used by the debugger protocol.\n * These values can be passed from the debugger so the task might not\n * actually exist.\n * Because of the special values and the fact that thread IDs can be\n * reused, this is more like a pattern that can match specific tasks than\n * a unique task ID.\n */\nstruct GdbThreadId {\n  GdbThreadId(pid_t pid = -1, pid_t tid = -1) : pid(pid), tid(tid) {}\n\n  pid_t pid;\n  pid_t tid;\n\n  bool operator==(const GdbThreadId& o) const {\n    return pid == o.pid && tid == o.tid;\n  }\n\n  static const GdbThreadId ANY;\n  static const GdbThreadId ALL;\n};\n\ninline std::ostream& operator<<(std::ostream& o, const GdbThreadId& t) {\n  o << t.pid << \".\" << t.tid;\n  return o;\n}\n\n/**\n * A really-unique `TaskUid` and its `ThreadGroupUid`. This always corresponds\n * to a specific task that exist(ed) somewhere in the recording, unless\n * tguid and tuid are zero.\n */\nstruct ExtendedTaskId {\n  ThreadGroupUid tguid;\n  TaskUid tuid;\n\n  ExtendedTaskId(ThreadGroupUid tguid, TaskUid tuid)\n    : tguid(tguid), tuid(tuid) {}\n  ExtendedTaskId() {}\n\n  GdbThreadId to_debugger_thread_id() const {\n    return GdbThreadId(tguid.tid(), tuid.tid());\n  }\n};\n\ninline std::ostream& operator<<(std::ostream& o, const ExtendedTaskId& t) {\n  o << t.tguid.tid() << \".\" << t.tuid.tid();\n  return o;\n}\n\n/**\n * Represents a possibly-undefined register |name|.  |size| indicates how\n * many bytes of |value| are valid, if any.\n */\nstruct GdbServerRegisterValue {\n  enum { MAX_SIZE = Registers::MAX_SIZE };\n  GdbServerRegister name;\n  union {\n    uint8_t value[MAX_SIZE];\n    uint8_t value1;\n    uint16_t value2;\n    uint32_t value4;\n    uint64_t value8;\n  };\n  size_t size;\n  bool defined;\n};\n\nenum GdbRequestType {\n  DREQ_NONE = 0,\n\n  /* None of these requests have parameters. */\n  DREQ_GET_CURRENT_THREAD,\n  DREQ_GET_OFFSETS,\n  DREQ_GET_REGS,\n  DREQ_GET_STOP_REASON,\n  DREQ_GET_THREAD_LIST,\n  DREQ_INTERRUPT,\n  DREQ_DETACH,\n\n  /* These use params.target. */\n  DREQ_GET_AUXV,\n  DREQ_GET_EXEC_FILE,\n  DREQ_GET_IS_THREAD_ALIVE,\n  DREQ_GET_THREAD_EXTRA_INFO,\n  DREQ_SET_CONTINUE_THREAD,\n  DREQ_SET_QUERY_THREAD,\n  // TLS lookup, uses params.target and params.tls.\n  DREQ_TLS,\n  // gdb wants to write back siginfo_t to a tracee.  More\n  // importantly, this packet arrives before an experiment\n  // session for a |call foo()| is about to be torn down.\n  //\n  // TODO: actual interface NYI.\n  DREQ_WRITE_SIGINFO,\n\n  /* These use params.mem. */\n  DREQ_GET_MEM,\n  DREQ_GET_MEM_BINARY,\n  DREQ_SET_MEM,\n  DREQ_SET_MEM_BINARY,\n  // gdb wants to read the current siginfo_t for a stopped\n  // tracee.  More importantly, this packet arrives at the very\n  // beginning of a |call foo()| experiment.\n  //\n  // Uses .mem for offset/len.\n  DREQ_READ_SIGINFO,\n  DREQ_SEARCH_MEM_BINARY,\n  DREQ_MEM_INFO,\n  DREQ_MEM_FIRST = DREQ_GET_MEM,\n  DREQ_MEM_LAST = DREQ_MEM_INFO,\n\n  DREQ_REMOVE_SW_BREAK,\n  DREQ_REMOVE_HW_BREAK,\n  DREQ_REMOVE_WR_WATCH,\n  DREQ_REMOVE_RD_WATCH,\n  DREQ_REMOVE_RDWR_WATCH,\n  DREQ_SET_SW_BREAK,\n  DREQ_SET_HW_BREAK,\n  DREQ_SET_WR_WATCH,\n  DREQ_SET_RD_WATCH,\n  DREQ_SET_RDWR_WATCH,\n  DREQ_WATCH_FIRST = DREQ_REMOVE_SW_BREAK,\n  DREQ_WATCH_LAST = DREQ_SET_RDWR_WATCH,\n\n  /* Use params.reg. */\n  DREQ_GET_REG,\n  DREQ_SET_REG,\n  DREQ_REG_FIRST = DREQ_GET_REG,\n  DREQ_REG_LAST = DREQ_SET_REG,\n\n  /* Use params.cont. */\n  DREQ_CONT,\n\n  /* gdb host detaching from stub.  No parameters. */\n\n  /* Uses params.restart. */\n  DREQ_RESTART,\n\n  /* Uses params.text. */\n  DREQ_RR_CMD,\n\n  // qSymbol packet, uses params.sym.\n  DREQ_QSYMBOL,\n\n  // vFile:setfs packet, uses params.file_setfs.\n  DREQ_FILE_SETFS,\n  // vFile:open packet, uses params.file_open.\n  DREQ_FILE_OPEN,\n  // vFile:pread packet, uses params.file_pread.\n  DREQ_FILE_PREAD,\n  // vFile:close packet, uses params.file_close.\n  DREQ_FILE_CLOSE,\n\n  // Uses params.mem_alloc\n  DREQ_MEM_ALLOC,\n  // Uses params.mem_free\n  DREQ_MEM_FREE,\n\n  DREQ_SAVE_REGISTER_STATE,\n  // Uses params.restore_register_state\n  DREQ_RESTORE_REGISTER_STATE,\n};\n\nenum GdbRestartType {\n  RESTART_FROM_PREVIOUS,\n  RESTART_FROM_EVENT,\n  RESTART_FROM_CHECKPOINT,\n  RESTART_FROM_TICKS\n};\n\nenum GdbActionType { ACTION_CONTINUE, ACTION_STEP };\n\nstruct GdbContAction {\n  GdbContAction(GdbActionType type = ACTION_CONTINUE,\n                const GdbThreadId& target = GdbThreadId::ANY,\n                int signal_to_deliver = 0)\n      : type(type), target(target), signal_to_deliver(signal_to_deliver) {}\n  GdbActionType type;\n  GdbThreadId target;\n  int signal_to_deliver;\n};\n\n/**\n * These requests are made by the debugger host and honored in proxy\n * by rr, the target.\n */\nstruct GdbRequest {\n  GdbRequest(GdbRequestType type = DREQ_NONE)\n      : type(type), suppress_debugger_stop(false) {}\n  GdbRequest(const GdbRequest& other)\n      : type(other.type),\n        target(other.target),\n        suppress_debugger_stop(other.suppress_debugger_stop) {\n    if (type >= DREQ_MEM_FIRST && type <= DREQ_MEM_LAST) {\n      mem_ = other.mem_;\n    } else if (type >= DREQ_WATCH_FIRST && type <= DREQ_WATCH_LAST) {\n      watch_ = other.watch_;\n    } else if (type >= DREQ_REG_FIRST && type <= DREQ_REG_LAST) {\n      reg_ = other.reg_;\n    } else if (type == DREQ_RESTART) {\n      restart_ = other.restart_;\n    } else if (type == DREQ_CONT) {\n      cont_ = other.cont_;\n    } else if (type == DREQ_RR_CMD) {\n      rr_cmd_ = other.rr_cmd_;\n    } else if (type == DREQ_TLS) {\n      tls_ = other.tls_;\n    } else if (type == DREQ_QSYMBOL) {\n      sym_ = other.sym_;\n    } else if (type == DREQ_FILE_SETFS) {\n      file_setfs_ = other.file_setfs_;\n    } else if (type == DREQ_FILE_OPEN) {\n      file_open_ = other.file_open_;\n    } else if (type == DREQ_FILE_PREAD) {\n      file_pread_ = other.file_pread_;\n    } else if (type == DREQ_FILE_CLOSE) {\n      file_close_ = other.file_close_;\n    } else if (type == DREQ_MEM_ALLOC) {\n      mem_alloc_ = other.mem_alloc_;\n    } else if (type == DREQ_MEM_FREE) {\n      mem_free_ = other.mem_free_;\n    } else if (type == DREQ_RESTORE_REGISTER_STATE) {\n      restore_register_state_ = other.restore_register_state_;\n    }\n  }\n  GdbRequest& operator=(const GdbRequest& other) {\n    this->~GdbRequest();\n    new (this) GdbRequest(other);\n    return *this;\n  }\n\n  const GdbRequestType type;\n  GdbThreadId target;\n  bool suppress_debugger_stop;\n\n  struct Mem {\n    uintptr_t addr = 0;\n    size_t len = 0;\n    // For SET_MEM requests, the |len| raw bytes that are to be written.\n    // For SEARCH_MEM requests, the bytes to search for.\n    std::vector<uint8_t> data;\n  } mem_;\n  struct Watch {\n    uintptr_t addr = 0;\n    int kind = 0;\n    std::vector<std::vector<uint8_t>> conditions;\n  } watch_;\n  GdbServerRegisterValue reg_;\n  struct Restart {\n    int64_t param = 0;\n    std::string param_str;\n    GdbRestartType type = RESTART_FROM_PREVIOUS;\n  } restart_;\n  struct Cont {\n    RunDirection run_direction = RUN_FORWARD;\n    std::vector<GdbContAction> actions;\n  } cont_;\n  struct RRCmd {\n    std::string name;\n    pid_t target_tid = -1;\n    std::vector<std::string> args;  \n  } rr_cmd_;\n  struct Tls {\n    size_t offset = 0;\n    remote_ptr<void> load_module;\n  } tls_;\n  struct Symbol {\n    bool has_address = false;\n    remote_ptr<void> address;\n    std::string name;\n  } sym_;\n  struct FileSetfs {\n    pid_t pid  = -1;\n  } file_setfs_;\n  struct FileOpen {\n    std::string file_name;\n    // In system format, not gdb's format\n    int flags = 0;\n    int mode = 0;\n  } file_open_;\n  struct FilePread {\n    int fd = -1;\n    size_t size = 0;\n    uint64_t offset = 0;\n  } file_pread_;\n  struct FileClose {\n    int fd = -1;\n  } file_close_;\n  struct MemAlloc {\n    size_t size = 0;\n    int prot = 0;\n  } mem_alloc_;\n  struct MemFree {\n    remote_ptr<void> address;\n  } mem_free_;\n  struct RestoreRegisterState {\n    int state_index = 0;\n  } restore_register_state_;\n\n  Mem& mem() {\n    DEBUG_ASSERT(type >= DREQ_MEM_FIRST && type <= DREQ_MEM_LAST);\n    return mem_;\n  }\n  const Mem& mem() const {\n    DEBUG_ASSERT(type >= DREQ_MEM_FIRST && type <= DREQ_MEM_LAST);\n    return mem_;\n  }\n  Watch& watch() {\n    DEBUG_ASSERT(type >= DREQ_WATCH_FIRST && type <= DREQ_WATCH_LAST);\n    return watch_;\n  }\n  const Watch& watch() const {\n    DEBUG_ASSERT(type >= DREQ_WATCH_FIRST && type <= DREQ_WATCH_LAST);\n    return watch_;\n  }\n  GdbServerRegisterValue& reg() {\n    DEBUG_ASSERT(type >= DREQ_REG_FIRST && type <= DREQ_REG_LAST);\n    return reg_;\n  }\n  const GdbServerRegisterValue& reg() const {\n    DEBUG_ASSERT(type >= DREQ_REG_FIRST && type <= DREQ_REG_LAST);\n    return reg_;\n  }\n  Restart& restart() {\n    DEBUG_ASSERT(type == DREQ_RESTART);\n    return restart_;\n  }\n  const Restart& restart() const {\n    DEBUG_ASSERT(type == DREQ_RESTART);\n    return restart_;\n  }\n  Cont& cont() {\n    DEBUG_ASSERT(type == DREQ_CONT);\n    return cont_;\n  }\n  const Cont& cont() const {\n    DEBUG_ASSERT(type == DREQ_CONT);\n    return cont_;\n  }\n  RRCmd& rr_cmd() {\n    DEBUG_ASSERT(type == DREQ_RR_CMD);\n    return rr_cmd_;\n  }\n  const RRCmd& rr_cmd() const {\n    DEBUG_ASSERT(type == DREQ_RR_CMD);\n    return rr_cmd_;\n  }\n  Tls& tls() {\n    DEBUG_ASSERT(type == DREQ_TLS);\n    return tls_;\n  }\n  const Tls& tls() const {\n    DEBUG_ASSERT(type == DREQ_TLS);\n    return tls_;\n  }\n  Symbol& sym() {\n    DEBUG_ASSERT(type == DREQ_QSYMBOL);\n    return sym_;\n  }\n  const Symbol& sym() const {\n    DEBUG_ASSERT(type == DREQ_QSYMBOL);\n    return sym_;\n  }\n  FileSetfs& file_setfs() {\n    DEBUG_ASSERT(type == DREQ_FILE_SETFS);\n    return file_setfs_;\n  }\n  const FileSetfs& file_setfs() const {\n    DEBUG_ASSERT(type == DREQ_FILE_SETFS);\n    return file_setfs_;\n  }\n  FileOpen& file_open() {\n    DEBUG_ASSERT(type == DREQ_FILE_OPEN);\n    return file_open_;\n  }\n  const FileOpen& file_open() const {\n    DEBUG_ASSERT(type == DREQ_FILE_OPEN);\n    return file_open_;\n  }\n  FilePread& file_pread() {\n    DEBUG_ASSERT(type == DREQ_FILE_PREAD);\n    return file_pread_;\n  }\n  const FilePread& file_pread() const {\n    DEBUG_ASSERT(type == DREQ_FILE_PREAD);\n    return file_pread_;\n  }\n  FileClose& file_close() {\n    DEBUG_ASSERT(type == DREQ_FILE_CLOSE);\n    return file_close_;\n  }\n  const FileClose& file_close() const {\n    DEBUG_ASSERT(type == DREQ_FILE_CLOSE);\n    return file_close_;\n  }\n  MemAlloc& mem_alloc() {\n    DEBUG_ASSERT(type == DREQ_MEM_ALLOC);\n    return mem_alloc_;\n  }\n  const MemAlloc& mem_alloc() const {\n    DEBUG_ASSERT(type == DREQ_MEM_ALLOC);\n    return mem_alloc_;\n  }\n  MemFree& mem_free() {\n    DEBUG_ASSERT(type == DREQ_MEM_FREE);\n    return mem_free_;\n  }\n  const MemFree& mem_free() const {\n    DEBUG_ASSERT(type == DREQ_MEM_FREE);\n    return mem_free_;\n  }\n  RestoreRegisterState& restore_register_state() {\n    DEBUG_ASSERT(type == DREQ_RESTORE_REGISTER_STATE);\n    return restore_register_state_;\n  }\n  const RestoreRegisterState& restore_register_state() const {\n    DEBUG_ASSERT(type == DREQ_RESTORE_REGISTER_STATE);\n    return restore_register_state_;\n  }\n\n  /**\n   * Return nonzero if this requires that program execution be resumed\n   * in some way.\n   */\n  bool is_resume_request() const { return type == DREQ_CONT; }\n};\n\n/**\n * This struct wraps up the state of the gdb protocol, so that we can\n * offer a (mostly) stateless interface to clients.\n */\nclass GdbServerConnection {\npublic:\n  struct Features {\n    Features() : reverse_execution(true) {}\n    bool reverse_execution;\n  };\n\n  /**\n   * Wait for exactly one gdb host to connect to this remote target on\n   * the specified IP address |host|, port |port|.  If |probe| is nonzero,\n   * a unique port based on |start_port| will be searched for.  Otherwise,\n   * if |port| is already bound, this function will fail.\n   *\n   * Pass the `Task` on which this debug-connection request\n   * is being made.  The remaining debugging session will be limited to\n   * traffic regarding this task, but clients don't need to and shouldn't\n   * need to assume that.\n   *\n   * If we're opening this connection on behalf of a known client, pass\n   * an fd in |client_params_fd|; we'll write the allocated port and |exe_image|\n   * through the fd before waiting for a connection. |exe_image| is the\n   * process that will be debugged by client, or null ptr if there isn't\n   * a client.\n   *\n   * This function is infallible: either it will return a valid\n   * debugging context, or it won't return.\n   */\n  static std::unique_ptr<GdbServerConnection> await_connection(\n    Task* t, ScopedFd& listen_fd, DebuggerType debugger_type,\n    const Features& features = Features());\n\n  /**\n   * Call this when the target of |req| is needed to fulfill the\n   * request, but the target is dead.  This situation is a symptom of a\n   * gdb or rr bug.\n   */\n  void notify_no_such_thread(const GdbRequest& req);\n\n  /**\n   * Finish a DREQ_RESTART request.  Should be invoked after replay\n   * restarts and prior GdbServerConnection has been restored.\n   */\n  void notify_restart();\n\n  /**\n   * Return the current request made by the debugger host, that needs to\n   * be satisfied.  This function will block until either there's a\n   * debugger host request that needs a response, or until a request is\n   * made to resume execution of the target.  In the latter case,\n   * calling this function multiple times will return an appropriate\n   * resume request each time (see above).\n   *\n   * The target should peek at the debugger request in between execution\n   * steps.  A new request may need to be serviced.\n   */\n  GdbRequest get_request();\n\n  /**\n   * Notify the host that this process has exited with |code|.\n   */\n  void notify_exit_code(int code);\n\n  /**\n   * Notify the host that this process has exited from |sig|.\n   */\n  void notify_exit_signal(int sig);\n\n  struct ThreadInfo {\n    ExtendedTaskId id;\n    uintptr_t pc;\n  };\n\n  /**\n   * Notify the host that a resume request has \"finished\", i.e., the\n   * target has stopped executing for some reason.  |sig| is the signal\n   * that stopped execution, or 0 if execution stopped otherwise.\n   */\n  void notify_stop(ExtendedTaskId which, int sig,\n                   const std::vector<ThreadInfo>& threads,\n                   const std::string& reason);\n\n  /** Notify the debugger that a restart request failed. */\n  void notify_restart_failed();\n\n  /**\n   * Tell the host that |thread| is the current thread.\n   */\n  void reply_get_current_thread(ExtendedTaskId thread);\n\n  /**\n   * Reply with the target thread's |auxv| pairs. |auxv.empty()|\n   * if there was an error reading the auxiliary vector.\n   */\n  void reply_get_auxv(const std::vector<uint8_t>& auxv);\n\n  /**\n   * Reply with the target thread's executable file name\n   */\n  void reply_get_exec_file(const std::string& exec_file);\n\n  /**\n   * |alive| is true if the requested thread is alive, false if dead.\n   */\n  void reply_get_is_thread_alive(bool alive);\n\n  /**\n   * |info| is a string containing data about the request target that\n   * might be relevant to the debugger user.\n   */\n  void reply_get_thread_extra_info(const std::string& info);\n\n  /**\n   * |ok| is true if req->target can be selected, false otherwise.\n   */\n  void reply_select_thread(bool ok);\n\n  /**\n   * The first |mem.size()| bytes of the request were read into |mem|.\n   * |mem.size()| must be less than or equal to the length of the request.\n   */\n  void reply_get_mem(const std::vector<uint8_t>& mem);\n\n  /**\n   * |ok| is true if a SET_MEM(_BINARY) request succeeded, false otherwise.  This\n   * function *must* be called whenever a SET_MEM(_BINARY) request is made,\n   * regardless of success/failure or special interpretation.\n   */\n  void reply_set_mem(bool ok);\n\n  /**\n   * Reply to the DREQ_SEARCH_MEM_BINARY request.\n   * |found| is true if we found the searched-for bytes starting at address\n   * |addr|.\n   */\n  void reply_search_mem_binary(bool found, remote_ptr<void> addr);\n\n  /**\n   * Reply to the DREQ_MEM_INFO request.\n   */\n  void reply_mem_info(MemoryRange range, int prot,\n                      const std::string& fs_name);\n\n  /**\n   * Reply to the DREQ_MEM_ALLOC request.\n   */\n  void reply_mem_alloc(remote_ptr<void> addr);\n\n  /**\n   * Reply to the DREQ_MEM_FREE request.\n   */\n  void reply_mem_free(bool ok);\n\n  /**\n   * Reply to the DREQ_GET_OFFSETS request.\n   */\n  void reply_get_offsets(/* TODO */);\n\n  /**\n   * Send |value| back to the debugger host.  |value| may be undefined.\n   */\n  void reply_get_reg(const GdbServerRegisterValue& value);\n\n  /**\n   * Send |file| back to the debugger host.  |file| may contain\n   * undefined register values.\n   */\n  void reply_get_regs(const std::vector<GdbServerRegisterValue>& file);\n\n  /**\n   * Pass |ok = true| iff the requested register was successfully set.\n   */\n  void reply_set_reg(bool ok);\n\n  /**\n   * Reply to the DREQ_GET_STOP_REASON request.\n   */\n  void reply_get_stop_reason(ExtendedTaskId which, int sig,\n                             const std::vector<ThreadInfo>& threads);\n\n  /**\n   * |threads| contains the list of live threads, of which there are\n   * |len|.\n   */\n  void reply_get_thread_list(const std::vector<ExtendedTaskId>& threads);\n\n  /**\n   * |ok| is true if the request was successfully applied, false if\n   * not.\n   */\n  void reply_watchpoint_request(bool ok);\n\n  /**\n   * DREQ_DETACH was processed.\n   *\n   * There's no functional reason to reply to the detach request.\n   * However, some versions of gdb expect a response and time out\n   * awaiting it, wasting developer time.\n   */\n  void reply_detach();\n\n  /**\n   * Pass the siginfo_t and its size (as requested by the debugger) in\n   * |si_bytes| and |num_bytes| if successfully read.  Otherwise pass\n   * |si_bytes = nullptr|.\n   */\n  void reply_read_siginfo(const std::vector<uint8_t>& si_bytes);\n  /**\n   * Not yet implemented, but call this after a WRITE_SIGINFO request\n   * anyway.\n   */\n  void reply_write_siginfo(/* TODO*/);\n\n  /**\n   * Send a manual text response to a rr cmd (maintenance) packet.\n   */\n  void reply_rr_cmd(const std::string& text);\n\n  /**\n   * Send a qSymbol response to gdb, requesting the address of the\n   * symbol |name|.\n   */\n  void send_qsymbol(const std::string& name);\n\n  /**\n   * The \"all done\" response to a qSymbol packet from gdb.\n   */\n  void qsymbols_finished();\n\n  /**\n   * Respond to a qGetTLSAddr packet.  If |ok| is true, then respond\n   * with |address|.  If |ok| is false, respond with an error.\n   */\n  void reply_tls_addr(bool ok, remote_ptr<void> address);\n\n  /**\n   * Respond to a vFile:setfs\n   */\n  void reply_setfs(int err);\n  /**\n   * Respond to a vFile:open\n   */\n  void reply_open(int fd, int err);\n  /**\n   * Respond to a vFile:pread\n   */\n  void reply_pread(const uint8_t* bytes, ssize_t len, int err);\n  /**\n   * Respond to a vFile:close\n   */\n  void reply_close(int err);\n\n  /**\n   * Respond to a QSaveRegisterState.\n   * -1 for failure.\n   */\n  void reply_save_register_state(bool ok, int state_index);\n  /**\n   * Respond to a QRestoreRegisterState.\n   */\n  void reply_restore_register_state(bool ok);\n\n  /**\n   * Create a checkpoint of the given Session with the given id. Delete the\n   * existing checkpoint with that id if there is one.\n   */\n  void created_checkpoint(ReplaySession::shr_ptr& checkpoint,\n                          int checkpoint_id);\n\n  /**\n   * Delete the checkpoint with the given id. Silently fail if the checkpoint\n   * does not exist.\n   */\n  void delete_checkpoint(int checkpoint_id);\n\n  /**\n   * Get the checkpoint with the given id. Return null if not found.\n   */\n  ReplaySession::shr_ptr get_checkpoint(int checkpoint_id);\n\n  /**\n   * Return true if there's a new packet to be read/process (whether\n   * incomplete or not), and false if there isn't one.\n   */\n  bool sniff_packet();\n\n  const Features& features() { return features_; }\n\n  enum {\n    CPU_X86_64 = 1 << 0,\n    CPU_AVX = 1 << 1,\n    CPU_AARCH64 = 1 << 2,\n    CPU_PKU = 1 << 3,\n    CPU_AVX512 = 1 << 4\n  };\n\n  void set_cpu_features(SupportedArch arch);\n  uint32_t cpu_features() const { return cpu_features_; }\n\n  GdbServerConnection(ThreadGroupUid tguid, DebuggerType debugger_type,\n    const Features& features);\n\n  /**\n   * Wait for a debugger client to connect to |dbg|'s socket.  Blocks\n   * indefinitely.\n   */\n  void await_debugger(ScopedFd& listen_fd);\n\n  /**\n   *  Returns false if the connection has been closed\n  */\n  bool is_connection_alive();\n\n  bool hwbreak_supported() const { return hwbreak_supported_; }\n  bool swbreak_supported() const { return swbreak_supported_; }\n  bool multiprocess_supported() const { return multiprocess_supported_; }\n\n  bool is_pass_signal(int sig);\n\nprivate:\n  /**\n   * read() incoming data exactly one time, successfully.  May block.\n   */\n  void read_data_once();\n  /**\n   * Send all pending output to gdb.  May block.\n   */\n  void write_flush();\n  void write_data_raw(const uint8_t* data, ssize_t len);\n  void write_hex(unsigned long hex);\n  void write_packet_bytes(const uint8_t* data, size_t num_bytes);\n  void write_packet(const char* data);\n  void write_binary_packet(const char* pfx, const uint8_t* data,\n                           ssize_t num_bytes);\n  void write_hex_bytes_packet(const char* prefix, const uint8_t* bytes,\n                              size_t len);\n  void write_hex_bytes_packet(const uint8_t* bytes, size_t len);\n  void write_xfer_response(const void* data, size_t size, uint64_t offset,\n                           uint64_t len);\n  void parse_thread_suffix_threadid(char* payload, GdbThreadId* out);\n  /**\n   * Consume bytes in the input buffer until start-of-packet ('$') or\n   * the interrupt character is seen.  Does not block.  Return true if\n   * seen, false if not.\n   */\n  bool skip_to_packet_start();\n  /**\n   * Block until the sequence of bytes\n   *\n   *    \"[^$]*\\$[^#]*#.*\"\n   *\n   * has been read from the client fd.  This is one (or more) gdb\n   * packet(s).\n   */\n  void read_packet();\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool xfer(const char* name, char* args);\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool query(char* payload);\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool set_var(char* payload);\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool process_underscore(char* payload);\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool process_vpacket(char* payload);\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool process_bpacket(char* payload);\n  /**\n   * Return true if we need to do something in a debugger request,\n   * false if we already handled the packet internally.\n   */\n  bool process_packet();\n  void consume_request();\n  void send_stop_reply_packet(ExtendedTaskId thread, int sig,\n                              const std::vector<ThreadInfo>& threads,\n                              const std::string& reason);\n  void send_file_error_reply(int system_errno);\n  std::string format_thread_id(ExtendedTaskId thread);\n\n  // Current request to be processed.\n  GdbRequest req;\n  // Thread to be resumed.\n  GdbThreadId resume_thread;\n  // Thread for get/set requests.\n  GdbThreadId query_thread;\n  // gdb and rr don't work well together in multi-process and\n  // multi-exe-image debugging scenarios, so we pretend only\n  // this thread group exists when interfacing with gdb\n  ThreadGroupUid tguid;\n  uint32_t cpu_features_;\n  DebuggerType debugger_type;\n  // true when \"no-ack mode\" enabled, in which we don't have\n  // to send ack packets back to gdb.  This is a huge perf win.\n  bool no_ack;\n  // contains signals (gdb not native) which should be passed directly to the\n  // debuggee without gdb being informed, speeding up\n  // reverse execution\n  std::unordered_set<int> pass_signals;\n  ScopedFd sock_fd;\n  std::vector<uint8_t> inbuf;  /* buffered input from gdb */\n  size_t packetend;            /* index of '#' character */\n  std::vector<uint8_t> outbuf; /* buffered output for gdb */\n  Features features_;\n  bool connection_alive_;\n  bool multiprocess_supported_; // client supports multiprocess extension\n  bool hwbreak_supported_; // client supports hwbreak extension\n  bool swbreak_supported_; // client supports swbreak extension\n  bool list_threads_in_stop_reply_; // client requested threads: and thread-pcs: in stop replies\n  std::unique_ptr<TargetDescription> target_description;\n};\n\n} // namespace rr\n\n#endif /* RR_GDB_CONNECTION_H_ */\n"
  },
  {
    "path": "src/GdbServerExpression.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"GdbServerExpression.h\"\n\n#include \"GdbServer.h\"\n#include \"Task.h\"\n#include \"core.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n#define WORKAROUND_GDB_BUGS\n\n// Extracted from\n// https://sourceware.org/gdb/current/onlinedocs/gdb/Bytecode-Descriptions.html\nenum Opcode {\n  OP_float = 0x01,\n  OP_add = 0x02,\n  OP_sub = 0x03,\n  OP_mul = 0x04,\n  OP_div_signed = 0x05,\n  OP_div_unsigned = 0x06,\n  OP_rem_signed = 0x07,\n  OP_rem_unsigned = 0x08,\n  OP_lsh = 0x09,\n  OP_rsh_signed = 0x0a,\n  OP_rsh_unsigned = 0x0b,\n  OP_trace = 0x0c,\n  OP_trace_quick = 0x0d,\n  OP_log_not = 0x0e,\n  OP_bit_and = 0x0f,\n  OP_bit_or = 0x10,\n  OP_bit_xor = 0x11,\n  OP_bit_not = 0x12,\n  OP_equal = 0x13,\n  OP_less_signed = 0x14,\n  OP_less_unsigned = 0x15,\n  OP_ext = 0x16,\n  OP_ref8 = 0x17,\n  OP_ref16 = 0x18,\n  OP_ref32 = 0x19,\n  OP_ref64 = 0x1a,\n  OP_ref_float = 0x1b,\n  OP_ref_double = 0x1c,\n  OP_ref_long_double = 0x1d,\n  OP_l_to_d = 0x1e,\n  OP_d_to_l = 0x1f,\n  OP_if_goto = 0x20,\n  OP_goto = 0x21,\n  OP_const8 = 0x22,\n  OP_const16 = 0x23,\n  OP_const32 = 0x24,\n  OP_const64 = 0x25,\n  OP_reg = 0x26,\n  OP_end = 0x27,\n  OP_dup = 0x28,\n  OP_pop = 0x29,\n  OP_zero_ext = 0x2a,\n  OP_swap = 0x2b,\n  OP_getv = 0x2c,\n  OP_setv = 0x2d,\n  OP_tracev = 0x2e,\n  OP_tracenz = 0x2f,\n  OP_trace16 = 0x30,\n  OP_pick = 0x32,\n  OP_rot = 0x33,\n  OP_printf = 0x34,\n};\n\nstruct ExpressionState {\n  typedef GdbServerExpression::Value Value;\n\n  ExpressionState(const vector<uint8_t>& bytecode)\n      : bytecode(bytecode), pc(0), error(false), end(false) {}\n\n  void set_error() { error = true; }\n\n  // Methods set error to true if there's an error and return some sentinel\n  // Value.\n  Value pop() {\n    if (stack.empty()) {\n      set_error();\n      return Value(-1);\n    }\n    Value v = stack.back();\n    stack.pop_back();\n    return v;\n  }\n  struct BinaryOperands {\n    BinaryOperands(int64_t a = 0, int64_t b = 0) : a(a), b(b) {}\n    int64_t a;\n    int64_t b;\n  };\n  BinaryOperands pop_a_b() {\n    int64_t b = pop().i;\n    return BinaryOperands(pop().i, b);\n  }\n  int64_t nonzero(int64_t v) {\n    if (!v) {\n      set_error();\n      return 1;\n    }\n    return v;\n  }\n  int64_t pop_a() { return pop().i; }\n  void push(int64_t i) { stack.push_back(Value(i)); }\n  template <typename T> T fetch() {\n    if (pc + sizeof(T) > bytecode.size()) {\n      set_error();\n      return T(-1);\n    }\n    T v = 0;\n    for (size_t i = 0; i < sizeof(T); ++i) {\n      v = (v << 8) | bytecode[pc + i];\n    }\n    pc += sizeof(T);\n    return v;\n  }\n  template <typename T> void load(Task* t) {\n    uint64_t addr = pop().i;\n    if (error) {\n      // Don't do unnecessary syscalls if we're already in an error state.\n      return;\n    }\n    bool ok = true;\n    T v = t->read_mem(remote_ptr<T>(addr), &ok);\n    if (!ok) {\n      set_error();\n      return;\n    }\n    push(v);\n  }\n  void pick(size_t offset) {\n    if (offset >= stack.size()) {\n      set_error();\n      return;\n    }\n    push(stack[stack.size() - 1 - offset].i);\n  }\n\n  void step(ReplayTask* t) {\n    DEBUG_ASSERT(!error);\n    BinaryOperands operands;\n    switch (fetch<uint8_t>()) {\n      case OP_add:\n        operands = pop_a_b();\n        return push(operands.a + operands.b);\n      case OP_sub:\n        operands = pop_a_b();\n        return push(operands.a - operands.b);\n      case OP_mul:\n        operands = pop_a_b();\n        return push(operands.a * operands.b);\n      case OP_div_signed:\n        operands = pop_a_b();\n        return push(operands.a / nonzero(operands.b));\n      case OP_div_unsigned:\n        operands = pop_a_b();\n        return push(uint64_t(operands.a) / uint64_t(nonzero(operands.b)));\n      case OP_rem_signed:\n        operands = pop_a_b();\n        return push(operands.a % nonzero(operands.b));\n      case OP_rem_unsigned:\n        operands = pop_a_b();\n        return push(uint64_t(operands.a) % uint64_t(nonzero(operands.b)));\n      case OP_lsh:\n        operands = pop_a_b();\n        return push(operands.a << operands.b);\n      case OP_rsh_signed:\n        operands = pop_a_b();\n        return push(operands.a >> operands.b);\n      case OP_rsh_unsigned:\n        operands = pop_a_b();\n        return push(uint64_t(operands.a) >> operands.b);\n      case OP_log_not:\n        return push(!pop_a());\n      case OP_bit_and:\n        operands = pop_a_b();\n        return push(operands.a & operands.b);\n      case OP_bit_or:\n        operands = pop_a_b();\n        return push(operands.a | operands.b);\n      case OP_bit_xor:\n        operands = pop_a_b();\n        return push(operands.a ^ operands.b);\n      case OP_bit_not:\n        return push(~pop_a());\n      case OP_equal:\n        operands = pop_a_b();\n        return push(operands.a == operands.b);\n      case OP_less_signed:\n        operands = pop_a_b();\n        return push(operands.a < operands.b);\n      case OP_less_unsigned:\n        operands = pop_a_b();\n        return push(uint64_t(operands.a) < uint64_t(operands.b));\n      case OP_ext: {\n        int64_t n = nonzero(fetch<uint8_t>());\n        if (n >= 64) {\n          return;\n        }\n        int64_t a = pop_a();\n        int64_t n_mask = (int64_t(1) << n) - 1;\n        int sign_bit = (a >> (n - 1)) & 1;\n        return push((sign_bit * ~n_mask) | (a & n_mask));\n      }\n      case OP_zero_ext: {\n        int64_t n = fetch<uint8_t>();\n        if (n >= 64) {\n          return;\n        }\n        int64_t a = pop_a();\n        int64_t n_mask = (int64_t(1) << n) - 1;\n        return push(a & n_mask);\n      }\n      case OP_ref8:\n        return load<uint8_t>(t);\n      case OP_ref16:\n        return load<uint16_t>(t);\n      case OP_ref32:\n        return load<uint32_t>(t);\n      case OP_ref64:\n        return load<uint64_t>(t);\n      case OP_dup:\n        return pick(0);\n      case OP_swap:\n        operands = pop_a_b();\n        push(operands.b);\n        return push(operands.a);\n      case OP_pop:\n        pop_a();\n        return;\n      case OP_pick:\n        return pick(fetch<uint8_t>());\n      case OP_rot: {\n        int64_t c = pop_a();\n        int64_t b = pop_a();\n        int64_t a = pop_a();\n        push(c);\n        push(b);\n        return push(a);\n      }\n      case OP_if_goto: {\n        uint16_t offset = fetch<uint16_t>();\n        if (pop_a()) {\n          pc = offset;\n        }\n        return;\n      }\n      case OP_goto:\n        pc = fetch<uint16_t>();\n        return;\n      case OP_const8:\n        return push(fetch<uint8_t>());\n      case OP_const16:\n        return push(fetch<uint16_t>());\n      case OP_const32:\n        return push(fetch<uint32_t>());\n      case OP_const64:\n        return push(fetch<uint64_t>());\n      case OP_reg: {\n        GdbServerRegisterValue v = GdbServer::get_reg(t->regs(), t->extra_regs(),\n                                                GdbServerRegister(fetch<uint16_t>()));\n        if (!v.defined) {\n          set_error();\n          return;\n        }\n        switch (v.size) {\n          case 1:\n            return push(v.value1);\n          case 2:\n            return push(v.value2);\n          case 4:\n            return push(v.value4);\n          case 8:\n            return push(v.value8);\n        }\n        set_error();\n        return;\n      }\n      case OP_end:\n        end = true;\n        return;\n      default:\n        set_error();\n        return;\n    }\n  }\n\n  const vector<uint8_t>& bytecode;\n  vector<Value> stack;\n  size_t pc;\n  bool error;\n  bool end;\n};\n\n#ifdef WORKAROUND_GDB_BUGS\n/* https://sourceware.org/bugzilla/show_bug.cgi?id=18617 means that\n * gdb generates incorrect operands for OP_ext and OP_zero_ext.\n * We work around this bug by generating all the alternative programs that gdb\n * maybe should have generated, and evaluating all of them. If they agree on\n * the result, we return that as the correct result, otherwise we return\n * failure.\n */\nstatic int count_variants(int bits) {\n  int result = 1;\n  if (bits > 8) {\n    ++result;\n  }\n  if (bits > 16) {\n    ++result;\n  }\n  if (bits > 32) {\n    ++result;\n  }\n  return result;\n}\n\ntemplate <typename T>\nstatic T fetch(const uint8_t* data, size_t size, size_t pc) {\n  if (pc + sizeof(T) > size) {\n    return T(-1);\n  }\n  T v = 0;\n  for (size_t i = 0; i < sizeof(T); ++i) {\n    v = (v << 8) | data[pc + i];\n  }\n  return v;\n}\n\nGdbServerExpression::GdbServerExpression(const uint8_t* data, size_t size) {\n  vector<bool> instruction_starts;\n  instruction_starts.resize(size);\n  fill(instruction_starts.begin(), instruction_starts.end(), false);\n\n  int64_t num_variants = 1;\n\n  vector<size_t> unvisited;\n  unvisited.push_back(0);\n  while (!unvisited.empty()) {\n    size_t pc = unvisited.back();\n    unvisited.pop_back();\n    if (pc >= instruction_starts.size() || instruction_starts[pc]) {\n      continue;\n    }\n    instruction_starts[pc] = true;\n    switch (data[pc]) {\n      case OP_ext:\n      case OP_zero_ext:\n        if (pc + 1 < size) {\n          num_variants *= count_variants(data[pc + 1]);\n          if (num_variants > 64) {\n            // Too many variants, giving up on this expression\n            return;\n          }\n        }\n        unvisited.push_back(pc + 2);\n        break;\n      case OP_pick:\n      case OP_const8:\n        unvisited.push_back(pc + 2);\n        break;\n      case OP_if_goto:\n        unvisited.push_back(fetch<uint16_t>(data, size, pc + 1));\n        unvisited.push_back(pc + 3);\n        break;\n      case OP_goto:\n        unvisited.push_back(fetch<uint16_t>(data, size, pc + 1));\n        break;\n      case OP_const16:\n      case OP_reg:\n        unvisited.push_back(pc + 3);\n        break;\n      case OP_const32:\n        unvisited.push_back(pc + 5);\n        break;\n      case OP_const64:\n        unvisited.push_back(pc + 9);\n        break;\n      case OP_end:\n        break;\n      default:\n        unvisited.push_back(pc + 1);\n        break;\n    }\n  }\n\n  bytecode_variants.push_back(vector<uint8_t>(data, data + size));\n  for (size_t i = 0; i < size; ++i) {\n    if (!instruction_starts[i]) {\n      continue;\n    }\n    if ((data[i] == OP_ext || data[i] == OP_zero_ext) && i + 1 < size) {\n      uint8_t bits = data[i + 1];\n      vector<vector<uint8_t>> variants;\n      for (auto& b : bytecode_variants) {\n        // gdb perhaps should have used a smaller type width here --- 8, 16 or\n        // 32 bits.\n        if (bits > 8) {\n          vector<uint8_t> v = b;\n          v[i + 1] = 8;\n          variants.push_back(std::move(v));\n        }\n        if (bits > 16) {\n          vector<uint8_t> v = b;\n          v[i + 1] = 16;\n          variants.push_back(std::move(v));\n        }\n        if (bits > 32) {\n          vector<uint8_t> v = b;\n          v[i + 1] = 32;\n          variants.push_back(std::move(v));\n        }\n        variants.push_back(std::move(b));\n      }\n      bytecode_variants = std::move(variants);\n    }\n  }\n}\n#else\nGdbServerExpression::GdbServerExpression(const uint8_t* data, size_t size) {\n  bytecode_variants.push_back(vector<uint8_t>(data, data + size));\n}\n#endif\n\nbool GdbServerExpression::evaluate(ReplayTask* t, Value* result) const {\n  if (bytecode_variants.empty()) {\n    return false;\n  }\n\n  bool first = true;\n\n  for (auto& b : bytecode_variants) {\n    ExpressionState state(b);\n    for (int steps = 0; !state.end; ++steps) {\n      if (steps >= 10000 || state.error) {\n        return false;\n      }\n      state.step(t);\n    }\n    Value v = state.pop();\n    if (state.error) {\n      return false;\n    }\n    if (first) {\n      *result = v;\n      first = false;\n    } else if (*result != v) {\n      return false;\n    }\n  }\n\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/GdbServerExpression.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_GDB_EXPRESSION_H_\n#define RR_GDB_EXPRESSION_H_\n\n#include <stddef.h>\n#include <stdint.h>\n\n#include <vector>\n\nnamespace rr {\n\nclass ReplayTask;\n\n/**\n * gdb has a simple bytecode language for writing expressions to be evaluated\n * in a remote target. This class implements evaluation of such expressions.\n * See https://sourceware.org/gdb/current/onlinedocs/gdb/Agent-Expressions.html\n */\nclass GdbServerExpression {\npublic:\n  GdbServerExpression(const uint8_t* data, size_t size);\n\n  struct Value {\n    Value(int64_t i = 0) : i(i) {}\n    bool operator==(const Value& v) { return i == v.i; }\n    bool operator!=(const Value& v) { return !(*this == v); }\n    int64_t i;\n  };\n  /**\n   * If evaluation succeeds, store the final result in *result and return true.\n   * Otherwise return false.\n   */\n  bool evaluate(ReplayTask* t, Value* result) const;\n\nprivate:\n  /**\n   * To work around gdb bugs, we may generate and evaluate multiple versions of\n   * the same expression program.\n   */\n  std::vector<std::vector<uint8_t>> bytecode_variants;\n};\n\n} // namespace rr\n\n#endif // RR_GDB_EXPRESSION_H_\n"
  },
  {
    "path": "src/GdbServerRegister.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_GDB_SERVER_REGISTER_H_\n#define RR_GDB_SERVER_REGISTER_H_\n\nnamespace rr {\n\n/**\n * This is the register numbering used by GDB.\n */\nenum GdbServerRegister {\n  DREG_EAX,\n  DREG_ECX,\n  DREG_EDX,\n  DREG_EBX,\n  DREG_ESP,\n  DREG_EBP,\n  DREG_ESI,\n  DREG_EDI,\n  DREG_EIP,\n  DREG_EFLAGS,\n  DREG_CS,\n  DREG_SS,\n  DREG_DS,\n  DREG_ES,\n  DREG_FS,\n  DREG_GS,\n  DREG_FIRST_FXSAVE_REG,\n  DREG_ST0 = DREG_FIRST_FXSAVE_REG,\n  DREG_ST1,\n  DREG_ST2,\n  DREG_ST3,\n  DREG_ST4,\n  DREG_ST5,\n  DREG_ST6,\n  DREG_ST7,\n  // These are the names GDB gives the registers.\n  DREG_FCTRL,\n  DREG_FSTAT,\n  DREG_FTAG,\n  DREG_FISEG,\n  DREG_FIOFF,\n  DREG_FOSEG,\n  DREG_FOOFF,\n  DREG_FOP,\n  DREG_XMM0,\n  DREG_XMM1,\n  DREG_XMM2,\n  DREG_XMM3,\n  DREG_XMM4,\n  DREG_XMM5,\n  DREG_XMM6,\n  DREG_XMM7,\n  DREG_MXCSR,\n  // XXX the last fxsave reg on *x86*\n  DREG_LAST_FXSAVE_REG = DREG_MXCSR,\n  DREG_ORIG_EAX,\n  DREG_YMM0H,\n  DREG_YMM1H,\n  DREG_YMM2H,\n  DREG_YMM3H,\n  DREG_YMM4H,\n  DREG_YMM5H,\n  DREG_YMM6H,\n  DREG_YMM7H,\n  DREG_ZMM0H,\n  DREG_ZMM1H,\n  DREG_ZMM2H,\n  DREG_ZMM3H,\n  DREG_ZMM4H,\n  DREG_ZMM5H,\n  DREG_ZMM6H,\n  DREG_ZMM7H,\n  DREG_K0,\n  DREG_K1,\n  DREG_K2,\n  DREG_K3,\n  DREG_K4,\n  DREG_K5,\n  DREG_K6,\n  DREG_K7,\n  DREG_PKRU,\n  DREG_NUM_LINUX_I386,\n  // Last register we can find in user_regs_struct\n  // (except for orig_eax).\n  DREG_NUM_USER_REGS = DREG_GS + 1,\n\n  // x86-64 register numbers\n  DREG_RAX = 0,\n  DREG_RBX,\n  DREG_RCX,\n  DREG_RDX,\n  DREG_RSI,\n  DREG_RDI,\n  DREG_RBP,\n  DREG_RSP,\n  DREG_R8,\n  DREG_R9,\n  DREG_R10,\n  DREG_R11,\n  DREG_R12,\n  DREG_R13,\n  DREG_R14,\n  DREG_R15,\n  DREG_RIP,\n  // Things get a little tricky here, because x86-64 has some registers\n  // named identically to its x86 counterpart, but we've used the names\n  // in the x86 register definitions above, and the numbers they need\n  // to represent are different.  Hence the unique names here.\n  DREG_64_EFLAGS,\n  DREG_64_CS,\n  DREG_64_SS,\n  DREG_64_DS,\n  DREG_64_ES,\n  DREG_64_FS,\n  DREG_64_GS,\n  DREG_64_FIRST_FXSAVE_REG,\n  DREG_64_ST0 = DREG_64_FIRST_FXSAVE_REG,\n  DREG_64_ST1,\n  DREG_64_ST2,\n  DREG_64_ST3,\n  DREG_64_ST4,\n  DREG_64_ST5,\n  DREG_64_ST6,\n  DREG_64_ST7,\n  // These are the names GDB gives the registers.\n  DREG_64_FCTRL,\n  DREG_64_FSTAT,\n  DREG_64_FTAG,\n  DREG_64_FISEG,\n  DREG_64_FIOFF,\n  DREG_64_FOSEG,\n  DREG_64_FOOFF,\n  DREG_64_FOP,\n  DREG_64_XMM0,\n  DREG_64_XMM1,\n  DREG_64_XMM2,\n  DREG_64_XMM3,\n  DREG_64_XMM4,\n  DREG_64_XMM5,\n  DREG_64_XMM6,\n  DREG_64_XMM7,\n  DREG_64_XMM8,\n  DREG_64_XMM9,\n  DREG_64_XMM10,\n  DREG_64_XMM11,\n  DREG_64_XMM12,\n  DREG_64_XMM13,\n  DREG_64_XMM14,\n  DREG_64_XMM15,\n  DREG_64_MXCSR,\n  DREG_64_LAST_FXSAVE_REG = DREG_64_MXCSR,\n  DREG_ORIG_RAX,\n  DREG_FS_BASE,\n  DREG_GS_BASE,\n  DREG_64_YMM0H,\n  DREG_64_YMM1H,\n  DREG_64_YMM2H,\n  DREG_64_YMM3H,\n  DREG_64_YMM4H,\n  DREG_64_YMM5H,\n  DREG_64_YMM6H,\n  DREG_64_YMM7H,\n  DREG_64_YMM8H,\n  DREG_64_YMM9H,\n  DREG_64_YMM10H,\n  DREG_64_YMM11H,\n  DREG_64_YMM12H,\n  DREG_64_YMM13H,\n  DREG_64_YMM14H,\n  DREG_64_YMM15H,\n  DREG_64_XMM16,\n  DREG_64_XMM17,\n  DREG_64_XMM18,\n  DREG_64_XMM19,\n  DREG_64_XMM20,\n  DREG_64_XMM21,\n  DREG_64_XMM22,\n  DREG_64_XMM23,\n  DREG_64_XMM24,\n  DREG_64_XMM25,\n  DREG_64_XMM26,\n  DREG_64_XMM27,\n  DREG_64_XMM28,\n  DREG_64_XMM29,\n  DREG_64_XMM30,\n  DREG_64_XMM31,\n  DREG_64_YMM16H,\n  DREG_64_YMM17H,\n  DREG_64_YMM18H,\n  DREG_64_YMM19H,\n  DREG_64_YMM20H,\n  DREG_64_YMM21H,\n  DREG_64_YMM22H,\n  DREG_64_YMM23H,\n  DREG_64_YMM24H,\n  DREG_64_YMM25H,\n  DREG_64_YMM26H,\n  DREG_64_YMM27H,\n  DREG_64_YMM28H,\n  DREG_64_YMM29H,\n  DREG_64_YMM30H,\n  DREG_64_YMM31H,\n  DREG_64_ZMM0H,\n  DREG_64_ZMM1H,\n  DREG_64_ZMM2H,\n  DREG_64_ZMM3H,\n  DREG_64_ZMM4H,\n  DREG_64_ZMM5H,\n  DREG_64_ZMM6H,\n  DREG_64_ZMM7H,\n  DREG_64_ZMM8H,\n  DREG_64_ZMM9H,\n  DREG_64_ZMM10H,\n  DREG_64_ZMM11H,\n  DREG_64_ZMM12H,\n  DREG_64_ZMM13H,\n  DREG_64_ZMM14H,\n  DREG_64_ZMM15H,\n  DREG_64_ZMM16H,\n  DREG_64_ZMM17H,\n  DREG_64_ZMM18H,\n  DREG_64_ZMM19H,\n  DREG_64_ZMM20H,\n  DREG_64_ZMM21H,\n  DREG_64_ZMM22H,\n  DREG_64_ZMM23H,\n  DREG_64_ZMM24H,\n  DREG_64_ZMM25H,\n  DREG_64_ZMM26H,\n  DREG_64_ZMM27H,\n  DREG_64_ZMM28H,\n  DREG_64_ZMM29H,\n  DREG_64_ZMM30H,\n  DREG_64_ZMM31H,\n  // We've moved K0..K7 to here, because it simplifies offset calculation for XMM16/YMM16/HiZMM offsets\n  // target description 64bit-avx512.xml also reflects this\n  DREG_64_K0,\n  DREG_64_K1,\n  DREG_64_K2,\n  DREG_64_K3,\n  DREG_64_K4,\n  DREG_64_K5,\n  DREG_64_K6,\n  DREG_64_K7,\n  DREG_64_PKRU,\n  DREG_NUM_LINUX_X86_64,\n  // Last register we can find in user_regs_struct (except for orig_rax).\n  DREG_64_NUM_USER_REGS = DREG_64_GS + 1,\n\n  // aarch64-core.xml\n  DREG_X0 = 0,\n  DREG_X1,\n  DREG_X2,\n  DREG_X3,\n  DREG_X4,\n  DREG_X5,\n  DREG_X6,\n  DREG_X7,\n  DREG_X8,\n  DREG_X9,\n  DREG_X10,\n  DREG_X11,\n  DREG_X12,\n  DREG_X13,\n  DREG_X14,\n  DREG_X15,\n  DREG_X16,\n  DREG_X17,\n  DREG_X18,\n  DREG_X19,\n  DREG_X20,\n  DREG_X21,\n  DREG_X22,\n  DREG_X23,\n  DREG_X24,\n  DREG_X25,\n  DREG_X26,\n  DREG_X27,\n  DREG_X28,\n  DREG_X29,\n  DREG_X30,\n  DREG_SP,\n  DREG_PC,\n  DREG_CPSR,\n\n  // aarch64-fpu.xml\n  DREG_V0 = 34,\n  DREG_V1,\n  DREG_V2,\n  DREG_V3,\n  DREG_V4,\n  DREG_V5,\n  DREG_V6,\n  DREG_V7,\n  DREG_V8,\n  DREG_V9,\n  DREG_V10,\n  DREG_V11,\n  DREG_V12,\n  DREG_V13,\n  DREG_V14,\n  DREG_V15,\n  DREG_V16,\n  DREG_V17,\n  DREG_V18,\n  DREG_V19,\n  DREG_V20,\n  DREG_V21,\n  DREG_V22,\n  DREG_V23,\n  DREG_V24,\n  DREG_V25,\n  DREG_V26,\n  DREG_V27,\n  DREG_V28,\n  DREG_V29,\n  DREG_V30,\n  DREG_V31,\n  DREG_FPSR,\n  DREG_FPCR,\n\n  DREG_NUM_LINUX_AARCH64 = DREG_FPCR + 1,\n};\n\n} // namespace rr\n\n#endif /* RR_GDB_SERVER_REGISTER_H_ */\n"
  },
  {
    "path": "src/HasTaskSet.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"HasTaskSet.h\"\n\n#include \"Task.h\"\n#include \"log.h\"\n\nnamespace rr {\n\nvoid HasTaskSet::insert_task(Task* t) {\n  LOG(debug) << \"adding \" << t->tid << \" to task set \" << this;\n  tasks.insert(t);\n}\n\nvoid HasTaskSet::erase_task(Task* t) {\n  LOG(debug) << \"removing \" << t->tid << \" from task set \" << this;\n  tasks.erase(t);\n}\n\nTask* HasTaskSet::first_running_task() const {\n  for (Task* t : task_set()) {\n    if (!t->already_exited() && !t->seen_ptrace_exit_event()) {\n      return t;\n    }\n  }\n  return nullptr;\n}\n\nTask* HasTaskSet::find_other_thread_group(Task* t) const {\n  for (Task* tt : task_set()) {\n    if (tt->thread_group() != t->thread_group()) {\n      return tt;\n    }\n  }\n  return nullptr;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/HasTaskSet.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_HASTASKSET_H_\n#define RR_HASTASKSET_H_\n\n#include <set>\n\nnamespace rr {\n\nclass Task;\n\n/**\n * Base class for classes that manage a set of Tasks.\n */\nclass HasTaskSet {\npublic:\n  // Has virtual methods, therefore must have virtual destructor\n  virtual ~HasTaskSet() {}\n\n  typedef std::set<Task*> TaskSet;\n\n  const TaskSet& task_set() const { return tasks; }\n\n  virtual void insert_task(Task* t);\n  virtual void erase_task(Task* t);\n  bool has_task(Task* t) const { return tasks.find(t) != tasks.end(); }\n  Task* find_other_thread_group(Task* t) const;\n  Task* first_running_task() const;\n\nprotected:\n  TaskSet tasks;\n};\n\n} // namespace rr\n\n#endif /* RR_HASTASKSET_H_ */\n"
  },
  {
    "path": "src/HelpCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Command.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass HelpCommand : public Command {\npublic:\n  virtual int run(std::vector<std::string>& args) override;\n\nprotected:\n  HelpCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static HelpCommand help1;\n  static HelpCommand help2;\n  static HelpCommand help3;\n};\n\nHelpCommand HelpCommand::help1(\"help\", \" rr help [command]\\n\");\nHelpCommand HelpCommand::help2(\"-h\", nullptr);\nHelpCommand HelpCommand::help3(\"--help\", nullptr);\n\nint HelpCommand::run(std::vector<std::string>& args) {\n  if (args.size() == 0) {\n    print_usage(stdout);\n  }\n\n  Command* command = Command::command_for_name(args[0]);\n  if (!command) {\n    print_usage(stderr);\n  }\n  command->print_help(stdout);\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/LldbInitCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Command.h\"\n#include \"GdbServer.h\"\n#include \"launch_debugger.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass LldbInitCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  LldbInitCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static LldbInitCommand singleton;\n};\n\nLldbInitCommand LldbInitCommand::singleton(\"lldbinit\", \" rr lldbinit\\n\");\n\nint LldbInitCommand::run(vector<string>& args) {\n  while (parse_global_option(args)) {\n  }\n\n  puts(\"# This is a Python script. Save it to a file and run it from LLDB using\");\n  puts(\"#     script exec(open('<filename>').read())\");\n  puts(\"# or similar.\");\n  fputs(lldb_init_script().c_str(), stdout);\n  return 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/LsCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <assert.h>\n#include <dirent.h>\n\n#include <algorithm>\n#include <iomanip>\n#include <memory>\n#include <numeric>\n#include <sstream>\n#include <vector>\n\n#include \"Command.h\"\n#include \"main.h\"\n#include \"TraceStream.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass LsCommand : public Command {\npublic:\n  virtual int run(vector<string>& args);\n\nprotected:\n  LsCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static LsCommand singleton;\n};\n\nLsCommand LsCommand::singleton(\n    \"ls\", \" rr ls [OPTION]...\\n\"\n          \"  -l, --long-listing use a long listing format\\n\"\n          \"     (trace name | start time | size | command line)\\n\"\n          \"  -t, --sort-by-age, sort from newest to oldest\\n\"\n          \"  -r, --reverse, the sort order\\n\");\n\nstruct LsFlags {\n  bool reverse;\n  bool full_listing;\n  bool sort_by_time;\n  LsFlags() : reverse(false), full_listing(false), sort_by_time(false) {}\n};\n\nstatic bool parse_ls_arg(vector<string>& args, LsFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = { { 'r', \"reverse\", NO_PARAMETER },\n                                        { 'l', \"long-listing\", NO_PARAMETER },\n                                        { 't', \"sort-by-age\", NO_PARAMETER } };\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 'r':\n      flags.reverse = true;\n      break;\n    case 'l':\n      flags.full_listing = true;\n      break;\n    case 't':\n      flags.sort_by_time = true;\n      break;\n    default:\n      assert(0 && \"Unknown option\");\n  }\n\n  return true;\n}\n\nstruct TraceInfo {\n  string name;\n  struct timespec ctime;\n  string exit;\n\n  TraceInfo(string in_name) : name(in_name) {}\n};\n\nstatic bool compare_by_name(const TraceInfo& at, const TraceInfo& bt) {\n  auto a = at.name;\n  auto b = bt.name;\n  return lexicographical_compare(begin(a), end(a), begin(b), end(b));\n}\n\nstatic bool get_folder_size(string dir_name, string& size_str) {\n  DIR* dir = opendir(dir_name.c_str());\n  if (!dir) {\n    cerr << \"Cannot open \" << dir_name << endl;\n    return false;\n  }\n\n  size_t bytes = 0;\n  while (struct dirent* ent = readdir(dir)) {\n    string path = dir_name + \"/\" + ent->d_name;\n\n    struct stat st;\n    if (stat(path.c_str(), &st) == -1) {\n      cerr << \"stat \" << path << \" failed\\n\";\n      return false;\n    }\n\n    bytes += st.st_size;\n  }\n  closedir(dir);\n\n  static const char suffixes[] = \" KMGT\";\n  double size = bytes;\n  size_t suffix_idx = 0;\n  while (size >= 1000.0) {\n    size /= 1024.0;\n    suffix_idx++;\n  }\n  char suffix = suffixes[suffix_idx];\n\n  ostringstream cvt;\n\n  if (suffix == ' ') {\n    cvt << bytes;\n  } else if (size >= 10) {\n    cvt << int(size) << suffix;\n  } else {\n    cvt << fixed << setprecision(1) << size << suffix;\n  }\n\n  size_str = cvt.str();\n  return true;\n}\n\nstatic string get_exec_path(TraceReader& reader) {\n  while (true) {\n    TraceTaskEvent r = reader.read_task_event();\n    if (r.type() == TraceTaskEvent::NONE) {\n      break;\n    }\n    if (r.type() == TraceTaskEvent::EXEC) {\n      return r.cmd_line()[0];\n    }\n  }\n  return string();\n}\n\nstring find_exit_code(pid_t pid, const vector<TraceTaskEvent>& events,\n                      size_t current_event,\n                      const map<pid_t, pid_t> current_tid_to_pid);\n\nstatic int ls(const string& traces_dir, const LsFlags& flags, FILE* out) {\n  DIR* dir = opendir(traces_dir.c_str());\n  if (!dir) {\n    fprintf(stderr, \"Cannot open %s\\n\", traces_dir.c_str());\n    return 1;\n  }\n\n  const string cpu_lock = real_path(get_cpu_lock_file());\n  const string full_traces_dir = real_path(traces_dir) + \"/\";\n  vector<TraceInfo> traces;\n\n  while (struct dirent* trace_dir = readdir(dir)) {\n    if (full_traces_dir + trace_dir->d_name == cpu_lock) {\n      continue;\n    }\n    if (!is_valid_trace_name(trace_dir->d_name)) {\n      continue;\n    }\n    traces.emplace_back(TraceInfo(string(trace_dir->d_name)));\n    if (flags.sort_by_time || flags.full_listing) {\n      struct stat st;\n      stat((traces_dir + \"/\" + trace_dir->d_name + \"/data\").c_str(), &st);\n      traces.back().ctime = st.st_ctim;\n    }\n\n    if (flags.full_listing) {\n      TraceReader trace(traces_dir + \"/\" + trace_dir->d_name);\n\n      vector<TraceTaskEvent> events;\n      while (true) {\n        TraceTaskEvent r = trace.read_task_event();\n        if (r.type() == TraceTaskEvent::NONE) {\n          break;\n        }\n        events.push_back(r);\n      }\n\n      if (events.empty() || events[0].type() != TraceTaskEvent::EXEC) {\n        traces.back().exit = \"????\";\n        continue;\n      }\n\n      map<pid_t, pid_t> tid_to_pid;\n      pid_t initial_tid = events[0].tid();\n      tid_to_pid[initial_tid] = initial_tid;\n      traces.back().exit = find_exit_code(initial_tid, events, 0, tid_to_pid);\n    }\n  }\n  closedir(dir);\n\n  if (flags.sort_by_time) {\n    auto compare_by_time = [&](const TraceInfo& at,\n                               const TraceInfo& bt) -> bool {\n      if (at.ctime.tv_sec == bt.ctime.tv_sec) {\n        return at.ctime.tv_nsec < bt.ctime.tv_nsec;\n      }\n      return at.ctime.tv_sec < bt.ctime.tv_sec;\n    };\n    sort(traces.begin(), traces.end(), compare_by_time);\n  } else {\n    sort(traces.begin(), traces.end(), compare_by_name);\n  }\n\n  if (flags.reverse) {\n    reverse(begin(traces), end(traces));\n  };\n\n  if (!flags.full_listing) {\n    for (TraceInfo& t : traces) {\n      cout << t.name << \"\\n\";\n    }\n    return 0;\n  }\n\n  int max_name_size =\n    accumulate(traces.begin(), traces.end(), 0, [](int m, TraceInfo& t) {\n        return max(m, static_cast<int>(t.name.length()));\n    });\n\n  fprintf(out, \"%-*s %-19s %5s %6s %s\\n\", max_name_size,\n          \"NAME\", \"WHEN\", \"SIZE\", \"EXIT\", \"CMD\");\n\n  for (TraceInfo& t : traces) {\n    // Record date & runtime estimates\n    string data_file = traces_dir + \"/\" + t.name + \"/data\";\n    char outstr[200];\n    struct tm ctime_tm;\n    if (localtime_r(&t.ctime.tv_sec, &ctime_tm)) {\n      strftime(outstr, sizeof(outstr), \"%F %T\", &ctime_tm);\n    } else {\n      strcpy(outstr, \"<error>\");\n    }\n\n    string folder_size = \"????\";\n    string exe = \"(incomplete)\";\n    string version_file = traces_dir + \"/\" + t.name + \"/version\";\n    struct stat st;\n    if (stat(version_file.c_str(), &st) != -1) {\n      TraceReader reader(traces_dir + \"/\" + t.name);\n      get_folder_size(reader.dir(), folder_size);\n      exe = get_exec_path(reader);\n    }\n\n    fprintf(out, \"%-*s %s %5s %6s %s\\n\", max_name_size, t.name.c_str(),\n            outstr, folder_size.c_str(), t.exit.c_str(), exe.c_str());\n  }\n\n  return 0;\n}\n\nint LsCommand::run(vector<string>& args) {\n  bool found_dir = false;\n  string trace_dir;\n  LsFlags flags;\n\n  while (!args.empty()) {\n    if (parse_ls_arg(args, flags)) {\n      continue;\n    }\n    if (!found_dir && parse_optional_trace_dir(args, &trace_dir)) {\n      found_dir = true;\n      continue;\n    }\n    print_help(stderr);\n    return 1;\n  };\n\n  if (!found_dir) {\n    trace_dir = trace_save_dir();\n  }\n  return ls(trace_dir, flags, stdout);\n};\n\n} // namespace rr\n"
  },
  {
    "path": "src/MagicSaveDataMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"MagicSaveDataMonitor.h\"\n\n#include <limits.h>\n\n#include <rr/rr.h>\n\n#include \"RecordTask.h\"\n#include \"ReplayTask.h\"\n#include \"Session.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic string dump_path_data(Task* t, FrameTime global_time, const char* tag,\n                           const void* buf, size_t buf_len,\n                           remote_ptr<void> addr) {\n  string filename = format_dump_filename(t, global_time, tag);\n  dump_binary_data(filename.c_str(), tag, (const uint32_t*)buf, buf_len / 4,\n                   addr);\n  return filename;\n}\n\nstatic void notify_save_data_error(ReplayTask* t, remote_ptr<void> addr,\n                                   const void* rec_buf, size_t rec_buf_len,\n                                   const void* rep_buf, size_t rep_buf_len) {\n  FrameTime global_time = t->current_trace_frame().time();\n  string rec_dump = dump_path_data(t, global_time, \"rec_save_data\",\n                                   rec_buf, rec_buf_len, addr);\n  string rep_dump = dump_path_data(t, global_time, \"rep_save_data\",\n                                   rep_buf, rep_buf_len, addr);\n\n  ASSERT(t,\n         (rec_buf_len == rep_buf_len && !memcmp(rec_buf, rep_buf, rec_buf_len)))\n      << \"Divergence in contents of 'tracee-save buffer'.  Recording executed\\n\"\n         \"\\n\"\n         \"  write(\"\n      << RR_MAGIC_SAVE_DATA_FD << \", \" << addr << \", \" << rec_buf_len\n      << \")\\n\"\n         \"\\n\"\n         \"and replay executed\\n\"\n         \"\\n\"\n         \"  write(\"\n      << RR_MAGIC_SAVE_DATA_FD << \", \" << addr << \", \" << rep_buf_len\n      << \")\\n\"\n         \"\\n\"\n         \"The contents of the tracee-save buffers have been dumped to disk.\\n\"\n         \"Compare them by using the following command\\n\"\n         \"\\n\"\n         \"$ diff -u \"\n      << rec_dump << \" \" << rep_dump << \" >save-data-diverge.diff\\n\";\n}\n\nvoid MagicSaveDataMonitor::did_write(Task* t, const std::vector<Range>& ranges,\n                                     LazyOffset&) {\n  for (auto& r : ranges) {\n    if (t->session().is_recording()) {\n      static_cast<RecordTask*>(t)->record_remote(r.data.cast<uint8_t>(),\n                                                 r.length);\n    } else if (t->session().is_replaying()) {\n      auto rt = static_cast<ReplayTask*>(t);\n      auto bytes = rt->read_mem(r.data.cast<uint8_t>(), r.length);\n      TraceReader::RawData rec;\n      bool ok = rt->trace_reader().read_raw_data_for_frame(rec);\n      ASSERT(t, ok);\n      if (rec.data != bytes) {\n        notify_save_data_error(rt, rec.addr, rec.data.data(), rec.data.size(),\n                               bytes.data(), bytes.size());\n      }\n    }\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/MagicSaveDataMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_MAGIC_SAVE_DATA_MONITOR_H_\n#define RR_MAGIC_SAVE_DATA_MONITOR_H_\n\n#include \"FileMonitor.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor to track writes to RR_MAGIC_SAVE_DATA_FD.\n */\nclass MagicSaveDataMonitor : public FileMonitor {\npublic:\n  MagicSaveDataMonitor() {}\n\n  virtual Type type() override { return MagicSaveData; }\n\n  virtual void did_write(Task* t, const std::vector<Range>& ranges,\n                         LazyOffset& offset) override;\n};\n\n} // namespace rr\n\n#endif /* RR_MAGIC_SAVE_DATA_MONITOR_H_ */\n"
  },
  {
    "path": "src/MemoryRange.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_MEMORY_RANGE_H_\n#define RR_MEMORY_RANGE_H_\n\n#include \"core.h\"\n#include \"log.h\"\n#include \"remote_ptr.h\"\n\nnamespace rr {\n\n/**\n * Range of memory addresses that can be used as a std::map key.\n */\nclass MemoryRange {\npublic:\n  MemoryRange() {}\n  MemoryRange(remote_ptr<void> addr, size_t num_bytes)\n      : start_(addr), end_(addr + num_bytes) {\n    DEBUG_ASSERT(start_ <= end_);\n  }\n  MemoryRange(remote_ptr<void> addr, remote_ptr<void> end)\n      : start_(addr), end_(end) {\n    DEBUG_ASSERT(start_ <= end);\n  }\n  MemoryRange(const MemoryRange&) = default;\n  MemoryRange& operator=(const MemoryRange&) = default;\n\n  bool operator==(const MemoryRange& o) const {\n    return start_ == o.start_ && end_ == o.end_;\n  }\n  bool operator<(const MemoryRange& o) const {\n    return start_ != o.start_ ? start_ < o.start_ : end_ < o.end_;\n  }\n\n  /**\n   * Return true iff |o| is an address range fully contained by\n   * this.\n   */\n  bool contains(const MemoryRange& o) const {\n    return start_ <= o.start_ && o.end_ <= end_;\n  }\n  bool contains(remote_ptr<void> p) const { return start_ <= p && p < end_; }\n\n  template <typename T> bool contains(remote_ptr<T> ptr, size_t count = 1) const {\n    auto o_start_ = ptr.template cast<void>();\n    auto o_end_ = (ptr + count).template cast<void>();\n    return start_ <= o_start_ && o_end_ <= end_;\n  }\n\n  bool intersects(const MemoryRange& other) const {\n    remote_ptr<void> s = std::max(start_, other.start_);\n    remote_ptr<void> e = std::min(end_, other.end_);\n    return s < e;\n  }\n\n  MemoryRange intersect(const MemoryRange& other) const {\n    remote_ptr<void> s = std::max(start_, other.start_);\n    remote_ptr<void> e = std::min(end_, other.end_);\n    return MemoryRange(s, std::max(s, e));\n  }\n\n  remote_ptr<void> start() const { return start_; }\n  remote_ptr<void> end() const { return end_; }\n  size_t size() const { return end_ - start_; }\n\n  static MemoryRange all() {\n    return MemoryRange(remote_ptr<void>(), remote_ptr<void>(UINTPTR_MAX));\n  }\n\n  // XXX DO NOT USE\n  void update_start(remote_ptr<void> s) const {\n    const_cast<MemoryRange*>(this)->start_ = s;\n  }\n\nprivate:\n  remote_ptr<void> start_;\n  remote_ptr<void> end_;\n};\n\ninline std::ostream& operator<<(std::ostream& o, const MemoryRange& m) {\n  o << m.start() << \"-\" << m.end();\n  return o;\n}\n\n} // namespace rr\n\n#endif /* RR_MEMORY_RANGE_H_ */\n"
  },
  {
    "path": "src/MmappedFileMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"MmappedFileMonitor.h\"\n\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"ReplayTask.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nMmappedFileMonitor::MmappedFileMonitor(Task* t, int fd) {\n  ASSERT(t, !t->session().is_replaying());\n  dead_ = false;\n  auto stat = t->stat_fd(fd);\n  device_ = stat.st_dev;\n  inode_ = stat.st_ino;\n}\n\nMmappedFileMonitor::MmappedFileMonitor(Task* t, EmuFile::shr_ptr f) {\n  ASSERT(t, t->session().is_replaying());\n\n  dead_ = false;\n  device_ = f->device();\n  inode_ = f->inode();\n}\n\nvoid MmappedFileMonitor::did_write(Task* t, const std::vector<Range>& ranges,\n                                   LazyOffset& offset) {\n  // If there are no remaining mappings that we care about, those can't reappear\n  // without going through mmap again, at which point this will be reset to\n  // false.\n  if (dead_) {\n    return;\n  }\n\n  if (ranges.empty()) {\n    return;\n  }\n\n  // Dead until proven otherwise\n  dead_ = true;\n  int64_t realized_offset = 0;\n\n  bool is_replay = t->session().is_replaying();\n  for (auto v : t->session().vms()) {\n    for (const auto& m : v->maps()) {\n      auto km = m.map;\n\n      if (is_replay) {\n        if (!m.emu_file || m.emu_file->device() != device_ ||\n            m.emu_file->inode() != inode_) {\n          continue;\n        }\n      } else {\n        if (km.device() != device_ || km.inode() != inode_) {\n          continue;\n        }\n        // If the mapping is MAP_PRIVATE then this write is dangerous\n        // because it's unpredictable what will be seen in the mapping.\n        // However, it could be OK if the application doesn't read from\n        // this part of the mapping. Just optimistically assume this mapping\n        // is not affected.\n        if (!(km.flags() & MAP_SHARED)) {\n          LOG(warn) << \"MAP_PRIVATE mapping affected by write\";\n          continue;\n        }\n      }\n\n      // We're discovering a mapping we care about\n      if (dead_) {\n        dead_ = false;\n        realized_offset = offset.retrieve(true);\n      }\n\n      // stat matches.\n      uint64_t mapping_offset = km.file_offset_bytes();\n      int64_t local_offset = realized_offset;\n      for (auto r : ranges) {\n        remote_ptr<void> start = km.start() + local_offset - mapping_offset;\n        MemoryRange mr(start, r.length);\n        if (km.intersects(mr)) {\n          if (is_replay) {\n            // If we're writing beyond the EmuFile's end, resize it.\n            m.emu_file->ensure_size(local_offset + r.length);\n          } else {\n            ASSERT(t, !v->task_set().empty());\n            // We will record multiple writes if the file is mapped multiple\n            // times. This is inefficient --- one is sufficient --- but not\n            // wrong.\n            // Make sure we use a task for this address space. `t` might have\n            // a different address space.\n            for (auto tt : v->task_set()) {\n              // If the task here has execed, we may not be able to record its\n              // memory any longer, so loop through all tasks in this address\n              // space in turn in case any *didn't* exec.\n              if (!tt->already_exited() && static_cast<RecordTask*>(tt)->record_remote_fallible(km.intersect(mr)) > 0) {\n                break;\n              }\n            }\n          }\n        }\n        local_offset += r.length;\n      }\n    }\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/MmappedFileMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_MMAPPED_FILE_MONITOR_H_\n#define RR_MMAPPED_FILE_MONITOR_H_\n\n#include \"EmuFs.h\"\n#include \"FileMonitor.h\"\n\n#include <sys/stat.h>\n\nnamespace rr {\n\n/**\n * A FileMonitor to track writes to files that are mmapped in so they can be\n * replayed.\n */\nclass MmappedFileMonitor : public FileMonitor {\npublic:\n  MmappedFileMonitor(Task* t, int fd);\n  MmappedFileMonitor(Task* t, EmuFile::shr_ptr f);\n\n  virtual Type type() override { return Mmapped; }\n  void revive() { dead_ = false; }\n  // If this write could potentially affect memory we need to PREVENT_SWITCH,\n  // since the timing of the write is otherwise unpredictable from our\n  // perspective.\n  virtual Switchable will_write(Task*) override {\n    return dead_ ? ALLOW_SWITCH : PREVENT_SWITCH;\n  }\n\n  /**\n   * During recording, note writes to mapped segments.\n   */\n  virtual void did_write(Task* t, const std::vector<Range>& ranges,\n                         LazyOffset& offset) override;\n\nprivate:\n  // Whether this monitor is still actively monitoring\n  bool dead_;\n  dev_t device_;\n  ino_t inode_;\n};\n\n} // namespace rr\n\n#endif /* RR_MMAPPED_FILE_MONITOR_H_ */\n"
  },
  {
    "path": "src/MonitoredSharedMemory.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"MonitoredSharedMemory.h\"\n\n#include <sys/mman.h>\n\n#include \"AddressSpace.h\"\n#include \"AutoRemoteSyscalls.h\"\n#include \"RecordTask.h\"\n#include \"Session.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nMonitoredSharedMemory::~MonitoredSharedMemory() { munmap(real_mem, size); }\n\nstatic const char dconf_suffix[] = \"/dconf/user\";\n\nvoid MonitoredSharedMemory::maybe_monitor(RecordTask* t,\n                                          const string& file_name,\n                                          const AddressSpace::Mapping& m,\n                                          int tracee_fd, uint64_t offset) {\n  size_t dconf_suffix_len = sizeof(dconf_suffix) - 1;\n  if (file_name.size() < dconf_suffix_len ||\n      file_name.substr(file_name.size() - dconf_suffix_len) != dconf_suffix) {\n    return;\n  }\n\n  AutoRemoteSyscalls remote(t);\n\n  ScopedFd fd = remote.retrieve_fd(tracee_fd);\n  if (!fd.is_open()) {\n    // Tracee died\n    return;\n  }\n  uint8_t* real_mem = static_cast<uint8_t*>(\n      mmap(NULL, m.map.size(), PROT_READ, MAP_SHARED, fd, offset));\n  ASSERT(t, real_mem != MAP_FAILED);\n\n  auto result = shared_ptr<MonitoredSharedMemory>(\n      new MonitoredSharedMemory(real_mem, m.map.size()));\n\n  AddressSpace::Mapping shared =\n      Session::steal_mapping(remote, m, std::move(result));\n  // m may be invalid now\n  if (!shared.local_addr) {\n    // tracee died\n    return;\n  }\n  memcpy(shared.local_addr, real_mem, shared.map.size());\n}\n\nMonitoredSharedMemory::shr_ptr MonitoredSharedMemory::subrange(uintptr_t,\n                                                               uintptr_t) {\n  DEBUG_ASSERT(false && \"Subranges not supported yet!\");\n  return nullptr;\n}\n\nvoid MonitoredSharedMemory::check_all(RecordTask* t) {\n  vector<remote_ptr<void>> addrs;\n  for (auto a : t->vm()->monitored_addrs()) {\n    addrs.push_back(a);\n  }\n  for (auto a : addrs) {\n    auto m = t->vm()->mapping_of(a);\n    if (m.monitored_shared_memory) {\n      m.monitored_shared_memory->check_for_changes(t, m);\n    }\n  }\n}\n\nvoid MonitoredSharedMemory::check_for_changes(RecordTask* t,\n                                              AddressSpace::Mapping& m) {\n  ASSERT(t, m.map.size() == size);\n  if (!m.local_addr) {\n    // reestablish local mapping after a fork or whatever\n    AutoRemoteSyscalls remote(t);\n    auto msm = m.monitored_shared_memory;\n    m = Session::recreate_shared_mmap(remote, m, Session::DISCARD_CONTENTS,\n                                      std::move(msm));\n    if (!m.local_addr) {\n      // Tracee died.\n      return;\n    }\n  }\n  if (!memcmp(m.local_addr, real_mem, size)) {\n    return;\n  }\n  memcpy(m.local_addr, real_mem, size);\n  t->record_local(m.map.start(), size, real_mem);\n}\n}\n"
  },
  {
    "path": "src/MonitoredSharedMemory.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_MONITORED_SHARED_MEMORY_H_\n#define RR_MONITORED_SHARED_MEMORY_H_\n\n#include <memory>\n\n#include \"AddressSpace.h\"\n\nnamespace rr {\n\nclass RecordTask;\n\n/**\n * Support tracees that share memory read-only with a non-tracee that\n * writes to the memory. Currently this just supports limited cases that\n * suffice for dconf: no remapping, coalescing or splitting of the memory is\n * allowed (|subrange| below just asserts). It doesn't handle mappings where\n * the mapping has more pages than the file.\n *\n * After such memory is mapped in the tracee, we also map it in rr at |real_mem|\n * and replace the tracee's mapping with a \"shadow buffer\" that's only shared\n * with rr. Then periodically rr reads the real memory, and if it doesn't match\n * the shadow buffer, we update the shadow buffer with the new values and\n * record that we did so.\n *\n * Currently we check the real memory after each syscall exit. This ensures\n * that if the tracee is woken up by some IPC mechanism (or after sched_yield),\n * it will get a chance to see updated memory values.\n */\nclass MonitoredSharedMemory {\npublic:\n  ~MonitoredSharedMemory();\n\n  typedef std::shared_ptr<MonitoredSharedMemory> shr_ptr;\n\n  static void maybe_monitor(RecordTask* t, const std::string& file_name,\n                            const AddressSpace::Mapping& m, int tracee_fd,\n                            uint64_t offset);\n\n  static void check_all(RecordTask* t);\n\n  shr_ptr subrange(uintptr_t start, uintptr_t size);\n\nprivate:\n  void check_for_changes(RecordTask* t, AddressSpace::Mapping& m);\n\n  MonitoredSharedMemory(uint8_t* real_mem, size_t size)\n      : real_mem(real_mem), size(size) {}\n  uint8_t* real_mem;\n  size_t size;\n};\n\n} // namespace rr\n\n#endif /* RR_MONITORED_SHARED_MEMORY_H_ */\n"
  },
  {
    "path": "src/Monkeypatcher.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Monkeypatcher.h\"\n\n#include <elf.h>\n#include <limits.h>\n#include <linux/auxvec.h>\n\n#include <sstream>\n\n#include \"AddressSpace.h\"\n#include \"AutoRemoteSyscalls.h\"\n#include \"ElfReader.h\"\n#include \"Flags.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"ReplaySession.h\"\n#include \"ScopedFd.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n#include \"AssemblyTemplates.generated\"\n\nstatic void write_and_record_bytes(RecordTask* t, remote_ptr<void> child_addr,\n                                   size_t size, const void* buf, bool* ok = nullptr) {\n  t->write_bytes_helper(child_addr, size, buf, ok);\n  if (!ok || *ok) {\n    t->record_local(child_addr, size, buf);\n  }\n}\n\ntemplate <size_t N>\nstatic void write_and_record_bytes(RecordTask* t, remote_ptr<void> child_addr,\n                                   const uint8_t (&buf)[N], bool* ok = nullptr) {\n  write_and_record_bytes(t, child_addr, N, buf, ok);\n}\n\ntemplate <typename T>\nstatic void write_and_record_mem(RecordTask* t, remote_ptr<T> child_addr,\n                                 const T* val, int count) {\n  t->write_bytes_helper(child_addr, sizeof(*val) * count,\n                        static_cast<const void*>(val));\n  t->record_local(child_addr, sizeof(T) * count, val);\n}\n\n/**\n * RecordSession sets up an LD_PRELOAD environment variable with an entry\n * SYSCALLBUF_LIB_FILENAME_PADDED (and, if enabled, an LD_AUDIT environment\n * variable with an entry RTLDAUDIT_LIB_FILENAME_PADDED) which is big enough to\n * hold either the 32-bit or 64-bit preload/audit library file names.\n * Immediately after exec we enter this function, which patches the environment\n * variable value with the correct library name for the task's architecture.\n *\n * It's possible for this to fail if a tracee alters the LD_PRELOAD value\n * and then does an exec. That's just too bad. If we ever have to handle that,\n * we should modify the environment passed to the exec call. This function\n * failing isn't necessarily fatal; a tracee might not rely on the functions\n * overridden by the preload library, or might override them itself (e.g.\n * because we're recording an rr replay).\n */\n#define setup_library_path(arch, env_var, soname, task) \\\n  setup_library_path_arch<arch>(task, env_var, soname ## _BASE, \\\n                                soname ## _PADDED, soname ## _32)\n\ntemplate <typename Arch>\nstatic void setup_library_path_arch(RecordTask* t, const char* env_var,\n                                    const char* soname_base,\n                                    const char* soname_padded,\n                                    const char* soname_32) {\n  const char* lib_name =\n      sizeof(typename Arch::unsigned_word) < sizeof(uintptr_t)\n          ? soname_32\n          : soname_padded;\n  auto env_assignment = string(env_var) + \"=\";\n\n  auto p = t->regs().sp().cast<typename Arch::unsigned_word>();\n  auto argc = t->read_mem(p);\n  p += 1 + argc + 1; // skip argc, argc parameters, and trailing NULL\n  while (true) {\n    auto envp = t->read_mem(p);\n    if (!envp) {\n      LOG(debug) << env_var << \" not found\";\n      return;\n    }\n    string env = t->read_c_str(envp);\n    if (env.find(env_assignment) != 0) {\n      ++p;\n      continue;\n    }\n    size_t lib_pos = env.find(soname_base);\n    if (lib_pos == string::npos) {\n      LOG(debug) << soname_base << \" not found in \" << env_var;\n      return;\n    }\n    size_t next_colon = env.find(':', lib_pos);\n    if (next_colon != string::npos) {\n      while ((next_colon + 1 < env.length()) &&\n             (env[next_colon + 1] == ':' || env[next_colon + 1] == 0)) {\n        ++next_colon;\n      }\n      if (next_colon + 1 <\n          lib_pos + sizeof(soname_padded) - 1) {\n        LOG(debug) << \"Insufficient space for \" << lib_name\n                   << \" in \" << env_var << \" before next ':'\";\n        return;\n      }\n    }\n    if (env.length() < lib_pos + sizeof(soname_padded) - 1) {\n      LOG(debug) << \"Insufficient space for \" << lib_name\n                 << \" in \" << env_var << \" before end of string\";\n      return;\n    }\n    remote_ptr<void> dest = envp + lib_pos;\n    write_and_record_mem(t, dest.cast<char>(), lib_name, strlen(soname_padded));\n    return;\n  }\n}\n\ntemplate <typename Arch> static void setup_preload_library_path(RecordTask* t) {\n  static_assert(sizeof(SYSCALLBUF_LIB_FILENAME_PADDED) ==\n                    sizeof(SYSCALLBUF_LIB_FILENAME_32),\n                \"filename length mismatch\");\n  setup_library_path(Arch, \"LD_PRELOAD\", SYSCALLBUF_LIB_FILENAME, t);\n}\n\ntemplate <typename Arch> static void setup_audit_library_path(RecordTask* t) {\n  static_assert(sizeof(RTLDAUDIT_LIB_FILENAME_PADDED) ==\n                    sizeof(RTLDAUDIT_LIB_FILENAME_32),\n                \"filename length mismatch\");\n  if (t->session().use_audit()) {\n    setup_library_path(Arch, \"LD_AUDIT\", RTLDAUDIT_LIB_FILENAME, t);\n  }\n}\n\nvoid Monkeypatcher::init_dynamic_syscall_patching(\n    RecordTask* t, int syscall_patch_hook_count,\n    remote_ptr<struct syscall_patch_hook> syscall_patch_hooks) {\n  if (syscall_patch_hook_count && syscall_hooks.empty()) {\n    syscall_hooks = t->read_mem(syscall_patch_hooks, syscall_patch_hook_count);\n  }\n}\n\ntemplate <typename Arch>\nstatic bool patch_syscall_with_hook_arch(Monkeypatcher& patcher, RecordTask* t,\n                                         const syscall_patch_hook& hook,\n                                         remote_code_ptr ip_of_instruction,\n                                         size_t instruction_length,\n                                         uint32_t fake_syscall_number);\n\ntemplate <typename StubPatch>\nstatic void substitute(uint8_t* buffer, uint64_t return_addr,\n                       uint32_t trampoline_relative_addr);\n\ntemplate <typename ExtendedJumpPatch>\nstatic void substitute_extended_jump(uint8_t* buffer, uint64_t patch_addr,\n                                     uint64_t return_addr,\n                                     uint64_t target_addr,\n                                     uint32_t fake_syscall_number);\n\ntemplate <>\nvoid substitute_extended_jump<X86SyscallStubExtendedJump>(\n    uint8_t* buffer, uint64_t patch_addr, uint64_t return_addr,\n    uint64_t target_addr, uint32_t) {\n  int64_t offset =\n      target_addr -\n      (patch_addr + X86SyscallStubExtendedJump::trampoline_relative_addr_end);\n  // An offset that appears to be > 2GB is OK here, since EIP will just\n  // wrap around.\n  X86SyscallStubExtendedJump::substitute(buffer, (uint32_t)return_addr,\n                                         (uint32_t)offset);\n}\n\ntemplate <>\nvoid substitute_extended_jump<X64SyscallStubExtendedJump>(\n    uint8_t* buffer, uint64_t, uint64_t return_addr, uint64_t target_addr,\n    uint32_t) {\n  X64SyscallStubExtendedJump::substitute(buffer, (uint32_t)return_addr,\n                                         (uint32_t)(return_addr >> 32),\n                                         target_addr);\n}\n\ntemplate <>\nvoid substitute_extended_jump<X86TrapInstructionStubExtendedJump>(\n    uint8_t* buffer, uint64_t patch_addr, uint64_t return_addr,\n    uint64_t target_addr, uint32_t fake_syscall_number) {\n  int64_t offset =\n      target_addr -\n      (patch_addr + X86SyscallStubExtendedJump::trampoline_relative_addr_end);\n  // An offset that appears to be > 2GB is OK here, since EIP will just\n  // wrap around.\n  X86TrapInstructionStubExtendedJump::substitute(buffer, (uint32_t)return_addr,\n                                         fake_syscall_number, (uint32_t)offset);\n}\n\ntemplate <>\nvoid substitute_extended_jump<X64TrapInstructionStubExtendedJump>(\n    uint8_t* buffer, uint64_t, uint64_t return_addr, uint64_t target_addr,\n    uint32_t fake_syscall_number) {\n  X64TrapInstructionStubExtendedJump::substitute(buffer, (uint32_t)return_addr,\n                                         (uint32_t)(return_addr >> 32),\n                                         fake_syscall_number,\n                                         target_addr);\n}\n\n/**\n * Allocate an extended jump in an extended jump page and return its address.\n * The resulting address must be within 2G of from_end, and the instruction\n * there must jump to to_start.\n */\ntemplate <typename ExtendedJumpPatch>\nstatic remote_ptr<uint8_t> allocate_extended_jump_x86ish(\n    RecordTask* t, vector<Monkeypatcher::ExtendedJumpPage>& pages,\n    remote_ptr<uint8_t> from_end) {\n  Monkeypatcher::ExtendedJumpPage* page = nullptr;\n  for (auto& p : pages) {\n    remote_ptr<uint8_t> page_jump_start = p.addr + p.allocated;\n    int64_t offset = page_jump_start - from_end;\n    if ((int32_t)offset == offset &&\n        p.allocated + ExtendedJumpPatch::size <= page_size()) {\n      page = &p;\n      break;\n    }\n  }\n\n  if (!page) {\n    // We're looking for a gap of three pages --- one page to allocate and\n    // a page on each side as a guard page.\n    uint32_t required_space = 3 * page_size();\n    remote_ptr<void> free_mem =\n        t->vm()->find_free_memory(t, required_space,\n                                  // Find free space after the patch site.\n                                  t->vm()->mapping_of(from_end).map.start());\n    if (!free_mem) {\n      LOG(debug) << \"Can't find free memory anywhere after the jump\";\n      return nullptr;\n    }\n\n    remote_ptr<uint8_t> addr = (free_mem + page_size()).cast<uint8_t>();\n    int64_t offset = addr - from_end;\n    if ((int32_t)offset != offset) {\n      LOG(debug) << \"Can't find space close enough for the jump\";\n      return nullptr;\n    }\n\n    {\n      AutoRemoteSyscalls remote(t);\n      int prot = PROT_READ | PROT_EXEC;\n      int flags = MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE;\n      auto ret = remote.infallible_mmap_syscall_if_alive(addr, page_size(), prot, flags, -1, 0);\n      if (!ret) {\n        /* Tracee died */\n        return nullptr;\n      }\n      KernelMapping recorded(addr, addr + page_size(), string(),\n                             KernelMapping::NO_DEVICE, KernelMapping::NO_INODE,\n                             prot, flags);\n      t->vm()->map(t, addr, page_size(), prot, flags, 0, string(),\n                   KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,\n                   &recorded);\n      t->vm()->mapping_flags_of(addr) |= AddressSpace::Mapping::IS_PATCH_STUBS;\n      t->trace_writer().write_mapped_region(t, recorded, recorded.fake_stat(),\n                                            recorded.fsname(),\n                                            vector<TraceRemoteFd>(),\n                                            TraceWriter::PATCH_MAPPING);\n    }\n\n    pages.push_back(Monkeypatcher::ExtendedJumpPage(addr));\n    page = &pages.back();\n  }\n\n  remote_ptr<uint8_t> jump_addr = page->addr + page->allocated;\n  page->allocated += ExtendedJumpPatch::size;\n  return jump_addr;\n}\n\n/**\n * Encode the standard movz|movk sequence for moving constant `v` into register `reg`\n */\nstatic void encode_immediate_aarch64(std::vector<uint32_t> &buff,\n                                     uint8_t reg, uint64_t v)\n{\n  DEBUG_ASSERT(reg < 31);\n  const uint32_t movz_inst = 0xd2800000;\n  const uint32_t movk_inst = 0xf2800000;\n  uint32_t mov_inst = movz_inst;\n  for (int lsl = 3; lsl >= 0; lsl--) {\n    uint32_t bits = (v >> (lsl * 16)) & 0xffff;\n    if (bits == 0 && !(lsl == 0 && mov_inst == movz_inst)) {\n      // Skip zero bits unless it's the only instruction, i.e. v == 0\n      continue;\n    }\n    // movz|movk x[reg], #bits, LSL #lsl\n    buff.push_back(mov_inst | (uint32_t(lsl) << 21) | (bits << 5) | reg);\n    mov_inst = movk_inst;\n  }\n}\n\n/**\n * Encode the following assembly.\n *\n *    cmp     x8, 1024\n *    b.hi    .Lnosys\n *    movk    x8, preload_thread_locals >> 16, lsl 16\n *    stp     x15, x30, [x8, stub_scratch_2 - preload_thread_locals]\n *    movz    x30, #:abs_g3:_syscall_hook_trampoline\n *    movk    x30, #:abs_g2_nc:_syscall_hook_trampoline\n *    movk    x30, #:abs_g1_nc:_syscall_hook_trampoline\n *    movk    x30, #:abs_g0_nc:_syscall_hook_trampoline // Might be shorter depending on the address\n *    blr     x30\n *    ldp     x15, x30, [x15]\n.Lreturn:\n *    b       syscall_return_address\n.Lnosys:\n *    svc     0x0 // the test relies on invalid syscall triggering an event.\n *    // mov     x0, -ENOSYS\n *    b       .Lreturn\n *    .long <syscall return address>\n *\n * And return the instruction index of `.Lreturn`.\n * The branch instruction following that label will not be encoded\n * since it depends on the address of this code.\n */\nstatic uint32_t encode_extended_jump_aarch64(std::vector<uint32_t> &buff,\n                                             uint64_t target, uint64_t return_addr,\n                                             uint32_t *_retaddr_idx = nullptr)\n{\n  // cmp x8, 1024\n  buff.push_back(0xf110011f);\n  uint32_t b_hi_idx = buff.size();\n  buff.push_back(0); // place holder\n  // movk x8, preload_thread_locals >> 16, lsl 16\n  buff.push_back(0xf2ae0028);\n  // stp x15, x30, [x8, #104]\n  buff.push_back(0xa906f90f);\n  encode_immediate_aarch64(buff, 30, target);\n  // blr x30\n  buff.push_back(0xd63f03c0);\n  // ldp x15, x30, [x15]\n  buff.push_back(0xa94079ef);\n  uint32_t ret_idx = buff.size();\n  buff.push_back(0); // place holder\n  // b.hi . + (ret_inst + 4 - .)\n  buff[b_hi_idx] = 0x54000000 | ((ret_idx + 1 - b_hi_idx) << 5) | 0x8;\n  // movn x0, (ENOSYS - 1), i.e. mov x0, -ENOSYS\n  // buff.push_back(0x92800000 | ((ENOSYS - 1) << 5) | 0);\n  buff.push_back(0xd4000001); // svc 0\n  // b .-2\n  buff.push_back(0x17fffffe);\n  uint32_t retaddr_idx = buff.size();\n  if (_retaddr_idx)\n    *_retaddr_idx = retaddr_idx;\n  buff.resize(retaddr_idx + 2);\n  memcpy(&buff[retaddr_idx], &return_addr, 8);\n  return ret_idx;\n}\n\n// b and bl has a 26bit signed immediate in unit of 4 bytes\nconstexpr int32_t aarch64_b_max_offset = ((1 << 25) - 1) * 4;\nconstexpr int32_t aarch64_b_min_offset = (1 << 25) * -4;\n\nstatic remote_ptr<uint8_t> allocate_extended_jump_aarch64(\n    RecordTask* t, vector<Monkeypatcher::ExtendedJumpPage>& pages,\n    remote_ptr<uint8_t> svc_ip, uint64_t to, std::vector<uint32_t> &inst_buff) {\n  uint64_t return_addr = svc_ip.as_int() + 4;\n  auto ret_idx = encode_extended_jump_aarch64(inst_buff, to, return_addr);\n  auto total_patch_size = inst_buff.size() * 4;\n\n  Monkeypatcher::ExtendedJumpPage* page = nullptr;\n\n  // There are two jumps we need to worry about for the offset\n  // (actually 3 since there's also the jump back after unpatching\n  //  but the requirement for that is always more relaxed than the combination\n  //  of these two),\n  // the jump to the stub and the jump back.\n  // The jump to the stub has offset `stub - syscall` and the jump back has offset\n  // `syscall + 4 - (stub + ret_idx * 4)`\n  // We need to make sure both are within the offset range so\n  // * aarch64_b_min_offset <= stub - syscall <= aarch64_b_max_offset\n  // * aarch64_b_min_offset <= syscall + 4 - (stub + ret_idx * 4) <= aarch64_b_max_offset\n  // or\n  // * aarch64_b_min_offset <= stub - syscall <= aarch64_b_max_offset\n  // * -aarch64_b_max_offset + 4 - ret_idx * 4 <= stub - syscall <= -aarch64_b_min_offset + 4 - ret_idx * 4\n\n  int64_t patch_offset_min = std::max(aarch64_b_min_offset,\n                                      -aarch64_b_max_offset + 4 - int(ret_idx) * 4);\n  int64_t patch_offset_max = std::min(aarch64_b_max_offset,\n                                      -aarch64_b_min_offset + 4 - int(ret_idx) * 4);\n  for (auto& p : pages) {\n    remote_ptr<uint8_t> page_jump_start = p.addr + p.allocated;\n    int64_t offset = page_jump_start - svc_ip;\n    if (offset <= patch_offset_max && offset >= patch_offset_min &&\n        p.allocated + total_patch_size <= page_size()) {\n      page = &p;\n      break;\n    }\n  }\n\n  if (!page) {\n    // We're looking for a gap of three pages --- one page to allocate and\n    // a page on each side as a guard page.\n    uint32_t required_space = 3 * page_size();\n    remote_ptr<void> free_mem =\n        t->vm()->find_free_memory(t, required_space,\n                                  // Find free space after the patch site.\n                                  t->vm()->mapping_of(svc_ip).map.start());\n    if (!free_mem) {\n      LOG(debug) << \"Can't find free memory anywhere after the jump\";\n      return nullptr;\n    }\n\n    remote_ptr<uint8_t> addr = (free_mem + page_size()).cast<uint8_t>();\n    int64_t offset = addr - svc_ip;\n    if (offset > patch_offset_max || offset < patch_offset_min) {\n      LOG(debug) << \"Can't find space close enough for the jump\";\n      return nullptr;\n    }\n\n    {\n      AutoRemoteSyscalls remote(t);\n      int prot = PROT_READ | PROT_EXEC;\n      int flags = MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE;\n      auto ret = remote.infallible_mmap_syscall_if_alive(addr, page_size(), prot, flags, -1, 0);\n      if (!ret) {\n        /* Tracee died */\n        return nullptr;\n      }\n      KernelMapping recorded(addr, addr + page_size(), string(),\n                             KernelMapping::NO_DEVICE, KernelMapping::NO_INODE,\n                             prot, flags);\n      t->vm()->map(t, addr, page_size(), prot, flags, 0, string(),\n                   KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,\n                   &recorded);\n      t->vm()->mapping_flags_of(addr) |= AddressSpace::Mapping::IS_PATCH_STUBS;\n      t->trace_writer().write_mapped_region(t, recorded, recorded.fake_stat(),\n                                            recorded.fsname(),\n                                            vector<TraceRemoteFd>(),\n                                            TraceWriter::PATCH_MAPPING);\n    }\n\n    pages.push_back(Monkeypatcher::ExtendedJumpPage(addr));\n    page = &pages.back();\n  }\n\n  remote_ptr<uint8_t> jump_addr = page->addr + page->allocated;\n\n  const uint64_t reverse_jump_addr = jump_addr.as_int() + ret_idx * 4;\n  const int64_t reverse_offset = int64_t(return_addr - reverse_jump_addr);\n  const uint32_t offset_imm26 = (reverse_offset >> 2) & 0x03ffffff;\n  inst_buff[ret_idx] = 0x14000000 | offset_imm26;\n\n  page->allocated += total_patch_size;\n\n  return jump_addr;\n}\n\nbool Monkeypatcher::is_jump_stub_instruction(remote_code_ptr ip, bool include_safearea) {\n  remote_ptr<uint8_t> pp = ip.to_data_ptr<uint8_t>();\n  auto it = syscallbuf_stubs.upper_bound(pp);\n  if (it == syscallbuf_stubs.begin()) {\n    return false;\n  }\n  --it;\n  auto begin = it->first;\n  auto end = begin + it->second.size;\n  if (!include_safearea) {\n    begin += it->second.safe_prefix;\n    end -= it->second.safe_suffix;\n  }\n  return begin <= pp && pp < end;\n}\n\nremote_code_ptr Monkeypatcher::get_jump_stub_exit_breakpoint(remote_code_ptr ip,\n                                                             RecordTask *t) {\n  if (t->arch() != aarch64) {\n    return nullptr;\n  }\n  remote_ptr<uint8_t> pp = ip.to_data_ptr<uint8_t>();\n  auto it = syscallbuf_stubs.upper_bound(pp);\n  if (it == syscallbuf_stubs.begin()) {\n    return nullptr;\n  }\n  --it;\n  auto bp = it->first + it->second.size - it->second.safe_suffix;\n  if (pp == bp || pp == bp - 4) {\n    return remote_code_ptr(bp.as_int());\n  }\n  return nullptr;\n}\n\nstatic bool hook_can_ignore_interfering_branches(const syscall_patch_hook& hook, size_t jump_patch_size) {\n  return hook.patch_region_length >= jump_patch_size &&\n    (hook.flags & (PATCH_IS_MULTIPLE_INSTRUCTIONS |\n                   PATCH_IS_NOP_INSTRUCTIONS |\n                   PATCH_NO_MATCH_TRAILING_4_BYTES)) == PATCH_IS_NOP_INSTRUCTIONS;\n}\n\n/**\n * Some functions make system calls while storing local variables in memory\n * below the stack pointer. We need to decrement the stack pointer by\n * some \"safety zone\" amount to get clear of those variables before we make\n * a call instruction. So, we allocate a stub per patched callsite, and jump\n * from the callsite to the stub. The stub decrements the stack pointer,\n * calls the appropriate syscall hook function, reincrements the stack pointer,\n * and jumps back to immediately after the patched callsite.\n *\n * It's important that gdb stack traces work while a thread is stopped in the\n * syscallbuf code. To ensure that the above manipulations don't foil gdb's\n * stack walking code, we add CFI data to all the stubs. To ease that, the\n * stubs are written in assembly and linked into the preload library.\n *\n * On x86-64 with ASLR, we need to be able to patch a call to a stub from\n * sites more than 2^31 bytes away. We only have space for a 5-byte jump\n * instruction. So, we allocate \"extender pages\" --- pages of memory within\n * 2GB of the patch site, that contain the stub code. We don't really need this\n * on x86, but we do it there too for consistency.\n *\n * If fake_syscall_number > 0 then we'll ensure AX is set to that number\n * by the stub code.\n */\ntemplate <typename JumpPatch, typename ExtendedJumpPatch, typename FakeSyscallExtendedJumpPatch>\nstatic bool patch_syscall_with_hook_x86ish(Monkeypatcher& patcher,\n                                           RecordTask* t,\n                                           const syscall_patch_hook& hook,\n                                           remote_code_ptr ip_of_instruction,\n                                           size_t instruction_length,\n                                           uint32_t fake_syscall_number) {\n  size_t patch_region_size = instruction_length + hook.patch_region_length;\n  // We're patching in a relative jump, so we need to compute the offset from\n  // the end of the jump to our actual destination.\n  remote_ptr<uint8_t> jump_patch_start = ip_of_instruction.to_data_ptr<uint8_t>();\n  if (hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST) {\n    jump_patch_start -= hook.patch_region_length;\n  }\n  remote_ptr<uint8_t> jump_patch_end = jump_patch_start + JumpPatch::size;\n  remote_ptr<uint8_t> return_addr =\n    jump_patch_start + patch_region_size;\n\n  remote_ptr<uint8_t> extended_jump_start;\n  if (fake_syscall_number) {\n    extended_jump_start = allocate_extended_jump_x86ish<FakeSyscallExtendedJumpPatch>(\n        t, patcher.extended_jump_pages, jump_patch_end);\n  } else {\n    extended_jump_start = allocate_extended_jump_x86ish<ExtendedJumpPatch>(\n          t, patcher.extended_jump_pages, jump_patch_end);\n  }\n  if (extended_jump_start.is_null()) {\n    return false;\n  }\n\n  if (fake_syscall_number) {\n    uint8_t stub_patch[FakeSyscallExtendedJumpPatch::size];\n    substitute_extended_jump<FakeSyscallExtendedJumpPatch>(stub_patch,\n                                                extended_jump_start.as_int(),\n                                                return_addr.as_int(),\n                                                hook.hook_address,\n                                                fake_syscall_number);\n    write_and_record_bytes(t, extended_jump_start, stub_patch);\n\n    patcher.syscallbuf_stubs[extended_jump_start] = { &hook, FakeSyscallExtendedJumpPatch::size };\n  } else {\n    uint8_t stub_patch[ExtendedJumpPatch::size];\n    substitute_extended_jump<ExtendedJumpPatch>(stub_patch,\n                                                extended_jump_start.as_int(),\n                                                return_addr.as_int(),\n                                                hook.hook_address,\n                                                0);\n    write_and_record_bytes(t, extended_jump_start, stub_patch);\n\n    patcher.syscallbuf_stubs[extended_jump_start] = { &hook, ExtendedJumpPatch::size };\n  }\n\n  intptr_t jump_offset = extended_jump_start - jump_patch_end;\n  int32_t jump_offset32 = (int32_t)jump_offset;\n  ASSERT(t, jump_offset32 == jump_offset)\n      << \"allocate_extended_jump_x86ish didn't work\";\n\n  // pad with NOPs to the next instruction\n  static const uint8_t NOP = 0x90;\n  vector<uint8_t> jump_patch;\n  int patch_size = patch_region_size;\n  if (hook.flags & PATCH_NO_MATCH_TRAILING_4_BYTES) {\n    patch_size -= 4;\n  }\n  jump_patch.resize(patch_size, NOP);\n  if (hook_can_ignore_interfering_branches(hook, JumpPatch::size)) {\n    // If the preceding instruction is long enough to contain the entire jump,\n    // and is a nop, replace the original instruction by a jump back to the\n    // start of the patch region. This allows us to ignore (likely spurious,\n    // but nevertheless), interfering branches, because whether we jump to the\n    // instruction or the start of the patch region, the effect is the same.\n    jump_patch[patch_region_size-2] = 0xeb; // jmp rel\n    jump_patch[patch_region_size-1] = (int8_t)-patch_size;\n  }\n  JumpPatch::substitute(jump_patch.data(), jump_offset32);\n  bool ok = true;\n  write_and_record_bytes(t, jump_patch_start, jump_patch.size(), jump_patch.data(), &ok);\n  if (!ok) {\n    LOG(warn) << \"Couldn't write patch; errno=\" << errno;\n  }\n  return ok;\n}\n\ntemplate <>\nbool patch_syscall_with_hook_arch<X86Arch>(Monkeypatcher& patcher,\n                                           RecordTask* t,\n                                           const syscall_patch_hook& hook,\n                                           remote_code_ptr ip_of_instruction,\n                                           size_t instruction_length,\n                                           uint32_t fake_syscall_number) {\n  return patch_syscall_with_hook_x86ish<X86SysenterVsyscallSyscallHook,\n                                        X86SyscallStubExtendedJump,\n                                        X86TrapInstructionStubExtendedJump>(patcher, t,\n                                                                            hook,\n                                                                            ip_of_instruction,\n                                                                            instruction_length,\n                                                                            fake_syscall_number);\n}\n\ntemplate <>\nbool patch_syscall_with_hook_arch<X64Arch>(Monkeypatcher& patcher,\n                                           RecordTask* t,\n                                           const syscall_patch_hook& hook,\n                                           remote_code_ptr ip_of_instruction,\n                                           size_t instruction_length,\n                                           uint32_t fake_syscall_number) {\n  return patch_syscall_with_hook_x86ish<X64JumpMonkeypatch,\n                                        X64SyscallStubExtendedJump,\n                                        X64TrapInstructionStubExtendedJump>(patcher, t,\n                                                                            hook,\n                                                                            ip_of_instruction,\n                                                                            instruction_length,\n                                                                            fake_syscall_number);\n}\n\ntemplate <>\nbool patch_syscall_with_hook_arch<ARM64Arch>(Monkeypatcher& patcher,\n                                             RecordTask *t,\n                                             const syscall_patch_hook &hook,\n                                             remote_code_ptr,\n                                             size_t,\n                                             uint32_t) {\n  Registers r = t->regs();\n  remote_ptr<uint8_t> svc_ip = r.ip().to_data_ptr<uint8_t>();\n  std::vector<uint32_t> inst_buff;\n\n  remote_ptr<uint8_t> extended_jump_start =\n    allocate_extended_jump_aarch64(\n      t, patcher.extended_jump_pages, svc_ip, hook.hook_address, inst_buff);\n  if (extended_jump_start.is_null()) {\n    return false;\n  }\n  LOG(debug) << \"Allocated stub size \" << inst_buff.size() * sizeof(uint32_t)\n             << \" bytes at \" << extended_jump_start << \" for syscall at \"\n             << svc_ip;\n\n  auto total_patch_size = inst_buff.size() * 4;\n  write_and_record_bytes(t, extended_jump_start, total_patch_size, &inst_buff[0]);\n\n  patcher.syscallbuf_stubs[extended_jump_start] = {\n    &hook, total_patch_size,\n    /**\n     * safe_prefix:\n     * We have not modified any registers yet in the first two instructions.\n     * More importantly, we may bail out and return to user code without\n     * hitting the breakpoint in syscallbuf\n     */\n    2 * 4,\n    /**\n     * safe_suffix:\n     * We've returned from syscallbuf and continue execution\n     * won't hit syscallbuf breakpoint\n     * (this also include the 8 bytes that stores the return address)\n     * Note that the 4th last instruction also belongs to the syscallbuf return path\n     * However, since it is still using the scratch memory,\n     * it doesn't belong to the safe area.\n     * The caller needs to have special handling for that instruction.\n     */\n    3 * 4 + 8\n  };\n\n  intptr_t jump_offset = extended_jump_start - svc_ip;\n  ASSERT(t, jump_offset <= aarch64_b_max_offset && jump_offset >= aarch64_b_min_offset)\n      << \"allocate_extended_jump_aarch64 didn't work\";\n\n  const uint32_t offset_imm26 = (jump_offset >> 2) & 0x03ffffff;\n  const uint32_t b_inst = 0x14000000 | offset_imm26;\n  bool ok = true;\n  write_and_record_bytes(t, svc_ip, 4, &b_inst, &ok);\n  if (!ok) {\n    LOG(warn) << \"Couldn't write patch; errno=\" << errno;\n  }\n  return ok;\n}\n\n\nstatic bool patch_syscall_with_hook(Monkeypatcher& patcher, RecordTask* t,\n                                    const syscall_patch_hook& hook,\n                                    remote_code_ptr ip_of_instruction,\n                                    size_t instruction_length,\n                                    uint32_t fake_syscall_number) {\n  RR_ARCH_FUNCTION(patch_syscall_with_hook_arch, t->arch(), patcher, t, hook,\n                   ip_of_instruction, instruction_length, fake_syscall_number);\n}\n\ntemplate <typename ExtendedJumpPatch>\nstatic bool match_extended_jump_patch(Task* t,\n  uint8_t patch[], uint64_t* return_addr, vector<uint8_t>* instruction);\n\ntemplate <>\nbool match_extended_jump_patch<X64SyscallStubExtendedJump>(\n      Task*, uint8_t patch[], uint64_t* return_addr, vector<uint8_t>* instruction) {\n  uint32_t return_addr_lo, return_addr_hi;\n  uint64_t jmp_target;\n  if (!X64SyscallStubExtendedJump::match(patch, &return_addr_lo, &return_addr_hi, &jmp_target)) {\n    return false;\n  }\n  *instruction = rr::syscall_instruction(x86_64);\n  *return_addr = return_addr_lo | (((uint64_t)return_addr_hi) << 32);\n  return true;\n}\n\ntemplate <>\nbool match_extended_jump_patch<X64TrapInstructionStubExtendedJump>(\n      Task* t, uint8_t patch[], uint64_t* return_addr, vector<uint8_t>* instruction) {\n  uint32_t return_addr_lo, return_addr_hi, fake_syscall_no;\n  uint64_t jmp_target;\n  if (!X64TrapInstructionStubExtendedJump::match(patch, &return_addr_lo, &return_addr_hi,\n                                                 &fake_syscall_no, &jmp_target)) {\n    return false;\n  }\n  *return_addr = return_addr_lo | (((uint64_t)return_addr_hi) << 32);\n  if ((int)fake_syscall_no == t->session().syscall_number_for_rrcall_rdtsc()) {\n    instruction->resize(sizeof(rdtsc_insn));\n    memcpy(instruction->data(), rdtsc_insn, instruction->size());\n  } else {\n    ASSERT(t, false) << \"Unknown fake-syscall number \" << fake_syscall_no;\n  }\n  return true;\n}\n\ntemplate <>\nbool match_extended_jump_patch<X86SyscallStubExtendedJump>(\n      Task*, uint8_t patch[], uint64_t* return_addr, vector<uint8_t>* instruction) {\n  uint32_t return_addr_32, jmp_target_relative;\n  if (!X86SyscallStubExtendedJump::match(patch, &return_addr_32, &jmp_target_relative)) {\n    return false;\n  }\n  *return_addr = return_addr_32;\n  *instruction = rr::syscall_instruction(x86);\n  return true;\n}\n\ntemplate <typename ReplacementPatch>\nstatic void substitute_replacement_patch(uint8_t *buffer, uint64_t patch_addr,\n                                     uint64_t jmp_target);\n\ntemplate <>\nvoid substitute_replacement_patch<X64SyscallStubRestore>(uint8_t *buffer, uint64_t patch_addr,\n                                  uint64_t jmp_target) {\n  (void)patch_addr;\n  X64SyscallStubRestore::substitute(buffer, jmp_target);\n}\n\ntemplate <>\nvoid substitute_replacement_patch<X86SyscallStubRestore>(uint8_t *buffer, uint64_t patch_addr,\n                                  uint64_t jmp_target) {\n  int64_t offset =\n      jmp_target -\n      (patch_addr + X86SyscallStubRestore::trampoline_relative_addr_end);\n  // An offset that appears to be > 2GB is OK here, since EIP will just\n  // wrap around.\n  X86SyscallStubRestore::substitute(buffer, (uint32_t)offset);\n}\n\ntemplate <typename ExtendedJumpPatch, typename FakeSyscallExtendedJumpPatch, typename ReplacementPatch>\nstatic void unpatch_extended_jumps(Monkeypatcher& patcher,\n                                   Task* t) {\n  static_assert(ExtendedJumpPatch::size < FakeSyscallExtendedJumpPatch::size,\n                \"If these were the same size then the logic below wouldn't work\");\n  for (auto patch : patcher.syscallbuf_stubs) {\n    const syscall_patch_hook &hook = *patch.second.hook;\n    uint8_t bytes[FakeSyscallExtendedJumpPatch::size];\n    t->read_bytes_helper(patch.first, patch.second.size, bytes);\n    uint64_t return_addr = 0;\n    vector<uint8_t> syscall;\n    if (patch.second.size == ExtendedJumpPatch::size) {\n      if (!match_extended_jump_patch<ExtendedJumpPatch>(\n              t, bytes, &return_addr, &syscall)) {\n        ASSERT(t, false) << \"Failed to match extended jump patch at \" << patch.first;\n        return;\n      }\n    } else if (patch.second.size == FakeSyscallExtendedJumpPatch::size) {\n      if (!match_extended_jump_patch<FakeSyscallExtendedJumpPatch>(\n              t, bytes, &return_addr, &syscall)) {\n        ASSERT(t, false) << \"Failed to match trap-instruction extended jump patch at \" << patch.first;\n        return;\n      }\n    } else {\n      ASSERT(t, false) << \"Unknown patch size \" << patch.second.size;\n    }\n\n    // Replace with\n    //  extended_jump:\n    //    <syscall> (unless PATCH_SYSCALL_INSTRUCTION_IS_LAST)\n    //    <original bytes>\n    //    <syscall> (if PATCH_SYSCALL_INSTRUCTION_IS_LAST)\n    //    jmp *(return_addr)\n    // As long as there are not relative branches or anything, this should\n    // always be correct.\n    size_t new_patch_size = hook.patch_region_length + syscall.size() + ReplacementPatch::size;\n    ASSERT(t, new_patch_size <= sizeof(bytes));\n    uint8_t* ptr = bytes;\n    if (!(hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST)) {\n      memcpy(ptr, syscall.data(), syscall.size());\n      ptr += syscall.size();\n    }\n    memcpy(ptr, hook.patch_region_bytes, hook.patch_region_length);\n    ptr += hook.patch_region_length;\n    if (hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST) {\n      memcpy(ptr, syscall.data(), syscall.size());\n      ptr += syscall.size();\n    }\n    substitute_replacement_patch<ReplacementPatch>(ptr,\n      patch.first.as_int() + hook.patch_region_length + syscall.size(), return_addr);\n    t->write_bytes_helper(patch.first, new_patch_size, bytes);\n  }\n}\n\ntemplate <typename Arch>\nstatic void unpatch_syscalls_arch(Monkeypatcher &patcher, Task *t);\n\ntemplate <>\nvoid unpatch_syscalls_arch<X86Arch>(Monkeypatcher &patcher, Task *t) {\n  // There is no 32-bit equivalent to X64TrapInstructionStubExtendedJump.\n  // We just pass the X64TrapInstructionStubExtendedJump; its length\n  // will never match any jump stub for 32-bit.\n  return unpatch_extended_jumps<X86SyscallStubExtendedJump,\n                                X64TrapInstructionStubExtendedJump,\n                                X86SyscallStubRestore>(patcher, t);\n}\n\ntemplate <>\nvoid unpatch_syscalls_arch<X64Arch>(Monkeypatcher &patcher, Task *t) {\n  return unpatch_extended_jumps<X64SyscallStubExtendedJump,\n                                X64TrapInstructionStubExtendedJump,\n                                X64SyscallStubRestore>(patcher, t);\n}\n\ntemplate <>\nvoid unpatch_syscalls_arch<ARM64Arch>(Monkeypatcher &patcher, Task *t) {\n  for (auto patch : patcher.syscallbuf_stubs) {\n    const syscall_patch_hook &hook = *patch.second.hook;\n    std::vector<uint32_t> hook_prefix;\n    uint32_t prefix_ninst;\n    encode_extended_jump_aarch64(hook_prefix, hook.hook_address, 0, &prefix_ninst);\n    uint32_t prefix_size = prefix_ninst * 4;\n    DEBUG_ASSERT(prefix_size <= 13 * 4);\n    ASSERT(t, patch.second.size >= prefix_size + 8);\n    uint8_t bytes[15 * 4];\n    t->read_bytes_helper(patch.first, prefix_size + 8, bytes);\n    // 3rd last instruction is the one jumping back and it won't match\n    if (memcmp(&hook_prefix[0], bytes, prefix_size - 3 * 4) != 0) {\n      ASSERT(t, false) << \"Failed to match extended jump patch at \" << patch.first;\n      return;\n    }\n\n    uint64_t return_addr;\n    memcpy(&return_addr, &bytes[prefix_size], 8);\n\n    uint32_t svc_inst = 0xd4000001;\n    memcpy(bytes, &svc_inst, 4);\n\n    uint64_t reverse_jump_addr = patch.first.as_int() + 4;\n    int64_t reverse_offset = int64_t(return_addr - reverse_jump_addr);\n    ASSERT(t, reverse_offset <= aarch64_b_max_offset &&\n           reverse_offset >= aarch64_b_min_offset)\n      << \"Cannot encode b instruction to jump back\";\n    uint32_t offset_imm26 = (reverse_offset >> 2) & 0x03ffffff;\n    uint32_t binst = 0x14000000 | offset_imm26;\n    memcpy(&bytes[4], &binst, 4);\n\n    t->write_bytes_helper(patch.first, 4 * 2, bytes);\n  }\n}\n\nvoid Monkeypatcher::unpatch_syscalls_in(Task *t) {\n  RR_ARCH_FUNCTION(unpatch_syscalls_arch, t->arch(), *this, t);\n}\n\nstatic string bytes_to_string(uint8_t* bytes, size_t size) {\n  stringstream ss;\n  for (size_t i = 0; i < size; ++i) {\n    if (i > 0) {\n      ss << ' ';\n    }\n    ss << HEX(bytes[i]);\n  }\n  return ss.str();\n}\n\nstatic bool safe_for_syscall_patching(remote_code_ptr start,\n                                      remote_code_ptr end,\n                                      RecordTask* exclude_stopped) {\n  for (auto& p : exclude_stopped->session().tasks()) {\n    RecordTask* rt = static_cast<RecordTask*>(p.second);\n    if (rt != exclude_stopped && rt->is_stopped()) {\n      remote_code_ptr ip = rt->ip();\n      if (start <= ip && ip < end) {\n        return false;\n      }\n    }\n\n    for (auto& e : rt->pending_events) {\n      if (e.is_syscall_event()) {\n        remote_code_ptr ip = e.Syscall().regs.ip();\n        if (start <= ip && ip < end) {\n          return false;\n        }\n      }\n    }\n  }\n  return true;\n}\n\nbool Monkeypatcher::try_patch_vsyscall_caller(RecordTask* t, remote_code_ptr ret_addr)\n{\n  // Emit FLUSH_SYSCALLBUF if there's one pending.\n  // We want our mmap records to be associated with the next (PATCH_SYSCALL)\n  // event, not a FLUSH_SYSCALLBUF event.\n  t->maybe_flush_syscallbuf();\n\n  uint8_t bytes[X64VSyscallEntry::size];\n  remote_ptr<uint8_t> patch_start = ret_addr.to_data_ptr<uint8_t>() - sizeof(bytes);\n  size_t bytes_count = t->read_bytes_fallible(patch_start, sizeof(bytes), bytes);\n  if (bytes_count < sizeof(bytes)) {\n    return false;\n  }\n  uint32_t target_addr = 0;\n  if (!X64VSyscallEntry::match(bytes, &target_addr)) {\n    return false;\n  }\n  uint64_t target_addr_sext = (uint64_t)(int32_t)target_addr;\n  int syscallno = 0;\n  switch (target_addr_sext) {\n    case 0xffffffffff600000:\n      syscallno = X64Arch::gettimeofday;\n      break;\n    case 0xffffffffff600400:\n      syscallno = X64Arch::time;\n      break;\n    case 0xffffffffff600800:\n      syscallno = X64Arch::getcpu;\n      break;\n    default:\n      return false;\n  }\n  X64VSyscallReplacement::substitute(bytes, syscallno);\n  write_and_record_bytes(t, patch_start, bytes);\n  LOG(debug) << \"monkeypatched vsyscall caller at \" << patch_start;\n  return true;\n}\n\nstatic uint64_t jump_patch_size(SupportedArch arch)\n{\n  switch (arch) {\n    case x86: return X86SysenterVsyscallSyscallHook::size;\n    case x86_64: return X64JumpMonkeypatch::size;\n    case aarch64: return 2*rr::syscall_instruction_length(arch);\n    default:\n      FATAL() << \"Unimplemented for this architecture\";\n      return 0;\n  }\n}\n\nstatic bool patch_matches(const syscall_patch_hook& hook, const uint8_t* bytes) {\n  int region_len = hook.patch_region_length;\n  if (hook.flags & PATCH_NO_MATCH_TRAILING_4_BYTES) {\n    region_len -= 4;\n  }\n  return memcmp(bytes, hook.patch_region_bytes, region_len) == 0;\n}\n\nconst syscall_patch_hook* Monkeypatcher::find_syscall_hook(RecordTask* t,\n                                                           remote_code_ptr ip,\n                                                           bool entering_syscall,\n                                                           size_t instruction_length,\n                                                           bool &should_retry,\n                                                           bool &transient_failure) {\n  /* we need to inspect this many bytes before the start of the instruction,\n     to find every short jump that might land after it. Conservative. */\n  static const intptr_t LOOK_BACK = 0x80;\n  /* we need to inspect this many bytes after the start of the instruction,\n     to find every short jump that might land after it into the patch area.\n     Conservative. */\n  static const intptr_t LOOK_FORWARD = 15 + 15 + 0x80;\n  uint8_t bytes[LOOK_BACK + LOOK_FORWARD];\n  memset(bytes, 0, sizeof(bytes));\n\n  // Split reading the code into separate reads for each page, so that if we can't read\n  // from one page, we still get the data from the other page.\n  ASSERT(t, sizeof(bytes) < page_size());\n  remote_ptr<uint8_t> code_start = ip.to_data_ptr<uint8_t>() - LOOK_BACK;\n  size_t buf_valid_start_offset = 0;\n  size_t buf_valid_end_offset = sizeof(bytes);\n  ssize_t first_page_bytes = min<size_t>(ceil_page_size(code_start) - code_start, sizeof(bytes));\n  if (t->read_bytes_fallible(code_start, first_page_bytes, bytes) < first_page_bytes) {\n    buf_valid_start_offset = first_page_bytes;\n  }\n  if (first_page_bytes < (ssize_t)sizeof(bytes)) {\n    if (t->read_bytes_fallible(code_start + first_page_bytes, sizeof(bytes) - first_page_bytes,\n                               bytes + first_page_bytes) < (ssize_t)sizeof(bytes) - first_page_bytes) {\n      buf_valid_end_offset = first_page_bytes;\n    }\n  }\n\n  if (buf_valid_start_offset > LOOK_BACK ||\n      buf_valid_end_offset < LOOK_BACK + instruction_length) {\n    ASSERT(t, false)\n      << \"Can't read memory containing patchable instruction, why are we trying this?\";\n  }\n\n  uint8_t* following_bytes = &bytes[LOOK_BACK + instruction_length];\n  size_t following_bytes_count = buf_valid_end_offset - (LOOK_BACK + instruction_length);\n  size_t preceding_bytes_count = LOOK_BACK - buf_valid_start_offset;\n\n  for (const auto& hook : syscall_hooks) {\n    bool matches_hook = false;\n    if ((!(hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST) &&\n         following_bytes_count >= hook.patch_region_length &&\n         patch_matches(hook, following_bytes))) {\n      matches_hook = true;\n    } else if ((hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST) &&\n               hook.patch_region_length <= preceding_bytes_count &&\n               patch_matches(hook, bytes + LOOK_BACK - hook.patch_region_length)) {\n      if (entering_syscall) {\n        // A patch that uses bytes before the syscall can't be done when\n        // entering the syscall, it must be done when exiting. So set a flag on\n        // the Task that tells us to come back later.\n        should_retry = true;\n        LOG(debug) << \"Deferring syscall patching at \" << ip << \" in \" << t\n                  << \" until syscall exit.\";\n        return nullptr;\n      }\n      matches_hook = true;\n    }\n\n    if (!matches_hook) {\n      continue;\n    }\n\n    if (!hook_can_ignore_interfering_branches(hook, jump_patch_size(t->arch()))) {\n      // Search for a following short-jump instruction that targets an\n      // instruction\n      // after the syscall. False positives are OK.\n      // glibc-2.23.1-8.fc24.x86_64's __clock_nanosleep needs this.\n      bool found_potential_interfering_branch = false;\n      for (size_t i = buf_valid_start_offset; i + 2 <= buf_valid_end_offset; ++i) {\n        uint8_t b = bytes[i];\n        // Check for short conditional or unconditional jump\n        int branch_instruction_len = 0;\n        int32_t branch_offset = 0;\n        if (b == 0xeb || b == 0xe3 || (b >= 0x70 && b < 0x80)) {\n          branch_instruction_len = 2;\n          branch_offset = (int8_t)bytes[i + 1];\n        } else if (b == 0x0f && i + 6 <= buf_valid_end_offset &&\n                   (bytes[i + 1] >= 0x80 && bytes[i + 1] < 0x90)) {\n          branch_instruction_len = 6;\n          memcpy(&branch_offset, bytes + i + 2, 4);\n        }\n        if (branch_instruction_len) {\n          int offset_from_instruction_end = (int)i + branch_instruction_len +\n              branch_offset - (LOOK_BACK + instruction_length);\n          if (hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST) {\n            if (hook.flags & PATCH_IS_MULTIPLE_INSTRUCTIONS) {\n              found_potential_interfering_branch =\n                offset_from_instruction_end <= -(ssize_t)instruction_length &&\n                offset_from_instruction_end > -(ssize_t)(instruction_length + hook.patch_region_length);\n            } else {\n              found_potential_interfering_branch = offset_from_instruction_end == -(ssize_t)instruction_length;\n            }\n          } else {\n            if (hook.flags & PATCH_IS_MULTIPLE_INSTRUCTIONS) {\n              found_potential_interfering_branch =\n                offset_from_instruction_end >= 0 && offset_from_instruction_end < hook.patch_region_length;\n            } else {\n              found_potential_interfering_branch = offset_from_instruction_end == 0;\n            }\n          }\n          if (found_potential_interfering_branch) {\n            LOG(debug) << \"Found potential interfering branch at \"\n                        << ip.to_data_ptr<uint8_t>() - LOOK_BACK + i;\n            break;\n          }\n        }\n      }\n      if (found_potential_interfering_branch) {\n        continue;\n      }\n    }\n\n    remote_code_ptr start_range, end_range;\n    if (hook.flags & PATCH_SYSCALL_INSTRUCTION_IS_LAST) {\n      start_range = ip - hook.patch_region_length;\n      // if a thread has its RIP at the end of our range,\n      // it could be immediately after a syscall instruction that\n      // will need to be restarted. Patching out that instruction will\n      // prevent the kernel from restarting it. So, extend our range by\n      // one byte to detect such threads.\n      end_range = ip + instruction_length + 1;\n    } else {\n      start_range = ip;\n      end_range = ip + instruction_length + hook.patch_region_length;\n    }\n    if (!safe_for_syscall_patching(start_range, end_range, t)) {\n      transient_failure = true;\n      LOG(debug)\n          << \"Temporarily declining to patch syscall at \" << ip\n          << \" because a different task has its ip in the patched range\";\n      return nullptr;\n    }\n    LOG(debug) << \"Trying to patch bytes \"\n              << bytes_to_string(\n                    following_bytes,\n                    min<size_t>(following_bytes_count,\n                        sizeof(syscall_patch_hook::patch_region_bytes)));\n\n    return &hook;\n  }\n\n  LOG(debug) << \"Failed to find a syscall hook for bytes \"\n             << bytes_to_string(\n                    following_bytes,\n                    min<size_t>(following_bytes_count,\n                        sizeof(syscall_patch_hook::patch_region_bytes)));\n\n  return nullptr;\n}\n\n// Syscalls can be patched either on entry or exit. For most syscall\n// instruction code patterns we can steal bytes after the syscall instruction\n// and thus we patch on entry, but some patterns require using bytes from\n// before the syscall instruction itself and thus can only be patched on exit.\n// The `entering_syscall` flag tells us whether or not we're at syscall entry.\n// If we are, and we find a pattern that can only be patched at exit, we'll\n// set a flag on the RecordTask telling it to try again after syscall exit.\nbool Monkeypatcher::try_patch_syscall_x86ish(RecordTask* t, remote_code_ptr ip, bool entering_syscall,\n                                             SupportedArch arch, bool &should_retry) {\n  ASSERT(t, is_x86ish(arch)) << \"Unsupported architecture\";\n\n  size_t instruction_length = rr::syscall_instruction_length(arch);\n  bool transient_failure = false;\n  const syscall_patch_hook* hook_ptr = find_syscall_hook(t, ip - instruction_length,\n      entering_syscall, instruction_length, should_retry, transient_failure);\n  bool success = false;\n  // `syscallno` isn't necessarily correct here (in the extremely rare corner case that we\n  // deferred a patch and the signal handler changed it), but we only use it for logging.\n  intptr_t syscallno = t->regs().original_syscallno();\n  if (hook_ptr) {\n    // Get out of executing the current syscall before we patch it.\n    if (entering_syscall && !t->exit_syscall_and_prepare_restart(arch)) {\n      return false;\n    }\n\n    LOG(debug) << \"Patching syscall at \" << ip << \" syscall \"\n               << syscall_name(syscallno, t->arch()) << \" tid \" << t->tid;\n\n    success = patch_syscall_with_hook(*this, t, *hook_ptr, ip - instruction_length, instruction_length, 0);\n    if (!success && entering_syscall) {\n      // Need to reenter the syscall to undo exit_syscall_and_prepare_restart\n      t->enter_syscall(arch);\n    }\n  }\n\n  if (!success) {\n    if (!should_retry && !transient_failure) {\n      LOG(debug) << \"Failed to patch syscall at \" << ip << \" syscall \"\n                 << syscall_name(syscallno, t->arch()) << \" tid \" << t->tid;\n      tried_to_patch_syscall_addresses.insert(ip);\n    }\n    return false;\n  }\n\n  return true;\n}\n\nbool Monkeypatcher::try_patch_syscall_aarch64(RecordTask* t, remote_code_ptr ip, bool entering_syscall) {\n  uint32_t inst[2] = {0, 0};\n  size_t bytes_count = t->read_bytes_fallible(ip.to_data_ptr<uint8_t>() - 8, 8, &inst);\n  if (bytes_count < sizeof(inst) || inst[1] != 0xd4000001) {\n    LOG(debug) << \"Declining to patch syscall at \"\n               << ip - 4 << \" for unexpected instruction\";\n    tried_to_patch_syscall_addresses.insert(ip);\n    return false;\n  }\n  // mov x8, 0xdc\n  if (inst[0] == 0xd2801b88) {\n    // Clone may either cause the new and the old process to share stack (vfork)\n    // or replacing the stack (pthread_create)\n    // and requires special handling on the caller.\n    // Our syscall hook cannot do that so this would have to be a raw syscall.\n    // We can handle this at runtime but if we know the call is definitely\n    // a clone we can avoid patching it here.\n    LOG(debug) << \"Declining to patch clone syscall at \" << ip - 4;\n    tried_to_patch_syscall_addresses.insert(ip);\n    return false;\n  }\n\n  ASSERT(t, (syscall_hooks.size() == 1 && syscall_hooks[0].patch_region_length == 4 &&\n             memcmp(syscall_hooks[0].patch_region_bytes, &inst[1], 4) == 0))\n    << \"Unknown syscall hook\";\n\n  if (!safe_for_syscall_patching(ip - 4, ip, t)) {\n    LOG(debug)\n      << \"Temporarily declining to patch syscall at \" << ip - 4\n      << \" because a different task has its ip in the patched range\";\n    return false;\n  }\n\n  // Get out of executing the current syscall before we patch it.\n  if (entering_syscall && !t->exit_syscall_and_prepare_restart(aarch64)) {\n    return false;\n  }\n\n  LOG(debug) << \"Patching syscall at \" << ip - 4 << \" syscall \"\n             << syscall_name(t->regs().original_syscallno(), aarch64) << \" tid \" << t->tid;\n\n  auto success = patch_syscall_with_hook(*this, t, syscall_hooks[0], ip - 4, 4, 0);\n  if (!success && entering_syscall) {\n    // Need to reenter the syscall to undo exit_syscall_and_prepare_restart\n    if (!t->enter_syscall(aarch64)) {\n      return false;\n    }\n  }\n\n  if (!success) {\n    LOG(debug) << \"Failed to patch syscall at \" << ip - 4 << \" syscall \"\n               << syscall_name(t->regs().original_syscallno(), aarch64) << \" tid \" << t->tid;\n    tried_to_patch_syscall_addresses.insert(ip);\n    return false;\n  }\n\n  return true;\n}\n\n\nbool Monkeypatcher::try_patch_syscall(RecordTask* t, bool entering_syscall, bool &should_retry) {\n  Registers r = t->regs();\n  remote_code_ptr ip = r.ip();\n  return try_patch_syscall(t, entering_syscall, should_retry, ip);\n}\n\nbool Monkeypatcher::try_patch_syscall(RecordTask* t, bool entering_syscall, bool &should_retry, remote_code_ptr ip) {\n  if (syscall_hooks.empty()) {\n    // Syscall hooks not set up yet. Don't spew warnings, and don't\n    // fill tried_to_patch_syscall_addresses with addresses that we might be\n    // able to patch later.\n    return false;\n  }\n  if (t->emulated_ptracer) {\n    // Syscall patching can confuse ptracers, which may be surprised to see\n    // a syscall instruction at the current IP but then when running\n    // forwards, that the syscall occurs deep in the preload library instead.\n    return false;\n  }\n  if (t->is_in_traced_syscall()) {\n    // Never try to patch the traced-syscall in our preload library!\n    return false;\n  }\n  int syscallno = t->regs().original_syscallno();\n  if (is_clone_syscall(syscallno, t->arch()) ||\n      is_fork_syscall(syscallno, t->arch()) ||\n      is_vfork_syscall(syscallno, t->arch()) ||\n      is_clone3_syscall(syscallno, t->arch())) {\n    // If these end up in the syscallbuf when we fork/clone then very bad\n    // things happen. Of course if these are called via some\n    // syscall()-type multiplexer we're in trouble anyway...\n    return false;\n  }\n\n  // We should not get here for untraced syscalls or anything else from the rr page.\n  // These should be normally prevented by our seccomp filter\n  // and in the case of syscalls interrupted by signals,\n  // the check for the syscall restart should prevent us from reaching here.\n  ASSERT(t, ip.to_data_ptr<void>() < AddressSpace::rr_page_start() ||\n            ip.to_data_ptr<void>() >= AddressSpace::rr_page_end());\n  if (tried_to_patch_syscall_addresses.count(ip) || is_jump_stub_instruction(ip, true)) {\n    return false;\n  }\n\n  // We could examine the current syscall number and if it's not one that\n  // we support syscall buffering for, refuse to patch the syscall instruction.\n  // This would, on the face of it, reduce overhead since patching the\n  // instruction just means a useless trip through the syscall buffering logic.\n  // However, it actually wouldn't help much since we'd still do a switch\n  // on the syscall number in this function instead, and due to context\n  // switching costs any overhead saved would be insignificant.\n  // Also, implementing that would require keeping a buffered-syscalls\n  // list in sync with the preload code, which is unnecessary complexity.\n\n  SupportedArch arch;\n  if (!get_syscall_instruction_arch(\n          t, ip.decrement_by_syscall_insn_length(t->arch()), &arch) ||\n      arch != t->arch()) {\n    LOG(debug) << \"Declining to patch cross-architecture syscall at \" << ip;\n    tried_to_patch_syscall_addresses.insert(ip);\n    return false;\n  }\n\n  // Emit FLUSH_SYSCALLBUF if there's one pending.\n  // We want our mmap records to be associated with the next (PATCH_SYSCALL)\n  // event, not a FLUSH_SYSCALLBUF event.\n  t->maybe_flush_syscallbuf();\n  if (!t->is_stopped()) {\n    // Tracee was unexpectedly kicked out of a ptrace-stop by SIGKILL or\n    // equivalent. Abort trying to patch.\n    return false;\n  }\n\n  if (arch == aarch64) {\n    return try_patch_syscall_aarch64(t, ip, entering_syscall);\n  }\n  return try_patch_syscall_x86ish(t, ip, entering_syscall, arch, should_retry);\n}\n\nbool Monkeypatcher::try_patch_trapping_instruction(RecordTask* t, size_t instruction_length,\n                                                   bool before_instruction, bool &should_retry) {\n  if (syscall_hooks.empty()) {\n    // Syscall hooks not set up yet. Don't spew warnings, and don't\n    // fill tried_to_patch_syscall_addresses with addresses that we might be\n    // able to patch later.\n    return false;\n  }\n  if (t->emulated_ptracer) {\n    // Patching can confuse ptracers.\n    return false;\n  }\n\n  Registers r = t->regs();\n  remote_code_ptr ip_of_instruction = r.ip() - (before_instruction ? 0 : instruction_length);\n  if (tried_to_patch_syscall_addresses.count(ip_of_instruction + instruction_length)) {\n    return false;\n  }\n\n  // Emit FLUSH_SYSCALLBUF if there's one pending.\n  // We want our mmap records to be associated with the next (PATCH_SYSCALL)\n  // event, not a FLUSH_SYSCALLBUF event.\n  t->maybe_flush_syscallbuf();\n\n  bool transient_failure = false;\n  const syscall_patch_hook* hook_ptr =\n    find_syscall_hook(t, ip_of_instruction, before_instruction, instruction_length, should_retry, transient_failure);\n  bool success = false;\n  if (hook_ptr) {\n    LOG(debug) << \"Patching trapping instruction at \" << ip_of_instruction << \" tid \" << t->tid;\n\n    success = patch_syscall_with_hook(*this, t, *hook_ptr, ip_of_instruction,\n                                      instruction_length, SYS_rrcall_rdtsc);\n  }\n\n  if (!success) {\n    if (!should_retry && !transient_failure) {\n      LOG(debug) << \"Failed to patch trapping instruction at \" << ip_of_instruction << \" tid \" << t->tid;\n      tried_to_patch_syscall_addresses.insert(ip_of_instruction + instruction_length);\n    }\n    return false;\n  }\n\n  return true;\n}\n\n// VDSOs are filled with overhead critical functions related to getting the\n// time and current CPU.  We need to ensure that these syscalls get redirected\n// into actual trap-into-the-kernel syscalls so rr can intercept them.\n\ntemplate <typename Arch>\nstatic void patch_after_exec_arch(RecordTask* t, Monkeypatcher& patcher);\n\ntemplate <typename Arch>\nstatic void patch_at_preload_init_arch(RecordTask* t, Monkeypatcher& patcher);\n\ntemplate <>\nvoid patch_after_exec_arch<X86Arch>(RecordTask* t, Monkeypatcher& patcher) {\n  (void)patcher;\n  setup_preload_library_path<X86Arch>(t);\n  setup_audit_library_path<X86Arch>(t);\n\n  if (!t->vm()->has_vdso()) {\n    patch_auxv_vdso(t, AT_SYSINFO_EHDR, AT_IGNORE);\n  } else {\n    size_t librrpage_base = RR_PAGE_ADDR - AddressSpace::RRPAGE_RECORD_PAGE_OFFSET*PRELOAD_LIBRARY_PAGE_SIZE;\n    patch_auxv_vdso(t, AT_SYSINFO_EHDR, librrpage_base);\n    patch_auxv_vdso(t, X86Arch::RR_AT_SYSINFO, librrpage_base +\n      AddressSpace::RRVDSO_PAGE_OFFSET*PRELOAD_LIBRARY_PAGE_SIZE);\n  }\n}\n\n// Monkeypatch x86 vsyscall hook only after the preload library\n// has initialized. The vsyscall hook expects to be able to use the syscallbuf.\n// Before the preload library has initialized, the regular vsyscall code\n// will trigger ptrace traps and be handled correctly by rr.\ntemplate <>\nvoid patch_at_preload_init_arch<X86Arch>(RecordTask* t,\n                                         Monkeypatcher& patcher) {\n  auto params = t->read_mem(\n      remote_ptr<rrcall_init_preload_params<X86Arch>>(t->regs().arg1()));\n  if (!params.syscallbuf_enabled) {\n    return;\n  }\n\n  patcher.init_dynamic_syscall_patching(t, params.syscall_patch_hook_count,\n                                        params.syscall_patch_hooks);\n}\n\ntemplate <>\nvoid patch_after_exec_arch<X64Arch>(RecordTask* t, Monkeypatcher& patcher) {\n  setup_preload_library_path<X64Arch>(t);\n  setup_audit_library_path<X64Arch>(t);\n\n  for (const auto& m : t->vm()->maps()) {\n    auto& km = m.map;\n    patcher.patch_after_mmap(t, km.start(), km.size(), km.file_offset_bytes(),\n                             km.prot(), -1, Monkeypatcher::MMAP_EXEC);\n  }\n\n  if (!t->vm()->has_vdso()) {\n    patch_auxv_vdso(t, AT_SYSINFO_EHDR, AT_IGNORE);\n  } else {\n    size_t librrpage_base = RR_PAGE_ADDR - AddressSpace::RRPAGE_RECORD_PAGE_OFFSET*PRELOAD_LIBRARY_PAGE_SIZE;\n    patch_auxv_vdso(t, AT_SYSINFO_EHDR, librrpage_base);\n  }\n}\n\ntemplate <>\nvoid patch_after_exec_arch<ARM64Arch>(RecordTask* t, Monkeypatcher& patcher) {\n  setup_preload_library_path<ARM64Arch>(t);\n  setup_audit_library_path<ARM64Arch>(t);\n\n  for (const auto& m : t->vm()->maps()) {\n    auto& km = m.map;\n    patcher.patch_after_mmap(t, km.start(), km.size(), km.file_offset_bytes(),\n                             km.prot(), -1, Monkeypatcher::MMAP_EXEC);\n  }\n\n  if (!t->vm()->has_vdso()) {\n    patch_auxv_vdso(t, AT_SYSINFO_EHDR, AT_IGNORE);\n  } else {\n    size_t librrpage_base = RR_PAGE_ADDR - AddressSpace::RRPAGE_RECORD_PAGE_OFFSET*PRELOAD_LIBRARY_PAGE_SIZE;\n    patch_auxv_vdso(t, AT_SYSINFO_EHDR, librrpage_base);\n  }\n}\n\ntemplate <>\nvoid patch_at_preload_init_arch<X64Arch>(RecordTask* t,\n                                         Monkeypatcher& patcher) {\n  auto params = t->read_mem(\n      remote_ptr<rrcall_init_preload_params<X64Arch>>(t->regs().arg1()));\n  if (!params.syscallbuf_enabled) {\n    return;\n  }\n\n  patcher.init_dynamic_syscall_patching(t, params.syscall_patch_hook_count,\n                                        params.syscall_patch_hooks);\n}\n\ntemplate <>\nvoid patch_at_preload_init_arch<ARM64Arch>(RecordTask* t,\n                                           Monkeypatcher& patcher) {\n  auto params = t->read_mem(\n      remote_ptr<rrcall_init_preload_params<ARM64Arch>>(t->regs().orig_arg1()));\n  if (!params.syscallbuf_enabled) {\n    return;\n  }\n\n  patcher.init_dynamic_syscall_patching(t, params.syscall_patch_hook_count,\n                                        params.syscall_patch_hooks);\n}\n\nvoid Monkeypatcher::patch_after_exec(RecordTask* t) {\n  ASSERT(t, 1 == t->vm()->task_set().size())\n      << \"Can't have multiple threads immediately after exec!\";\n\n  RR_ARCH_FUNCTION(patch_after_exec_arch, t->arch(), t, *this);\n}\n\nvoid Monkeypatcher::patch_at_preload_init(RecordTask* t) {\n  // NB: the tracee can't be interrupted with a signal while\n  // we're processing the rrcall, because it's masked off all\n  // signals.\n  RR_ARCH_FUNCTION(patch_at_preload_init_arch, t->arch(), t, *this);\n}\n\nstatic remote_ptr<void> resolve_address(ElfReader& reader, uintptr_t elf_addr,\n                                        remote_ptr<void> map_start,\n                                        size_t map_size, uintptr_t map_offset,\n                                        uint64_t prot) {\n  PhdrInfo phdr;\n  if (!reader.addr_to_phdr(elf_addr, phdr)) {\n    LOG(warn) << \"ELF address \" << HEX(elf_addr) << \" not in file\";\n  }\n  if (phdr.offset < map_offset ||\n      phdr.offset + phdr.filesz > map_offset + map_size ||\n      bool(phdr.flags & PF_R) != bool(prot & PROT_READ) ||\n      bool(phdr.flags & PF_W) != bool(prot & PROT_WRITE) ||\n      bool(phdr.flags & PF_X) != bool(prot & PROT_EXEC)) {\n    // The value(s) to be set are outside the mapped range or belong to another\n    // mapping as indicated by the flags. This happens because code and data can\n    // be mapped in separate, partial mmaps in which case some symbols will be\n    // outside the mapped range.\n    return nullptr;\n  }\n\n  // This is the distance from the file offset of the mapping to p_offset, which\n  // is the same as the distance from map_start to p_vaddr + load bias.\n  auto page_start_offset = phdr.offset - map_offset;\n\n  // Adjust map_start so that it points to p_vaddr + load bias.\n  map_start += page_start_offset;\n\n  // Now subtract p_vaddr to make it point to virtual address 0 (the load bias).\n  map_start -= phdr.vaddr;\n\n  // Finally, add the address from the symbol table to adjust it by the load\n  // bias.\n  return map_start + elf_addr;\n}\n\nstatic void set_and_record_bytes(RecordTask* t, ElfReader& reader,\n                                 uintptr_t elf_addr, const void* bytes,\n                                 size_t size, remote_ptr<void> map_start,\n                                 size_t map_size, size_t map_offset,\n                                 uint64_t prot) {\n  remote_ptr<void> addr =\n      resolve_address(reader, elf_addr, map_start, map_size, map_offset, prot);\n  if (!addr) {\n    return;\n  }\n  bool ok = true;\n  t->write_bytes_helper(addr, size, bytes, &ok);\n  // Writing can fail when the value appears to be in the mapped range, but it\n  // actually is beyond the file length.\n  if (ok) {\n    t->record_local(addr, size, bytes);\n  }\n}\n\n/**\n * Patch _dl_runtime_resolve_(fxsave,xsave,xsavec) to clear \"FDP Data Pointer\"\n * register so that CPU-specific behaviors involving that register don't leak\n * into stack memory.\n */\nvoid Monkeypatcher::patch_dl_runtime_resolve(RecordTask* t, ElfReader& reader,\n                                             uintptr_t elf_addr,\n                                             remote_ptr<void> map_start,\n                                             size_t map_size, size_t map_offset,\n                                             uint64_t prot) {\n  if (t->arch() != x86_64) {\n    return;\n  }\n  remote_ptr<void> addr =\n    resolve_address(reader, elf_addr, map_start, map_size, map_offset, prot);\n  if (!addr) {\n    return;\n  }\n\n  uint8_t impl[X64DLRuntimeResolve::size + X64EndBr::size];\n  uint8_t *impl_start = impl;\n  t->read_bytes(addr, impl);\n  if (X64EndBr::match(impl) || X86EndBr::match(impl)) {\n    static_assert(X64EndBr::size == X86EndBr::size, \"EndBr patch size mismatch\");\n    LOG(debug) << \"Starts with endbr, skipping\";\n    addr += X64EndBr::size;\n    impl_start += X64EndBr::size;\n  }\n\n  static_assert(X64DLRuntimeResolve::size == X64DLRuntimeResolve2::size,\n                \"DLRuntimeResolve patch size mismatch\");\n  if (!X64DLRuntimeResolve::match(impl_start) &&\n      !X64DLRuntimeResolve2::match(impl_start)) {\n    LOG(warn) << \"_dl_runtime_resolve implementation doesn't look right\";\n    return;\n  }\n\n  vector<uint8_t> bytes(impl_start, impl_start + X64DLRuntimeResolve::size);\n  auto call_patch_start = addr.cast<uint8_t>();\n  saved_dl_runtime_resolve_code[call_patch_start] = std::move(bytes);\n\n  uint8_t call_patch[X64AbsoluteIndirectCallMonkeypatch::size];\n  X64AbsoluteIndirectCallMonkeypatch::substitute(call_patch,\n      RR_DL_RUNTIME_RESOLVE_CLEAR_FIP);\n  write_and_record_bytes(t, call_patch_start, call_patch);\n\n  // pad with NOPs to the next instruction\n  static const uint8_t NOP = 0x90;\n  uint8_t nops[X64DLRuntimeResolve::size - sizeof(call_patch)];\n  memset(nops, NOP, sizeof(nops));\n  write_and_record_mem(t, call_patch_start + sizeof(call_patch), nops,\n                       sizeof(nops));\n}\n\nvoid Monkeypatcher::unpatch_dl_runtime_resolves(RecordTask* t) {\n  for (auto entry : saved_dl_runtime_resolve_code) {\n    remote_ptr<uint8_t> addr = entry.first;\n    uint8_t impl[X64DLRuntimeResolve::size];\n    bool ok = true;\n    t->read_bytes_helper(addr, sizeof(impl), impl, &ok);\n    if (!ok) {\n      LOG(warn) << \"dl_runtime_resolve code has gone!\";\n      continue;\n    }\n    uint8_t call_patch[X64AbsoluteIndirectCallMonkeypatch::size];\n    X64AbsoluteIndirectCallMonkeypatch::substitute(call_patch,\n      RR_PAGE_ADDR - PRELOAD_LIBRARY_PAGE_SIZE);\n    if (memcmp(impl, call_patch, sizeof(call_patch))) {\n      LOG(warn) << \"dl_runtime_resolve code has changed!\";\n      continue;\n    }\n    write_and_record_mem(t, addr, entry.second.data(), entry.second.size());\n  }\n  saved_dl_runtime_resolve_code.clear();\n}\n\n// https://documentation-service.arm.com/static/67581b3355451e3c38d97c22\nstatic bool is_aarch64_bti(uint32_t instruction) {\n  if ((instruction >> 12) == 0b11010101000000110010 && (instruction & 0x1f) == 0b11111) {\n    // Hint instruction.\n    uint32_t crm = (instruction >> 8) & ((1 << 4) - 1);\n    uint32_t op2 = (instruction >> 5) & ((1 << 3) - 1);\n    return crm == 0b0100 && (op2 & 1) == 0;\n  }\n  return false;\n}\n\nstatic bool is_aarch64_adrp(uint32_t instruction, remote_ptr<void> pc, remote_ptr<void>* address) {\n  if ((instruction >> 31) == 1 && ((instruction >> 24) & 0x1f) == 0b10000) {\n    uint64_t base = (pc.as_int() >> 12) << 12;\n    uint64_t imm =  ((instruction >> 29) & 0x3) +\n        (((instruction >> 5) & ((1 << 19) - 1)) << 2);\n    *address = remote_ptr<void>(base + (imm << 12));\n    return true;\n  }\n  return false;\n}\n\nstatic bool is_aarch64_ldrb(uint32_t instruction, uint32_t* offset) {\n  if ((instruction >> 22) == 0b0011100101) {\n    *offset = (instruction >> 10) & ((1 << 12) - 1);\n    return true;\n  }\n  return false;\n}\n\n/**\n * Patch the __aarch64_have_lse_atomics variable to ensure that LSE atomics are\n * always used even if init_lse_atomics\n */\nvoid Monkeypatcher::patch_aarch64_have_lse_atomics(\n    RecordTask* t, ElfReader& reader, uintptr_t ldadd4_addr,\n    remote_ptr<void> map_start, size_t map_size, size_t map_offset,\n    uint64_t prot) {\n  ASSERT(t, t->arch() == aarch64);\n  remote_ptr<void> addr =\n    resolve_address(reader, ldadd4_addr, map_start, map_size, map_offset, prot);\n  if (!addr) {\n    return;\n  }\n\n  bool ok = true;\n  uint8_t instruction_bytes[12];\n  t->read_bytes_helper(addr, sizeof(instruction_bytes), instruction_bytes, &ok);\n  if (!ok) {\n    LOG(warn) << \"Can't read ldadd4 instruction bytes at \" << addr;\n    return;\n  }\n  uint32_t instructions[3];\n  memcpy(instructions, instruction_bytes, sizeof(instructions));\n  int index = 0;\n  if (is_aarch64_bti(instructions[0])) {\n    ++index;\n  }\n  remote_ptr<void> adrp_address;\n  if (!is_aarch64_adrp(instructions[index], addr + index*4, &adrp_address)) {\n    LOG(warn) << \"Instruction 0x\" << HEX(instructions[index]) << \" is not ADRP\";\n    return;\n  }\n  uint32_t ldrb_offset;\n  if (!is_aarch64_ldrb(instructions[index + 1], &ldrb_offset)) {\n    LOG(warn) << \"Instruction 0x\" << HEX(instructions[index + 1]) << \" is not LDRB\";\n    return;\n  }\n  remote_ptr<void> have_lse_atomics_addr = adrp_address + ldrb_offset;\n  uint8_t enable = 1;\n  write_and_record_mem(t, have_lse_atomics_addr.cast<uint8_t>(), &enable, 1);\n}\n\nstatic bool file_may_need_instrumentation(const AddressSpace::Mapping& map) {\n  size_t file_part = map.map.fsname().rfind('/');\n  if (file_part == string::npos) {\n    file_part = 0;\n  } else {\n    ++file_part;\n  }\n  const string& fsname = map.map.fsname();\n  return fsname.find(\"libpthread\", file_part) != string::npos ||\n    fsname.find(\"ld\", file_part) != string::npos;\n}\n\nvoid Monkeypatcher::patch_after_mmap(RecordTask* t, remote_ptr<void> start,\n                                     size_t size, size_t offset_bytes, uint64_t prot,\n                                     int child_fd, MmapMode mode) {\n  const auto& map = t->vm()->mapping_of(start);\n  if (!file_may_need_instrumentation(map)) {\n    return;\n  }\n  if (t->arch() == aarch64 && mode != MMAP_EXEC) {\n    return;\n  }\n  ScopedFd open_fd;\n  if (child_fd >= 0) {\n    open_fd = t->open_fd(child_fd, O_RDONLY);\n    ASSERT(t, open_fd.is_open()) << \"Failed to open child fd \" << child_fd;\n  } else {\n    char buf[100];\n    sprintf(buf, \"/proc/%d/map_files/%llx-%llx\", t->tid,\n            (long long)start.as_int(), (long long)start.as_int() + size);\n    // Reading these directly requires CAP_SYS_ADMIN, so open the link target\n    // instead.\n    char link[PATH_MAX];\n    int ret = readlink(buf, link, sizeof(link) - 1);\n    if (ret < 0) {\n      return;\n    }\n    link[ret] = 0;\n    open_fd = ScopedFd(link, O_RDONLY);\n    if (!open_fd.is_open()) {\n      return;\n    }\n  }\n  ElfFileReader reader(open_fd, t->arch());\n  // Check for symbols first in the library itself, regardless of whether\n  // there is a debuglink.  For example, on Fedora 26, the .symtab and\n  // .strtab sections are stripped from the debuginfo file for\n  // libpthread.so.\n  SymbolTable syms = reader.read_symbols(\".symtab\", \".strtab\");\n  if (syms.size() == 0) {\n    ScopedFd debug_fd = reader.open_debug_file(map.map.fsname());\n    if (debug_fd.is_open()) {\n      ElfFileReader debug_reader(debug_fd, t->arch());\n      syms = debug_reader.read_symbols(\".symtab\", \".strtab\");\n    }\n  }\n  switch (t->arch()) {\n    case x86:\n    case x86_64:\n      for (size_t i = 0; i < syms.size(); ++i) {\n        if (syms.is_name(i, \"__elision_aconf\")) {\n          static const int zero = 0;\n          // Setting __elision_aconf.retry_try_xbegin to zero means that\n          // pthread rwlocks don't try to use elision at all. See ELIDE_LOCK\n          // in glibc's elide.h.\n          set_and_record_bytes(t, reader, syms.addr(i) + 8, &zero, sizeof(zero),\n                               start, size, offset_bytes, prot);\n        }\n        if (syms.is_name(i, \"elision_init\")) {\n          // Make elision_init return without doing anything. This means\n          // the __elision_available and __pthread_force_elision flags will\n          // remain zero, disabling elision for mutexes. See glibc's\n          // elision-conf.c.\n          static const uint8_t ret = 0xC3;\n          set_and_record_bytes(t, reader, syms.addr(i), &ret, sizeof(ret), start,\n                               size, offset_bytes, prot);\n        }\n        // The following operations can only be applied once because after the\n        // patch is applied the code no longer matches the expected template.\n        // For replaying a replay to work, we need to only apply these changes\n        // during a real exec, not during the mmap operations performed when rr\n        // replays an exec.\n        if (mode == MMAP_EXEC &&\n            (syms.is_name(i, \"_dl_runtime_resolve_fxsave\") ||\n             syms.is_name(i, \"_dl_runtime_resolve_xsave\") ||\n             syms.is_name(i, \"_dl_runtime_resolve_xsavec\"))) {\n          patch_dl_runtime_resolve(t, reader, syms.addr(i), start, size,\n                                   offset_bytes, prot);\n        }\n      }\n      break;\n    case aarch64:\n      for (size_t i = 0; i < syms.size(); ++i) {\n        if (syms.is_name(i, \"__aarch64_ldadd4_relax\")) {\n          patch_aarch64_have_lse_atomics(t, reader, syms.addr(i), start, size,\n                                         offset_bytes, prot);\n        }\n      }\n      break;\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Monkeypatcher.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_MONKEYPATCHER_H_\n#define RR_MONKEYPATCHER_H_\n\n#include <map>\n#include <unordered_set>\n#include <vector>\n\n#include \"preload/preload_interface.h\"\n\n#include \"remote_code_ptr.h\"\n#include \"remote_ptr.h\"\n\nnamespace rr {\n\nclass ElfReader;\nclass RecordTask;\nclass ScopedFd;\nclass Task;\n\n/**\n * A class encapsulating patching state. There is one instance of this\n * class per tracee address space. Currently this class performs the following\n * tasks:\n *\n * 1) Patch the VDSO's user-space-only implementation of certain system calls\n * (e.g. gettimeofday) to do a proper kernel system call instead, so rr can\n * trap and record it (x86-64 only).\n *\n * 2) Patch the VDSO __kernel_vsyscall fast-system-call stub to redirect to\n * our syscall hook in the preload library (x86 only).\n *\n * 3) Patch syscall instructions whose following instructions match a known\n * pattern to call the syscall hook.\n *\n * Monkeypatcher only runs during recording, never replay.\n */\nclass Monkeypatcher {\npublic:\n  Monkeypatcher() {}\n  Monkeypatcher(const Monkeypatcher&) = default;\n\n  /**\n   * Apply any necessary patching immediately after exec.\n   * In this hook we patch everything that doesn't depend on the preload\n   * library being loaded.\n   */\n  void patch_after_exec(RecordTask* t);\n\n  /**\n   * During librrpreload initialization, apply patches that require the\n   * preload library to be initialized.\n   */\n  void patch_at_preload_init(RecordTask* t);\n\n  /**\n   * Try to patch the syscall instruction that |t| just entered. If this\n   * returns false, patching failed and the syscall should be processed\n   * as normal. If this returns true, patching succeeded and the syscall\n   * was aborted; ip() has been reset to the start of the patched syscall,\n   * and execution should resume normally to execute the patched code.\n   * Zero or more mapping operations are also recorded to the trace and must\n   * be replayed.\n   */\n  bool try_patch_syscall(RecordTask* t, bool entering_syscall, bool &should_retry);\n  bool try_patch_syscall(RecordTask* t, bool entering_syscall, bool &should_retry, remote_code_ptr ip);\n\n  bool try_patch_syscall_x86ish(RecordTask* t, remote_code_ptr ip, bool entering_syscall,\n                                SupportedArch arch, bool &should_retry);\n  bool try_patch_syscall_aarch64(RecordTask* t, remote_code_ptr ip, bool entering_syscall);\n\n  /**\n   * Try to patch the trapping instruction that |t| just trapped on. If this\n   * returns false, patching failed and the instruction should be processed\n   * as normal. If this returns true, patching succeeded.\n   * t->ip() is the address of the trapping instruction.\n   * and execution should resume normally to execute the patched code.\n   * Zero or more mapping operations are also recorded to the trace and must\n   * be replayed.\n   */\n  bool try_patch_trapping_instruction(RecordTask* t, size_t instruction_length,\n                                      bool before_instruction,\n                                      bool &should_retry);\n\n  /**\n   * Replace all extended jumps by syscalls again. Note that we do not try to\n   * patch the original locations, since we don't know what the tracee may have\n   * done with them in the meantime, we only patch the extended jump stubs,\n   * which the tracee isn't allowed to touch.\n   */\n  void unpatch_syscalls_in(Task *t);\n\n  /**\n   * Try to patch the vsyscall-entry pattern occurring right before ret_addr\n   * to instead point into the corresponding entry points in the vdso.\n   * Returns true if the patching succeeded, false if it doesn't. The tasks\n   * registers are left unmodified.\n   */\n  bool try_patch_vsyscall_caller(RecordTask *t, remote_code_ptr ret_addr);\n\n  void init_dynamic_syscall_patching(\n      RecordTask* t, int syscall_patch_hook_count,\n      remote_ptr<syscall_patch_hook> syscall_patch_hooks);\n\n  /**\n   * Try to allocate a stub from the sycall patching stub buffer. Returns null\n   * if there's no buffer or we've run out of free stubs.\n   */\n  remote_ptr<uint8_t> allocate_stub(RecordTask* t, size_t bytes);\n\n  enum MmapMode {\n    MMAP_EXEC,\n    MMAP_SYSCALL,\n  };\n  /**\n   * Apply any necessary patching immediately after an mmap. We use this to\n   * patch libpthread.so.\n   */\n  void patch_after_mmap(RecordTask* t, remote_ptr<void> start, size_t size,\n                        size_t offset_bytes, uint64_t prot, int child_fd,\n                        MmapMode mode);\n\n  /**\n   * The list of pages we've allocated to hold our extended jumps.\n   */\n  struct ExtendedJumpPage {\n    ExtendedJumpPage(remote_ptr<uint8_t> addr) : addr(addr), allocated(0) {}\n    remote_ptr<uint8_t> addr;\n    size_t allocated;\n  };\n  std::vector<ExtendedJumpPage> extended_jump_pages;\n\n  bool is_jump_stub_instruction(remote_code_ptr p, bool include_safearea);\n  // Return the breakpoint instruction (i.e. the last branch back to caller)\n  // if we are on the exit path in the jump stub\n  remote_code_ptr get_jump_stub_exit_breakpoint(remote_code_ptr ip, RecordTask *t);\n\n  void unpatch_dl_runtime_resolves(RecordTask* t);\n\n  struct patched_syscall {\n    // Pointer to hook inside the syscall_hooks array, which gets initialized\n    // once and is fixed afterwards.\n    const syscall_patch_hook *hook;\n    size_t size;\n    uint16_t safe_prefix = 0;\n    uint16_t safe_suffix = 0;\n  };\n\n  /**\n   * Addresses/lengths of syscallbuf stubs.\n   */\n  std::map<remote_ptr<uint8_t>, patched_syscall> syscallbuf_stubs;\n\nprivate:\n  void patch_dl_runtime_resolve(RecordTask* t, ElfReader& reader,\n                                uintptr_t elf_addr, remote_ptr<void> map_start,\n                                size_t map_size, size_t map_offset,\n                                uint64_t prot);\n  void patch_aarch64_have_lse_atomics(RecordTask* t, ElfReader& reader,\n                                      uintptr_t elf_addr,\n                                      remote_ptr<void> map_start,\n                                      size_t map_size, size_t map_offset,\n                                      uint64_t prot);\n\n  /**\n   * `ip` is the address of the instruction that triggered the syscall or trap\n   */\n  const syscall_patch_hook* find_syscall_hook(RecordTask* t,\n                                              remote_code_ptr ip,\n                                              bool entering_syscall,\n                                              size_t instruction_length,\n                                              bool &should_retry,\n                                              bool &transient_failure);\n\n  /**\n   * The list of supported syscall patches obtained from the preload\n   * library. Each one matches a specific byte signature for the instruction(s)\n   * after a syscall instruction.\n   */\n  std::vector<syscall_patch_hook> syscall_hooks;\n  /**\n   * The addresses of the instructions following syscalls or other\n   * instructions that we've tried (or are currently trying) to patch.\n   */\n  std::unordered_set<remote_code_ptr> tried_to_patch_syscall_addresses;\n\n  std::map<remote_ptr<uint8_t>, std::vector<uint8_t>> saved_dl_runtime_resolve_code;\n};\n\n} // namespace rr\n\n#endif /* RR_MONKEYPATCHER_H_ */\n"
  },
  {
    "path": "src/MvCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <stdio.h>\n#include <sysexits.h>\n\n#include <vector>\n\n#include \"Command.h\"\n#include \"TraceStream.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass MvCommand : public Command {\npublic:\n  virtual int run(vector<string>& args);\n\nprotected:\n  MvCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static MvCommand singleton;\n};\n\nMvCommand MvCommand::singleton(\"mv\", \" rr mv <trace> <new-trace>\\n\");\n\nstatic int mv(const string& from, const string& to, FILE* out) {\n  string reason;\n  if (!is_valid_trace_name(from, &reason) ||\n      !is_valid_trace_name(to, &reason)) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Trace name is invalid: %s\\n\"\n            \"\\n\",\n            reason.c_str());\n    return 1;\n  }\n\n  string from_path = resolve_trace_name(from);\n\n  if (!is_trace(from_path)) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Could not access / identify '%s' as a trace (errno %d).\\n\"\n            \"\\n\",\n            from_path.c_str(), errno);\n    return 1;\n  }\n\n  // resolve symlinks like latest_trace\n  from_path = real_path(from_path);\n\n  string to_path = to;\n  // if 'to' is not a path, view it as trace name and move to trace_dir/to\n  if (to.find(\"/\") == string::npos) {\n    to_path = trace_save_dir() + \"/\" + to;\n  }\n\n  string to_fname = filename(to_path.c_str());\n  if (to_fname == \"latest-trace\") {\n    fprintf(stderr, \"\\nrr: Cannot rename to latest-trace.\\n\\n\");\n    return 1;\n  }\n\n  if (access(to_path.c_str(), F_OK) == 0) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: New trace '%s' already exists or cannot be accessed.\\n\"\n            \"\\n\",\n            to_path.c_str());\n    return 1;\n  } else if (errno != ENOENT) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Cannot access new trace path '%s': errno %d\\n\"\n            \"\\n\",\n            to_path.c_str(), errno);\n    return 1;\n  }\n\n  // remove symlink before removing trace in case the former fails\n  // a bad symlink crashes e.g. rr ls and midas\n  if (is_latest_trace(from_path)) {\n    if (!remove_latest_trace_symlink()) {\n      return 1;\n    }\n  }\n\n  int ret = rename(from_path.c_str(), to_path.c_str());\n  if (ret != 0) {\n    const string err = strerror(errno);\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Cannot move '%s' to '%s': %s\\n\"\n            \"\\n\",\n            from_path.c_str(), to_path.c_str(), err.c_str());\n    return 1;\n  }\n\n  fprintf(out,\n          \"rr: Moved '%s' to '%s'\\n\",\n          from_path.c_str(),\n          to_path.c_str());\n  return 0;\n}\n\nint MvCommand::run(vector<string>& args) {\n  if (args.size() == 2 && verify_not_option(args)) {\n    string from = args[0];\n    args.erase(args.begin());\n    if (verify_not_option(args)) {\n      string to = args[0];\n      return mv(from, to, stdout);\n    }\n  }\n\n  print_help(stderr);\n  return 1;\n};\n\n} // namespace rr\n"
  },
  {
    "path": "src/NonvirtualPerfCounterMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_NONVIRTUAL_PERF_COUNTER_MONITOR_H_\n#define RR_NONVIRTUAL_PERF_COUNTER_MONITOR_H_\n\n#include \"FileMonitor.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor attached to (nonvirtualized) perf counter fds. This just stops those fds from\n * being mmaped.\n */\nclass NonvirtualPerfCounterMonitor : public FileMonitor {\npublic:\n  NonvirtualPerfCounterMonitor() {}\n\n  virtual Type type() override { return NonvirtualPerfCounter; }\n};\n\n} // namespace rr\n\n#endif /* RR_NONVIRTUAL_PERF_COUNTER_MONITOR_H_ */\n"
  },
  {
    "path": "src/ODirectFileMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_ODIRECT_MONITOR_H_\n#define RR_ODIRECT_MONITOR_H_\n\n#include \"FileMonitor.h\"\n#include \"TraceStream.h\"\n\nnamespace rr {\n\n/**\n * ODirectFileMonitor gets installed upon any use of O_DIRECT.\n * This monitor can get replaced by an MMappedFileMonitor if the\n * file is later MAP_SHARED.\n */\nclass ODirectFileMonitor : public FileMonitor {\npublic:\n  ODirectFileMonitor() : FileMonitor() {};\n\n  virtual Type type() override { return ODirect; }\n};\n\n} // namespace rr\n\n#endif /* RR_ODIRECT_MONITOR_H_ */\n"
  },
  {
    "path": "src/PackCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <dirent.h>\n#include <limits.h>\n#include <linux/fs.h>\n#include <linux/fiemap.h>\n#include <pthread.h>\n#include <string.h>\n#include <sys/statvfs.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <algorithm>\n#include <filesystem>\n#include <limits>\n#include <map>\n#include <set>\n\n#include \"Command.h\"\n#include \"Flags.h\"\n#include \"GdbServer.h\"\n#include \"ReplaySession.h\"\n#include \"ScopedFd.h\"\n#include \"TraceStream.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"main.h\"\n\n#include \"../third-party/blake2/blake2.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n/**\n * Pack the trace directory to eliminate duplicate files and to include all\n * files needed for transportation.\n *\n * We try VERY HARD to avoid losing data if a PackCommand is interrupted.\n */\nclass PackCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  PackCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static PackCommand singleton;\n};\n\nPackCommand PackCommand::singleton(\n    \"pack\",\n    \" rr pack [OPTION]... [<trace-dirs>...]\\n\"\n    \"  --symlink                  Create symlinks to all mmapped files\\n\"\n    \"                             instead of copying them.\\n\"\n    \"  --pack-dir=<path>          Specify a directory in which to pack common files.\\n\"\n    \"                             This helps conserve space when packing multiple traces\\n\"\n    \"                             with common files. Both the trace dir and pack dir\\n\"\n    \"                             (at the same relative path) are required for replay\\n\"\n    \"\\n\"\n    \"Eliminates duplicate files in the trace directory, and copies files into\\n\"\n    \"the trace directory as necessary to ensure that all needed files are in\\n\"\n    \"the trace directory and none of them are links to files outside the\\n\"\n    \"trace directory. This makes the trace directory independent of changes\\n\"\n    \"to other files and ready to be transported elsewhere (e.g. by packaging\\n\"\n    \"it into a ZIP or tar archive).\\n\"\n    \"Be careful sharing traces with others; they may contain sensitive information.\\n\");\n\nstruct PackFlags {\n  /* If true, insert symlinks into the trace dir which point to the original\n   * files, rather than copying the files themselves */\n  bool symlink;\n  std::string pack_dir;\n\n  PackFlags()\n      : symlink(false) {}\n};\n\nstruct FileHash {\n  uint8_t bytes[32];\n};\n\nbool operator<(const FileHash& h1, const FileHash& h2) {\n  return memcmp(h1.bytes, h2.bytes, sizeof(h1)) < 0;\n}\n\n// Allocate a fresh FileHash different from every other\n// FileHash. Not thread-safe!\nstatic FileHash allocate_unique_file_hash() {\n  static uint32_t hash = 0;\n  FileHash result;\n  memcpy(&result.bytes[0], &hash, sizeof(hash));\n  ++hash;\n  memset(&result.bytes[4], 0, sizeof(result.bytes) - sizeof(hash));\n  return result;\n}\n\nstruct FsExtentsHash {\n  uint8_t bytes[32];\n};\n\nbool operator<(const FsExtentsHash& h1, const FsExtentsHash& h2) {\n  return memcmp(h1.bytes, h2.bytes, sizeof(h1)) < 0;\n}\n\nstruct PackDir {\n  string dir;\n  map<FileHash, string> mapped_files;\n  PackDir(string dir) : dir(dir) {}\n};\n\nstatic bool name_comparator(const TraceReader::MappedData& d1,\n                            const TraceReader::MappedData d2) {\n  return d1.file_name < d2.file_name;\n}\n\nstatic bool names_equal(const TraceReader::MappedData& d1,\n                        const TraceReader::MappedData d2) {\n  return d1.file_name == d2.file_name;\n}\n\nstatic bool decreasing_size_comparator(const TraceReader::MappedData* d1,\n                                       const TraceReader::MappedData* d2) {\n  return d1->file_size_bytes > d2->file_size_bytes;\n}\n\nstatic bool is_hardlink(const string& file_name) {\n  const char* name = file_name.c_str();\n  const char* right_slash = strrchr(name, '/');\n  return right_slash && strncmp(right_slash + 1, \"mmap_hardlink_\", 14) == 0;\n}\n\nstatic void* process_files_thread(void* p) {\n  // Don't use log.h macros here since they're not necessarily thread-safe\n  auto data = static_cast<vector<pair<const std::string*, FileHash>>*>(p);\n  for (auto& pair : *data) {\n    const char* name = pair.first->c_str();\n    ScopedFd fd(name, O_RDONLY);\n    if (!fd.is_open()) {\n      fprintf(stderr, \"Failed to open %s\\n\", name);\n      exit(1);\n    }\n    blake2b_state b2_state;\n    if (blake2b_init(&b2_state, sizeof(pair.second.bytes))) {\n      fprintf(stderr, \"blake2b_init failed\");\n      exit(1);\n    }\n    while (true) {\n      char buf[1024 * 1024];\n      ssize_t r = read(fd, buf, sizeof(buf));\n      if (r < 0) {\n        fprintf(stderr, \"Failed reading from %s\\n\", name);\n        exit(1);\n      }\n      if (r == 0) {\n        break;\n      }\n      if (blake2b_update(&b2_state, buf, r)) {\n        fprintf(stderr, \"blake2b_update failed\");\n        exit(1);\n      }\n    }\n    if (blake2b_final(&b2_state, pair.second.bytes,\n                      sizeof(pair.second.bytes))) {\n      fprintf(stderr, \"blake2b_final failed\");\n      exit(1);\n    }\n  }\n  return nullptr;\n}\n\n// Return a size-sorted list of all mmapped files found in the trace\nstatic vector<TraceReader::MappedData> gather_files(const string& trace_dir) {\n  TraceReader trace(trace_dir);\n  vector<TraceReader::MappedData> files;\n  while (true) {\n    TraceReader::MappedData data;\n    bool found;\n    trace.read_mapped_region(&data, &found, TraceReader::VALIDATE,\n                             TraceReader::ANY_TIME);\n    if (!found) {\n      break;\n    }\n    if (data.source == TraceReader::SOURCE_FILE) {\n      files.push_back(data);\n    }\n  }\n\n  // Eliminate duplicates\n  stable_sort(files.begin(), files.end(), name_comparator);\n  auto last = unique(files.begin(), files.end(), names_equal);\n  files.erase(last, files.end());\n\n  return files;\n}\n\n// Returns true if FS_IOC_FIEMAP was supported and no extents are\n// UNKNOWN, storing a BLAKE2b hash of the extents metadata, file\n// size and filesystem ID in `result`. Otherwise returns false and\n// `result` is not initialized. `size` is always initialized.\n// If two files have the same FsExtentsHash then they have the same extents\n// and therefore the same contents.\n// If FS_IOC_FIEMAP is supported and the extents are known then this\n// deduplicates reflinked, hardlinked and symlinked files.\nstatic bool get_file_extents_hash(const string& file_name, FsExtentsHash* result,\n                                  uint64_t* size) {\n  const char* name = file_name.c_str();\n  ScopedFd fd(name, O_RDONLY);\n  if (!fd.is_open()) {\n    fprintf(stderr, \"Failed to open %s\\n\", name);\n    exit(1);\n  }\n  off_t seek_end = lseek(fd, 0, SEEK_END);\n  if (seek_end < 0) {\n    fprintf(stderr, \"Failed to SEEK_END %s\\n\", name);\n    exit(1);\n  }\n  *size = seek_end;\n\n  blake2b_state b2_state;\n  if (blake2b_init(&b2_state, sizeof(result->bytes))) {\n    fprintf(stderr, \"blake2b_init failed\\n\");\n    exit(1);\n  }\n  uint64_t offset = 0;\n  bool saw_last = false;\n  do {\n    union {\n      struct fiemap request;\n      char bytes[16384];\n    } buffer;\n    memset(&buffer.request, 0, sizeof(buffer.request));\n    buffer.request.fm_start = offset;\n    buffer.request.fm_length = FIEMAP_MAX_OFFSET;\n    buffer.request.fm_extent_count = ((char*)&buffer.bytes[sizeof(buffer.bytes)] -\n      (char*)&buffer.request.fm_extents[0])/sizeof(buffer.request.fm_extents[0]);\n    int ret = ioctl(fd, FS_IOC_FIEMAP, &buffer.request);\n    if (ret < 0) {\n      if (errno == ENOTTY || errno == EOPNOTSUPP) {\n        return false;\n      }\n      fprintf(stderr, \"FIEMAP ioctl failed\\n\");\n      exit(1);\n    }\n    if (!buffer.request.fm_mapped_extents) {\n      break;\n    }\n    for (size_t i = 0; i < buffer.request.fm_mapped_extents; ++i) {\n      const struct fiemap_extent& extent = buffer.request.fm_extents[i];\n      // Be super paranoid here. In btrfs at least, we see file extents where\n      // fe_physical is 0 and FIEMAP_EXTENT_DATA_INLINE|FIEMAP_EXTENT_NOT_ALIGNED\n      // are set; these are not real extents and the file contents are different\n      // even though the extent records are the same.\n      if ((extent.fe_flags & (FIEMAP_EXTENT_UNKNOWN | FIEMAP_EXTENT_DATA_INLINE |\n                              FIEMAP_EXTENT_DATA_TAIL | FIEMAP_EXTENT_NOT_ALIGNED))\n          || !extent.fe_physical) {\n        return false;\n      }\n      // It's not clear if file holes appear in the extents list or not.\n      // To be on the safe side, we hash the logical offsets so any holes\n      // will change the hash.\n      struct {\n        uint64_t fe_logical;\n        uint64_t fe_physical;\n        uint64_t fe_length;\n        uint32_t fe_flags;\n        uint32_t padding;\n      } buf = {\n        extent.fe_logical,\n        extent.fe_physical,\n        extent.fe_length,\n        extent.fe_flags,\n        0\n      };\n      if (blake2b_update(&b2_state, &buf, sizeof(buf))) {\n        fprintf(stderr, \"blake2b_update failed\\n\");\n        exit(1);\n      }\n      if (extent.fe_flags & FIEMAP_EXTENT_LAST) {\n        saw_last = true;\n        break;\n      }\n      offset = extent.fe_logical + extent.fe_length;\n    }\n  } while (!saw_last);\n\n  struct statvfs vfs_buf;\n  int ret = fstatvfs(fd, &vfs_buf);\n  if (ret < 0) {\n    fprintf(stderr, \"fstatvfs failed\\n\");\n    exit(1);\n  }\n  struct {\n    uint64_t size;\n    uint64_t fsid;\n  } buf = { *size, vfs_buf.f_fsid };\n  // Make sure the file size is hashed just in case it doesn't\n  // show up in the extents. We also need to hash the filesystem\n  // ID because the physical extents are local to the filesystem.\n  if (blake2b_update(&b2_state, &buf, sizeof(buf))) {\n    fprintf(stderr, \"blake2b_update failed\\n\");\n    exit(1);\n  }\n  if (blake2b_final(&b2_state, result->bytes, sizeof(result->bytes))) {\n    fprintf(stderr, \"blake2b_final failed\\n\");\n    exit(1);\n  }\n  return true;\n}\n\n// Makes a list of all mmapped files and computes their BLAKE2b hashes.\n// BLAKE2b was chosen because it's fast and cryptographically strong (we don't\n// compare the actual file contents, we're relying on hash collision avoidance).\n// Files with the same FileHash have the same contents.\n// The keys of the returned map are the full file names of the mapped files.\nstatic map<string, FileHash> gather_file_info(const string& trace_dir) {\n  vector<TraceReader::MappedData> files = gather_files(trace_dir);\n  int online_cpus = sysconf(_SC_NPROCESSORS_ONLN);\n  if (online_cpus < 1) {\n    FATAL() << \"sysconf(_SC_NPROCESSORS_ONLN) failed\";\n  }\n  int use_cpus = min(20, online_cpus);\n  use_cpus = min((int)files.size(), use_cpus);\n\n  // List of files indexed by their extents hash. All files\n  // with the same FsExtentsHash have the same contents.\n  map<FsExtentsHash, vector<const TraceReader::MappedData*>> extents_to_file;\n  // All files for which we failed to get extents. We know nothing\n  // about their contents.\n  vector<const TraceReader::MappedData*> files_with_no_extents;\n  for (const auto& file : files) {\n    FsExtentsHash extents_hash;\n    uint64_t size;\n    if (get_file_extents_hash(file.file_name, &extents_hash, &size)) {\n      extents_to_file[extents_hash].push_back(&file);\n    } else {\n      files_with_no_extents.push_back(&file);\n    }\n    if (size != file.file_size_bytes) {\n      fprintf(stderr, \"File size mismatch for %s\\n\", file.file_name.c_str());\n      exit(1);\n    }\n  }\n\n  // Make a list of files with possibly unique contents (i.e. excluding\n  // duplicates with the same FsExtentsHash).\n  vector<const TraceReader::MappedData*> files_to_hash = files_with_no_extents;\n  for (const auto& entry : extents_to_file) {\n    files_to_hash.push_back(entry.second[0]);\n  }\n  // We'll assign files to threads in round-robin order, ordered by decreasing size.\n  stable_sort(files_to_hash.begin(), files_to_hash.end(),\n              decreasing_size_comparator);\n\n  map<uint64_t, int32_t> file_size_to_file_count;\n  for (auto file : files_to_hash) {\n    ++file_size_to_file_count[file->file_size_bytes];\n  }\n\n  map<string, FileHash> result;\n  vector<vector<pair<const std::string*, FileHash>>> thread_files;\n  thread_files.resize(use_cpus);\n  int num_files_to_hash = 0;\n  for (auto file : files_to_hash) {\n    if (file_size_to_file_count[file->file_size_bytes] == 1) {\n      // There is only one file with this size, so it can't be a duplicate\n      // of any other files in `files_to_hash` and there is no need to hash\n      // its contents. We'll just make up a fake, unique hash value for it.\n      result[file->file_name] = allocate_unique_file_hash();\n      continue;\n    }\n    thread_files[num_files_to_hash % use_cpus].push_back(\n        make_pair(&file->file_name, FileHash()));\n    ++num_files_to_hash;\n  }\n\n  // Use multiple threads to actually hash the files we need to hash.\n  vector<pthread_t> threads;\n  for (size_t i = 0; i < thread_files.size(); ++i) {\n    pthread_t thread;\n    pthread_create(&thread, nullptr, process_files_thread, &thread_files[i]);\n    threads.push_back(thread);\n  }\n  for (pthread_t t : threads) {\n    pthread_join(t, nullptr);\n  }\n  for (auto& f : thread_files) {\n    for (auto& ff : f) {\n      result[*ff.first] = ff.second;\n    }\n  }\n\n  // Populate results for files we skipped because they had duplicate\n  // FsExtentsHashes.\n  for (const auto& entry : extents_to_file) {\n    for (size_t i = 1; i < entry.second.size(); ++i) {\n      // Taking a reference into `result` while we potentially\n      // rehash it could be bad.\n      FileHash h = result[entry.second[0]->file_name];\n      result[entry.second[i]->file_name] = h;\n    }\n  }\n\n  return result;\n}\n\nstatic bool is_in_trace_dir(const string& file_name, const string& trace_dir) {\n  return file_name.find(trace_dir) == 0;\n}\n\nstatic const char* last_filename_component(const string& file_name) {\n  const char* last_slash = strrchr(file_name.c_str(), '/');\n  const char* last_component = last_slash ? last_slash + 1 : file_name.c_str();\n  if (strncmp(last_component, \"mmap_hardlink_\", 14) == 0) {\n    last_component += 14;\n    while (*last_component && *last_component != '_') {\n      ++last_component;\n    }\n    if (*last_component == '_') {\n      ++last_component;\n    }\n  }\n  return last_component;\n}\n\nstatic string copy_into_trace(const string& file_name, const string& trace_dir,\n                              int* name_index) {\n  // We don't bother trying to do a reflink-copy here because if that was going\n  // to succeed, rr would probably already have used it during recording.\n  string new_name;\n  ScopedFd out_fd;\n  const char* last_component = last_filename_component(file_name);\n  while (true) {\n    char new_name_buf[PATH_MAX];\n    snprintf(new_name_buf, sizeof(new_name_buf) - 1, \"mmap_pack_%d_%s\",\n             *name_index, last_component);\n    new_name_buf[sizeof(new_name_buf) - 1] = 0;\n    new_name = trace_dir + \"/\" + new_name_buf;\n    ++*name_index;\n    out_fd = ScopedFd(new_name.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0700);\n    if (!out_fd.is_open()) {\n      if (errno == EEXIST) {\n        continue;\n      }\n      FATAL() << \"Couldn't create \" << new_name;\n    }\n    break;\n  }\n\n  ScopedFd in_fd(file_name.c_str(), O_RDONLY);\n  if (!in_fd.is_open()) {\n    FATAL() << \"Couldn't open \" << file_name;\n  }\n\n  while (true) {\n    char buf[1024 * 1024];\n    ssize_t r = read(in_fd, buf, sizeof(buf));\n    if (r < 0) {\n      FATAL() << \"Can't read from \" << file_name;\n    }\n    if (r == 0) {\n      break;\n    }\n    ssize_t written = 0;\n    while (written < r) {\n      ssize_t w = write(out_fd, buf + written, r - written);\n      if (w <= 0) {\n        FATAL() << \"Can't write to \" << new_name;\n      }\n      written += w;\n    }\n  }\n\n  // Try to avoid dataloss\n  if (fsync(out_fd) < 0) {\n    FATAL() << \"Can't write to \" << new_name;\n  }\n\n  return new_name;\n}\n\n// Generates a symlink inside the trace directory, pointing to the provided\n// file name.\nstatic string symlink_into_trace(const string& file_name,\n                                 const string& trace_dir, int* name_index) {\n  string new_name;\n  ScopedFd out_fd;\n  const char* last_component = last_filename_component(file_name);\n  while (true) {\n    char new_name_buf[PATH_MAX];\n    snprintf(new_name_buf, sizeof(new_name_buf) - 1, \"mmap_symlink_%d_%s\",\n             *name_index, last_component);\n    new_name_buf[sizeof(new_name_buf) - 1] = 0;\n    new_name = trace_dir + \"/\" + new_name_buf;\n    ++*name_index;\n    int ret = symlink(file_name.c_str(), new_name.c_str());\n    if (ret < 0) {\n      if (errno == EEXIST) {\n        continue;\n      }\n      FATAL() << \"Couldn't create symlink `\" << new_name << \"' to `\"\n              << file_name << \"'.\";\n    }\n    break;\n  }\n  return new_name;\n}\n\n// Insert symlinks into the trace directory, one for each mmapped file found in\n// the trace. Returns a mapping of absolute original file paths and the new\n// relative paths to the symlinks which are to be used in their place. Files\n// that already exist in the trace directory (including hardlinks) are left\n// in place and not symlinked.\nstatic map<string, string> compute_canonical_symlink_map(\n    const string& trace_dir) {\n  map<string, string> symlink_map;\n  int name_index = 0;\n\n  // Get all mmapped files from trace\n  vector<TraceReader::MappedData> files = gather_files(trace_dir);\n\n  for (auto& p : files) {\n    string name = p.file_name;\n    // If file is not in trace dir, create a symlink to it\n    if (!is_in_trace_dir(p.file_name, trace_dir)) {\n      name = symlink_into_trace(p.file_name, trace_dir, &name_index);\n    }\n    // Update the file map with the relative path of the target file\n    symlink_map[p.file_name] = string(strrchr(name.c_str(), '/') + 1);\n  }\n\n  return symlink_map;\n}\n\n/**\n * This computes a map giving, for each file referenced in the trace, the name\n * of a trace file to use instead. This copies files into the\n * trace directory if they're not in the tracedir already, or if they're\n * hardlinks to files outside the trace directory. All of the copied files\n * will have names starting with \"mmap_pack_\". For files in the trace directory\n * that have the same hash, we select just one of the files as the destination\n * for all files with that hash.\n */\nstatic map<string, string> compute_canonical_mmapped_files(\n    const string& trace_dir,\n    PackDir &pack_dir) {\n  map<string, FileHash> file_info = gather_file_info(trace_dir);\n\n  map<FileHash, string> hash_to_name;\n  for (auto& p : file_info) {\n    const auto& existing = hash_to_name.find(p.second);\n    if (existing != hash_to_name.end()) {\n      if (!is_hardlink(existing->second) &&\n          is_in_trace_dir(existing->second, trace_dir)) {\n        continue;\n      }\n    }\n    hash_to_name[p.second] = p.first;\n  }\n\n  int name_index = 0;\n  for (auto& p : hash_to_name) {\n    // Check if this in our common pack directory\n    auto it = pack_dir.mapped_files.find(p.first);\n    if (it != pack_dir.mapped_files.end()) {\n      LOG(debug) << \"Found in common pack dir\";\n      p.second = symlink_into_trace(filesystem::relative(it->second, trace_dir), trace_dir, &name_index);\n      continue;\n    }\n\n    // Copy hardlinked files into the trace to avoid the possibility of someone\n    // overwriting the original file.\n    if (is_hardlink(p.second) || !is_in_trace_dir(p.second, trace_dir)) {\n      if (pack_dir.dir != \"\") {\n        // If a pack dir is specified, first copy into pack dir, then symlink into trace.\n        auto path = pack_dir.mapped_files[p.first] = copy_into_trace(p.second, pack_dir.dir, &name_index);\n        p.second = symlink_into_trace(filesystem::relative(path, trace_dir), trace_dir, &name_index);\n      } else {\n        p.second = copy_into_trace(p.second, trace_dir, &name_index);\n      }\n    }\n  }\n\n  map<string, string> file_map;\n  for (auto& p : file_info) {\n    string name = hash_to_name[p.second];\n    if (!is_in_trace_dir(name, trace_dir)) {\n      FATAL() << \"Internal error; file is not in trace dir\";\n    }\n    // Replace absolute paths with trace-relative file names\n    file_map[p.first] = string(strrchr(name.c_str(), '/') + 1);\n  }\n\n  return file_map;\n}\n\n// Write out a new 'mmaps' file with the new file names and atomically\n// replace the existing 'mmaps' file with it.\nstatic void rewrite_mmaps(const map<string, string>& file_map,\n                          const string& trace_dir) {\n  string path = trace_dir + \"/pack_mmaps\";\n  CompressedWriter writer(path, TraceStream::mmaps_block_size(), 1);\n\n  TraceReader trace(trace_dir);\n  vector<TraceReader::MappedData> files;\n  while (true) {\n    TraceReader::MappedData data;\n    bool found;\n    vector<TraceRemoteFd> extra_fds;\n    bool skip_monitoring_mapped_fd;\n    KernelMapping km = trace.read_mapped_region(\n        &data, &found, TraceReader::VALIDATE, TraceReader::ANY_TIME,\n        &extra_fds, &skip_monitoring_mapped_fd);\n    if (!found) {\n      break;\n    }\n    if (data.source == TraceReader::SOURCE_FILE) {\n      auto m = file_map.find(data.file_name);\n      if (m == file_map.end()) {\n        FATAL() << \"Internal error, didn't assign file \" << data.file_name;\n      }\n      data.file_name = m->second;\n    }\n    TraceWriter::write_mapped_region_to_alternative_stream(\n        writer, data, km, extra_fds, skip_monitoring_mapped_fd);\n  }\n\n  // Try not to lose data!\n  writer.close(CompressedWriter::SYNC);\n  if (!writer.good()) {\n    FATAL() << \"Error writing \" << path;\n  }\n\n  // OK, now the atomic switchover to the new maps file.\n  // BEFORE this point, we haven't altered any of the original trace files.\n  // A crash might leave some \"mmap_pack_\" files around but that's OK. A retried\n  // \"rr pack\" that runs to completion will clean them all up.\n  // AFTER this point, we have altered the mmaps file and the trace remains\n  // valid.\n  string mmaps_path = trace_dir + \"/mmaps\";\n  if (rename(path.c_str(), mmaps_path.c_str()) < 0) {\n    FATAL() << \"Error renaming \" << path << \" to \" << mmaps_path;\n  }\n}\n\n// Delete any \"mmap_\" files that aren't destination files in our file_map.\nstatic void delete_unnecessary_files(const map<string, string>& file_map,\n                                     const string& trace_dir) {\n  set<string> retain;\n  for (auto& p : file_map) {\n    retain.insert(p.second);\n  }\n\n  DIR* dir = opendir(trace_dir.c_str());\n  if (!dir) {\n    FATAL() << \"Can't open directory \" << trace_dir;\n  }\n  struct dirent* d;\n  errno = 0;\n  vector<string> names;\n  while ((d = readdir(dir)) != nullptr) {\n    if (strncmp(d->d_name, \"mmap_\", 5) == 0 &&\n        retain.count(string(d->d_name)) == 0) {\n      names.push_back(string(d->d_name));\n    }\n  }\n  if (errno) {\n    FATAL() << \"Can't read directory \" << trace_dir;\n  }\n  closedir(dir);\n\n  for (auto& n : names) {\n    string name = trace_dir + \"/\" + n;\n    if (unlink(name.c_str()) < 0) {\n      FATAL() << \"Can't delete file \" << name;\n    }\n  }\n}\n\nstatic int pack(const vector<string>& trace_dirs, const PackFlags& flags) {\n  for (const string &trace_dir : trace_dirs) {\n    string dir;\n    {\n      // validate trace and produce default trace directory if trace_dir is empty\n      TraceReader reader(trace_dir);\n      dir = reader.dir();\n    }\n\n    PackDir pack_dir(flags.pack_dir);\n    char buf[PATH_MAX];\n    char* ret = realpath(dir.c_str(), buf);\n    if (!ret) {\n      FATAL() << \"realpath failed on \" << dir;\n    }\n    string abspath(buf);\n\n    if (flags.symlink) {\n      map<string, string> canonical_symlink_map =\n          compute_canonical_symlink_map(abspath);\n      rewrite_mmaps(canonical_symlink_map, abspath);\n      delete_unnecessary_files(canonical_symlink_map, abspath);\n    } else {\n      map<string, string> canonical_mmapped_files =\n          compute_canonical_mmapped_files(abspath, pack_dir);\n      rewrite_mmaps(canonical_mmapped_files, abspath);\n      delete_unnecessary_files(canonical_mmapped_files, abspath);\n    }\n\n    if (!probably_not_interactive(STDOUT_FILENO)) {\n      printf(\"rr: Packed trace directory `%s'.\\n\", dir.c_str());\n    }\n  }\n\n  return 0;\n}\n\nstatic bool parse_pack_arg(vector<string>& args, PackFlags& flags) {\n  static const OptionSpec options[] = {\n    { 0, \"symlink\", NO_PARAMETER },\n    { 1, \"pack-dir\", HAS_PARAMETER },\n  };\n  ParsedOption opt;\n  auto args_copy = args;\n  if (!Command::parse_option(args_copy, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 0:\n      flags.symlink = true;\n      break;\n    case 1:\n      flags.pack_dir = opt.value;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown pack option\");\n  }\n\n  args = args_copy;\n  return true;\n}\n\nint PackCommand::run(vector<string>& args) {\n  PackFlags flags;\n\n  while (parse_pack_arg(args, flags)) {\n  }\n\n  vector<string> trace_dirs;\n  while (!args.empty()) {\n    string trace_dir;\n    if (!parse_optional_trace_dir(args, &trace_dir)) {\n      print_help(stderr);\n      return 1;\n    }\n    trace_dirs.push_back(trace_dir);\n  }\n\n  // If no trace dirs were supplied, default to packing \"\", i.e. the latest trace.\n  if (trace_dirs.empty()) {\n    trace_dirs.push_back(\"\");\n  }\n\n  return pack(trace_dirs, flags);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/PerfCounterBuffers.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"PerfCounterBuffers.h\"\n\n#include <sys/mman.h>\n\n#include \"util.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nvoid PerfCounterBuffers::destroy() {\n  if (mmap_aux_buffer) {\n    munmap(mmap_aux_buffer, mmap_header->aux_size);\n    mmap_aux_buffer = nullptr;\n  }\n  if (mmap_header) {\n    munmap(mmap_header, page_size() + buffer_size);\n    mmap_header = nullptr;\n  }\n}\n\nvoid PerfCounterBuffers::allocate(ScopedFd& perf_event_fd,\n    uint64_t buffer_size, uint64_t aux_size, bool *ok) {\n  this->buffer_size = buffer_size;\n  if (ok) {\n    *ok = true;\n  }\n\n  void* base = mmap(NULL, page_size() + buffer_size,\n      PROT_READ | PROT_WRITE, MAP_SHARED, perf_event_fd, 0);\n  if (base == MAP_FAILED) {\n    const auto msg = \"Can't allocate memory for PT DATA area\";\n    if (!ok) {\n      FATAL() << msg;\n    }\n    LOG(warn) << msg;\n    *ok = false;\n    return;\n  }\n  mmap_header = static_cast<struct perf_event_mmap_page*>(base);\n\n  if (aux_size > 0) {\n    mmap_header->aux_offset = mmap_header->data_offset + mmap_header->data_size;\n    mmap_header->aux_size = aux_size;\n\n    void* aux = mmap(NULL, mmap_header->aux_size, PROT_READ | PROT_WRITE, MAP_SHARED,\n        perf_event_fd, mmap_header->aux_offset);\n    if (aux == MAP_FAILED) {\n      const auto msg = \"Can't allocate memory for PT AUX area\";\n      if (!ok) {\n        FATAL() << msg;\n      }\n      LOG(warn) << msg;\n      *ok = false;\n      return;\n    }\n    mmap_aux_buffer = static_cast<char*>(aux);\n  }\n}\n\noptional<PerfCounterBuffers::Packet> PerfCounterBuffers::next_packet() {\n  if (packet_in_use) {\n    FATAL() << \"Can't offer more than one packet at a time\";\n  }\n\n  // Equivalent of kernel's READ_ONCE. This value is written\n  // by the kernel.\n  uint64_t data_end =\n    *reinterpret_cast<volatile unsigned long long*>(&mmap_header->data_head);\n\n  // Force memory barrier to ensure that we see all memory updates that were\n  // performed before `data_head `was updated.\n  __sync_synchronize();\n\n  if (mmap_header->data_tail >= data_end) {\n    return nullopt;\n  }\n\n  char* data_buf = reinterpret_cast<char*>(mmap_header) + mmap_header->data_offset;\n  uint64_t data_start = mmap_header->data_tail;\n  size_t start_offset = data_start % mmap_header->data_size;\n  auto header_ptr = reinterpret_cast<struct perf_event_header*>(data_buf + start_offset);\n  struct perf_event_header header;\n  memcpy(&header, header_ptr, sizeof(header));\n\n  size_t first_chunk_size = min<size_t>(header.size,\n      mmap_header->data_size - start_offset);\n\n  if (first_chunk_size < header.size) {\n    packet_storage.resize(header.size);\n    memcpy(packet_storage.data(), const_cast<perf_event_header*>(header_ptr), first_chunk_size);\n    memcpy(packet_storage.data() + first_chunk_size, const_cast<char*>(data_buf), header.size - first_chunk_size);\n    header_ptr = reinterpret_cast<struct perf_event_header*>(packet_storage.data());\n  }\n\n  void* aux_ptr = nullptr;\n  packet_data_aux_end = mmap_header->aux_tail;\n  if (header.type == PERF_RECORD_AUX) {\n    PerfEventAux aux_packet = *reinterpret_cast<PerfEventAux*>(header_ptr);\n    size_t aux_start_offset = aux_packet.aux_offset % mmap_header->aux_size;\n    aux_ptr = mmap_aux_buffer + aux_start_offset;\n    first_chunk_size = min<size_t>(aux_packet.aux_size, mmap_header->aux_size - aux_start_offset);\n    if (first_chunk_size < aux_packet.aux_size) {\n      aux_packet_storage.resize(aux_packet.aux_size);\n      memcpy(aux_packet_storage.data(), aux_ptr, first_chunk_size);\n      memcpy(aux_packet_storage.data() + first_chunk_size, mmap_aux_buffer,\n             aux_packet.aux_size - first_chunk_size);\n      aux_ptr = aux_packet_storage.data();\n    }\n    packet_data_aux_end += aux_packet.aux_size;\n  }\n\n  packet_in_use = true;\n  packet_data_end = data_start + header.size;\n  return Packet(*this, header_ptr, aux_ptr);\n}\n\nvoid PerfCounterBuffers::release_packet() {\n  if (!packet_in_use) {\n    FATAL() << \"No packet!\";\n  }\n  mmap_header->data_tail = packet_data_end;\n  mmap_header->aux_tail = packet_data_aux_end;\n  packet_in_use = false;\n}\n\n}\n"
  },
  {
    "path": "src/PerfCounterBuffers.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PERF_COUNTER_BUFFERS_H_\n#define RR_PERF_COUNTER_BUFFERS_H_\n\n#include <stdint.h>\n\n#include <optional>\n\n#include <linux/perf_event.h>\n\n#include \"ScopedFd.h\"\n\nnamespace rr {\n\n// I wish I knew why this type isn't defined in perf_event.h but is just\n// commented out there...\nstruct PerfEventAux {\n  struct perf_event_header header;\n  uint64_t aux_offset;\n  uint64_t aux_size;\n  uint64_t flags;\n  uint64_t sample_id;\n};\n\n/**\n * Encapsulates the mmap buffers used for perf events.\n */\nclass PerfCounterBuffers {\npublic:\n  PerfCounterBuffers() : mmap_header(nullptr), mmap_aux_buffer(nullptr),\n      buffer_size(0), packet_in_use(false) {}\n  ~PerfCounterBuffers() { destroy(); }\n\n  void allocate(ScopedFd& perf_event_fd, uint64_t buffer_size, uint64_t aux_size, bool *ok = nullptr);\n  void destroy();\n\n  bool allocated() const { return mmap_header != nullptr; }\n\n  class Packet {\n  public:\n    Packet(Packet&& other) : buffers(other.buffers), data_(other.data_),\n        aux_data_(other.aux_data_) {\n      other.buffers = nullptr;\n    }\n    ~Packet() {\n      if (buffers) {\n        buffers->release_packet();\n      }\n    }\n    struct perf_event_header* data() const { return data_; }\n    void* aux_data() const { return aux_data_; }\n\n  private:\n    friend class PerfCounterBuffers;\n\n    Packet(PerfCounterBuffers& buffers, struct perf_event_header* data,\n        void* aux_data)\n      : buffers(&buffers), data_(data), aux_data_(aux_data) {}\n\n    PerfCounterBuffers* buffers;\n    struct perf_event_header* data_;\n    void* aux_data_;\n  };\n\n  std::optional<Packet> next_packet();\n\nprivate:\n  friend class Packet;\n\n  void release_packet();\n\n  perf_event_mmap_page* mmap_header;\n  char* mmap_aux_buffer;\n  uint64_t buffer_size;\n  uint64_t packet_data_end;\n  uint64_t packet_data_aux_end;\n  std::vector<uint8_t> packet_storage;\n  std::vector<uint8_t> aux_packet_storage;\n  bool packet_in_use;\n};\n\n} // namespace rr\n\n#endif /* RR_PERF_COUNTER_BUFFERS_H_ */\n"
  },
  {
    "path": "src/PerfCounters.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"PerfCounters.h\"\n\n#include <dirent.h>\n#include <err.h>\n#include <fcntl.h>\n#include <linux/perf_event.h>\n#include <poll.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/syscall.h>\n#include <sys/types.h>\n#include <unistd.h>\n#include <time.h>\n\n#ifdef BPF\n#include <bpf/libbpf.h>\n#include <linux/hw_breakpoint.h>\n#endif\n\n#include <algorithm>\n#include <fstream>\n#include <limits>\n#include <regex>\n#include <string>\n#include <unordered_set>\n\n#include \"CPUs.h\"\n#include \"Flags.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n#define PERF_COUNT_RR 0x72727272L\n\nstatic bool attributes_initialized;\nstatic bool cpu_improperly_configured;\n// At some point we might support multiple kinds of ticks for the same CPU arch.\n// At that point this will need to become more complicated.\nstruct perf_event_attrs {\n  // bug_flags is an architecture dependent flags to determine\n  // what bugs need to be checked.\n  // Current, this is simply the uarch on x86 and unused on aarch64.\n  int bug_flags = 0;\n  perf_event_attr ticks{};\n  perf_event_attr minus_ticks{};\n  perf_event_attr cycles{};\n  perf_event_attr llsc_fail{};\n  const char *pmu_name = nullptr;\n  uint32_t pmu_flags = 0;\n  uint32_t skid_size = 0;\n  uint32_t ticks_min_period = 1;\n  bool checked = false;\n  bool has_ioc_period_bug = false;\n  bool only_one_counter = false;\n  bool activate_useless_counter = false;\n};\n// If this contains more than one element, it's indexed by the CPU index.\nstatic std::vector<perf_event_attrs> perf_attrs;\nstatic uint32_t pmu_semantics_flags;\n\n/*\n * Find out the cpu model using the cpuid instruction.\n *\n * A 3rd party list of CPUIDs at https://sandpile.org/x86/cpuid.htm\n *\n * Intel's up-to-date and complete list is in\n * \"Volume 4: Model-Specific Registers\", Chapter 2.\n * See \"Intel 64 and IA-32 Architectures Software Developer Manual\"\n * https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html\n *\n * Alternatively you can find the recently added CPUIDs in the lighter document\n * called \"Documentation Changes\", navigate in table of contents to\n * \"27. Updates to Chapter 2, Volume 4\"\n * and then \"Chapter 2 Model-Specific Registers (MSRs)\"\n *\n * AMD: your best bet is https://www.amd.com/en/search/documentation/hub.html\n * Search for \"revision guide Family 17h\" and \"Model 31h\" or \"Models 00h-0Fh\"\n * For example \"Revision Guide for AMD Family 19h Models 00h-0Fh Processors\"\n * has a \"Table 2\" with \"CPUID Values for AMD\" showing the specific model and\n * revisions.\n *\n * These are roughly sorted by vendor, then by lineage, and then by time.\n */\nenum CpuMicroarch {\n  UnknownCpu,\n  FirstIntel,\n  IntelMerom = FirstIntel,\n  IntelPenryn,\n  IntelNehalem,\n  IntelWestmere,\n  IntelSandyBridge,\n  IntelIvyBridge,\n  IntelHaswell,\n  IntelBroadwell,\n  IntelSkylake,\n  IntelKabyLake,\n  IntelCometLake,\n  IntelIceLake,\n  IntelTigerLake,\n  IntelRocketLake,\n  IntelAlderLake,\n  IntelRaptorLake,\n  IntelSapphireRapids,\n  IntelEmeraldRapids,\n  IntelGraniteRapids,\n  IntelMeteorLake,\n  IntelLunarLake,\n  IntelArrowLake,\n  IntelSilvermont,\n  IntelGoldmont,\n  IntelTremont,\n  IntelGracemont,\n  IntelCrestmont,\n  IntelSkymont,\n  LastIntel = IntelSkymont,\n  FirstAMD,\n  AMDF15 = FirstAMD,\n  AMDZen,\n  AMDZen2,\n  AMDZen3,\n  AMDZen4,\n  AMDZen5,\n  LastAMD = AMDZen5,\n  FirstARM,\n  ARMNeoverseN1 = FirstARM,\n  ARMNeoverseN2,\n  ARMNeoverseN3,\n  ARMNeoverseE1,\n  ARMNeoverseV1,\n  ARMNeoverseV2,\n  ARMNeoverseV3AE,\n  ARMNeoverseV3,\n  ARMCortexA55,\n  ARMCortexA75,\n  ARMCortexA76,\n  ARMCortexA77,\n  ARMCortexA78,\n  ARMCortexX1,\n  AmpereOne,\n  AppleM1Icestorm,\n  AppleM1Firestorm,\n  AppleM2Blizzard,\n  AppleM2Avalanche,\n  LastARM = AppleM2Avalanche,\n};\n\n/*\n * Set if this CPU supports ticks counting retired conditional branches.\n */\n#define PMU_TICKS_RCB (1<<0)\n\n/*\n * Some CPUs turn off the whole PMU when there are no remaining events\n * scheduled (perhaps as a power consumption optimization). This can be a\n * very expensive operation, and is thus best avoided. For cpus, where this\n * is a problem, we keep a cycles counter (which corresponds to one of the\n * fixed function counters, so we don't use up a programmable PMC) that we\n * don't otherwise use, but keeps the PMU active, greatly increasing\n * performance.\n */\n#define PMU_BENEFITS_FROM_USELESS_COUNTER (1<<1)\n\n/*\n * Set if this CPU supports ticks counting all taken branches\n * (excluding interrupts, far branches, and rets).\n */\n#define PMU_TICKS_TAKEN_BRANCHES (1<<3)\n\n/*\n * Set if this CPU is known to have essentially unbounded skid,\n * i.e. the provided skid value is exceeded in rare cases.\n */\n#define PMU_SKID_UNBOUNDED (1<<4)\n\nstruct PmuConfig {\n  CpuMicroarch uarch;\n  const char* name;\n  uint64_t rcb_cntr_event;\n  uint64_t minus_ticks_cntr_event;\n  uint64_t llsc_cntr_event;\n  uint32_t skid_size;\n  uint32_t flags;\n  const char* pmu_name = nullptr; // ARM only\n  uint64_t cycle_event = PERF_COUNT_HW_CPU_CYCLES;\n  int cycle_type = PERF_TYPE_HARDWARE;\n  int event_type = PERF_TYPE_RAW;\n};\n\n// XXX please only edit this if you really know what you're doing.\n// event = 0x5101c4:\n// - 51 = generic PMU\n// - 01 = umask for event BR_INST_RETIRED.CONDITIONAL\n// - c4 = eventsel for event BR_INST_RETIRED.CONDITIONAL\n// event = 0x5301cb:\n// - 51 = generic PMU\n// - 01 = umask for event HW_INTERRUPTS.RECEIVED\n// - cb = eventsel for event HW_INTERRUPTS.RECEIVED\n// See Intel 64 and IA32 Architectures Performance Monitoring Events.\n// See check_events from libpfm4.\n// Match order of CpuMicroarch.\n// For the Intel Core lineage, we use the name of the product rather than\n// the official name of the microarchitecture. For hybrid products the\n// data in this table is for the P-cores of that product. For E-cores\n// we use their actual Atom (\"mont\") microarchitecture.\nstatic const PmuConfig pmu_configs[] = {\n  { UnknownCpu, \"Unknown\", 0, 0, 0, 0, 0 },\n  { IntelMerom, \"Intel Merom\", 0, 0, 0, 100, 0 },\n  { IntelPenryn, \"Intel Penryn\", 0, 0, 0, 100, 0 },\n  { IntelNehalem, \"Intel Nehalem\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelWestmere, \"Intel Westmere\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelSandyBridge, \"Intel Sandy Bridge\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelIvyBridge, \"Intel Ivy Bridge\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelHaswell, \"Intel Haswell\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelBroadwell, \"Intel Broadwell\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelSkylake, \"Intel Skylake\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelKabyLake, \"Intel Kaby Lake\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelCometLake, \"Intel Comet Lake\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelIceLake, \"Intel Ice Lake\", 0x5111c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelTigerLake, \"Intel Tiger Lake\", 0x5111c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelRocketLake, \"Intel Rocket Lake\", 0x5111c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelAlderLake, \"Intel Alder Lake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelRaptorLake, \"Intel Raptor Lake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelSapphireRapids, \"Intel Sapphire Rapids\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelEmeraldRapids, \"Intel Emerald Rapids\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelGraniteRapids, \"Intel Granite Rapids\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelMeteorLake, \"Intel Meteor Lake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelLunarLake, \"Intel Lunar Lake\", 0x100005111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelArrowLake, \"Intel Arrow Lake\", 0x100005111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelSilvermont, \"Intel Silvermont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelGoldmont, \"Intel Goldmont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelTremont, \"Intel Tremont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelGracemont, \"Intel Gracemont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelCrestmont, \"Intel Crestmont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelSkymont, \"Intel Skymont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { AMDF15, \"AMD Family 15h\", 0xc4, 0xc6, 0, 250, PMU_TICKS_TAKEN_BRANCHES },\n  // 0xd1 == RETIRED_CONDITIONAL_BRANCH_INSTRUCTIONS - Number of retired conditional branch instructions\n  // 0x2c == INTERRUPT_TAKEN - Counts the number of interrupts taken\n  // Both counters are available on all Zen microarchitecures so far.\n  { AMDZen, \"AMD Zen\", 0x5100d1, 0, 0, 10000, PMU_TICKS_RCB | PMU_SKID_UNBOUNDED },\n  { AMDZen2, \"AMD Zen 2\", 0x5100d1, 0, 0, 10000, PMU_TICKS_RCB | PMU_SKID_UNBOUNDED },\n  { AMDZen3, \"AMD Zen 3\", 0x5100d1, 0, 0, 10000, PMU_TICKS_RCB | PMU_SKID_UNBOUNDED },\n  { AMDZen4, \"AMD Zen 4\", 0x5100d1, 0, 0, 10000, PMU_TICKS_RCB | PMU_SKID_UNBOUNDED },\n  { AMDZen5, \"AMD Zen 5\", 0x5100d1, 0, 0, 10000, PMU_TICKS_RCB | PMU_SKID_UNBOUNDED },\n  // Performance cores from ARM from cortex-a76 on (including neoverse-n1 and later)\n  // have the following counters that are reliable enough for us.\n  // 0x21 == BR_RETIRED - Architecturally retired taken branches\n  // 0x6F == STREX_SPEC - Speculatively executed strex instructions\n  // 0x11 == CPU_CYCLES - Cycle\n  { ARMNeoverseN1, \"ARM Neoverse N1\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseN2, \"ARM Neoverse N2\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseN3, \"ARM Neoverse N3\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseE1, \"ARM Neoverse E1\", 0, 0, 0, 0, 0 },\n  { ARMNeoverseV1, \"ARM Neoverse V1\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseV2, \"ARM Neoverse V2\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseV3AE, \"ARM Neoverse V3AE\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseV3, \"ARM Neoverse V3\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  // cortex-a55, cortex-a75 and neoverse-e1 counts uarch ISB\n  // as retired branches so the BR_RETIRED counter is not reliable.\n  // There are some counters that are somewhat more reliable than\n  // the total branch count (0x21) including\n  // 0x0D (BR_IMMED_RETIRED) 0x0E (BR_RETURN_RETIRED)\n  // 0xCD (BR_INDIRECT_ADDR_PRED) 0x76 (PC_WRITE_SPEC)\n  // 0x78 (BR_IMMED_SPEC), 0xC9 (BR_COND_PRED)\n  // 0xCD (BR_INDIRECT_ADDR_PRED)\n  // but according to tests on the LITTLE core on a snapdragon 865\n  // none of them (including the sums) seems to be useful/reliable enough.\n  { ARMCortexA55, \"ARM Cortex A55\", 0, 0, 0, 0, 0 },\n  { ARMCortexA75, \"ARM Cortex A75\", 0, 0, 0, 0, 0 },\n  { ARMCortexA76, \"ARM Cortex A76\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { ARMCortexA77, \"ARM Cortex A77\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { ARMCortexA78, \"ARM Cortex A78\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { ARMCortexX1, \"ARM Cortex X1\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { AmpereOne, \"AmpereOne\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { AppleM1Icestorm, \"Apple M1 Icestorm\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_icestorm_pmu\", 0x8c, -1, -1 },\n  { AppleM1Firestorm, \"Apple M1 Firestorm\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_firestorm_pmu\", 0x8c, -1, -1 },\n  { AppleM2Blizzard, \"Apple M2 Blizzard\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_blizzard_pmu\", 0x8c, -1, -1 },\n  { AppleM2Avalanche, \"Apple M2 Avalanche\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_avalanche_pmu\", 0x8c, -1, -1 },\n};\n\n#define RR_SKID_MAX 10000\n\nstatic string lowercase(const string& s) {\n  string c = s;\n  transform(c.begin(), c.end(), c.begin(), ::tolower);\n  return c;\n}\n\n// The index of the PMU we are using within perf_attrs.\n// This is always 0 if we detected a single PMU type\n// and will be the same as the CPU index if we detected multiple PMU types.\nstatic int get_pmu_index(BindCPU cpu_binding) {\n  if (cpu_binding.mode == BindCPU::UNBOUND) {\n    if (perf_attrs.size() > 1) {\n      CLEAN_FATAL() << \"\\nMultiple PMU types detected. Unbinding CPU is not supported.\";\n    }\n    return 0;\n  }\n  if (cpu_binding.mode != BindCPU::SPECIFIED_CORE) {\n    FATAL() << \"Only specified-core mode supported at this point\";\n  }\n  int cpu = cpu_binding.specified_core;\n  if (!PerfCounters::support_cpu(cpu)) {\n    CLEAN_FATAL() << \"\\nPMU on cpu \" << cpu << \" is not supported.\";\n  }\n  if (perf_attrs.size() == 1) {\n    // Single PMU type.\n    return 0;\n  }\n  if ((size_t)cpu >= perf_attrs.size()) {\n    CLEAN_FATAL() << \"\\nUnable to find PMU type for CPU \" << cpu;\n  }\n  return cpu;\n}\n\nstatic void init_perf_event_attr(struct perf_event_attr* attr,\n                                 unsigned type, uint64_t config) {\n  memset(attr, 0, sizeof(*attr));\n  attr->type = perf_type_id(type);\n  attr->size = sizeof(*attr);\n  attr->config = config;\n  // rr requires that its events count userspace tracee code\n  // only.\n  attr->exclude_kernel = 1;\n  attr->exclude_guest = 1;\n}\n\nstatic const uint64_t IN_TX = 1ULL << 32;\nstatic const uint64_t IN_TXCP = 1ULL << 33;\n\nstatic int64_t read_counter(ScopedFd& fd) {\n  int64_t val;\n  ssize_t nread = read(fd, &val, sizeof(val));\n  DEBUG_ASSERT(nread == sizeof(val));\n  return val;\n}\n\n// Can return a closed fd if `tid > 0` and the task was just SIGKILLed.\nstatic ScopedFd start_counter(pid_t tid, int group_fd,\n                              struct perf_event_attr* attr,\n                              bool* disabled_txcp = nullptr) {\n  if (disabled_txcp) {\n    *disabled_txcp = false;\n  }\n  attr->pinned = group_fd == -1;\n  int fd = syscall(__NR_perf_event_open, attr, tid, -1, group_fd, PERF_FLAG_FD_CLOEXEC);\n  if (fd < 0 && errno == EINVAL && attr->type == PERF_TYPE_RAW &&\n      (attr->config & IN_TXCP)) {\n    // The kernel might not support IN_TXCP, so try again without it.\n    struct perf_event_attr tmp_attr = *attr;\n    tmp_attr.config &= ~IN_TXCP;\n    fd = syscall(__NR_perf_event_open, &tmp_attr, tid, -1, group_fd, PERF_FLAG_FD_CLOEXEC);\n    if (fd >= 0) {\n      if (disabled_txcp) {\n        *disabled_txcp = true;\n      }\n      LOG(warn) << \"kernel does not support IN_TXCP\";\n      if ((cpuid(CPUID_GETEXTENDEDFEATURES, 0).ebx & HLE_FEATURE_FLAG) &&\n          !Flags::get().suppress_environment_warnings) {\n        fprintf(stderr,\n                \"Your CPU supports Hardware Lock Elision but your kernel does\\n\"\n                \"not support setting the IN_TXCP PMU flag. Record and replay\\n\"\n                \"of code that uses HLE will fail unless you update your\\n\"\n                \"kernel.\\n\");\n      }\n    }\n  }\n  if (fd < 0) {\n    switch (errno) {\n      case EACCES: {\n        // Debian/Ubuntu/Android? are known to carry a patch that creates\n        // additional perf_event_paranoid levels, and at level 4 no\n        // perf_event_open() is allowed at all.\n        // https://git.launchpad.net/~ubuntu-kernel/ubuntu/+source/linux/+git/noble/commit/kernel/events/core.c?id=e88769f04a4f050e02980f776942c28431e56faf\n        // XXXkhuey ideally we could suggest adding CAP_PERFMON to rr here\n        // but the patch only accepts CAP_SYS_ADMIN.\n        auto perf_event_paranoid = read_perf_event_paranoid();\n        if (perf_event_paranoid.has_value() && *perf_event_paranoid > 3) {\n          string paranoid_value = std::to_string(*perf_event_paranoid);\n          CLEAN_FATAL() <<\n            \"rr needs /proc/sys/kernel/perf_event_paranoid <= 3, but it is \"\n                        << paranoid_value << \".\\n\"\n                        << \"Change it to <= 3.\\n\"\n                        << \"Consider putting 'kernel.perf_event_paranoid = 3' in /etc/sysctl.d/10-rr.conf.\\n\"\n                        << \"See 'man 8 sysctl', 'man 5 sysctl.d' (systemd systems)\\n\"\n                        << \"and 'man 5 sysctl.conf' (non-systemd systems) for more details.\";\n        }\n        RR_FALLTHROUGH;\n      }\n      case EPERM:\n        CLEAN_FATAL() << \"Permission denied to use 'perf_event_open'; are hardware perf events \"\n                   \"available? See https://github.com/rr-debugger/rr/wiki/Will-rr-work-on-my-system\";\n        break;\n      case ENOENT:\n        CLEAN_FATAL() << \"Unable to open performance counter with 'perf_event_open'; \"\n                   \"are hardware perf events available? See https://github.com/rr-debugger/rr/wiki/Will-rr-work-on-my-system\";\n        break;\n      case ESRCH:\n        if (tid > 0) {\n          break;\n        }\n        RR_FALLTHROUGH;\n      default:\n        FATAL() << \"Failed to initialize counter\";\n        break;\n    }\n  }\n  return ScopedFd(fd);\n}\n\n// Returns the ticks minimum period.\nstatic uint32_t check_for_ioc_period_bug(perf_event_attrs &perf_attr) {\n  // Start a cycles counter\n  struct perf_event_attr attr = perf_attr.ticks;\n  attr.sample_period = 0xffffffff;\n  attr.exclude_kernel = 1;\n  ScopedFd bug_fd = start_counter(0, -1, &attr);\n\n  uint64_t period = 1;\n  if (ioctl(bug_fd, PERF_EVENT_IOC_PERIOD, &period)) {\n    // On some hardware the kernel imposes a minimum period of 32 to work\n    // around errata, e.g.\n    // https://github.com/torvalds/linux/blob/11066801dd4b7c4d75fce65c812723a80c1481ae/arch/x86/events/intel/core.c#L4610\n    period = 32;\n    if (ioctl(bug_fd, PERF_EVENT_IOC_PERIOD, &period)) {\n      FATAL() << \"ioctl(PERF_EVENT_IOC_PERIOD) failed\";\n    }\n  }\n\n  struct pollfd poll_bug_fd = {.fd = bug_fd, .events = POLL_IN, .revents = 0 };\n  poll(&poll_bug_fd, 1, 0);\n\n  perf_attr.has_ioc_period_bug = poll_bug_fd.revents == 0;\n  LOG(debug) << \"has_ioc_period_bug=\" << perf_attr.has_ioc_period_bug\n    << \" min_period=\" << period;\n  return period;\n}\n\nstatic const int NUM_BRANCHES = 500;\n\nvolatile uint32_t accumulator_sink = 0;\n\nstatic void do_branches() {\n  // Do NUM_BRANCHES conditional branches that can't be optimized out.\n  // 'accumulator' is always odd and can't be zero\n  uint32_t accumulator = uint32_t(rand()) * 2 + 1;\n  for (int i = 0; i < NUM_BRANCHES && accumulator; ++i) {\n    accumulator = ((accumulator * 7) + 2) & 0xffffff;\n  }\n  // Use 'accumulator' so it can't be  optimized out.\n  accumulator_sink = accumulator;\n}\n\nstruct CPUInfo {\n  // The microarch of the CPU core.\n  CpuMicroarch microarch;\n  // Either PERF_TYPE_RAW or some alternative type that should be used\n  // instead of PERF_TYPE_RAW for raw events on this core.\n  int raw_perf_event_type;\n};\n\n// Architecture specific detection code\n#if defined(__i386__) || defined(__x86_64__)\n#include \"PerfCounters_x86.h\"\n#elif defined(__aarch64__)\n#include \"PerfCounters_aarch64.h\"\n#else\n#error Must define microarchitecture detection code for this architecture\n#endif\n\nstatic void check_working_counters(perf_event_attrs &perf_attr, int pmu_index) {\n  struct perf_event_attr attr = perf_attr.ticks;\n  attr.sample_period = 0;\n  struct perf_event_attr attr2 = perf_attr.cycles;\n  attr2.sample_period = 0;\n  ScopedFd fd = start_counter(0, -1, &attr);\n  ScopedFd fd2 = start_counter(0, -1, &attr2);\n  do_branches();\n  int64_t events = read_counter(fd);\n  int64_t events2 = read_counter(fd2);\n\n  if (events < NUM_BRANCHES) {\n    char config[100];\n    sprintf(config, \"%llx\", (long long)perf_attr.ticks.config);\n    std::string perf_cmdline = \"perf stat -e \";\n    if (perf_attr.pmu_name) {\n      perf_cmdline = perf_cmdline + perf_attr.pmu_name + \"/r\" + config + \"/ true\";\n    }\n    else {\n      perf_cmdline = perf_cmdline + \"r\" + config + \" true\";\n    }\n    FATAL()\n        << \"\\nGot \" << events << \" branch events, expected at least \"\n        << NUM_BRANCHES\n        << \".\\n\"\n           \"\\nThe hardware performance counter seems to not be working on cpu \"\n        << pmu_index << \"\\n\"\n           \"Check that hardware performance counters are working by running\\n\"\n           \"  \"\n        << perf_cmdline\n        << \"\\n\"\n           \"and checking that it reports a nonzero number of events.\\n\"\n           \"If performance counters seem to be working with 'perf', file an\\n\"\n           \"rr issue, otherwise check your hardware/OS/VM configuration. Also\\n\"\n           \"check that other software is not using performance counters on\\n\"\n           \"this CPU.\";\n  }\n\n  perf_attr.only_one_counter = events2 == 0;\n  LOG(debug) << \"only_one_counter=\" << perf_attr.only_one_counter;\n\n  if (perf_attr.only_one_counter) {\n    arch_check_restricted_counter();\n  }\n}\n\n// Returns the ticks minimum period.\n// Must be run on the CPU that we're checking for bugs.\nstatic uint32_t check_for_bugs(perf_event_attrs &perf_attr, int pmu_index) {\n  DEBUG_ASSERT(!running_under_rr());\n  cpu_improperly_configured = false;\n\n  uint32_t min_period = check_for_ioc_period_bug(perf_attr);\n  check_working_counters(perf_attr, pmu_index);\n  check_for_arch_bugs(perf_attr);\n  return min_period;\n}\n\nstatic vector<CPUInfo> get_cpus_info() {\n  string forced_uarch = lowercase(Flags::get().forced_uarch);\n  if (!forced_uarch.empty()) {\n    for (size_t i = 0; i < array_length(pmu_configs); ++i) {\n      const PmuConfig& pmu = pmu_configs[i];\n      string name = lowercase(pmu.name);\n      if (name.npos != name.find(forced_uarch)) {\n        LOG(info) << \"Using forced uarch \" << pmu.name;\n        return {\n          { pmu.uarch, PERF_TYPE_RAW }\n        };\n      }\n    }\n    CLEAN_FATAL() << \"Forced uarch \" << Flags::get().forced_uarch\n                  << \" isn't known.\";\n  }\n  return compute_cpus_info();\n}\n\n// Similar to rr::perf_attrs, if this contains more than one element,\n// it's indexed by the CPU index.\nstatic std::vector<PmuConfig> get_pmu_microarchs() {\n  std::vector<PmuConfig> pmu_uarchs;\n  auto cpus_info = get_cpus_info();\n  bool found_working_pmu = false;\n  for (const auto& info : cpus_info) {\n    bool found = false;\n    for (const auto& pmu_config : pmu_configs) {\n      if (info.microarch == pmu_config.uarch) {\n        found = true;\n        if (pmu_config.flags & (PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES)) {\n          found_working_pmu |= true;\n        }\n        pmu_uarchs.push_back(pmu_config);\n        pmu_uarchs.back().event_type = info.raw_perf_event_type;\n        break;\n      }\n    }\n    if (!found) {\n      FATAL() << \"Can't find PMU config for \" << info.microarch;\n    }\n    LOG(info) << \"Found PMU config for \" << info.microarch;\n  }\n  if (!found_working_pmu) {\n    CLEAN_FATAL() << \"No supported microarchitectures found.\";\n  }\n  DEBUG_ASSERT(!pmu_uarchs.empty());\n  // Note that the `uarch` field after processed by `post_init_pmu_uarchs`\n  // is used to store the bug_flags and may not be the actual uarch.\n  post_init_pmu_uarchs(pmu_uarchs);\n  return pmu_uarchs;\n}\n\nstatic void init_attributes() {\n  if (attributes_initialized) {\n    return;\n  }\n  attributes_initialized = true;\n\n  auto pmu_uarchs = get_pmu_microarchs();\n  pmu_semantics_flags = PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES;\n  for (auto &pmu_uarch : pmu_uarchs) {\n    if (!(pmu_uarch.flags & (PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES))) {\n      continue;\n    }\n    pmu_semantics_flags = pmu_semantics_flags & pmu_uarch.flags;\n  }\n  if (!(pmu_semantics_flags & (PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES))) {\n    if (pmu_uarchs.size() == 1) {\n      FATAL() << \"Microarchitecture `\" << pmu_uarchs[0].name\n              << \"' currently unsupported.\";\n    } else {\n      std::string uarch_list;\n      for (auto &pmu_uarch : pmu_uarchs) {\n        uarch_list += \"\\n  \";\n        uarch_list += pmu_uarch.name;\n      }\n      FATAL() << \"Microarchitecture combination currently unsupported:\"\n              << uarch_list;\n    }\n  }\n\n  if (running_under_rr()) {\n    perf_attrs.resize(1);\n    init_perf_event_attr(&perf_attrs[0].ticks, PERF_TYPE_HARDWARE, PERF_COUNT_RR);\n    perf_attrs[0].skid_size = RR_SKID_MAX;\n    perf_attrs[0].pmu_flags = pmu_semantics_flags;\n  } else {\n    auto npmus = pmu_uarchs.size();\n    perf_attrs.resize(npmus);\n    for (size_t i = 0; i < npmus; i++) {\n      auto &perf_attr = perf_attrs[i];\n      auto &pmu_uarch = pmu_uarchs[i];\n      if (!(pmu_uarch.flags & (PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES))) {\n        perf_attr.pmu_flags = 0; // Mark as unsupported\n        continue;\n      }\n      perf_attr.pmu_name = pmu_uarch.pmu_name;\n      perf_attr.skid_size = pmu_uarch.skid_size;\n      perf_attr.pmu_flags = pmu_uarch.flags;\n      perf_attr.bug_flags = (int)pmu_uarch.uarch;\n      init_perf_event_attr(&perf_attr.ticks, pmu_uarch.event_type,\n                           pmu_uarch.rcb_cntr_event);\n      if (pmu_uarch.minus_ticks_cntr_event != 0) {\n        init_perf_event_attr(&perf_attr.minus_ticks, pmu_uarch.event_type,\n                             pmu_uarch.minus_ticks_cntr_event);\n      }\n      init_perf_event_attr(&perf_attr.cycles, pmu_uarch.cycle_type,\n                           pmu_uarch.cycle_event);\n      init_perf_event_attr(&perf_attr.llsc_fail, pmu_uarch.event_type,\n                           pmu_uarch.llsc_cntr_event);\n    }\n  }\n}\n\nbool PerfCounters::support_cpu(int cpu) {\n  // We could probably make cpu=-1 mean whether all CPUs are supported\n  // if there's a need for it...\n  DEBUG_ASSERT(cpu >= 0);\n  init_attributes();\n\n  auto nattrs = (int)perf_attrs.size();\n  if (nattrs == 1) {\n    cpu = 0;\n  }\n  if (cpu >= nattrs) {\n    return false;\n  }\n  auto &perf_attr = perf_attrs[cpu];\n  return perf_attr.pmu_flags & (PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES);\n}\n\nstatic void check_pmu(int pmu_index) {\n  auto &perf_attr = perf_attrs[pmu_index];\n  if (perf_attr.checked) {\n    return;\n  }\n  perf_attr.checked = true;\n\n  // Under rr we emulate idealized performance counters, so we can assume\n  // none of the bugs apply.\n  if (running_under_rr()) {\n    return;\n  }\n\n  if (perf_attrs.size() > 1 && !CPUs::set_affinity_to_cpu(pmu_index)) {\n    FATAL() << \"Couldn't set affinity to the right PMU\";\n  }\n  perf_attr.ticks_min_period = check_for_bugs(perf_attr, pmu_index);\n  if (perf_attrs.size() > 1) {\n    CPUs::get().restore_initial_affinity();\n  }\n\n  /*\n   * For maintainability, and since it doesn't impact performance when not\n   * needed, we always activate this. If it ever turns out to be a problem,\n   * this can be set to pmu->flags & PMU_BENEFITS_FROM_USELESS_COUNTER,\n   * instead.\n   *\n   * We also disable this counter when running under rr. Even though it's the\n   * same event for the same task as the outer rr, the linux kernel does not\n   * coalesce them and tries to schedule the new one on a general purpose PMC.\n   * On CPUs with only 2 general PMCs (e.g. KNL), we'd run out.\n   */\n  perf_attr.activate_useless_counter = perf_attr.has_ioc_period_bug;\n}\n\nbool PerfCounters::is_rr_ticks_attr(const perf_event_attr& attr) {\n  return attr.type == PERF_TYPE_HARDWARE && attr.config == PERF_COUNT_RR;\n}\n\nbool PerfCounters::supports_ticks_semantics(TicksSemantics ticks_semantics) {\n  init_attributes();\n  switch (ticks_semantics) {\n  case TICKS_RETIRED_CONDITIONAL_BRANCHES:\n    return (pmu_semantics_flags & PMU_TICKS_RCB) != 0;\n  case TICKS_TAKEN_BRANCHES:\n    return (pmu_semantics_flags & PMU_TICKS_TAKEN_BRANCHES) != 0;\n  default:\n    FATAL() << \"Unknown ticks_semantics \" << ticks_semantics;\n    return false;\n  }\n}\n\nTicksSemantics PerfCounters::default_ticks_semantics() {\n  init_attributes();\n  if (pmu_semantics_flags & PMU_TICKS_TAKEN_BRANCHES) {\n    return TICKS_TAKEN_BRANCHES;\n  }\n  if (pmu_semantics_flags & PMU_TICKS_RCB) {\n    return TICKS_RETIRED_CONDITIONAL_BRANCHES;\n  }\n  FATAL() << \"Unsupported architecture\";\n  return TICKS_TAKEN_BRANCHES;\n}\n\nuint32_t PerfCounters::skid_size() {\n  DEBUG_ASSERT(attributes_initialized);\n  DEBUG_ASSERT(perf_attrs[pmu_index].checked);\n  // If we want to stop after one event, and our minimum period is Y,\n  // and the skid size is X, then we'll actually use a period of Y\n  // and potentially skid to Y + X, so report Y + X as the skid size.\n  return perf_attrs[pmu_index].skid_size +\n      perf_attrs[pmu_index].ticks_min_period;\n}\n\nPerfCounters::PerfCounters(pid_t tid, BindCPU cpu_binding,\n                           TicksSemantics ticks_semantics, Enabled enabled,\n                           IntelPTEnabled enable_pt)\n    : tid(tid), pmu_index(0), ticks_semantics_(ticks_semantics),\n      enabled(enabled), opened(false), counting(false) {\n  if (enabled == Enabled::DISABLE) {\n    return;\n  }\n  pmu_index = get_pmu_index(cpu_binding);\n  if (!supports_ticks_semantics(ticks_semantics)) {\n    FATAL() << \"Ticks semantics \" << ticks_semantics << \" not supported\";\n  }\n  if (enable_pt == PT_ENABLE) {\n    pt_state = make_unique<PTState>();\n  }\n}\n\nstatic void make_counter_async(ScopedFd& fd, int signal) {\n  if (fcntl(fd, F_SETFL, O_ASYNC) || fcntl(fd, F_SETSIG, signal)) {\n    FATAL() << \"Failed to make ticks counter ASYNC with sig\"\n            << signal_name(signal);\n  }\n}\n\nstatic void infallible_perf_event_reset_if_open(ScopedFd& fd) {\n  if (fd.is_open()) {\n    if (ioctl(fd, PERF_EVENT_IOC_RESET, 0)) {\n      FATAL() << \"ioctl(PERF_EVENT_IOC_RESET) failed\";\n    }\n  }\n}\n\nstatic void infallible_perf_event_enable_if_open(ScopedFd& fd) {\n  if (fd.is_open()) {\n    if (ioctl(fd, PERF_EVENT_IOC_ENABLE, 0)) {\n      FATAL() << \"ioctl(PERF_EVENT_IOC_ENABLE) failed\";\n    }\n  }\n}\n\nstatic void infallible_perf_event_disable_if_open(ScopedFd& fd) {\n  if (fd.is_open()) {\n    if (ioctl(fd, PERF_EVENT_IOC_DISABLE, 0)) {\n      FATAL() << \"ioctl(PERF_EVENT_IOC_ENABLE) failed\";\n    }\n  }\n}\n\nstatic uint32_t pt_event_type() {\n  static const char file_name[] = \"/sys/bus/event_source/devices/intel_pt/type\";\n  ScopedFd fd(file_name, O_RDONLY);\n  if (!fd.is_open()) {\n    FATAL() << \"Can't open \" << file_name << \", PT events not available\";\n  }\n  char buf[6];\n  ssize_t ret = read(fd, buf, sizeof(buf));\n  if (ret < 1 || ret > 5) {\n    FATAL() << \"Invalid value in \" << file_name;\n  }\n  char* end_ptr;\n  unsigned long value = strtoul(buf, &end_ptr, 10);\n  if (end_ptr < buf + ret && *end_ptr && *end_ptr != '\\n') {\n    FATAL() << \"Invalid value in \" << file_name;\n  }\n  return value;\n}\n\nstatic const size_t PT_PERF_DATA_SIZE = 8*1024*1024;\nstatic const size_t PT_PERF_AUX_SIZE = 128*1024*1024;\n\nstruct PTCopyThreadState {\n  pthread_mutex_t mutex;\n  unordered_set<PerfCounters::PTState*> counting_pt_states;\n\n  PTCopyThreadState() {\n    pthread_mutex_init(&mutex, nullptr);\n    pthread_t thread;\n    pthread_create(&thread, nullptr, do_thread, this);\n    pthread_setname_np(thread, \"pt_copy\");\n  }\n  void start_copying(PerfCounters::PTState* state) {\n    pthread_mutex_lock(&mutex);\n    counting_pt_states.insert(state);\n    pthread_mutex_unlock(&mutex);\n  }\n  void stop_copying(PerfCounters::PTState* state) {\n    pthread_mutex_lock(&mutex);\n    counting_pt_states.erase(state);\n    pthread_mutex_unlock(&mutex);\n  }\n\nprivate:\n  static void* do_thread(void* p) {\n    static_cast<PTCopyThreadState*>(p)->thread_run();\n    return nullptr;\n  }\n  void thread_run() {\n    while (true) {\n      pthread_mutex_lock(&mutex);\n      while (true) {\n        bool did_work = false;\n        for (PerfCounters::PTState* state : counting_pt_states) {\n          size_t bytes = state->flush();\n          if (bytes > 0) {\n            did_work = true;\n          }\n        }\n        if (!did_work) {\n          break;\n        }\n      }\n      pthread_mutex_unlock(&mutex);\n\n      struct timespec ts = { 0, 250000 };\n      nanosleep(&ts, nullptr);\n    }\n  }\n};\n\nstatic PTCopyThreadState* pt_thread_state;\n\nvoid PerfCounters::start_pt_copy_thread() {\n  if (!pt_thread_state) {\n    pt_thread_state = new PTCopyThreadState();\n  }\n}\n\nbool PerfCounters::improperly_configured() {\n  return cpu_improperly_configured;\n}\n\n// See https://github.com/intel/libipt/blob/master/doc/howto_capture.md\nvoid PerfCounters::PTState::open(pid_t tid) {\n  static uint32_t event_type = pt_event_type();\n\n  struct perf_event_attr attr;\n  init_perf_event_attr(&attr, event_type, 0);\n  attr.aux_watermark = 8 * 1024 * 1024;\n  pt_perf_event_fd = start_counter(tid, -1, &attr);\n  if (!pt_perf_event_fd.is_open()) {\n    return;\n  }\n\n  perf_buffers.allocate(pt_perf_event_fd, PT_PERF_DATA_SIZE, PT_PERF_AUX_SIZE);\n}\n\nsize_t PerfCounters::PTState::flush() {\n  if (!perf_buffers.allocated()) {\n    return 0;\n  }\n\n  size_t ret = 0;\n\n  while (auto packet = perf_buffers.next_packet()) {\n    struct perf_event_header header = *packet->data();\n    switch (header.type) {\n      case PERF_RECORD_LOST:\n        FATAL() << \"PT records lost!\";\n        break;\n      case PERF_RECORD_ITRACE_START:\n        break;\n      case PERF_RECORD_AUX: {\n        auto aux_packet = *reinterpret_cast<PerfEventAux*>(packet->data());\n        if (aux_packet.flags) {\n          if (aux_packet.flags & PERF_AUX_FLAG_TRUNCATED) {\n            CLEAN_FATAL() << \"PT aux data truncated. Try increasing \"\n              \"PT_PERF_AUX_SIZE in src/PerfCounters.cc and rerecording.\";\n          }\n          FATAL() << \"Unexpected AUX packet flags \" << aux_packet.flags;\n        }\n        pt_data.data.emplace_back();\n        vector<uint8_t>& data = pt_data.data.back();\n        data.resize(aux_packet.aux_size);\n        memcpy(data.data(), packet->aux_data(), aux_packet.aux_size);\n        ret += aux_packet.aux_size;\n        break;\n      }\n      default:\n        FATAL() << \"Unknown record \" << header.type;\n        break;\n    }\n  }\n\n  return ret;\n}\n\nPTData PerfCounters::extract_intel_pt_data() {\n  PTData result;\n  if (pt_state) {\n    result = std::move(pt_state->pt_data);\n  }\n  return result;\n}\n\nvoid PerfCounters::PTState::close() {\n  pt_perf_event_fd.close();\n  perf_buffers.destroy();\n}\n\nvoid PerfCounters::start(Task* t, Ticks ticks_period) {\n  ASSERT(t, !counting);\n  ASSERT(t, ticks_period >= 0);\n\n  if (enabled == DISABLE) {\n    return;\n  }\n\n  check_pmu(pmu_index);\n\n  auto &perf_attr = perf_attrs[pmu_index];\n  if (ticks_period == 0) {\n    // We can't switch a counter between sampling and non-sampling via\n    // PERF_EVENT_IOC_PERIOD so just turn 0 into a very big number.\n    ticks_period = uint64_t(1) << 60;\n  }\n  ticks_period = max<Ticks>(ticks_period, perf_attr.ticks_min_period);\n\n  if (!opened) {\n    LOG(debug) << \"Recreating counters with period \" << ticks_period;\n\n    struct perf_event_attr attr = perf_attr.ticks;\n    struct perf_event_attr minus_attr = perf_attr.minus_ticks;\n    attr.sample_period = ticks_period;\n    fd_ticks_interrupt = start_counter(tid, -1, &attr);\n    if (minus_attr.config != 0) {\n      fd_minus_ticks_measure = start_counter(tid, fd_ticks_interrupt, &minus_attr);\n    }\n\n    if (!perf_attr.only_one_counter && !running_under_rr()) {\n      reset_arch_extras<NativeArch>(pmu_index);\n    }\n\n    if (perf_attr.activate_useless_counter && !fd_useless_counter.is_open()) {\n      // N.B.: This is deliberately not in the same group as the other counters\n      // since we want to keep it scheduled at all times.\n      fd_useless_counter = start_counter(tid, -1, &perf_attr.cycles);\n    }\n\n    if (fd_ticks_interrupt.is_open()) {\n      struct f_owner_ex own;\n      own.type = F_OWNER_TID;\n      own.pid = tid;\n      if (fcntl(fd_ticks_interrupt, F_SETOWN_EX, &own)) {\n        FATAL() << \"Failed to SETOWN_EX ticks event fd\";\n      }\n      make_counter_async(fd_ticks_interrupt, PerfCounters::TIME_SLICE_SIGNAL);\n    }\n\n    if (pt_state) {\n      pt_state->open(tid);\n      pt_thread_state->start_copying(pt_state.get());\n    }\n  } else {\n    LOG(debug) << \"Resetting counters with period \" << ticks_period;\n\n    infallible_perf_event_reset_if_open(fd_ticks_interrupt);\n    if (ioctl(fd_ticks_interrupt, PERF_EVENT_IOC_PERIOD, &ticks_period)) {\n      FATAL() << \"ioctl(PERF_EVENT_IOC_PERIOD) failed with period \"\n              << ticks_period;\n    }\n    infallible_perf_event_enable_if_open(fd_ticks_interrupt);\n\n    infallible_perf_event_reset_if_open(fd_minus_ticks_measure);\n    infallible_perf_event_enable_if_open(fd_minus_ticks_measure);\n\n    infallible_perf_event_reset_if_open(fd_ticks_measure);\n    infallible_perf_event_enable_if_open(fd_ticks_measure);\n\n    infallible_perf_event_reset_if_open(fd_ticks_in_transaction);\n    infallible_perf_event_enable_if_open(fd_ticks_in_transaction);\n\n    if (pt_state) {\n      infallible_perf_event_enable_if_open(pt_state->pt_perf_event_fd);\n      pt_thread_state->start_copying(pt_state.get());\n    }\n  }\n\n  opened = true;\n  counting = true;\n  counting_period = ticks_period;\n}\n\nvoid PerfCounters::set_tid(pid_t tid) {\n  close();\n  this->tid = tid;\n}\n\nvoid PerfCounters::close() {\n  if (counting) {\n    FATAL() << \"Can't close while counting task \" << tid;\n  }\n\n  if (!opened) {\n    return;\n  }\n  opened = false;\n  if (pt_state) {\n    pt_state->close();\n  }\n\n  fd_ticks_interrupt.close();\n  fd_ticks_measure.close();\n  fd_minus_ticks_measure.close();\n  fd_useless_counter.close();\n  fd_ticks_in_transaction.close();\n  fd_async_signal_accelerator.close();\n}\n\nTicks PerfCounters::stop(Task* t, Error* error) {\n  if (!counting) {\n    if (error) {\n      *error = Error::None;\n    }\n    return 0;\n  }\n\n  Ticks ticks = read_ticks(t, error);\n  counting = false;\n  if (pt_state) {\n    pt_thread_state->stop_copying(pt_state.get());\n    pt_state->flush();\n  }\n  if (always_recreate_counters(perf_attrs[pmu_index])) {\n    close();\n  } else {\n    infallible_perf_event_disable_if_open(fd_ticks_interrupt);\n    infallible_perf_event_disable_if_open(fd_minus_ticks_measure);\n    infallible_perf_event_disable_if_open(fd_ticks_measure);\n    infallible_perf_event_disable_if_open(fd_ticks_in_transaction);\n    if (pt_state) {\n      infallible_perf_event_disable_if_open(pt_state->pt_perf_event_fd);\n    }\n    infallible_perf_event_disable_if_open(fd_async_signal_accelerator);\n  }\n  return ticks;\n}\n\n// Note that on aarch64 this is also used to get the count for `ret`\nTicks PerfCounters::ticks_for_unconditional_indirect_branch(Task*) {\n  DEBUG_ASSERT(attributes_initialized);\n  return (pmu_semantics_flags & PMU_TICKS_TAKEN_BRANCHES) ? 1 : 0;\n}\n\nTicks PerfCounters::ticks_for_unconditional_direct_branch(Task*) {\n  DEBUG_ASSERT(attributes_initialized);\n  return (pmu_semantics_flags & PMU_TICKS_TAKEN_BRANCHES) ? 1 : 0;\n}\n\nTicks PerfCounters::ticks_for_direct_call(Task*) {\n  DEBUG_ASSERT(attributes_initialized);\n  return (pmu_semantics_flags & PMU_TICKS_TAKEN_BRANCHES) ? 1 : 0;\n}\n\nTicks PerfCounters::read_ticks(Task* t, Error* error) {\n  if (error) {\n    *error = Error::None;\n  }\n\n  ASSERT(t, opened);\n  ASSERT(t, counting);\n  ASSERT(t, counting_period > 0);\n\n  if (fd_ticks_in_transaction.is_open()) {\n    uint64_t transaction_ticks = read_counter(fd_ticks_in_transaction);\n    if (transaction_ticks > 0) {\n      LOG(debug) << transaction_ticks << \" IN_TX ticks detected\";\n      if (!Flags::get().force_things) {\n        ASSERT(t, false)\n            << transaction_ticks\n            << \" IN_TX ticks detected while HLE not supported due to KVM PMU\\n\"\n               \"virtualization bug. See \"\n               \"http://marc.info/?l=linux-kernel&m=148582794808419&w=2\\n\"\n               \"Aborting. Retry with -F to override, but it will probably\\n\"\n               \"fail.\";\n      }\n    }\n  }\n\n  if (fd_strex_counter.is_open()) {\n    uint64_t strex_count = read_counter(fd_strex_counter);\n    if (strex_count > 0) {\n      LOG(debug) << strex_count << \" strex detected\";\n      if (!Flags::get().force_things) {\n        ASSERT(t, false)\n            << strex_count\n            << \" (speculatively) executed strex instructions detected. \\n\"\n               \"On aarch64, rr only supports applications making use of LSE\\n\"\n               \"atomics rather than legacy LL/SC-based atomics.\\n\"\n               \"Aborting. Retry with -F to override, but replaying such\\n\"\n               \"a recording will probably fail.\";\n      }\n    }\n  }\n\n  uint64_t adjusted_counting_period =\n      counting_period +\n      (t->session().is_recording() ? recording_skid_size() : skid_size());\n  uint64_t interrupt_val = 0;\n  if (fd_ticks_interrupt.is_open()) {\n    interrupt_val = read_counter(fd_ticks_interrupt);\n  }\n  uint64_t ret;\n  if (!fd_ticks_measure.is_open()) {\n    if (fd_minus_ticks_measure.is_open()) {\n      uint64_t minus_measure_val = read_counter(fd_minus_ticks_measure);\n      interrupt_val -= minus_measure_val;\n    }\n    if (t->session().is_recording()) {\n      if (interrupt_val > adjusted_counting_period) {\n        LOG(warn) << \"Recorded ticks of \" << interrupt_val\n          << \" overshot requested ticks target by \" << interrupt_val - counting_period\n          << \" ticks.\\n\"\n           \"On AMD systems this is known to occur occasionally for unknown reasons.\\n\"\n           \"Recording should continue normally. Please report any unexpected rr failures\\n\"\n           \"received after this warning, any conditions that reliably reproduce it,\\n\"\n           \"or sightings of this warning on non-AMD systems.\";\n      }\n    }\n    ret = interrupt_val;\n  } else {\n    uint64_t measure_val = read_counter(fd_ticks_measure);\n    if (measure_val > interrupt_val) {\n      // There is some kind of kernel or hardware bug that means we sometimes\n      // see more events with IN_TXCP set than without. These are clearly\n      // spurious events :-(. For now, work around it by returning the\n      // interrupt_val. That will work if HLE hasn't been used in this interval.\n      // Note that interrupt_val > measure_val is valid behavior (when HLE is\n      // being used).\n      LOG(debug) << \"Measured too many ticks; measure=\" << measure_val\n                 << \", interrupt=\" << interrupt_val;\n      ret = interrupt_val;\n    } else {\n      ret = measure_val;\n    }\n  }\n  if (!t->session().is_recording() && ret > adjusted_counting_period) {\n    if (error && (perf_attrs[pmu_index].pmu_flags & PMU_SKID_UNBOUNDED)) {\n      *error = Error::Transient;\n    } else {\n      ASSERT(t, false) << \"Detected \" << ret\n          << \" ticks, expected no more than \" << adjusted_counting_period;\n    }\n  }\n  return ret;\n}\n\n#ifdef BPF\nclass BpfAccelerator {\npublic:\n  static std::shared_ptr<BpfAccelerator> get_or_create();\n\n  ScopedFd create_counter(pid_t tid);\n  void match_regs_and_open_counter(const Registers& regs, ScopedFd& counter);\n  uint64_t skips() const {\n    return *bpf_skips;\n  }\n\n  // Can't be private because of make_shared.\n  BpfAccelerator(struct bpf_object* bpf_obj, int bpf_prog_fd,\n                 user_regs_struct* bpf_regs, uint64_t* bpf_skips)\n    : bpf_obj(bpf_obj), bpf_prog_fd(bpf_prog_fd), bpf_regs(bpf_regs), bpf_skips(bpf_skips)\n  {}\n\n  ~BpfAccelerator() {\n    munmap(bpf_skips, 4096);\n    munmap(bpf_regs, 4096);\n    bpf_object__close(bpf_obj);\n  }\n\nprivate:\n  static std::shared_ptr<BpfAccelerator> singleton;\n\n  struct perf_event_attr attr;\n  struct bpf_object* bpf_obj;\n  // Not a ScopedFd because the bpf_object maintains ownership.\n  int bpf_prog_fd;\n  user_regs_struct* bpf_regs;\n  uint64_t* bpf_skips;\n};\n\nstd::shared_ptr<BpfAccelerator> BpfAccelerator::singleton;\n\n/* static */ std::shared_ptr<BpfAccelerator> BpfAccelerator::get_or_create() {\n  static int initialized;\n  if (BpfAccelerator::singleton) {\n    return BpfAccelerator::singleton;\n  }\n\n  if (!initialized) {\n    initialized = -1;\n\n    libbpf_set_strict_mode(LIBBPF_STRICT_DIRECT_ERRS);\n    string path = resource_path() + \"share/rr/async_event_filter.o\";\n    struct bpf_object* obj = bpf_object__open(path.c_str());\n    if ((intptr_t)obj <= 0) {\n      LOG(error) << \"Failed to find bpf at \" << path;\n      return nullptr;\n    }\n    if (bpf_object__load(obj) < 0) {\n      LOG(error) << \"Failed to load bpf at \" << path << \" into the kernel. Do we have permissions?\";\n      bpf_object__close(obj);\n      return nullptr;\n    }\n    int bpf_map_fd = bpf_object__find_map_fd_by_name(obj, \"registers\");\n    if (bpf_map_fd < 0) {\n      CLEAN_FATAL() << \"rr's bpf at \" << path << \" is corrupt\";\n      return nullptr;\n    }\n    struct bpf_program* prog = bpf_object__next_program(obj, nullptr);\n    if (!prog) {\n      CLEAN_FATAL() << \"rr's bpf at \" << path << \" is corrupt\";\n      return nullptr;\n    }\n    int bpf_prog_fd = bpf_program__fd(prog);\n    if (bpf_prog_fd < 0) {\n      CLEAN_FATAL() << \"rr's bpf at \" << path << \" is corrupt\";\n      return nullptr;\n    }\n\n    auto bpf_regs = (struct user_regs_struct*)\n      mmap(NULL, 4096, PROT_READ | PROT_WRITE,\n           MAP_SHARED, bpf_map_fd, 0);\n    if (bpf_regs == MAP_FAILED) {\n      CLEAN_FATAL() << \"Failed to mmap bpf maps\";\n      return nullptr;\n    }\n\n    bpf_map_fd = bpf_object__find_map_fd_by_name(obj, \"skips\");\n    if (bpf_map_fd < 0) {\n      CLEAN_FATAL() << \"rr's bpf at \" << path << \" is corrupt\";\n      return nullptr;\n    }\n\n    auto bpf_skips = (uint64_t*)\n      mmap(NULL, 4096, PROT_READ | PROT_WRITE,\n           MAP_SHARED, bpf_map_fd, 0);\n    if (bpf_regs == MAP_FAILED) {\n      CLEAN_FATAL() << \"Failed to mmap bpf maps\";\n      return nullptr;\n    }\n\n    BpfAccelerator::singleton =\n      std::make_shared<BpfAccelerator>(obj, bpf_prog_fd, bpf_regs, bpf_skips);\n    memset(&singleton->attr, 0, sizeof(singleton->attr));\n    singleton->attr.type = PERF_TYPE_BREAKPOINT;\n    singleton->attr.size = sizeof(attr);\n    singleton->attr.bp_type = HW_BREAKPOINT_X;\n    singleton->attr.bp_len = sizeof(long);\n    singleton->attr.sample_period = 1;\n    singleton->attr.sample_type = PERF_SAMPLE_IP;\n    singleton->attr.pinned = 1;\n    singleton->attr.exclude_kernel = 1;\n    singleton->attr.exclude_hv = 1;\n    singleton->attr.wakeup_events = 1;\n    singleton->attr.precise_ip = 3;\n    singleton->attr.disabled = 1;\n    initialized = 1;\n  }\n\n  return BpfAccelerator::singleton;\n}\n\nScopedFd BpfAccelerator::create_counter(pid_t tid) {\n  attr.bp_addr = 0;\n  ScopedFd fd = start_counter(tid, -1, &attr);\n\n  struct f_owner_ex own;\n  own.type = F_OWNER_TID;\n  own.pid = tid;\n  if (fcntl(fd, F_SETOWN_EX, &own)) {\n    FATAL() << \"Failed to SETOWN_EX bpf-accelerated breakpoint fd\";\n  }\n\n  make_counter_async(fd, SIGTRAP);\n\n  if (ioctl(fd, PERF_EVENT_IOC_SET_BPF, bpf_prog_fd)) {\n    FATAL() << \"Failed PERF_EVENT_IOC_SET_BPF\";\n  }\n\n  return fd;\n}\n\nvoid BpfAccelerator::match_regs_and_open_counter(const Registers& regs, ScopedFd& fd) {\n  attr.bp_addr = regs.ip().register_value();\n  if (ioctl(fd, PERF_EVENT_IOC_MODIFY_ATTRIBUTES, &attr)) {\n    FATAL() << \"Failed PERF_EVENT_IOC_MODIFY_ATTRIBUTES\";\n  }\n\n  auto r = regs.get_ptrace();\n  memcpy(bpf_regs, &r, sizeof(struct user_regs_struct));\n  *bpf_skips = 0;\n\n  infallible_perf_event_enable_if_open(fd);\n}\n\nbool PerfCounters::accelerate_async_signal(const Registers& regs) {\n  if (!fd_async_signal_accelerator.is_open()) {\n    if (!bpf) {\n      bpf = BpfAccelerator::get_or_create();\n    }\n\n    if (!bpf) {\n      return false;\n    }\n\n    fd_async_signal_accelerator = bpf->create_counter(tid);\n  }\n\n  if (!fd_async_signal_accelerator.is_open()) {\n    return false;\n  }\n\n  bpf->match_regs_and_open_counter(regs, fd_async_signal_accelerator);\n  return true;\n}\n\nuint64_t PerfCounters::bpf_skips() const {\n  if (!bpf) {\n    return 0;\n  }\n\n  return bpf->skips();\n}\n#endif\n\n} // namespace rr\n"
  },
  {
    "path": "src/PerfCounters.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PERF_COUNTERS_H_\n#define RR_PERF_COUNTERS_H_\n\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n\n#include <signal.h>\n#include <stdint.h>\n#include <linux/perf_event.h>\n#include <sys/types.h>\n\n#include <memory>\n#include <utility>\n#include <vector>\n\n#include \"CPUs.h\"\n#include \"PerfCounterBuffers.h\"\n#include \"ScopedFd.h\"\n#include \"Ticks.h\"\n\nnamespace rr {\n\nclass Registers;\nclass Task;\nclass BpfAccelerator;\n\nenum TicksSemantics {\n  TICKS_RETIRED_CONDITIONAL_BRANCHES,\n  TICKS_TAKEN_BRANCHES,\n};\n\n/**\n * A buffer of Intel PT control-flow data.\n */\nstruct PTData {\n  PTData() {}\n  explicit PTData(std::vector<std::vector<uint8_t>> data)\n    : data(std::move(data)) {}\n  std::vector<std::vector<uint8_t>> data;\n};\n\n/**\n * A class encapsulating the performance counters we use to monitor\n * each task during recording and replay.\n *\n * Normally we monitor a single kind of event that we use as a proxy\n * for progress, which we call \"ticks\". Currently this is the count of retired\n * conditional branches. We support dispatching a signal when the counter\n * reaches a particular value.\n */\nclass PerfCounters {\npublic:\n  /**\n   * Create performance counters monitoring the given task.\n   * When enable is false, we always report 0 and don't do any interrupts.\n   */\n  enum Enabled {\n    ENABLE,\n    DISABLE\n  };\n  enum IntelPTEnabled {\n    PT_DISABLE,\n    PT_ENABLE\n  };\n  // `cpu_binding` must be `UNBOUND` or `SPECIFIED_CORE`.\n  PerfCounters(pid_t tid, BindCPU cpu_binding, TicksSemantics ticks_semantics,\n               Enabled enabled, IntelPTEnabled enable_pt);\n  ~PerfCounters() { close(); }\n\n  struct PTState {\n    PTData pt_data;\n    ScopedFd pt_perf_event_fd;\n    PerfCounterBuffers perf_buffers;\n\n    PTState() {}\n    ~PTState() { close(); }\n\n    void open(pid_t tid);\n    // Returns number of bytes flushed\n    size_t flush();\n    void close();\n  };\n\n  void set_tid(pid_t tid);\n\n  /**\n   * Reset all counter values to 0 and program the counters to send\n   * TIME_SLICE_SIGNAL when 'ticks_period' tick events have elapsed. (In reality\n   * the hardware triggers its interrupt some time after that. We also allow\n   * the interrupt to fire early.)\n   * This must be called while the task is stopped, and it must be called\n   * before the task is allowed to run again if it's going to trigger ticks.\n   * `ticks_period` of zero means don't interrupt at all.\n   * Opens all relevant fds if necessary.\n   */\n  void start(Task* t, Ticks ticks_period);\n\n  enum class Error {\n    // Everything ok\n    None,\n    // A transient error was detected. Retrying might succeed.\n    Transient,\n  };\n\n  /**\n   * Suspend counting until the next start.\n   * Returns the current value of the ticks counter.\n   * `t` is used for debugging purposes.\n   * If `error` is non-null,`*error` will be set to `Error::Transient`\n   * if a transient error is detected, otherwise `Error::None`.\n   * If `error` is null and a transient error is detected, it will be\n   * treated as fatal.\n   */\n  Ticks stop(Task* t, Error* error = nullptr);\n\n  /**\n   * Close the perfcounter fds (if open). They will be automatically reopened if/when\n   * reset is called again. The counters must not be currently running.\n   */\n  void close();\n\n  /**\n   * Return the number of ticks we need for an emulated branch.\n   */\n  static Ticks ticks_for_unconditional_indirect_branch(Task*);\n  /**\n   * Return the number of ticks we need for an emulated direct branch.\n   */\n  static Ticks ticks_for_unconditional_direct_branch(Task*);\n  /**\n   * Return the number of ticks we need for a direct call.\n   */\n  static Ticks ticks_for_direct_call(Task*);\n\n  /**\n   * Whether PMU on core i is supported.\n   */\n  static bool support_cpu(int cpu);\n\n  /**\n   * Returns what ticks mean for these counters.\n   */\n  TicksSemantics ticks_semantics() const { return ticks_semantics_; }\n\n  /**\n   * Return the fd we last used to generate the ticks-counter signal.\n   */\n  int ticks_interrupt_fd() const { return fd_ticks_interrupt.get(); }\n\n  /* This choice is fairly arbitrary; linux doesn't use SIGSTKFLT so we\n   * hope that tracees don't either. */\n  enum { TIME_SLICE_SIGNAL = SIGSTKFLT };\n\n  static bool is_rr_ticks_attr(const perf_event_attr& attr);\n\n  static bool supports_ticks_semantics(TicksSemantics ticks_semantics);\n\n  static TicksSemantics default_ticks_semantics();\n\n  /**\n   * When an interrupt is requested, at most this many ticks may elapse before\n   * the interrupt is delivered.\n   */\n  uint32_t skid_size();\n\n  /**\n   * If Intel PT data collection is on, returns the accumulated raw PT data\n   * and clears the internal buffer.\n   * Otherwise returns an empty buffer.\n   */\n  PTData extract_intel_pt_data();\n\n  /**\n   * Start the PT copy thread. We need to do this early, before CPU binding\n   * has occurred.\n   */\n  static void start_pt_copy_thread();\n\n  /**\n   * Returns true iff we detected issues with performance counter configuration\n   * and wanted to die but the user forced continuation.\n   */\n  static bool improperly_configured();\n\n  /**\n   * Try to use BPF to accelerate async signal processing\n   */\n#ifdef BPF\n  bool accelerate_async_signal(const Registers& regs);\n  uint64_t bpf_skips() const;\n#else\n  bool accelerate_async_signal(const Registers&) {\n    return false;\n  }\n  uint64_t bpf_skips() const {\n    return 0;\n  }\n#endif\n\nprivate:\n  template <typename Arch> void reset_arch_extras(int pmu_index);\n\n  /**\n   * Use a separate skid_size for recording since we seem to see more skid\n   * in practice during recording, in particular during the\n   * async_signal_syscalls tests\n   */\n  uint32_t recording_skid_size() { return skid_size() * 5; }\n\n  /**\n   * If `error` is non-null,`*error` will be set to `Error::Transient`\n   * if a transient error is detected, otherwise `Error::None`.\n   * If `error` is null and a transient error is detected, it will be\n   * treated as fatal.\n   */\n  Ticks read_ticks(Task* t, Error* error);\n\n  // Only valid while 'counting' is true\n  Ticks counting_period;\n  pid_t tid;\n  // Either 0 or the cpu index. Used to index into `perf_attrs`.\n  int pmu_index;\n  // We use separate fds for counting ticks and for generating interrupts. The\n  // former ignores ticks in aborted transactions, and does not support\n  // sample_period; the latter does not ignore ticks in aborted transactions,\n  // but does support sample_period.\n  ScopedFd fd_ticks_measure;\n  ScopedFd fd_minus_ticks_measure;\n  ScopedFd fd_ticks_interrupt;\n  ScopedFd fd_useless_counter;\n\n  // x86(_64) specific counter to support recording HLE\n  ScopedFd fd_ticks_in_transaction;\n\n  // aarch64 specific counter to detect use of ll/sc instructions\n  ScopedFd fd_strex_counter;\n\n  // BPF-enabled hardware breakpoint for fast async signal emulation.\n  ScopedFd fd_async_signal_accelerator;\n\n  std::shared_ptr<BpfAccelerator> bpf;\n\n  std::unique_ptr<PTState> pt_state;\n\n  TicksSemantics ticks_semantics_;\n  Enabled enabled;\n  bool opened;\n  bool counting;\n};\n\n} // namespace rr\n\n#endif /* RR_PERF_COUNTERS_H_ */\n"
  },
  {
    "path": "src/PerfCounters_aarch64.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n// This file is included from PerfCounters.cc\n\nstruct CPUID {\n  uint8_t implementer = 0;\n  uint8_t variant = 0;\n  uint16_t part = 0;\n  operator bool() const\n  {\n    return implementer || variant || part;\n  }\n  // bool operator==(const CPUID&) const = default; // c++20\n  bool operator==(const CPUID &other) const\n  {\n    return implementer == other.implementer &&\n      variant == other.variant && part == other.part;\n  }\n  bool operator!=(const CPUID &other) const\n  {\n    return !(*this == other);\n  }\n};\nstatic std::ostream &operator<<(std::ostream &stm, const CPUID &cpuid)\n{\n  stm << std::hex << \"implementer: 0x\" << int(cpuid.implementer)\n      << \", variant: 0x\" << int(cpuid.variant) << \" part: 0x\" << int(cpuid.part);\n  return stm;\n}\n\n/**\n * Return the detected, known microarchitecture of this CPU, or don't\n * return; i.e. never return UnknownCpu.\n */\nstatic CpuMicroarch compute_cpu_microarch(const CPUID &cpuid) {\n  switch (cpuid.implementer) {\n  case 0x41: // ARM\n    switch (cpuid.part) {\n    case 0xd05:\n      return ARMCortexA55;\n    case 0xd0a:\n      return ARMCortexA75;\n    case 0xd0b:\n      return ARMCortexA76;\n    case 0xd0d:\n      return ARMCortexA77;\n    case 0xd41:\n    case 0xd4b: // ARM Cortex A78C\n      return ARMCortexA78;\n    case 0xd44:\n    case 0xd4c: // ARM Cortex X1C\n      return ARMCortexX1;\n    case 0xd0c:\n      return ARMNeoverseN1;\n    case 0xd49:\n      return ARMNeoverseN2;\n    case 0xd8e:\n      return ARMNeoverseN3;\n    case 0xd4a:\n      return ARMNeoverseE1;\n    case 0xd40:\n      return ARMNeoverseV1;\n    case 0xd4f:\n      return ARMNeoverseV2;\n    case 0xd83:\n      return ARMNeoverseV3AE;\n    case 0xd84:\n      return ARMNeoverseV3;\n    }\n    break;\n  case 0x51: // Qualcomm\n    switch (cpuid.part) {\n    case 0x802:\n      return ARMCortexA75;\n    case 0x803:\n      return ARMCortexA55;\n    case 0x804:\n      return ARMCortexA76;\n    case 0x805:\n      return ARMCortexA55;\n    }\n    break;\n  case 0x61: // Apple\n    switch (cpuid.part) {\n    case 0x22:\n    case 0x24:\n    case 0x28:\n      return AppleM1Icestorm;\n    case 0x23:\n    case 0x25:\n    case 0x29:\n      return AppleM1Firestorm;\n    case 0x32:\n    case 0x34:\n    case 0x38:\n      return AppleM2Blizzard;\n    case 0x33:\n    case 0x35:\n    case 0x39:\n      return AppleM2Avalanche;\n    }\n    break;\n  case 0xc0: // Ampere\n    switch (cpuid.part) {\n    case 0xac3:\n      return AmpereOne;\n    }\n    break;\n  }\n  CLEAN_FATAL() << \"Unknown aarch64 CPU type \" << cpuid;\n  return UnknownCpu; // not reached\n}\n\nstatic void set_cpuid(std::vector<CPUID> &cpuids, unsigned long cpuidx, CPUID cpuid)\n{\n  if (cpuids.size() <= cpuidx) {\n    cpuids.resize(cpuidx + 1);\n  }\n  if (cpuids[cpuidx]) {\n    CLEAN_FATAL() << \"Duplicated CPUID for core \" << cpuidx;\n  }\n  cpuids[cpuidx] = cpuid;\n}\n\n/**\n * The new interface to get ID register values on AArch64\n * `/sys/devices/system/cpu/cpu([0-9]+)/regs/identification/midr_el1`\n * The register value is stored in hex.\n */\nstatic inline void get_cpuinfo_sysfs(std::vector<CPUID> &res)\n{\n  const std::string cpu_dir = \"/sys/devices/system/cpu/\";\n  const std::regex cpuname_regex(\"cpu([0-9]+)\");\n  auto dir = opendir(cpu_dir.c_str());\n  if (!dir) {\n    return;\n  }\n  while (auto entry = readdir(dir)) {\n    std::cmatch match;\n    if (entry->d_type != DT_DIR ||\n        !std::regex_match(entry->d_name, match, cpuname_regex)) {\n      continue;\n    }\n    auto cpuidx = std::stoul(match[1].str());\n    std::string name = cpu_dir + entry->d_name + \"/regs/identification/midr_el1\";\n    std::ifstream file(name);\n    if (!file) {\n      CLEAN_FATAL() << \"Failed to read midr register from kernel\";\n    }\n    uint64_t val = 0;\n    file >> std::hex >> val;\n    if (!file) {\n      CLEAN_FATAL() << \"Failed to read midr register from kernel\";\n    }\n    set_cpuid(res, cpuidx, {\n        uint8_t(val >> 24),\n        uint8_t((val >> 20) & 0xf),\n        uint16_t((val >> 4) & 0xfff)\n      });\n  }\n  closedir(dir);\n}\n\n/**\n * A line we care about in /proc/cpuinfo starts with a prefix followed by\n * `:` and some white space characters, then followed by the value we care about.\n * Return true if we've found the prefix. Set `flag` to `false`\n * if the value parsing failed.\n *\n * Use an external template since lambda's can't be templated in C++11\n */\ntemplate<typename T, typename F>\nstatic inline bool try_read_procfs_line(const std::string &line,\n                                        const char *prefix, T &out,\n                                        bool &flag, F &&reset)\n{\n  size_t prefix_len = strlen(prefix);\n  if (line.size() < prefix_len) {\n    return false;\n  }\n  if (memcmp(&line[0], prefix, prefix_len) != 0) {\n    return false;\n  }\n  if (flag) {\n    // We've seen this already,\n    // i.e. we didn't see a new line between the processor lines\n    reset();\n  }\n  const char *p = &line[prefix_len];\n  // Skip blank and `:`.\n  while (*p == '\\t' || *p == ' ' || *p == ':') {\n    p++;\n  }\n  char *str_end;\n  auto num = std::strtoull(p, &str_end, 0);\n  out = (T)num;\n  if (str_end == p) {\n    flag = false;\n  } else if (num > (unsigned long long)std::numeric_limits<T>::max()) {\n    flag = false;\n  } else {\n    flag = true;\n  }\n  return true;\n}\n\n/**\n * /proc/cpuinfo reader\n * The cpuinfo file contains blocks of text for each core.\n * The blocks are separated by empty lines and it should start with a\n * `processor : <num>` line followed by lines showing properties of the core.\n * The three property lines we are looking for starts with\n * `CPU implementer`, `CPU variant` and `CPU part`.\n */\nstatic inline void get_cpuinfo_procfs(std::vector<CPUID> &res)\n{\n  std::ifstream file(\"/proc/cpuinfo\");\n  CPUID cpuid = {0, 0, 0};\n  unsigned cpuidx = 0;\n  bool has_cpuidx = false;\n  bool has_impl = false;\n  bool has_part = false;\n  bool has_var = false;\n  auto reset = [&] () {\n    // Few (none) of the detection code care about the variant number\n    // so we'll accept it if we couldn't read it.\n    if (has_cpuidx && has_impl && has_part) {\n      set_cpuid(res, cpuidx, cpuid);\n    }\n    has_cpuidx = false;\n    has_impl = false;\n    has_part = false;\n    has_var = false;\n    cpuid = {0, 0, 0};\n  };\n  for (std::string line; std::getline(file, line);) {\n    // Empty lines means that we've finished processing of a block\n    if (line.empty()) {\n      reset();\n      continue;\n    }\n    // First find the processor line\n    if (try_read_procfs_line(line, \"processor\", cpuidx, has_cpuidx, reset)) {\n      continue;\n    }\n    // and ignore the line until we found the processor line.\n    if (!has_cpuidx) {\n      continue;\n    }\n\n    // Try parsing as one of the data lines.\n    // Short circuiting after the first hit.\n    try_read_procfs_line(line, \"CPU implementer\", cpuid.implementer, has_impl, reset) ||\n      try_read_procfs_line(line, \"CPU variant\", cpuid.variant, has_var, reset) ||\n      try_read_procfs_line(line, \"CPU part\", cpuid.part, has_part, reset);\n  }\n  reset();\n}\n\nstatic vector<CPUInfo> compute_cpus_info() {\n  vector<CPUInfo> result;\n  vector<CPUID> cpuids;\n  get_cpuinfo_sysfs(cpuids);\n  if (cpuids.empty()) {\n    LOG(warn) << \"Unable to read CPU type from sysfs, trying procfs instead.\";\n    get_cpuinfo_procfs(cpuids);\n  }\n  if (cpuids.empty()) {\n    CLEAN_FATAL() << \"Failed to read midr register from kernel\";\n  }\n  for (auto &cpuid : cpuids) {\n    if (!cpuid) {\n      CLEAN_FATAL() << \"Unable to find CPU id for core \" << &cpuid - &cpuids[0];\n    }\n  }\n  auto cpuid0 = cpuids[0];\n  bool single_uarch = true;\n  for (auto &cpuid : cpuids) {\n    if (cpuid != cpuid0) {\n      single_uarch = false;\n      break;\n    }\n  }\n  if (single_uarch) {\n    result.push_back({compute_cpu_microarch(cpuid0), PERF_TYPE_RAW});\n    return result;\n  }\n  for (auto &cpuid : cpuids) {\n    result.push_back({compute_cpu_microarch(cpuid), PERF_TYPE_RAW});\n  }\n  return result;\n}\n\nstatic void arch_check_restricted_counter() {\n  if (!Flags::get().suppress_environment_warnings) {\n    fprintf(stderr,\n            \"Your CPU supports only one performance counter.\\n\"\n            \"Use of LL/SC instructions will not be detected and will\\n\"\n            \"cause silently corrupt recordings. It is highly recommended\\n\"\n            \"that you alter your configuration to enable additional performance\\n\"\n            \"counters.\\n\");\n  }\n}\n\nstatic bool always_recreate_counters(__attribute__((unused)) const perf_event_attrs &perf_attr) {\n  return false;\n}\n\nstatic void check_for_arch_bugs(__attribute__((unused)) perf_event_attrs &perf_attr) {}\n\nstatic void post_init_pmu_uarchs(std::vector<PmuConfig> &pmu_uarchs)\n{\n  std::map<std::string,int> pmu_types;\n  size_t npmus = pmu_uarchs.size();\n  int pmu_type_failed = 0;\n  auto fallback_pmu = [] (PmuConfig &pmu_uarch) {\n    pmu_uarch.pmu_name = nullptr;\n    if (pmu_uarch.cycle_type != PERF_TYPE_HARDWARE) {\n      pmu_uarch.cycle_type = PERF_TYPE_HARDWARE;\n      pmu_uarch.cycle_event = PERF_COUNT_HW_CPU_CYCLES;\n    }\n    if (pmu_uarch.event_type != PERF_TYPE_RAW) {\n      pmu_uarch.event_type = PERF_TYPE_RAW;\n    }\n  };\n  auto set_pmu_type = [] (PmuConfig &pmu_uarch, int type) {\n    if (pmu_uarch.cycle_type != PERF_TYPE_HARDWARE) {\n      pmu_uarch.cycle_type = type;\n    }\n    if (pmu_uarch.event_type != PERF_TYPE_RAW) {\n      pmu_uarch.event_type = type;\n    }\n  };\n  bool has_unknown = false;\n  for (size_t i = 0; i < npmus; i++) {\n    auto &pmu_uarch = pmu_uarchs[i];\n    if (!(pmu_uarch.flags & (PMU_TICKS_RCB | PMU_TICKS_TAKEN_BRANCHES))) {\n      has_unknown = true;\n      continue;\n    }\n    if (!pmu_uarch.pmu_name) {\n      CLEAN_FATAL() << \"Unknown PMU name for core \" << i;\n      continue;\n    }\n    std::string pmu_name(pmu_uarch.pmu_name);\n    auto &pmu_type = pmu_types[pmu_name];\n    if (pmu_type == -1) {\n      fallback_pmu(pmu_uarch);\n      continue;\n    }\n    if (pmu_type) {\n      set_pmu_type(pmu_uarch, pmu_type);\n      continue;\n    }\n    auto filename = \"/sys/bus/event_source/devices/\" + pmu_name + \"/type\";\n    std::ifstream file(filename);\n    int val = 0;\n    bool failed = false;\n    if (!file) {\n      failed = true;\n      LOG(warn) << \"Cannot open \" << filename;\n    }\n    else {\n      file >> val;\n      if (!file) {\n        failed = true;\n        LOG(warn) << \"Cannot read \" << filename;\n      }\n    }\n    if (failed) {\n      // Record the failure and fallback to the kernel raw and hardware events instead\n      pmu_type_failed++;\n      fallback_pmu(pmu_uarch);\n      pmu_type = -1;\n    }\n    else {\n      set_pmu_type(pmu_uarch, val);\n      pmu_type = val;\n    }\n  }\n  if (pmu_types.size() == 1 && !has_unknown) {\n    bool single_type = true;\n    auto &pmu_uarch0 = pmu_uarchs[0];\n    // Apparently the same PMU type doesn't actually mean the same PMU events...\n    for (auto &pmu_uarch: pmu_uarchs) {\n      if (&pmu_uarch == &pmu_uarch0) {\n        // Skip first\n        continue;\n      }\n      if (pmu_uarch.rcb_cntr_event != pmu_uarch0.rcb_cntr_event ||\n          pmu_uarch.minus_ticks_cntr_event != pmu_uarch0.minus_ticks_cntr_event ||\n          pmu_uarch.llsc_cntr_event != pmu_uarch0.llsc_cntr_event) {\n        single_type = false;\n        break;\n      }\n    }\n    if (single_type) {\n      // Single PMU type\n      pmu_uarchs.resize(1);\n    }\n  }\n  if (pmu_uarchs.size() != 1 && pmu_type_failed) {\n    // If reading PMU type failed, we only allow a single PMU type to be sure\n    // that we get what we want from the kernel events.\n    CLEAN_FATAL() << \"Unable to read PMU event types\";\n  }\n}\n\ntemplate <>\nvoid PerfCounters::reset_arch_extras<ARM64Arch>(int pmu_index) {\n  // LL/SC can't be recorded reliably. Start a counter to detect\n  // any usage, such that we can give an intelligent error message.\n  struct perf_event_attr attr = perf_attrs[pmu_index].llsc_fail;\n  attr.sample_period = 0;\n  fd_strex_counter = start_counter(tid, fd_ticks_interrupt, &attr);\n}\n"
  },
  {
    "path": "src/PerfCounters_x86.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n// This file is included from PerfCounters.cc\n\nstatic bool has_kvm_in_txcp_bug;\nstatic bool has_xen_pmi_bug;\nstatic bool supports_txcp;\n\n/**\n * Return the detected, known microarchitecture of this CPU, or don't\n * return; i.e. never return UnknownCpu.\n *\n * Another way to do this would be to read the pmu type under\n * /sys/devices/.../caps/pmu_name. There are tradeoffs:\n *   * With the current approach, rr works with old kernels that haven't\n * been updated with specific knowledge of the CPU type. Reading\n * `pmu_name`, rr would not work.\n *   * Reading `pmu_name`, rr would work with new CPUs that use an\n * existing PMU type, if the kernel is new enough to know about those\n * CPUs. With the current approach users have to have an rr that has\n * been updated for those CPUs.\n * Assuming that it's easier to update rr than update one's kernel,\n * the current approach seems a little better.\n *\n * This detects the overall microarchitecture, which we also use\n * as the microarchitecture identifier for the P-cores of that architecture\n * in a hybrid setup.\n */\nstatic CpuMicroarch compute_cpu_microarch() {\n  auto cpuid_vendor = cpuid(CPUID_GETVENDORSTRING, 0);\n  char vendor[12];\n  memcpy(&vendor[0], &cpuid_vendor.ebx, 4);\n  memcpy(&vendor[4], &cpuid_vendor.edx, 4);\n  memcpy(&vendor[8], &cpuid_vendor.ecx, 4);\n  if (strncmp(vendor, \"GenuineIntel\", sizeof(vendor)) &&\n      strncmp(vendor, \"AuthenticAMD\", sizeof(vendor))) {\n    CLEAN_FATAL() << \"Unknown CPU vendor '\" << vendor << \"'\";\n  }\n\n  auto cpuid_data = cpuid(CPUID_GETFEATURES, 0);\n  unsigned int cpu_type = cpuid_data.eax & 0xF0FF0;\n  unsigned int ext_family = (cpuid_data.eax >> 20) & 0xff;\n  switch (cpu_type) {\n    case 0x006F0:\n    case 0x10660:\n      return IntelMerom;\n    case 0x10670:\n    case 0x106D0:\n      return IntelPenryn;\n    case 0x106A0:\n    case 0x106E0:\n    case 0x206E0:\n      return IntelNehalem;\n    case 0x20650:\n    case 0x206C0:\n    case 0x206F0:\n      return IntelWestmere;\n    case 0x206A0:\n    case 0x206D0:\n    case 0x306e0:\n      return IntelSandyBridge;\n    case 0x306A0:\n      return IntelIvyBridge;\n    case 0x306C0: /* Devil's Canyon */\n    case 0x306F0:\n    case 0x40650:\n    case 0x40660:\n      return IntelHaswell;\n    case 0x306D0:\n    case 0x40670:\n    case 0x406F0:\n    case 0x50660:\n      return IntelBroadwell;\n    case 0x406e0:\n    case 0x50650:\n    case 0x506e0:\n      return IntelSkylake;\n    case 0x30670:\n    case 0x406c0:\n    case 0x50670:\n      return IntelSilvermont;\n    case 0x506f0:\n    case 0x706a0:\n    case 0x506c0:\n      return IntelGoldmont;\n    case 0x906c0:\n      return IntelTremont;\n    case 0x706e0:\n    case 0x606a0:\n    case 0x80660:\n      return IntelIceLake;\n    case 0x806c0:\n    case 0x806d0:\n      return IntelTigerLake;\n    case 0x806e0:\n    case 0x906e0:\n      return IntelKabyLake;\n    case 0xa0650:\n    case 0xa0660:\n      return IntelCometLake;\n    case 0xa0670:\n      return IntelRocketLake;\n    case 0x90670:\n    case 0x906a0:\n      return IntelAlderLake;\n    case 0xb0670:\n    case 0xb06a0:\n    case 0xb06f0:\n      return IntelRaptorLake;\n    case 0x806f0:\n      return IntelSapphireRapids;\n    case 0xc06f0:\n      return IntelEmeraldRapids;\n    case 0xa06d0:\n      return IntelGraniteRapids;\n    case 0xa06a0:\n      return IntelMeteorLake;\n    case 0xb06d0:\n      return IntelLunarLake;\n    case 0xb06e0:\n      return IntelGracemont;\n    case 0xb0650:\n    case 0xc0650:\n    case 0xc0660:\n      return IntelArrowLake;\n    case 0xf20:  // Piledriver\n    case 0x30f00:  // Steamroller\n      return AMDF15;\n    case 0x00f10: // A8-3530MX, Naples, Whitehaven, Summit Ridge, Snowy Owl (Zen), Milan (Zen 3) (UNTESTED)\n      if (ext_family == 8) {\n        return AMDZen;\n      } else if (ext_family == 0xa) {\n        return AMDZen3;\n      } else if (ext_family == 3) {\n        return AMDF15;\n      }\n      break;\n    case 0x00f80: // Colfax, Pinnacle Ridge (Zen+), Chagall (Zen3) (UNTESTED)\n      if (ext_family == 8) {\n        return AMDZen;\n      } else if (ext_family == 0xa) {\n        return AMDZen3;\n      }\n      break;\n    case 0x10f10: // Raven Ridge, Great Horned Owl (Zen) (UNTESTED)\n    case 0x10f80: // Banded Kestrel (Zen), Picasso (Zen+), 7975WX (Zen2)\n    case 0x20f00: // Dali (Zen)\n      if (ext_family == 8) {\n        return AMDZen;\n      } else if (ext_family == 0xa) {\n        return AMDZen2;\n      }\n      break;\n    case 0x30f10: // Rome, Castle Peak (Zen 2)\n    case 0x60f00: // Renoir (Zen 2), Krackan Point (Zen 5) (EXPERIMENTAL)\n    case 0x70f10: // Matisse (Zen 2)\n    case 0x60f80: // Lucienne (Zen 2)\n    case 0x90f00: // Van Gogh (Zen 2)\n      if (ext_family == 8) {\n        return AMDZen2;\n      } else if (ext_family == 0xb) {\n        return AMDZen5;\n      }\n      break;\n    case 0x20f10: // Vermeer (Zen 3)\n    case 0x50f00: // Cezanne (Zen 3)\n    case 0x40f40: // Rembrandt (Zen 3+)\n      return AMDZen3;\n    case 0x60f10: // Raphael (Zen 4)\n    case 0x70f40: // Phoenix (Zen 4)\n    case 0x70f50: // Hawk Point (Zen 4)\n      return AMDZen4;\n    case 0x20f40: // Strix Point (Zen 5)\n    case 0x70f00: // Strix Halo (Zen 5)\n      return AMDZen5;\n    default:\n      break;\n  }\n\n  if (!strncmp(vendor, \"AuthenticAMD\", sizeof(vendor))) {\n    CLEAN_FATAL() << \"AMD CPU type \" << HEX(cpu_type) <<\n                     \" (ext family \" << HEX(ext_family) << \") unknown\";\n  } else {\n    CLEAN_FATAL() << \"Intel CPU type \" << HEX(cpu_type) << \" unknown\";\n  }\n  return UnknownCpu; // not reached\n}\n\nstatic vector<CPUInfo> compute_cpus_info() {\n  vector<CPUInfo> result;\n  auto groups = CPUs::get().cpu_groups();\n  if (groups.empty()) {\n    // Only one kind of CPU core.\n    result.push_back({compute_cpu_microarch(), PERF_TYPE_RAW});\n    return result;\n  }\n\n  for (int cpu : CPUs::get().initial_affinity()) {\n    if (cpu < static_cast<int>(result.size()) &&\n        result[cpu].microarch != UnknownCpu) {\n      // This cpu belongs to a group we already computed the microarch for.\n      // Using groups like this lets us avoid having to schedule this thread\n      // on every single CPU in the system.\n      continue;\n    }\n    while (static_cast<int>(result.size()) < cpu) {\n      result.push_back({UnknownCpu, PERF_TYPE_RAW});\n    }\n    if (!CPUs::set_affinity_to_cpu(cpu)) {\n      FATAL() << \"Can't set affinity to previously allowed CPU\";\n    }\n    CpuMicroarch uarch = compute_cpu_microarch();\n    // May be overwritten below if this is part of a known hybrid core grouping.\n    result.push_back({uarch, PERF_TYPE_RAW});\n    // Fill in `result` for all CPUs in the same group as the current CPU.\n    // This avoids having to schedule this thread on every single CPU in the\n    // system.\n    for (auto group : groups) {\n      if (group.start_cpu <= cpu && cpu < group.end_cpu) {\n        result.resize(group.end_cpu);\n        if (group.name == \"atom\") {\n          switch (uarch) {\n          case IntelAlderLake:\n          case IntelRaptorLake:\n            uarch = IntelGracemont;\n            break;\n          case IntelMeteorLake:\n            uarch = IntelCrestmont;\n            break;\n          case IntelLunarLake:\n          case IntelArrowLake:\n            // Some Arrow Lakes use Crestmont E-cores maybe? Hopefully doesn't matter\n            // for the PMU.\n            uarch = IntelSkymont;\n            break;\n          default:\n            FATAL() << \"Atom architecture detected but not known for \" << uarch;\n          }\n        } else if (group.name == \"lowpower\") {\n          switch (uarch) {\n          case IntelArrowLake:\n            uarch = IntelCrestmont;\n            break;\n          default:\n            FATAL() << \"Lowpower architecture detected but not known for \" << uarch;\n          }\n        } else if (group.name != \"core\") {\n          FATAL() << \"Hybrid architecture group name not known: \" << group.name;\n        }\n        for (int i = group.start_cpu; i < group.end_cpu; ++i) {\n          result[i] = {uarch, group.type};\n        }\n        break;\n      }\n    }\n  }\n  CPUs::get().restore_initial_affinity();\n  return result;\n}\n\nstatic void check_for_kvm_in_txcp_bug(const perf_event_attrs &perf_attr) {\n  int64_t count = 0;\n  struct perf_event_attr attr = perf_attr.ticks;\n  attr.config |= IN_TXCP;\n  attr.sample_period = 0;\n  bool disabled_txcp;\n  ScopedFd fd = start_counter(0, -1, &attr, &disabled_txcp);\n  if (fd.is_open() && !disabled_txcp) {\n    ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);\n    ioctl(fd, PERF_EVENT_IOC_ENABLE, 0);\n    do_branches();\n    count = read_counter(fd);\n  }\n\n  supports_txcp = count > 0;\n  has_kvm_in_txcp_bug = supports_txcp && count < NUM_BRANCHES;\n  LOG(debug) << \"supports txcp=\" << supports_txcp;\n  LOG(debug) << \"has_kvm_in_txcp_bug=\" << has_kvm_in_txcp_bug\n             << \" count=\" << count;\n}\n\nstatic void check_for_xen_pmi_bug(const perf_event_attrs &perf_attr) {\n  int32_t count = -1;\n  struct perf_event_attr attr = perf_attr.ticks;\n  attr.sample_period = NUM_BRANCHES - 1;\n  ScopedFd fd = start_counter(0, -1, &attr);\n  if (fd.is_open()) {\n    // Do NUM_BRANCHES conditional branches that can't be optimized out.\n    // 'accumulator' is always odd and can't be zero\n    uint32_t accumulator = uint32_t(rand()) * 2 + 1;\n    int raw_fd = fd;\n    asm volatile(\n#if defined(__x86_64__)\n        \"mov %[_SYS_ioctl], %%rax;\"\n        \"mov %[raw_fd], %%edi;\"\n        \"xor %%rdx, %%rdx;\"\n        \"mov %[_PERF_EVENT_IOC_ENABLE], %%rsi;\"\n        \"syscall;\"\n        \"cmp $-4095, %%rax;\"\n        \"jae 2f;\"\n        \"mov %[_SYS_ioctl], %%rax;\"\n        \"mov %[_PERF_EVENT_IOC_RESET], %%rsi;\"\n        \"syscall;\"\n        // From this point on all conditional branches count!\n        \"cmp $-4095, %%rax;\"\n        \"jae 2f;\"\n        // Reset the counter period to the desired value.\n        \"mov %[_SYS_ioctl], %%rax;\"\n        \"mov %[_PERF_EVENT_IOC_PERIOD], %%rsi;\"\n        \"mov %[period], %%rdx;\"\n        \"syscall;\"\n        \"cmp $-4095, %%rax;\"\n        \"jae 2f;\"\n        \"mov %[_iterations], %%rax;\"\n        \"1: dec %%rax;\"\n        // Multiply by 7.\n        \"mov %[accumulator], %%edx;\"\n        \"shl $3, %[accumulator];\"\n        \"sub %%edx, %[accumulator];\"\n        // Add 2.\n        \"add $2, %[accumulator];\"\n        // Mask off bits.\n        \"and $0xffffff, %[accumulator];\"\n        // And loop.\n        \"test %%rax, %%rax;\"\n        \"jnz 1b;\"\n        \"mov %[_PERF_EVENT_IOC_DISABLE], %%rsi;\"\n        \"mov %[_SYS_ioctl], %%rax;\"\n        \"xor %%rdx, %%rdx;\"\n        // We didn't touch rdi.\n        \"syscall;\"\n        \"cmp $-4095, %%rax;\"\n        \"jae 2f;\"\n        \"movl $0, %[count];\"\n        \"2: nop;\"\n#elif defined(__i386__)\n        \"mov %[_SYS_ioctl], %%eax;\"\n        \"mov %[raw_fd], %%ebx;\"\n        \"xor %%edx, %%edx;\"\n        \"mov %[_PERF_EVENT_IOC_ENABLE], %%ecx;\"\n        \"int $0x80;\"\n        \"cmp $-4095, %%eax;\"\n        \"jae 2f;\"\n        \"mov %[_SYS_ioctl], %%eax;\"\n        \"mov %[_PERF_EVENT_IOC_RESET], %%ecx;\"\n        \"int $0x80;\"\n        // From this point on all conditional branches count!\n        \"cmp $-4095, %%eax;\"\n        \"jae 2f;\"\n        // Reset the counter period to the desired value.\n        \"mov %[_SYS_ioctl], %%eax;\"\n        \"mov %[_PERF_EVENT_IOC_PERIOD], %%ecx;\"\n        \"mov %[period], %%edx;\"\n        \"int $0x80;\"\n        \"cmp $-4095, %%eax;\"\n        \"jae 2f;\"\n        \"mov %[_iterations], %%eax;\"\n        \"1: dec %%eax;\"\n        // Multiply by 7.\n        \"mov %[accumulator], %%edx;\"\n        \"shll $3, %[accumulator];\"\n        \"sub %%edx, %[accumulator];\"\n        // Add 2.\n        \"addl $2, %[accumulator];\"\n        // Mask off bits.\n        \"andl $0xffffff, %[accumulator];\"\n        // And loop.\n        \"test %%eax, %%eax;\"\n        \"jnz 1b;\"\n        \"mov %[_PERF_EVENT_IOC_DISABLE], %%ecx;\"\n        \"mov %[_SYS_ioctl], %%eax;\"\n        \"xor %%edx, %%edx;\"\n        // We didn't touch rdi.\n        \"int $0x80;\"\n        \"cmp $-4095, %%eax;\"\n        \"jae 2f;\"\n        \"movl $0, %[count];\"\n        \"2: nop;\"\n#else\n#error unknown CPU architecture\n#endif\n        : [accumulator] \"+rm\"(accumulator), [count] \"=rm\"(count)\n        : [_SYS_ioctl] \"i\"(SYS_ioctl),\n          [_PERF_EVENT_IOC_DISABLE] \"i\"(PERF_EVENT_IOC_DISABLE),\n          [_PERF_EVENT_IOC_ENABLE] \"i\"(PERF_EVENT_IOC_ENABLE),\n          [_PERF_EVENT_IOC_PERIOD] \"i\"(PERF_EVENT_IOC_PERIOD),\n          [_PERF_EVENT_IOC_RESET] \"i\"(PERF_EVENT_IOC_RESET),\n          // The check for the failure of some of our ioctls is in\n          // the measured region, so account for that when looping.\n          [_iterations] \"i\"(NUM_BRANCHES - 2),\n          [period] \"rm\"(&attr.sample_period), [raw_fd] \"rm\"(raw_fd)\n        :\n#if defined(__x86_64__)\n        \"rax\", \"rdx\", \"rdi\", \"rsi\"\n        // `syscall` clobbers rcx and r11.\n        ,\n        \"rcx\", \"r11\"\n#elif defined(__i386__)\n        \"eax\", \"ebx\", \"ecx\", \"edx\"\n#else\n#error unknown CPU architecture\n#endif\n        );\n    // If things worked above, `count` should have been set to 0.\n    if (count == 0) {\n      count = read_counter(fd);\n    }\n    // Use 'accumulator' so it can't be optimized out.\n    accumulator_sink = accumulator;\n  }\n\n  has_xen_pmi_bug = count > NUM_BRANCHES || count == -1;\n  if (has_xen_pmi_bug) {\n    LOG(debug) << \"has_xen_pmi_bug=\" << has_xen_pmi_bug << \" count=\" << count;\n    if (!Flags::get().force_things) {\n      FATAL()\n          << \"Overcount triggered by PMU interrupts detected due to Xen PMU \"\n             \"virtualization bug.\\n\"\n             \"Aborting. Retry with -F to override, but it will probably\\n\"\n             \"fail.\";\n    } else {\n      cpu_improperly_configured = true;\n    }\n  }\n}\n\nstatic void check_for_zen_speclockmap() {\n  // When the SpecLockMap optimization is not disabled, rr will not work\n  // reliably (e.g. it would work fine on a single process with a single\n  // thread, but not more). When the optimization is disabled, the\n  // perf counter for retired lock instructions of type SpecLockMapCommit\n  // (on PMC 0x25) stays at 0.\n  // See more details at https://github.com/rr-debugger/rr/issues/2034.\n  struct perf_event_attr attr;\n  // 0x25 == RETIRED_LOCK_INSTRUCTIONS - Counts the number of retired locked instructions\n  // + 0x08 == SPECLOCKMAPCOMMIT\n  init_perf_event_attr(&attr, PERF_TYPE_RAW, 0x510825);\n\n  ScopedFd fd = start_counter(0, -1, &attr);\n  if (fd.is_open()) {\n    int atomic = 0;\n    int64_t count = read_counter(fd);\n    // A lock add is known to increase the perf counter we're looking at.\n    asm volatile(\"lock addl $1, %0\": \"+m\" (atomic));\n    if (read_counter(fd) == count) {\n      LOG(debug) << \"SpecLockMap is disabled\";\n    } else {\n      LOG(debug) << \"SpecLockMap is not disabled\";\n      if (!Flags::get().force_things) {\n        CLEAN_FATAL() <<\n                \"On Zen CPUs, rr will not work reliably unless you disable the \"\n                \"hardware SpecLockMap optimization.\\nFor instructions on how to \"\n                \"do this, see https://github.com/rr-debugger/rr/wiki/Zen\\n\";\n      } else {\n        cpu_improperly_configured = true;\n      }\n    }\n  }\n}\n\nstatic void check_for_freeze_on_smi() {\n  ScopedFd fd = ScopedFd(\"/sys/devices/cpu/freeze_on_smi\", O_RDONLY);\n  if (!fd.is_open()) {\n    LOG(debug) << \"/sys/devices/cpu/freeze_on_smi not present\";\n    return;\n  }\n\n  char freeze_on_smi = 0;\n  ssize_t ret = read(fd, &freeze_on_smi, 1);\n  if (ret != 1) {\n    FATAL() << \"Can't read freeze_on_smi\";\n  }\n  if (freeze_on_smi == 0) {\n    LOG(warn) << \"Failed to read freeze_on_smi\";\n  } else if (freeze_on_smi == '1') {\n    LOG(debug) << \"freeze_on_smi is set\";\n  } else if (freeze_on_smi == '0') {\n    LOG(warn) << \"freeze_on_smi is not set\";\n    if (!Flags::get().force_things) {\n      CLEAN_FATAL() <<\n              \"Freezing performance counters on SMIs should be enabled for maximum rr\\n\"\n              \"reliability on Comet Lake and later CPUs. To manually enable this setting, run\\n\"\n              \"\\techo 1 | sudo tee /sys/devices/cpu/freeze_on_smi\\n\"\n              \"On systemd systems, consider putting\\n\"\n              \"'w /sys/devices/cpu/freeze_on_smi - - - - 1' into /etc/tmpfiles.d/10-rr.conf\\n\"\n              \"to automatically apply this setting on every reboot.\\n\"\n              \"See 'man 5 sysfs', 'man 5 tmpfiles.d'.\\n\"\n              \"If you are seeing this message, the setting has not been enabled.\\n\";\n    } else {\n      cpu_improperly_configured = true;\n    }\n  } else {\n    LOG(warn) << \"Unrecognized freeze_on_smi value \" << freeze_on_smi;\n  }\n}\n\n// Must be run on the CPU where we're checking for bugs.\nstatic void check_for_arch_bugs(perf_event_attrs &perf_attr) {\n  CpuMicroarch uarch = (CpuMicroarch)perf_attr.bug_flags;\n  if (uarch >= FirstIntel && uarch <= LastIntel) {\n    check_for_kvm_in_txcp_bug(perf_attr);\n    check_for_xen_pmi_bug(perf_attr);\n  }\n  if (uarch >= IntelCometLake && uarch <= LastIntel) {\n    check_for_freeze_on_smi();\n  }\n  if (uarch >= AMDZen && uarch <= LastAMD) {\n    check_for_zen_speclockmap();\n  }\n}\n\nstatic void post_init_pmu_uarchs(std::vector<PmuConfig> &) {\n\n}\n\nstatic bool always_recreate_counters(const perf_event_attrs &perf_attr) {\n  // When we have the KVM IN_TXCP bug, reenabling the TXCP counter after\n  // disabling it does not work.\n  DEBUG_ASSERT(perf_attr.checked);\n  return perf_attr.has_ioc_period_bug || has_kvm_in_txcp_bug;\n}\n\nstatic void arch_check_restricted_counter() {\n  if ((cpuid(CPUID_GETEXTENDEDFEATURES, 0).ebx & HLE_FEATURE_FLAG) &&\n    !Flags::get().suppress_environment_warnings) {\n    fprintf(stderr,\n            \"Your CPU supports Hardware Lock Elision but you only have one\\n\"\n            \"hardware performance counter available. Record and replay\\n\"\n            \"of code that uses HLE will fail unless you alter your\\n\"\n            \"configuration to make more than one hardware performance counter\\n\"\n            \"available.\\n\");\n  }\n}\n\ntemplate <typename Arch>\nvoid PerfCounters::reset_arch_extras(int pmu_index) {\n  if (supports_txcp) {\n    struct perf_event_attr attr = rr::perf_attrs[pmu_index].ticks;\n    if (has_kvm_in_txcp_bug) {\n      // IN_TXCP isn't going to work reliably. Assume that HLE/RTM are not\n      // used,\n      // and check that.\n      attr.sample_period = 0;\n      attr.config |= IN_TX;\n      fd_ticks_in_transaction = start_counter(tid, fd_ticks_interrupt, &attr);\n    } else {\n      // Set up a separate counter for measuring ticks, which does not have\n      // a sample period and does not count events during aborted\n      // transactions.\n      // We have to use two separate counters here because the kernel does\n      // not support setting a sample_period with IN_TXCP, apparently for\n      // reasons related to this Intel note on IA32_PERFEVTSEL2:\n      // ``When IN_TXCP=1 & IN_TX=1 and in sampling, spurious PMI may\n      // occur and transactions may continuously abort near overflow\n      // conditions. Software should favor using IN_TXCP for counting over\n      // sampling. If sampling, software should use large “sample-after“\n      // value after clearing the counter configured to use IN_TXCP and\n      // also always reset the counter even when no overflow condition\n      // was reported.''\n      attr.sample_period = 0;\n      attr.config |= IN_TXCP;\n      fd_ticks_measure = start_counter(tid, fd_ticks_interrupt, &attr);\n    }\n  }\n}\n"
  },
  {
    "path": "src/PidFdMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"PidFdMonitor.h\"\n\n#include \"Session.h\"\n\nnamespace rr {\n\n/* static */ PidFdMonitor*\nPidFdMonitor::get(FdTable* fd_table, int fd) {\n  FileMonitor* monitor = fd_table->get_monitor(fd);\n  if (!monitor) {\n    return NULL;\n  }\n\n  if (monitor->type() == PidFd) {\n    return static_cast<PidFdMonitor*>(monitor);\n  }\n\n  return NULL;\n}\n\nFdTable::shr_ptr\nPidFdMonitor::fd_table(Session& session) const {\n  Task* t = session.find_task(tuid);\n  if (!t) {\n    return NULL;\n  }\n\n  return t->fd_table();\n}\n\n}\n"
  },
  {
    "path": "src/PidFdMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PID_FD_MONITOR_H_\n#define RR_PID_FD_MONITOR_H_\n\n#include \"FdTable.h\"\n#include \"FileMonitor.h\"\n#include \"TaskishUid.h\"\n\nstruct perf_event_attr;\n\nnamespace rr {\n\nclass Session;\n\n/**\n * A FileMonitor to handle pidfd fds\n */\nclass PidFdMonitor : public FileMonitor {\npublic:\n  PidFdMonitor(TaskUid tuid)\n    : tuid(tuid) {}\n\n  virtual Type type() override { return PidFd; }\n\n  static PidFdMonitor* get(FdTable* fd_table, int fd);\n\n  FdTable::shr_ptr fd_table(Session& session) const;\n\nprivate:\n  // 0 if this doesn't object doesn't refer to a tracee's proc-mem.\n  TaskUid tuid;\n};\n\n} // namespace rr\n\n#endif /* RR_PID_FD_MONITOR_H_ */\n"
  },
  {
    "path": "src/PreserveFileMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PRESERVE_FILE_MONITOR_H_\n#define RR_PRESERVE_FILE_MONITOR_H_\n\n#include \"FileMonitor.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor that does no monitoring of I/O itself, but prevents the file\n * descriptor from being closed (except via privileged syscalls made by\n * preload.c) or seen in /proc/pid/fd/.\n *\n * The mere existence of this monitor disables syscall buffering for the fd, so\n * we get syscall traps for close() etc on the fd. Then\n * rec_prepare_syscall_arch calls allow_close() to check whether closing is\n * allowed.\n */\nclass PreserveFileMonitor : public FileMonitor {\npublic:\n  PreserveFileMonitor() {}\n  virtual Type type() override { return Preserve; }\n  virtual bool is_rr_fd() override { return true; }\n};\n\n} // namespace rr\n\n#endif /* RR_PRESERVE_FILE_MONITOR_H_ */\n"
  },
  {
    "path": "src/ProcFdDirMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ProcFdDirMonitor.h\"\n\n#include <dirent.h>\n#include <stdlib.h>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nProcFdDirMonitor::ProcFdDirMonitor(Task* t, const string& pathname) {\n  // XXX this makes some assumptions about namespaces... Probably fails\n  // if |t| is not the same pid namespace as rr\n  int tid = parse_tid_from_proc_path(pathname, \"/fd\");\n  if (tid > 0) {\n    Task* target = t->session().find_task(tid);\n    if (target) {\n      tuid = target->tuid();\n    }\n  }\n}\n\n// returns the number of valid dirent structs left in the buffer\ntemplate <typename D>\nstatic int filter_dirent_structs(RecordTask* t, uint8_t* buf, size_t size) {\n  int bytes = 0;\n  size_t current_offset = 0;\n  while (1) {\n    if (current_offset == size) {\n      break;\n    }\n\n    D* current_struct = reinterpret_cast<D*>(buf + current_offset);\n    auto next_off = current_offset + current_struct->d_reclen;\n\n    char* fname = (char*)current_struct->d_name;\n    char* end;\n    int fd = strtol(fname, &end, 10);\n    if (!*end && t->fd_table()->is_rr_fd(fd)) {\n      // Skip this entry.\n      memmove(current_struct, buf + next_off, size - next_off);\n      size -= (next_off - current_offset);\n      next_off = current_offset;\n    } else {\n      // Either this is a tracee fd or not an fd at all (e.g. '.')\n      bytes += current_struct->d_reclen;\n    }\n\n    current_offset = next_off;\n  }\n\n  return bytes;\n}\n\ntemplate <typename Arch> static void filter_dirents_arch(RecordTask* t) {\n  auto regs = t->regs();\n  remote_ptr<uint8_t> ptr(regs.arg2());\n  size_t len = regs.arg3();\n\n  if (regs.syscall_failed() || !regs.syscall_result()) {\n    return;\n  }\n\n  while (1) {\n    vector<uint8_t> buf = t->read_mem(ptr, len);\n    int bytes = regs.syscall_result();\n    if (regs.original_syscallno() == Arch::getdents64) {\n      bytes =\n          filter_dirent_structs<typename Arch::dirent64>(t, buf.data(), bytes);\n    } else {\n      bytes =\n          filter_dirent_structs<typename Arch::dirent>(t, buf.data(), bytes);\n    }\n\n    if (bytes > 0) {\n      t->write_mem(ptr, buf.data(), bytes);\n      regs.set_syscall_result(bytes);\n      t->set_regs(regs);\n      // Explicitly record what the kernel may have touched and we discarded,\n      // because it's userspace modification that will not be caught otherwise.\n      if (len > (size_t)bytes) {\n        t->record_remote(ptr + bytes, len - bytes);\n      }\n      return;\n    }\n\n    // We filtered out all the entries, so we need to repeat the syscall.\n    {\n      AutoRemoteSyscalls remote(t);\n      remote.syscall(regs.original_syscallno(), regs.orig_arg1(), regs.arg2(),\n                     regs.arg3());\n      // Only copy over the syscall result. In particular, we don't want to\n      // copy the AutoRemoteSyscalls ip().\n      regs.set_syscall_result(t->regs().syscall_result());\n    }\n\n    if (regs.syscall_failed() || regs.syscall_result() == 0) {\n      // Save the new syscall result, and record the buffer we will otherwise\n      // ignore.\n      t->record_remote(ptr, len);\n      t->set_regs(regs);\n      return;\n    }\n  }\n}\n\nstatic void filter_dirents(RecordTask* t) {\n  RR_ARCH_FUNCTION(filter_dirents_arch, t->arch(), t);\n}\n\nvoid ProcFdDirMonitor::filter_getdents(RecordTask* t) {\n  ASSERT(t, !t->session().is_replaying());\n  auto* target = static_cast<RecordTask*>(t->session().find_task(tuid));\n  if (!target) {\n    return;\n  }\n\n  filter_dirents(t);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ProcFdDirMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PROC_FD_DIR_MONITOR_H_\n#define RR_PROC_FD_DIR_MONITOR_H_\n\n#include \"FileMonitor.h\"\n#include \"TaskishUid.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor to intercept enumerations of /proc/<pid>/fd so that entries\n * for rr's private fds can be hidden when <pid> is a tracee.\n */\nclass ProcFdDirMonitor : public FileMonitor {\npublic:\n  ProcFdDirMonitor(Task* t, const std::string& pathname);\n\n  virtual Type type() override { return ProcFd; }\n\n  virtual void filter_getdents(RecordTask* t) override;\n\nprivate:\n  // 0 if this doesn't object doesn't refer to a tracee's proc-mem.\n  TaskUid tuid;\n};\n\n} // namespace rr\n\n#endif /* RR_PROC_FD_DIR_MONITOR_H_ */\n"
  },
  {
    "path": "src/ProcMemMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ProcMemMonitor.h\"\n\n#include <stdlib.h>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"RecordSession.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nProcMemMonitor::ProcMemMonitor(Task* t, const string& pathname) {\n  // XXX this makes some assumptions about namespaces... Probably fails\n  // if |t| is not the same pid namespace as rr\n  int tid = parse_tid_from_proc_path(pathname, \"/mem\");\n  if (tid > 0) {\n    Task* target = t->session().find_task(tid);\n    if (target) {\n      auid = target->vm()->uid();\n    }\n  }\n}\n\nvoid ProcMemMonitor::did_write(Task* t, const std::vector<Range>& ranges,\n                               LazyOffset& lazy_offset) {\n  if (ranges.empty()) {\n    return;\n  }\n  int64_t offset = lazy_offset.retrieve(true);\n\n  // In prior versions of rr, we recorded this directly into the trace.\n  // If so, there's nothing to do here.\n  if (t->session().is_replaying() && t->session().as_replay()->has_trace_quirk(TraceReader::ExplicitProcMem)) {\n    return;\n  }\n\n  if (t->session().is_recording()) {\n    // Nothing to do now (though we may have just recorded the offset)\n    return;\n  }\n\n  auto* target = t->session().find_address_space(auid);\n  if (!target) {\n    return;\n  }\n\n  ReplayTask* task = static_cast<ReplayTask*>(target->first_running_task());\n  if (!task) {\n    return;\n  }\n\n  for (auto& r : ranges) {\n    auto bytes = t->read_mem(r.data.cast<uint8_t>(), r.length);\n    remote_ptr<uint8_t> target_addr = offset;\n    task->write_mem(target_addr, bytes.data(), r.length);\n    target->maybe_update_breakpoints(task, target_addr,\n                                     r.length);\n    offset += r.length;\n  }\n}\n\nbool ProcMemMonitor::target_is_vm(AddressSpace *vm) {\n  return auid == vm->uid();\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ProcMemMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PROC_MEM_MONITOR_H_\n#define RR_PROC_MEM_MONITOR_H_\n\n#include \"FileMonitor.h\"\n#include \"TaskishUid.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor to track writes to /proc/<pid>/mem so they can be replayed\n * when <pid> is a replayed tracee.\n */\nclass ProcMemMonitor : public FileMonitor {\npublic:\n  ProcMemMonitor(Task* t, const std::string& pathname);\n\n  virtual Type type() override { return ProcMem; }\n\n  // We need to PREVENT_SWITCH, since the timing of the write is otherwise\n  // unpredictable from our perspective.\n  virtual Switchable will_write(Task*) override { return PREVENT_SWITCH; }\n\n  virtual void did_write(Task* t, const std::vector<Range>& ranges,\n                         LazyOffset& lazy_offset) override;\n\n  virtual enum syscallbuf_fd_classes get_syscallbuf_class() override {\n    return FD_CLASS_PROC_MEM;\n  }\n\n  bool target_is_vm(AddressSpace *t);\n\nprivate:\n  // 0 if this doesn't object doesn't refer to a tracee's proc-mem.\n  AddressSpaceUid auid;\n};\n\n} // namespace rr\n\n#endif /* RR_PROC_MEM_MONITOR_H_ */\n"
  },
  {
    "path": "src/ProcStatMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <sys/stat.h>\n#include <unistd.h>\n\n#include <fstream>\n#include <algorithm>\n\n#include \"ProcStatMonitor.h\"\n#include \"RecordTask.h\"\n#include \"RecordSession.h\"\n#include \"Scheduler.h\"\n\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n// Skip any lines that contain CPUs not in our cpu mask\nstatic void filter_proc_stat(string& data, const cpu_set_t& active) {\n  string::iterator pos = data.begin();\n  while (pos + 4 < data.end()) {\n    const char *cur_data = &*pos;\n    static char cpu_str[] = \"cpu\";\n    if (memcmp(cur_data, cpu_str, sizeof(cpu_str)-1) == 0 && isdigit(*(cur_data + 3))) {\n      unsigned long cpu = strtoul((char*)cur_data + 3, NULL, 10);\n      if (!CPU_ISSET(cpu, &active)) {\n        pos = data.erase(pos, ++std::find(pos, data.end(), '\\n'));\n        continue;\n      }\n    }\n    pos = ++std::find(pos, data.end(), '\\n');\n  }\n}\n\nProcStatMonitor::ProcStatMonitor(Task* t, const string&) {\n  if (t->session().is_replaying())\n    return;\n  // Grab all the data now and buffer it for later access. This matches what the\n  // kernel does (except that it does the buffering on first access) and is\n  // required to give userspace code a consistent view of the file.\n  std::ifstream proc_stat(\"/proc/stat\");\n  if (!proc_stat.is_open()) {\n    FATAL() << \"Failed to process /proc/stat\";\n  }\n  data = string(\n    (std::istreambuf_iterator<char>(proc_stat)),\n    (std::istreambuf_iterator<char>()));\n  const cpu_set_t cpus = static_cast<RecordTask*>(t)->session().scheduler().pretend_affinity_mask();\n  filter_proc_stat(data, cpus);\n}\n\nbool ProcStatMonitor::emulate_read(\n  RecordTask* t, const vector<Range>& ranges,\n  LazyOffset& lazy_offset, uint64_t* result) {\n  int64_t offset = lazy_offset.retrieve(false);\n  *result = t->write_ranges(ranges, (uint8_t*)data.data() + offset,\n    (offset > (ssize_t)data.size()) ? 0 : data.size() - offset);\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ProcStatMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PROC_STAT_MONITOR_H_\n#define RR_PROC_STAT_MONITOR_H_\n\n#include \"FileMonitor.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor to intercept /proc/stat in order to pretend to the\n * tracee that it only has the CPUs that rr is willing to give it.\n * This is necessary on top of the SysCpuMonitor, because some versions\n * of glibc have bugs that cause it to fail to parse the\n * /sys/devices/system/cpu/online format, causing them to fallback to /proc/stat\n */\nclass ProcStatMonitor : public FileMonitor {\npublic:\n  ProcStatMonitor(Task* t, const std::string& pathname);\n\n  virtual Type type() override { return ProcStat; }\n\n  bool emulate_read(RecordTask* t, const std::vector<Range>& ranges,\n                    LazyOffset&, uint64_t* result) override;\nprivate:\n  std::string data;\n};\n\n} // namespace rr\n\n#endif /* RR_PROC_STAT_MONITOR_H_ */\n"
  },
  {
    "path": "src/ProcessorTraceDecoder.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <intel-pt.h>\n\n#include <ostream>\n#include <sstream>\n#include <vector>\n\n#include \"AddressSpace.h\"\n#include \"ProcessorTraceDecoder.h\"\n#include \"Session.h\"\n#include \"log.h\"\n#include \"preload/preload_interface.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic string pt_err(int status) {\n  char buf[1024];\n  sprintf(buf, \"%s (%d)\", pt_errstr(pt_errcode(status)), status);\n  return buf;\n}\n\nProcessorTraceDecoder::~ProcessorTraceDecoder() {\n  if (decoder) {\n    pt_insn_free_decoder(decoder);\n  }\n}\n\nint read_mem_callback(uint8_t *buffer, size_t size,\n                      const pt_asid *,\n                      uint64_t ip, void *context) {\n  return static_cast<ProcessorTraceDecoder*>(context)->\n      read_mem(ip, buffer, size);\n}\n\nstatic constexpr uint8_t injected_header_packets[] =\n    { /*PSB*/ 0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82,\n              0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82,\n      /*CBR 31*/ 0x02, 0x03, 0x1f, 0x00,\n      /*PSBEND*/ 0x02, 0x23 };\nstatic constexpr size_t PSB_LEN = 16;\n\nvoid ProcessorTraceDecoder::init(const vector<uint8_t>& trace_data) {\n  if (trace_data.empty()) {\n    return;\n  }\n\n  if (trace_data.size() < PSB_LEN ||\n      memcmp(injected_header_packets, trace_data.data(), PSB_LEN)) {\n    full_trace_data.reserve(sizeof(injected_header_packets) + trace_data.size());\n    full_trace_data.insert(full_trace_data.end(), injected_header_packets,\n                           injected_header_packets + sizeof(injected_header_packets));\n  }\n  full_trace_data.insert(full_trace_data.end(), trace_data.begin(),\n                         trace_data.end());\n\n  init_decoder();\n}\n\nvoid ProcessorTraceDecoder::dump_full_trace_data_to_file() {\n  ScopedFd out(\"/tmp/ptdata\", O_WRONLY | O_CREAT | O_TRUNC, 0700);\n  write_all(out, full_trace_data.data(), full_trace_data.size());\n}\n\nvoid ProcessorTraceDecoder::init_decoder() {\n  pt_config config;\n  memset(&config, 0, sizeof(config));\n  config.size = sizeof(config);\n  config.begin = const_cast<uint8_t*>(full_trace_data.data());\n  config.end = const_cast<uint8_t*>(full_trace_data.data() + full_trace_data.size());\n\n  decoder = pt_insn_alloc_decoder(&config);\n  if (!decoder) {\n    FATAL() << \"Cannot create PT decoder\";\n  }\n\n  pt_image* image = pt_insn_get_image(decoder);\n  int status = pt_image_set_callback(image, read_mem_callback, this);\n  if (status < 0) {\n    FATAL() << \"Can't set PT mem callback: \" << pt_errstr(pt_errcode(status));\n  }\n\n  need_sync = true;\n}\n\nstatic vector<uint8_t>* cached_rr_page_for_recording[2];\n\nstatic const vector<uint8_t>& rr_page_for_recording(SupportedArch arch) {\n  if (arch != x86 && arch != x86_64) {\n    FATAL() << \"Unsupported arch \" << arch_name(arch);\n  }\n  int index = arch == x86_64;\n  vector<uint8_t>* page = cached_rr_page_for_recording[index];\n  if (page) {\n    return *page;\n  }\n  page = new vector<uint8_t>();\n  *page = AddressSpace::read_rr_page_for_recording(arch);\n  cached_rr_page_for_recording[index] = page;\n  return *page;\n}\n\nint ProcessorTraceDecoder::read_mem(uint64_t ip, uint8_t *buffer, size_t size) {\n  ssize_t ret = task->read_bytes_fallible(ip, size, buffer);\n  if (ret <= 0) {\n    return ret;\n  }\n  if (mode == IS_RECORDING) {\n    // The rr page instructions differ between recording and replay. The\n    // task's rr page contains the replay values; if we're analyzing\n    // PT data from the recording, make sure to use the rr page instructions\n    // from the recording.\n    const vector<uint8_t>& rr_page_data = rr_page_for_recording(task->arch());\n    remote_ptr<void> rr_page_addr(RR_PAGE_ADDR);\n    remote_ptr<void> ip_addr(ip);\n    replace_in_buffer(MemoryRange(rr_page_addr, rr_page_data.size()),\n                      rr_page_data.data(), MemoryRange(ip, ret), buffer);\n  }\n  replace_in_buffer(MemoryRange(patch_addr, patch_data.size()),\n                    patch_data.data(), MemoryRange(ip, ret), buffer);\n  return ret;\n}\n\nvoid ProcessorTraceDecoder::maybe_process_events(int status) {\n  while (status & pts_event_pending) {\n    pt_event event;\n    status = pt_insn_event(decoder, &event, sizeof(event));\n    if (status < 0) {\n      FATAL() << \"Cannot get PT event: \" << pt_err(status);\n    }\n    switch (event.type) {\n      case ptev_enabled:\n      case ptev_disabled:\n      case ptev_async_disabled:\n      case ptev_exec_mode:\n      case ptev_cbr:\n      case ptev_tsx:\n      case ptev_async_vmcs:\n        break;\n      case ptev_overflow:\n        FATAL() << \"Detected ptev_overflow\";\n        break;\n      default:\n        FATAL() << \"Unhandled event type: \" << event.type;\n        break;\n    }\n  }\n}\n\nstring ProcessorTraceDecoder::internal_error_context_string() {\n  ProcessorTraceDecoder helper(task, full_trace_data, mode);\n  vector<Instruction> instructions;\n  while (true) {\n    int pt_status = 0;\n    Instruction instruction;\n    if (helper.next_instruction(&instruction, &pt_status)) {\n      instructions.push_back(instruction);\n    } else {\n      break;\n    }\n  }\n  size_t start_index = 0;\n  stringstream out;\n  if (instructions.size() > 10000) {\n    start_index = instructions.size() - 10000;\n    out << \"\\n... skipped \" << start_index << \" instructions\";\n  }\n  for (size_t i = start_index; i < instructions.size(); ++i) {\n    out << \"\\n\" << instructions[i].address;\n  }\n  return out.str();\n}\n\nbool ProcessorTraceDecoder::next_instruction(Instruction* out, int* pt_status) {\n  if (!decoder) {\n    return false;\n  }\n\n  while (true) {\n    if (need_sync) {\n      int status = pt_insn_sync_forward(decoder);\n      if (pt_errcode(status) == pte_eos) {\n        return false;\n      }\n      if (status < 0) {\n        if (pt_status) {\n          *pt_status = status;\n          return false;\n        }\n        FATAL() << \"Can't sync forward: \" << pt_err(status)\n            << internal_error_context_string();\n      }\n      need_sync = false;\n      maybe_process_events(status);\n    }\n\n    pt_insn insn;\n    int status = pt_insn_next(decoder, &insn, sizeof(insn));\n    if (pt_errcode(status) == pte_eos) {\n      need_sync = true;\n      continue;\n    }\n    if (status < 0) {\n      if (pt_status) {\n        *pt_status = status;\n        return false;\n      }\n      FATAL() << \"Can't read next instruction: \" << pt_err(status)\n          << internal_error_context_string();\n    }\n    maybe_process_events(status);\n    out->address = insn.ip;\n    return true;\n  }\n}\n\n}\n"
  },
  {
    "path": "src/ProcessorTraceDecoder.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PROCESSOR_TRACE_DECODER_H_\n#define RR_PROCESSOR_TRACE_DECODER_H_\n\n#include <stdint.h>\n\n#include <vector>\n\n#include \"log.h\"\n#include \"Task.h\"\n#include \"remote_code_ptr.h\"\n\nstruct pt_insn_decoder;\n\nnamespace rr {\n\n/**\n * Decodes Intel PT data to produce a control flow trace as a sequence\n * of executed instructions.\n *\n * If intel_pt_decoding was not explicitly set to TRUE via `cmake -Dintel_pt_decoding=TRUE`,\n * then libipt is not linked in and this always returns no instructions.\n */\nclass ProcessorTraceDecoder {\npublic:\n  enum Mode {\n    IS_RECORDING,\n    IS_REPLAY\n  };\n\n  struct Instruction {\n    remote_code_ptr address;\n  };\n\n  ProcessorTraceDecoder(Task* t, const std::vector<uint8_t>& trace_data, Mode mode)\n    : task(t), decoder(nullptr), mode(mode), need_sync(false) {\n    init(trace_data);\n  }\n#ifdef INTEL_PT_DECODING\n  ~ProcessorTraceDecoder();\n  bool next_instruction(Instruction* out, int* pt_status = nullptr);\n#else\n  bool next_instruction(Instruction*, int* = nullptr)\n  {\n    FATAL() << \"Intel PT support not built\";\n    return false;\n  }\n#endif\n\n  // Override a memory range with specific data to be seen by libipt.\n  // This is needed when memory (other than the rr page) is different between\n  // when the PT data was gathered and its current contents.\n  void set_patch(remote_ptr<void> addr, const std::vector<uint8_t>& data) {\n    patch_addr = addr;\n    patch_data = data;\n  }\n  int read_mem(uint64_t ip, uint8_t *buffer, size_t size);\n\nprivate:\n#ifdef INTEL_PT_DECODING\n  void init(const std::vector<uint8_t>& trace_data);\n#else\n  void init(const std::vector<uint8_t>&)\n  {\n    FATAL() << \"Intel PT decoding support not built; run CMake with -Dintel_pt_decoding=TRUE\";\n  }\n#endif\n  void init_decoder();\n\n  void dump_full_trace_data_to_file();\n\n  void maybe_process_events(int status);\n  std::string internal_error_context_string();\n\n  Task* const task;\n  std::vector<uint8_t> full_trace_data;\n  pt_insn_decoder* decoder;\n  remote_ptr<void> patch_addr;\n  std::vector<uint8_t> patch_data;\n  Mode mode;\n  bool need_sync;\n};\n\n} // namespace rr\n\n#endif /* RR_PROCESSOR_TRACE_DECODER_H_ */\n"
  },
  {
    "path": "src/PsCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <map>\n\n#include \"Command.h\"\n#include \"TraceStream.h\"\n#include \"TraceTaskEvent.h\"\n#include \"core.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass PsCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  PsCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static PsCommand singleton;\n};\n\nPsCommand PsCommand::singleton(\"ps\", \" rr ps [<trace_dir>]\\n\");\n\nstatic void print_exec_cmd_line(const TraceTaskEvent& event, FILE* out) {\n  bool first = true;\n  for (auto& word : event.cmd_line()) {\n    fprintf(out, \"%s%s\", first ? \"\" : \" \", word.c_str());\n    first = false;\n  }\n  fprintf(out, \"\\n\");\n}\n\nstatic void update_tid_to_pid_map(map<pid_t, pid_t>& tid_to_pid,\n                                  const TraceTaskEvent& e) {\n  if (e.type() == TraceTaskEvent::CLONE) {\n    if (e.clone_flags() & CLONE_THREAD) {\n      // thread clone. Record thread's pid.\n      tid_to_pid[e.tid()] = tid_to_pid[e.parent_tid()];\n    } else {\n      // Some kind of fork. This task is its own pid.\n      tid_to_pid[e.tid()] = e.tid();\n    }\n  } else if (e.type() == TraceTaskEvent::EXIT) {\n    tid_to_pid.erase(e.tid());\n  }\n}\n\nstatic int count_tids_for_pid(const std::map<pid_t, pid_t> tid_to_pid,\n                              pid_t pid) {\n  int count = 0;\n  for (auto& tp : tid_to_pid) {\n    if (tp.second == pid) {\n      ++count;\n    }\n  }\n  return count;\n}\n\nstatic ssize_t find_cmd_line(pid_t pid, const vector<TraceTaskEvent>& events,\n                             size_t current_event,\n                             const map<pid_t, pid_t> current_tid_to_pid) {\n  map<pid_t, pid_t> tid_to_pid = current_tid_to_pid;\n  for (size_t i = current_event; i < events.size(); ++i) {\n    const TraceTaskEvent& e = events[i];\n    if (e.type() == TraceTaskEvent::EXEC && tid_to_pid[e.tid()] == pid) {\n      return i;\n    }\n    if (e.type() == TraceTaskEvent::EXIT && tid_to_pid[e.tid()] == pid &&\n        count_tids_for_pid(tid_to_pid, pid) == 1) {\n      return -1;\n    }\n    update_tid_to_pid_map(tid_to_pid, e);\n  }\n  return -1;\n}\n\nstring find_exit_code(pid_t pid, const vector<TraceTaskEvent>& events,\n                      size_t current_event,\n                      const map<pid_t, pid_t> current_tid_to_pid) {\n  map<pid_t, pid_t> tid_to_pid = current_tid_to_pid;\n  for (size_t i = current_event; i < events.size(); ++i) {\n    const TraceTaskEvent& e = events[i];\n    if (e.type() == TraceTaskEvent::EXIT && tid_to_pid[e.tid()] == pid &&\n        count_tids_for_pid(tid_to_pid, pid) == 1) {\n      WaitStatus status = e.exit_status();\n      if (status.type() == WaitStatus::EXIT) {\n        return to_string(status.exit_code());\n      }\n      DEBUG_ASSERT(status.type() == WaitStatus::FATAL_SIGNAL);\n      return to_string(-status.fatal_sig());\n    } else if (e.type() == TraceTaskEvent::DETACH && tid_to_pid[e.tid()] == pid &&\n        count_tids_for_pid(tid_to_pid, pid) == 1) {\n      return string(\"detach\");\n    }\n    update_tid_to_pid_map(tid_to_pid, e);\n  }\n  return string(\"none\");\n}\n\nstatic int ps(const string& trace_dir, FILE* out) {\n  TraceReader trace(trace_dir);\n\n  fprintf(out, \"PID\\tPPID\\tEXIT\\tCMD\\n\");\n\n  vector<TraceTaskEvent> events;\n  while (true) {\n    TraceTaskEvent r = trace.read_task_event();\n    if (r.type() == TraceTaskEvent::NONE) {\n      break;\n    }\n    events.push_back(r);\n  }\n\n  if (events.empty() || events[0].type() != TraceTaskEvent::EXEC) {\n    fprintf(stderr, \"Invalid trace\\n\");\n    return 1;\n  }\n\n  map<pid_t, pid_t> tid_to_pid;\n\n  pid_t initial_tid = events[0].tid();\n  tid_to_pid[initial_tid] = initial_tid;\n  fprintf(out, \"%d\\t--\\t%s\\t\", initial_tid,\n          find_exit_code(initial_tid, events, 0, tid_to_pid).c_str());\n  print_exec_cmd_line(events[0], out);\n\n  for (size_t i = 1; i < events.size(); ++i) {\n    auto& e = events[i];\n    update_tid_to_pid_map(tid_to_pid, e);\n\n    if (e.type() == TraceTaskEvent::CLONE &&\n        !(e.clone_flags() & CLONE_THREAD)) {\n      pid_t pid = tid_to_pid[e.tid()];\n      fprintf(out, \"%d\", e.tid());\n      if (e.own_ns_tid() != e.tid()) {\n        fprintf(out, \" (%d)\", e.own_ns_tid());\n      }\n      fprintf(out, \"\\t%d\\t%s\\t\", tid_to_pid[e.parent_tid()],\n              find_exit_code(pid, events, i, tid_to_pid).c_str());\n\n      ssize_t cmd_line_index = find_cmd_line(pid, events, i, tid_to_pid);\n      if (cmd_line_index < 0) {\n        // The main thread exited. All other threads must too, so there\n        // is no more opportunity for e's pid to exec.\n        fprintf(out, \"(forked without exec)\\n\");\n      } else {\n        print_exec_cmd_line(events[cmd_line_index], out);\n      }\n    }\n  }\n  return 0;\n}\n\nint PsCommand::run(vector<string>& args) {\n  while (parse_global_option(args)) {\n  }\n\n  string trace_dir;\n  if (!parse_optional_trace_dir(args, &trace_dir)) {\n    print_help(stderr);\n    return 1;\n  }\n\n  return ps(trace_dir, stdout);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/RRPageMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_RR_PAGE_MONITOR_H_\n#define RR_RR_PAGE_MONITOR_H_\n\n#include \"FileMonitor.h\"\n#include \"TraceStream.h\"\n\nnamespace rr {\n\n/**\n * RRPageMonitor gets installed upon any open of the librrpage.so preload library.\n * If this file gets mmaped, rr will attempt to map it to coincide with the\n * required fixed location for the rr page.\n */\nclass RRPageMonitor : public FileMonitor {\npublic:\n  RRPageMonitor() : FileMonitor() {};\n\n  virtual Type type() override { return RRPage; }\n};\n\nstatic_assert(TraceReader::SpecialLibRRpage != 0,\n  \"Remember to delete this if support for the quirk is ever dropped\");\n\n} // namespace rr\n\n#endif /* RR_RR_PAGE_MONITOR_H_ */\n"
  },
  {
    "path": "src/RecordCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"RecordCommand.h\"\n\n#include <linux/capability.h>\n#include <spawn.h>\n#include <sys/prctl.h>\n#include <sys/wait.h>\n#include <sysexits.h>\n#include <time.h>\n\n#include \"preload/preload_interface.h\"\n\n#include \"Flags.h\"\n#include \"RecordSession.h\"\n#include \"StringVectorToCharArray.h\"\n#include \"WaitManager.h\"\n#include \"WaitStatus.h\"\n#include \"core.h\"\n#include \"git_revision.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nRecordCommand RecordCommand::singleton(\n    \"record\",\n    \" rr record [OPTION]... <exe> [exe-args]...\\n\"\n    \"  -c, --num-cpu-ticks=<NUM>  maximum number of 'CPU ticks' (currently \\n\"\n    \"                             retired conditional branches) to allow a \\n\"\n    \"                             task to run before interrupting it\\n\"\n    \"  --disable-avx-512          Masks out the CPUID bits for AVX512\\n\"\n    \"                             This can improve trace portability\\n\"\n    \"  --disable-cpuid-features <CCC>[,<DDD>]\\n\"\n    \"                             Mask out CPUID EAX=1 feature bits\\n\"\n    \"                             <CCC>: Bitmask of bits to clear from ECX\\n\"\n    \"                             <DDD>: Bitmask of bits to clear from EDX\\n\"\n    \"  --disable-cpuid-features-ext <BBB>[,<CCC>[,<DDD>]]\\n\"\n    \"                             Mask out CPUID EAX=7,ECX=0 feature bits\\n\"\n    \"                             <BBB>: Bitmask of bits to clear from EBX\\n\"\n    \"                             <CCC>: Bitmask of bits to clear from ECX\\n\"\n    \"                             <DDD>: Bitmask of bits to clear from EDX\\n\"\n    \"  --disable-cpuid-features-xsave <AAA>\\n\"\n    \"                             Mask out CPUID EAX=0xD,ECX=1 feature bits\\n\"\n    \"                             <AAA>: Bitmask of bits to clear from EAX\\n\"\n    \"  -h, --chaos                randomize scheduling decisions to try to \\n\"\n    \"                             reproduce bugs\\n\"\n    \"  -n, --no-syscall-buffer    disable syscall buffering even if it would\\n\"\n    \"                             otherwise be used\\n\"\n    \"  --no-preload               disable the preload library; useful when\\n\"\n    \"                             tracee uses a non-standard C ABI but may\\n\"\n    \"                             cause replay issues. Implies -n.\\n\"\n    \"  --no-file-cloning          disable file cloning for mmapped files\\n\"\n    \"  --no-read-cloning          disable file-block cloning for syscallbuf\\n\"\n    \"                             reads\\n\"\n    \"  --num-cores=N              pretend to have N cores (rr will still\\n\"\n    \"                             only run on a single core). Overrides\\n\"\n    \"                             random setting from --chaos.\\n\"\n    \"  -o, --output-trace-dir<DIR> set the output trace directory.\\n\"\n    \"                             _RR_TRACE_DIR gets ignored.\\n\"\n    \"                             Directory name is given name, not the\\n\"\n    \"                             application name.\\n\"\n    \"  -p --print-trace-dir=<NUM> print trace directory followed by a newline\\n\"\n    \"                             to given file descriptor\\n\"\n    \"  --syscall-buffer-sig=<NUM> the signal used for communication with the\\n\"\n    \"                             syscall buffer. SIGPWR by default, unused\\n\"\n    \"                             if --no-syscall-buffer is passed\\n\"\n    \"  -s, --always-switch        Context-switch after every rr event\\n\"\n    \"                             (mainly for testing)\\n\"\n    \"  -t, --continue-through-signal=<SIG>\\n\"\n    \"                             Unhandled <SIG> signals will be ignored\\n\"\n    \"                             instead of terminating the program. The\\n\"\n    \"                             signal will still be delivered for user\\n\"\n    \"                             handlers and debugging.\\n\"\n    \"  --intel-pt                 Enable PT collection of control flow\\n\"\n    \"                             (for debugging rr)\\n\"\n    \"  -u, --cpu-unbound          allow tracees to run on any virtual CPU.\\n\"\n    \"                             Default is to bind to a random CPU.  This \"\n    \"option\\n\"\n    \"                             can cause replay divergence: use with\\n\"\n    \"                             caution.\\n\"\n    \"  --bind-to-cpu=<CORE>       Bind to a CPU core. <CORE> can be 'any',\\n\"\n    \"                             'p-core' (default), or a specific number.\\n\"\n    \"  -v, --env=NAME=VALUE       value to add to the environment of the\\n\"\n    \"                             tracee. There can be any number of these.\\n\"\n    \"  -w, --wait                 Wait for all child processes to exit, not\\n\"\n    \"                             just the initial process.\\n\"\n    \"  --nested=<value>           Control behavior when run inside an outer\\n\"\n    \"                             rr recording. Default: exit with error\\n\"\n    \"  --nested=ignore            Directly start child process so it's part\\n\"\n    \"                             of the outer recording\\n\"\n    \"  --nested=detach            Start a separate recording session.\\n\"\n    \"                             Must not share memory with the outer.\\n\"\n    \"  --nested=release           Run the child without recording it.\\n\"\n    \"                             Must not share memory with the outer.\\n\"\n    \"  --setuid-sudo              If running under sudo, pretend to be the\\n\"\n    \"                             user that ran sudo rather than root. This\\n\"\n    \"                             allows recording setuid/setcap binaries.\\n\"\n    \"  --trace-id                 Sets the trace id to the specified id.\\n\"\n    \"  --copy-preload-src         Copy preload sources to trace dir\\n\"\n    \"  --stap-sdt                 Enables the use of SystemTap statically-\\n\"\n    \"                             defined tracepoints\\n\"\n    \"  --asan                     Override heuristics and always enable ASAN\\n\"\n    \"                             compatibility.\\n\"\n    \"  --tsan                     Override heuristics and always enable TSAN\\n\"\n    \"                             compatibility.\\n\"\n    \"  --check-outside-mmaps      Try to identify files that are mapped outside\\n\"\n    \"                             of the trace and could cause diversions.\\n\");\n\nstruct RecordFlags {\n  vector<string> extra_env;\n\n  /* Max counter value before the scheduler interrupts a tracee. */\n  Ticks max_ticks;\n\n  /* Whenever |ignore_sig| is pending for a tracee, decline to\n   * deliver it. */\n  int ignore_sig;\n  /* Whenever |continue_through_sig| is delivered to a tracee, if there is no\n   * user handler and the signal would terminate the program, just ignore it. */\n  int continue_through_sig;\n\n  /* Whether to use syscall buffering optimization during recording. */\n  RecordSession::SyscallBuffering use_syscall_buffer;\n\n  /* If nonzero, the desired syscall buffer size. Must be a multiple of the page\n   * size.\n   */\n  size_t syscall_buffer_size;\n\n  /* CPUID features to disable */\n  DisableCPUIDFeatures disable_cpuid_features;\n\n  int print_trace_dir;\n\n  string output_trace_dir;\n\n  /* Whether to use file-cloning optimization during recording. */\n  bool use_file_cloning;\n\n  /* Whether to use read-cloning optimization during recording. */\n  bool use_read_cloning;\n\n  /* Whether tracee processes in record and replay are allowed\n   * to run on any logical CPU. */\n  BindCPU bind_cpu;\n\n  /* True if we should context switch after every rr event */\n  bool always_switch;\n\n  /* Whether to enable chaos mode in the scheduler */\n  bool chaos;\n\n  /* Controls number of cores reported to recorded process. */\n  int num_cores;\n\n  /* True if we should wait for all processes to exit before finishing\n   * recording. */\n  bool wait_for_all;\n\n  /* Start child process directly if run under nested rr recording */\n  NestedBehavior nested;\n\n  bool scarce_fds;\n\n  bool setuid_sudo;\n\n  unique_ptr<TraceUuid> trace_id;\n\n  /* Copy preload sources to trace dir */\n  bool copy_preload_src;\n\n  /* The signal to use for syscallbuf desched events */\n  int syscallbuf_desched_sig;\n\n  /* True if we should load the audit library for SystemTap SDT support. */\n  bool stap_sdt;\n\n  /* True if we should unmap the vdso */\n  bool unmap_vdso;\n\n  /* True if we should always enable ASAN compatibility. */\n  bool asan;\n\n  /* True if we should always enable TSAN compatibility. */\n  bool tsan;\n\n  /* True if we should enable collection of control flow\n     with PT. */\n  bool intel_pt;\n\n  /* True if we should check files being mapped outside of the recording. */\n  bool check_outside_mmaps;\n\n  /* True if we should not add the preload library to LD_PRELOAD. */\n  bool no_preload = false;\n\n  RecordFlags()\n      : max_ticks(Scheduler::DEFAULT_MAX_TICKS),\n        ignore_sig(0),\n        continue_through_sig(0),\n        use_syscall_buffer(RecordSession::ENABLE_SYSCALL_BUF),\n        syscall_buffer_size(0),\n        print_trace_dir(-1),\n        output_trace_dir(\"\"),\n        use_file_cloning(true),\n        use_read_cloning(true),\n        bind_cpu(BindCPU::PREFER_PERF_CORE),\n        always_switch(false),\n        chaos(false),\n        num_cores(0),\n        wait_for_all(false),\n        nested(NESTED_ERROR),\n        scarce_fds(false),\n        setuid_sudo(false),\n        copy_preload_src(false),\n        syscallbuf_desched_sig(SYSCALLBUF_DEFAULT_DESCHED_SIGNAL),\n        stap_sdt(false),\n        unmap_vdso(false),\n        asan(false),\n        tsan(false),\n        intel_pt(false),\n        check_outside_mmaps(false) {}\n};\n\nstatic void parse_signal_name(ParsedOption& opt) {\n  if (opt.int_value != INT64_MIN) {\n    return;\n  }\n\n  for (int i = 1; i < _NSIG; i++) {\n    std::string signame = signal_name(i);\n    if (signame == opt.value) {\n      opt.int_value = i;\n      return;\n    }\n    DEBUG_ASSERT(signame[0] == 'S' && signame[1] == 'I' && signame[2] == 'G');\n    if (signame.substr(3) == opt.value) {\n      opt.int_value = i;\n      return;\n    }\n  }\n}\n\nstatic vector<uint32_t> parse_feature_bits(ParsedOption& opt) {\n  vector<uint32_t> ret;\n  const char* p = opt.value.c_str();\n  while (*p) {\n    char* endptr;\n    unsigned long long v = strtoull(p, &endptr, 0);\n    if (v > UINT32_MAX || (*endptr && *endptr != ',')) {\n      return vector<uint32_t>();\n    }\n    ret.push_back(v);\n    p = *endptr == ',' ? endptr + 1 : endptr;\n  }\n  return ret;\n}\n\nstatic bool parse_record_arg(vector<string>& args, RecordFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = {\n    { 0, \"no-read-cloning\", NO_PARAMETER },\n    { 1, \"no-file-cloning\", NO_PARAMETER },\n    { 2, \"syscall-buffer-size\", HAS_PARAMETER },\n    { 3, \"nested\", HAS_PARAMETER },\n    { 4, \"scarce-fds\", NO_PARAMETER },\n    { 5, \"setuid-sudo\", NO_PARAMETER },\n    { 6, \"bind-to-cpu\", HAS_PARAMETER },\n    { 7, \"disable-cpuid-features\", HAS_PARAMETER },\n    { 8, \"disable-cpuid-features-ext\", HAS_PARAMETER },\n    { 9, \"disable-cpuid-features-xsave\", HAS_PARAMETER },\n    { 10, \"num-cores\", HAS_PARAMETER },\n    { 11, \"trace-id\", HAS_PARAMETER },\n    { 12, \"copy-preload-src\", NO_PARAMETER },\n    { 13, \"syscall-buffer-sig\", HAS_PARAMETER },\n    { 14, \"stap-sdt\", NO_PARAMETER },\n    { 15, \"unmap-vdso\", NO_PARAMETER },\n    { 16, \"disable-avx-512\", NO_PARAMETER },\n    { 17, \"asan\", NO_PARAMETER },\n    { 18, \"tsan\", NO_PARAMETER },\n    { 19, \"intel-pt\", NO_PARAMETER },\n    { 20, \"check-outside-mmaps\", NO_PARAMETER },\n    { 21, \"no-preload\", NO_PARAMETER },\n    { 'c', \"num-cpu-ticks\", HAS_PARAMETER },\n    { 'h', \"chaos\", NO_PARAMETER },\n    { 'i', \"ignore-signal\", HAS_PARAMETER },\n    { 'n', \"no-syscall-buffer\", NO_PARAMETER },\n    { 'p', \"print-trace-dir\", HAS_PARAMETER },\n    { 'o', \"output-trace-dir\", HAS_PARAMETER },\n    { 's', \"always-switch\", NO_PARAMETER },\n    { 't', \"continue-through-signal\", HAS_PARAMETER },\n    { 'u', \"cpu-unbound\", NO_PARAMETER },\n    { 'v', \"env\", HAS_PARAMETER },\n    { 'w', \"wait\", NO_PARAMETER }};\n  ParsedOption opt;\n  auto args_copy = args;\n  if (!Command::parse_option(args_copy, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 'c':\n      if (!opt.verify_valid_int(1, Scheduler::MAX_MAX_TICKS)) {\n        return false;\n      }\n      flags.max_ticks = opt.int_value;\n      break;\n    case 'h':\n      LOG(info) << \"Enabled chaos mode\";\n      flags.chaos = true;\n      break;\n    case 'i':\n      parse_signal_name(opt);\n      if (!opt.verify_valid_int(1, _NSIG - 1)) {\n        return false;\n      }\n      flags.ignore_sig = opt.int_value;\n      break;\n    case 'n':\n      flags.use_syscall_buffer = RecordSession::DISABLE_SYSCALL_BUF;\n      break;\n    case 'p':\n      if (!opt.verify_valid_int(0, INT32_MAX)) {\n        return false;\n      }\n      flags.print_trace_dir = opt.int_value;\n      break;\n    case 'o':\n      flags.output_trace_dir = opt.value;\n      break;\n    case 0:\n      flags.use_read_cloning = false;\n      break;\n    case 1:\n      flags.use_file_cloning = false;\n      break;\n    case 2:\n      if (!opt.verify_valid_int(4, 1024 * 1024)) {\n        return false;\n      }\n      flags.syscall_buffer_size = ceil_page_size(opt.int_value * 1024);\n      break;\n    case 3:\n      if (opt.value == \"default\" || opt.value == \"error\") {\n        flags.nested = NESTED_ERROR;\n      } else if (opt.value == \"ignore\") {\n        flags.nested = NESTED_IGNORE;\n      } else if (opt.value == \"detach\") {\n        flags.nested = NESTED_DETACH;\n      } else if (opt.value == \"release\") {\n        flags.nested = NESTED_RELEASE;\n      } else {\n        LOG(warn) << \"Unknown nesting behavior `\" << opt.value << \"`\";\n        flags.nested = NESTED_ERROR;\n      }\n      break;\n    case 4:\n      flags.scarce_fds = true;\n      break;\n    case 5:\n      flags.setuid_sudo = true;\n      break;\n    case 6:\n      if (opt.value == \"any\") {\n        flags.bind_cpu = BindCPU(BindCPU::ANY);\n      } else if (opt.value == \"p-core\") {\n        flags.bind_cpu = BindCPU(BindCPU::PREFER_PERF_CORE);\n      } else {\n        if (!opt.verify_valid_int(0, INT32_MAX)) {\n          return false;\n        }\n        flags.bind_cpu = BindCPU(opt.int_value);\n      }\n      break;\n    case 7: {\n      vector<uint32_t> bits = parse_feature_bits(opt);\n      if (bits.empty() || bits.size() > 2) {\n        return false;\n      }\n      flags.disable_cpuid_features.features_ecx = bits[0];\n      if (bits.size() > 1) {\n        flags.disable_cpuid_features.features_edx = bits[1];\n      }\n      break;\n    }\n    case 8: {\n      vector<uint32_t> bits = parse_feature_bits(opt);\n      if (bits.empty() || bits.size() > 3) {\n        return false;\n      }\n      flags.disable_cpuid_features.extended_features_ebx = bits[0];\n      if (bits.size() > 1) {\n        flags.disable_cpuid_features.extended_features_ecx = bits[1];\n        if (bits.size() > 2) {\n          flags.disable_cpuid_features.extended_features_edx = bits[2];\n        }\n      }\n      break;\n    }\n    case 9: {\n      vector<uint32_t> bits = parse_feature_bits(opt);\n      if (bits.size() != 1) {\n        return false;\n      }\n      flags.disable_cpuid_features.xsave_features_eax = bits[0];\n      break;\n    }\n    case 10: {\n      if (!opt.verify_valid_int(1, 128)) {\n        return false;\n      }\n      flags.num_cores = opt.int_value;\n      break;\n    }\n    case 11: {\n      const uint8_t SUM_GROUP_LENS[5] = { 8, 12, 16, 20, 32 };\n      /* Parse UUIDs from string form optionally with hyphens */\n      uint8_t digit = 0; // This counts only hex digits (i.e. not hyphens)\n      uint8_t group = 0;\n      uint8_t acc = 0;\n      unique_ptr<TraceUuid> buf(new TraceUuid);\n      auto it = opt.value.begin();\n      while (it < opt.value.end()) {\n        auto c = *it;\n\n        if (digit > SUM_GROUP_LENS[4]) {\n          return false;\n        }\n\n        if (digit % 2 == 0) {\n          // First digit of the byte.\n          if ('0' <= c && c <= '9') {\n            acc = c - '0';\n          } else if ('a' <= c && c <= 'f') {\n            acc = c - 'a' + 10;\n          } else if ('A' <= c && c <= 'F') {\n            acc = c - 'A' + 10;\n          } else if (c == '-') {\n            // Group delimiter.\n            if (SUM_GROUP_LENS[group] != digit) {\n              return false;\n            }\n            ++group;\n            ++it;\n            continue;\n          } else {\n            return false;\n          }\n        } else {\n          // Second digit of the byte.\n          acc <<= 4;\n          if ('0' <= c && c <= '9') {\n            acc += c - '0';\n          } else if ('a' <= c && c <= 'f') {\n            acc += c - 'a' + 10;\n          } else if ('A' <= c && c <= 'F') {\n            acc += c - 'A' + 10;\n          } else {\n            return false;\n          }\n\n          buf->bytes[digit / 2] = acc;\n        }\n\n        ++digit;\n        ++it;\n      }\n\n      if (SUM_GROUP_LENS[4] != digit) {\n        return false;\n      }\n\n      flags.trace_id.swap(buf);\n      break;\n    }\n    case 12:\n      flags.copy_preload_src = true;\n      break;\n    case 13:\n      parse_signal_name(opt);\n      if (!opt.verify_valid_int(1, _NSIG - 1)) {\n        return false;\n      }\n      flags.syscallbuf_desched_sig = opt.int_value;\n      break;\n    case 14:\n      flags.stap_sdt = true;\n      break;\n    case 15:\n      flags.unmap_vdso = true;\n      break;\n    case 16:\n      flags.disable_cpuid_features.extended_features_ebx |= 0xdc230000;\n      flags.disable_cpuid_features.extended_features_ecx |= 0x00002c42;\n      flags.disable_cpuid_features.extended_features_edx |= 0x0000000c;\n      break;\n    case 17:\n      flags.asan = true;\n      break;\n    case 18:\n      flags.tsan = true;\n      break;\n    case 19:\n      flags.intel_pt = true;\n      break;\n    case 20:\n      flags.check_outside_mmaps = true;\n      break;\n    case 21:\n      flags.no_preload = true;\n      break;\n    case 's':\n      flags.always_switch = true;\n      break;\n    case 't':\n      parse_signal_name(opt);\n      if (!opt.verify_valid_int(1, _NSIG - 1)) {\n        return false;\n      }\n      flags.continue_through_sig = opt.int_value;\n      break;\n    case 'u':\n      flags.bind_cpu = BindCPU(BindCPU::UNBOUND);\n      break;\n    case 'v':\n      flags.extra_env.push_back(opt.value);\n      break;\n    case 'w':\n      flags.wait_for_all = true;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown option\");\n  }\n\n  args = args_copy;\n  return true;\n}\n\nstatic volatile double term_requested;\nstatic bool did_print_reassurance = false;\n\nstatic const double TRACEE_SIGTERM_RESPONSE_MAX_TIME = 5;\nstatic const double RR_SIGKILL_GRACE_TIME = 5;\n\n/**\n * A terminating signal was received.\n *\n * First we forward it to the tracee. Then if the tracee is still\n * running after TRACEE_SIGTERM_RESPONSE_MAX_TIME, we kill it with SIGKILL.\n * If a term request remains pending for more than one second,\n * then assume rr is wedged and abort().\n *\n * Note that this is called in a signal handler and could also\n * be called off the main thread.\n */\nstatic void handle_SIGTERM(__attribute__((unused)) int sig) {\n  // Don't use LOG() here because we're in a signal handler. If we do anything\n  // that could allocate, we could deadlock.\n  if (term_requested > 0) {\n    double now = monotonic_now_sec();\n    if (now - term_requested > 1 + TRACEE_SIGTERM_RESPONSE_MAX_TIME) {\n      if (!did_print_reassurance) {\n        static const char msg[] =\n          \"[rr] Tracee failed to exit within 1s after SIGKILL. Recording will forcibly terminate in 4s.\\n\";\n        did_print_reassurance = true;\n        write_all(STDERR_FILENO, msg, sizeof(msg) - 1);\n      } else if (now - term_requested > RR_SIGKILL_GRACE_TIME + TRACEE_SIGTERM_RESPONSE_MAX_TIME) {\n        errno = 0;\n        FATAL() << \"SIGTERM grace period expired\";\n      }\n    }\n  } else {\n    term_requested = monotonic_now_sec();\n  }\n}\n\n/**\n * Something segfaulted - this is probably a bug in rr. Try to at least\n * give a stacktrace.\n */\nstatic void handle_SIGSEGV(__attribute__((unused)) int sig) {\n  errno = 0;\n  FATAL() << \"rr itself crashed (SIGSEGV). This shouldn't happen!\";\n}\n\nstatic void install_signal_handlers(void) {\n  struct sigaction sa;\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_handler = handle_SIGTERM;\n  sigaction(SIGTERM, &sa, nullptr);\n\n  sa.sa_handler = handle_SIGSEGV;\n  sigaction(SIGSEGV, &sa, nullptr);\n\n  sa.sa_handler = SIG_IGN;\n  sigaction(SIGHUP, &sa, nullptr);\n  sigaction(SIGINT, &sa, nullptr);\n  sigaction(SIGABRT, &sa, nullptr);\n  sigaction(SIGQUIT, &sa, nullptr);\n  sigaction(SIGTRAP, &sa, nullptr);\n  sigaction(SIGTTIN, &sa, nullptr);\n  sigaction(SIGTTOU, &sa, nullptr);\n  sigaction(SIGWINCH, &sa, nullptr);\n}\n\nstatic void setup_session_from_flags(RecordSession& session,\n                                     const RecordFlags& flags) {\n  session.scheduler().set_max_ticks(flags.max_ticks);\n  session.scheduler().set_always_switch(flags.always_switch);\n  session.set_enable_chaos(flags.chaos);\n  if (flags.num_cores) {\n    // Set the number of cores reported, possibly overriding the chaos mode\n    // setting.\n    session.set_num_cores(flags.num_cores);\n  }\n  session.set_use_read_cloning(flags.use_read_cloning);\n  session.set_use_file_cloning(flags.use_file_cloning);\n  session.set_ignore_sig(flags.ignore_sig);\n  session.set_continue_through_sig(flags.continue_through_sig);\n  session.set_wait_for_all(flags.wait_for_all);\n  if (flags.syscall_buffer_size > 0) {\n    session.set_syscall_buffer_size(flags.syscall_buffer_size);\n  }\n\n  if (flags.scarce_fds) {\n    for (int i = 0; i < 950; ++i) {\n      open(\"/dev/null\", O_RDONLY);\n    }\n  }\n}\n\nstatic RecordSession* static_session;\n\n// This can be called during debugging to close the trace so it can be used\n// later.\nvoid force_close_record_session() {\n  if (static_session) {\n    static_session->close_trace_writer(TraceWriter::CLOSE_ERROR);\n  }\n}\n\nstatic void copy_preload_sources_to_trace(const string& trace_dir) {\n  string files_dir = trace_dir + \"/files.rr\";\n  mkdir(files_dir.c_str(), 0700);\n  pid_t pid;\n  string dest_path = files_dir + \"/librrpreload.zip\";\n  string src_path = resource_path() + \"share/rr/src\";\n  char zip[] = \"zip\";\n  char r[] = \"-r\";\n  char j[] = \"-j\";\n  char* argv[] = {\n    zip, r, j,\n    const_cast<char*>(dest_path.c_str()),\n    const_cast<char*>(src_path.c_str()),\n    NULL\n  };\n  posix_spawn_file_actions_t actions;\n  posix_spawn_file_actions_init(&actions);\n  posix_spawn_file_actions_addopen(&actions, STDOUT_FILENO, \"/dev/null\", O_RDONLY, 0);\n  posix_spawn_file_actions_addopen(&actions, STDERR_FILENO, \"/dev/null\", O_RDONLY, 0);\n  int ret = posix_spawnp(&pid, argv[0], &actions, NULL, argv, environ);\n  if (ret) {\n    FATAL() << \"Can't spawn 'zip'\";\n  }\n  posix_spawn_file_actions_destroy(&actions);\n  WaitResult result = WaitManager::wait_exit(WaitOptions(pid));\n  if (result.code != WAIT_OK) {\n    FATAL() << \"Wait failed\";\n  }\n  LOG(info) << \"Got zip status \" << result.status;\n}\n\nstatic void save_rr_git_revision(const string& trace_dir) {\n  string files_dir = trace_dir + \"/files.rr\";\n  mkdir(files_dir.c_str(), 0700);\n  string dest_path = files_dir + \"/rr_git_revision\";\n  ScopedFd fd(dest_path.c_str(), O_CREAT | O_WRONLY, 0600);\n  ssize_t written = write(fd, GIT_REVISION, sizeof(GIT_REVISION) - 1);\n  if (written != sizeof(GIT_REVISION) - 1) {\n    FATAL() << \"Can't write GIT_REVISION\";\n  }\n}\n\nstatic void* repeat_SIGTERM(__attribute__((unused)) void* p) {\n  sleep_time(TRACEE_SIGTERM_RESPONSE_MAX_TIME);\n  /* send another SIGTERM so we wake up and SIGKILL our tracees */\n  kill(getpid(), SIGTERM);\n  sleep_time(RR_SIGKILL_GRACE_TIME);\n  /* Ok, now we're really wedged, just repeatedly SIGTERM until we're out */\n  while (1) {\n    kill(getpid(), SIGTERM);\n    sleep_time(0.01);\n  }\n}\n\nstatic WaitStatus record(const vector<string>& args, const RecordFlags& flags) {\n  LOG(info) << \"Start recording...\";\n\n  auto session = RecordSession::create(\n      args, flags.extra_env, flags.disable_cpuid_features,\n      flags.use_syscall_buffer, flags.syscallbuf_desched_sig, flags.bind_cpu,\n      flags.output_trace_dir, flags.trace_id.get(), flags.stap_sdt,\n      flags.unmap_vdso, flags.asan, flags.tsan, flags.intel_pt,\n      flags.check_outside_mmaps, flags.no_preload);\n  setup_session_from_flags(*session, flags);\n\n  static_session = session.get();\n\n  if (flags.print_trace_dir >= 0) {\n    const string& dir = session->trace_writer().dir();\n    write_all(flags.print_trace_dir, dir.c_str(), dir.size());\n    write_all(flags.print_trace_dir, \"\\n\", 1);\n  }\n\n  if (flags.copy_preload_src) {\n    const string& dir = session->trace_writer().dir();\n    copy_preload_sources_to_trace(dir);\n    save_rr_git_revision(dir);\n  }\n\n  // Install signal handlers after creating the session, to ensure they're not\n  // inherited by the tracee.\n  install_signal_handlers();\n\n  RecordSession::RecordResult step_result;\n  bool did_forward_SIGTERM = false;\n  bool did_term_detached_tasks = false;\n  pthread_t term_repeater_thread;\n  do {\n    bool done_initial_exec = session->done_initial_exec();\n    step_result = session->record_step();\n    // Only create latest-trace symlink if --output-trace-dir is not being used\n    if (!done_initial_exec && session->done_initial_exec() && flags.output_trace_dir.empty()) {\n      session->trace_writer().make_latest_trace();\n    }\n    if (term_requested) {\n      if (monotonic_now_sec() - term_requested > TRACEE_SIGTERM_RESPONSE_MAX_TIME) {\n        /* time ran out for the tracee to respond to SIGTERM; kill everything */\n        session->terminate_tracees();\n      } else if (!did_forward_SIGTERM) {\n        session->forward_SIGTERM();\n        // Start a thread to send a SIGTERM to ourselves (again)\n        // in case the tracee doesn't respond to SIGTERM.\n        pthread_create(&term_repeater_thread, NULL, repeat_SIGTERM, NULL);\n        did_forward_SIGTERM = true;\n      }\n      /* Forward SIGTERM to detached tasks immediately */\n      if (!did_term_detached_tasks) {\n        session->term_detached_tasks();\n        did_term_detached_tasks = true;\n      }\n    }\n  } while (step_result.status == RecordSession::STEP_CONTINUE);\n\n  session->close_trace_writer(TraceWriter::CLOSE_OK);\n  static_session = nullptr;\n\n  switch (step_result.status) {\n    case RecordSession::STEP_CONTINUE:\n      // SIGTERM interrupted us.\n      return WaitStatus::for_fatal_sig(SIGTERM);\n\n    case RecordSession::STEP_EXITED:\n      return step_result.exit_status;\n\n    case RecordSession::STEP_SPAWN_FAILED:\n      cerr << \"\\n\" << step_result.failure_message << \"\\n\";\n      return WaitStatus::for_exit_code(EX_UNAVAILABLE);\n\n    default:\n      DEBUG_ASSERT(0 && \"Unknown exit status\");\n      return WaitStatus();\n  }\n}\n\nstatic void exec_child(vector<string>& args) {\n  execvp(args[0].c_str(), StringVectorToCharArray(args).get());\n  // That failed. Try executing the file directly.\n  execv(args[0].c_str(), StringVectorToCharArray(args).get());\n  switch (errno) {\n    case ENOENT:\n      fprintf(stderr, \"execv failed: '%s' (or interpreter) not found (%s)\",\n              args[0].c_str(), errno_name(errno).c_str());\n      break;\n    default:\n      fprintf(stderr, \"execv of '%s' failed (%s)\", args[0].c_str(),\n              errno_name(errno).c_str());\n      break;\n  }\n  _exit(1);\n  // Never returns!\n}\n\nstatic void reset_uid_sudo() {\n  // Let's change our uids now. We do keep capabilities though, since that's\n  // the point of the exercise. The first exec will reset both the keepcaps,\n  // and the capabilities in the child\n  std::string sudo_uid = getenv(\"SUDO_UID\");\n  std::string sudo_gid = getenv(\"SUDO_GID\");\n  DEBUG_ASSERT(!sudo_uid.empty() && !sudo_gid.empty());\n  uid_t tracee_uid = stoi(sudo_uid);\n  gid_t tracee_gid = stoi(sudo_gid);\n  // Setuid will drop effective capabilities. Save them now and set them\n  // back after\n  struct NativeArch::cap_header header = {.version =\n                                              _LINUX_CAPABILITY_VERSION_3,\n                                          .pid = 0 };\n  struct NativeArch::cap_data data[2];\n  if (syscall(NativeArch::capget, &header, data) != 0) {\n    FATAL() << \"FAILED to read capabilities\";\n  }\n  if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {\n    FATAL() << \"FAILED to set keepcaps\";\n  }\n  if (setgid(tracee_gid) != 0) {\n    FATAL() << \"FAILED to setgid to sudo group\";\n  }\n  if (setuid(tracee_uid) != 0) {\n    FATAL() << \"FAILED to setuid to sudo user\";\n  }\n  if (syscall(NativeArch::capset, &header, data) != 0) {\n    FATAL() << \"FAILED to set capabilities\";\n  }\n  // Just make sure the ambient set is cleared, to avoid polluting the tracee\n  prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);\n}\n\nstatic ScopedFd open_controlling_terminal_if_foreground_process_group_leader() {\n  char path[L_ctermid + 1];\n  ctermid(path);\n  ScopedFd terminal_fd(path, O_RDONLY);\n  if (terminal_fd.is_open()) {\n    pid_t fg_process_group = tcgetpgrp(terminal_fd);\n    if (fg_process_group != getpid()) {\n      terminal_fd.close();\n    }\n  }\n  return terminal_fd;\n}\n\nstatic void detach_teleport() {\n  int ret = syscall(SYS_rrcall_detach_teleport, (uintptr_t)0, (uintptr_t)0,\n    (uintptr_t)0, (uintptr_t)0, (uintptr_t)0, (uintptr_t)0);\n  if (ret < 0) {\n    FATAL() << \"Failed to detach from parent rr\";\n  }\n  if (running_under_rr(false)) {\n    FATAL() << \"Detaching from parent rr did not work\";\n  }\n}\n\nint RecordCommand::run(vector<string>& args) {\n  RecordFlags flags;\n  while (parse_record_arg(args, flags)) {\n  }\n\n  if (running_under_rr()) {\n    switch (flags.nested) {\n      case NESTED_IGNORE:\n        exec_child(args);\n        return 1;\n      case NESTED_DETACH:\n      case NESTED_RELEASE: {\n        bool is_process_group_leader = getpgrp() == getpid();\n        ScopedFd terminal_fd = open_controlling_terminal_if_foreground_process_group_leader();\n\n        detach_teleport();\n\n        if (is_process_group_leader) {\n          setpgid(0, 0);\n        }\n        if (terminal_fd.is_open()) {\n          struct sigaction sa;\n          struct sigaction sa_old;\n          memset(&sa, 0, sizeof(sa));\n          sa.sa_handler = SIG_IGN;\n          // Ignore SIGTTOU while we change settings, we don't want it to stop us\n          sigaction(SIGTTOU, &sa, &sa_old);\n          int ret = tcsetpgrp(terminal_fd, getpid());\n          if (ret) {\n            LOG(warn) << \"Failed to make ourselves the foreground process: \" << errno_name(errno);\n          }\n          sigaction(SIGTTOU, &sa_old, nullptr);\n        }\n\n        if (flags.nested == NESTED_RELEASE) {\n          exec_child(args);\n          return 1;\n        }\n        // running_under_rr() changed - respect the log specification from RR_LOG\n        // just as if we hadn't been running under rr.\n        apply_log_spec_from_env();\n        break;\n      }\n      default:\n        fprintf(stderr, \"rr: cannot run rr recording under rr. Exiting.\\n\"\n                        \"Use `rr record --nested=ignore` to start the child \"\n                        \"process directly.\\n\");\n        return 1;\n    }\n  }\n\n  if (!verify_not_option(args) || args.size() == 0) {\n    print_help(stderr);\n    return 1;\n  }\n\n  assert_prerequisites(flags.use_syscall_buffer);\n\n  if (flags.setuid_sudo) {\n    if (geteuid() != 0 || getenv(\"SUDO_UID\") == NULL) {\n      fprintf(stderr, \"rr: --setuid-sudo option may only be used under sudo.\\n\"\n                      \"Re-run as `sudo -EP --preserve-env=HOME rr record --setuid-sudo` to \"\n                      \"record privileged executables.\\n\");\n      return 1;\n    }\n\n    reset_uid_sudo();\n  }\n\n  if (flags.chaos) {\n    // Add up to one page worth of random padding to the environment to induce\n    // a variety of possible stack pointer offsets\n    vector<char> chars;\n    chars.resize(random() % page_size());\n    memset(chars.data(), '0', chars.size());\n    chars.push_back(0);\n    string padding = string(\"RR_CHAOS_PADDING=\") + chars.data();\n    flags.extra_env.push_back(padding);\n  }\n\n  WaitStatus status = record(args, flags);\n\n  // Everything should have been cleaned up by now.\n  check_for_leaks();\n\n  switch (status.type()) {\n    case WaitStatus::EXIT:\n      return status.exit_code();\n    case WaitStatus::FATAL_SIGNAL:\n      signal(status.fatal_sig(), SIG_DFL);\n      prctl(PR_SET_DUMPABLE, 0);\n      kill(getpid(), status.fatal_sig());\n      break;\n    default:\n      FATAL() << \"Don't know why we exited: \" << status;\n      break;\n  }\n  return 1;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/RecordCommand.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_RECORD_COMMAND_H_\n#define RR_RECORD_COMMAND_H_\n\n#include \"Command.h\"\n\nnamespace rr {\n\nvoid force_close_record_session();\n\nclass RecordCommand : public Command {\npublic:\n  virtual int run(std::vector<std::string>& args) override;\n\n  static RecordCommand* get() { return &singleton; }\n\nprotected:\n  RecordCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static RecordCommand singleton;\n};\n\n} // namespace rr\n\n#endif // RR_RECORD_COMMAND_H_\n"
  },
  {
    "path": "src/RecordSession.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"RecordSession.h\"\n\n#include <elf.h>\n#include <limits.h>\n#include <linux/capability.h>\n#include <linux/futex.h>\n#include <sys/types.h>\n#include <sys/socket.h>\n\n#include <algorithm>\n#include <sstream>\n#include <string>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"ElfReader.h\"\n#include \"Flags.h\"\n#include \"PerfCounters.h\"\n#include \"RecordTask.h\"\n#include \"TraceeAttentionSet.h\"\n#include \"TraceStream.h\"\n#include \"VirtualPerfCounterMonitor.h\"\n#include \"WaitManager.h\"\n#include \"core.h\"\n#include \"ftrace.h\"\n#include \"kernel_metadata.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"record_signal.h\"\n#include \"record_syscall.h\"\n#include \"seccomp-bpf.h\"\n\nnamespace rr {\n\n// Undef si_addr_lsb since it's an alias for a field name that doesn't exist,\n// and we need to use the actual field name.\n#ifdef si_addr_lsb\n#undef si_addr_lsb\n#endif\n\nusing namespace rr;\nusing namespace std;\n\ntemplate <typename T> static remote_ptr<T> mask_low_bit(remote_ptr<T> p) {\n  return p.as_int() & ~uintptr_t(1);\n}\n\ntemplate <typename Arch>\nstatic void record_robust_futex_change(\n    RecordTask* t, const typename Arch::robust_list_head& head,\n    remote_ptr<void> base) {\n  if (base.is_null()) {\n    return;\n  }\n  remote_ptr<void> futex_void_ptr = base + head.futex_offset;\n  auto futex_ptr = futex_void_ptr.cast<uint32_t>();\n  // We can't just record the current futex value because at this point\n  // in task exit the robust futex handling has not happened yet. So we have\n  // to emulate what the kernel will do!\n  bool ok = true;\n  uint32_t val = t->read_mem(futex_ptr, &ok);\n  if (!ok) {\n    return;\n  }\n  if (pid_t(val & FUTEX_TID_MASK) != t->own_namespace_rec_tid) {\n    return;\n  }\n  val = (val & FUTEX_WAITERS) | FUTEX_OWNER_DIED;\n  // Update memory now so that the kernel doesn't decide to do it later, at\n  // a time that might race with other tracee execution.\n  t->write_mem(futex_ptr, val);\n  t->record_local(futex_ptr, &val);\n}\n\n/**\n * Any user-space writes performed by robust futex handling are captured here.\n * They must be emulated during replay; the kernel will not do it for us\n * during replay because the TID value in each futex is the recorded\n * TID, not the actual TID of the dying task.\n */\ntemplate <typename Arch>\nstatic void record_robust_futex_changes_arch(RecordTask* t) {\n  if (t->did_record_robust_futex_changes) {\n    return;\n  }\n  t->did_record_robust_futex_changes = true;\n\n  auto head_ptr = t->robust_list().cast<typename Arch::robust_list_head>();\n  if (head_ptr.is_null()) {\n    return;\n  }\n  ASSERT(t, t->robust_list_len() == sizeof(typename Arch::robust_list_head));\n  bool ok = true;\n  auto head = t->read_mem(head_ptr, &ok);\n  if (!ok) {\n    return;\n  }\n  record_robust_futex_change<Arch>(t, head,\n                                   mask_low_bit(head.list_op_pending.rptr()));\n  for (auto current = mask_low_bit(head.list.next.rptr());\n       current.as_int() != head_ptr.as_int();) {\n    record_robust_futex_change<Arch>(t, head, current);\n    auto next = t->read_mem(current, &ok);\n    if (!ok) {\n      return;\n    }\n    current = mask_low_bit(next.next.rptr());\n  }\n}\n\nstatic void record_robust_futex_changes(RecordTask* t) {\n  RR_ARCH_FUNCTION(record_robust_futex_changes_arch, t->arch(), t);\n}\n\nstatic bool looks_like_syscall_entry(RecordTask* t) {\n  bool ok;\n  bool at_syscall = is_at_syscall_instruction(t,\n      t->regs().ip().decrement_by_syscall_insn_length(t->arch()), &ok);\n  // It's possible for the task to have died (e.g. if it got signaled twice\n  // in rapid succession). In that case, try to just go by register contents.\n  if (ok && !at_syscall) {\n    return false;\n  }\n  if (is_x86ish(t->arch())) {\n    // On x86 rax gets set to ENOSYS on entry. Elsewhere this does not happen.\n    // Further, even if we did ask about the syscallno, it might have been\n    // reset by the signal handler. However, on non-x86 platforms we currently\n    // count taken braches, rather than only conditional ones, so it should\n    // be impossible to see the same syscall ip twice without intervening\n    // ticks, so the check that follows these conditions, should be sufficient\n    // there.\n    return t->regs().original_syscallno() >= 0 &&\n           t->regs().syscall_result_signed() == -ENOSYS;\n  } else if (t->arch() == aarch64) {\n    // We recorded when we saw the last syscall entry\n    // so just use that to determine if we've already save it in the trace.\n    if (t->ticks_at_last_syscall_entry == t->tick_count() &&\n        t->ip_at_last_syscall_entry == t->regs().ip()) {\n      return !t->last_syscall_entry_recorded;\n    }\n  }\n  // Getting a sched event here is better than a spurious syscall event.\n  // Syscall entry does not cause visible register modification, so upon\n  // hitting the sched event the register state would indeed match.\n  return ok;\n}\n\n/**\n * Return true if we handle a ptrace exit event for task t. When this returns\n * true, t may have been deleted.\n */\nstatic bool handle_ptrace_exit_event(RecordTask* t) {\n  if (t->was_reaped()) {\n    if (t->handled_ptrace_exit_event()) {\n      t->did_reach_zombie();\n      return true;\n    }\n  } else if (t->ptrace_event() != PTRACE_EVENT_EXIT) {\n    return false;\n  }\n\n  if (t->stable_exit || t->was_reaped()) {\n    LOG(debug) << \"stable exit\";\n  } else {\n    if (!t->may_be_blocked()) {\n      // might have been hit by a SIGKILL or a SECCOMP_RET_KILL, in which case\n      // there might be some execution since its last recorded event that we\n      // need to replay.\n      // There's a weird case (in 4.13.5-200.fc26.x86_64 at least) where the\n      // task can enter the kernel but instead of receiving a syscall ptrace\n      // event, we receive a PTRACE_EVENT_EXIT due to a concurrent execve\n      // (and probably a concurrent SIGKILL could do the same). The task state\n      // has been updated to reflect syscall entry. If we record a SCHED in\n      // that state replay of the SCHED will fail. So detect that state and fix\n      // it up.\n      // If we got killed in an untraced syscall on AArch64,\n      // it is difficult/impossible to tell if the value of x0 has been overwritten\n      // with the syscall result/error number\n      // and it's even harder to recover the correct value of x0.\n      // Simply ignore these since we weren't going to record them anyway.\n      if (looks_like_syscall_entry(t) && !t->is_in_untraced_syscall()) {\n        // Either we're in a syscall, or we're immediately after a syscall\n        // and it exited.\n        if (t->ticks_at_last_recorded_syscall_exit == t->tick_count() &&\n            t->regs().ip() == t->ip_at_last_recorded_syscall_exit) {\n          LOG(debug) << \"Nothing to record after PTRACE_EVENT_EXIT\";\n          // It's the latter case; do nothing.\n        } else {\n          // It's the former case ... probably. Theoretically we could have\n          // re-executed a syscall without any ticks in between, but that seems\n          // highly improbable.\n          // Record the syscall-entry event that we otherwise failed to record.\n          t->canonicalize_regs(t->arch());\n          auto r = t->regs();\n          if (t->arch() == aarch64) {\n            // On AArch64, when we get here, there are 3 different cases,\n            // 1. EXIT before we hit the syscall entry stop\n            // 2. EXIT after syscall entry stop but\n            //    before the result (X0) is overwritten\n            // 3. EXIT after syscall entry stop and\n            //    after the result (X0) is overwritten\n            //    (i.e. after the syscall but we got an EXIT\n            //     before the syscall exit stop.)\n\n            // We detect the first case based on `*_at_last_syscall_entry`\n            // set by `apply_syscall_entry_regs` and trust the current values\n            // `x0` and `x8`.\n\n            // For the second and third cases, we rely on the syscall enter stop\n            // to set the orig_arg1 and original_syscallno correctly.\n            if (t->ticks_at_last_syscall_entry == t->tick_count() &&\n                t->ip_at_last_syscall_entry == r.ip()) {\n              // We need to rely on the saved `orig_arg1` since in the third case\n              // the `x0` may already be overwritten.\n              // The assertion here assumes that\n              // `apply_syscall_entry_regs` is called when we enter the syscall\n              // and `x8` still holds the correct syscall number\n              // when we hit the process exit stop.\n              ASSERT(t, r.original_syscallno() == r.syscallno())\n                << \"syscallno not saved by syscall enter handler: \" << r;\n              r.set_arg1(r.orig_arg1());\n            } else {\n              r.set_original_syscallno(r.syscallno());\n            }\n          }\n          // Assume it's a native-arch syscall. If it isn't, it doesn't matter\n          // all that much since we aren't actually going to do anything with it\n          // in this task.\n          // Avoid calling detect_syscall_arch here since it could fail if the\n          // task is already completely dead and gone.\n          SyscallEvent event(r.original_syscallno(), t->arch());\n          event.state = ENTERING_SYSCALL;\n          // Don't try to reset the syscallbuf here. The task may be exiting\n          // while in arbitrary syscallbuf code. And of course, because it's\n          // exiting, it doesn't matter if we don't reset the syscallbuf.\n          t->record_event(event, RecordTask::FLUSH_SYSCALLBUF,\n                          RecordTask::DONT_RESET_SYSCALLBUF, &r);\n        }\n      } else {\n        // Don't try to reset the syscallbuf here. The task may be exiting\n        // while in arbitrary syscallbuf code. And of course, because it's\n        // exiting, it doesn't matter if we don't reset the syscallbuf.\n        // XXX flushing the syscallbuf may be risky too...\n        auto event = Event::sched();\n        // When replaying this SCHED, we won't proceed past the `syscall_hook`\n        // entry point. Code inside the syscallbuf may be in a bad state during\n        // replay because we didn't save buffered syscalls.\n        event.Sched().in_syscallbuf_syscall_hook = t->syscallbuf_code_layout.syscallbuf_syscall_hook;\n        t->record_event(event, RecordTask::FLUSH_SYSCALLBUF,\n                        RecordTask::DONT_RESET_SYSCALLBUF);\n      }\n    }\n    /* XXX: We could try to find some tasks here to unmap our buffers, but it\n     *      seems hardly worth it.\n     * Mark buffers as gone after recording events, in case they need to flush the syscallbuf.\n     */\n    t->destroy_buffers(nullptr, nullptr);\n  }\n\n  WaitStatus exit_status;\n  if (t->was_reaped()) {\n    exit_status = t->status();\n  } else {\n    record_robust_futex_changes(t);\n\n    unsigned long msg = 0;\n    // If ptrace_if_stopped fails, then the task has been killed by SIGKILL\n    // or equivalent.\n    if (t->ptrace_if_stopped(PTRACE_GETEVENTMSG, nullptr, &msg)) {\n      exit_status = WaitStatus(msg);\n    } else {\n      exit_status = WaitStatus::for_fatal_sig(SIGKILL);\n    }\n  }\n\n  t->did_handle_ptrace_exit_event();\n  // The counters might be running if we did not read the final register values\n  // (e.g. because our registers are dirty). Stop them now so we can close them\n  // safely.\n  t->hpc.stop(t);\n\n  // If we died because of a coredumping signal, that is a barrier event, and\n  // every task in the address space needs to pass its PTRACE_EXIT_EVENT before\n  // they proceed to (potentially hidden) zombie state, so we can't wait for\n  // that to happen.\n  // Similarly we can't wait for this task to exit if there are other\n  // tasks in its pid namespace that need to exit and this is the last thread\n  // of pid-1 in that namespace, because the kernel must reap them before\n  // letting this task complete its exit.\n  bool may_wait_exit = !t->was_reaped() && !is_coredumping_signal(exit_status.fatal_sig()) &&\n    !t->waiting_for_pid_namespace_tasks_to_exit();\n  t->record_exit_trace_event(exit_status);\n  t->record_exit_event(\n    (!t->was_reaped() && !may_wait_exit) ? RecordTask::WRITE_CHILD_TID : RecordTask::KERNEL_WRITES_CHILD_TID);\n  if (!t->was_reaped()) {\n    t->proceed_to_exit(may_wait_exit);\n  }\n  t->do_ptrace_exit_stop(exit_status);\n  if (may_wait_exit) {\n    t->did_reach_zombie();\n  } else if (!t->was_reaped()) {\n    t->waiting_for_reap = true;\n  }\n  return true;\n}\n\nstatic void note_entering_syscall(RecordTask* t) {\n  ASSERT(t, EV_SYSCALL == t->ev().type());\n  t->ev().Syscall().state = ENTERING_SYSCALL;\n  if (!t->ev().Syscall().is_restart) {\n    /* Save a copy of the arg registers so that we\n     * can use them to detect later restarted\n     * syscalls, if this syscall ends up being\n     * restarted.  We have to save the registers\n     * in this rather awkward place because we\n     * need the original registers; the restart\n     * (if it's not a SYS_restart_syscall restart)\n     * will use the original registers. */\n    t->ev().Syscall().regs = t->regs();\n  } else {\n    t->ev().Syscall().regs.set_syscallno(t->regs().syscallno());\n    // We may have intentionally stored the syscall result here.\n    // Now that we're safely past the signal delivery, make the\n    // registers look like they did at the original syscall entry\n    // again.\n    t->ev().Syscall().regs.set_arg1(t->ev().Syscall().regs.orig_arg1());\n    if (t->arch() == aarch64) {\n      // We probably got here with a PTRACE_SYSCALL. The x7\n      // value will be wrong due to the aarch64 kernel bug.\n      // Get it from the syscall event.\n      Registers r = t->regs();\n      r.set_x(7, t->ev().Syscall().regs.x(7));\n      t->set_regs(r);\n    }\n  }\n}\n\n#if defined (__x86_64__)\nstatic bool is_in_vsyscall(remote_code_ptr ip)\n{\n  // This is hardcoded by the Linux ABI\n  remote_code_ptr vsyscall_start = 0xffffffffff600000;\n  remote_code_ptr vsyscall_end = 0xffffffffff601000;\n  return vsyscall_start <= ip && ip < vsyscall_end;\n}\n#else\nstatic bool is_in_vsyscall(remote_code_ptr)\n{\n  return false;\n}\n#endif\n\nvoid RecordSession::handle_seccomp_traced_syscall(RecordTask* t,\n                                                  StepState* step_state,\n                                                  RecordResult* result,\n                                                  bool* did_enter_syscall) {\n  *did_enter_syscall = false;\n\n  // Special case: If the tracee issues a vsyscall, we will get a seccomp trap,\n  // but no syscall traps whatsoever. In particular, we wouldn't see it during\n  // replay either. We try to monkeypatch the caller on the assumption that known\n  // callers of this (deprecated) interface all follow a common pattern. If we\n  // can't patch the caller, this is a fatal error, since the recording will\n  // otherwise be broken.\n  remote_code_ptr ip = t->regs().ip();\n  if (is_in_vsyscall(ip)) {\n    remote_ptr<void> sp = t->regs().sp();\n    // The kernel assumes the return address is on the stack - we do the same\n    remote_ptr<remote_code_ptr> ret_addr_addr = sp.cast<remote_code_ptr>();\n    remote_code_ptr ret_addr = t->read_mem(ret_addr_addr);\n\n    // Skip this syscall. We will attempt to patch it to the vdso entry and\n    // let the tracee retry there.\n    Registers regs = t->regs();\n    regs.set_original_syscallno(-1);\n    // We can't modify the ip here, the kernel will kill the tracee with\n    // SIGSYS. Instead, we set a breakpoint at the return instruction.\n    t->set_regs(regs);\n    t->vm()->add_breakpoint(ret_addr, BKPT_INTERNAL);\n    while (true) {\n      if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        // Tracee exited unexpectedly\n        return;\n      }\n      ASSERT(t, !t->ptrace_event());\n      if (t->stop_sig() == syscallbuf_desched_sig()) {\n        continue;\n      }\n      if (t->stop_sig() == SIGTRAP &&\n          is_kernel_trap(t->get_siginfo().si_code)) {\n        // Hit the breakpoint\n        break;\n      }\n      t->stash_sig();\n    }\n    t->vm()->remove_breakpoint(ret_addr, BKPT_INTERNAL);\n\n    ASSERT(t, t->regs().ip().undo_executed_bkpt(t->arch()) == ret_addr);\n\n    // Now that we're in a sane state, ask the Monkeypatcher to try and patch\n    // that.\n    bool patch_ok = t->vm()->monkeypatcher().try_patch_vsyscall_caller(t, ret_addr);\n    ASSERT(t, patch_ok) << \"The tracee issues a vsyscall to \" << ip\n            << \" but we failed to monkeypatch the caller (return address \"\n            << ret_addr << \", sp=\" << sp << \"). Recording will not succeed. Exiting.\";\n\n    // Reset to the start of the region and continue\n    regs = t->regs();\n    regs.set_ip(ret_addr.decrement_by_vsyscall_entry_length(t->arch()));\n    t->set_regs(regs);\n\n    // We patched this syscall, record that\n    auto ev = Event::patch_syscall();\n    ev.PatchSyscall().patch_vsyscall = true;\n    t->record_event(ev);\n\n    step_state->continue_type = RecordSession::CONTINUE;\n    return;\n  }\n\n  int syscallno = t->regs().original_syscallno();\n  if (syscallno < 0) {\n    // negative syscall numbers after a SECCOMP event\n    // are treated as \"skip this syscall\". There will be one syscall event\n    // reported instead of two. So fake an enter-syscall event now.\n    // It doesn't really matter what the syscall-arch is.\n    t->canonicalize_regs(t->arch());\n    if (syscall_seccomp_ordering_ == SECCOMP_BEFORE_PTRACE_SYSCALL) {\n      // If the ptrace entry stop hasn't happened yet, we're at a weird\n      // intermediate state where the behavior of the next PTRACE_SYSCALL\n      // will depend on the register state (i.e. whether we see an entry\n      // trap or proceed right to the exit trap). To make things easier\n      // on the rest of the system, do a fake syscall entry, then reset\n      // the register state.\n      Registers orig_regs = t->regs();\n      Registers r = orig_regs;\n      r.set_original_syscallno(syscall_number_for_gettid(t->arch()));\n      t->set_regs(r);\n      if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        // Tracee died unexpectedly. We did not enter a syscall.\n        // We shouldn't try to resume it now.\n        last_task_switchable = ALLOW_SWITCH;\n        step_state->continue_type = RecordSession::DONT_CONTINUE;\n        return;\n      }\n      t->set_regs(orig_regs);\n    }\n\n    // Don't continue yet. At the next iteration of record_step, we'll\n    // enter syscall_state_changed and that will trigger a continue to\n    // the syscall exit.\n    last_task_switchable = ALLOW_SWITCH;\n    step_state->continue_type = RecordSession::DONT_CONTINUE;\n    if (!process_syscall_entry(t, step_state, result, t->arch())) {\n      return;\n    }\n    *did_enter_syscall = true;\n    return;\n  }\n\n  if (syscall_seccomp_ordering_ == SECCOMP_BEFORE_PTRACE_SYSCALL) {\n    // The next continue needs to be a PTRACE_SYSCALL to observe\n    // the enter-syscall event.\n    step_state->continue_type = RecordSession::CONTINUE_SYSCALL;\n  } else {\n    ASSERT(t, syscall_seccomp_ordering_ == PTRACE_SYSCALL_BEFORE_SECCOMP);\n    if (t->ev().is_syscall_event() &&\n        t->ev().Syscall().state == PROCESSING_SYSCALL) {\n      // We did PTRACE_SYSCALL and already saw a syscall trap. Just ignore this.\n      LOG(debug) << \"Ignoring SECCOMP syscall trap since we already got a \"\n                    \"PTRACE_SYSCALL trap\";\n      // The next continue needs to be a PTRACE_SYSCALL to observe\n      // the exit-syscall event.\n      step_state->continue_type = RecordSession::CONTINUE_SYSCALL;\n      // Need to restore last_task_switchable since it will have been\n      // reset to PREVENT_SWITCH\n      last_task_switchable = t->ev().Syscall().switchable;\n    } else {\n      // We've already passed the PTRACE_SYSCALL trap for syscall entry, so\n      // we need to handle that now.\n      SupportedArch syscall_arch = t->detect_syscall_arch();\n      t->canonicalize_regs(syscall_arch);\n      if (!process_syscall_entry(t, step_state, result, syscall_arch)) {\n        last_task_switchable = ALLOW_SWITCH;\n        step_state->continue_type = RecordSession::DONT_CONTINUE;\n        return;\n      }\n      *did_enter_syscall = true;\n    }\n  }\n}\n\nstatic void seccomp_trap_done(RecordTask* t) {\n  t->pop_seccomp_trap();\n\n  // It's safe to reset the syscall buffer now.\n  t->delay_syscallbuf_reset_for_seccomp_trap = false;\n\n  t->write_and_record(REMOTE_PTR_FIELD(t->syscallbuf_child, failed_during_preparation),\n                      (uint8_t)1);\n  if (EV_DESCHED == t->ev().type()) {\n    // Desched processing will do the rest for us\n    return;\n  }\n\n  // Abort the current syscallbuf record, which corresponds to the syscall that\n  // wasn't actually executed due to seccomp.\n  t->write_mem(REMOTE_PTR_FIELD(t->syscallbuf_child, abort_commit), (uint8_t)1);\n  t->record_event(Event::syscallbuf_abort_commit());\n\n  // In fact, we need to. Running the syscall exit hook will ensure we\n  // reset the buffer before we try to buffer another a syscall.\n  t->write_mem(\n      REMOTE_PTR_FIELD(t->syscallbuf_child, notify_on_syscall_hook_exit),\n      (uint8_t)1);\n}\n\nvoid RecordSession::handle_seccomp_trap(RecordTask* t,\n                                        RecordSession::StepState* step_state,\n                                        uint16_t seccomp_data) {\n  // The architecture may be wrong, but that's ok, because an actual syscall\n  // entry did happen, so the registers are already updated according to the\n  // architecture of the system call.\n  t->canonicalize_regs(t->detect_syscall_arch());\n  t->apply_syscall_entry_regs();\n\n  Registers r = t->regs();\n  int syscallno = r.original_syscallno();\n  // Cause kernel processing to skip the syscall\n  r.set_original_syscallno(SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO);\n  t->set_regs(r);\n\n  bool syscall_entry_already_recorded = false;\n  if (t->ev().is_syscall_event()) {\n    // A syscall event was already pushed, probably because we did a\n    // PTRACE_SYSCALL to enter the syscall during handle_desched_event. Cancel\n    // that event now since the seccomp SIGSYS aborts it completely.\n    ASSERT(t, t->ev().Syscall().number == syscallno);\n    // Make sure any prepared syscall state is discarded and any temporary\n    // effects (e.g. redirecting pointers to scratch) undone.\n    rec_abort_prepared_syscall(t);\n    if (t->ev().type() == EV_SYSCALL_INTERRUPTION) {\n      // The event could be a syscall-interruption if it was pushed by\n      // `handle_desched_event`. In that case, it has not been recorded yet.\n      t->pop_syscall_interruption();\n    } else {\n      t->pop_syscall();\n      syscall_entry_already_recorded = true;\n    }\n  }\n\n  if (t->is_in_untraced_syscall()) {\n    ASSERT(t, !t->delay_syscallbuf_reset_for_seccomp_trap);\n    // Don't reset the syscallbuf immediately after delivering the trap. We have\n    // to wait until this buffered syscall aborts completely before resetting\n    // the buffer.\n    t->delay_syscallbuf_reset_for_seccomp_trap = true;\n\n    t->push_event(Event::seccomp_trap());\n\n    // desched may be armed but we're not going to execute the syscall, let\n    // alone block. If it fires, ignore it.\n    t->write_mem(\n        REMOTE_PTR_FIELD(t->syscallbuf_child, desched_signal_may_be_relevant),\n        (uint8_t)0);\n  }\n\n  t->push_syscall_event(syscallno);\n  t->ev().Syscall().failed_during_preparation = true;\n  note_entering_syscall(t);\n\n  if (t->is_in_untraced_syscall() && !syscall_entry_already_recorded) {\n    t->record_current_event();\n  }\n\n  // Use NativeArch here because different versions of system headers\n  // have inconsistent field naming.\n  union {\n    NativeArch::siginfo_t native_api;\n    siginfo_t linux_api;\n  } si;\n  memset(&si, 0, sizeof(si));\n  si.native_api.si_signo = SIGSYS;\n  si.native_api.si_errno = seccomp_data;\n  si.native_api.si_code = SYS_SECCOMP;\n  si.native_api._sifields._sigsys._arch = to_audit_arch(r.arch());\n  si.native_api._sifields._sigsys._syscall = syscallno;\n  // Documentation says that si_call_addr is the address of the syscall\n  // instruction, but in tests it's immediately after the syscall\n  // instruction.\n  si.native_api._sifields._sigsys._call_addr = t->ip().to_data_ptr<void>();\n  LOG(debug) << \"Synthesizing \" << si.linux_api;\n  t->stash_synthetic_sig(si.linux_api, DETERMINISTIC_SIG);\n\n  // Tests show that the current registers are preserved (on x86, eax/rax\n  // retains the syscall number).\n  r.set_syscallno(syscallno);\n  t->set_regs(r);\n  t->maybe_restore_original_syscall_registers();\n\n  if (t->is_in_untraced_syscall()) {\n    // For buffered syscalls, go ahead and record the exit state immediately.\n    t->ev().Syscall().state = EXITING_SYSCALL;\n    t->record_current_event();\n    t->pop_syscall();\n\n    // The tracee is currently in the seccomp ptrace-stop. Advance it to the\n    // syscall-exit stop so that when we try to deliver the SIGSYS via\n    // PTRACE_SINGLESTEP, that doesn't trigger a SIGTRAP stop.\n    // If this fails, that's fine, we're not going to deliver the SIGSYS.\n    t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS);\n  }\n\n  // Don't continue yet. At the next iteration of record_step, if we\n  // recorded the syscall-entry we'll enter syscall_state_changed and\n  // that will trigger a continue to the syscall exit. If we recorded the\n  // syscall-exit we'll go straight into signal delivery.\n  step_state->continue_type = RecordSession::DONT_CONTINUE;\n}\n\nvoid RecordSession::handle_seccomp_errno(RecordTask* t,\n                                         RecordSession::StepState* step_state,\n                                         uint16_t seccomp_data) {\n  t->canonicalize_regs(t->detect_syscall_arch());\n\n  Registers r = t->regs();\n  int syscallno = r.original_syscallno();\n  // Cause kernel processing to skip the syscall\n  r.set_original_syscallno(SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO);\n  t->set_regs(r);\n\n  if (!t->is_in_untraced_syscall()) {\n    t->push_syscall_event(syscallno);\n    // Note that the syscall failed. prepare_clone() needs to know\n    // this during replay of the syscall entry.\n    t->ev().Syscall().failed_during_preparation = true;\n    note_entering_syscall(t);\n  }\n\n  r.set_syscall_result(-seccomp_data);\n  t->set_regs(r);\n  // Don't continue yet. At the next iteration of record_step, if we\n  // recorded the syscall-entry we'll enter syscall_state_changed and\n  // that will trigger a continue to the syscall exit.\n  step_state->continue_type = RecordSession::DONT_CONTINUE;\n}\n\nbool RecordSession::handle_ptrace_event(RecordTask** t_ptr,\n                                        StepState* step_state,\n                                        RecordResult* result,\n                                        bool* did_enter_syscall) {\n  *did_enter_syscall = false;\n\n  RecordTask* t = *t_ptr;\n  if (t->status().group_stop() || t->has_stashed_group_stop()) {\n    t->clear_stashed_group_stop();\n    last_task_switchable = ALLOW_SWITCH;\n    step_state->continue_type = DONT_CONTINUE;\n    return true;\n  }\n\n  int event = t->ptrace_event();\n  if (!event) {\n    return false;\n  }\n\n  LOG(debug) << \"  \" << t->tid << \": handle_ptrace_event \"\n             << ptrace_event_name(event) << \": event \" << t->ev();\n\n  switch (event) {\n    case PTRACE_EVENT_SECCOMP_OBSOLETE:\n    case PTRACE_EVENT_SECCOMP: {\n      if (syscall_seccomp_ordering_ == PTRACE_SYSCALL_BEFORE_SECCOMP_UNKNOWN) {\n        syscall_seccomp_ordering_ = SECCOMP_BEFORE_PTRACE_SYSCALL;\n      }\n\n      int seccomp_data = t->get_ptrace_eventmsg_seccomp_data();\n      // We need to set the orig_* values before we let the process continue to exit\n      // since the handler for the exit event will need them.\n      // See `handle_ptrace_exit_event` above.\n      t->apply_syscall_entry_regs();\n      if (seccomp_data < 0) {\n        // Process just died. Urk. Just wait for the exit event and pretend this stop never happened!\n        last_task_switchable = ALLOW_SWITCH;\n        step_state->continue_type = DONT_CONTINUE;\n        return true;\n      }\n      int syscallno = t->regs().original_syscallno();\n      if (seccomp_data == SECCOMP_RET_DATA) {\n        LOG(debug) << \"  traced syscall entered: \"\n                   << syscall_name(syscallno, t->arch());\n        handle_seccomp_traced_syscall(t, step_state, result, did_enter_syscall);\n      } else {\n        // Note that we make no attempt to patch the syscall site when the\n        // user handle does not return ALLOW. Apart from the ERRNO case,\n        // handling these syscalls is necessarily slow anyway.\n        uint32_t real_result;\n        if (!seccomp_filter_rewriter().map_filter_data_to_real_result(\n                t, seccomp_data, &real_result)) {\n          LOG(debug)\n              << \"Process terminated unexpectedly during PTRACE_GETEVENTMSG\";\n          step_state->continue_type = RecordSession::CONTINUE;\n          break;\n        }\n        uint16_t real_result_data = real_result & SECCOMP_RET_DATA;\n        switch (real_result & SECCOMP_RET_ACTION) {\n          case SECCOMP_RET_TRAP:\n            LOG(debug) << \"  seccomp trap for syscall: \"\n                       << syscall_name(syscallno, t->arch());\n            handle_seccomp_trap(t, step_state, real_result_data);\n            break;\n          case SECCOMP_RET_ERRNO:\n            LOG(debug) << \"  seccomp errno \" << errno_name(real_result_data)\n                       << \" for syscall: \"\n                       << syscall_name(syscallno, t->arch());\n            handle_seccomp_errno(t, step_state, real_result_data);\n            break;\n          case SECCOMP_RET_KILL:\n            LOG(debug) << \"  seccomp kill for syscall: \"\n                       << syscall_name(syscallno, t->arch());\n            t->tgkill(SIGKILL);\n            // Rely on the SIGKILL to bump us out of the ptrace stop.\n            last_task_switchable = ALLOW_SWITCH;\n            step_state->continue_type = RecordSession::DONT_CONTINUE;\n            // Now wait for us to actually exit our ptrace-stop and proceed\n            // to the PTRACE_EVENT_EXIT. This avoids the race where our\n            // PTRACE_CONT might kick us out of the PTRACE_EVENT_EXIT before\n            // we can process it.\n            // If this fails because of *another* SIGKILL that's fine.\n            t->wait();\n            break;\n          default:\n            ASSERT(t, false) << \"Seccomp result not handled\";\n            break;\n        }\n      }\n      break;\n    }\n\n    case PTRACE_EVENT_EXEC: {\n      if (t->thread_group()->task_set().size() > 1) {\n        // All tasks but the task that did the execve should have exited by\n        // now and notified us of their exits. However, it's possible that\n        // while running the thread-group leader, our PTRACE_CONT raced with its\n        // PTRACE_EVENT_EXIT and it exited, and the next event we got is this\n        // PTRACE_EVENT_EXEC after the exec'ing task changed its tid to the\n        // leader's tid. Or maybe there are kernel bugs; on\n        // 4.2.0-42-generic running exec_from_other_thread, we reproducibly\n        // enter PTRACE_EVENT_EXEC for the thread-group leader without seeing\n        // its PTRACE_EVENT_EXIT.\n\n        // So, record this task's exit and destroy it.\n        // XXX We can't do record_robust_futex_changes here because the address\n        // space has already gone. That would only matter if some of them were\n        // in memory accessible to another process even after exec, i.e. a\n        // shared-memory mapping or two different thread-groups sharing the same\n        // address space.\n        pid_t tid = t->rec_tid;\n        WaitStatus status = t->status();\n        t->record_exit_trace_event(WaitStatus(0));\n        t->record_exit_event();\n        // Don't call RecordTask::destroy() because we don't want to\n        // PTRACE_DETACH.\n        delete t;\n        // Steal the exec'ing task and make it the thread-group leader, and\n        // carry on!\n        t = revive_task_for_exec(tid);\n        scheduler().set_current(t);\n        *t_ptr = t;\n        // Tell t that it is actually stopped, because the stop we got is really\n        // for this task, not the old dead task.\n        if (!t->did_waitpid(status)) {\n          // This is totally untested and almost certainly broken, but if the\n          // task was SIGKILLed out of the EXEC stop then we should probably\n          // just pretend the exec never happened.\n          step_state->continue_type = CONTINUE_SYSCALL;\n          break;\n        }\n      }\n      t->post_exec();\n      t->session().scheduler().did_exit_execve(t);\n\n      // Forward ptrace exec notification\n      if (t->emulated_ptracer) {\n        if (t->emulated_ptrace_options & PTRACE_O_TRACEEXEC) {\n          t->emulate_ptrace_stop(\n              WaitStatus::for_ptrace_event(PTRACE_EVENT_EXEC));\n        } else if (!t->emulated_ptrace_seized) {\n          // Inject legacy SIGTRAP-after-exec\n          t->tgkill(SIGTRAP);\n        }\n      }\n\n      if (t->emulated_stop_pending) {\n        last_task_switchable = ALLOW_SWITCH;\n        step_state->continue_type = DONT_CONTINUE;\n      } else {\n        // Skip past the ptrace event.\n        step_state->continue_type = CONTINUE_SYSCALL;\n      }\n      break;\n    }\n\n    default:\n      ASSERT(t, false) << \"Unhandled ptrace event \" << ptrace_event_name(event)\n                       << \"(\" << event << \")\";\n      break;\n  }\n\n  return true;\n}\n\nstatic void debug_exec_state(const char* msg, RecordTask* t) {\n  LOG(debug) << msg << \": status=\" << t->status();\n}\n\ntemplate <typename Arch>\nstatic bool is_ptrace_any_singlestep_arch(int command) {\n  return command >= 0 &&\n    (command == PTRACE_SINGLESTEP || command == Arch::PTRACE_SYSEMU_SINGLESTEP);\n}\n\nstatic bool is_ptrace_any_singlestep(SupportedArch arch, int command)\n{\n  RR_ARCH_FUNCTION(is_ptrace_any_singlestep_arch, arch, command);\n}\n\nvoid RecordSession::task_continue(const StepState& step_state) {\n  RecordTask* t = scheduler().current();\n\n  ASSERT(t, step_state.continue_type != DONT_CONTINUE);\n  // A task in an emulated ptrace-stop must really stay stopped\n  ASSERT(t, !t->emulated_stop_pending);\n\n  bool may_restart = t->at_may_restart_syscall();\n\n  if (may_restart && t->seccomp_bpf_enabled) {\n    LOG(debug) << \"  PTRACE_SYSCALL to possibly-restarted \" << t->ev();\n  }\n\n  if (!t->vm()->first_run_event()) {\n    t->vm()->set_first_run_event(trace_writer().time());\n  }\n\n  if (!t->thread_group()->first_run_event()) {\n    t->thread_group()->set_first_run_event(trace_writer().time());\n  }\n\n  TicksRequest ticks_request;\n  ResumeRequest resume;\n  if (step_state.continue_type == CONTINUE_SYSCALL) {\n    ticks_request = RESUME_NO_TICKS;\n    resume = RESUME_SYSCALL;\n  } else {\n    if (t->has_stashed_sig(PerfCounters::TIME_SLICE_SIGNAL)) {\n      // timeslice signal already stashed, no point in generating another one\n      // (and potentially slow)\n      ticks_request = RESUME_UNLIMITED_TICKS;\n    } else if (scheduler().may_use_unlimited_ticks()) {\n      ticks_request = RESUME_UNLIMITED_TICKS;\n    } else {\n      ticks_request = (TicksRequest)max<Ticks>(\n          0, scheduler().current_timeslice_end() - t->tick_count());\n    }\n\n    // Clear any lingering state, then see if we need to stop earlier for a\n    // tracee-requested pmc interrupt on the virtualized performance counter.\n    t->next_pmc_interrupt_is_for_user = false;\n    if (auto vpmc =\n            VirtualPerfCounterMonitor::interrupting_virtual_pmc_for_task(t)) {\n      ASSERT(t, vpmc->target_tuid() == t->tuid());\n\n      Ticks after = max<Ticks>(vpmc->target_ticks() - t->tick_count(), 0);\n      if ((uint64_t)after < (uint64_t)ticks_request) {\n        LOG(debug) << \"ticks_request constrained from \" << ticks_request\n                   << \" to \" << after << \" for vpmc\";\n        ticks_request = (TicksRequest)after;\n        t->next_pmc_interrupt_is_for_user = true;\n      }\n    }\n\n    // Override requested by the tracee for testing purposes\n    if (t->tick_request_override != (TicksRequest)0) {\n      ASSERT(t, !t->next_pmc_interrupt_is_for_user);\n      ticks_request = t->tick_request_override;\n      t->tick_request_override = (TicksRequest)0;\n    }\n\n    bool singlestep = is_ptrace_any_singlestep(t->arch(),\n      t->emulated_ptrace_cont_command);\n    if (singlestep && is_at_syscall_instruction(t, t->ip())) {\n      // We're about to singlestep into a syscall instruction.\n      // Act like we're NOT singlestepping since doing a PTRACE_SINGLESTEP would\n      // skip over the system call.\n      LOG(debug)\n          << \"Clearing singlestep because we're about to enter a syscall\";\n      singlestep = false;\n    }\n    if (singlestep) {\n      resume = RESUME_SINGLESTEP;\n    } else {\n      /* We won't receive PTRACE_EVENT_SECCOMP events until\n       * the seccomp filter is installed by the\n       * syscall_buffer lib in the child, therefore we must\n       * record in the traditional way (with PTRACE_SYSCALL)\n       * until it is installed. */\n      /* Kernel commit\n         https://github.com/torvalds/linux/commit/93e35efb8de45393cf61ed07f7b407629bf698ea\n         makes PTRACE_SYSCALL traps be delivered *before* seccomp RET_TRACE\n         traps.\n         Detect and handle this. */\n      if (!t->seccomp_bpf_enabled || may_restart ||\n          syscall_seccomp_ordering_ == PTRACE_SYSCALL_BEFORE_SECCOMP_UNKNOWN) {\n        resume = RESUME_SYSCALL;\n      } else {\n        /* When the seccomp filter is on, instead of capturing\n         * syscalls by using PTRACE_SYSCALL, the filter will\n         * generate the ptrace events. This means we allow the\n         * process to run using PTRACE_CONT, and rely on the\n         * seccomp filter to generate the special\n         * PTRACE_EVENT_SECCOMP event once a syscall happens.\n         * This event is handled here by simply allowing the\n         * process to continue to the actual entry point of\n         * the syscall (using cont_syscall_block()) and then\n         * using the same logic as before. */\n        resume = RESUME_CONT;\n      }\n    }\n  }\n  t->resume_execution(resume, RESUME_NONBLOCKING, ticks_request);\n}\n\n/**\n * Step |t| forward until the tracee syscall that disarms the desched\n * event. If a signal becomes pending in the interim, we stash it.\n * This allows the caller to deliver the signal after this returns.\n * (In reality the desched event will already have been disarmed before we\n * enter this function.)\n */\nstatic void advance_to_disarm_desched_syscall(RecordTask* t) {\n  int old_sig = 0;\n\n  LOG(debug) << \"desched: DISARMING_DESCHED_EVENT\";\n  /* TODO: send this through main loop. */\n  /* TODO: mask off signals and avoid this loop. */\n  do {\n    if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_UNLIMITED_TICKS)) {\n      return;\n    }\n    if (t->status().is_syscall()) {\n      t->apply_syscall_entry_regs();\n    }\n    /* We can safely ignore TIME_SLICE_SIGNAL while trying to\n     * reach the disarm-desched ioctl: once we reach it,\n     * the desched'd syscall will be \"done\" and the tracee\n     * will be at a preemption point.  In fact, we *want*\n     * to ignore this signal.  Syscalls like read() can\n     * have large buffers passed to them, and we have to\n     * copy-out the buffered out data to the user's\n     * buffer.  This happens in the interval where we're\n     * reaching the disarm-desched ioctl, so that code is\n     * susceptible to receiving TIME_SLICE_SIGNAL. */\n    int sig = t->stop_sig();\n    if (PerfCounters::TIME_SLICE_SIGNAL == sig) {\n      continue;\n    }\n    // We should not receive SYSCALLBUF_DESCHED_SIGNAL since it should already\n    // have been disarmed. However, we observe these being received here when\n    // we arm the desched signal before we restart a blocking syscall, which\n    // completes successfully, then we disarm, then we see a desched signal\n    // here.\n    if (t->session().syscallbuf_desched_sig() == sig) {\n      continue;\n    }\n    if (sig && sig == old_sig) {\n      LOG(debug) << \"  coalescing pending \" << signal_name(sig);\n      continue;\n    }\n    if (sig) {\n      LOG(debug) << \"  \" << signal_name(sig) << \" now pending\";\n      t->stash_sig();\n    }\n  } while (!t->is_disarm_desched_event_syscall());\n\n  // Exit the syscall. If this fails, that's fine, we can ignore it.\n  t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS);\n}\n\n/**\n * |t| is at a desched event and some relevant aspect of its state\n * changed.  (For now, changes except the original desched'd syscall\n * being restarted.)\n */\nvoid RecordSession::desched_state_changed(RecordTask* t) {\n  LOG(debug) << \"desched: IN_SYSCALL\";\n  /* We need to ensure that the syscallbuf code doesn't\n   * try to commit the current record; we've already\n   * recorded that syscall.  The following event sets\n   * the abort-commit bit. */\n  t->write_mem(REMOTE_PTR_FIELD(t->syscallbuf_child, abort_commit), (uint8_t)1);\n  t->record_event(Event::syscallbuf_abort_commit());\n\n  advance_to_disarm_desched_syscall(t);\n\n  t->pop_desched();\n\n  /* The tracee has just finished sanity-checking the\n   * aborted record, and won't touch the syscallbuf\n   * during this (aborted) transaction again.  So now\n   * is a good time for us to reset the record counter. */\n  t->delay_syscallbuf_reset_for_desched = false;\n  // Run the syscallbuf exit hook. This ensures we'll be able to reset\n  // the syscallbuf before trying to buffer another syscall.\n  t->write_mem(\n      REMOTE_PTR_FIELD(t->syscallbuf_child, notify_on_syscall_hook_exit),\n      (uint8_t)1);\n}\n\nstatic void retry_syscall_patch(RecordTask* t, remote_code_ptr orig_syscall_ip)\n{\n  bool should_retry = false;\n  if (t->vm()->monkeypatcher().try_patch_syscall(t, false, should_retry, orig_syscall_ip)) {\n    // Syscall was patched. Emit event and continue execution.\n    LOG(debug) << \"Retried patch applied successfully\";\n    auto ev = Event::patch_syscall();\n    ev.PatchSyscall().patch_after_syscall = true;\n    t->record_event(ev);\n  }\n  ASSERT(t, !should_retry);\n}\n\nstatic void syscall_not_restarted(RecordTask* t) {\n  LOG(debug) << \"  \" << t->tid << \": popping abandoned interrupted \" << t->ev()\n             << \"; pending events:\";\n  if (IS_LOGGING(debug)) {\n    t->log_pending_events();\n  }\n  bool should_retry_patch = t->ev().Syscall().should_retry_patch;\n  remote_code_ptr orig_syscall_ip = t->ev().Syscall().regs.ip();\n  t->pop_syscall_interruption();\n  if (should_retry_patch) {\n    LOG(debug) << \"Retrying deferred syscall patching non-restarted syscall at \" << orig_syscall_ip << \" (current ip \" << t->regs().ip() << \")\";\n    retry_syscall_patch(t, orig_syscall_ip);\n  }\n}\n\n/**\n * \"Thaw\" a frozen interrupted syscall if |t| is restarting it.\n * Return true if a syscall is indeed restarted.\n *\n * A postcondition of this function is that |t->ev| is no longer a\n * syscall interruption, whether or whether not a syscall was\n * restarted.\n */\nstatic bool maybe_restart_syscall(RecordTask* t) {\n  if (is_restart_syscall_syscall(t->regs().original_syscallno(), t->arch())) {\n    LOG(debug) << \"  \" << t->tid << \": SYS_restart_syscall'ing \" << t->ev();\n  }\n  if (t->is_syscall_restart()) {\n    t->ev().transform(EV_SYSCALL);\n    Registers regs = t->regs();\n    regs.set_original_syscallno(t->ev().Syscall().regs.original_syscallno());\n    t->set_regs(regs);\n    t->canonicalize_regs(t->arch());\n    return true;\n  }\n  if (EV_SYSCALL_INTERRUPTION == t->ev().type()) {\n    syscall_not_restarted(t);\n  }\n  return false;\n}\n\n/**\n * After a SYS_sigreturn \"exit\" of task |t| with return value |ret|,\n * check to see if there's an interrupted syscall that /won't/ be\n * restarted, and if so, pop it off the pending event stack.\n */\nstatic void maybe_discard_syscall_interruption(RecordTask* t, intptr_t ret) {\n  int syscallno;\n\n  if (EV_SYSCALL_INTERRUPTION != t->ev().type()) {\n    /* We currently don't track syscalls interrupted with\n     * ERESTARTSYS or ERESTARTNOHAND, so it's possible for\n     * a sigreturn not to affect the event stack. */\n    LOG(debug) << \"  (no interrupted syscall to retire)\";\n    return;\n  }\n\n  syscallno = t->ev().Syscall().number;\n  if (0 > ret) {\n    syscall_not_restarted(t);\n  } else if (t->arch() == x86 || t->arch() == x86_64) {\n    SupportedArch arch;\n    if (get_syscall_instruction_arch(t, t->regs().ip(), &arch) && arch == t->arch() &&\n        (syscallno == ret || is_restart_syscall_syscall(ret, t->ev().Syscall().arch()))) {\n      return;\n    }\n    syscall_not_restarted(t);\n  }\n}\n\n/**\n * Copy the registers used for syscall arguments (not including\n * syscall number) from |from| to |to|.\n */\nstatic void copy_syscall_arg_regs(Registers* to, const Registers& from) {\n  to->set_orig_arg1(from.arg1());\n  to->set_arg2(from.arg2());\n  to->set_arg3(from.arg3());\n  to->set_arg4(from.arg4());\n  to->set_arg5(from.arg5());\n  to->set_arg6(from.arg6());\n}\n\nstatic void maybe_trigger_emulated_ptrace_syscall_exit_stop(RecordTask* t) {\n  if (t->emulated_ptrace_cont_command == PTRACE_SYSCALL) {\n    t->emulate_ptrace_stop(WaitStatus::for_syscall(t), SYSCALL_EXIT_STOP);\n  } else if (is_ptrace_any_singlestep(t->arch(), t->emulated_ptrace_cont_command)) {\n    // Deliver the singlestep trap now that we've finished executing the\n    // syscall.\n    t->emulate_ptrace_stop(WaitStatus::for_stop_sig(SIGTRAP), SIGNAL_DELIVERY_STOP, nullptr,\n                           SI_KERNEL);\n  }\n}\n\nstatic void save_interrupted_syscall_ret_in_syscallbuf(RecordTask* t,\n                                                       intptr_t retval) {\n  // Record storing the return value in the syscallbuf record, where\n  // we expect to find it during replay.\n  auto child_rec = t->next_syscallbuf_record();\n  // Also store it there now so that our memory checksums are correct.\n  // It will be overwritten by the tracee's syscallbuf code.\n  t->write_and_record(REMOTE_PTR_FIELD(child_rec, ret),\n                      static_cast<int64_t>(retval));\n}\n\nstatic bool is_in_privileged_syscall(RecordTask* t) {\n  auto type = AddressSpace::rr_page_syscall_from_exit_point(t->arch(), t->ip());\n  return type && type->privileged == AddressSpace::PRIVILEGED;\n}\n\nvoid RecordSession::syscall_state_changed(RecordTask* t,\n                                          StepState* step_state) {\n  switch (t->ev().Syscall().state) {\n    case ENTERING_SYSCALL_PTRACE:\n      debug_exec_state(\"EXEC_SYSCALL_ENTRY_PTRACE\", t);\n      step_state->continue_type = DONT_CONTINUE;\n      last_task_switchable = ALLOW_SWITCH;\n      if (t->emulated_stop_type != NOT_STOPPED) {\n        // Don't go any further.\n        return;\n      }\n      if (t->ev().Syscall().in_sysemu) {\n        // We'll have recorded just the ENTERING_SYSCALL_PTRACE event and\n        // nothing else. Resume with an invalid syscall to ensure no real\n        // syscall runs.\n        t->pop_syscall();\n        Registers r = t->regs();\n        Registers orig_regs = r;\n        r.set_original_syscallno(-1);\n        t->set_regs(r);\n        // If this fails because of premature exit, don't mess with the\n        // task anymore.\n        if (t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n          ASSERT(t, t->ip() == r.ip());\n          t->set_regs(orig_regs);\n          maybe_trigger_emulated_ptrace_syscall_exit_stop(t);\n        }\n        return;\n      }\n      last_task_switchable = PREVENT_SWITCH;\n      t->ev().Syscall().regs = t->regs();\n      t->ev().Syscall().state = ENTERING_SYSCALL;\n      // The syscallno may have been changed by the ptracer\n      t->ev().Syscall().number = t->regs().original_syscallno();\n      return;\n\n    case ENTERING_SYSCALL: {\n      debug_exec_state(\"EXEC_SYSCALL_ENTRY\", t);\n      ASSERT(t, !t->emulated_stop_pending);\n\n      // Flush syscallbuf now so that anything recorded by\n      // rec_prepare_syscall is associated with the syscall event\n      t->maybe_flush_syscallbuf();\n\n      last_task_switchable = t->ev().Syscall().switchable =\n          rec_prepare_syscall(t);\n      t->record_event(t->ev(), RecordTask::DONT_FLUSH_SYSCALLBUF,\n                      RecordTask::ALLOW_RESET_SYSCALLBUF,\n                      &t->ev().Syscall().regs);\n\n      debug_exec_state(\"after cont\", t);\n      t->ev().Syscall().state = PROCESSING_SYSCALL;\n\n      if (t->emulated_stop_pending) {\n        step_state->continue_type = DONT_CONTINUE;\n      } else {\n        // Resume the syscall execution in the kernel context.\n        step_state->continue_type = CONTINUE_SYSCALL;\n      }\n\n      if (t->session().done_initial_exec() && Flags::get().check_cached_mmaps) {\n        t->vm()->verify(t);\n      }\n\n      if (t->desched_rec() && t->is_in_untraced_syscall() &&\n          t->has_stashed_sig()) {\n        // We have a signal to deliver but we're about to (re?)enter an untraced\n        // syscall that may block and the desched event has been disarmed.\n        // Rearm the desched event so if the syscall blocks, it will be\n        // interrupted and we'll have a chance to deliver our signal.\n        LOG(debug) << \"Rearming desched event so we'll get a chance to deliver \"\n                      \"stashed signal\";\n        arm_desched_event(t);\n      }\n\n      if (t->detached_proxy) {\n        // We detached. Record that.\n        t->session().trace_writer().write_task_event(\n            TraceTaskEvent::for_detach(t->tid));\n        t->record_event(Event::exit(), RecordTask::DONT_FLUSH_SYSCALLBUF,\n          RecordTask::DONT_RESET_SYSCALLBUF);\n        step_state->continue_type = DONT_CONTINUE;\n      }\n\n      return;\n    }\n\n    case PROCESSING_SYSCALL:\n      debug_exec_state(\"EXEC_IN_SYSCALL\", t);\n\n      // Linux kicks tasks out of syscalls before delivering\n      // signals.\n      ASSERT(t, !t->stop_sig()) << \"Signal \" << signal_name(t->stop_sig())\n                                << \" pending while in syscall???\";\n\n      t->ev().Syscall().state = EXITING_SYSCALL;\n      step_state->continue_type = DONT_CONTINUE;\n      return;\n\n    case EXITING_SYSCALL: {\n      debug_exec_state(\"EXEC_SYSCALL_DONE\", t);\n\n      DEBUG_ASSERT(t->stop_sig() == 0);\n\n      SupportedArch syscall_arch = t->ev().Syscall().arch();\n      int syscallno = t->ev().Syscall().number;\n      intptr_t retval = t->regs().syscall_result_signed();\n\n      if (t->desched_rec()) {\n        // If we enabled the desched event above, disable it.\n        disarm_desched_event(t);\n        // Write syscall return value to the syscallbuf now. This lets replay\n        // get the correct value even though we're aborting the commit. This\n        // value affects register values in the preload code (which must be\n        // correct since register values may escape).\n        save_interrupted_syscall_ret_in_syscallbuf(t, retval);\n      }\n\n      // sigreturn is a special snowflake, because it\n      // doesn't actually return.  Instead, it undoes the\n      // setup for signal delivery, which possibly includes\n      // preparing the tracee for a restart-syscall.  So we\n      // take this opportunity to possibly pop an\n      // interrupted-syscall event.\n      if (is_sigreturn(syscallno, syscall_arch)) {\n        if (is_x86ish(t->arch())) {\n          ASSERT(t, t->regs().original_syscallno() == -1);\n        }\n        rec_did_sigreturn(t);\n        t->record_current_event();\n        t->pop_syscall();\n\n        // We've finished processing this signal now.\n        t->pop_signal_handler();\n        t->invalidate_sigmask();\n\n        maybe_discard_syscall_interruption(t, retval);\n\n        if (EV_SECCOMP_TRAP == t->ev().type()) {\n          LOG(debug) << \"  exiting seccomp trap\";\n          save_interrupted_syscall_ret_in_syscallbuf(t, retval);\n          seccomp_trap_done(t);\n        }\n        if (EV_DESCHED == t->ev().type()) {\n          LOG(debug) << \"  exiting desched critical section\";\n          // The signal handler could have modified the apparent syscall\n          // return handler. Save that value into the syscall buf again so\n          // replay will pick it up later.\n          save_interrupted_syscall_ret_in_syscallbuf(t, retval);\n          desched_state_changed(t);\n        }\n      } else {\n        LOG(debug) << \"  original_syscallno:\" << t->regs().original_syscallno()\n                   << \" (\" << syscall_name(syscallno, syscall_arch)\n                   << \"); return val:\" << HEX(t->regs().syscall_result());\n\n        /* a syscall_restart ending is equivalent to the\n         * restarted syscall ending */\n        if (t->ev().Syscall().is_restart) {\n          LOG(debug) << \"  exiting restarted \"\n                     << syscall_name(syscallno, syscall_arch);\n        }\n\n        // Wait-like syscalls always check for notifications from waited-for processes\n        // before they check for pending signals. So, if the tracee has a pending\n        // notification that also generated a signal, the wait syscall returns\n        // normally rather than returning with ERESTARTSYS etc. (The signal will\n        // be dequeued and any handler run on the return to userspace, however.)\n        bool return_normally_from_wait = rec_return_normally_from_wait(t);\n\n        /* TODO: is there any reason a restart_syscall can't\n         * be interrupted by a signal and itself restarted? */\n        bool may_restart = !is_restart_syscall_syscall(syscallno, t->arch())\n                           // SYS_pause is either interrupted or\n                           // never returns.  It doesn't restart.\n                           && !is_pause_syscall(syscallno, t->arch()) &&\n                           t->regs().syscall_may_restart() &&\n                           !return_normally_from_wait;\n        /* no need to process the syscall in case its\n         * restarted this will be done in the exit from the\n         * restart_syscall */\n        if (!may_restart) {\n          rec_process_syscall(t);\n          if (t->session().done_initial_exec() &&\n              Flags::get().check_cached_mmaps) {\n            t->vm()->verify(t);\n          }\n        } else {\n          LOG(debug) << \"  may restart \"\n                     << syscall_name(syscallno, syscall_arch)\n                     << \" (from retval \" << HEX(retval) << \")\";\n\n          rec_prepare_restart_syscall(t);\n          /* If we may restart this syscall, we've most\n           * likely fudged some of the argument\n           * registers with scratch pointers.  We don't\n           * want to record those fudged registers,\n           * because scratch doesn't exist in replay.\n           * So cover our tracks here. */\n          Registers r = t->regs();\n          copy_syscall_arg_regs(&r, t->ev().Syscall().regs);\n          t->set_regs(r);\n          // We need to track what the return value was on architectures\n          // where the kernel replaces the return value by the new arg1\n          // on restart.\n          t->ev().Syscall().regs = r;\n        }\n        t->record_current_event();\n\n        /* If we're not going to restart this syscall, we're\n         * done with it.  But if we are, \"freeze\" it on the\n         * event stack until the execution point where it\n         * might be restarted. */\n        bool need_patch_retry = false;\n        remote_code_ptr orig_syscall_ip;\n        if (!may_restart) {\n          need_patch_retry = t->ev().Syscall().should_retry_patch;\n          if (need_patch_retry) {\n            orig_syscall_ip = t->ev().Syscall().regs.ip();\n          }\n          t->pop_syscall();\n          if (EV_DESCHED == t->ev().type()) {\n            LOG(debug) << \"  exiting desched critical section\";\n            desched_state_changed(t);\n          }\n        } else {\n          t->ev().transform(EV_SYSCALL_INTERRUPTION);\n          t->ev().Syscall().is_restart = true;\n        }\n\n        t->canonicalize_regs(syscall_arch);\n\n        if (need_patch_retry) {\n          LOG(debug) << \"Retrying deferred syscall patching at \" << orig_syscall_ip << \" (current ip \" << t->regs().ip() << \")\";\n          retry_syscall_patch(t, orig_syscall_ip);\n        }\n      }\n\n      last_task_switchable = ALLOW_SWITCH;\n      step_state->continue_type = DONT_CONTINUE;\n\n      if (!is_in_privileged_syscall(t)) {\n        maybe_trigger_emulated_ptrace_syscall_exit_stop(t);\n      }\n      return;\n    }\n\n    default:\n      FATAL() << \"Unknown exec state \" << t->ev().Syscall().state;\n  }\n}\n\n/** If the perf counters seem to be working return, otherwise don't return. */\nvoid RecordSession::check_initial_task_syscalls(RecordTask* t,\n                                                RecordResult* step_result) {\n  if (done_initial_exec()) {\n    return;\n  }\n\n  if (is_write_syscall(t->ev().Syscall().number, t->arch()) &&\n      t->regs().arg1_signed() == -1) {\n    Ticks ticks = t->tick_count();\n    LOG(debug) << \"ticks on entry to dummy write: \" << ticks;\n    if (ticks == 0) {\n      step_result->status = RecordSession::STEP_SPAWN_FAILED;\n      step_result->failure_message = string(\n          \"rr internal recorder error: Performance counter doesn't seem to \"\n          \"be working. Are you perhaps running rr in a VM but didn't enable \"\n          \"perf-counter virtualization?\");\n    }\n  }\n\n  if (is_exit_group_syscall(t->ev().Syscall().number, t->arch())) {\n    step_result->status = RecordSession::STEP_SPAWN_FAILED;\n    step_result->failure_message = read_spawned_task_error();\n  }\n}\n\nRecordTask* RecordSession::revive_task_for_exec(pid_t rec_tid) {\n  unsigned long msg = 0;\n  int ret =\n      ptrace(_ptrace_request(PTRACE_GETEVENTMSG), rec_tid, nullptr, &msg);\n  if (ret < 0) {\n    FATAL() << \"Can't get old tid for execve (leader=\" << rec_tid << \")\";\n  }\n  RecordTask* t = find_task(msg);\n  if (!t) {\n    FATAL() << \"Can't find old task for execve\";\n  }\n  ASSERT(t, rec_tid == t->tgid());\n  pid_t own_namespace_tid = t->thread_group()->tgid_own_namespace;\n\n  LOG(debug) << \"Changing task tid from \" << t->tid << \" to \" << rec_tid;\n\n  // Pretend the old task cloned a new task with the right tid, and then exited\n  trace_writer().write_task_event(TraceTaskEvent::for_clone(\n      rec_tid, t->tid, own_namespace_tid,\n      CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD |\n          CLONE_SYSVSEM));\n  trace_writer().write_task_event(\n      TraceTaskEvent::for_exit(t->tid, WaitStatus::for_exit_code(0)));\n\n  // Account for tid change\n  task_map.erase(t->tid);\n  task_map.insert(make_pair(rec_tid, t));\n  // Update the serial as if this task was really created by cloning the old\n  // task.\n  t->set_tid_and_update_serial(rec_tid, own_namespace_tid);\n\n  return t;\n}\n\n/**\n * Take a NativeArch::siginfo_t& here instead of siginfo_t because different\n * versions of system headers have inconsistent field naming.\n */\ntemplate <typename Arch>\nstatic void setup_sigframe_siginfo_arch(RecordTask* t,\n                                        const siginfo_t& siginfo) {\n  remote_ptr<typename Arch::siginfo_t> dest;\n  switch (Arch::arch()) {\n    case x86: {\n      auto p = t->regs().sp().cast<typename Arch::unsigned_word>() + 2;\n      dest = t->read_mem(p);\n      break;\n    }\n    case x86_64:\n      dest = t->regs().si();\n      break;\n    case aarch64:\n      dest = t->regs().x(1);\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown architecture\");\n      break;\n  }\n  typename Arch::siginfo_t si = t->read_mem(dest);\n  set_arch_siginfo(siginfo, t->arch(), &si, sizeof(si));\n  t->write_mem(dest, si);\n}\n\nstatic void setup_sigframe_siginfo(RecordTask* t, const siginfo_t& siginfo) {\n  RR_ARCH_FUNCTION(setup_sigframe_siginfo_arch, t->arch(), t, siginfo);\n}\n\n/**\n * Get t into a state where resume_execution with a signal will actually work.\n */\nstatic bool preinject_signal(RecordTask* t) {\n  int sig = t->ev().Signal().siginfo.si_signo;\n\n  /* Signal injection is tricky. Per the ptrace(2) man page, injecting\n   * a signal while the task is not in a signal-stop is not guaranteed to work\n   * (and indeed, we see that the kernel sometimes ignores such signals).\n   * But some signals must be delayed until after the signal-stop that notified\n   * us of them.\n   * So, first we check if we're in a signal-stop that we can use to inject\n   * a signal.\n   */\n  if (t->in_injectable_signal_stop()) {\n    LOG(debug) << \"    in signal-stop for \" << signal_name(t->stop_sig());\n  } else {\n    /* We're not in a usable signal-stop. Force a signal-stop by sending\n     * a new signal with tgkill (as the ptrace(2) man page recommends).\n     */\n    LOG(debug) << \"    maybe not in signal-stop (status \" << t->status()\n               << \"); doing tgkill(SYSCALLBUF_DESCHED_SIGNAL)\";\n    if (!t->move_to_signal_stop()) {\n      /* We raced with an exit (e.g. due to a pending SIGKILL). */\n      return false;\n    }\n\n    ASSERT(t, t->stop_sig() == t->session().syscallbuf_desched_sig())\n        << \"Expected SYSCALLBUF_DESCHED_SIGNAL, got \" << t->status();\n    /* We're now in a signal-stop */\n  }\n\n  /* Now that we're in a signal-stop, we can inject our signal and advance\n   * to the signal handler with one single-step.\n   */\n  LOG(debug) << \"    injecting signal \" << signal_name(sig);\n  t->set_siginfo(t->ev().Signal().siginfo);\n  return true;\n}\n\n// More memory than we'll need for a sigframe\nstatic const size_t CONSERVATIVE_SIGFRAME_MEM = 0x10000;\n\n// We might need to extend a MAP_GROWSDOWN stack mapping to have\n// space for the sigframe. Do that now. We don't know how big\n// the sigframe is going to be, so we just try to ensure we have 64K\n// available. Should be harmless to allocate more than we strictly need.\n// If something's in the way we just allocate as much as we can.\nstatic void maybe_grow_stack_for_sigframe(RecordTask* t) {\n  auto sp = t->regs().sp();\n  AddressSpace& vm = *t->vm();\n  if (!vm.has_mapping(sp)) {\n    return;\n  }\n  AddressSpace::Mapping stack_mapping = vm.mapping_of(sp);\n  remote_ptr<void> desired_sp =\n    max(remote_ptr<void>(CONSERVATIVE_SIGFRAME_MEM + page_size()), sp) - CONSERVATIVE_SIGFRAME_MEM;\n  if (desired_sp >= stack_mapping.map.start()) {\n    // desired_sp is in the current stack map so we're good.\n    return;\n  }\n  auto maps = vm.maps_containing_or_after(desired_sp - page_size());\n  // The iterator must have the current stack map at least\n  ASSERT(t, maps.begin() != maps.end());\n\n  const AddressSpace::Mapping& m = *maps.begin();\n  if (m.map.start() == stack_mapping.map.start()) {\n    // No mapping is in the way.\n    t->try_grow_map(desired_sp);\n    return;\n  }\n\n  remote_ptr<void> last_end;\n  auto iter = maps.begin();\n  while (true) {\n    last_end = iter->map.end();\n    ++iter;\n    if (iter->map.start() == stack_mapping.map.start()) {\n      break;\n    }\n  }\n  if (last_end + page_size() >= stack_mapping.map.start()) {\n    // Don't try to grow the stack if there's no room for a guard page.\n    return;\n  }\n  t->try_grow_map(last_end + page_size());\n}\n\n/**\n * Returns true if the signal should be delivered.\n * Returns false if this signal should not be delivered because another signal\n * occurred during delivery or there was a premature exit.\n * Must call t->stashed_signal_processed() once we're ready to unmask signals.\n */\nstatic bool inject_handled_signal(RecordTask* t) {\n  maybe_grow_stack_for_sigframe(t);\n\n  if (!preinject_signal(t)) {\n    // Task prematurely exited.\n    return false;\n  }\n  // If there aren't any more stashed signals, it's OK to stop blocking all\n  // signals.\n  t->stashed_signal_processed();\n\n  int sig = t->ev().Signal().siginfo.si_signo;\n  int stop_sig;\n  while (true) {\n    // We are ready to inject our signal.\n    // Ideally we would block signals here so only the signal we care about can be raised.\n    // But that breaks all kinds of things because signal delivery itself can update\n    // the sigmaks (e.g. via sa_mask). Emulating all that would be painful, so we\n    // don't change the sigmask.\n    if (!t->resume_execution(RESUME_SINGLESTEP, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS, sig)) {\n      return false;\n    }\n    // We're expecting a kernel SIGTRAP from the singlestep, but we can also be notified\n    // of other pending signals unfortunately :-(.\n    stop_sig = t->stop_sig();\n    ASSERT(t, stop_sig) << \"Only signal-stops should occur here\";\n    if (t->get_siginfo().si_code > 0) {\n      // Signal was generated by the kernel (i.e. not via kill() etc).\n      // Signal injection can change the sigmask due to sa_mask effects, lack of\n      // SA_NODEFER, and signal frame construction triggering a synchronous\n      // SIGSEGV.\n      t->invalidate_sigmask();\n      // We should either have a SIGTRAP or possibly a SIGSEGV due to\n      // sigframe construction overflowing the stack.\n      break;\n    }\n    if (stop_sig == t->session().syscallbuf_desched_sig()) {\n      // Repeat injection if we got a desched signal. We observe in Linux 4.14.12\n      // that we get SYSCALLBUF_DESCHED_SIGNAL here once in a while.\n       continue;\n    }\n    if (stop_sig == sig && sig < SIGRTMIN) {\n      // Repeat injection if we got the same non-RT signal. We can coalesce\n      // this with the current undelivered signal so there's no need to stash it.\n      continue;\n    }\n    // Stash it for later processing and retry injecting our signal.\n    t->stash_sig();\n  }\n\n  if (stop_sig == SIGSEGV) {\n    // Constructing the signal handler frame must have failed. Stash the signal\n    // to deliver it later.\n    t->stash_sig();\n    if (sig == SIGSEGV) {\n      // The kernel will kill the process after this. Make sure we know to treat\n      // it as fatal when we inject it. Also disable the signal handler to match\n      // what the kernel does.\n      t->did_set_sig_handler_default(SIGSEGV);\n      t->thread_group()->received_sigframe_SIGSEGV = true;\n    }\n    return false;\n  }\n\n  // We stepped into a user signal handler.\n  ASSERT(t, stop_sig == SIGTRAP)\n      << \"Got unexpected status \" << t->status() << \" trying to deliver \"\n      << signal_name(sig) << \" siginfo is \" << t->get_siginfo();\n  ASSERT(t, t->get_signal_user_handler(sig) == t->ip())\n      << \"Expected handler IP \" << t->get_signal_user_handler(sig) << \", got \"\n      << t->ip()\n      << \"; actual signal mask=\" << HEX(t->read_sigmask_from_process())\n      << \" (cached \" << HEX(t->get_sigmask()) << \")\";\n\n  if (t->signal_handler_takes_siginfo(sig)) {\n    // The kernel copied siginfo into userspace so it can pass a pointer to\n    // the signal handler. Replace the contents of that siginfo with\n    // the exact data we want to deliver. (We called Task::set_siginfo\n    // above to set that data, but the kernel sanitizes the passed-in data\n    // which wipes out certain fields; e.g. we can't set SI_KERNEL in si_code.)\n    setup_sigframe_siginfo(t, t->ev().Signal().siginfo);\n  }\n\n  // The kernel clears the FPU state on entering the signal handler, but prior\n  // to 4.7 or thereabouts ptrace can still return stale values. Fix that here.\n  // This also sets bit 0 of the XINUSE register to 1 to avoid issues where it\n  // get set to 1 nondeterministically.\n  if (auto e_ptr = t->extra_regs_fallible()) {\n    ExtraRegisters e = *e_ptr;\n    e.reset();\n    t->set_extra_regs(e);\n  }\n\n  return true;\n}\n\n/**\n * |t| is being delivered a signal, and its state changed.\n * Must call t->stashed_signal_processed() once we're ready to unmask signals.\n */\nbool RecordSession::signal_state_changed(RecordTask* t, StepState* step_state) {\n  int sig = t->ev().Signal().siginfo.si_signo;\n\n  switch (t->ev().type()) {\n    case EV_SIGNAL: {\n      // This event is used by the replayer to advance to\n      // the point of signal delivery.\n      if (t->arch() == aarch64 && t->status().is_syscall() &&\n          t->prev_ev() && t->prev_ev()->type() == EV_SYSCALL_INTERRUPTION) {\n        // On aarch64, replaying expects the signal to be delivered before\n        // the syscall instruction but the current pc during recording\n        // is after the syscall instruction with the arg1 clobbered\n        // with the return value (aborted syscall).\n        auto regs = t->regs();\n        auto &syscall_regs = t->prev_ev()->Syscall().regs;\n        regs.set_ip(syscall_regs.ip().decrement_by_syscall_insn_length(t->arch()));\n        regs.set_arg1(syscall_regs.orig_arg1());\n        t->record_event(t->ev(), RecordTask::FLUSH_SYSCALLBUF,\n                        RecordTask::ALLOW_RESET_SYSCALLBUF, &regs);\n      } else {\n        t->record_current_event();\n      }\n      t->ev().transform(EV_SIGNAL_DELIVERY);\n      ssize_t sigframe_size = 0;\n\n      bool has_handler = t->signal_has_user_handler(sig);\n      if (has_handler) {\n        LOG(debug) << \"  \" << t->tid << \": \" << signal_name(sig)\n                   << \" has user handler\";\n\n        if (!inject_handled_signal(t)) {\n          // Signal delivery isn't happening. Prepare to process the new\n          // signal that aborted signal delivery.\n          t->signal_delivered(sig);\n          t->pop_signal_delivery();\n          step_state->continue_type = DONT_CONTINUE;\n          last_task_switchable = PREVENT_SWITCH;\n          break;\n        }\n\n        if (is_x86ish(t->arch())) {\n          // It's somewhat difficult engineering-wise to\n          // compute the sigframe size at compile time,\n          // and it can vary across kernel versions and CPU\n          // microarchitectures. So this size is an overestimate\n          // of the real size(s).\n          //\n          // If this size becomes too small in the\n          // future, and unit tests that use sighandlers\n          // are run with checksumming enabled, then\n          // they can catch errors here.\n          sigframe_size = 1152 /* Overestimate of kernel sigframe */ +\n                          128 /* Redzone */ +\n                          /* this returns 512 when XSAVE unsupported */\n                          xsave_area_size();\n        } else if (t->arch() == aarch64) {\n          sigframe_size = sizeof(ARM64Arch::rt_sigframe);\n        } else {\n          DEBUG_ASSERT(0 && \"Add sigframe size for your architecture here\");\n        }\n\n        t->ev().transform(EV_SIGNAL_HANDLER);\n        t->signal_delivered(sig);\n        // We already continued! Don't continue now, and allow switching.\n        step_state->continue_type = DONT_CONTINUE;\n        last_task_switchable = ALLOW_SWITCH;\n      } else {\n        t->stashed_signal_processed();\n        LOG(debug) << \"  \" << t->tid << \": no user handler for \"\n                   << signal_name(sig);\n        // Don't do another task continue. We want to deliver the signal\n        // as the next thing that the task does.\n        step_state->continue_type = DONT_CONTINUE;\n        // If we didn't set up the sighandler frame, we need\n        // to ensure that this tracee is scheduled next so\n        // that we can deliver the signal normally.  We have\n        // to do that because setting up the sighandler frame\n        // is synchronous, but delivery otherwise is async.\n        // But right after this, we may have to process some\n        // syscallbuf state, so we can't let the tracee race\n        // with us.\n        last_task_switchable = PREVENT_SWITCH;\n      }\n\n      // We record this data even if sigframe_size is zero to simplify replay.\n      // Stop recording data if we run off the end of a writable mapping.\n      // Our sigframe size is conservative so we need to do this.\n      t->record_remote_writable(t->regs().sp(), sigframe_size,\n                                MemWriteSizeValidation::CONSERVATIVE);\n\n      // This event is used by the replayer to set up the signal handler frame.\n      // But if we don't have a handler, we don't want to record the event\n      // until we deal with the EV_SIGNAL_DELIVERY.\n      if (has_handler) {\n        t->record_current_event();\n      }\n      break;\n    }\n\n    case EV_SIGNAL_DELIVERY: {\n      // A SIGSTOP requires us to allow switching to another task.\n      // So does a fatal, core-dumping signal, since we need to allow other\n      // tasks to proceed to their exit events.\n      bool is_deterministic = t->ev().Signal().deterministic == DETERMINISTIC_SIG;\n      // Signals that would normally be fatal are just ignored for init processes,\n      // unless they're deterministic.\n      bool is_fatal = t->ev().Signal().disposition == DISPOSITION_FATAL &&\n        (!t->is_container_init() || is_deterministic);\n      Switchable can_switch =\n        ((is_fatal && is_coredumping_signal(sig)) || t->is_sig_stopping(sig)) ?\n        ALLOW_SWITCH : PREVENT_SWITCH;\n\n      // We didn't record this event above, so do that now.\n      // NB: If there is no handler, and we interrupted a syscall, and there are\n      // no more actionable signals, the kernel sets us up for a syscall\n      // restart. But it does that *after* the ptrace trap. To replay this\n      // correctly we need to fake those changes here. But we don't do this\n      // if we're going to switch away at the ptrace trap, and for the moment,\n      // 'can_switch' is actually 'will_switch'.\n      // This is essentially copied from do_signal in arch/x86/kernel/signal.c\n      bool has_other_signals = t->has_any_actionable_signal();\n      auto r = t->regs();\n      if (!is_fatal) {\n        Event *prev_ev = t->prev_ev();\n        if (can_switch == PREVENT_SWITCH && !has_other_signals && prev_ev &&\n            EV_SYSCALL_INTERRUPTION == prev_ev->type()) {\n          switch (prev_ev->Syscall().regs.syscall_result_signed()) {\n            case -ERESTARTNOHAND:\n            case -ERESTARTSYS:\n            case -ERESTARTNOINTR:\n              r.set_syscallno(r.original_syscallno());\n              break;\n            case -ERESTART_RESTARTBLOCK:\n              r.set_syscallno(syscall_number_for_restart_syscall(t->arch()));\n              break;\n          }\n          // On aarch64, the kernel modifies the registers before the signal stop.\n          // so we should not decrement the pc again or we'll rerun the instruction\n          // before the syscall.\n          // [1] https://github.com/torvalds/linux/blob/caffb99b6929f41a69edbb5aef3a359bf45f3315/arch/arm64/kernel/signal.c#L855-L862\n          if (t->arch() != aarch64)\n            r.set_ip(r.ip().decrement_by_syscall_insn_length(t->arch()));\n          // Now that we've mucked with the registers, we can't switch tasks. That\n          // could allow more signals to be generated, breaking our assumption\n          // that we are the last signal.\n        } else {\n          // But if we didn't touch the registers switching here is ok.\n          can_switch = ALLOW_SWITCH;\n        }\n      }\n\n      t->record_event(t->ev(), RecordTask::FLUSH_SYSCALLBUF,\n                      RecordTask::ALLOW_RESET_SYSCALLBUF, &r);\n      // Don't actually set_regs(r), the kernel does these modifications.\n\n      if (t->is_container_init() && is_fatal) {\n        // Nondeterministic signals were already filtered out.\n        ASSERT(t, is_deterministic);\n        // Usually, the kernel removes the killable-protection from an init process\n        // when a deterministic fatal signal gets executed, but (due to what is\n        // arguably a bug) when a ptracer is attached, this does not happen.\n        // If we try to inject it here, the kernel will just ignore it,\n        // and we'll go around again. As a hack, we detach here, in the\n        // expectation that the deterministic instruction will run again and\n        // actually kill the task now that it isn't under ptrace control anymore.\n        t->destroy_buffers(nullptr, nullptr);\n        WaitStatus exit_status = WaitStatus::for_fatal_sig(sig);\n        t->record_exit_trace_event(exit_status);\n        // Allow writing child_tid now because otherwise the write will race\n        t->record_exit_event(RecordTask::WRITE_CHILD_TID);\n        // On a real affected kernel, we probably would have never gotten here,\n        // since the signal we would be seeing was not deterministic, but let's\n        // be conservative and still try to emulate the ptrace stop.\n        t->do_ptrace_exit_stop(exit_status);\n        t->did_kill();\n        t->detach();\n        // Not really, but we detached, so we're never gonna see that event\n        // anyway, so just pretend we're there already\n        t->did_reach_zombie();\n        return true;\n      }\n\n      // Only inject fatal signals. Non-fatal signals with signal handlers\n      // were taken care of above; for non-fatal signals without signal\n      // handlers, there is no need to deliver the signal at all. In fact,\n      // there is really no way to inject a non-fatal, non-handled signal\n      // without letting the task execute at least one instruction, which\n      // we don't want to do here.\n      bool inject_signal = is_fatal && sig != get_continue_through_sig();\n      if (inject_signal) {\n        preinject_signal(t);\n        t->resume_execution(RESUME_CONT, RESUME_NONBLOCKING, RESUME_NO_TICKS,\n                            sig);\n      }\n\n      t->signal_delivered(sig);\n      if (!inject_signal || !is_coredumping_signal(sig)) {\n        /* Fatal signals may core-dump, so we don't consider the signal\n         * delivery complete until we've actually managed to advance past that\n         */\n        t->pop_signal_delivery();\n      }\n\n      // Mark each task in this address space as expecting a ptrace exit\n      // to avoid causing any ptrace_exit races.\n      if (is_fatal && is_coredumping_signal(sig)) {\n        for (Task *ot : t->vm()->task_set()) {\n          if (t != ot) {\n            if (t->tgid() == ot->tgid() || coredumping_signal_takes_down_entire_vm()) {\n              ((RecordTask *)ot)->waiting_for_ptrace_exit = true;\n            }\n          }\n        }\n      }\n\n      last_task_switchable = can_switch;\n      step_state->continue_type = DONT_CONTINUE;\n      break;\n    }\n\n    default:\n      FATAL() << \"Unhandled signal state \" << t->ev().type();\n      break;\n  }\n  return false;\n}\n\nbool RecordSession::handle_signal_event(RecordTask* t, StepState* step_state) {\n  int sig = t->stop_sig();\n  if (!sig) {\n    return false;\n  }\n  if (!done_initial_exec()) {\n    // If the initial tracee isn't prepared to handle\n    // signals yet, then us ignoring the ptrace\n    // notification here will have the side effect of\n    // declining to deliver the signal.\n    //\n    // This doesn't really occur in practice, only in\n    // tests that force a degenerately low time slice.\n    LOG(warn) << \"Dropping \" << signal_name(sig)\n              << \" because it can't be delivered yet\";\n    // These signals might have effects on the sigmask.\n    t->invalidate_sigmask();\n    // No events to be recorded, so no syscallbuf updates\n    // needed.\n    return true;\n  }\n\n  if (sig == SIGTRAP && handle_syscallbuf_breakpoint(t)) {\n    return true;\n  }\n\n  SignalDeterministic deterministic = is_deterministic_signal(t);\n  // The kernel might have forcibly unblocked the signal. Check whether it\n  // was blocked now, before we update our cached sigmask.\n  SignalBlocked signal_was_blocked =\n      t->is_sig_blocked(sig) ? SIG_BLOCKED : SIG_UNBLOCKED;\n  if (deterministic || sig == t->session().syscallbuf_desched_sig()) {\n    // Don't stash these signals; deliver them immediately.\n    // We don't want them to be reordered around other signals.\n    // invalidate_sigmask() must not be called before we reach handle_signal!\n    siginfo_t siginfo = t->get_siginfo();\n    switch (handle_signal(t, &siginfo, deterministic, signal_was_blocked)) {\n      case SIGNAL_PTRACE_STOP:\n        // Emulated ptrace-stop. Don't run the task again yet.\n        last_task_switchable = ALLOW_SWITCH;\n        step_state->continue_type = DONT_CONTINUE;\n        return true;\n      case DEFER_SIGNAL:\n        ASSERT(t, false) << \"Can't defer deterministic or internal signal \"\n                         << siginfo << \" at ip \" << t->ip();\n        break;\n      case SIGNAL_HANDLED:\n        if (t->ptrace_event() == PTRACE_EVENT_SECCOMP) {\n          // `handle_desched_event` detected a spurious desched followed\n          // by a SECCOMP event, which it left pending. Handle that SECCOMP\n          // event now.\n          bool dummy_did_enter_syscall;\n          handle_ptrace_event(&t, step_state, nullptr,\n                              &dummy_did_enter_syscall);\n          ASSERT(t, !dummy_did_enter_syscall);\n        }\n        if (t->ptrace_event() == PTRACE_EVENT_EXIT) {\n          // Tracee was nuked (probably SIGKILL) during desched processing.\n          return true;\n        }\n        break;\n    }\n    return false;\n  }\n  // Conservatively invalidate the sigmask in case just accepting a signal has\n  // sigmask effects.\n  t->invalidate_sigmask();\n  if (sig == PerfCounters::TIME_SLICE_SIGNAL) {\n    if (t->next_pmc_interrupt_is_for_user) {\n      auto vpmc =\n          VirtualPerfCounterMonitor::interrupting_virtual_pmc_for_task(t);\n      ASSERT(t, vpmc);\n\n      // Synthesize the requested signal.\n      vpmc->synthesize_signal(t);\n\n      t->next_pmc_interrupt_is_for_user = false;\n      return true;\n    }\n\n    auto& si = t->get_siginfo();\n    /* This implementation will of course fall over if rr tries to\n     * record itself.\n     *\n     * NB: we can't check that the ticks is >= the programmed\n     * target, because this signal may have become pending before\n     * we reset the HPC counters.  There be a way to handle that\n     * more elegantly, but bridge will be crossed in due time.\n     *\n     * We can't check that the fd matches t->hpc.ticks_fd() because this\n     * signal could have been queued quite a long time ago and the PerfCounters\n     * might have been stopped (and restarted!), perhaps even more than once,\n     * since the signal was queued. possibly changing its fd. We could check\n     * against all fds the PerfCounters have ever used, but that seems like\n     * overkill.\n     */\n    ASSERT(t,\n           PerfCounters::TIME_SLICE_SIGNAL == si.si_signo &&\n               (RecordTask::SYNTHETIC_TIME_SLICE_SI_CODE == si.si_code ||\n                POLL_IN == si.si_code))\n        << \"Tracee is using SIGSTKFLT??? (code=\" << si.si_code\n        << \", fd=\" << si.si_fd << \")\";\n  }\n  t->stash_sig();\n  return true;\n}\n\ntemplate <typename Arch>\nstatic bool is_ptrace_any_sysemu_arch(int command) {\n  return command >= 0 &&\n    (command == Arch::PTRACE_SYSEMU ||\n     command == Arch::PTRACE_SYSEMU_SINGLESTEP);\n}\n\nstatic bool is_ptrace_any_sysemu(SupportedArch arch, int command)\n{\n  RR_ARCH_FUNCTION(is_ptrace_any_sysemu_arch, arch, command);\n}\n\nbool RecordSession::process_syscall_entry(RecordTask* t, StepState* step_state,\n                                          RecordResult* step_result,\n                                          SupportedArch syscall_arch) {\n  if (const RecordTask::StashedSignal* sig = t->stashed_sig_not_synthetic_SIGCHLD()) {\n    // The only four cases where we allow a stashed signal to be pending on\n    // syscall entry are:\n    // -- the signal is a ptrace-related signal, in which case if it's generated\n    // during a blocking syscall, it does not interrupt the syscall\n    // -- rrcall_notify_syscall_hook_exit, which is effectively a noop and\n    // lets us dispatch signals afterward\n    // -- when we're entering a blocking untraced syscall. If it really blocks,\n    // we'll get the desched-signal notification and dispatch our stashed\n    // signal.\n    // -- when we're doing a privileged syscall that's internal to the preload\n    // logic\n    // We do not generally want to have stashed signals pending when we enter\n    // a syscall, because that will execute with a hacked signal mask\n    // (see RecordTask::will_resume_execution) which could make things go wrong.\n    ASSERT(t,\n           t->desched_rec() || is_rrcall_notify_syscall_hook_exit_syscall(\n                                   t->regs().original_syscallno(), t->arch()) ||\n               t->ip() ==\n                   t->vm()\n                       ->privileged_traced_syscall_ip()\n                       .increment_by_syscall_insn_length(t->arch()))\n      << \"Stashed signal pending on syscall entry when it shouldn't be: \"\n      << sig->siginfo << \"; regs=\" << t->regs()\n      << \"; last_execution_resume=\" << t->last_execution_resume()\n      << \"; sig ip=\" << sig->ip;\n  }\n\n  // We just entered a syscall.\n  if (!maybe_restart_syscall(t)) {\n    if (syscall_seccomp_ordering_ == PTRACE_SYSCALL_BEFORE_SECCOMP_UNKNOWN &&\n        t->seccomp_bpf_enabled) {\n      // We received a PTRACE_SYSCALL notification before the seccomp\n      // notification. Ignore it and continue to the seccomp notification.\n      syscall_seccomp_ordering_ = PTRACE_SYSCALL_BEFORE_SECCOMP;\n      step_state->continue_type = CONTINUE;\n      return true;\n    }\n\n    // Don't ever patch a sigreturn syscall. These can't go through the syscallbuf.\n    bool should_retry = false;\n    if (!is_sigreturn(t->regs().original_syscallno(), t->arch())) {\n      if (t->vm()->monkeypatcher().try_patch_syscall(t, true, should_retry)) {\n        // Syscall was patched. Emit event and continue execution.\n        t->record_event(Event::patch_syscall());\n        return true;\n      }\n      if (!t->is_stopped()) {\n        // task exited while we were trying to patch it.\n        // Make sure that this exit event gets processed\n        step_state->continue_type = DONT_CONTINUE;\n        return false;\n      }\n    }\n\n    t->push_event(SyscallEvent(t->regs().original_syscallno(), syscall_arch));\n    t->ev().Syscall().should_retry_patch = should_retry;\n  }\n\n  check_initial_task_syscalls(t, step_result);\n  note_entering_syscall(t);\n  if ((t->emulated_ptrace_cont_command == PTRACE_SYSCALL ||\n       is_ptrace_any_sysemu(t->arch(),\n        t->emulated_ptrace_cont_command)) &&\n      !is_in_privileged_syscall(t)) {\n    t->ev().Syscall().state = ENTERING_SYSCALL_PTRACE;\n    t->emulate_ptrace_stop(WaitStatus::for_syscall(t), SYSCALL_ENTRY_STOP);\n    t->record_current_event();\n\n    t->ev().Syscall().in_sysemu = is_ptrace_any_sysemu(t->arch(),\n      t->emulated_ptrace_cont_command);\n  }\n  return true;\n}\n\n/**\n * The execution of |t| has just been resumed, and it most likely has\n * a new event that needs to be processed.  Prepare that new event.\n * Returns false if the task exits during processing\n */\nvoid RecordSession::runnable_state_changed(RecordTask* t, StepState* step_state,\n                                           RecordResult* step_result,\n                                           bool can_consume_wait_status) {\n  switch (t->ev().type()) {\n    case EV_NOOP:\n      t->pop_noop();\n      return;\n    case EV_INSTRUCTION_TRAP:\n      t->record_current_event();\n      t->pop_event(t->ev().type());\n      return;\n    case EV_SENTINEL:\n    case EV_SIGNAL_HANDLER:\n    case EV_SYSCALL_INTERRUPTION: {\n      if (!can_consume_wait_status) {\n        return;\n      }\n\n      SupportedArch syscall_arch = t->detect_syscall_arch();\n      t->canonicalize_regs(syscall_arch);\n      t->apply_syscall_entry_regs();\n      process_syscall_entry(t, step_state, step_result, syscall_arch);\n      return;\n    }\n\n    default:\n      return;\n  }\n}\n\nbool RecordSession::prepare_to_inject_signal(RecordTask* t,\n                                             StepState* step_state) {\n  if (!done_initial_exec() || step_state->continue_type != CONTINUE) {\n    return false;\n  }\n\n  union {\n    NativeArch::siginfo_t native_api;\n    siginfo_t linux_api;\n  } si;\n  const RecordTask::StashedSignal* sig;\n\n  while (true) {\n    sig = t->peek_stashed_sig_to_deliver();\n    if (!sig) {\n      return false;\n    }\n    si.linux_api = sig->siginfo;\n    if (si.linux_api.si_signo == get_ignore_sig()) {\n      LOG(debug) << \"Declining to deliver \"\n                 << signal_name(si.linux_api.si_signo) << \" by user request\";\n      t->pop_stash_sig(sig);\n      t->stashed_signal_processed();\n    } else {\n      break;\n    }\n  }\n\n  if (sig->deterministic == DETERMINISTIC_SIG &&\n      sig->siginfo.si_signo == SIGSYS &&\n      t->is_sig_blocked(sig->siginfo.si_signo) == SIG_BLOCKED) {\n    // Our synthesized deterministic SIGSYS (seccomp trap) needs to match the\n    // kernel behavior of unblocking the signal and resetting disposition to\n    // default.\n    t->unblock_signal(SIGSYS);\n    t->set_sig_handler_default(SIGSYS);\n  }\n  switch (handle_signal(t, &si.linux_api, sig->deterministic, SIG_UNBLOCKED)) {\n    case SIGNAL_PTRACE_STOP:\n      // Emulated ptrace-stop. Don't run the task again yet.\n      last_task_switchable = ALLOW_SWITCH;\n      LOG(debug) << signal_name(si.linux_api.si_signo)\n                 << \", emulating ptrace stop\";\n      break;\n    case DEFER_SIGNAL:\n      LOG(debug) << signal_name(si.linux_api.si_signo) << \" deferred\";\n      // Leave signal on the stack and continue task execution. We'll try again\n      // later.\n      return false;\n    case SIGNAL_HANDLED:\n      LOG(debug) << signal_name(si.linux_api.si_signo) << \" handled\";\n      // Signal is now a pending event on |t|'s event stack\n\n      if (t->ev().type() == EV_SCHED) {\n        if (t->maybe_in_spinlock()) {\n          LOG(debug) << \"Detected possible spinlock, forcing one round-robin\";\n          scheduler().schedule_one_round_robin(t);\n        }\n        // Allow switching after a SCHED. We'll flush the SCHED if and only\n        // if we really do a switch.\n        last_task_switchable = ALLOW_SWITCH;\n      }\n      break;\n  }\n  step_state->continue_type = DONT_CONTINUE;\n  t->pop_stash_sig(sig);\n  if (t->ev().type() != EV_SIGNAL) {\n    t->stashed_signal_processed();\n  }\n  return true;\n}\n\nstatic void inject_ld_helper_library(vector<string>& env,\n                                     string env_var,\n                                     string value) {\n  // Our preload lib should come first if possible, because that will speed up\n  // the loading of the other libraries; it's also a good idea to put our audit\n  // library at the head of the list, since there's only sixteen possible link\n  // namespaces on glibc and each audit library uses up one.\n  //\n  // We supply a placeholder which is then mutated to the correct filename in\n  // Monkeypatcher::patch_after_exec.\n  auto env_assignment = env_var + \"=\";\n  auto it = env.begin();\n  for (; it != env.end(); ++it) {\n    if (it->find(env_assignment) != 0) {\n      continue;\n    }\n    // Honor old preloads too.  This may cause\n    // problems, but only in those libs, and\n    // that's the user's problem.\n    value += \":\";\n    value += it->substr(it->find(\"=\") + 1);\n    break;\n  }\n  value = env_assignment + value;\n  if (it == env.end()) {\n    env.push_back(value);\n  } else {\n    *it = value;\n  }\n}\n\nvoid strip_outer_ld_preload(vector<string>& env) {\n  auto env_assignment = \"LD_PRELOAD=\";\n  auto it = env.begin();\n  for (; it != env.end(); ++it) {\n    if (it->find(env_assignment) != 0) {\n      continue;\n    }\n    size_t colon_pos = it->find(\":\");\n    if (colon_pos != string::npos) {\n      // If the preload library is loaded at all, it must be first\n      size_t preload_pos = it->find(\"librrpreload\");\n      if (preload_pos < colon_pos) {\n        string new_ld_preload = it->substr(++colon_pos);\n        *it = env_assignment + new_ld_preload;\n        return;\n      } else {\n        DEBUG_ASSERT(preload_pos == string::npos);\n      }\n    }\n  }\n}\n\nstatic const MemoryRange asan_shadow(remote_ptr<void>((uintptr_t)0x00007fff7000LL),\n                                     remote_ptr<void>((uintptr_t)0x10007fff8000LL));\nstatic const MemoryRange asan_allocator_reserved(remote_ptr<void>((uintptr_t)0x600000000000LL),\n                                                 remote_ptr<void>((uintptr_t)0x640000002000LL));\n// See https://github.com/llvm/llvm-project/commit/fb77ca05ffb4f8e666878f2f6718a9fb4d686839\n// and https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/asan/asan_allocator.h\nstatic const MemoryRange asan_allocator_reserved2(remote_ptr<void>((uintptr_t)0x500000000000LL),\n                                                  remote_ptr<void>((uintptr_t)0x540000000000LL));\n\n// See https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/tsan/rtl/tsan_platform_posix.cpp\nstatic const MemoryRange tsan_shadow(remote_ptr<void>((uintptr_t)0x008000000000LL),\n                                     remote_ptr<void>((uintptr_t)0x550000000000LL));\n// The memory area 0x7b0000000000-0x7c0000002000 is reserved for TSAN's\n// custom heap allocator --- applications end up using it, but *we* can't use\n// it.\nstatic const MemoryRange tsan_exclude(remote_ptr<void>((uintptr_t)0x568000000000LL),\n                                      remote_ptr<void>((uintptr_t)0x7e8000000000LL));\n// It's only 1TB because tsan can't fit more\nstatic const MemoryRange tsan_fixed_global_exclusion_range(remote_ptr<void>((uintptr_t)0x7e8000000000LL),\n                                                           remote_ptr<void>((uintptr_t)0x7f8000000000LL));\n\nstruct ExeInfo {\n  ExeInfo() : arch(NativeArch::arch()) {}\n  SupportedArch arch;\n  // Empty if anything fails\n  string sanitizer_path;\n  vector<MemoryRange> sanitizer_exclude_memory_ranges;\n  // If non-empty, use this as the global exclusion range.\n  MemoryRange fixed_global_exclusion_range;\n\n  void setup_asan_memory_ranges() {\n    if (!check_sanitizer_arch()) {\n      return;\n    }\n    sanitizer_exclude_memory_ranges.push_back(asan_shadow);\n    sanitizer_exclude_memory_ranges.push_back(asan_allocator_reserved);\n    sanitizer_exclude_memory_ranges.push_back(asan_allocator_reserved2);\n  }\n  void setup_tsan_memory_ranges() {\n    if (!check_sanitizer_arch()) {\n      return;\n    }\n    sanitizer_exclude_memory_ranges.push_back(tsan_shadow);\n    sanitizer_exclude_memory_ranges.push_back(tsan_exclude);\n    fixed_global_exclusion_range = tsan_fixed_global_exclusion_range;\n  }\nprivate:\n  bool check_sanitizer_arch() {\n    switch (arch) {\n      case x86_64:\n        return true;\n      default:\n        // We have no idea what's going on. Disable mmap randomization if\n        // chaos mode is active.\n        sanitizer_exclude_memory_ranges.push_back(MemoryRange::all());\n        return false;\n    }\n  }\n};\n\nstatic ExeInfo read_exe_info(const string& exe_file) {\n  ExeInfo ret;\n  ScopedFd fd(exe_file.c_str(), O_RDONLY);\n  if (!fd.is_open()) {\n    return ret;\n  }\n  ElfFileReader reader(fd);\n  ret.arch = reader.arch();\n\n  DynamicSection dynamic = reader.read_dynamic();\n  for (auto& entry : dynamic.entries) {\n    if (entry.tag == DT_NEEDED && entry.val < dynamic.strtab.size()) {\n      const char* name = &dynamic.strtab[entry.val];\n      if (!strncmp(name, \"libasan\", 7)) {\n        ret.sanitizer_path = string(name);\n        ret.setup_asan_memory_ranges();\n      } else if (!strncmp(name, \"libtsan\", 7)) {\n        ret.sanitizer_path = string(name);\n        ret.setup_tsan_memory_ranges();\n      }\n    }\n  }\n\n  auto syms = reader.read_symbols(\".dynsym\", \".dynstr\");\n  for (size_t i = 0; i < syms.size(); ++i) {\n    if (syms.is_name(i, \"__asan_init\")) {\n      ret.setup_asan_memory_ranges();\n    } else if (syms.is_name(i, \"__tsan_init\")) {\n      ret.setup_tsan_memory_ranges();\n    }\n  }\n\n  return ret;\n}\n\nstatic string lookup_by_path(const string& name) {\n  if (name.find('/') != string::npos) {\n    return name;\n  }\n  const char* env = getenv(\"PATH\");\n  if (!env) {\n    return name;\n  }\n  char* p = strdup(env);\n  char* s = p;\n  while (*s) {\n    char* next = strchr(s, ':');\n    if (next) {\n      *next = 0;\n    }\n    string file = string(s) + \"/\" + name;\n    struct stat st;\n    if (!stat(file.c_str(), &st) && S_ISREG(st.st_mode) &&\n        !access(file.c_str(), X_OK)) {\n      free(p);\n      return file;\n    }\n    if (!next) {\n      break;\n    }\n    s = next + 1;\n  }\n  free(p);\n  return name;\n}\n\n/*static*/ RecordSession::shr_ptr RecordSession::create(\n    const vector<string>& argv, const vector<string>& extra_env,\n    const DisableCPUIDFeatures& disable_cpuid_features,\n    SyscallBuffering syscallbuf,\n    unsigned char syscallbuf_desched_sig,\n    BindCPU bind_cpu,\n    const string& output_trace_dir,\n    const TraceUuid* trace_id,\n    bool use_audit,\n    bool unmap_vdso,\n    bool force_asan_active,\n    bool force_tsan_active,\n    bool intel_pt,\n    bool check_outside_mmaps,\n    bool no_preload) {\n  TraceeAttentionSet::initialize();\n\n  // The syscallbuf library interposes some critical\n  // external symbols like XShmQueryExtension(), so we\n  // preload it whether or not syscallbuf is enabled. Indicate here whether\n  // syscallbuf is enabled.\n  if (syscallbuf == DISABLE_SYSCALL_BUF) {\n    unsetenv(SYSCALLBUF_ENABLED_ENV_VAR);\n  } else {\n    setenv(SYSCALLBUF_ENABLED_ENV_VAR, \"1\", 1);\n  }\n\n  vector<string> env = current_env();\n\n  // Have extra_env override anything already in the environment\n  for (string extra : extra_env) {\n    string extra_var = extra.substr(0, extra.find('='));\n    auto it = env.begin();\n    for (; it != env.end(); ++it) {\n      if (it->find(extra_var) != 0) {\n        continue;\n      }\n      it = env.erase(it);\n      break;\n    }\n  }\n  env.insert(env.end(), extra_env.begin(), extra_env.end());\n\n  string full_path = lookup_by_path(argv[0]);\n  struct stat st;\n  if (stat(full_path.c_str(), &st) == 0 && S_ISDIR(st.st_mode)) {\n    CLEAN_FATAL() << \"Provided tracee '\" << argv[0] << \"' is a directory, not an executable\";\n  }\n  ExeInfo exe_info = read_exe_info(full_path);\n  if (exe_info.sanitizer_exclude_memory_ranges.empty()) {\n    if (force_asan_active) {\n      exe_info.setup_asan_memory_ranges();\n    } else if (force_tsan_active) {\n      exe_info.setup_tsan_memory_ranges();\n    }\n  }\n\n  // Strip any LD_PRELOAD that an outer rr may have inserted\n  strip_outer_ld_preload(env);\n\n  // LD_PRELOAD the syscall interception lib\n  string syscall_buffer_lib_path = find_helper_library(SYSCALLBUF_LIB_FILENAME);\n  if (!no_preload && !syscall_buffer_lib_path.empty()) {\n    string ld_preload = \"\";\n    if (!exe_info.sanitizer_path.empty()) {\n      LOG(debug) << \"Prepending \" << exe_info.sanitizer_path << \" to LD_PRELOAD\";\n      // Put an LD_PRELOAD entry for it before our preload library, because\n      // it checks that it's loaded first\n      ld_preload += exe_info.sanitizer_path + \":\";\n    }\n    ld_preload += syscall_buffer_lib_path + SYSCALLBUF_LIB_FILENAME_PADDED;\n#ifndef __BIONIC__\n    // When librrpreload is built against glibc 2.34 but runs in a process linking pre-2.34 glibc,\n    // its call to dlsym needs to search libdl before libc. When librrpreload found dlsym\n    // in libc at link time, pre-2.34 ld.so throws a fatal error if it searches for dlsym in libc and\n    // can't find it.\n    ld_preload += \":libdl.so.2\";\n#endif\n    inject_ld_helper_library(env, \"LD_PRELOAD\", ld_preload);\n  }\n\n  if (use_audit) {\n    string rtld_audit_lib_path = find_helper_library(RTLDAUDIT_LIB_FILENAME);\n    if (!rtld_audit_lib_path.empty()) {\n      string ld_audit = rtld_audit_lib_path + RTLDAUDIT_LIB_FILENAME_PADDED;\n      inject_ld_helper_library(env, \"LD_AUDIT\", ld_audit);\n    }\n  }\n\n  env.push_back(\"RUNNING_UNDER_RR=1\");\n  // Stop Mesa using the GPU\n  env.push_back(\"LIBGL_ALWAYS_SOFTWARE=1\");\n  env.push_back(\"GBM_ALWAYS_SOFTWARE=1\");\n  env.push_back(\"SDL_RENDER_DRIVER=software\");\n  // Stop sssd from using shared-memory with its daemon\n  env.push_back(\"SSS_NSS_USE_MEMCACHE=NO\");\n\n  // Disable Gecko's \"wait for gdb to attach on process crash\" behavior, since\n  // it is useless when running under rr.\n  env.push_back(\"MOZ_GDB_SLEEP=0\");\n\n  // Avoid GVFS using separate processes that might run\n  // outside the recording but share memory mapped files.\n  env.push_back(\"GIO_USE_VFS=local\");\n\n  // If we have CPUID faulting, don't use these environment hacks. We don't\n  // need them and the user might want to use them themselves for other reasons.\n  if (!Session::has_cpuid_faulting()) {\n    // OpenSSL uses RDRAND, but we can disable it. These bitmasks are inverted\n    // and ANDed with the results of CPUID. The number below is 2^62, which is the\n    // bit for RDRAND support.\n    env.push_back(\"OPENSSL_ia32cap=~4611686018427387904:0\");\n    // Disable Qt's use of RDRAND/RDSEED/RTM\n    env.push_back(\"QT_NO_CPU_FEATURE=rdrnd rdseed rtm\");\n    // Disable systemd's use of RDRAND\n    env.push_back(\"SYSTEMD_RDRAND=0\");\n  }\n\n  shr_ptr session(\n      new RecordSession(full_path, argv, env, disable_cpuid_features,\n                        syscallbuf, syscallbuf_desched_sig, bind_cpu,\n                        output_trace_dir, trace_id, use_audit, unmap_vdso,\n                        intel_pt, check_outside_mmaps));\n  session->excluded_ranges_ = std::move(exe_info.sanitizer_exclude_memory_ranges);\n  session->fixed_global_exclusion_range_ = std::move(exe_info.fixed_global_exclusion_range);\n  return session;\n}\n\nRecordSession::RecordSession(const std::string& exe_path,\n                             const std::vector<std::string>& argv,\n                             const std::vector<std::string>& envp,\n                             const DisableCPUIDFeatures& disable_cpuid_features,\n                             SyscallBuffering syscallbuf,\n                             int syscallbuf_desched_sig,\n                             BindCPU bind_cpu,\n                             const string& output_trace_dir,\n                             const TraceUuid* trace_id,\n                             bool use_audit,\n                             bool unmap_vdso,\n                             bool intel_pt_enabled,\n                             bool check_outside_mmaps)\n    : trace_out(argv[0], output_trace_dir, ticks_semantics_),\n      scheduler_(*this),\n      trace_id(trace_id),\n      disable_cpuid_features_(disable_cpuid_features),\n      ignore_sig(0),\n      continue_through_sig(0),\n      last_task_switchable(PREVENT_SWITCH),\n      syscall_buffer_size_(1024 * 1024),\n      syscallbuf_desched_sig_(syscallbuf_desched_sig),\n      use_syscall_buffer_(syscallbuf == ENABLE_SYSCALL_BUF),\n      use_file_cloning_(true),\n      use_read_cloning_(true),\n      enable_chaos_(false),\n      wait_for_all_(false),\n      use_audit_(use_audit),\n      unmap_vdso_(unmap_vdso),\n      check_outside_mmaps_(check_outside_mmaps) {\n  set_intel_pt_enabled(intel_pt_enabled);\n  if (intel_pt_enabled) {\n    PerfCounters::start_pt_copy_thread();\n  }\n\n  if (!has_cpuid_faulting() &&\n      disable_cpuid_features.any_features_disabled()) {\n    FATAL() << \"CPUID faulting required to disable CPUID features\";\n  }\n\n  if (rr::syscall_number_for_rrcall_init_preload(x86_64) != RR_CALL_BASE) {\n    FATAL() << \"RR_CALL_BASE is incorrect\";\n  }\n\n  trace_out.set_bound_cpu(choose_cpu(bind_cpu, cpu_lock));\n  do_bind_cpu();\n  ScopedFd error_fd = create_spawn_task_error_pipe();\n  RecordTask* t = static_cast<RecordTask*>(\n      Task::spawn(*this, error_fd, &tracee_socket_fd(),\n                  &tracee_socket_receiver_fd(),\n                  &tracee_socket_fd_number,\n                  exe_path, argv, envp));\n\n  if (NativeArch::is_x86ish()) {\n    // CPU affinity has been set.\n    trace_out.setup_cpuid_records(has_cpuid_faulting(), disable_cpuid_features_);\n    if (cpu_has_xsave_fip_fdp_quirk()) {\n      trace_out.set_xsave_fip_fdp_quirk(true);\n      // Clear FIP/FDP on every event to reduce the probability of this quirk\n      // causing divergence, especially when porting traces to Intel machines\n      trace_out.set_clear_fip_fdp(true);\n    }\n    if (cpu_has_fdp_exception_only_quirk()) {\n      trace_out.set_fdp_exception_only_quirk(true);\n    }\n  }\n\n  initial_thread_group = t->thread_group();\n  on_create(t);\n}\n\nRecordSession::~RecordSession() {\n  // Do this now while we're still a RecordSession. When Session's\n  // destructor calls kill_all_tasks(), things turn bad.\n  kill_all_tasks();\n}\n\nRecordSession::RecordResult RecordSession::record_step() {\n  RecordResult result;\n\n  if (task_map.empty()) {\n    result.status = STEP_EXITED;\n    result.exit_status = initial_thread_group->exit_status;\n    return result;\n  }\n\n  if (!wait_for_all_ && initial_thread_group->task_set().empty()) {\n    // SIGKILL any tasks we haven't already killed.\n    terminate_tracees();\n  }\n\n  result.status = STEP_CONTINUE;\n\n  TaskUid prev_task_tuid;\n  if (scheduler().current()) {\n    prev_task_tuid = scheduler().current()->tuid();\n  }\n  auto rescheduled = scheduler().reschedule(last_task_switchable);\n  if (rescheduled.interrupted_by_signal) {\n    // The scheduler was waiting for some task to become active, but was\n    // interrupted by a signal. Yield to our caller now to give the caller\n    // a chance to do something triggered by the signal\n    // (e.g. terminate the recording).\n    return result;\n  }\n  RecordTask* t = scheduler().current();\n  if (!t) {\n    // No child to schedule. Yield to our caller to give it a chance\n    // to do something (e.g. terminate the recording).\n    return result;\n  }\n  // If the task has been reaped prematurely then it's not running\n  // and we can't get registers etc, so minimize what we do between here\n  // to handle_ptrace_exit_event().\n  if (t->waiting_for_reap) {\n    // Give it another chance to be reaped\n    t->did_reach_zombie();\n    return result;\n  }\n  RecordTask* prev_task = find_task(prev_task_tuid);\n  if (prev_task && prev_task->ev().type() == EV_SCHED) {\n    if (prev_task != t) {\n      // We did do a context switch, so record the SCHED event. Otherwise\n      // we'll just discard it.\n      prev_task->record_current_event();\n    }\n    prev_task->pop_event(EV_SCHED);\n  }\n  if (t->tuid() != prev_task_tuid) {\n    t->will_schedule();\n  }\n\n  // Have to disable context-switching until we know it's safe\n  // to allow switching the context.\n  last_task_switchable = PREVENT_SWITCH;\n\n  LOG(debug) << \"trace time \" << t->trace_time() << \": Active task is \"\n             << t->tid << \". Events:\";\n  if (IS_LOGGING(debug)) {\n    t->log_pending_events();\n  }\n\n  if (handle_ptrace_exit_event(t)) {\n    // t may have been deleted.\n    last_task_switchable = ALLOW_SWITCH;\n    return result;\n  }\n\n  if (rescheduled.started_new_timeslice) {\n    t->registers_at_start_of_last_timeslice = t->regs();\n    t->time_at_start_of_last_timeslice = trace_writer().time();\n  }\n\n  StepState step_state(CONTINUE);\n\n  ASSERT(t, t->is_stopped()) << \"Somehow we're not stopped here; status=\"\n    << t->status();\n  bool did_enter_syscall;\n  if (rescheduled.by_waitpid &&\n      handle_ptrace_event(&t, &step_state, &result, &did_enter_syscall)) {\n    if (step_state.continue_type == DONT_CONTINUE) {\n      return result;\n    }\n    if (result.status != STEP_CONTINUE) {\n      last_task_switchable = ALLOW_SWITCH;\n      return result;\n    }\n\n    if (did_enter_syscall && t->ev().type() == EV_SYSCALL) {\n      syscall_state_changed(t, &step_state);\n    }\n  } else {\n    ASSERT(t, t->is_stopped()) << \"handle_ptrace_event left us in a not-stopped state\";\n    if (rescheduled.by_waitpid && handle_signal_event(t, &step_state)) {\n      // Tracee may have exited while processing descheds; handle that.\n      if (handle_ptrace_exit_event(t)) {\n        // t may have been deleted.\n        last_task_switchable = ALLOW_SWITCH;\n        return result;\n      }\n    } else {\n      ASSERT(t, t->is_stopped()) << \"handle_signal_event left us in a not-stopped state\";\n      runnable_state_changed(t, &step_state, &result, rescheduled.by_waitpid);\n\n      if (result.status != STEP_CONTINUE ||\n          step_state.continue_type == DONT_CONTINUE) {\n        return result;\n      }\n\n      switch (t->ev().type()) {\n        case EV_DESCHED:\n          desched_state_changed(t);\n          break;\n        case EV_SYSCALL:\n          syscall_state_changed(t, &step_state);\n          break;\n        case EV_SIGNAL:\n        case EV_SIGNAL_DELIVERY:\n          if (signal_state_changed(t, &step_state)) {\n            // t may have been deleted\n            return result;\n          }\n          break;\n        default:\n          break;\n      }\n    }\n  }\n\n  t->verify_signal_states();\n  t->unmap_dead_syscallbufs_if_required();\n\n  // We try to inject a signal if there's one pending; otherwise we continue\n  // task execution.\n  if (!prepare_to_inject_signal(t, &step_state) &&\n      step_state.continue_type != DONT_CONTINUE) {\n    // Ensure that we aren't allowing switches away from a running task.\n    // Only tasks blocked in a syscall can be switched away from, otherwise\n    // we have races.\n    ASSERT(t,\n           last_task_switchable == PREVENT_SWITCH ||\n               t->may_be_blocked());\n\n    debug_exec_state(\"EXEC_START\", t);\n\n    task_continue(step_state);\n  }\n\n  return result;\n}\n\nvoid RecordSession::terminate_tracees() {\n  for (auto& v : task_map) {\n    RecordTask* t = static_cast<RecordTask*>(v.second);\n    if (!t->detached_proxy && !t->sent_shutdown_kill) {\n      LOG(debug) << \"Terminating tracee \" << t->tid;\n      ::kill(t->rec_tid, SIGKILL);\n      t->sent_shutdown_kill = true;\n      t->emulate_SIGCONT();\n    }\n  }\n}\n\nvoid RecordSession::forward_SIGTERM() {\n  if (!initial_thread_group->task_set().empty()) {\n    kill(initial_thread_group->tgid, SIGTERM);\n  }\n}\n\nvoid RecordSession::term_detached_tasks() {\n  // Send SIGTERM to all detached child tasks first, so they may clean up\n  // in parallel.\n  for (auto& v : task_map) {\n    RecordTask* t = static_cast<RecordTask*>(v.second);\n    if (!t->detached_proxy) {\n      continue;\n    }\n    ::kill(t->rec_tid, SIGTERM);\n  }\n  for (auto it = task_map.begin(); it != task_map.end(); ) {\n    RecordTask* t = static_cast<RecordTask*>(it->second);\n    if (!t->detached_proxy) {\n      ++it;\n      continue;\n    }\n    WaitResult result = WaitManager::wait_exit(WaitOptions(t->rec_tid));\n    if (result.code != WAIT_OK) {\n      LOG(warn) << \"Wait failed\";\n    } else if (result.status.type() != WaitStatus::EXIT) {\n      LOG(warn) << \"Unexpected wait status \" << result.status <<\n        \" while waiting for detached child \" << t->rec_tid;\n    }\n    ++it;\n    delete t;\n  }\n}\n\nvoid RecordSession::close_trace_writer(TraceWriter::CloseStatus status) {\n  trace_out.close(status, trace_id.get());\n}\n\nTask* RecordSession::new_task(pid_t tid, pid_t, uint32_t serial,\n                              SupportedArch a, const std::string&) {\n  return new RecordTask(*this, tid, serial, a);\n}\n\nvoid RecordSession::on_create(Task* t) {\n  Session::on_create(t);\n  scheduler().on_create(static_cast<RecordTask*>(t));\n}\n\nRecordTask* RecordSession::find_task(pid_t rec_tid) const {\n  return static_cast<RecordTask*>(Session::find_task(rec_tid));\n}\n\nRecordTask* RecordSession::find_task(const TaskUid& tuid) const {\n  return static_cast<RecordTask*>(Session::find_task(tuid));\n}\n\nRecordTask* RecordSession::find_detached_proxy_task(pid_t proxy_tid) const {\n  auto it = detached_task_map.find(proxy_tid);\n  return detached_task_map.end() != it ? it->second : nullptr;\n}\n\nvoid RecordSession::on_proxy_detach(RecordTask *t, pid_t new_tid) {\n  Session::on_destroy(t);\n  task_map[new_tid] = t;\n  detached_task_map[t->tid] = t;\n}\n\nvoid RecordSession::on_destroy_record_task(RecordTask* t) {\n  if (t->detached_proxy) {\n    detached_task_map.erase(t->tid);\n  }\n  scheduler().on_destroy(t);\n}\n\nuint64_t RecordSession::rr_signal_mask() const {\n  return signal_bit(PerfCounters::TIME_SLICE_SIGNAL) |\n         signal_bit(syscallbuf_desched_sig_);\n}\n\nstatic const uint32_t CPUID_RDRAND_FLAG = 1 << 30;\nstatic const uint32_t CPUID_RTM_FLAG = 1 << 11;\nstatic const uint32_t CPUID_RDSEED_FLAG = 1 << 18;\nstatic const uint32_t CPUID_XSAVEOPT_FLAG = 1 << 0;\n\nvoid DisableCPUIDFeatures::amend_cpuid_data(uint32_t eax_in, uint32_t ecx_in,\n                                            CPUIDData* cpuid_data) const {\n  switch (eax_in) {\n    case CPUID_GETFEATURES:\n      cpuid_data->ecx &= ~(CPUID_RDRAND_FLAG | features_ecx);\n      cpuid_data->edx &= ~features_edx;\n      break;\n    case CPUID_GETEXTENDEDFEATURES:\n      if (ecx_in == 0) {\n        cpuid_data->ebx &= ~(CPUID_RDSEED_FLAG | CPUID_RTM_FLAG\n            | extended_features_ebx);\n        cpuid_data->ecx &= ~extended_features_ecx;\n        cpuid_data->edx &= ~extended_features_edx;\n      }\n      break;\n    case CPUID_GETXSAVE:\n      if (ecx_in == 1) {\n        // Always disable XSAVEOPT because it's nondeterministic,\n        // possibly depending on context switching behavior. Intel\n        // recommends not using it from user space.\n        cpuid_data->eax &= ~(CPUID_XSAVEOPT_FLAG | xsave_features_eax);\n      }\n      break;\n    default:\n      break;\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/RecordSession.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_RECORD_SESSION_H_\n#define RR_RECORD_SESSION_H_\n\n#include <string>\n#include <vector>\n\n#include \"Scheduler.h\"\n#include \"SeccompFilterRewriter.h\"\n#include \"Session.h\"\n#include \"ThreadGroup.h\"\n#include \"TraceFrame.h\"\n#include \"WaitStatus.h\"\n\nnamespace rr {\n\nclass RecordTask;\n\nstruct DisableCPUIDFeatures {\n  DisableCPUIDFeatures()\n    : features_ecx(0)\n    , features_edx(0)\n    , extended_features_ebx(0)\n    , extended_features_ecx(0)\n    , extended_features_edx(0)\n    , xsave_features_eax(0)\n  {}\n  bool any_features_disabled() const {\n    return features_ecx || features_edx || extended_features_ebx\n      || extended_features_ecx || extended_features_edx || xsave_features_eax;\n  }\n  /**\n   * Includes disabling TSX and other rr-incompatible features */\n  void amend_cpuid_data(uint32_t eax_in, uint32_t ecx_in,\n                        CPUIDData* cpuid_data) const;\n\n  /* in: EAX=0x01 */\n  uint32_t features_ecx;\n  uint32_t features_edx;\n  /* in: EAX=0x07 ECX=0 */\n  uint32_t extended_features_ebx;\n  uint32_t extended_features_ecx;\n  uint32_t extended_features_edx;\n  /* in: EAX=0x0D ECX=1 */\n  uint32_t xsave_features_eax;\n};\n\nstruct TraceUuid {\n  uint8_t bytes[16];\n};\n\n/** Encapsulates additional session state related to recording. */\nclass RecordSession final : public Session {\npublic:\n  typedef std::shared_ptr<RecordSession> shr_ptr;\n\n  /**\n   * Create a recording session for the initial command line |argv|.\n   */\n  enum SyscallBuffering { ENABLE_SYSCALL_BUF, DISABLE_SYSCALL_BUF };\n  static shr_ptr create(\n      const std::vector<std::string>& argv,\n      const std::vector<std::string>& extra_env,\n      const DisableCPUIDFeatures& features,\n      SyscallBuffering syscallbuf = ENABLE_SYSCALL_BUF,\n      unsigned char syscallbuf_desched_sig = SIGPWR,\n      BindCPU bind_cpu = BindCPU(BindCPU::ANY),\n      const std::string& output_trace_dir = \"\",\n      const TraceUuid* trace_id = nullptr,\n      bool use_audit = false,\n      bool unmap_vdso = false,\n      bool force_asan_active = false,\n      bool force_tsan_active = false,\n      bool intel_pt = false,\n      bool check_outside_mmaps = false,\n      bool no_preload = false);\n\n  ~RecordSession() override;\n\n  const DisableCPUIDFeatures& disable_cpuid_features() const {\n    return disable_cpuid_features_;\n  }\n  bool use_syscall_buffer() const { return use_syscall_buffer_; }\n  size_t syscall_buffer_size() const { return syscall_buffer_size_; }\n  unsigned char syscallbuf_desched_sig() const { return syscallbuf_desched_sig_; }\n  bool use_read_cloning() const { return use_read_cloning_; }\n  bool use_file_cloning() const { return use_file_cloning_; }\n  void set_ignore_sig(int sig) { ignore_sig = sig; }\n  int get_ignore_sig() const { return ignore_sig; }\n  void set_continue_through_sig(int sig) { continue_through_sig = sig; }\n  int get_continue_through_sig() const { return continue_through_sig; }\n  // Returns ranges to exclude from chaos mode memory allocation.\n  // Used to exclude ranges used by sanitizers.\n  const std::vector<MemoryRange> excluded_ranges() const {\n    return excluded_ranges_;\n  }\n  MemoryRange fixed_global_exclusion_range() const {\n    return fixed_global_exclusion_range_;\n  }\n  bool use_audit() const { return use_audit_; }\n  bool unmap_vdso() { return unmap_vdso_; }\n  bool check_outside_mmaps() { return check_outside_mmaps_; }\n  uint64_t rr_signal_mask() const;\n\n  enum RecordStatus {\n    // Some execution was recorded. record_step() can be called again.\n    STEP_CONTINUE,\n    // All tracees are dead. record_step() should not be called again.\n    STEP_EXITED,\n    // Spawning the initial tracee failed. An error message will be in\n    // failure_message.\n    STEP_SPAWN_FAILED\n  };\n  struct RecordResult {\n    RecordStatus status;\n    // When status == STEP_EXITED\n    WaitStatus exit_status;\n    // When status == STEP_SPAWN_FAILED\n    std::string failure_message;\n  };\n  /**\n   * Record some tracee execution.\n   * This may block. If blocking is interrupted by a signal, will return\n   * STEP_CONTINUE.\n   * Typically you'd call this in a loop until it returns something other than\n   * STEP_CONTINUE.\n   * Note that when this returns, some tasks may be running (not in a ptrace-\n   * stop). In particular, up to one task may be executing user code and any\n   * number of tasks may be blocked in syscalls.\n   */\n  RecordResult record_step();\n\n  /**\n   * SIGKILL all tracees.\n   */\n  void terminate_tracees();\n\n  /**\n   * Close trace output without flushing syscall buffers or writing\n   * task exit/termination records to the trace.\n   */\n  void close_trace_writer(TraceWriter::CloseStatus status);\n\n  virtual RecordSession* as_record() override { return this; }\n\n  TraceWriter& trace_writer() { return trace_out; }\n\n  Scheduler& scheduler() { return scheduler_; }\n\n  SeccompFilterRewriter& seccomp_filter_rewriter() {\n    return seccomp_filter_rewriter_;\n  }\n\n  enum ContinueType { DONT_CONTINUE = 0, CONTINUE, CONTINUE_SYSCALL };\n\n  struct StepState {\n    // Continue with this continuation type.\n    ContinueType continue_type;\n    StepState(ContinueType continue_type) : continue_type(continue_type) {}\n  };\n\n  void set_enable_chaos(bool enable_chaos) {\n    scheduler().set_enable_chaos(enable_chaos);\n    enable_chaos_ = enable_chaos;\n    trace_out.set_chaos_mode(enable_chaos);\n  }\n  bool enable_chaos() const { return enable_chaos_; }\n\n  void set_num_cores(int num_cores) {\n    scheduler().set_num_cores(num_cores);\n  }\n  void set_use_read_cloning(bool enable) { use_read_cloning_ = enable; }\n  void set_use_file_cloning(bool enable) { use_file_cloning_ = enable; }\n  void set_syscall_buffer_size(size_t size) { syscall_buffer_size_ = size; }\n\n  void set_wait_for_all(bool wait_for_all) {\n    this->wait_for_all_ = wait_for_all;\n  }\n\n  virtual Task* new_task(pid_t tid, pid_t rec_tid, uint32_t serial,\n                         SupportedArch a, const std::string& name) override;\n\n  RecordTask* find_task(pid_t rec_tid) const;\n  RecordTask* find_task(const TaskUid& tuid) const;\n  RecordTask* find_detached_proxy_task(pid_t proxy_tid) const;\n\n  void on_proxy_detach(RecordTask *t, pid_t new_tid);\n\n  /**\n   * This gets called when we detect that a task has been revived from the\n   * dead with a PTRACE_EVENT_EXEC. See ptrace man page under \"execve(2) under\n   * ptrace\" for the horrid details.\n   *\n   * The task in the thread-group that triggered the successful execve has changed\n   * its tid to |rec_tid|. We mirror that, and emit TraceTaskEvents to make it\n   * look like a new task was spawned and the old task exited.\n   */\n  RecordTask* revive_task_for_exec(pid_t rec_tid);\n\n  virtual TraceStream* trace_stream() override { return &trace_out; }\n\n  /**\n   * Send SIGTERM to all detached tasks and wait for them to finish.\n   */\n  void term_detached_tasks();\n\n  /**\n   * Forward SIGTERM to initial task\n   */\n  void forward_SIGTERM();\n\n  void on_destroy_record_task(RecordTask* t);\n\nprivate:\n  RecordSession(const std::string& exe_path,\n                const std::vector<std::string>& argv,\n                const std::vector<std::string>& envp,\n                const DisableCPUIDFeatures& features,\n                SyscallBuffering syscallbuf,\n                int syscallbuf_desched_sig,\n                BindCPU bind_cpu,\n                const std::string& output_trace_dir,\n                const TraceUuid* trace_id,\n                bool use_audit,\n                bool unmap_vdso,\n                bool intel_pt,\n                bool check_outside_mmaps);\n\n  virtual void on_create(Task* t) override;\n\n  void handle_seccomp_traced_syscall(RecordTask* t,\n                                     RecordSession::StepState* step_state,\n                                     RecordResult* result,\n                                     bool* did_enter_syscall);\n  // Returns false if the task exits during processing\n  bool process_syscall_entry(RecordTask* t, StepState* step_state,\n                             RecordResult* step_result,\n                             SupportedArch syscall_arch);\n  void check_initial_task_syscalls(RecordTask* t, RecordResult* step_result);\n  void handle_seccomp_trap(RecordTask* t, StepState* step_state,\n                           uint16_t seccomp_data);\n  void handle_seccomp_errno(RecordTask* t, StepState* step_state,\n                            uint16_t seccomp_data);\n  bool handle_ptrace_event(RecordTask** t_ptr, StepState* step_state,\n                           RecordResult* result, bool* did_enter_syscall);\n  bool handle_signal_event(RecordTask* t, StepState* step_state);\n  void runnable_state_changed(RecordTask* t, StepState* step_state,\n                              RecordResult* step_result,\n                              bool can_consume_wait_status);\n  bool signal_state_changed(RecordTask* t, StepState* step_state);\n  void syscall_state_changed(RecordTask* t, StepState* step_state);\n  void desched_state_changed(RecordTask* t);\n  bool prepare_to_inject_signal(RecordTask* t, StepState* step_state);\n  void task_continue(const StepState& step_state);\n\n  TraceWriter trace_out;\n  Scheduler scheduler_;\n  ThreadGroup::shr_ptr initial_thread_group;\n  SeccompFilterRewriter seccomp_filter_rewriter_;\n  std::unique_ptr<const TraceUuid> trace_id;\n\n  DisableCPUIDFeatures disable_cpuid_features_;\n  int ignore_sig;\n  int continue_through_sig;\n  Switchable last_task_switchable;\n  size_t syscall_buffer_size_;\n  unsigned char syscallbuf_desched_sig_;\n  bool use_syscall_buffer_;\n\n  bool use_file_cloning_;\n  bool use_read_cloning_;\n  /**\n   * When true, try to increase the probability of finding bugs.\n   */\n  bool enable_chaos_;\n  /**\n   * When true, wait for all tracees to exit before finishing recording.\n   */\n  bool wait_for_all_;\n\n  std::vector<MemoryRange> excluded_ranges_;\n  MemoryRange fixed_global_exclusion_range_;\n  /**\n   * Keeps track of detached tasks.\n   */\n  std::map<pid_t, RecordTask*> detached_task_map;\n\n  std::string output_trace_dir;\n\n  bool use_audit_;\n  bool unmap_vdso_;\n  bool check_outside_mmaps_;\n};\n\n} // namespace rr\n\n#endif // RR_RECORD_SESSION_H_\n"
  },
  {
    "path": "src/RecordTask.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"RecordTask.h\"\n\n#include <dirent.h>\n#include <elf.h>\n#include <limits.h>\n#include <linux/perf_event.h>\n#include <sys/prctl.h>\n#include <sys/resource.h>\n#include <sys/syscall.h>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"ContextSwitchEvent.h\"\n#include \"PreserveFileMonitor.h\"\n#include \"RecordSession.h\"\n#include \"WaitManager.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"record_signal.h\"\n#include \"rr/rr.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n/**\n * Stores the table of signal dispositions and metadata for an\n * arbitrary set of tasks.  Each of those tasks must own one of\n * the |refcount|s while they still refer to this.\n */\nstruct Sighandler {\n  Sighandler() : resethand(false), takes_siginfo(false) {}\n\n  template <typename Arch>\n  void init_arch(const typename Arch::kernel_sigaction& ksa) {\n    k_sa_handler = ksa.k_sa_handler;\n    sa.resize(sizeof(ksa));\n    memcpy(sa.data(), &ksa, sizeof(ksa));\n    resethand = (ksa.sa_flags & SA_RESETHAND) != 0;\n    takes_siginfo = (ksa.sa_flags & SA_SIGINFO) != 0;\n  }\n\n  template <typename Arch> void reset_arch() {\n    typename Arch::kernel_sigaction ksa;\n    memset(&ksa, 0, sizeof(ksa));\n    DEBUG_ASSERT(uintptr_t(SIG_DFL) == 0);\n    init_arch<Arch>(ksa);\n  }\n\n  SignalDisposition disposition() const {\n    DEBUG_ASSERT(uintptr_t(SIG_DFL) == 0);\n    DEBUG_ASSERT(uintptr_t(SIG_IGN) == 1);\n    switch (k_sa_handler.as_int()) {\n      case 0:\n        return SIGNAL_DEFAULT;\n      case 1:\n        return SIGNAL_IGNORE;\n      default:\n        return SIGNAL_HANDLER;\n    }\n  }\n\n  remote_code_ptr get_user_handler() const {\n    return disposition() == SIGNAL_HANDLER\n               ? remote_code_ptr(k_sa_handler.as_int())\n               : remote_code_ptr();\n  }\n\n  remote_ptr<void> k_sa_handler;\n  // Saved kernel_sigaction; used to restore handler\n  vector<uint8_t> sa;\n  bool resethand;\n  bool takes_siginfo;\n};\n\nstatic void reset_handler(Sighandler* handler, SupportedArch arch) {\n  RR_ARCH_FUNCTION(handler->reset_arch, arch);\n}\n\nstruct Sighandlers {\n  typedef shared_ptr<Sighandlers> shr_ptr;\n\n  shr_ptr clone() const {\n    shr_ptr s(new Sighandlers());\n    // NB: depends on the fact that Sighandler is for all\n    // intents and purposes a POD type, though not\n    // technically.\n    for (size_t i = 0; i < array_length(handlers); ++i) {\n      s->handlers[i] = handlers[i];\n    }\n    return s;\n  }\n\n  Sighandler& get(int sig) {\n    assert_valid(sig);\n    return handlers[sig];\n  }\n  const Sighandler& get(int sig) const {\n    assert_valid(sig);\n    return handlers[sig];\n  }\n\n  void init_from_current_process() {\n    for (size_t i = 1; i < array_length(handlers); ++i) {\n      Sighandler& h = handlers[i];\n\n      NativeArch::kernel_sigaction sa;\n      if (::syscall(SYS_rt_sigaction, i, nullptr, &sa, sizeof(uint64_t))) {\n        /* EINVAL means we're querying an\n         * unused signal number. */\n        DEBUG_ASSERT(EINVAL == errno);\n        continue;\n      }\n      msan_unpoison(&sa, sizeof(NativeArch::kernel_sigaction));\n\n      h.init_arch<NativeArch>(sa);\n    }\n  }\n\n  /**\n   * For each signal in |table| such that is_user_handler() is\n   * true, reset the disposition of that signal to SIG_DFL, and\n   * clear the resethand flag if it's set.  SIG_IGN signals are\n   * not modified.\n   *\n   * (After an exec() call copies the original sighandler table,\n   * this is the operation required by POSIX to initialize that\n   * table copy.)\n   */\n  void reset_user_handlers(SupportedArch arch) {\n    for (int i = 0; i < ssize_t(array_length(handlers)); ++i) {\n      Sighandler& h = handlers[i];\n      // If the handler was a user handler, reset to\n      // default.  If it was SIG_IGN or SIG_DFL,\n      // leave it alone.\n      if (h.disposition() == SIGNAL_HANDLER) {\n        reset_handler(&h, arch);\n      }\n    }\n  }\n\n  void assert_valid(int sig) const {\n    DEBUG_ASSERT(0 < sig && sig < ssize_t(array_length(handlers)));\n  }\n\n  static shr_ptr create() { return shr_ptr(new Sighandlers()); }\n\n  Sighandler handlers[_NSIG];\n\nprivate:\n  Sighandlers() {}\n  Sighandlers(const Sighandlers&);\n  Sighandlers operator=(const Sighandlers&);\n};\n\nRecordTask::RecordTask(RecordSession& session, pid_t _tid, uint32_t serial,\n                       SupportedArch a)\n    : Task(session, _tid, _tid, serial, a),\n      scheduler_token(0),\n      ticks_at_last_recorded_syscall_exit(0),\n      ip_at_last_recorded_syscall_exit(nullptr),\n      time_at_start_of_last_timeslice(0),\n      priority(0),\n      in_round_robin_queue(false),\n      stable_exit(false),\n      detached_proxy(false),\n      emulated_ptracer(nullptr),\n      emulated_ptrace_event_msg(0),\n      emulated_ptrace_options(0),\n      emulated_ptrace_cont_command(0),\n      emulated_stop_pending(false),\n      emulated_ptrace_SIGCHLD_pending(false),\n      emulated_SIGCHLD_pending(false),\n      emulated_ptrace_seized(false),\n      in_wait_type(WAIT_TYPE_NONE),\n      in_wait_pid(0),\n      creator_tid(0),\n      emulated_stop_type(NOT_STOPPED),\n      blocked_sigs_dirty(true),\n      syscallbuf_blocked_sigs_generation(0),\n      flushed_num_rec_bytes(0),\n      flushed_syscallbuf(false),\n      delay_syscallbuf_reset_for_desched(false),\n      delay_syscallbuf_reset_for_seccomp_trap(false),\n      prctl_seccomp_status(0),\n      robust_futex_list_len(0),\n      termination_signal(0),\n      tsc_mode(PR_TSC_ENABLE),\n      cpuid_mode(1),\n      stashed_signals_blocking_more_signals(false),\n      stashed_group_stop(false),\n      break_at_syscallbuf_traced_syscalls(false),\n      break_at_syscallbuf_untraced_syscalls(false),\n      break_at_syscallbuf_final_instruction(false),\n      syscallstub_exit_breakpoint(),\n      next_pmc_interrupt_is_for_user(false),\n      did_record_robust_futex_changes(false),\n      waiting_for_reap(false),\n      waiting_for_ptrace_exit(false),\n      sent_shutdown_kill(false),\n      did_execveat(false),\n      tick_request_override((TicksRequest)0),\n      schedule_frozen(false) {\n  push_event(Event::sentinel());\n  if (session.tasks().empty()) {\n    // Initial tracee.\n    auto sh = Sighandlers::create();\n    sh->init_from_current_process();\n    // Task::set_up_process resets all non-RT signals to\n    // default handling, so mimic that now.\n    for (int sig = 1; sig <= 31; ++sig) {\n      reset_handler(&sh->get(sig), arch());\n    }\n    sighandlers.swap(sh);\n    own_namespace_rec_tid = _tid;\n  }\n}\n\nRecordTask::~RecordTask() {\n  if (emulated_ptracer) {\n    emulated_ptracer->emulated_ptrace_tracees.erase(this);\n    if (emulated_ptrace_options & PTRACE_O_TRACEEXIT) {\n      ASSERT(this, stable_exit)\n          << \"PTRACE_O_TRACEEXIT only supported for stable exits for now\";\n    }\n  }\n  for (RecordTask* t : emulated_ptrace_tracees) {\n    // XXX emulate PTRACE_O_EXITKILL\n    ASSERT(this, t->emulated_ptracer == this);\n    t->emulated_ptracer = nullptr;\n    t->emulated_ptrace_options = 0;\n    t->emulated_stop_pending = false;\n    t->emulated_stop_type = NOT_STOPPED;\n  }\n\n  // We expect tasks to usually exit by a call to exit() or\n  // exit_group(), so it's not helpful to warn about that.\n  if (EV_SENTINEL != ev().type() &&\n      (pending_events.size() > 2 ||\n       !(ev().type() == EV_SYSCALL &&\n         (is_exit_syscall(ev().Syscall().number, ev().Syscall().regs.arch()) ||\n          is_exit_group_syscall(ev().Syscall().number,\n                                ev().Syscall().regs.arch()))))) {\n    LOG(info) << tid << \" still has pending events.  From top down:\";\n    log_pending_events();\n  }\n\n  if (detached_proxy) {\n    // Kill it so that proceed_to_exit will reach PTRACE_EVENT_EXIT.\n    ::kill(tid, SIGKILL);\n    // We kept the zombie of the original task around to prevent its pid from\n    // being re-used. Reap that now.\n    proceed_to_exit();\n    if (!was_reaped() && may_reap()) {\n      reap();\n    }\n    did_kill();\n  }\n\n  // If this was stopped, notify the scheduler.\n  set_stopped(false);\n\n  session().on_destroy_record_task(this);\n}\n\nvoid RecordTask::record_exit_trace_event(WaitStatus exit_status) {\n  session().trace_writer().write_task_event(\n      TraceTaskEvent::for_exit(tid, exit_status));\n  if (thread_group()->tgid == tid) {\n    thread_group()->exit_status = exit_status;\n  }\n}\n\nvoid RecordTask::record_exit_event(WriteChildTid write_child_tid) {\n  // The kernel explicitly only clears the futex if the address space is shared.\n  // If the address space has no other users then the futex will not be cleared\n  // even if it lives in shared memory which other tasks can read.\n  if (!tid_futex.is_null() && as->task_set().size() > 1 &&\n     as->has_mapping(tid_futex)) {\n    int val = 0;\n    record_local(tid_futex, &val);\n    if (write_child_tid == WRITE_CHILD_TID) {\n      // Write the memory now, otherwise the kernel will write it later and that can\n      // race with the execution of other threads if we don't wait for this\n      // thread to fully exit.\n      // This could fail since the address space might have gone away/been switched\n      // by execve.\n      bool ok = true;\n      write_mem(tid_futex, 0, &ok);\n      // The kernel will do an unconditional futex wake on that location so we don't\n      // need to do it.\n    }\n  }\n\n  // Write the exit event here so that the value recorded above is captured.\n  // Don't flush syscallbuf. Whatever triggered the exit (syscall, signal)\n  // should already have flushed it, if it was running. If it was blocked,\n  // then the syscallbuf would already have been flushed too. Trying to flush\n  // syscallbuf for an exiting task could be bad,\n  // e.g. it could be in the middle of syscallbuf code that's supposed to be\n  // atomic. For the same reasons don't allow syscallbuf to be reset here.\n  record_event(Event::exit(), DONT_FLUSH_SYSCALLBUF, DONT_RESET_SYSCALLBUF);\n}\n\nRecordSession& RecordTask::session() const {\n  return *Task::session().as_record();\n}\n\nTraceWriter& RecordTask::trace_writer() const {\n  return session().trace_writer();\n}\n\nTask* RecordTask::clone(CloneReason reason, int flags, remote_ptr<void> stack,\n                        remote_ptr<void> tls, remote_ptr<int> cleartid_addr,\n                        pid_t new_tid, pid_t new_rec_tid, uint32_t new_serial,\n                        Session* other_session, FdTable::shr_ptr new_fds,\n                        ThreadGroup::shr_ptr new_tg) {\n  ASSERT(this, reason == Task::TRACEE_CLONE);\n  ASSERT(this, !new_fds);\n  ASSERT(this, !new_tg);\n  Task* t = Task::clone(reason, flags, stack, tls, cleartid_addr, new_tid,\n                        new_rec_tid, new_serial, other_session, new_fds,\n                        new_tg);\n  if (t->session().is_recording()) {\n    RecordTask* rt = static_cast<RecordTask*>(t);\n    if (CLONE_CLEARTID & flags) {\n      LOG(debug) << \"cleartid futex is \" << cleartid_addr;\n      ASSERT(this, !cleartid_addr.is_null());\n      rt->tid_futex = cleartid_addr;\n    } else {\n      LOG(debug) << \"(clone child not enabling CLEARTID)\";\n    }\n    if (reason == TRACEE_CLONE) {\n      rt->creator_tid = tid;\n    }\n  }\n  return t;\n}\n\nvoid RecordTask::post_wait_clone(Task* cloned_from, int flags) {\n  ASSERT(cloned_from, cloned_from->session().is_recording());\n  Task::post_wait_clone(cloned_from, flags);\n\n  RecordTask* rt = static_cast<RecordTask*>(cloned_from);\n  priority = rt->priority;\n  syscallbuf_code_layout = rt->syscallbuf_code_layout;\n  prctl_seccomp_status = rt->prctl_seccomp_status;\n  robust_futex_list = rt->robust_futex_list;\n  robust_futex_list_len = rt->robust_futex_list_len;\n  tsc_mode = rt->tsc_mode;\n  cpuid_mode = rt->cpuid_mode;\n  if (CLONE_SHARE_SIGHANDLERS & flags) {\n    sighandlers = rt->sighandlers;\n  } else {\n    auto sh = rt->sighandlers->clone();\n    sighandlers.swap(sh);\n  }\n\n  update_own_namespace_tid();\n}\n\nvoid RecordTask::post_exec() {\n  // Change syscall number to execve/execveat *for the new arch*. If we don't do this,\n  // and the arch changes, then the syscall number for execve in the old arch/\n  // is treated as the syscall we're executing in the new arch, with hilarious\n  // results.\n  int new_syscallno = did_execveat ? syscall_number_for_execveat(arch())\n      : syscall_number_for_execve(arch());\n  registers.set_original_syscallno(new_syscallno);\n  // Fix event architecture and syscall number\n  ev().Syscall().number = new_syscallno;\n  ev().Syscall().set_arch(arch());\n\n  // The signal mask is inherited across execve so we don't need to invalidate.\n  Task::post_exec(exe_path());\n  if (emulated_ptracer) {\n    ASSERT(this, !(emulated_ptracer->arch() == x86 && arch() == x86_64))\n        << \"We don't support a 32-bit process tracing a 64-bit process\";\n  }\n\n  // Clear robust_list state to match kernel state. If this task is cloned\n  // soon after exec, we must not do a bogus set_robust_list syscall for\n  // the clone.\n  set_robust_list(nullptr, 0);\n  sighandlers = sighandlers->clone();\n  sighandlers->reset_user_handlers(arch());\n\n  // Newly execed tasks always have non-faulting mode (from their point of\n  // view, even if rr is secretly causing faults).\n  cpuid_mode = 1;\n}\n\ntemplate <typename Arch> static void do_preload_init_arch(RecordTask* t) {\n  auto params = t->read_mem(\n      remote_ptr<rrcall_init_preload_params<Arch>>(t->regs().orig_arg1()));\n\n  t->syscallbuf_code_layout.syscallbuf_syscall_hook =\n      params.syscallbuf_syscall_hook.rptr().as_int();\n  t->syscallbuf_code_layout.syscallbuf_final_exit_instruction =\n      params.syscallbuf_final_exit_instruction.rptr().as_int();\n  t->syscallbuf_code_layout.syscallbuf_code_start =\n      params.syscallbuf_code_start.rptr().as_int();\n  t->syscallbuf_code_layout.syscallbuf_code_end =\n      params.syscallbuf_code_end.rptr().as_int();\n  t->syscallbuf_code_layout.get_pc_thunks_start =\n      params.get_pc_thunks_start.rptr().as_int();\n  t->syscallbuf_code_layout.get_pc_thunks_end =\n      params.get_pc_thunks_end.rptr().as_int();\n\n  unsigned char in_chaos = t->session().enable_chaos();\n  auto in_chaos_ptr REMOTE_PTR_FIELD(params.globals.rptr(), in_chaos);\n  t->write_mem(in_chaos_ptr, in_chaos);\n  t->record_local(in_chaos_ptr, &in_chaos);\n\n  auto desched_sig = t->session().syscallbuf_desched_sig();\n  auto desched_sig_ptr = REMOTE_PTR_FIELD(params.globals.rptr(), desched_sig);\n  t->write_mem(desched_sig_ptr, desched_sig);\n  t->record_local(desched_sig_ptr, &desched_sig);\n\n  uint64_t random_seed;\n  do {\n    random_seed = rand() | (uint64_t(rand()) << 32);\n  } while (!random_seed);\n  auto random_seed_ptr REMOTE_PTR_FIELD(params.globals.rptr(), random_seed);\n  t->write_mem(random_seed_ptr, random_seed);\n  t->record_local(random_seed_ptr, &random_seed);\n\n  auto cpu_binding = t->session().cpu_binding();\n  int core_num = cpu_binding.mode == BindCPU::SPECIFIED_CORE ?\n    cpu_binding.specified_core : -1;\n  auto cpu_binding_ptr = REMOTE_PTR_FIELD(params.globals.rptr(), cpu_binding);\n  t->write_mem(cpu_binding_ptr, core_num);\n  t->record_local(cpu_binding_ptr, &core_num);\n\n  auto context_switch_event_strategy = ContextSwitchEvent::strategy();\n  auto context_switch_event_strategy_ptr =\n      REMOTE_PTR_FIELD(params.globals.rptr(), context_switch_event_strategy);\n  t->write_mem(context_switch_event_strategy_ptr, context_switch_event_strategy);\n  t->record_local(context_switch_event_strategy_ptr, &context_switch_event_strategy);\n}\n\nvoid RecordTask::push_syscall_event(int syscallno) {\n  push_event(SyscallEvent(syscallno, detect_syscall_arch()));\n}\n\nstatic void do_preload_init(RecordTask* t) {\n  RR_ARCH_FUNCTION(do_preload_init_arch, t->arch(), t);\n}\n\nvoid RecordTask::at_preload_init() {\n  Task::at_preload_init();\n  do_preload_init(this);\n}\n\n/**\n * Avoid using low-numbered file descriptors since that can confuse\n * developers.\n */\nstatic int find_free_file_descriptor(RecordTask* t) {\n  int fd;\n  int fd_limit;\n  struct rlimit limit;\n  // Try to determine what the maximum fd is. If we can't, just\n  // start the search from 0 and bail out if we hit an absurd\n  // number of fds;\n  if (prlimit(t->tgid(), RLIMIT_NOFILE, nullptr, &limit) < 0) {\n    // We might get EPERM if the tracee has changed UID. If that\n    // happens fall back to being slow. (We can probably go faster\n    // using readdir().)\n    ASSERT(t, errno == EPERM) << \"Unknown error in prlimit\";\n    fd_limit = 128*1024;\n    fd = 0;\n  } else {\n    fd_limit = limit.rlim_cur;\n    fd = max(300, t->fd_table()->last_free_fd());\n  }\n\n  bool searched_from_start = fd == 0;\n  while (true) {\n    if (fd >= fd_limit) {\n      ASSERT(t, !searched_from_start) << \"No free fds available\";\n      fd = 0;\n      searched_from_start = true;\n    }\n\n    char buf[PATH_MAX];\n    sprintf(buf, \"/proc/%d/fd/%d\", t->tid, fd);\n    if (access(buf, F_OK) == -1 && errno == ENOENT) {\n      t->fd_table()->set_last_free_fd(fd);\n      return fd;\n    }\n    ++fd;\n  }\n}\n\ntemplate <typename Arch> void RecordTask::init_buffers_arch() {\n  ASSERT(this, as->syscallbuf_enabled())\n      << \"Someone called rrcall_init_buffers with syscallbuf disabled?\";\n\n  // NB: the tracee can't be interrupted with a signal while\n  // we're processing the rrcall, because it's masked off all\n  // signals.\n  AutoRemoteSyscalls remote(this);\n\n  // Arguments to the rrcall.\n  remote_ptr<rrcall_init_buffers_params<Arch>> child_args = regs().orig_arg1();\n  auto args = read_mem(child_args);\n\n  args.cloned_file_data_fd = -1;\n  args.syscallbuf_size = syscallbuf_size = session().syscall_buffer_size();\n  KernelMapping syscallbuf_km = init_syscall_buffer(remote, nullptr);\n  if (!syscallbuf_km.size()) {\n    // Syscallbuf allocation failed. This should mean the child is dead,\n    // but just in case, return an error.\n    remote.regs().set_syscall_result(-ENOMEM);\n    return;\n  }\n\n  args.syscallbuf_ptr = syscallbuf_child;\n  if (syscallbuf_child != nullptr) {\n    // This needs to be skipped if we couldn't allocate the buffer\n    // since replaying only reads (and advances) the mmap record\n    // if `args.syscallbuf_ptr != nullptr`.\n    auto record_in_trace = trace_writer().write_mapped_region(\n      this, syscallbuf_km, syscallbuf_km.fake_stat(), syscallbuf_km.fsname(),\n      vector<TraceRemoteFd>(),\n      TraceWriter::RR_BUFFER_MAPPING);\n    ASSERT(this, record_in_trace == TraceWriter::DONT_RECORD_IN_TRACE);\n  } else {\n    // This can fail, e.g. if the tracee died unexpectedly.\n    LOG(debug) << \"Syscallbuf initialization failed\";\n    args.syscallbuf_size = 0;\n  }\n\n  if (args.syscallbuf_ptr) {\n    desched_fd_child = args.desched_counter_fd;\n    // Prevent the child from closing this fd\n    fds->add_monitor(this, desched_fd_child, new PreserveFileMonitor());\n    if (!desched_fd.init(remote.retrieve_fd(desched_fd_child))) {\n      LOG(warn)\n          << \"ContextSwitchEvent initialization with strategy \"\n             \"STRATEGY_RECORD_SWITCH failed. tracee died unexpectedly or killed ??\";\n    }\n\n    if (trace_writer().supports_file_data_cloning() &&\n        session().use_read_cloning()) {\n      cloned_file_data_fname = trace_writer().file_data_clone_file_name(tuid());\n      ScopedFd clone_file(cloned_file_data_fname.c_str(), O_RDWR | O_CREAT, 0600);\n      int cloned_file_data = remote.infallible_send_fd_if_alive(clone_file);\n      if (cloned_file_data >= 0) {\n        int free_fd = find_free_file_descriptor(this);\n        cloned_file_data_fd_child =\n            remote.syscall(syscall_number_for_dup3(arch()), cloned_file_data,\n                            free_fd, O_CLOEXEC);\n        if (cloned_file_data_fd_child != free_fd) {\n          ASSERT(this, cloned_file_data_fd_child < 0);\n          LOG(warn) << \"Couldn't dup clone-data file to free fd\";\n          cloned_file_data_fd_child = cloned_file_data;\n        } else {\n          // Prevent the child from closing this fd. We're going to close it\n          // ourselves and we don't want the child closing it and then reopening\n          // its own file with this fd.\n          fds->add_monitor(this, cloned_file_data_fd_child,\n                            new PreserveFileMonitor());\n          remote.infallible_close_syscall_if_alive(cloned_file_data);\n        }\n        args.cloned_file_data_fd = cloned_file_data_fd_child;\n      }\n    }\n  }\n  args.scratch_buf = scratch_ptr;\n  args.usable_scratch_size = usable_scratch_size();\n\n  // Return the mapped buffers to the child.\n  write_mem(child_args, args);\n\n  // The tracee doesn't need this addr returned, because it's\n  // already written to the inout |args| param, but we stash it\n  // away in the return value slot so that we can easily check\n  // that we map the segment at the same addr during replay.\n  remote.regs().set_syscall_result(syscallbuf_child);\n}\n\nvoid RecordTask::init_buffers() { RR_ARCH_FUNCTION(init_buffers_arch, arch()); }\n\ntemplate <typename Arch>\nvoid RecordTask::on_syscall_exit_arch(int syscallno, const Registers& regs) {\n  switch (syscallno) {\n    // These syscalls affect the sigmask even if they fail.\n    case Arch::epoll_pwait:\n    case Arch::epoll_pwait2:\n    case Arch::pselect6:\n    case Arch::pselect6_time64:\n    case Arch::ppoll:\n    case Arch::ppoll_time64:\n      invalidate_sigmask();\n      break;\n  }\n\n  if (regs.original_syscallno() == SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO ||\n      regs.syscall_failed()) {\n    return;\n  }\n\n  switch (syscallno) {\n    case Arch::set_robust_list:\n      set_robust_list(regs.orig_arg1(), (size_t)regs.arg2());\n      return;\n    case Arch::sigaction:\n    case Arch::rt_sigaction:\n      // TODO: SYS_signal\n      update_sigaction(regs);\n      return;\n    case Arch::set_tid_address:\n      set_tid_addr(regs.orig_arg1());\n      return;\n    case Arch::sigsuspend:\n    case Arch::rt_sigsuspend:\n    case Arch::sigprocmask:\n    case Arch::rt_sigprocmask:\n    case Arch::pselect6:\n    case Arch::pselect6_time64:\n    case Arch::ppoll:\n    case Arch::ppoll_time64:\n      invalidate_sigmask();\n      return;\n  }\n}\n\nvoid RecordTask::on_syscall_exit(int syscallno, SupportedArch arch,\n                                 const Registers& regs) {\n  with_converted_registers<void>(regs, arch, [&](const Registers& regs) {\n    Task::on_syscall_exit(syscallno, arch, regs);\n    RR_ARCH_FUNCTION(on_syscall_exit_arch, arch, syscallno, regs)\n  });\n}\n\nbool RecordTask::is_at_syscallbuf_syscall_entry_breakpoint() {\n  auto i = ip().undo_executed_bkpt(arch());\n  for (auto p : syscallbuf_syscall_entry_breakpoints()) {\n    if (i == p) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool RecordTask::is_at_syscallbuf_final_instruction_breakpoint() {\n  if (!break_at_syscallbuf_final_instruction) {\n    return false;\n  }\n  auto i = ip().undo_executed_bkpt(arch());\n  return i == syscallbuf_code_layout.syscallbuf_final_exit_instruction;\n}\n\nbool RecordTask::is_at_syscallstub_exit_breakpoint() {\n  if (!break_at_syscallbuf_final_instruction || !syscallstub_exit_breakpoint) {\n    return false;\n  }\n  auto i = ip().undo_executed_bkpt(arch());\n  return i == syscallstub_exit_breakpoint;\n}\n\nvoid RecordTask::will_resume_execution(ResumeRequest, WaitRequest,\n                                       TicksRequest ticks_request, int sig) {\n  // We may execute user code, which could lead to an RDTSC or grow-map\n  // operation which unblocks SIGSEGV, and we'll need to know whether to\n  // re-block it. So we need our cached sigmask to be up to date.\n  // We don't need to this if we're not going to execute user code\n  // (i.e. ticks_request == RESUME_NO_TICKS) except that did_wait can't\n  // easily check for that and may restore blocked_sigs so it had better be\n  // accurate.\n  get_sigmask();\n\n  if (stashed_signals_blocking_more_signals) {\n    // A stashed signal we have already accepted for this task may\n    // have a sigaction::sa_mask that would block the next signal to be\n    // delivered and cause it to be delivered to a different task. If we allow\n    // such a signal to be delivered to this task then we run the risk of never\n    // being able to process the signal (if it stays blocked indefinitely).\n    // To prevent this, block any further signal delivery as long as there are\n    // stashed signals.\n    // We assume the kernel can't report a new signal of the same number\n    // in response to us injecting a signal. XXX is this true??? We don't\n    // have much choice, signal injection won't work if we block the signal.\n    // We leave rr signals unblocked. TIME_SLICE_SIGNAL has to be unblocked\n    // because blocking it seems to cause problems for some hardware/kernel\n    // configurations (see https://github.com/rr-debugger/rr/issues/1979),\n    // causing them to stop counting events.\n    sig_set_t sigset = ~session().rr_signal_mask();\n    if (sig) {\n      // We're injecting a signal, so make sure that signal is unblocked.\n      sigset &= ~signal_bit(sig);\n    }\n    LOG(debug) << \"Set signal mask for \" << tid << \" to block all signals (bar \"\n               << \"SYSCALLBUF_DESCHED_SIGNAL/TIME_SLICE_SIGNAL) while we \"\n               << \"have a stashed signal\";\n    set_sigmask(sigset);\n  }\n\n  // RESUME_NO_TICKS means that tracee code is not going to run so there's no\n  // need to set breakpoints and in fact they might interfere with rr\n  // processing.\n  if (ticks_request != RESUME_NO_TICKS) {\n    if (!at_may_restart_syscall()) {\n      // If the tracee has SIGTRAP blocked or ignored and we hit one of these\n      // breakpoints, the kernel will automatically unblock the signal and set\n      // its disposition to DFL, effects which we ought to undo to keep these\n      // SIGTRAPs invisible to tracees. Fixing the sigmask happens\n      // automatically in did_wait(). Restoring the signal-ignored status is\n      // handled in `handle_syscallbuf_breakpoint`.\n\n      // Set breakpoints at untraced syscalls to catch us entering an untraced\n      // syscall. We don't need to do this (and shouldn't do this) if the\n      // execution requestor wants to stop inside untraced syscalls.\n      // If we have an interrupted syscall that we may restart, don't\n      // set the breakpoints because we should restart the syscall instead\n      // of breaking and delivering signals. The syscallbuf code doesn't\n      // (and must not) perform more than one blocking syscall for any given\n      // buffered syscall.\n      for (auto p : syscallbuf_syscall_entry_breakpoints()) {\n        vm()->add_breakpoint(p, BKPT_INTERNAL);\n      }\n    }\n    if (break_at_syscallbuf_final_instruction) {\n      vm()->add_breakpoint(\n          syscallbuf_code_layout.syscallbuf_final_exit_instruction,\n          BKPT_INTERNAL);\n      auto stub_bp = as->monkeypatcher().get_jump_stub_exit_breakpoint(ip(), this);\n      if (stub_bp) {\n        syscallstub_exit_breakpoint = stub_bp;\n        vm()->add_breakpoint(stub_bp, BKPT_INTERNAL);\n      }\n    }\n  }\n\n  desched_fd.drain_events();\n}\n\nvector<remote_code_ptr> RecordTask::syscallbuf_syscall_entry_breakpoints() {\n  vector<remote_code_ptr> result;\n  if (break_at_syscallbuf_untraced_syscalls) {\n    result.push_back(AddressSpace::rr_page_syscall_entry_point(\n        AddressSpace::UNTRACED, AddressSpace::UNPRIVILEGED,\n        AddressSpace::RECORDING_ONLY, arch()));\n    result.push_back(AddressSpace::rr_page_syscall_entry_point(\n        AddressSpace::UNTRACED, AddressSpace::UNPRIVILEGED,\n        AddressSpace::RECORDING_AND_REPLAY, arch()));\n  }\n  if (break_at_syscallbuf_traced_syscalls) {\n    result.push_back(AddressSpace::rr_page_syscall_entry_point(\n        AddressSpace::TRACED, AddressSpace::UNPRIVILEGED,\n        AddressSpace::RECORDING_AND_REPLAY, arch()));\n  }\n  return result;\n}\n\nvoid RecordTask::did_wait() {\n  for (auto p : syscallbuf_syscall_entry_breakpoints()) {\n    vm()->remove_breakpoint(p, BKPT_INTERNAL);\n  }\n  if (break_at_syscallbuf_final_instruction) {\n    vm()->remove_breakpoint(\n        syscallbuf_code_layout.syscallbuf_final_exit_instruction,\n        BKPT_INTERNAL);\n  }\n  if (syscallstub_exit_breakpoint) {\n    vm()->remove_breakpoint(syscallstub_exit_breakpoint, BKPT_INTERNAL);\n  }\n\n  if (stashed_signals_blocking_more_signals) {\n    // Saved 'blocked_sigs' must still be correct regardless of syscallbuf\n    // state, because we do not allow stashed_signals_blocking_more_signals\n    // to hold across syscalls (traced or untraced) that change the signal mask.\n    ASSERT(this, !blocked_sigs_dirty);\n    // If this fails the tracee is on the exit path and its sigmask is irrelevant.\n    ptrace_if_stopped(PTRACE_SETSIGMASK, remote_ptr<void>(8), &blocked_sigs);\n  } else if (syscallbuf_child) {\n    // The syscallbuf struct is only 32 bytes currently so read the whole thing\n    // at once to avoid multiple calls to read_mem. Even though this shouldn't\n    // need a syscall because we use a local-mapping, apparently that lookup\n    // is still noticeably expensive.\n    auto syscallbuf = read_mem(syscallbuf_child);\n    if (syscallbuf.in_sigprocmask_critical_section) {\n      // |blocked_sigs| may have been updated but the syscall not yet issued.\n      // Use the kernel's value.\n      invalidate_sigmask();\n    } else {\n      uint32_t syscallbuf_generation = syscallbuf.blocked_sigs_generation;\n      if (syscallbuf_generation > syscallbuf_blocked_sigs_generation) {\n        syscallbuf_blocked_sigs_generation = syscallbuf_generation;\n        blocked_sigs = syscallbuf.blocked_sigs;\n      }\n    }\n  }\n}\n\nvoid RecordTask::set_emulated_ptracer(RecordTask* tracer) {\n  if (tracer) {\n    ASSERT(this, !emulated_ptracer);\n    emulated_ptracer = tracer;\n    emulated_ptracer->emulated_ptrace_tracees.insert(this);\n  } else {\n    ASSERT(this, emulated_ptracer);\n    ASSERT(this,\n           emulated_stop_type == NOT_STOPPED ||\n               emulated_stop_type == GROUP_STOP);\n    emulated_ptracer->emulated_ptrace_tracees.erase(this);\n    emulated_ptracer = nullptr;\n  }\n}\n\nbool RecordTask::emulate_ptrace_stop(WaitStatus status, EmulatedStopType stop_type,\n                                     const siginfo_t* siginfo, int si_code) {\n  ASSERT(this, emulated_stop_type == NOT_STOPPED);\n  if (!emulated_ptracer) {\n    return false;\n  }\n  if (siginfo) {\n    ASSERT(this, status.ptrace_signal() == siginfo->si_signo);\n    save_ptrace_signal_siginfo(*siginfo);\n  } else {\n    siginfo_t si;\n    memset(&si, 0, sizeof(si));\n    si.si_signo = status.ptrace_signal();\n    if (status.ptrace_event() || status.is_syscall()) {\n      si.si_code = status.get() >> 8;\n    } else {\n      si.si_code = si_code;\n    }\n    save_ptrace_signal_siginfo(si);\n  }\n  force_emulate_ptrace_stop(status, stop_type);\n  return true;\n}\n\nvoid RecordTask::force_emulate_ptrace_stop(WaitStatus status, EmulatedStopType stop_type) {\n  emulated_stop_type = stop_type;\n  emulated_stop_code = status;\n  emulated_stop_pending = true;\n  emulated_ptrace_SIGCHLD_pending = true;\n\n  emulated_ptracer->send_synthetic_SIGCHLD_if_necessary();\n  // The SIGCHLD will eventually be reported to rr via a ptrace stop,\n  // interrupting wake_task's syscall (probably a waitpid) if necessary. At\n  // that point, we'll fix up the siginfo data with values that match what\n  // the kernel would have delivered for a real ptracer's SIGCHLD. When the\n  // signal handler (if any) returns, if wake_task was in a blocking wait that\n  // wait will be resumed, at which point rec_prepare_syscall_arch will\n  // discover the pending ptrace result and emulate the wait syscall to\n  // return that result immediately.\n}\n\nvoid RecordTask::do_ptrace_exit_stop(WaitStatus exit_status) {\n  // Notify ptracer of the exit if it's not going to receive it from the\n  // kernel because it's not the parent. (The kernel has similar logic to\n  // deliver two stops in this case.)\n  if (emulated_ptracer &&\n      (is_clone_child() ||\n       get_parent_pid() != emulated_ptracer->real_tgid())) {\n    // The task is dead so treat it as not stopped so we can deliver a new stop\n    emulated_stop_type = NOT_STOPPED;\n    // This is a bit wrong; this is an exit stop, not a signal/ptrace stop.\n    emulate_ptrace_stop(exit_status);\n  }\n}\n\nvoid RecordTask::did_reach_zombie() {\n  // Remove from address-space and fds list since we really aren't associated\n  // with them anymore (and we can't be used to operate on them)\n  as->erase_task(this);\n  fds->erase_task(this);\n\n  if (!was_reaped()) {\n    if (may_reap()) {\n      reap();\n    } else {\n      waiting_for_reap = true;\n    }\n  }\n  if ((was_reaped() || !waiting_for_reap) && !emulated_stop_pending) {\n    delete this;\n  }\n}\n\nvoid RecordTask::set_stopped(bool stopped) {\n  if (is_stopped_ == stopped) {\n    return;\n  }\n  is_stopped_ = stopped;\n  if (stopped) {\n    session().scheduler().stopped_task(this);\n  } else {\n    session().scheduler().started_task(this);\n  }\n}\n\nvoid RecordTask::send_synthetic_SIGCHLD_if_necessary() {\n  RecordTask* wake_task = nullptr;\n  bool need_signal = false;\n  for (RecordTask* tracee : emulated_ptrace_tracees) {\n    if (tracee->emulated_ptrace_SIGCHLD_pending) {\n      need_signal = true;\n      // check to see if any thread in the ptracer process is in a waitpid that\n      // could read the status of 'tracee'. If it is, we should wake up that\n      // thread. Otherwise we send SIGCHLD to the ptracer thread.\n      for (Task* t : thread_group()->task_set()) {\n        auto rt = static_cast<RecordTask*>(t);\n        if (rt->is_waiting_for_ptrace(tracee)) {\n          wake_task = rt;\n          break;\n        }\n      }\n      if (wake_task) {\n        break;\n      }\n    }\n  }\n  if (!need_signal) {\n    for (ThreadGroup* child_tg : thread_group()->children()) {\n      for (Task* child : child_tg->task_set()) {\n        RecordTask* rchild = static_cast<RecordTask*>(child);\n        if (rchild->emulated_SIGCHLD_pending) {\n          need_signal = true;\n          // check to see if any thread in the ptracer process is in a waitpid\n          // that could read the status of 'tracee'. If it is, we should wake\n          // up that thread. Otherwise we send SIGCHLD to the ptracer thread.\n          for (Task* t : thread_group()->task_set()) {\n            auto rt = static_cast<RecordTask*>(t);\n            if (rt->is_waiting_for(rchild)) {\n              wake_task = rt;\n              break;\n            }\n          }\n          if (wake_task) {\n            break;\n          }\n        }\n      }\n    }\n    if (!need_signal) {\n      return;\n    }\n  }\n\n  // ptrace events trigger SIGCHLD in the ptracer's wake_task.\n  // We can't set all the siginfo values to their correct values here, so\n  // we'll patch this up when the signal is received.\n  // If there's already a pending SIGCHLD, this signal will be ignored,\n  // but at some point the pending SIGCHLD will be delivered and then\n  // send_synthetic_SIGCHLD_if_necessary will be called again to deliver a new\n  // SIGCHLD if necessary.\n  siginfo_t si;\n  memset(&si, 0, sizeof(si));\n  si.si_code = SI_QUEUE;\n  si.si_value.sival_int = SIGCHLD_SYNTHETIC;\n  int ret;\n  if (wake_task) {\n    LOG(debug) << \"Sending synthetic SIGCHLD to waiting tid \" << wake_task->tid;\n    // We must use the raw SYS_rt_tgsigqueueinfo syscall here to ensure the\n    // signal is sent to the correct thread by tid.\n    ret = syscall(SYS_rt_tgsigqueueinfo, wake_task->tgid(), wake_task->tid,\n                  SIGCHLD, &si);\n    ASSERT(this, ret == 0);\n    // `stashed_signals_blocking_more_signals` means that SIGCHLD can be\n    // blocked even when `is_sig_blocked` is false.\n    if (wake_task->is_sig_blocked(SIGCHLD) ||\n        wake_task->stashed_signals_blocking_more_signals) {\n      LOG(debug) << \"SIGCHLD is blocked, kicking it out of the syscall\";\n      // Just sending SIGCHLD won't wake it up. Send it a TIME_SLICE_SIGNAL\n      // as well to make sure it exits a blocking syscall. We ensure those\n      // can never be blocked.\n      // We have to send a negative code here because only the kernel can set\n      // positive codes. We set a magic number so we can recognize it\n      // when received.\n      si.si_code = SYNTHETIC_TIME_SLICE_SI_CODE;\n      ret = syscall(SYS_rt_tgsigqueueinfo, wake_task->tgid(), wake_task->tid,\n                    PerfCounters::TIME_SLICE_SIGNAL, &si);\n      ASSERT(this, ret == 0);\n    }\n  } else {\n    // Send the signal to the process as a whole and let the kernel\n    // decide which thread gets it.\n    ret = syscall(SYS_rt_sigqueueinfo, tgid(), SIGCHLD, &si);\n    ASSERT(this, ret == 0);\n    LOG(debug) << \"Sending synthetic SIGCHLD to pid \" << tgid();\n  }\n}\n\nstatic bool is_synthetic_SIGCHLD(const siginfo_t& si) {\n  return si.si_signo == SIGCHLD && si.si_value.sival_int == SIGCHLD_SYNTHETIC;\n}\n\nvoid RecordTask::set_siginfo_for_synthetic_SIGCHLD(siginfo_t* si) {\n  if (!is_synthetic_SIGCHLD(*si)) {\n    return;\n  }\n\n  RecordTask* from_task = nullptr;\n  for (RecordTask* tracee : emulated_ptrace_tracees) {\n    if (tracee->emulated_ptrace_SIGCHLD_pending) {\n      if (!from_task) {\n        from_task = tracee;\n      }\n      tracee->emulated_ptrace_SIGCHLD_pending = false;\n    }\n  }\n\n  if (!from_task) {\n    for (ThreadGroup* child_tg : thread_group()->children()) {\n      for (Task* child : child_tg->task_set()) {\n        auto rchild = static_cast<RecordTask*>(child);\n        if (rchild->emulated_SIGCHLD_pending) {\n          if (!from_task) {\n            from_task = rchild;\n          }\n          rchild->emulated_SIGCHLD_pending = false;\n        }\n      }\n    }\n\n    if (!from_task) {\n      // Maybe the task died after the synthetic SIGCHLD was sent\n      LOG(warn) << \"Can't find traced task that send synthetic SIGCHLD\";\n      return;\n    }\n  }\n\n  from_task->set_siginfo_for_waited_task<NativeArch>(\n      reinterpret_cast<NativeArch::siginfo_t*>(si));\n  si->si_value.sival_int = 0;\n}\n\nbool RecordTask::is_waiting_for_ptrace(RecordTask* t) {\n  // This task's process must be a ptracer of t.\n  if (!t->emulated_ptracer ||\n      t->emulated_ptracer->thread_group() != thread_group()) {\n    return false;\n  }\n  // XXX need to check |options| to make sure this task is eligible!!\n  switch (in_wait_type) {\n    case WAIT_TYPE_NONE:\n      return false;\n    case WAIT_TYPE_ANY:\n      return true;\n    case WAIT_TYPE_SAME_PGID:\n      return getpgid(t->tgid()) == getpgid(tgid());\n    case WAIT_TYPE_PGID:\n      return getpgid(t->tgid()) == in_wait_pid;\n    case WAIT_TYPE_PID:\n      // When waiting for a ptracee, a specific pid is interpreted as the\n      // exact tid.\n      return t->tid == in_wait_pid;\n    default:\n      ASSERT(this, false);\n      return false;\n  }\n}\n\nbool RecordTask::is_waiting_for(RecordTask* t) {\n  // t must be a child of this task.\n  if (t->thread_group()->parent() != thread_group().get()) {\n    return false;\n  }\n  switch (in_wait_type) {\n    case WAIT_TYPE_NONE:\n      return false;\n    case WAIT_TYPE_ANY:\n      return true;\n    case WAIT_TYPE_SAME_PGID:\n      return getpgid(t->tgid()) == getpgid(tgid());\n    case WAIT_TYPE_PGID:\n      return getpgid(t->tgid()) == in_wait_pid;\n    case WAIT_TYPE_PID:\n      return t->tgid() == in_wait_pid;\n    default:\n      ASSERT(this, false);\n      return false;\n  }\n}\n\nvoid RecordTask::save_ptrace_signal_siginfo(const siginfo_t& si) {\n  for (auto it = saved_ptrace_siginfos.begin();\n       it != saved_ptrace_siginfos.end(); ++it) {\n    if (it->si_signo == si.si_signo) {\n      saved_ptrace_siginfos.erase(it);\n      break;\n    }\n  }\n  saved_ptrace_siginfos.push_back(si);\n}\n\nsiginfo_t& RecordTask::get_saved_ptrace_siginfo() {\n  int sig = emulated_stop_code.ptrace_signal();\n  ASSERT(this, sig > 0);\n  for (auto it = saved_ptrace_siginfos.begin();\n       it != saved_ptrace_siginfos.end(); ++it) {\n    if (it->si_signo == sig) {\n      return *it;\n    }\n  }\n  ASSERT(this, false) << \"No saved siginfo found for stop-signal???\";\n  while (true) {\n    // Avoid having to return anything along this (unreachable) path\n  }\n}\n\nsiginfo_t RecordTask::take_ptrace_signal_siginfo(int sig) {\n  for (auto it = saved_ptrace_siginfos.begin();\n       it != saved_ptrace_siginfos.end(); ++it) {\n    if (it->si_signo == sig) {\n      siginfo_t si = *it;\n      saved_ptrace_siginfos.erase(it);\n      return si;\n    }\n  }\n  siginfo_t si;\n  memset(&si, 0, sizeof(si));\n  si.si_signo = sig;\n  return si;\n}\n\nstatic pid_t get_ppid(pid_t pid) {\n  auto ppid_str = read_proc_status_fields(pid, \"PPid\");\n  if (ppid_str.empty()) {\n    return -1;\n  }\n  char* end;\n  int actual_ppid = strtol(ppid_str[0].c_str(), &end, 10);\n  return *end ? -1 : actual_ppid;\n}\n\nvoid RecordTask::apply_group_stop(int sig) {\n  if (emulated_stop_type == NOT_STOPPED) {\n    LOG(debug) << \"setting \" << tid << \" to GROUP_STOP due to signal \" << sig;\n    WaitStatus status = WaitStatus::for_group_sig(sig, this);\n    if (!emulate_ptrace_stop(status)) {\n      emulated_stop_type = GROUP_STOP;\n      emulated_stop_code = status;\n      emulated_stop_pending = true;\n      emulated_SIGCHLD_pending = true;\n      RecordTask* t = session().find_task(get_ppid(tid));\n      if (t) {\n        t->send_synthetic_SIGCHLD_if_necessary();\n      }\n    }\n  }\n}\n\nbool RecordTask::is_signal_pending(int sig) {\n  auto pending_strs = read_proc_status_fields(tid, \"SigPnd\", \"ShdPnd\");\n  if (pending_strs.size() < 2) {\n    return false;\n  }\n  char* end1;\n  sig_set_t mask1 = strtoull(pending_strs[0].c_str(), &end1, 16);\n  char* end2;\n  sig_set_t mask2 = strtoull(pending_strs[1].c_str(), &end2, 16);\n  return !*end1 && !*end2 && ((mask1 | mask2) & signal_bit(sig));\n}\n\nbool RecordTask::has_any_actionable_signal() {\n  auto sig_strs = read_proc_status_fields(tid, \"SigPnd\", \"ShdPnd\", \"SigBlk\");\n  if (sig_strs.size() < 3) {\n    return false;\n  }\n\n  char* end1;\n  uint64_t mask1 = strtoull(sig_strs[0].c_str(), &end1, 16);\n  char* end2;\n  uint64_t mask2 = strtoull(sig_strs[1].c_str(), &end2, 16);\n  char* end3;\n  uint64_t mask_blk = strtoull(sig_strs[2].c_str(), &end3, 16);\n  return !*end1 && !*end2 && !*end3 && ((mask1 | mask2) & ~mask_blk);\n}\n\nvoid RecordTask::emulate_SIGCONT() {\n  // All threads in the process are resumed.\n  for (Task* t : thread_group()->task_set()) {\n    auto rt = static_cast<RecordTask*>(t);\n    LOG(debug) << \"setting \" << rt->tid << \" to NOT_STOPPED due to SIGCONT\";\n    rt->clear_stashed_group_stop();\n    rt->emulated_stop_pending = false;\n    rt->emulated_stop_type = NOT_STOPPED;\n  }\n}\n\nvoid RecordTask::signal_delivered(int sig) {\n  bool needs_SIGCHLD = true;\n  Sighandler& h = sighandlers->get(sig);\n  if (h.resethand) {\n    reset_handler(&h, arch());\n  }\n\n  if (is_sig_stopping(sig)) {\n    // All threads in the process are stopped.\n    for (Task* t : thread_group()->task_set()) {\n      auto rt = static_cast<RecordTask*>(t);\n      rt->apply_group_stop(sig);\n    }\n    // apply_group_stop calls send_synthetic_SIGCHLD_if_necessary(). Don't\n    // do it again.\n    needs_SIGCHLD = false;\n  } else if (sig == SIGCONT && !is_sig_ignored(sig)) {\n    emulate_SIGCONT();\n  }\n\n  if (needs_SIGCHLD) {\n    send_synthetic_SIGCHLD_if_necessary();\n  }\n}\n\nbool RecordTask::signal_has_user_handler(int sig) const {\n  return sighandlers->get(sig).disposition() == SIGNAL_HANDLER;\n}\n\nremote_code_ptr RecordTask::get_signal_user_handler(int sig) const {\n  return sighandlers->get(sig).get_user_handler();\n}\n\nconst vector<uint8_t>& RecordTask::signal_action(int sig) const {\n  return sighandlers->get(sig).sa;\n}\n\nbool RecordTask::signal_handler_takes_siginfo(int sig) const {\n  return sighandlers->get(sig).takes_siginfo;\n}\n\nstatic bool is_unstoppable_signal(int sig) {\n  return sig == SIGSTOP || sig == SIGKILL;\n}\n\nbool RecordTask::is_sig_blocked(int sig) {\n  if (is_unstoppable_signal(sig)) {\n    // These can never be blocked\n    return false;\n  }\n  int sig_bit = sig - 1;\n  return (get_sigmask() >> sig_bit) & 1;\n}\n\nbool RecordTask::is_sig_ignored(int sig) const {\n  if (is_unstoppable_signal(sig)) {\n    // These can never be ignored\n    return false;\n  }\n  switch (sighandlers->get(sig).disposition()) {\n    case SIGNAL_IGNORE:\n      return true;\n    case SIGNAL_DEFAULT:\n      return IGNORE == default_action(sig);\n    default:\n      return false;\n  }\n}\n\nbool RecordTask::is_sig_stopping(int sig) const {\n  switch (sig) {\n    case SIGTSTP:\n    case SIGTTIN:\n    case SIGTTOU:\n      if (sig_disposition(sig) != SIGNAL_DEFAULT) {\n        break;\n      }\n      RR_FALLTHROUGH;\n    case SIGSTOP:\n      return true;\n  }\n  return false;\n}\n\nSignalDisposition RecordTask::sig_disposition(int sig) const {\n  return sighandlers->get(sig).disposition();\n}\n\nSignalResolvedDisposition RecordTask::sig_resolved_disposition(\n    int sig, SignalDeterministic deterministic) {\n  if (is_fatal_signal(sig, deterministic)) {\n    return DISPOSITION_FATAL;\n  }\n  if (signal_has_user_handler(sig) && !is_sig_blocked(sig)) {\n    return DISPOSITION_USER_HANDLER;\n  }\n  return DISPOSITION_IGNORED;\n}\n\nvoid RecordTask::set_siginfo(const siginfo_t& si) {\n  pending_siginfo = si;\n  // If this fails, the tracee is on the exit path and its siginfo\n  // is irrelevant.\n  ptrace_if_stopped(PTRACE_SETSIGINFO, nullptr, (void*)&si);\n}\n\ntemplate <typename Arch>\nvoid RecordTask::update_sigaction_arch(const Registers& regs) {\n  int sig = regs.orig_arg1_signed();\n  remote_ptr<typename Arch::kernel_sigaction> new_sigaction = regs.arg2();\n  if (0 == regs.syscall_result() && !new_sigaction.is_null()) {\n    // A new sighandler was installed.  Update our\n    // sighandler table.\n    // TODO: discard attempts to handle or ignore signals\n    // that can't be by POSIX\n    typename Arch::kernel_sigaction sa;\n    memset(&sa, 0, sizeof(sa));\n    read_bytes_helper(new_sigaction, sizeof(sa), &sa);\n    sighandlers->get(sig).init_arch<Arch>(sa);\n  }\n}\n\nvoid RecordTask::update_sigaction(const Registers& regs) {\n  RR_ARCH_FUNCTION(update_sigaction_arch, regs.arch(), regs);\n}\n\nsig_set_t RecordTask::read_sigmask_from_process() {\n  // During syscall interruptions, PTRACE_GETSIGMASK may return the sigmask that is going\n  // to be restored, not the kernel's current (internal) sigmask, which is what\n  // /proc/.../status reports. Always go with what /proc/.../status reports. See\n  // https://github.com/torvalds/linux/commit/fcfc2aa0185f4a731d05a21e9f359968fdfd02e7\n  // XXXkhuey and yet that's not what we actually do here ...\n  if (at_interrupted_non_restartable_signal_modifying_syscall()) {\n    // Mark the sigmask as already invalid. The moment we exit the kernel and run more\n    // of the tracee the sigmask will change, so we need to keep refetching the\n    // sigmask until that happens.\n    invalidate_sigmask();\n  } else if (!at_may_restart_syscall()) {\n    sig_set_t mask;\n    long ret = fallible_ptrace(PTRACE_GETSIGMASK,\n                               remote_ptr<void>(sizeof(sig_set_t)), &mask);\n    if (ret >= 0) {\n      return mask;\n    }\n  }\n\n  auto results = read_proc_status_fields(tid, \"SigBlk\");\n  if (results.empty()) {\n    // Read failed, process probably died\n    return 0;\n  }\n  ASSERT(this, results.size() == 1);\n  return strtoull(results[0].c_str(), NULL, 16);\n}\n\nsig_set_t RecordTask::get_sigmask() {\n  if (blocked_sigs_dirty) {\n    // Clear this first, read_sigmask_from_process might set it again.\n    blocked_sigs_dirty = false;\n    blocked_sigs = read_sigmask_from_process();\n    LOG(debug) << \"Refreshed sigmask, now \" << HEX(blocked_sigs);\n  }\n  return blocked_sigs;\n}\n\nvoid RecordTask::unblock_signal(int sig) {\n  sig_set_t mask = get_sigmask();\n  mask &= ~signal_bit(sig);\n  set_sigmask(mask);\n  invalidate_sigmask();\n}\n\nvoid RecordTask::set_sigmask(sig_set_t mask) {\n  ASSERT(this, is_stopped_);\n  int ret = fallible_ptrace(PTRACE_SETSIGMASK, remote_ptr<void>(8), &mask);\n  if (ret < 0) {\n    if (errno == EIO) {\n      FATAL() << \"PTRACE_SETSIGMASK not supported; rr requires Linux kernel >= 3.11\";\n    }\n    if (errno == ESRCH) {\n      // The task has been unexpectedly killed due to SIGKILL or equivalent.\n      // Just pretend we set the mask; it doesn't matter anymore.\n      // Reporting this to the caller is pointless because callers still need\n      // to handle the case where this function succeeds but the task\n      // is unexpectedly killed immediately afterwards.\n      return;\n    }\n    ASSERT(this, errno == EINVAL);\n  }\n}\n\nvoid RecordTask::set_sig_handler_default(int sig) {\n  did_set_sig_handler_default(sig);\n  // This could happen during a syscallbuf untraced syscall. In that case\n  // our remote syscall here could trigger a desched signal if that event\n  // is armed, making progress impossible. Disarm the event now.\n  disarm_desched_event(this);\n  AutoRemoteSyscalls remote(this);\n  Sighandler& h = sighandlers->get(sig);\n  AutoRestoreMem mem(remote, h.sa.data(), h.sa.size());\n  remote.infallible_syscall(syscall_number_for_rt_sigaction(arch()),\n      sig, mem.get().as_int(), nullptr,\n      sigaction_sigset_size(arch()));\n}\n\nvoid RecordTask::did_set_sig_handler_default(int sig) {\n  Sighandler& h = sighandlers->get(sig);\n  reset_handler(&h, arch());\n}\n\nvoid RecordTask::verify_signal_states() {\n#ifndef DEBUG\n  return;\n#endif\n  if (ev().is_syscall_event()) {\n    // If the syscall event is on the event stack with PROCESSING or EXITING\n    // states, we won't have applied the signal-state updates yet while the\n    // kernel may have.\n    return;\n  }\n  if (detached_proxy) {\n    // This task isn't real\n    return;\n  }\n\n  auto results = read_proc_status_fields(tid, \"SigBlk\", \"SigIgn\", \"SigCgt\");\n  if (results.empty()) {\n    // Read failed, process probably died\n    return;\n  }\n  ASSERT(this, results.size() == 3);\n  sig_set_t blocked = strtoull(results[0].c_str(), NULL, 16);\n  sig_set_t ignored = strtoull(results[1].c_str(), NULL, 16);\n  sig_set_t caught = strtoull(results[2].c_str(), NULL, 16);\n  for (int sig = 1; sig < _NSIG; ++sig) {\n    sig_set_t mask = signal_bit(sig);\n    if (is_unstoppable_signal(sig)) {\n      ASSERT(this, !(blocked & mask))\n          << \"Expected \" << signal_name(sig) << \" to not be blocked, but it is\";\n      ASSERT(this, !(ignored & mask))\n          << \"Expected \" << signal_name(sig) << \" to not be ignored, but it is\";\n      ASSERT(this, !(caught & mask))\n          << \"Expected \" << signal_name(sig) << \" to not be caught, but it is\";\n    } else {\n      ASSERT(this, !!(blocked & mask) == is_sig_blocked(sig))\n          << signal_name(sig)\n          << ((blocked & mask) ? \" is blocked\" : \" is not blocked\");\n      if (sig == SIGCHLD && is_container_init() && (ignored & mask)) {\n        // pid-1-in-its-own-pid-namespace tasks can have their SIGCHLD set\n        // to \"ignore\" when they die (in zap_pid_ns_processes). We may\n        // not have observed anything relating to this death yet. We could\n        // probe to ensure it's already marked as a zombie but why bother.\n        // XXX arguably we should actually change our disposition here but\n        // it would only matter in certain very weird cases: a vfork() where\n        // the child process is pid-1 in its namespace.\n        continue;\n      }\n      auto disposition = sighandlers->get(sig).disposition();\n      ASSERT(this, !!(ignored & mask) == (disposition == SIGNAL_IGNORE))\n          << signal_name(sig)\n          << ((ignored & mask) ? \" is ignored\" : \" is not ignored\");\n      ASSERT(this, !!(caught & mask) == (disposition == SIGNAL_HANDLER))\n          << signal_name(sig)\n          << ((caught & mask) ? \" is caught\" : \" is not caught\");\n    }\n  }\n}\n\nvoid RecordTask::stash_sig() {\n  int sig = stop_sig();\n  ASSERT(this, sig);\n  // Callers should avoid passing SYSCALLBUF_DESCHED_SIGNAL in here.\n  ASSERT(this, sig != session().syscallbuf_desched_sig());\n  // multiple non-RT signals coalesce\n  if (sig < SIGRTMIN) {\n    for (auto it = stashed_signals.begin(); it != stashed_signals.end(); ++it) {\n      if (it->siginfo.si_signo == sig) {\n        LOG(debug) << \"discarding stashed signal \" << sig\n                   << \" since we already have one pending\";\n        return;\n      }\n    }\n  }\n\n  const siginfo_t& si = get_siginfo();\n  stashed_signals.push_back(StashedSignal(si, is_deterministic_signal(this), ip()));\n  // Once we've stashed a signal, stop at the next traced/untraced syscall to\n  // check whether we need to process the signal before it runs.\n  stashed_signals_blocking_more_signals =\n      break_at_syscallbuf_final_instruction =\n          break_at_syscallbuf_traced_syscalls =\n              break_at_syscallbuf_untraced_syscalls = true;\n  syscallstub_exit_breakpoint = nullptr;\n}\n\nvoid RecordTask::stash_synthetic_sig(const siginfo_t& si,\n                                     SignalDeterministic deterministic) {\n  int sig = si.si_signo;\n  DEBUG_ASSERT(sig);\n  // Callers should avoid passing SYSCALLBUF_DESCHED_SIGNAL in here.\n  DEBUG_ASSERT(sig != session().syscallbuf_desched_sig());\n  // multiple non-RT signals coalesce\n  if (sig < SIGRTMIN) {\n    for (auto it = stashed_signals.begin(); it != stashed_signals.end(); ++it) {\n      if (it->siginfo.si_signo == sig) {\n        if (deterministic == DETERMINISTIC_SIG &&\n            it->deterministic == NONDETERMINISTIC_SIG) {\n          stashed_signals.erase(it);\n          break;\n        } else {\n          LOG(debug) << \"discarding stashed signal \" << sig\n                     << \" since we already have one pending\";\n          return;\n        }\n      }\n    }\n  }\n\n  stashed_signals.insert(stashed_signals.begin(),\n                         StashedSignal(si, deterministic, ip()));\n  stashed_signals_blocking_more_signals =\n      break_at_syscallbuf_final_instruction =\n          break_at_syscallbuf_traced_syscalls =\n              break_at_syscallbuf_untraced_syscalls = true;\n  syscallstub_exit_breakpoint = nullptr;\n}\n\nbool RecordTask::has_stashed_sig(int sig) const {\n  for (auto it = stashed_signals.begin(); it != stashed_signals.end(); ++it) {\n    if (it->siginfo.si_signo == sig) {\n      return true;\n    }\n  }\n  return false;\n}\n\nconst RecordTask::StashedSignal* RecordTask::stashed_sig_not_synthetic_SIGCHLD() const {\n  for (auto it = stashed_signals.begin(); it != stashed_signals.end(); ++it) {\n    if (!is_synthetic_SIGCHLD(it->siginfo)) {\n      return &*it;\n    }\n  }\n  return nullptr;\n}\n\nvoid RecordTask::pop_stash_sig(const StashedSignal* stashed) {\n  for (auto it = stashed_signals.begin(); it != stashed_signals.end(); ++it) {\n    if (&*it == stashed) {\n      stashed_signals.erase(it);\n      return;\n    }\n  }\n  ASSERT(this, false) << \"signal not found\";\n}\n\nvoid RecordTask::stashed_signal_processed() {\n  break_at_syscallbuf_final_instruction = break_at_syscallbuf_traced_syscalls =\n      break_at_syscallbuf_untraced_syscalls =\n          stashed_signals_blocking_more_signals = has_stashed_sig();\n  syscallstub_exit_breakpoint = nullptr;\n}\n\nconst RecordTask::StashedSignal* RecordTask::peek_stashed_sig_to_deliver()\n    const {\n  if (stashed_signals.empty()) {\n    return nullptr;\n  }\n  // Choose the first non-synthetic-SIGCHLD signal so that if a syscall should\n  // be interrupted, we'll interrupt it.\n  for (auto& sig : stashed_signals) {\n    if (!is_synthetic_SIGCHLD(sig.siginfo)) {\n      return &sig;\n    }\n  }\n  return &stashed_signals[0];\n}\n\nbool RecordTask::is_syscall_restart() {\n  if (EV_SYSCALL_INTERRUPTION != ev().type()) {\n    return false;\n  }\n\n  int syscallno = regs().original_syscallno();\n  SupportedArch syscall_arch = ev().Syscall().arch();\n  string call_name = syscall_name(syscallno, syscall_arch);\n  bool is_restart = false;\n  LOG(debug) << \"  is syscall interruption of recorded \" << ev() << \"? (now \"\n             << call_name << \")\";\n\n  /* It's possible for the tracee to resume after a sighandler\n   * with a fresh syscall that happens to be the same as the one\n   * that was interrupted.  So we check here if the args are the\n   * same.\n   *\n   * Of course, it's possible (but less likely) for the tracee\n   * to incidentally resume with a fresh syscall that just\n   * happens to have the same *arguments* too.  But in that\n   * case, we would usually set up scratch buffers etc the same\n   * was as for the original interrupted syscall, so we just\n   * save a step here.\n   *\n   * TODO: it's possible for arg structures to be mutated\n   * between the original call and restarted call in such a way\n   * that it might change the scratch allocation decisions. */\n  if (is_restart_syscall_syscall(syscallno, syscall_arch)) {\n    is_restart = true;\n    syscallno = ev().Syscall().number;\n    LOG(debug) << \"  (SYS_restart_syscall)\";\n  }\n  if (ev().Syscall().number != syscallno) {\n    LOG(debug) << \"  interrupted \" << ev() << \" != \" << call_name;\n    goto done;\n  }\n\n  {\n    const Registers& old_regs = ev().Syscall().regs;\n    if (!(old_regs.orig_arg1() == regs().arg1() &&\n          old_regs.arg2() == regs().arg2() &&\n          old_regs.arg3() == regs().arg3() &&\n          old_regs.arg4() == regs().arg4() &&\n          old_regs.arg5() == regs().arg5() &&\n          old_regs.arg6() == regs().arg6())) {\n      LOG(debug) << \"  regs different at interrupted \" << call_name << \": \"\n                 << old_regs << \" vs \" << regs();\n      goto done;\n    }\n  }\n\n  is_restart = true;\n\ndone:\n  if (is_restart) {\n    LOG(debug) << \"  restart of \" << call_name;\n  }\n  return is_restart;\n}\n\ntemplate <typename Arch>\nstatic uint64_t read_ptr_arch(Task* t, remote_ptr<void> p, bool* ok) {\n  return t->read_mem(p.cast<typename Arch::unsigned_word>(), ok);\n}\n\nstatic uint64_t read_ptr(Task* t, remote_ptr<void> p, bool* ok) {\n  RR_ARCH_FUNCTION(read_ptr_arch, t->arch(), t, p, ok);\n}\n\nbool RecordTask::is_in_syscallbuf() {\n  if (!as->syscallbuf_enabled()) {\n    // Even if we're in the rr page, if syscallbuf isn't enabled then the\n    // rr page is not being used by syscallbuf.\n    return false;\n  }\n  remote_code_ptr p = ip();\n  if (is_in_rr_page() || (syscallbuf_code_layout.get_pc_thunks_start <= p &&\n                          p < syscallbuf_code_layout.get_pc_thunks_end)) {\n    // Look at the caller to see if we're in the syscallbuf or not.\n    bool ok = true;\n    uint64_t addr;\n    if (arch() == aarch64) {\n      addr = regs().x(30);\n    }\n    else {\n      ASSERT(this, is_x86ish(arch())) << \"Unknown architecture\";\n      addr = read_ptr(this, regs().sp(), &ok);\n    }\n    if (ok) {\n      p = addr;\n    }\n  }\n  return as->monkeypatcher().is_jump_stub_instruction(p, false) ||\n         (syscallbuf_code_layout.syscallbuf_code_start <= p &&\n          p < syscallbuf_code_layout.syscallbuf_code_end);\n}\n\nbool RecordTask::at_may_restart_syscall() const {\n  ssize_t depth = pending_events.size();\n  const Event* prev_ev = depth > 2 ? &pending_events[depth - 2] : nullptr;\n  return EV_SYSCALL_INTERRUPTION == ev().type() ||\n         (EV_SIGNAL_DELIVERY == ev().type() && prev_ev &&\n          EV_SYSCALL_INTERRUPTION == prev_ev->type());\n}\n\nbool RecordTask::at_interrupted_non_restartable_signal_modifying_syscall() const {\n  auto r = regs();\n  // XXXkhuey io_uring_enter (not yet supported) can do this too.\n  return r.syscall_result_signed() == -EINTR &&\n    (is_epoll_pwait_syscall(r.original_syscallno(), arch()) ||\n     is_epoll_pwait2_syscall(r.original_syscallno(), arch()));\n}\n\nbool RecordTask::is_arm_desched_event_syscall() {\n  return is_desched_event_syscall() && PERF_EVENT_IOC_ENABLE == regs().arg2();\n}\n\nbool RecordTask::is_disarm_desched_event_syscall() {\n  return (is_desched_event_syscall() &&\n          PERF_EVENT_IOC_DISABLE == regs().arg2());\n}\n\nbool RecordTask::may_be_blocked() const {\n  return (EV_SYSCALL == ev().type() &&\n          PROCESSING_SYSCALL == ev().Syscall().state) ||\n         emulated_stop_type != NOT_STOPPED ||\n         (EV_SIGNAL_DELIVERY == ev().type() &&\n          DISPOSITION_FATAL == ev().Signal().disposition) ||\n         waiting_for_ptrace_exit;\n}\n\nbool RecordTask::maybe_in_spinlock() {\n  return time_at_start_of_last_timeslice == session().trace_writer().time() &&\n         regs().matches(registers_at_start_of_last_timeslice);\n}\n\nremote_ptr<const struct syscallbuf_record> RecordTask::desched_rec() const {\n  return (ev().is_syscall_event()\n              ? ev().Syscall().desched_rec\n              : (EV_DESCHED == ev().type()) ? ev().Desched().rec : nullptr);\n}\n\nbool RecordTask::running_inside_desched() const {\n  for (auto& e : pending_events) {\n    if (e.type() == EV_DESCHED) {\n      return e.Desched().rec != desched_rec();\n    }\n  }\n  return false;\n}\n\nint RecordTask::get_ptrace_eventmsg_seccomp_data() {\n  unsigned long data = 0;\n  // in theory we could hit an assertion failure if the tracee suffers\n  // a SIGKILL before we get here. But the SIGKILL would have to be\n  // precisely timed between the generation of a PTRACE_EVENT_FORK/CLONE/\n  // SYS_clone event, and us fetching the event message here.\n  if (fallible_ptrace(PTRACE_GETEVENTMSG, nullptr, &data) < 0) {\n    ASSERT(this, errno == ESRCH);\n    return -1;\n  }\n  return data;\n}\n\nvoid RecordTask::record_local(remote_ptr<void> addr, ssize_t num_bytes,\n                              const void* data) {\n  ASSERT(this, num_bytes >= 0);\n\n  if (!addr) {\n    return;\n  }\n\n  trace_writer().write_raw(rec_tid, data, num_bytes, addr);\n}\n\nbool RecordTask::record_remote_by_local_map(remote_ptr<void> addr,\n                                            size_t num_bytes) {\n  if (uint8_t* local_addr = as->local_mapping(addr, num_bytes)) {\n    record_local(addr, num_bytes, local_addr);\n    return true;\n  }\n  return false;\n}\n\nvoid RecordTask::record_remote(remote_ptr<void> addr, ssize_t num_bytes,\n                               MemWriteSizeValidation size_validation) {\n  ASSERT(this, num_bytes >= 0);\n\n  if (!addr) {\n    return;\n  }\n\n  if (record_remote_by_local_map(addr, num_bytes) != 0) {\n    return;\n  }\n\n  bool ok = true;\n  auto buf = read_mem(addr.cast<uint8_t>(), num_bytes, &ok);\n  if (!ok) {\n    // Tracee probably died unexpectedly. This should only happen\n    // due to SIGKILL racing with our PTRACE_CONT.\n    if (!vm()->find_other_thread_group(this) &&\n        vm()->range_is_private_mapping(MemoryRange(addr, num_bytes))) {\n      // The recording range is mapped private and no other threadgroup shares the\n      // address space, so the new memory contents should be unobservable, and we can\n      // just not record the data.\n      return;\n    }\n    ASSERT(this, false) << \"Should have recorded \" << num_bytes << \" bytes from \"\n                        << addr << \", but failed\";\n  }\n  trace_writer().write_raw(rec_tid, buf.data(), num_bytes, addr, size_validation);\n}\n\nvoid RecordTask::record_remote_writable(remote_ptr<void> addr, ssize_t num_bytes,\n                                        MemWriteSizeValidation size_validation) {\n  ASSERT(this, num_bytes >= 0);\n\n  remote_ptr<void> p = addr;\n  bool seen_rr_mapping = false;\n  int mapping_count = 0;\n  while (p < addr + num_bytes) {\n    if (!as->has_mapping(p)) {\n      break;\n    }\n    ++mapping_count;\n    auto m = as->mapping_of(p);\n    if (m.flags) {\n      seen_rr_mapping = true;\n    }\n    if (!(m.map.prot() & PROT_WRITE) ||\n        (seen_rr_mapping && mapping_count > 1)) {\n      break;\n    }\n    p = m.map.end();\n  }\n  num_bytes = min(num_bytes, p - addr);\n\n  record_remote(addr, num_bytes, size_validation);\n}\n\nssize_t RecordTask::record_remote_fallible(remote_ptr<void> addr,\n                                           uintptr_t num_bytes,\n                                           const std::vector<WriteHole>& holes) {\n  auto hole_iter = holes.begin();\n  uintptr_t offset = 0;\n  vector<uint8_t> buf;\n  while (offset < num_bytes) {\n    if (hole_iter != holes.end() && hole_iter->offset == offset) {\n      offset += hole_iter->size;\n      ++hole_iter;\n      continue;\n    }\n\n    uintptr_t bytes = min(uintptr_t(4*1024*1024), num_bytes - offset);\n    if (hole_iter != holes.end()) {\n      ASSERT(this, hole_iter->offset > offset);\n      bytes = min(bytes, uintptr_t(hole_iter->offset) - offset);\n    }\n    if (record_remote_by_local_map(addr + offset, bytes)) {\n      offset += bytes;\n      continue;\n    }\n\n    if (addr) {\n      buf.resize(bytes);\n      ssize_t nread = read_bytes_fallible(addr + offset, bytes, buf.data());\n      if (nread <= 0) {\n        break;\n      }\n      trace_writer().write_raw_data(buf.data(), nread);\n      offset += nread;\n    } else {\n      offset += bytes;\n    }\n  }\n  trace_writer().write_raw_header(rec_tid, offset, addr, holes);\n  return offset;\n}\n\nvoid RecordTask::record_remote_even_if_null(remote_ptr<void> addr,\n                                            ssize_t num_bytes) {\n  DEBUG_ASSERT(num_bytes >= 0);\n\n  if (!addr) {\n    trace_writer().write_raw(rec_tid, nullptr, 0, addr);\n    return;\n  }\n\n  if (record_remote_by_local_map(addr, num_bytes) != 0) {\n    return;\n  }\n\n  auto buf = read_mem(addr.cast<uint8_t>(), num_bytes);\n  trace_writer().write_raw(rec_tid, buf.data(), num_bytes, addr);\n}\n\nvoid RecordTask::pop_event(EventType expected_type) {\n  ASSERT(this, pending_events.back().type() == expected_type);\n  pending_events.pop_back();\n}\n\nvoid RecordTask::log_pending_events() const {\n  ssize_t depth = pending_events.size();\n\n  DEBUG_ASSERT(depth > 0);\n  if (1 == depth) {\n    LOG(info) << \"(no pending events)\";\n    return;\n  }\n\n  /* The event at depth 0 is the placeholder event, which isn't\n   * useful to log.  Skip it. */\n  for (auto it = pending_events.rbegin(); it != pending_events.rend(); ++it) {\n    LOG(info) << *it;\n  }\n}\n\ntemplate <typename Arch>\nstatic void maybe_handle_set_robust_list_arch(RecordTask* t) {\n  auto remote_locals = AddressSpace::preload_thread_locals_start()\n    .cast<preload_thread_locals<Arch>>();\n  if (!remote_locals) {\n    return;\n  }\n  auto robust_list_ptr = REMOTE_PTR_FIELD(remote_locals, robust_list);\n  auto robust_list = t->read_mem(robust_list_ptr);\n  if (robust_list.len) {\n    t->set_robust_list(robust_list.head.rptr(), robust_list.len);\n\n    auto robust_list_len_ptr = REMOTE_PTR_FIELD(robust_list_ptr, len);\n    t->write_mem(robust_list_len_ptr, static_cast<uint32_t>(0));\n    robust_list.len = 0;\n    t->record_local(robust_list_len_ptr, &robust_list.len);\n  }\n}\n\nstatic void maybe_handle_set_robust_list(RecordTask* t) {\n  RR_ARCH_FUNCTION(maybe_handle_set_robust_list_arch, t->arch(), t);\n}\n\ntemplate <typename Arch>\nstatic void maybe_handle_rseq_arch(RecordTask* t) {\n  auto remote_locals = AddressSpace::preload_thread_locals_start()\n    .cast<preload_thread_locals<Arch>>();\n  if (!remote_locals) {\n    return;\n  }\n  auto rseq_ptr = REMOTE_PTR_FIELD(remote_locals, rseq);\n  auto rseq = t->read_mem(rseq_ptr);\n  if (rseq.len) {\n    t->rseq_state = make_unique<RseqState>(rseq.rseq.rptr(), rseq.sig);\n\n    auto rseq_len_ptr = REMOTE_PTR_FIELD(rseq_ptr, len);\n    t->write_mem(rseq_len_ptr, static_cast<uint32_t>(0));\n    rseq.len = 0;\n    t->record_local(rseq_len_ptr, &rseq.len);\n  }\n}\n\nstatic void maybe_handle_rseq(RecordTask* t) {\n  RR_ARCH_FUNCTION(maybe_handle_rseq_arch, t->arch(), t);\n}\n\nvoid RecordTask::maybe_flush_syscallbuf() {\n  if (EV_SYSCALLBUF_FLUSH == ev().type()) {\n    // Already flushing.\n    return;\n  }\n  if (!syscallbuf_child) {\n    return;\n  }\n\n  // This can be called while the task is not stopped, when we prematurely\n  // terminate the trace. In that case, the tracee could be concurrently\n  // modifying the header. We'll take a snapshot of the header now.\n  // The syscallbuf code ensures that writes to syscallbuf records\n  // complete before num_rec_bytes is incremented.\n  struct syscallbuf_hdr hdr = read_mem(syscallbuf_child);\n\n  ASSERT(this,\n         !flushed_syscallbuf || flushed_num_rec_bytes == hdr.num_rec_bytes);\n\n  if (!hdr.num_rec_bytes || flushed_syscallbuf) {\n    // no records, or we've already flushed.\n    return;\n  }\n\n  push_event(Event(SyscallbufFlushEvent()));\n\n  // Apply buffered mprotect operations and flush the buffer in the tracee.\n  if (hdr.mprotect_record_count) {\n    auto& records = ev().SyscallbufFlush().mprotect_records;\n    records = read_mem(REMOTE_PTR_FIELD(preload_globals, mprotect_records[0]),\n                       hdr.mprotect_record_count);\n    for (auto& r : records) {\n      as->protect(this, r.start, r.size, r.prot);\n    }\n  }\n\n  // Write the entire buffer in one shot without parsing it,\n  // because replay will take care of that.\n  if (is_stopped()) {\n    record_remote(syscallbuf_child, syscallbuf_data_size());\n  } else {\n    vector<uint8_t> buf;\n    buf.resize(sizeof(hdr) + hdr.num_rec_bytes);\n    memcpy(buf.data(), &hdr, sizeof(hdr));\n    read_bytes_helper(syscallbuf_child + 1, hdr.num_rec_bytes,\n                      buf.data() + sizeof(hdr));\n    record_local(syscallbuf_child, buf.size(), buf.data());\n  }\n  maybe_handle_rseq(this);\n  maybe_handle_set_robust_list(this);\n\n  record_current_event();\n  pop_event(EV_SYSCALLBUF_FLUSH);\n\n  flushed_syscallbuf = true;\n  flushed_num_rec_bytes = hdr.num_rec_bytes;\n\n  LOG(debug) << \"Syscallbuf flushed with num_rec_bytes=\"\n             << (uint32_t)hdr.num_rec_bytes;\n}\n\n/**\n * If the syscallbuf has just been flushed, and resetting hasn't been\n * overridden with a delay request, then record the reset event for\n * replay.\n */\nvoid RecordTask::maybe_reset_syscallbuf() {\n  if (flushed_syscallbuf && !delay_syscallbuf_reset_for_desched &&\n      !delay_syscallbuf_reset_for_seccomp_trap) {\n    flushed_syscallbuf = false;\n    LOG(debug) << \"Syscallbuf reset\";\n    reset_syscallbuf();\n    syscallbuf_blocked_sigs_generation = 0;\n    record_event(Event::syscallbuf_reset());\n  }\n}\n\nvoid RecordTask::record_event(Event ev, FlushSyscallbuf flush,\n                              AllowSyscallbufReset reset,\n                              const Registers* registers) {\n  if (flush == FLUSH_SYSCALLBUF) {\n    maybe_flush_syscallbuf();\n  }\n\n  FrameTime current_time = trace_writer().time();\n  if (should_dump_memory(ev, current_time)) {\n    dump_process_memory(this, current_time, \"rec\");\n  }\n  if (should_checksum(ev, current_time)) {\n    checksum_process_memory(this, current_time);\n  }\n  if (!ev.has_ticks_slop()) {\n    // Only associate PT data with events whose timing is\n    // exactly the same between recording and replay.\n    PTData pt_data = hpc.extract_intel_pt_data();\n    if (!pt_data.data.empty()) {\n      write_pt_data(this, current_time, pt_data.data);\n    }\n  }\n\n  if (trace_writer().clear_fip_fdp()) {\n    const ExtraRegisters* maybe_extra = extra_regs_fallible();\n    if (maybe_extra) {\n      ExtraRegisters extra_registers = *maybe_extra;\n      extra_registers.clear_fip_fdp();\n      set_extra_regs(extra_registers);\n    }\n  }\n\n  const ExtraRegisters* extra_registers = nullptr;\n  if (ev.record_regs()) {\n    if (!registers) {\n      registers = &regs();\n    }\n    if (ev.record_extra_regs()) {\n      extra_registers = extra_regs_fallible();\n    }\n  }\n\n  if (ev.is_syscall_event()) {\n    auto state = ev.Syscall().state;\n    if (state == EXITING_SYSCALL) {\n      ticks_at_last_recorded_syscall_exit = tick_count();\n      ip_at_last_recorded_syscall_exit = registers->ip();\n      if (ticks_at_last_recorded_syscall_exit == ticks_at_last_syscall_entry &&\n          ip_at_last_recorded_syscall_exit == ip_at_last_syscall_entry) {\n        // We've done processing this syscall so we can forget about the entry now\n        // This makes sure that any restarted syscalls would not be treated\n        // as the same entry.\n        ticks_at_last_syscall_entry = 0;\n        ip_at_last_syscall_entry = nullptr;\n        last_syscall_entry_recorded = false;\n      }\n    } else if (state == ENTERING_SYSCALL || state == ENTERING_SYSCALL_PTRACE) {\n      if (tick_count() == ticks_at_last_syscall_entry &&\n          registers->ip() == ip_at_last_syscall_entry) {\n        // Let the process handler know that we've recorded the entry already\n        last_syscall_entry_recorded = true;\n      }\n    }\n  }\n\n  remote_code_ptr rseq_new_ip = ip();\n  bool invalid_rseq_cs = false;\n  if (should_apply_rseq_abort(ev.type(), &rseq_new_ip, &invalid_rseq_cs)) {\n    auto addr = REMOTE_PTR_FIELD(rseq_state->ptr.cast<typename NativeArch::rseq_t>(), rseq_cs);\n    uint64_t value = 0;\n    write_mem(addr, value);\n    record_local(addr, &value);\n  } else {\n    ASSERT(this, !invalid_rseq_cs) << \"Invalid rseq_cs found, not currently emulated properly by rr (should segfault)\";\n  }\n\n  trace_writer().write_frame(this, ev, registers, extra_registers);\n  LOG(debug) << \"Wrote event \" << ev << \" for time \" << current_time;\n\n  if (rseq_new_ip != ip()) {\n    Registers r = regs();\n    r.set_ip(rseq_new_ip);\n    set_regs(r);\n  }\n\n  if (!ev.has_ticks_slop() && reset == ALLOW_RESET_SYSCALLBUF) {\n    // After we've output an event, it's safe to reset the syscallbuf (if not\n    // explicitly delayed) since we will have exited the syscallbuf code that\n    // consumed the syscallbuf data.\n    // This only works if the event has a reliable tick count so when we\n    // reach it, we're done.\n    maybe_reset_syscallbuf();\n  }\n}\n\nbool RecordTask::is_fatal_signal(int sig,\n                                 SignalDeterministic deterministic) const {\n  if (thread_group()->received_sigframe_SIGSEGV) {\n    // Can't be blocked, caught or ignored\n    return true;\n  }\n\n  auto action = default_action(sig);\n  if (action != DUMP_CORE && action != TERMINATE) {\n    // If the default action doesn't kill the process, it won't die.\n    return false;\n  }\n\n  if (is_sig_ignored(sig)) {\n    // Deterministic fatal signals can't be ignored.\n    return deterministic == DETERMINISTIC_SIG;\n  }\n  // If there's a signal handler, the signal won't be fatal.\n  return !signal_has_user_handler(sig);\n}\n\nvoid RecordTask::record_current_event() { record_event(ev()); }\n\nvoid RecordTask::set_tid_addr(remote_ptr<int> tid_addr) {\n  LOG(debug) << \"updating cleartid futex to \" << tid_addr;\n  tid_futex = tid_addr;\n}\n\nvoid RecordTask::update_own_namespace_tid() {\n  AutoRemoteSyscalls remote(this);\n  own_namespace_rec_tid =\n      remote.infallible_syscall_if_alive(syscall_number_for_gettid(arch()));\n  if (own_namespace_rec_tid == -ESRCH) {\n    own_namespace_rec_tid = -1;\n  }\n}\n\nvoid RecordTask::kill_if_alive() {\n  if (!seen_ptrace_exit_event()) {\n    tgkill(SIGKILL);\n  }\n}\n\npid_t RecordTask::get_parent_pid() const { return get_ppid(tid); }\n\nvoid RecordTask::set_tid_and_update_serial(pid_t tid,\n                                           pid_t own_namespace_tid) {\n  hpc.set_tid(tid);\n  this->tid = rec_tid = tid;\n  serial = session().next_task_serial();\n  own_namespace_rec_tid = own_namespace_tid;\n}\n\nbool RecordTask::may_reap() {\n  if (emulated_stop_pending) {\n    LOG(debug) << \"Declining to reap \" << tid << \"; emulated stop pending \" << emulated_stop_code;\n    // Don't reap until the emulated ptrace stop has been processed.\n    return false;\n  }\n  // Non thread-group-leaders may always be reaped\n  if (tid != real_tgid()) {\n    return true;\n  }\n  for (auto it : thread_group()->task_set()) {\n    if (&*it != this) {\n      LOG(debug) << \"Declining to reap \" << tid << \"; leader of non-empty thread-group with active thread \" << it->tid;\n      return false;\n    }\n  }\n  return true;\n}\n\nvoid RecordTask::reap() {\n  ASSERT(this, !was_reaped_);\n  LOG(debug) << \"Reaping \" << tid;\n  WaitOptions options(tid);\n  options.block_seconds = 0;\n  WaitManager::wait_exit(options);\n  was_reaped_ = true;\n}\n\nstatic uint64_t read_pid_ns(const RecordTask* t) {\n  char buf[PATH_MAX];\n  sprintf(buf, \"/proc/%d/ns/pid\", t->tid);\n  char link[PATH_MAX];\n  int ret = readlink(buf, link, sizeof(link));\n  ASSERT(t, ret >= 0);\n  ASSERT(t, ret < (int)sizeof(link));\n  link[ret] = 0;\n  ASSERT(t, strncmp(link, \"pid:[\", 5) == 0);\n  char* end;\n  uint64_t result = strtoul(link + 5, &end, 10);\n  ASSERT(t, strcmp(end, \"]\") == 0);\n  return result;\n}\n\nbool RecordTask::waiting_for_pid_namespace_tasks_to_exit() const {\n  // read_pid_ns() will fail if we're reaped\n  if (tg->tgid_own_namespace != 1 || was_reaped()) {\n    return false;\n  }\n  // This might be the last live thread for pid-1 in the pid namespace.\n  // Checking that it *is* the last live thread is tricky because other\n  // threads could unexpectedly die asynchronously :-(.\n  // See if there are any other tasks in the pid namespace.\n  // Note that due to setns there can be tasks in the pid namespace\n  // with parents outside the pid namespace other than our thread-group.\n\n  // If there are multiple threads in our threadgroup, they're in our\n  // pid namespace.\n  if (thread_group()->task_set().size() > 1) {\n    return true;\n  }\n  // If we have any child processes then those belong to our pid namespace\n  // (or a descendant).\n  for (auto p : session().thread_group_map()) {\n    if (p.second->parent() == tg.get()) {\n      return true;\n    }\n  }\n  // If there are any other tasks in the pid namespace at least one must be\n  // directly in the namespace.\n  uint64_t pid_ns = read_pid_ns(this);\n  for (auto it : session().tasks()) {\n    auto rt = static_cast<RecordTask*>(it.second);\n    if (rt == this) {\n      continue;\n    }\n    if (read_pid_ns(rt) == pid_ns) {\n      return true;\n    }\n  }\n  return false;\n}\n\n// Disable chaos mode memory randomization for 32-bit ASAN builds. There isn't\n// much address space to play with and it gets tricky.\nbool RecordTask::enable_chaos_memory_allocations() const {\n  return session().enable_chaos() &&\n    !as->layout_randomization_disabled() &&\n    (session().excluded_ranges().empty() || word_size(arch()) >= 8);\n}\n\nint RecordTask::process_depth() const {\n  int depth = 0;\n  ThreadGroup* tg = this->tg.get();\n  while (tg) {\n    ++depth;\n    tg = tg->parent();\n  }\n  return depth;\n}\n\ntemplate <typename Arch>\nstatic void maybe_restore_original_syscall_registers_arch(RecordTask* t,\n                                                          void* local_addr) {\n  if (!local_addr) {\n    return;\n  }\n  auto locals = reinterpret_cast<preload_thread_locals<Arch>*>(local_addr);\n  static_assert(sizeof(*locals) <= PRELOAD_THREAD_LOCALS_SIZE,\n                \"bad PRELOAD_THREAD_LOCALS_SIZE\");\n  if (!locals->original_syscall_parameters) {\n    return;\n  }\n  auto args = t->read_mem(locals->original_syscall_parameters.rptr());\n  Registers r = t->regs();\n  if (args.no != r.syscallno()) {\n    // Maybe a preparatory syscall before the real syscall (e.g. sys_read)\n    return;\n  }\n  r.set_arg1(args.args[0]);\n  r.set_arg2(args.args[1]);\n  r.set_arg3(args.args[2]);\n  r.set_arg4(args.args[3]);\n  r.set_arg5(args.args[4]);\n  r.set_arg6(args.args[5]);\n  t->set_regs(r);\n}\n\nvoid RecordTask::maybe_restore_original_syscall_registers() {\n  RR_ARCH_FUNCTION(maybe_restore_original_syscall_registers_arch, arch(), this,\n                   preload_thread_locals());\n}\n\nbool RecordTask::post_vm_clone(CloneReason reason, int flags, Task* origin) {\n  if (Task::post_vm_clone(reason, flags, origin)) {\n    KernelMapping preload_thread_locals_mapping =\n      vm()->mapping_of(AddressSpace::preload_thread_locals_start()).map;\n    auto mode = trace_writer().write_mapped_region(\n      this, preload_thread_locals_mapping,\n      preload_thread_locals_mapping.fake_stat(),\n      preload_thread_locals_mapping.fsname(),\n      vector<TraceRemoteFd>(),\n      TraceWriter::RR_BUFFER_MAPPING);\n    ASSERT(this, mode == TraceWriter::DONT_RECORD_IN_TRACE);\n    return true;\n  }\n\n  return false;\n};\n\nbool RecordTask::try_grow_map(remote_ptr<void> addr) {\n  if (vm()->has_mapping(addr)) {\n    LOG(debug) << \"try_grow_map \" << addr << \": address already mapped\";\n    return false;\n  }\n  auto maps = vm()->maps_starting_at(floor_page_size(addr));\n  auto it = maps.begin();\n  if (it == maps.end()) {\n    LOG(debug) << \"try_grow_map \" << addr << \": no later map to grow downward\";\n    return false;\n  }\n  if (!(it->map.flags() & MAP_GROWSDOWN)) {\n    LOG(debug) << \"try_grow_map \" << addr << \": map is not MAP_GROWSDOWN (\"\n               << it->map << \")\";\n    return false;\n  }\n  if (addr >= page_size() && vm()->has_mapping(addr - page_size())) {\n    LOG(debug) << \"try_grow_map \" << addr << \": address would be in guard page\";\n    return false;\n  }\n  remote_ptr<void> limit_bottom;\n#if defined (__i386__)\n  struct rlimit stack_limit;\n  int ret = prlimit(tid, RLIMIT_STACK, NULL, &stack_limit);\n#else\n  struct rlimit64 stack_limit;\n  int ret = syscall(__NR_prlimit64, tid, RLIMIT_STACK, (void*)0, &stack_limit);\n#endif\n  if (ret >= 0 && stack_limit.rlim_cur != RLIM_INFINITY) {\n    limit_bottom = ceil_page_size(it->map.end() - stack_limit.rlim_cur);\n    if (limit_bottom > addr) {\n      LOG(debug) << \"try_grow_map \" << addr << \": RLIMIT_STACK exceeded\";\n      return false;\n    }\n  }\n\n  // Try to grow by 64K at a time to reduce signal frequency.\n  auto new_start = floor_page_size(addr);\n  static const uintptr_t grow_size = 0x10000;\n  if (it->map.start().as_int() >= grow_size) {\n    auto possible_new_start = std::max(\n        limit_bottom, std::min(new_start, it->map.start() - grow_size));\n    // Ensure that no mapping exists between possible_new_start - page_size()\n    // and new_start. If there is, possible_new_start is not valid, in which\n    // case we just abandon the optimization.\n    if (possible_new_start >= page_size() &&\n        !vm()->has_mapping(possible_new_start - page_size()) &&\n        vm()->maps_starting_at(possible_new_start - page_size())\n                .begin()\n                ->map.start() == it->map.start()) {\n      new_start = possible_new_start;\n    }\n  }\n  LOG(debug) << \"try_grow_map \" << addr << \": trying to grow map \" << it->map;\n\n  {\n    AutoRemoteSyscalls remote(this, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);\n    remote.infallible_mmap_syscall_if_alive(\n        new_start, it->map.start() - new_start, it->map.prot(),\n        (it->map.flags() & ~MAP_GROWSDOWN) | MAP_ANONYMOUS | MAP_FIXED, -1, 0);\n  }\n\n  KernelMapping km =\n      vm()->map(this, new_start, it->map.start() - new_start, it->map.prot(),\n                it->map.flags() | MAP_ANONYMOUS, 0, string(),\n                KernelMapping::NO_DEVICE, KernelMapping::NO_INODE);\n  trace_writer().write_mapped_region(this, km, km.fake_stat(), km.fsname(), vector<TraceRemoteFd>());\n  // No need to flush syscallbuf here. It's safe to map these pages \"early\"\n  // before they're really needed.\n  record_event(Event::grow_map(), RecordTask::DONT_FLUSH_SYSCALLBUF);\n  LOG(debug) << \"try_grow_map \" << addr << \": extended map \"\n             << vm()->mapping_of(addr).map;\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/RecordTask.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_RECORD_TASK_H_\n#define RR_RECORD_TASK_H_\n\n#include \"ContextSwitchEvent.h\"\n#include \"Registers.h\"\n#include \"Task.h\"\n#include \"TraceFrame.h\"\n\nnamespace rr {\n\nstruct Sighandlers;\nclass TaskSyscallStateBase {\npublic:\n  virtual ~TaskSyscallStateBase() {}\n};\n\n/** Different kinds of waits a task can do.\n */\nenum WaitType {\n  // Not waiting for anything\n  WAIT_TYPE_NONE,\n  // Waiting for any child process\n  WAIT_TYPE_ANY,\n  // Waiting for any child with the same process group ID\n  WAIT_TYPE_SAME_PGID,\n  // Waiting for any child with a specific process group ID\n  WAIT_TYPE_PGID,\n  // Waiting for a specific process ID\n  WAIT_TYPE_PID\n};\n\n/** Reasons why we simulate stopping of a task (see ptrace(2) man page).\n */\nenum EmulatedStopType {\n  NOT_STOPPED,\n  GROUP_STOP,          // stopped by a signal. This applies to non-ptracees too.\n  SIGNAL_DELIVERY_STOP,// Stopped before delivering a signal. ptracees only.\n  SYSCALL_ENTRY_STOP,  // Stopped at syscall entry. ptracees only\n  SYSCALL_EXIT_STOP,   // Stopped at syscall exit. ptracees only\n  SECCOMP_STOP,        // Stopped at seccomp stop. ptracees only\n  CHILD_STOP           // All other kinds of non-ptrace stops\n};\n\n/**\n * Pass USE_SYSGOOD to emulate_ptrace_stop to add 0x80 to the signal\n * if PTRACE_O_TRACESYSGOOD is in effect.\n */\nenum AddSysgoodFlag { IGNORE_SYSGOOD, USE_SYSGOOD };\n\nstruct SyscallbufCodeLayout {\n  remote_code_ptr syscallbuf_code_start;\n  remote_code_ptr syscallbuf_code_end;\n  remote_code_ptr get_pc_thunks_start;\n  remote_code_ptr get_pc_thunks_end;\n  remote_code_ptr syscallbuf_syscall_hook;\n  remote_code_ptr syscallbuf_final_exit_instruction;\n};\n\nenum SignalDisposition { SIGNAL_DEFAULT, SIGNAL_IGNORE, SIGNAL_HANDLER };\n\n/**\n * Every Task owned by a RecordSession is a RecordTask. Functionality that\n * only applies during recording belongs here.\n */\nclass RecordTask final : public Task {\npublic:\n  RecordTask(RecordSession& session, pid_t _tid, uint32_t serial,\n             SupportedArch a);\n\n  Task* clone(CloneReason reason, int flags, remote_ptr<void> stack,\n              remote_ptr<void> tls, remote_ptr<int> cleartid_addr,\n              pid_t new_tid, pid_t new_rec_tid, uint32_t new_serial,\n              Session* other_session = nullptr,\n              FdTable::shr_ptr new_fds = nullptr,\n              ThreadGroup::shr_ptr new_tg = nullptr) override;\n  virtual void post_wait_clone(Task* cloned_from, int flags) override;\n  virtual void on_syscall_exit(int syscallno, SupportedArch arch,\n                               const Registers& regs) override;\n  virtual void will_resume_execution(ResumeRequest, WaitRequest, TicksRequest,\n                                     int /*sig*/) override;\n  virtual void did_wait() override;\n\n  bool enable_chaos_memory_allocations() const;\n\n  std::vector<remote_code_ptr> syscallbuf_syscall_entry_breakpoints();\n  bool is_at_syscallbuf_syscall_entry_breakpoint();\n  bool is_at_syscallbuf_final_instruction_breakpoint();\n  bool is_at_syscallstub_exit_breakpoint();\n\n  /**\n   * Initialize tracee buffers in this, i.e., implement\n   * RRCALL_init_syscall_buffer.  This task must be at the point\n   * of *exit from* the rrcall.  Registers will be updated with\n   * the return value from the rrcall, which is also returned\n   * from this call.\n   */\n  void init_buffers();\n  void post_exec();\n  /**\n   * Called when SYS_rrcall_init_preload has happened.\n   */\n  virtual void at_preload_init() override;\n\n  RecordSession& session() const;\n  TraceWriter& trace_writer() const;\n\n  /**\n   * Emulate 'tracer' ptracing this task.\n   */\n  void set_emulated_ptracer(RecordTask* tracer);\n  /**\n   * Call this when an event occurs that should stop a ptraced task.\n   * If we're emulating ptrace of the task, stop the task and wake the ptracer\n   * if it's waiting, and queue \"status\" to be reported to the\n   * ptracer. If siginfo is non-null, we'll report that siginfo, otherwise we'll\n   * make one up based on the status (unless the status is an exit code).\n   * Returns true if the task is stopped-for-emulated-ptrace, false otherwise.\n   */\n  bool emulate_ptrace_stop(WaitStatus status,\n                           const siginfo_t* siginfo = nullptr, int si_code = 0) {\n    return emulate_ptrace_stop(status, status.group_stop() ? GROUP_STOP : SIGNAL_DELIVERY_STOP,\n      siginfo, si_code);\n  }\n  bool emulate_ptrace_stop(WaitStatus status, EmulatedStopType stop_type,\n                           const siginfo_t* siginfo = nullptr, int si_code = 0);\n\n  /**\n   * Force the ptrace-stop state no matter what state the task is currently in.\n   */\n  void force_emulate_ptrace_stop(WaitStatus status, EmulatedStopType stop_type);\n  /**\n   * If necessary, signal the ptracer that this task has exited.\n   */\n  void do_ptrace_exit_stop(WaitStatus exit_status);\n\n  void record_exit_trace_event(WaitStatus exit_status);\n  /**\n   * Return the exit event.\n   * If write_child_tid is set, zero out child_tid now if applicable.\n   */\n  enum WriteChildTid {\n    KERNEL_WRITES_CHILD_TID,\n    WRITE_CHILD_TID,\n  };\n  void record_exit_event(WriteChildTid write_child_tid = KERNEL_WRITES_CHILD_TID);\n  /**\n   * Called when we're about to deliver a signal to this task. If it's a\n   * synthetic SIGCHLD and there's a ptraced task that needs to SIGCHLD,\n   * update the siginfo to reflect the status and note that that\n   * ptraced task has had its SIGCHLD sent.\n   * Note that we can't set the correct siginfo when we send the signal, because\n   * it requires us to set information only the kernel has permission to set.\n   */\n  void set_siginfo_for_synthetic_SIGCHLD(siginfo_t* si);\n  /**\n   * Sets up |si| as if we're delivering a SIGCHLD/waitid for this waited task.\n   */\n  template <typename Arch>\n  void set_siginfo_for_waited_task(typename Arch::siginfo_t* si) {\n    // XXX: The `ptrace` argument is likely incorrect here.\n    emulated_stop_code.fill_siginfo<Arch>(si,\n      emulated_stop_type != GROUP_STOP, emulated_ptrace_options);\n    si->_sifields._sigchld.si_pid_ = tgid();\n    si->_sifields._sigchld.si_uid_ = getuid();\n  }\n  /**\n   * Return a reference to the saved siginfo record for the stop-signal\n   * that we're currently in a ptrace-stop for.\n   */\n  siginfo_t& get_saved_ptrace_siginfo();\n  /**\n   * When emulating a ptrace-continue with a signal number, extract the siginfo\n   * that was saved by |save_ptrace_signal_siginfo|. If no such siginfo was\n   * saved, make one up.\n   */\n  siginfo_t take_ptrace_signal_siginfo(int sig);\n\n  /**\n   * Returns true if this task is in a waitpid or similar that would return\n   * when t's status changes due to a ptrace event.\n   */\n  bool is_waiting_for_ptrace(RecordTask* t);\n  /**\n   * Returns true if this task is in a waitpid or similar that would return\n   * when t's status changes due to a regular event (exit).\n   */\n  bool is_waiting_for(RecordTask* t);\n\n  bool already_exited() const override {\n    return waiting_for_reap;\n  }\n\n  bool is_detached_proxy() const override {\n    return detached_proxy;\n  }\n\n  /**\n   * Call this to force a group stop for this task with signal 'sig',\n   * notifying ptracer if necessary.\n   */\n  void apply_group_stop(int sig);\n  /**\n   * Call this after |sig| is delivered to this task.  Emulate\n   * sighandler updates induced by the signal delivery.\n   */\n  void signal_delivered(int sig);\n  /**\n   * Return true if |sig| is pending but hasn't been reported to ptrace yet\n   */\n  bool is_signal_pending(int sig);\n  /**\n   * Return true if there are any signals pending that are not blocked.\n   */\n  bool has_any_actionable_signal();\n  /**\n   * Get all threads out of an emulated GROUP_STOP\n   */\n  void emulate_SIGCONT();\n  /**\n   * Return true if the disposition of |sig| in |table| isn't\n   * SIG_IGN or SIG_DFL, that is, if a user sighandler will be\n   * invoked when |sig| is received.\n   */\n  bool signal_has_user_handler(int sig) const;\n  /**\n   * If signal_has_user_handler(sig) is true, return the address of the\n   * user handler, otherwise return null.\n   */\n  remote_code_ptr get_signal_user_handler(int sig) const;\n  /**\n   * Return true if the signal handler for |sig| takes a siginfo_t*\n   * parameter.\n   */\n  bool signal_handler_takes_siginfo(int sig) const;\n  /**\n   * Return |sig|'s current sigaction. Returned as raw bytes since the\n   * data is architecture-dependent.\n   */\n  const std::vector<uint8_t>& signal_action(int sig) const;\n  /** Return true iff |sig| is blocked for this. */\n  bool is_sig_blocked(int sig);\n  /**\n   * Return true iff |sig| is SIG_IGN, or it's SIG_DFL and the\n   * default disposition is \"ignore\".\n   */\n  bool is_sig_ignored(int sig) const;\n  /**\n   * Return true iff |sig| is a stopping signal.\n   */\n  bool is_sig_stopping(int sig) const;\n  /**\n   * Return the applications current disposition of |sig|.\n   */\n  SignalDisposition sig_disposition(int sig) const;\n  /**\n   * Return the resolved disposition --- what this signal will actually do,\n   * taking into account the default behavior.\n   */\n  SignalResolvedDisposition sig_resolved_disposition(\n      int sig, SignalDeterministic deterministic);\n  /**\n   * Set the siginfo for the signal-stop of this.\n   */\n  void set_siginfo(const siginfo_t& si);\n  /** Note that the task sigmask needs to be refetched. */\n  void invalidate_sigmask() { blocked_sigs_dirty = true; }\n  /**\n   * Reset the signal handler for this signal to the default.\n   */\n  void did_set_sig_handler_default(int sig);\n\n  /**\n   * Check that our status for |sig| matches what's in /proc/<pid>/status.\n   */\n  void verify_signal_states();\n\n  /**\n   * Stashed-signal API: if a signal becomes pending at an\n   * awkward time, but could be handled \"soon\", call\n   * |stash_sig()| to stash the current pending-signal state.\n   *\n   * |has_stashed_sig()| obviously returns true if |stash_sig()|\n   * has been called successfully.\n   *\n   * |pop_stash_sig()| restores the (relevant) state of this\n   * Task to what was saved in |stash_sig()|, and returns the\n   * saved siginfo.  After this call, |has_stashed_sig()| is\n   * false.\n   *\n   * NB: |get_siginfo()| will always return the \"real\" siginfo,\n   * regardless of stash popped-ness state.  Callers must ensure\n   * they do the right thing with the popped siginfo.\n   *\n   * If the process unexpectedly died (due to SIGKILL), we don't\n   * stash anything.\n   */\n  void stash_sig();\n  void stash_synthetic_sig(const siginfo_t& si,\n                           SignalDeterministic deterministic);\n  bool has_stashed_sig() const { return !stashed_signals.empty(); }\n  struct StashedSignal {\n    StashedSignal(const siginfo_t& siginfo, SignalDeterministic deterministic,\n                  remote_code_ptr ip)\n        : siginfo(siginfo), deterministic(deterministic), ip(ip) {}\n    siginfo_t siginfo;\n    SignalDeterministic deterministic;\n    remote_code_ptr ip;\n  };\n  const StashedSignal* stashed_sig_not_synthetic_SIGCHLD() const;\n  bool has_stashed_sig(int sig) const;\n  const StashedSignal* peek_stashed_sig_to_deliver() const;\n  void pop_stash_sig(const StashedSignal* stashed);\n  void stashed_signal_processed();\n\n  /**\n   * If a group-stop occurs at an inconvenient time, stash it and\n   * process it later.\n   */\n  void stash_group_stop() { stashed_group_stop = true; }\n  void clear_stashed_group_stop() { stashed_group_stop = false; }\n  bool has_stashed_group_stop() const { return stashed_group_stop; }\n\n  /**\n   * Return true if the current state of this looks like the\n   * interrupted syscall at the top of our event stack, if there\n   * is one.\n   */\n  bool is_syscall_restart();\n  /**\n   * Return true iff this is at an execution state where\n   * resuming execution may lead to the restart of an\n   * interrupted syscall.\n   *\n   * For example, if a signal without a user handler is about to\n   * be delivered to this just after a syscall interruption,\n   * then delivering the signal may restart the first syscall\n   * and this method will return true.\n   */\n  bool at_may_restart_syscall() const;\n  /**\n   * Return true iff this is at an execution state where\n   * a syscall that modifies signals was interrupted but will not\n   * be automatically restarted.\n   **/\n  bool at_interrupted_non_restartable_signal_modifying_syscall() const;\n  /**\n   * Return true if this is at an arm-desched-event syscall.\n   */\n  bool is_arm_desched_event_syscall();\n  /**\n   * Return true if this is at a disarm-desched-event syscall.\n   */\n  bool is_disarm_desched_event_syscall();\n  /**\n   * Return true if |t| may not be immediately runnable,\n   * i.e., resuming execution and then |waitpid()|'ing may block\n   * for an unbounded amount of time.  When the task is in this\n   * state, the tracer must await a |waitpid()| notification\n   * that the task is no longer possibly-blocked before resuming\n   * its execution.\n   */\n  bool may_be_blocked() const;\n  /**\n   * Returns true if it looks like this task has been spinning on an atomic\n   * access/lock.\n   */\n  bool maybe_in_spinlock();\n  /**\n   * Return true if this is within the syscallbuf library.  This\n   * *does not* imply that $ip is at a buffered syscall.\n   * This also includes the runtime stub code that runs\n   * before entering syscallbuf but does not include the \"safe area\".\n   * Returning true from this function implies that the code will execute\n   * `_syscallbuf_final_exit_instruction` before returning to normal code.\n   */\n  bool is_in_syscallbuf();\n  /**\n   * Shortcut to the most recent |pending_event->desched.rec| when\n   * there's a desched event on the stack, and nullptr otherwise.\n   * Exists just so that clients don't need to dig around in the\n   * event stack to find this record.\n   */\n  remote_ptr<const struct syscallbuf_record> desched_rec() const;\n  /**\n   * Returns true when the task is in a signal handler in an interrupted\n   * system call being handled by syscall buffering.\n   */\n  bool running_inside_desched() const;\n  /**\n   * Returns -1 if we failed (the process unexpectedly exited).\n   */\n  int get_ptrace_eventmsg_seccomp_data();\n\n  /**\n   * Save tracee data to the trace.  |addr| is the address in\n   * the address space of this task.  The |record_local*()|\n   * variants record data that's already been read from this,\n   * and the |record_remote*()| variants read the data and then\n   * record it.\n   * If 'addr' is null then no record is written.\n   */\n  void record_local(remote_ptr<void> addr, ssize_t num_bytes, const void* buf);\n  template <typename T>\n  void record_local(remote_ptr<T> addr, const T* buf, size_t count = 1) {\n    record_local(addr, sizeof(T) * count, buf);\n  }\n  void record_remote(remote_ptr<void> addr, ssize_t num_bytes,\n                     MemWriteSizeValidation size_validation = MemWriteSizeValidation::EXACT);\n  template <typename T> void record_remote(remote_ptr<T> addr) {\n    record_remote(addr, sizeof(T));\n  }\n  void record_remote(const MemoryRange& range) {\n    record_remote(range.start(), range.size());\n  }\n  ssize_t record_remote_fallible(const MemoryRange& range) {\n    return record_remote_fallible(range.start(), range.size());\n  }\n  // Record as much as we can of the bytes in this range. Will record only\n  // contiguous mapped data starting at `addr`.\n  ssize_t record_remote_fallible(remote_ptr<void> addr, uintptr_t num_bytes,\n                                 const std::vector<WriteHole>& holes = std::vector<WriteHole>());\n  // Record as much as we can of the bytes in this range. Will record only\n  // contiguous mapped-writable data starting at `addr`. rr mappings (e.g. syscallbuf)\n  // are treated as non-contiguous with any other mapping.\n  void record_remote_writable(remote_ptr<void> addr, ssize_t num_bytes,\n                              MemWriteSizeValidation size_validation = MemWriteSizeValidation::EXACT);\n\n  // Simple helper that attempts to use the local mapping to record if one\n  // exists\n  bool record_remote_by_local_map(remote_ptr<void> addr, size_t num_bytes);\n\n  template <typename T>\n  void write_and_record(remote_ptr<T> addr, const T& value, bool* ok = nullptr,\n                        uint32_t flags = 0) {\n    write_mem(addr, value, ok, flags);\n    record_local(addr, &value, 1);\n  }\n\n  /**\n   * Save tracee data to the trace.  |addr| is the address in\n   * the address space of this task.\n   * If 'addr' is null then a zero-length record is written.\n   */\n  void record_remote_even_if_null(remote_ptr<void> addr, ssize_t num_bytes);\n  template <typename T> void record_remote_even_if_null(remote_ptr<T> addr) {\n    record_remote_even_if_null(addr, sizeof(T));\n  }\n\n  /**\n   * Manage pending events.  |push_event()| pushes the given\n   * event onto the top of the event stack.  The |pop_*()|\n   * helpers pop the event at top of the stack, which must be of\n   * the specified type.\n   */\n  void push_event(const Event& ev) { pending_events.push_back(ev); }\n  void push_syscall_event(int syscallno);\n  void pop_event(EventType expected_type);\n  void pop_noop() { pop_event(EV_NOOP); }\n  void pop_desched() { pop_event(EV_DESCHED); }\n  void pop_seccomp_trap() { pop_event(EV_SECCOMP_TRAP); }\n  void pop_signal_delivery() { pop_event(EV_SIGNAL_DELIVERY); }\n  void pop_signal_handler() { pop_event(EV_SIGNAL_HANDLER); }\n  void pop_syscall() { pop_event(EV_SYSCALL); }\n  void pop_syscall_interruption() { pop_event(EV_SYSCALL_INTERRUPTION); }\n  virtual void log_pending_events() const override;\n  /** Return the event at the top of this's stack. */\n  Event& ev() { return pending_events.back(); }\n  const Event& ev() const { return pending_events.back(); }\n\n  /**\n   * Obtain the previous event on the stack (if any) or nullptr (if not)\n   */\n  Event *prev_ev() {\n    ssize_t depth = pending_events.size();\n    return depth > 2 ? &pending_events[depth - 2] : nullptr;\n  }\n\n  /**\n   * Call this before recording events or data.  Records\n   * syscallbuf data and flushes the buffer, if there's buffered\n   * data.\n   *\n   * The timing of calls to this is tricky. We must flush the syscallbuf\n   * before recording any data associated with events that happened after the\n   * buffered syscalls. But we don't support flushing a syscallbuf twice with\n   * no intervening reset, i.e. after flushing we have to be sure we'll get\n   * a chance to reset the syscallbuf (i.e. record some other kind of event)\n   * before the tracee runs again in a way that might append another buffered\n   * syscall --- so we can't flush too early\n   */\n  void maybe_flush_syscallbuf();\n  /**\n   * Call this after recording an event when it might be safe to reset the\n   * syscallbuf. It must be after recording an event to ensure during replay\n   * we run past any syscallbuf after-syscall code that uses the buffer data.\n   */\n  void maybe_reset_syscallbuf();\n  /**\n   * Record an event on behalf of this.  Record the registers of\n   * this (and other relevant execution state) so that it can be\n   * used or verified during replay, if that state is available\n   * and meaningful at this's current execution point.\n   * |record_current_event()| record |this->ev()|, and\n   * |record_event()| records the specified event.\n   */\n  void record_current_event();\n  enum FlushSyscallbuf {\n    FLUSH_SYSCALLBUF,\n    /* Pass this if it's safe to replay the event before we process the\n     * syscallbuf records.\n     */\n    DONT_FLUSH_SYSCALLBUF\n  };\n  enum AllowSyscallbufReset {\n    ALLOW_RESET_SYSCALLBUF,\n    /* Pass this if it's safe to replay the event before we process the\n     * syscallbuf records.\n     */\n    DONT_RESET_SYSCALLBUF\n  };\n  // Take `ev` by value to avoid bugs where we pass in an event in\n  // `pending_events`, which could lead to dangling references when\n  // flushing the syscallbuf manipulates `pending_events`.\n  void record_event(Event ev, FlushSyscallbuf flush = FLUSH_SYSCALLBUF,\n                    AllowSyscallbufReset reset = ALLOW_RESET_SYSCALLBUF,\n                    const Registers* registers = nullptr);\n\n  bool is_fatal_signal(int sig, SignalDeterministic deterministic) const;\n\n  /**\n   * If the process looks alive, kill it.\n   */\n  void kill_if_alive();\n\n  remote_ptr<void> robust_list() const { return robust_futex_list; }\n  size_t robust_list_len() const { return robust_futex_list_len; }\n\n  /** Uses /proc so not trivially cheap. */\n  pid_t get_parent_pid() const;\n\n  /**\n   * Return true if this is a \"clone child\" per the wait(2) man page.\n   */\n  bool is_clone_child() { return termination_signal != SIGCHLD; }\n\n  void set_termination_signal(int sig) { termination_signal = sig; }\n\n  /**\n   * When a signal triggers an emulated a ptrace-stop for this task,\n   * save the siginfo so a later emulated ptrace-continue with this signal\n   * number can use it.\n   */\n  void save_ptrace_signal_siginfo(const siginfo_t& si);\n\n  enum { SYNTHETIC_TIME_SLICE_SI_CODE = -9999 };\n\n  /**\n   * Tasks normally can't change their tid. There is one very special situation\n   * where they can: when a non-main-thread does an execve, its tid changes\n   * to the tid of the thread-group leader.\n   */\n  void set_tid_and_update_serial(pid_t tid, pid_t own_namespace_tid);\n\n  /**\n   * Return our cached copy of the signal mask, updating it if necessary.\n   */\n  sig_set_t get_sigmask();\n  /**\n   * Just get the signal mask of the process.\n   */\n  sig_set_t read_sigmask_from_process();\n  /**\n   * Unblock the signal for the process.\n   */\n  void unblock_signal(int sig);\n  /**\n   * Set the signal handler to default for the process.\n   */\n  void set_sig_handler_default(int sig);\n\n  ~RecordTask();\n\n  void maybe_restore_original_syscall_registers();\n\n  /**\n   * The task reached zombie state. Do whatever processing is necessary (reaping\n   * it, emulating ptrace stops, etc.)\n   */\n  void did_reach_zombie();\n\n  // Is this task a container init? (which has special signal behavior)\n  bool is_container_init() const { return tg->tgid_own_namespace == 1; }\n\n  /**\n   * Linux requires the invariant that all members of a thread group\n   * are reaped before the thread group leader. This determines whether or\n   * not we're allowed to attempt reaping this thread or whether doing so\n   * risks deadlock.\n   */\n  bool may_reap();\n\n  /**\n   * Reaps a task-exit notification, thus detaching us from the tracee.\n   * N.B.: If may_reap is false, this risks a deadlock.\n   */\n  void reap();\n\n  bool waiting_for_pid_namespace_tasks_to_exit() const;\n  int process_depth() const;\n\n  /**\n   * Called when this task is able to receive a SIGCHLD (e.g. because\n   * we completed delivery of a signal). Sends a new synthetic\n   * SIGCHLD to the task if there are still tasks that need a SIGCHLD\n   * sent for them.\n   * May queue signals for specific tasks.\n   */\n  void send_synthetic_SIGCHLD_if_necessary();\n\n  void set_sigmask(sig_set_t mask);\n\n  /**\n   * Update the futex robust list head pointer to |list| (which\n   * is of size |len|).\n   */\n  void set_robust_list(remote_ptr<void> list, size_t len) {\n    robust_futex_list = list;\n    robust_futex_list_len = len;\n  }\n\n  void set_stopped(bool stopped) override;\n\n  // Tries to extend an adjacent `MAP_GROWSDOWN` mapping to include the\n  // given address. Returns false if nothing was done.\n  bool try_grow_map(remote_ptr<void> addr);\n\nprivate:\n  /* Retrieve the tid of this task from the tracee and store it */\n  void update_own_namespace_tid();\n\n  /**\n   * Wait for |futex| in this address space to have the value\n   * |val|.\n   *\n   * WARNING: this implementation semi-busy-waits for the value\n   * change.  This must only be used in contexts where the futex\n   * will change \"soon\".\n   */\n  void futex_wait(remote_ptr<int> futex, int val, bool* ok);\n\n  /**\n   * Call this when SYS_sigaction is finishing with |regs|.\n   */\n  void update_sigaction(const Registers& regs);\n\n  template <typename Arch> void init_buffers_arch();\n  template <typename Arch>\n  void on_syscall_exit_arch(int syscallno, const Registers& regs);\n  /** Helper function for update_sigaction. */\n  template <typename Arch> void update_sigaction_arch(const Registers& regs);\n\n  /** Update the clear-tid futex to |tid_addr|. */\n  void set_tid_addr(remote_ptr<int> tid_addr);\n\n  virtual bool post_vm_clone(CloneReason reason, int flags, Task* origin) override;\n\npublic:\n  uint64_t scheduler_token;\n  std::unique_ptr<TaskSyscallStateBase> syscall_state;\n  Ticks ticks_at_last_recorded_syscall_exit;\n  remote_code_ptr ip_at_last_recorded_syscall_exit;\n\n  // Scheduler state\n\n  Registers registers_at_start_of_last_timeslice;\n  FrameTime time_at_start_of_last_timeslice;\n  /* Task 'nice' value set by setpriority(2).\n     We use this to drive scheduling decisions. rr's scheduler is\n     deliberately simple and unfair; a task never runs as long as there's\n     another runnable task with a lower nice value. */\n  int priority;\n  /* Tasks with in_round_robin_queue set are in the session's\n   * in_round_robin_queue instead of its task_priority_set.\n   */\n  bool in_round_robin_queue;\n  /* exit(), or exit_group() with one task, has been called, so\n   * the exit can be treated as stable. */\n  bool stable_exit;\n\n  bool detached_proxy;\n\n  // ptrace emulation state\n\n  // Task for which we're emulating ptrace of this task, or null\n  RecordTask* emulated_ptracer;\n  std::set<RecordTask*> emulated_ptrace_tracees;\n  uintptr_t emulated_ptrace_event_msg;\n  // Saved emulated-ptrace signals\n  std::vector<siginfo_t> saved_ptrace_siginfos;\n  // Code to deliver to ptracer/waiter when it waits. Note that zero can be a\n  // valid code! Reset to zero when leaving the stop due to PTRACE_CONT etc.\n  WaitStatus emulated_stop_code;\n  // Always zero while no ptracer is attached.\n  int emulated_ptrace_options;\n  // One of PTRACE_CONT, PTRACE_SYSCALL --- or 0 if the tracee has not been\n  // continued by its ptracer yet, or has no ptracer.\n  int emulated_ptrace_cont_command;\n  // true when a ptracer/waiter wait() can return |emulated_stop_code|.\n  bool emulated_stop_pending;\n  // true if this task needs to send a SIGCHLD to its ptracer for its\n  // emulated ptrace stop\n  bool emulated_ptrace_SIGCHLD_pending;\n  // true if this task needs to send a SIGCHLD to its parent for its\n  // emulated stop\n  bool emulated_SIGCHLD_pending;\n  // tracer attached via PTRACE_SEIZE\n  bool emulated_ptrace_seized;\n  WaitType in_wait_type;\n  int in_wait_options;\n  pid_t in_wait_pid;\n  pid_t creator_tid;\n\n  // Signal handler state\n\n  // Points to the signal-hander table of this task.  If this\n  // task is a non-fork clone child, then the table will be\n  // shared with all its \"thread\" siblings.  Any updates made to\n  // that shared table are immediately visible to all sibling\n  // threads.\n  //\n  // fork children always get their own copies of the table.\n  // And if this task exec()s, the table is copied and stripped\n  // of user sighandlers (see below). */\n  std::shared_ptr<Sighandlers> sighandlers;\n  // If not NOT_STOPPED, then the task is logically stopped and this is the type\n  // of stop.\n  EmulatedStopType emulated_stop_type;\n  // True if the task sigmask may have changed and we need to refetch it.\n  bool blocked_sigs_dirty;\n  // Most accesses to this should use set_sigmask and get_sigmask to ensure\n  // the mirroring to syscallbuf is correct.\n  sig_set_t blocked_sigs;\n  uint32_t syscallbuf_blocked_sigs_generation;\n\n  // Syscallbuf state\n\n  SyscallbufCodeLayout syscallbuf_code_layout;\n  ContextSwitchEvent desched_fd;\n  /* Value of hdr->num_rec_bytes when the buffer was flushed */\n  uint32_t flushed_num_rec_bytes;\n  /* Nonzero after the trace recorder has flushed the\n   * syscallbuf.  When this happens, the recorder must prepare a\n   * \"reset\" of the buffer, to zero the record count, at the\n   * next available slow (taking |desched| into\n   * consideration). */\n  bool flushed_syscallbuf;\n  /* This bit is set when code wants to prevent the syscall\n   * record buffer from being reset when it normally would be.\n   * This bit is set by the desched code. */\n  bool delay_syscallbuf_reset_for_desched;\n  /* This is set when code wants to prevent the syscall\n   * record buffer from being reset when it normally would be.\n   * This is set by the code for handling seccomp SIGSYS signals. */\n  bool delay_syscallbuf_reset_for_seccomp_trap;\n  // Value to return from PR_GET_SECCOMP\n  uint8_t prctl_seccomp_status;\n\n  // Mirrored kernel state\n  // This state agrees with kernel-internal values\n\n  // Futex list passed to |set_robust_list()|.  We could keep a\n  // strong type for this list head and read it if we wanted to,\n  // but for now we only need to remember its address / size at\n  // the time of the most recent set_robust_list() call.\n  remote_ptr<void> robust_futex_list;\n  size_t robust_futex_list_len;\n  // The memory cell the kernel will clear and notify on exit,\n  // if our clone parent requested it.\n  remote_ptr<int> tid_futex;\n  // Signal delivered by the kernel when this task terminates, or zero\n  int termination_signal;\n\n  // Our value for PR_GET/SET_TSC (one of PR_TSC_ENABLED, PR_TSC_SIGSEGV).\n  int tsc_mode;\n  // Our value for ARCH_GET/SET_CPUID (0 -> generate SIGSEGV, 1 -> do CPUID).\n  // Only used if session().has_cpuid_faulting().\n  int cpuid_mode;\n  // The current stack of events being processed.\n  std::vector<Event> pending_events;\n  // Stashed signal-delivery state, ready to be delivered at\n  // next opportunity.\n  std::deque<StashedSignal> stashed_signals;\n  // When true, we're blocking signals during a syscall to\n  // prevent new signals from being delivered. `blocked_sigs_dirty`\n  // is false and `blocked_sigs` contains the previous sigmask.\n  bool stashed_signals_blocking_more_signals;\n  bool stashed_group_stop;\n  bool break_at_syscallbuf_traced_syscalls;\n  bool break_at_syscallbuf_untraced_syscalls;\n  bool break_at_syscallbuf_final_instruction;\n  remote_code_ptr syscallstub_exit_breakpoint;\n\n  // The pmc is programmed to interrupt at a value requested by the tracee, not\n  // by rr.\n  bool next_pmc_interrupt_is_for_user;\n\n  bool did_record_robust_futex_changes;\n\n  // This task is just waiting to be reaped.\n  bool waiting_for_reap;\n\n  // This task is waiting for a ptrace exit event. It should not\n  // be manually run.\n  bool waiting_for_ptrace_exit;\n\n  // We've sent a SIGKILL during shutdown for this task.\n  bool sent_shutdown_kill;\n\n  // Last exec system call was an execveat\n  bool did_execveat;\n\n  // Set if the tracee requested an override of the ticks request.\n  // Used for testing.\n  TicksRequest tick_request_override;\n\n  // Set to prevent the scheduler from scheduling this tid, even\n  // if it is otherwise considered runnable. Used for testing.\n  bool schedule_frozen;\n};\n\n} // namespace rr\n\n#endif /* RR_RECORD_TASK_H_ */\n"
  },
  {
    "path": "src/Registers.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Registers.h\"\n\n#include <array>\n#include <initializer_list>\n#include <utility>\n\n#include <string.h>\n\n#include \"ReplayTask.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstruct RegisterValue {\n  // The name of this register.\n  const char* name;\n  // The offsetof the register in user_regs_struct.\n  size_t offset;\n  // The size of the register.  0 means we cannot read it.\n  size_t nbytes;\n  // Mask to be applied to register values prior to comparing them.  Will\n  // typically be ((1 << nbytes) - 1), but some registers may have special\n  // comparison semantics.\n  uint64_t comparison_mask;\n\n  constexpr RegisterValue()\n      : name(nullptr), offset(0), nbytes(0), comparison_mask(0) {}\n\n  RegisterValue(const char* name_, size_t offset_, size_t nbytes_)\n      : name(name_), offset(offset_), nbytes(nbytes_) {\n    comparison_mask = mask_for_nbytes(nbytes_);\n  }\n\n  RegisterValue(const char* name_, size_t offset_, size_t nbytes_,\n                uint64_t comparison_mask_, size_t size_override = 0)\n      : name(name_),\n        offset(offset_),\n        nbytes(nbytes_),\n        comparison_mask(comparison_mask_) {\n    // Ensure no bits are set outside of the register's bitwidth.\n    DEBUG_ASSERT((comparison_mask_ & ~mask_for_nbytes(nbytes_)) == 0);\n    if (size_override > 0) {\n      nbytes = size_override;\n    }\n  }\n  // Returns a pointer to the register in |regs| represented by |offset|.\n  // |regs| is assumed to be a pointer to the user_struct_regs for the\n  // appropriate architecture.\n  void* pointer_into(void* regs) { return static_cast<char*>(regs) + offset; }\n\n  const void* pointer_into(const void* regs) {\n    return static_cast<const char*>(regs) + offset;\n  }\n\n  static uint64_t mask_for_nbytes(size_t nbytes) {\n    DEBUG_ASSERT(nbytes <= sizeof(comparison_mask));\n    return ((nbytes == sizeof(comparison_mask)) ? uint64_t(0)\n                                                : (uint64_t(1) << nbytes * 8)) -\n           1;\n  }\n};\n\ntypedef std::pair<size_t, RegisterValue> RegisterInit;\n\ntemplate <size_t N> struct RegisterTable : std::array<RegisterValue, N> {\n  RegisterTable(std::initializer_list<RegisterInit> list) {\n    for (auto& ri : list) {\n      (*this)[ri.first] = ri.second;\n    }\n  }\n};\n\ntemplate <typename T> struct RegisterInfo;\n\ntemplate <> struct RegisterInfo<rr::X86Arch> {\n  static bool ignore_undefined_register(GdbServerRegister regno) {\n    return regno == DREG_FOSEG || regno == DREG_MXCSR;\n  }\n  static const size_t num_registers = DREG_NUM_LINUX_I386;\n  typedef RegisterTable<num_registers> Table;\n  static Table registers;\n};\n\ntemplate <> struct RegisterInfo<rr::X64Arch> {\n  static bool ignore_undefined_register(GdbServerRegister regno) {\n    return regno == DREG_64_FOSEG || regno == DREG_64_MXCSR;\n  }\n  static const size_t num_registers = DREG_NUM_LINUX_X86_64;\n  typedef RegisterTable<num_registers> Table;\n  static Table registers;\n};\n\ntemplate <> struct RegisterInfo<rr::ARM64Arch> {\n  static bool ignore_undefined_register(GdbServerRegister) {\n    return false;\n  }\n  static const size_t num_registers = DREG_NUM_LINUX_AARCH64;\n  typedef RegisterTable<num_registers> Table;\n  static Table registers;\n};\n\n#define RV_ARCH(gdb_suffix, name, arch, extra_ctor_args)                       \\\n  RegisterInit(DREG_##gdb_suffix,                                              \\\n               RegisterValue(#name, offsetof(arch::user_regs_struct, name),    \\\n                             sizeof(((arch::user_regs_struct*)0)->name)        \\\n                                 extra_ctor_args))\n#define RV_X86(gdb_suffix, name)                                               \\\n  RV_ARCH(gdb_suffix, name, rr::X86Arch, /* empty */)\n#define RV_X64(gdb_suffix, name)                                               \\\n  RV_ARCH(gdb_suffix, name, rr::X64Arch, /* empty */)\n#define COMMA ,\n#define RV_X86_WITH_MASK(gdb_suffix, name, comparison_mask)                    \\\n  RV_ARCH(gdb_suffix, name, rr::X86Arch, COMMA comparison_mask)\n#define RV_X64_WITH_MASK(gdb_suffix, name, comparison_mask, size)              \\\n  RV_ARCH(gdb_suffix, name, rr::X64Arch, COMMA comparison_mask COMMA size)\n#define RV_AARCH64(gdb_suffix, name) RV_ARCH(gdb_suffix, name, rr::ARM64Arch, /* empty */)\n#define RV_AARCH64_WITH_MASK(gdb_suffix, name, comparison_mask, size)          \\\n  RV_ARCH(gdb_suffix, name, rr::ARM64Arch, COMMA comparison_mask COMMA size)\n\nRegisterInfo<rr::X86Arch>::Table RegisterInfo<rr::X86Arch>::registers = {\n  RV_X86(EAX, eax), RV_X86(ECX, ecx), RV_X86(EDX, edx), RV_X86(EBX, ebx),\n  RV_X86(ESP, esp), RV_X86(EBP, ebp), RV_X86(ESI, esi), RV_X86(EDI, edi),\n  RV_X86(EIP, eip), RV_X86_WITH_MASK(EFLAGS, eflags, 0),\n  RV_X86_WITH_MASK(CS, xcs, 0), RV_X86_WITH_MASK(SS, xss, 0),\n  RV_X86_WITH_MASK(DS, xds, 0), RV_X86_WITH_MASK(ES, xes, 0),\n  // Mask out the RPL from the fs and gs segment selectors. The kernel\n  // unconditionally sets RPL=3 on sigreturn, but if the segment index is 0,\n  // the RPL doesn't matter, and the CPU resets the entire register to 0,\n  // so whether or not we see this depends on whether the value round-tripped\n  // to the CPU yet.\n  RV_X86_WITH_MASK(FS, xfs, (uint16_t)~3),\n  RV_X86_WITH_MASK(GS, xgs, (uint16_t)~3),\n  // The comparison for this is handled specially elsewhere.\n  RV_X86_WITH_MASK(ORIG_EAX, orig_eax, 0),\n};\n\nRegisterInfo<rr::X64Arch>::Table RegisterInfo<rr::X64Arch>::registers = {\n  RV_X64(RAX, rax), RV_X64(RCX, rcx), RV_X64(RDX, rdx), RV_X64(RBX, rbx),\n  RV_X64_WITH_MASK(RSP, rsp, 0, 8), RV_X64(RBP, rbp), RV_X64(RSI, rsi),\n  RV_X64(RDI, rdi), RV_X64(R8, r8), RV_X64(R9, r9), RV_X64(R10, r10),\n  RV_X64(R11, r11), RV_X64(R12, r12), RV_X64(R13, r13), RV_X64(R14, r14),\n  RV_X64(R15, r15), RV_X64(RIP, rip), RV_X64_WITH_MASK(64_EFLAGS, eflags, 0, 4),\n  RV_X64_WITH_MASK(64_CS, cs, 0, 4), RV_X64_WITH_MASK(64_SS, ss, 0, 4),\n  RV_X64_WITH_MASK(64_DS, ds, 0, 4), RV_X64_WITH_MASK(64_ES, es, 0, 4),\n  RV_X64_WITH_MASK(64_FS, fs, 0xffffffffLL, 4),\n  RV_X64_WITH_MASK(64_GS, gs, 0xffffffffLL, 4),\n  // The comparison for this is handled specially\n  // elsewhere.\n  RV_X64_WITH_MASK(ORIG_RAX, orig_rax, 0, 8), RV_X64(FS_BASE, fs_base),\n  RV_X64(GS_BASE, gs_base),\n};\n\nRegisterInfo<rr::ARM64Arch>::Table RegisterInfo<rr::ARM64Arch>::registers = {\n  RV_AARCH64(X0, x[0]), RV_AARCH64(X1, x[1]), RV_AARCH64(X2, x[2]),\n  RV_AARCH64(X3, x[3]), RV_AARCH64(X4, x[4]), RV_AARCH64(X5, x[5]),\n  RV_AARCH64(X6, x[6]),\n  // Don't compare these - the kernel sometimes lies [1] about this value\n  // [1] https://github.com/torvalds/linux/blob/d2f8825ab78e4c18686f3e1a756a30255bb00bf3/arch/arm64/kernel/ptrace.c#L1814-L1820\n  RV_AARCH64_WITH_MASK(X7, x[7], 0, 8),\n  RV_AARCH64(X8, x[8]), RV_AARCH64(X9, x[9]),\n  RV_AARCH64(X10, x[10]), RV_AARCH64(X11, x[11]), RV_AARCH64(X12, x[12]),\n  RV_AARCH64(X13, x[13]), RV_AARCH64(X14, x[14]), RV_AARCH64(X15, x[15]),\n  RV_AARCH64(X16, x[16]), RV_AARCH64(X17, x[17]), RV_AARCH64(X18, x[18]),\n  RV_AARCH64(X19, x[19]),\n  RV_AARCH64(X20, x[20]), RV_AARCH64(X21, x[21]), RV_AARCH64(X22, x[22]),\n  RV_AARCH64(X23, x[23]), RV_AARCH64(X24, x[24]), RV_AARCH64(X25, x[25]),\n  RV_AARCH64(X26, x[26]), RV_AARCH64(X27, x[27]), RV_AARCH64(X28, x[28]),\n  RV_AARCH64(X29, x[29]), RV_AARCH64(X30, x[30]),\n  RV_AARCH64(SP, sp), RV_AARCH64(PC, pc),\n  // Mask out the single-step flag from the pstate. During replay, we may\n  // single-step to an execution point, which could set the single-step bit\n  // when it wasn't set during record.\n  //\n  // In Apple Air M2 SPSR bit 11 seems to be sometimes set leading to record/replay register\n  // comparison errors. This seems to be a unused/undocumented bit in SPSR as per aarch64\n  // documentation anyways so ignore it.\n  RV_AARCH64_WITH_MASK(CPSR, pstate, 0xffffffffLL & ~AARCH64_DBG_SPSR_SS & ~AARCH64_DBG_SPSR_11, 4),\n};\n\n#undef RV_X64\n#undef RV_X86\n#undef RV_AARCH64\n#undef RV_X64_WITH_MASK\n#undef RV_X86_WITH_MASK\n#undef RV_AARCH64_WITH_MASK\n#undef RV_ARCH\n\n// 32-bit format, 64-bit format for all of these.\n// format_index in RegisterPrinting depends on the ordering here.\nstatic const char* hex_format_leading_0x[] = { \"0x%\" PRIx32, \"0x%\" PRIx64 };\n// static const char* decimal_format[] = { \"%\" PRId32, \"%\" PRId64 };\n\ntemplate <size_t nbytes> struct RegisterPrinting;\n\ntemplate <> struct RegisterPrinting<4> {\n  typedef uint32_t type;\n  static const size_t format_index = 0;\n};\n\ntemplate <> struct RegisterPrinting<8> {\n  typedef uint64_t type;\n  static const size_t format_index = 1;\n};\n\ntemplate <size_t nbytes>\nvoid print_single_register(FILE* f, const char* name, const void* register_ptr,\n                           const char* formats[]) {\n  typename RegisterPrinting<nbytes>::type val;\n  memcpy(&val, register_ptr, nbytes);\n  if (name) {\n    fprintf(f, \"%s:\", name);\n  } else {\n    fprintf(f, \" \");\n  }\n  fprintf(f, formats[RegisterPrinting<nbytes>::format_index], val);\n}\n\ntemplate <typename Arch>\nvoid Registers::print_register_file_arch(FILE* f, const char* formats[]) const {\n  fprintf(f, \"Printing register file:\\n\");\n  const void* user_regs = &u;\n  for (auto& rv : RegisterInfo<Arch>::registers) {\n    if (rv.nbytes == 0) {\n      continue;\n    }\n    switch (rv.nbytes) {\n      case 8:\n        print_single_register<8>(f, rv.name, rv.pointer_into(user_regs),\n                                 formats);\n        break;\n      case 4:\n        print_single_register<4>(f, rv.name, rv.pointer_into(user_regs),\n                                 formats);\n        break;\n      default:\n        DEBUG_ASSERT(0 && \"bad register size\");\n    }\n    fprintf(f, \"\\n\");\n  }\n  fprintf(f, \"\\n\");\n}\n\nvoid Registers::print_register_file(FILE* f) const {\n  RR_ARCH_FUNCTION(print_register_file_arch, arch(), f, hex_format_leading_0x);\n}\n\ntemplate <typename Arch>\nvoid Registers::print_register_file_for_trace_arch(\n    FILE* f, TraceStyle style, const char* formats[]) const {\n  const void* user_regs = &u;\n  bool first = true;\n  for (auto& rv : RegisterInfo<Arch>::registers) {\n    if (rv.nbytes == 0) {\n      continue;\n    }\n\n    if (!first) {\n      fputc(' ', f);\n    }\n    first = false;\n    const char* name = (style == Annotated ? rv.name : nullptr);\n\n    switch (rv.nbytes) {\n      case 8:\n        print_single_register<8>(f, name, rv.pointer_into(user_regs), formats);\n        break;\n      case 4:\n        print_single_register<4>(f, name, rv.pointer_into(user_regs), formats);\n        break;\n      default:\n        DEBUG_ASSERT(0 && \"bad register size\");\n    }\n  }\n}\n\nvoid Registers::print_register_file_compact(FILE* f) const {\n  RR_ARCH_FUNCTION(print_register_file_for_trace_arch, arch(), f, Annotated,\n                   hex_format_leading_0x);\n}\n\nvoid Registers::print_register_file_for_trace_raw(FILE* f) const {\n  fprintf(f, \" %d %d %d %d %d %d %d\"\n             \" %d %d %d %d\",\n          u.x86regs.eax, u.x86regs.ebx, u.x86regs.ecx, u.x86regs.edx,\n          u.x86regs.esi, u.x86regs.edi, u.x86regs.ebp, u.x86regs.orig_eax,\n          u.x86regs.esp, u.x86regs.eip, u.x86regs.eflags);\n}\n\nstd::ostream& operator<<(std::ostream& stream, const Registers::Comparison& c) {\n  if (c.store_mismatches) {\n    bool first = true;\n    for (const Registers::Mismatch& mismatch : c.mismatches) {\n      if (first) {\n        first = false;\n      } else {\n        stream << \", \";\n      }\n      stream << mismatch.register_name << \" \" << mismatch.val1 << \" != \" << mismatch.val2;\n    }\n  } else {\n    stream << c.mismatch_count << \" register mismatches\";\n  }\n  return stream;\n}\n\nvoid Registers::Comparison::add_mismatch(const char* reg_name, uint64_t val1, uint64_t val2) {\n  ++mismatch_count;\n  if (store_mismatches) {\n    char buf1[40];\n    sprintf(buf1, \"%p\", reinterpret_cast<void*>(val1));\n    char buf2[40];\n    sprintf(buf2, \"%p\", reinterpret_cast<void*>(val2));\n    mismatches.push_back({reg_name, buf1, buf2});\n  }\n}\n\ntemplate <typename Arch>\nvoid Registers::compare_registers_core(const Registers& reg1,\n                                       const Registers& reg2, Comparison& result) {\n  for (auto& rv : RegisterInfo<Arch>::registers) {\n    if (rv.nbytes == 0) {\n      continue;\n    }\n\n    // Disregard registers that will trivially compare equal.\n    if (rv.comparison_mask == 0) {\n      continue;\n    }\n\n    // XXX correct but oddly displayed for big-endian processors.\n    uint64_t val1 = 0, val2 = 0;\n    memcpy(&val1, rv.pointer_into(&reg1.u), rv.nbytes);\n    memcpy(&val2, rv.pointer_into(&reg2.u), rv.nbytes);\n\n    if ((val1 ^ val2) & rv.comparison_mask) {\n      result.add_mismatch(rv.name, val1, val2);\n    }\n  }\n}\n\n// A handy macro for compare_registers_arch specializations.\n#define REGCMP(user_regs, _reg, result)                                    \\\n  do {                                                                     \\\n    if (reg1.user_regs._reg != reg2.user_regs._reg) {                      \\\n      result.add_mismatch(#_reg, reg1.user_regs._reg, reg2.user_regs._reg);\\\n    }                                                                      \\\n  } while (0)\n#define X86_REGCMP(_reg, result) REGCMP(u.x86regs, _reg, result)\n#define X64_REGCMP(_reg, result) REGCMP(u.x64regs, _reg, result)\n\n// A wrapper around compare_registers_core so registers requiring special\n// processing can be handled via template specialization.\ntemplate <typename Arch>\n/* static */ void Registers::compare_registers_arch(\n    const Registers& reg1, const Registers& reg2, Comparison& result) {\n  // Default behavior.\n  return compare_registers_core<Arch>(reg1, reg2, result);\n}\n\ntemplate <>\n/* static */ void Registers::compare_registers_arch<rr::X86Arch>(\n    const Registers& reg1, const Registers& reg2, Comparison& result) {\n  compare_registers_core<rr::X86Arch>(reg1, reg2, result);\n  /* When the kernel is entered via an interrupt, orig_rax is set to -IRQ.\n     We observe negative orig_eax values at SCHED events and signals and other\n     timer interrupts. These values are only really meaningful to compare when\n     they reflect original syscall numbers, in which case both will be positive.\n  */\n  if (reg1.u.x86regs.orig_eax >= 0 && reg2.u.x86regs.orig_eax >= 0) {\n    X86_REGCMP(orig_eax, result);\n  }\n}\n\ntemplate <>\n/* static */ void Registers::compare_registers_arch<rr::X64Arch>(\n    const Registers& reg1, const Registers& reg2, Comparison& result) {\n  compare_registers_core<rr::X64Arch>(reg1, reg2, result);\n  // See comment in the x86 case\n  if ((intptr_t)reg1.u.x64regs.orig_rax >= 0 &&\n      (intptr_t)reg2.u.x64regs.orig_rax >= 0) {\n    X64_REGCMP(orig_rax, result);\n  }\n}\n\nvoid Registers::compare_internal(const Registers& other,\n                                 Comparison& result) const {\n  DEBUG_ASSERT(arch() == other.arch());\n  RR_ARCH_FUNCTION(compare_registers_arch, arch(), *this, other, result);\n}\n\ntemplate <typename Arch>\nsize_t Registers::read_register_arch(uint8_t* buf, GdbServerRegister regno,\n                                     bool* defined) const {\n  if (regno >= array_length(RegisterInfo<Arch>::registers)) {\n    *defined = false;\n    return 0;\n  }\n\n  RegisterValue& rv = RegisterInfo<Arch>::registers[regno];\n  if (rv.nbytes == 0) {\n    *defined = false;\n  } else {\n    *defined = true;\n    memcpy(buf, rv.pointer_into(&u), rv.nbytes);\n  }\n\n  return rv.nbytes;\n}\n\nsize_t Registers::read_register(uint8_t* buf, GdbServerRegister regno,\n                                bool* defined) const {\n  RR_ARCH_FUNCTION(read_register_arch, arch(), buf, regno, defined);\n}\n\ntemplate <typename Arch>\nsize_t Registers::read_register_by_user_offset_arch(uint8_t* buf,\n                                                    uintptr_t offset,\n                                                    bool* defined) const {\n  for (size_t regno = 0; regno < RegisterInfo<Arch>::num_registers; ++regno) {\n    RegisterValue& rv = RegisterInfo<Arch>::registers[regno];\n    if (rv.offset == offset) {\n      return read_register_arch<Arch>(buf, GdbServerRegister(regno), defined);\n    }\n  }\n\n  *defined = false;\n  return 0;\n}\n\nsize_t Registers::read_register_by_user_offset(uint8_t* buf, uintptr_t offset,\n                                               bool* defined) const {\n  RR_ARCH_FUNCTION(read_register_by_user_offset_arch, arch(), buf, offset,\n                   defined);\n}\n\ntemplate <typename Arch>\nbool Registers::write_register_arch(GdbServerRegister regno, const void* value,\n                                    size_t value_size) {\n  RegisterValue& rv = RegisterInfo<Arch>::registers[regno];\n\n  if (rv.nbytes == 0) {\n    // TODO: can we get away with not writing these?\n    if (RegisterInfo<Arch>::ignore_undefined_register(regno)) {\n      return true;\n    }\n    return false;\n  } else {\n    DEBUG_ASSERT(value_size == rv.nbytes);\n    memcpy(rv.pointer_into(&u), value, value_size);\n    return true;\n  }\n}\n\nbool Registers::write_register(GdbServerRegister regno, const void* value,\n                               size_t value_size) {\n  RR_ARCH_FUNCTION(write_register_arch, arch(), regno, value, value_size);\n}\n\ntemplate <typename Arch>\nvoid Registers::write_register_by_user_offset_arch(uintptr_t offset,\n                                                   uintptr_t value) {\n  for (size_t regno = 0; regno < RegisterInfo<Arch>::num_registers; ++regno) {\n    RegisterValue& rv = RegisterInfo<Arch>::registers[regno];\n    if (rv.offset == offset) {\n      DEBUG_ASSERT(rv.nbytes <= sizeof(value));\n      memcpy(rv.pointer_into(&u), &value, rv.nbytes);\n      return;\n    }\n  }\n}\n\nvoid Registers::write_register_by_user_offset(uintptr_t offset,\n                                              uintptr_t value) {\n  RR_ARCH_FUNCTION(write_register_by_user_offset_arch, arch(), offset, value);\n}\n\n// In theory it doesn't matter how 32-bit register values are sign extended\n// to 64 bits for PTRACE_SETREGS. However:\n// -- When setting up a signal handler frame, the kernel does some arithmetic\n// on the 64-bit SP value and validates that the result points to writeable\n// memory. This validation fails if SP has been sign-extended to point\n// outside the 32-bit address space.\n// -- Some kernels (e.g. 4.3.3-301.fc23.x86_64) with commit\n// c5c46f59e4e7c1ab244b8d38f2b61d317df90bba have a bug where if you clear\n// the upper 32 bits of %rax while in the kernel, syscalls may fail to\n// restart. So sign-extension is necessary for %eax in this case. We may as\n// well sign-extend %eax in all cases.\n\ntypedef void (*NarrowConversion)(int32_t& r32, uint64_t& r64);\ntemplate <NarrowConversion narrow, NarrowConversion narrow_signed>\nvoid convert_x86(X86Arch::user_regs_struct& x86,\n                 X64Arch::user_regs_struct& x64) {\n  narrow_signed(x86.eax, x64.rax);\n  narrow(x86.ebx, x64.rbx);\n  narrow(x86.ecx, x64.rcx);\n  narrow(x86.edx, x64.rdx);\n  narrow(x86.esi, x64.rsi);\n  narrow(x86.edi, x64.rdi);\n  narrow(x86.esp, x64.rsp);\n  narrow(x86.ebp, x64.rbp);\n  narrow(x86.eip, x64.rip);\n  narrow(x86.orig_eax, x64.orig_rax);\n  narrow(x86.eflags, x64.eflags);\n  narrow(x86.xcs, x64.cs);\n  narrow(x86.xds, x64.ds);\n  narrow(x86.xes, x64.es);\n  narrow(x86.xfs, x64.fs);\n  narrow(x86.xgs, x64.gs);\n  narrow(x86.xss, x64.ss);\n}\n\nvoid to_x86_narrow(int32_t& r32, uint64_t& r64) { r32 = r64; }\nvoid from_x86_narrow(int32_t& r32, uint64_t& r64) { r64 = (uint32_t)r32; }\nvoid from_x86_narrow_signed(int32_t& r32, uint64_t& r64) { r64 = (int64_t)r32; }\n\nvoid Registers::set_from_ptrace(const NativeArch::user_regs_struct& ptrace_regs) {\n  if (arch() == NativeArch::arch()) {\n    memcpy(&u, &ptrace_regs, sizeof(ptrace_regs));\n    return;\n  }\n\n  DEBUG_ASSERT(arch() == x86 && NativeArch::arch() == x86_64);\n  convert_x86<to_x86_narrow, to_x86_narrow>(\n      u.x86regs,\n      *const_cast<X64Arch::user_regs_struct*>(\n        reinterpret_cast<const X64Arch::user_regs_struct*>(&ptrace_regs)));\n}\n\n/**\n * Get a user_regs_struct from these Registers. If the tracee architecture\n * is not rr's native architecture, then it must be a 32-bit tracee with a\n * 64-bit rr. In that case the user_regs_struct is 64-bit and we copy\n * the 32-bit register values from u.x86regs into it.\n */\nNativeArch::user_regs_struct Registers::get_ptrace() const {\n  union {\n    NativeArch::user_regs_struct linux_api;\n    struct X64Arch::user_regs_struct x64arch_api;\n  } result;\n  if (arch() == NativeArch::arch()) {\n    memcpy(&result, &u, sizeof(result));\n    return result.linux_api;\n  }\n\n  DEBUG_ASSERT(arch() == x86 && NativeArch::arch() == x86_64);\n  memset(&result, 0, sizeof(result));\n  convert_x86<from_x86_narrow, from_x86_narrow_signed>(\n      const_cast<Registers*>(this)->u.x86regs, result.x64arch_api);\n  return result.linux_api;\n}\n\niovec Registers::get_ptrace_iovec() {\n  if (arch() == NativeArch::arch()) {\n    iovec iov = { &u, sizeof(NativeArch::user_regs_struct) };\n    return iov;\n  }\n\n  DEBUG_ASSERT(arch() == x86 && NativeArch::arch() == x86_64);\n  iovec iov = { &u.x86regs, sizeof(u.x86regs) };\n  return iov;\n}\n\nRegisters::InternalData Registers::get_ptrace_for_self_arch() const {\n  switch (arch_) {\n    case x86:\n      return { reinterpret_cast<const uint8_t*>(&u.x86regs),\n               sizeof(u.x86regs) };\n    case x86_64:\n      return { reinterpret_cast<const uint8_t*>(&u.x64regs),\n               sizeof(u.x64regs) };\n    case aarch64:\n      return { reinterpret_cast<const uint8_t*>(&u.arm64regs._ptrace),\n               sizeof(u.arm64regs._ptrace) };\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n      return { nullptr, 0 };\n  }\n}\n\nRegisters::InternalData Registers::get_regs_for_trace() const {\n  switch (arch_) {\n    case x86:\n      return { reinterpret_cast<const uint8_t*>(&u.x86regs),\n               sizeof(u.x86regs) };\n    case x86_64:\n      return { reinterpret_cast<const uint8_t*>(&u.x64regs),\n               sizeof(u.x64regs) };\n    case aarch64:\n      return { reinterpret_cast<const uint8_t*>(&u.arm64regs),\n               sizeof(u.arm64regs) };\n    default:\n      DEBUG_ASSERT(0 && \"Unknown arch\");\n      return { nullptr, 0 };\n  }\n}\n\nvector<uint8_t> Registers::get_ptrace_for_arch(SupportedArch arch) const {\n  Registers tmp_regs(arch);\n  tmp_regs.set_from_ptrace(get_ptrace());\n\n  InternalData tmp_data = tmp_regs.get_ptrace_for_self_arch();\n  vector<uint8_t> result;\n  result.resize(tmp_data.size);\n  memcpy(result.data(), tmp_data.data, tmp_data.size);\n  return result;\n}\n\nvoid Registers::set_from_ptrace_for_arch(SupportedArch a, const void* data,\n                                         size_t size) {\n  if (a == NativeArch::arch()) {\n    DEBUG_ASSERT(size == sizeof(NativeArch::user_regs_struct));\n    set_from_ptrace(*static_cast<const NativeArch::user_regs_struct*>(data));\n    return;\n  }\n\n  DEBUG_ASSERT(a == x86 && NativeArch::arch() == x86_64);\n  // We don't support a 32-bit tracee trying to set registers of a 64-bit tracee\n  DEBUG_ASSERT(arch() == x86);\n  DEBUG_ASSERT(size == sizeof(u.x86regs));\n  memcpy(&u.x86regs, data, sizeof(u.x86regs));\n}\n\nvoid Registers::set_from_trace(SupportedArch a, const void* data,\n                               size_t size) {\n  if (is_x86ish(a)) {\n    return set_from_ptrace_for_arch(a, data, size);\n  }\n\n  DEBUG_ASSERT(a == aarch64);\n  DEBUG_ASSERT(size == sizeof(u.arm64regs));\n  memcpy(&u.arm64regs, data, sizeof(u.arm64regs));\n}\n\nbool Registers::aarch64_singlestep_flag() const {\n  switch (arch()) {\n    case aarch64:\n      return pstate() & AARCH64_DBG_SPSR_SS;\n    default:\n      DEBUG_ASSERT(0 && \"X86 only code path\");\n      return false;\n  }\n}\n\nvoid Registers::set_aarch64_singlestep_flag() {\n  switch (arch()) {\n    case aarch64:\n      return set_pstate(pstate() | AARCH64_DBG_SPSR_SS);\n    default:\n      DEBUG_ASSERT(0 && \"AArch64 only code path\");\n      return;\n  }\n}\n\nbool Registers::x86_singlestep_flag() const {\n  switch (arch()) {\n    case x86:\n    case x86_64:\n      return flags() & X86_TF_FLAG;\n    default:\n      DEBUG_ASSERT(0 && \"X86 only code path\");\n      return false;\n  }\n}\n\nvoid Registers::clear_x86_singlestep_flag() {\n  switch (arch()) {\n    case x86:\n    case x86_64:\n      set_flags(flags() & ~X86_TF_FLAG);\n      return;\n    default:\n      DEBUG_ASSERT(0 && \"X86 only code path\");\n      break;\n  }\n}\n\nbool Registers::syscall_failed() const {\n  auto result = syscall_result_signed();\n  return -4096 < result && result < 0;\n}\n\nbool Registers::syscall_may_restart() const {\n  switch (-syscall_result_signed()) {\n    case ERESTART_RESTARTBLOCK:\n    case ERESTARTNOINTR:\n    case ERESTARTNOHAND:\n    case ERESTARTSYS:\n      return true;\n    default:\n      return false;\n  }\n}\n\nostream& operator<<(ostream& stream, const Registers& r) {\n  stream << \"{ ip:\" << HEX(r.ip().register_value()) << \" args:(\" << HEX(r.arg1()) << \",\" << HEX(r.arg2()) << \",\"\n         << HEX(r.arg3()) << \",\" << HEX(r.arg4()) << \",\" << HEX(r.arg5()) << \",\"\n         << r.arg6() << \") orig_syscall: \" << r.original_syscallno()\n         << \" syscallno: \" << r.syscallno();\n  if (r.arch() == aarch64) {\n    stream << \" orig_arg1: \" << HEX(r.orig_arg1());\n  }\n  stream << \" }\";\n  return stream;\n}\n\nvoid Registers::emulate_syscall_entry() {\n  set_original_syscallno(syscallno());\n  set_orig_arg1(arg1());\n  /**\n   * The aarch64 kernel has a quirk where if the syscallno is -1 (and only -1),\n   * it will apply the -ENOSYS result before any ptrace entry stop.\n   * On x86, this happens unconditionally for every syscall, but there the\n   * result isn't shared with arg1, and we usually don't care because we have\n   * access to original_syscallno.\n   */\n  if (is_x86ish(arch()) || (arch() == aarch64 && syscallno() == -1)) {\n    set_syscall_result(-ENOSYS);\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Registers.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REGISTERS_H_\n#define RR_REGISTERS_H_\n\n#include <errno.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/user.h>\n\n#include \"GdbServerRegister.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"remote_code_ptr.h\"\n#include \"remote_ptr.h\"\n\nstruct iovec;\n\nnamespace rr {\n\nclass ReplayTask;\n\nconst uintptr_t X86_RESERVED_FLAG = 1 << 1;\nconst uintptr_t X86_ZF_FLAG = 1 << 6;\nconst uintptr_t X86_TF_FLAG = 1 << 8;\nconst uintptr_t X86_IF_FLAG = 1 << 9;\nconst uintptr_t X86_DF_FLAG = 1 << 10;\nconst uintptr_t X86_RF_FLAG = 1 << 16;\nconst uintptr_t X86_ID_FLAG = 1 << 21;\n\nconst uintptr_t AARCH64_DBG_SPSR_SS = 1 << 21;\nconst uintptr_t AARCH64_DBG_SPSR_11 = 1 << 11;\n\n/**\n * A Registers object contains values for all general-purpose registers.\n * These must include all registers used to pass syscall parameters and return\n * syscall results.\n *\n * When reading register values, be sure to cast the result to the correct\n * type according to the kernel docs. E.g. int values should be cast\n * to int explicitly (or implicitly, by assigning to an int-typed variable),\n * size_t should be cast to size_t, etc. If the type is signed, call the\n * _signed getter. This ensures that when building rr 64-bit we will use the\n * right number of register bits whether the tracee is 32-bit or 64-bit, and\n * get sign-extension right.\n *\n * We have different register sets for different architectures. To ensure a\n * trace can be dumped/processed by an rr build on any platform, we allow\n * Registers to contain registers for any architecture. So we store them\n * in a union of Arch::user_regs_structs for each known Arch.\n */\nclass Registers {\npublic:\n  enum { MAX_SIZE = 32 };\n\n  Registers(SupportedArch a = x86) : arch_(a) {\n    memset(&u, 0, sizeof(u));\n  }\n\n  SupportedArch arch() const { return arch_; }\n\n  void set_arch(SupportedArch a) { arch_ = a; }\n\n  /**\n   * Copy a user_regs_struct into these Registers. If the tracee architecture\n   * is not rr's native architecture, then it must be a 32-bit tracee with a\n   * 64-bit rr. In that case the user_regs_struct is 64-bit and we extract\n   * the 32-bit register values from it into u.x86regs.\n   * It's invalid to call this when the Registers' arch is 64-bit and the\n   * rr build is 32-bit, or when the Registers' arch is completely different\n   * to the rr build (e.g. ARM vs x86).\n   */\n  void set_from_ptrace(const NativeArch::user_regs_struct& ptrace_regs);\n\n  /**\n   * Get a user_regs_struct from these Registers. If the tracee architecture\n   * is not rr's native architecture, then it must be a 32-bit tracee with a\n   * 64-bit rr. In that case the user_regs_struct is 64-bit and we copy\n   * the 32-bit register values from u.x86regs into it.\n   * It's invalid to call this when the Registers' arch is 64-bit and the\n   * rr build is 32-bit, or when the Registers' arch is completely different\n   * to the rr build (e.g. ARM vs x86).\n   */\n  NativeArch::user_regs_struct get_ptrace() const;\n  iovec get_ptrace_iovec();\n\n  /**\n   * Get a user_regs_struct for a particular Arch from these Registers.\n   * It's invalid to call this when 'arch' is 64-bit and the\n   * rr build is 32-bit, or when the Registers' arch is completely different\n   * to the rr build (e.g. ARM vs x86).\n   */\n  std::vector<uint8_t> get_ptrace_for_arch(SupportedArch arch) const;\n  struct InternalData {\n    const uint8_t* data;\n    size_t size;\n  };\n\n  /**\n   * Get the register content to save in the trace.\n   */\n  InternalData get_regs_for_trace() const;\n\n  /**\n   * Equivalent to get_ptrace_for_arch(arch()) but doesn't copy.\n   */\n  InternalData get_ptrace_for_self_arch() const;\n\n  /**\n   * Copy an arch-specific user_regs_struct into these Registers.\n   * It's invalid to call this when 'arch' is 64-bit and the\n   * rr build is 32-bit, or when the Registers' arch is completely different\n   * to the rr build (e.g. ARM vs x86).\n   */\n  void set_from_ptrace_for_arch(SupportedArch arch, const void* data,\n                                size_t size);\n\n  /**\n   * Copy from the arch-specific structure returned in get_regs_for_trace()\n   * back into *this\n   */\n  void set_from_trace(SupportedArch arch, const void* data,\n                      size_t size);\n\n#define ARCH_SWITCH_CASE(rettype, x86case, x64case, arm64case)                 \\\n(([&](void) -> rettype {                                                       \\\n  switch (arch()) {                                                            \\\n    default:                                                                   \\\n      DEBUG_ASSERT(0 && \"unknown architecture\");                               \\\n      RR_FALLTHROUGH; /* Fall through to avoid warnings */                     \\\n    case x86: {                                                                \\\n      x86case;                                                                 \\\n      break;                                                                   \\\n    }                                                                          \\\n    case x86_64: {                                                             \\\n      x64case;                                                                 \\\n      break;                                                                   \\\n    }                                                                          \\\n    case aarch64: {                                                            \\\n      arm64case;                                                               \\\n      break;                                                                   \\\n    }                                                                          \\\n  }                                                                            \\\n})())\n\n#define RR_GET_REG(x86case, x64case, arm64case)                                \\\n  ARCH_SWITCH_CASE(uint64_t,                                                   \\\n    return (uint32_t)u.x86regs.x86case,                                        \\\n    return u.x64regs.x64case,                                                  \\\n    return u.arm64regs.arm64case)\n\n#define RR_GET_REG_SIGNED(x86case, x64case, arm64case)                         \\\n  ARCH_SWITCH_CASE(int64_t,                                                    \\\n    return (int32_t)u.x86regs.x86case,                                         \\\n    return u.x64regs.x64case,                                                  \\\n    return u.arm64regs.arm64case)\n\n#define RR_GET_REG_X86(x86case, x64case)                                       \\\n  ARCH_SWITCH_CASE(uint64_t,                                                   \\\n    return (uint32_t)u.x86regs.x86case,                                        \\\n    return u.x64regs.x64case,                                                  \\\n    DEBUG_ASSERT(0 && \"Hit an x86-only case, but this is not x86\"); return 0)\n\n#define RR_UPDATE_CHECK(loc, value) bool changed = (uintptr_t)loc != (uintptr_t)(value); \\\n  loc = (value); \\\n  return changed;\n#define RR_SET_REG(x86case, x64case, arm64case, value)                         \\\n  ARCH_SWITCH_CASE(bool,                                                       \\\n    RR_UPDATE_CHECK(u.x86regs.x86case, value),                                 \\\n    RR_UPDATE_CHECK(u.x64regs.x64case, value),                                 \\\n    RR_UPDATE_CHECK(u.arm64regs.arm64case, value))\n\n#define RR_SET_REG_X86(x86case, x64case, value)                                \\\n  ARCH_SWITCH_CASE(bool,                                                       \\\n    RR_UPDATE_CHECK(u.x86regs.x86case, value),                                 \\\n    RR_UPDATE_CHECK(u.x64regs.x64case, value),                                 \\\n    DEBUG_ASSERT(0 && \"Hit an x86-only case, but this is not x86\"); return false)\n\n  remote_code_ptr ip() const { return RR_GET_REG(eip, rip, pc); }\n  bool set_ip(remote_code_ptr addr) {\n    return RR_SET_REG(eip, rip, pc, addr.register_value());\n  }\n  remote_ptr<void> sp() const { return RR_GET_REG(esp, rsp, sp); }\n  bool set_sp(remote_ptr<void> addr) { return RR_SET_REG(esp, rsp, sp, addr.as_int()); }\n\n  // Access the registers holding system-call numbers, results, and\n  // parameters.\n\n  intptr_t syscallno() const { return (int)RR_GET_REG(eax, rax, x[8]); }\n  bool set_syscallno(intptr_t syscallno) { return RR_SET_REG(eax, rax, x[8], syscallno); }\n\n  /**\n   * This pseudo-register holds the system-call number when we get ptrace\n   * enter-system-call and exit-system-call events. Setting it changes\n   * the system-call executed when resuming after an enter-system-call\n   * event.\n   */\n  intptr_t original_syscallno() const {\n    return RR_GET_REG_SIGNED(orig_eax, orig_rax, orig_syscall);\n  }\n  bool set_original_syscallno(intptr_t syscallno) {\n    return RR_SET_REG(orig_eax, orig_rax, orig_syscall, syscallno);\n  }\n\n  #define SYSCALL_REGISTER(name, x86case, x64case, arm64case)                  \\\n  uintptr_t name() const { return RR_GET_REG(x86case, x64case, arm64case); }   \\\n  intptr_t name ## _signed() const {                                           \\\n    return RR_GET_REG_SIGNED(x86case, x64case, arm64case);                     \\\n  }                                                                            \\\n  bool set_ ## name(uintptr_t value) {                                         \\\n    return RR_SET_REG(x86case, x64case, arm64case, value);                     \\\n  }                                                                            \\\n  template <typename T> bool set_ ## name(remote_ptr<T> value) {               \\\n    return RR_SET_REG(x86case, x64case, arm64case, value.as_int());            \\\n  }\n\n  SYSCALL_REGISTER(syscall_result, eax, rax, x[0]);\n  SYSCALL_REGISTER(orig_arg1, ebx, rdi, orig_x0)\n  SYSCALL_REGISTER(arg1, ebx, rdi, x[0])\n  SYSCALL_REGISTER(arg2, ecx, rsi, x[1])\n  SYSCALL_REGISTER(arg3, edx, rdx, x[2])\n  SYSCALL_REGISTER(arg4, esi, r10, x[3])\n  SYSCALL_REGISTER(arg5, edi, r8, x[4])\n  SYSCALL_REGISTER(arg6, ebp, r9, x[5])\n\n  uintptr_t arg(int index) const {\n    switch (index) {\n      case 1:\n        return arg1();\n      case 2:\n        return arg2();\n      case 3:\n        return arg3();\n      case 4:\n        return arg4();\n      case 5:\n        return arg5();\n      case 6:\n        return arg6();\n      default:\n        DEBUG_ASSERT(0 && \"Argument index out of range\");\n        return 0;\n    }\n  }\n\n  /**\n   * Set the register containing syscall argument |Index| to\n   * |value|.\n   */\n  template <int Index> bool set_arg(std::nullptr_t) { return set_arg(Index, 0); }\n  template <int Index, typename T> bool set_arg(remote_ptr<T> value) {\n    return set_arg(Index, value.as_int());\n  }\n  template <int Index, typename T> bool set_arg(T value) {\n    return set_arg(Index, uintptr_t(value));\n  }\n\n  bool set_arg(int index, uintptr_t value) {\n    switch (index) {\n      case 1:\n        return set_arg1(value);\n      case 2:\n        return set_arg2(value);\n      case 3:\n        return set_arg3(value);\n      case 4:\n        return set_arg4(value);\n      case 5:\n        return set_arg5(value);\n      case 6:\n        return set_arg6(value);\n      default:\n        DEBUG_ASSERT(0 && \"Argument index out of range\");\n        return false;\n    }\n  }\n\n  bool set_orig_arg(int index, uintptr_t value) {\n    switch (index) {\n      case 1:\n        return set_orig_arg1(value);\n      case 2:\n        return set_arg2(value);\n      case 3:\n        return set_arg3(value);\n      case 4:\n        return set_arg4(value);\n      case 5:\n        return set_arg5(value);\n      case 6:\n        return set_arg6(value);\n      default:\n        DEBUG_ASSERT(0 && \"Argument index out of range\");\n        return false;\n    }\n  }\n\n  /**\n   * Returns true if syscall_result() indicates failure.\n   */\n  bool syscall_failed() const;\n\n  /**\n   * Returns true if syscall_result() indicates a syscall restart.\n   */\n  bool syscall_may_restart() const;\n\n  // Some X86-specific stuff follows. Use of these accessors should be guarded\n  // by an architecture test.\n  /**\n   * Set the output registers of the |rdtsc| instruction.\n   */\n  void set_rdtsc_output(uint64_t value) {\n    RR_SET_REG_X86(eax, rax, value & 0xffffffff);\n    RR_SET_REG_X86(edx, rdx, value >> 32);\n  }\n\n  void set_cpuid_output(uint32_t eax, uint32_t ebx, uint32_t ecx,\n                        uint32_t edx) {\n    RR_SET_REG_X86(eax, rax, eax);\n    RR_SET_REG_X86(ebx, rbx, ebx);\n    RR_SET_REG_X86(ecx, rcx, ecx);\n    RR_SET_REG_X86(edx, rdx, edx);\n  }\n\n  bool set_r8(uintptr_t value) {\n    DEBUG_ASSERT(arch() == x86_64);\n    RR_UPDATE_CHECK(u.x64regs.r8, value);\n  }\n\n  bool set_r9(uintptr_t value) {\n    DEBUG_ASSERT(arch() == x86_64);\n    RR_UPDATE_CHECK(u.x64regs.r9, value);\n  }\n\n  bool set_r10(uintptr_t value) {\n    DEBUG_ASSERT(arch() == x86_64);\n    RR_UPDATE_CHECK(u.x64regs.r10, value);\n  }\n\n  bool set_r11(uintptr_t value) {\n    DEBUG_ASSERT(arch() == x86_64);\n    RR_UPDATE_CHECK(u.x64regs.r11, value);\n  }\n\n  uintptr_t di() const { return RR_GET_REG_X86(edi, rdi); }\n  bool set_di(uintptr_t value) { return RR_SET_REG_X86(edi, rdi, value); }\n\n  uintptr_t si() const { return RR_GET_REG_X86(esi, rsi); }\n  bool set_si(uintptr_t value) { return RR_SET_REG_X86(esi, rsi, value); }\n\n  uintptr_t cx() const { return RR_GET_REG_X86(ecx, rcx); }\n  bool set_cx(uintptr_t value) { return RR_SET_REG_X86(ecx, rcx, value); }\n\n  uintptr_t ax() const { return RR_GET_REG_X86(eax, rax); }\n  bool set_ax(uintptr_t value) { return RR_SET_REG_X86(eax, rax, value); }\n\n  uintptr_t dx() const { return RR_GET_REG_X86(edx, rdx); }\n  bool set_dx(uintptr_t value) { return RR_SET_REG_X86(edx, rdx, value); }\n\n  uintptr_t bp() const { return RR_GET_REG_X86(ebp, rbp); }\n\n  uintptr_t flags() const { return RR_GET_REG_X86(eflags, eflags); };\n  bool set_flags(uintptr_t value) { return RR_SET_REG_X86(eflags, eflags, value); }\n  bool zf_flag() const { return flags() & X86_ZF_FLAG; }\n  bool df_flag() const { return flags() & X86_DF_FLAG; }\n\n  uintptr_t fs_base() const {\n    DEBUG_ASSERT(arch() == x86_64);\n    return u.x64regs.fs_base;\n  }\n  uintptr_t gs_base() const {\n    DEBUG_ASSERT(arch() == x86_64);\n    return u.x64regs.gs_base;\n  }\n\n  void set_fs_base(uintptr_t fs_base) {\n    DEBUG_ASSERT(arch() == x86_64);\n    u.x64regs.fs_base = fs_base;\n  }\n  void set_gs_base(uintptr_t gs_base) {\n    DEBUG_ASSERT(arch() == x86_64);\n    u.x64regs.gs_base = gs_base;\n  }\n\n  uint64_t cs() const { return RR_GET_REG_X86(xcs, cs); }\n  uint64_t ss() const { return RR_GET_REG_X86(xss, ss); }\n  uint64_t ds() const { return RR_GET_REG_X86(xds, ds); }\n  uint64_t es() const { return RR_GET_REG_X86(xes, es); }\n  uint64_t fs() const { return RR_GET_REG_X86(xfs, fs); }\n  uint64_t gs() const { return RR_GET_REG_X86(xgs, gs); }\n\n  // End of X86-specific stuff\n  // Begin aarch64 specific accessors\n  uintptr_t pstate() const {\n    DEBUG_ASSERT(arch() == aarch64);\n    return u.arm64regs.pstate;\n  }\n\n  void set_pstate(uintptr_t pstate) {\n    DEBUG_ASSERT(arch() == aarch64);\n    u.arm64regs.pstate = pstate;\n  }\n\n  void set_x(unsigned regno, uintptr_t val) {\n    DEBUG_ASSERT(arch() == aarch64 && regno < 31);\n    u.arm64regs.x[regno] = val;\n  }\n\n  uintptr_t x(unsigned regno) const {\n    DEBUG_ASSERT(arch() == aarch64 && regno < 31);\n    return u.arm64regs.x[regno];\n  }\n  // End of aarch64 specific accessors\n\n  /**\n   * Modify the processor's single step flag. On x86 this is the TF flag in the\n   * eflags register.\n   */\n  bool x86_singlestep_flag() const;\n  void clear_x86_singlestep_flag();\n\n  /**\n   * Aarch64 has two flags that control single stepping. An EL1 one that\n   * enables singlestep exceptions and an EL0 one in pstate (SPSR_SS). The EL1 bit\n   * is controlled by PTRACE_SINGLESTEP (it gets turned on upon the first\n   * PTRACE_(SYSEMU_)SINGLESTEP and turned off on any other ptrace resume).\n   * The EL0 bit controls whether an exception is taken *before* execution\n   * of the next instruction (an exception is taken when the bit is *clear*).\n   * The hardware clears this bit whenever an instruction completes. Thus, to\n   * ensure that a single step actually happens, regardless of how we got to\n   * this step, we must both using PTRACE_SINGLESTEP and *set* the SPSR_SS bit.\n   * Otherwise, if we got to this stop via single step, the SPSR_SS bit will\n   * likely already be clear, and we'd take a single step exception without\n   * ever having executed any userspace instructions whatsoever.\n   */\n  bool aarch64_singlestep_flag() const;\n  void set_aarch64_singlestep_flag();\n\n  void print_register_file(FILE* f) const;\n  void print_register_file_compact(FILE* f) const;\n  void print_register_file_for_trace_raw(FILE* f) const;\n\n  struct Mismatch {\n    std::string register_name;\n    std::string val1;\n    std::string val2;\n  };\n  struct Comparison {\n    std::vector<Mismatch> mismatches;\n    int mismatch_count = 0;\n    bool store_mismatches = true;\n\n    void add_mismatch(const char* reg_name, uint64_t val1, uint64_t val2);\n  };\n\n  // This is cheap when there are no mismatches. It can be a bit expensive\n  // (allocation) when mismatches are expected; call matches() instead in\n  // that case, which doesn't allocate.\n  Comparison compare_with(const Registers& other) const {\n    Comparison result;\n    compare_internal(other, result);\n    return result;\n  }\n\n  bool matches(const Registers& other) const {\n    Comparison result;\n    result.store_mismatches = false;\n    compare_internal(other, result);\n    return !result.mismatch_count;\n  }\n\n  // TODO: refactor me to use the GdbServerRegisterValue helper from\n  // GdbServerConnection.h.\n\n  /**\n   * Write the value for register |regno| into |buf|, which should\n   * be large enough to hold any register supported by the target.\n   * Return the size of the register in bytes and set |defined| to\n   * indicate whether a useful value has been written to |buf|.\n   */\n  size_t read_register(uint8_t* buf, GdbServerRegister regno, bool* defined) const;\n\n  /**\n   * Write the value for register |offset| into |buf|, which should\n   * be large enough to hold any register supported by the target.\n   * Return the size of the register in bytes and set |defined| to\n   * indicate whether a useful value has been written to |buf|.\n   * |offset| is the offset of the register within a user_regs_struct.\n   */\n  size_t read_register_by_user_offset(uint8_t* buf, uintptr_t offset,\n                                      bool* defined) const;\n\n  /**\n   * Update the register named |reg_name| to |value| with\n   * |value_size| number of bytes.\n   */\n  bool write_register(GdbServerRegister reg_name, const void* value,\n                      size_t value_size);\n\n  /**\n   * Update the register at user offset |offset| to |value|, taking the low\n   * bytes if necessary.\n   */\n  void write_register_by_user_offset(uintptr_t offset, uintptr_t value);\n\n\n  bool operator==(const Registers &other) const {\n    if (arch() != other.arch()) {\n      return false;\n    }\n    switch (arch()) {\n      case x86:\n        return memcmp(&u.x86regs, &other.u.x86regs, sizeof(u.x86regs)) == 0;\n      case x86_64:\n        return memcmp(&u.x64regs, &other.u.x64regs, sizeof(u.x64regs)) == 0;\n      case aarch64:\n        return memcmp(&u.arm64regs, &other.u.arm64regs, sizeof(u.arm64regs)) == 0;\n      default:\n        DEBUG_ASSERT(0 && \"Unknown architecture\");\n        return false;\n    }\n  }\n\n  bool operator!=(const Registers &other) const {\n    return !(*this == other);\n  }\n\n  void emulate_syscall_entry();\n\nprivate:\n  template <typename Arch>\n  void print_register_file_arch(FILE* f, const char* formats[]) const;\n\n  enum TraceStyle {\n    Annotated,\n    Raw,\n  };\n\n  template <typename Arch>\n  void print_register_file_for_trace_arch(FILE* f, TraceStyle style,\n                                          const char* formats[]) const;\n\n  template <typename Arch>\n  static void compare_registers_core(const Registers& reg1,\n                                     const Registers& reg2,\n                                     Comparison& result);\n\n  template <typename Arch>\n  static void compare_registers_arch(const Registers& reg1,\n                                     const Registers& reg2,\n                                     Comparison& result);\n\n  void compare_internal(const Registers& other, Comparison& result) const;\n\n  template <typename Arch>\n  size_t read_register_arch(uint8_t* buf, GdbServerRegister regno,\n                            bool* defined) const;\n\n  template <typename Arch>\n  size_t read_register_by_user_offset_arch(uint8_t* buf, uintptr_t offset,\n                                           bool* defined) const;\n\n  template <typename Arch>\n  bool write_register_arch(GdbServerRegister regno, const void* value,\n                           size_t value_size);\n\n  template <typename Arch>\n  void write_register_by_user_offset_arch(uintptr_t offset, uintptr_t value);\n\n  template <typename Arch> size_t total_registers_arch() const;\n\n  SupportedArch arch_;\n  union {\n    rr::X86Arch::user_regs_struct x86regs;\n    rr::X64Arch::user_regs_struct x64regs;\n    struct {\n      // This is the NT_PRSTATUS regset\n      union {\n        rr::ARM64Arch::user_regs_struct _ptrace;\n        // This duplicates the field names of the user_regs_struct and makes\n        // them available as fields of arm64regs for easy access.\n        struct {\n          uint64_t x[31];\n          uint64_t sp;\n          uint64_t pc;\n          uint64_t pstate;\n        };\n      };\n      // This is not exposed through GETREGSET. We track it manually\n      uint64_t orig_x0;\n      // This is the NT_ARM_SYSTEM_CALL regset\n      int orig_syscall;\n    } arm64regs;\n  } u;\n};\n\ntemplate <typename ret, typename callback>\nret with_converted_registers(const Registers& regs, SupportedArch arch,\n                             callback f) {\n  if (regs.arch() != arch) {\n    // If this is a cross architecture syscall, first convert the registers.\n    Registers converted_regs(arch);\n    std::vector<uint8_t> data = regs.get_ptrace_for_arch(arch);\n    converted_regs.set_from_ptrace_for_arch(arch, data.data(), data.size());\n    return f(converted_regs);\n  }\n  return f(regs);\n}\n\nstd::ostream& operator<<(std::ostream& stream, const Registers& r);\n\nstd::ostream& operator<<(std::ostream& stream, const Registers::Comparison& c);\n\n} // namespace rr\n\n#endif /* RR_REGISTERS_H_ */\n"
  },
  {
    "path": "src/ReplayCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ReplayCommand.h\"\n\n#include <sys/prctl.h>\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <limits>\n\n#include \"Command.h\"\n#include \"Flags.h\"\n#include \"GdbServer.h\"\n#include \"ReplaySession.h\"\n#include \"ScopedFd.h\"\n#include \"WaitManager.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"launch_debugger.h\"\n#include \"log.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nReplayCommand ReplayCommand::singleton(\n    \"replay\",\n    \" rr replay [OPTION]... [<trace-dir>] [-- <debugger-options>]\\n\"\n    \"  -a, --autopilot            replay without debugger server\\n\"\n    \"  -f, --onfork=<PID>         start a debug server when <PID> has been\\n\"\n    \"                             fork()d, AND the target event has been\\n\"\n    \"                             reached.\\n\"\n    \"  -g, --goto=<EVENT-NUM>     start a debug server on reaching \"\n    \"<EVENT-NUM>\\n\"\n    \"                             in the trace.  See -M in the general \"\n    \"options.\\n\"\n    \"  -e, --goto-exit            start a debug server at the end of the \"\n    \"recording\\n\"\n    \"                             or the end of the specified process.\\n\"\n    \"  -o, --debugger-option=<OPTION>\\n\"\n    \"                             pass <OPTION> to debugger\\n\"\n    \"  -p, --onprocess=<PID>|<COMMAND>\\n\"\n    \"                             start a debug server when <PID> or \"\n    \"<COMMAND>\\n\"\n    \"                             has been exec()d, AND the target event has \"\n    \"been\\n\"\n    \"                             reached.\\n\"\n    \"  --fullname\\n\"\n    \"  -i=<X>\\n\"\n    \"  --interpreter=<X>          These are passed directly to gdb. They are\\n\"\n    \"                             here for convenience to support 'gdb -i=mi'\\n\"\n    \"                             and 'gdb --fullname' as suggested by GNU \"\n    \"Emacs\\n\"\n    \"  -d, --debugger=<FILE>      use <FILE> as the gdb command\\n\"\n    \"  -q, --no-redirect-output   don't replay writes to stdout/stderr\\n\"\n    \"  -h, --dbghost=<HOST>       listen address for the debug server.\\n\"\n    \"                             default listen address is set to localhost.\\n\"\n    \"  -s, --dbgport=<PORT>       only start a debug server on <PORT>,\\n\"\n    \"                             don't automatically launch the debugger\\n\"\n    \"                             client; set PORT to 0 to automatically\\n\"\n    \"                             probe a port\\n\"\n    \"  -k, --keep-listening       keep listening after detaching when using \\n\"\n    \"                             --dbgport (-s) mode\\n\"\n    \"  -t, --trace=<EVENT>        singlestep instructions and dump register\\n\"\n    \"                             states when replaying towards <EVENT> or\\n\"\n    \"                             later\\n\"\n    \"  -u, --cpu-unbound          allow replay to run on any CPU. Default is\\n\"\n    \"                             to run on the CPU stored in the trace.\\n\"\n    \"                             Note that this may diverge from the recording\\n\"\n    \"                             in some cases.\\n\"\n    \"  --intel-pt-start-checking-event   verify control flow using Intel PT\\n\"\n    \"                             (used for debugging rr)\\n\"\n    \"  -x, --gdb-x=<FILE>         execute gdb commands from <FILE>\\n\"\n    \"  --retry-transient-errors   If we detect a transient error that might resolve\\n\"\n    \"                             by retrying, retry it\\n\"\n    \"  --stats=<N>                display brief stats every N steps (eg 10000).\\n\"\n    \"  --serve-files              Serve all files from the trace rather than\\n\"\n    \"                             assuming they exist on disk. Debugging will\\n\"\n    \"                             be slower, but be able to tolerate missing files\\n\"\n    \"  --tty <file>               Redirect tracee replay output to <file>\\n\");\n\nstruct ReplayFlags {\n  // Start a debug server for the task scheduled at the first\n  // event at which reached this event AND target_process has\n  // been \"created\".\n  FrameTime goto_event;\n\n  FrameTime singlestep_to_event;\n\n  pid_t target_process;\n\n  string target_command;\n\n  // We let users specify which process should be \"created\" before\n  // starting a debug session for it.  Problem is, \"process\" in this\n  // context is ambiguous.  It could mean the \"thread group\", which is\n  // created at fork().  Or it could mean the \"address space\", which is\n  // created at exec() (after the fork).\n  //\n  // We force choosers to specify which they mean.\n  enum { CREATED_NONE, CREATED_EXEC, CREATED_FORK } process_created_how;\n\n  // Only open a debug socket, don't launch the debugger too.\n  bool dont_launch_debugger;\n\n  // IP port to listen on for debug connections.\n  int dbg_port;\n\n  // IP host to listen on for debug connections.\n  string dbg_host;\n\n  // Whether to keep listening with a new server after the existing server\n  // detaches\n  bool keep_listening;\n\n  // Pass these options to gdb\n  vector<string> gdb_options;\n\n  // Specify a custom gdb binary with -d\n  string gdb_binary_file_path;\n\n  /* When true, echo tracee stdout/stderr writes to console. */\n  bool redirect;\n\n  /* When true, do not bind to the CPU stored in the trace file. */\n  bool cpu_unbound;\n\n  // When true make all private mappings shared with the tracee by default\n  // to test the corresponding code.\n  bool share_private_mappings;\n\n  bool retry_transient_errors;\n\n  // When nonzero, display statistics every N steps.\n  uint32_t dump_interval;\n\n  // When set, serve files from the tracer rather than asking GDB\n  // to get them from the filesystem\n  bool serve_files;\n\n  string tty;\n\n  FrameTime intel_pt_start_checking_event;\n\n  ReplayFlags()\n      : goto_event(0),\n        singlestep_to_event(0),\n        target_process(0),\n        process_created_how(CREATED_NONE),\n        dont_launch_debugger(false),\n        dbg_port(-1),\n        keep_listening(false),\n        gdb_binary_file_path(\"gdb\"),\n        redirect(true),\n        cpu_unbound(false),\n        share_private_mappings(false),\n        retry_transient_errors(false),\n        dump_interval(0),\n        serve_files(false),\n        intel_pt_start_checking_event(-1) {}\n};\n\nstatic bool parse_replay_arg(vector<string>& args, ReplayFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = {\n    { 'a', \"autopilot\", NO_PARAMETER },\n    { 'd', \"debugger\", HAS_PARAMETER },\n    { 'e', \"goto-exit\", NO_PARAMETER },\n    { 'k', \"keep-listening\", NO_PARAMETER },\n    { 'f', \"onfork\", HAS_PARAMETER },\n    { 'g', \"goto\", HAS_PARAMETER },\n    { 'i', \"interpreter\", HAS_PARAMETER },\n    { 'o', \"debugger-option\", HAS_PARAMETER },\n    { 'p', \"onprocess\", HAS_PARAMETER },\n    { 'q', \"no-redirect-output\", NO_PARAMETER },\n    { 'h', \"dbghost\", HAS_PARAMETER },\n    { 's', \"dbgport\", HAS_PARAMETER },\n    { 't', \"trace\", HAS_PARAMETER },\n    { 'u', \"cpu-unbound\", NO_PARAMETER },\n    { 'x', \"gdb-x\", HAS_PARAMETER },\n    { 0, \"share-private-mappings\", NO_PARAMETER },\n    { 1, \"fullname\", NO_PARAMETER },\n    { 2, \"stats\", HAS_PARAMETER },\n    { 3, \"serve-files\", NO_PARAMETER },\n    { 4, \"tty\", HAS_PARAMETER },\n    { 5, \"intel-pt-start-checking-event\", HAS_PARAMETER },\n    { 6, \"retry-transient-errors\", NO_PARAMETER }\n  };\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 'a':\n      flags.goto_event = numeric_limits<decltype(flags.goto_event)>::max();\n      flags.dont_launch_debugger = true;\n      break;\n    case 'd':\n      flags.gdb_binary_file_path = opt.value;\n      break;\n    case 'e':\n      flags.goto_event = -1;\n      break;\n    case 'f':\n      if (!opt.verify_valid_int(1, INT32_MAX)) {\n        return false;\n      }\n      flags.target_process = opt.int_value;\n      flags.process_created_how = ReplayFlags::CREATED_FORK;\n      break;\n    case 'g':\n      if (!opt.verify_valid_int(1, UINT32_MAX)) {\n        return false;\n      }\n      flags.goto_event = opt.int_value;\n      break;\n    case 'i':\n      flags.gdb_options.push_back(\"-i\");\n      flags.gdb_options.push_back(opt.value);\n      break;\n    case 'k':\n      flags.keep_listening = true;\n      break;\n    case 'o':\n      flags.gdb_options.push_back(opt.value);\n      break;\n    case 'p':\n      if (opt.int_value > 0) {\n        if (!opt.verify_valid_int(1, INT32_MAX)) {\n          return false;\n        }\n        flags.target_process = opt.int_value;\n      } else {\n        flags.target_command = opt.value;\n      }\n      flags.process_created_how = ReplayFlags::CREATED_EXEC;\n      break;\n    case 'q':\n      flags.redirect = false;\n      break;\n    case 'h':\n      flags.dbg_host = opt.value;\n      flags.dont_launch_debugger = true;\n      break;\n    case 's':\n      if (!opt.verify_valid_int(0, INT32_MAX)) {\n        return false;\n      }\n      flags.dbg_port = opt.int_value;\n      flags.dont_launch_debugger = true;\n      break;\n    case 't':\n      if (!opt.verify_valid_int(1, INT32_MAX)) {\n        return false;\n      }\n      flags.singlestep_to_event = opt.int_value;\n      break;\n    case 'u':\n      flags.cpu_unbound = true;\n      break;\n    case 'x':\n      flags.gdb_options.push_back(\"-x\");\n      flags.gdb_options.push_back(opt.value);\n      break;\n    case 0:\n      flags.share_private_mappings = true;\n      break;\n    case 1:\n      flags.gdb_options.push_back(\"--fullname\");\n      break;\n    case 2:\n      if (!opt.verify_valid_int(1, INT32_MAX)) {\n        return false;\n      }\n      flags.dump_interval = opt.int_value;\n      break;\n    case 3:\n      flags.serve_files = true;\n      break;\n    case 4:\n      flags.tty = opt.value;\n      break;\n    case 5:\n      if (!opt.verify_valid_int(1, INT64_MAX)) {\n        return false;\n      }\n      flags.intel_pt_start_checking_event = opt.int_value;\n      break;\n    case 6:\n      flags.retry_transient_errors = true;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown option\");\n  }\n  return true;\n}\n\nstatic int find_pid_for_command(const string& trace_dir,\n                                const string& command) {\n  TraceReader trace(trace_dir);\n\n  while (true) {\n    TraceTaskEvent e = trace.read_task_event();\n    if (e.type() == TraceTaskEvent::NONE) {\n      return -1;\n    }\n    if (e.type() != TraceTaskEvent::EXEC) {\n      continue;\n    }\n    if (e.cmd_line().empty()) {\n      continue;\n    }\n    auto& cmd = e.cmd_line()[0];\n    if (cmd == command ||\n        (cmd.size() > command.size() &&\n         cmd.substr(cmd.size() - command.size() - 1) == ('/' + command))) {\n      return e.tid();\n    }\n  }\n}\n\nstatic bool pid_exists(const string& trace_dir, pid_t pid) {\n  TraceReader trace(trace_dir);\n\n  while (true) {\n    auto e = trace.read_task_event();\n    if (e.type() == TraceTaskEvent::NONE) {\n      return false;\n    }\n    if (e.tid() == pid) {\n      return true;\n    }\n  }\n}\n\nstatic bool pid_execs(const string& trace_dir, pid_t pid) {\n  TraceReader trace(trace_dir);\n\n  while (true) {\n    auto e = trace.read_task_event();\n    if (e.type() == TraceTaskEvent::NONE) {\n      return false;\n    }\n    if (e.tid() == pid && e.type() == TraceTaskEvent::EXEC) {\n      return true;\n    }\n  }\n}\n\n// The parent process waits until the server, |waiting_for_child|, creates a\n// debug socket. Then the parent exec()s the debugger over itself. While it's\n// waiting for the child, this is the child's pid.\n// This needs to be global because it's used by a signal handler.\nstatic pid_t waiting_for_child;\n\nstatic ReplaySession::Flags session_flags(const ReplayFlags& flags, bool can_retry_transient_errors) {\n  ReplaySession::Flags result;\n  result.redirect_stdio = flags.redirect;\n  result.redirect_stdio_file = flags.tty;\n  result.share_private_mappings = flags.share_private_mappings;\n  result.cpu_unbound = flags.cpu_unbound;\n  result.intel_pt_start_checking_event = flags.intel_pt_start_checking_event;\n  result.transient_errors_fatal = !can_retry_transient_errors || !flags.retry_transient_errors;\n  return result;\n}\n\nstatic uint64_t to_microseconds(const struct timeval& tv) {\n  return (uint64_t)tv.tv_sec * 1000000 + tv.tv_usec;\n}\n\nstatic void serve_replay_no_debugger(const string& trace_dir,\n                                     const ReplayFlags& flags) {\n  ReplaySession::shr_ptr replay_session =\n    ReplaySession::create(trace_dir, session_flags(flags, true));\n  uint32_t step_count = 0;\n  struct timeval last_dump_time;\n  double last_dump_rectime = 0;\n  Session::Statistics last_stats;\n  gettimeofday(&last_dump_time, NULL);\n  FrameTime printed_stdio_up_to_event = 0;\n\n  while (true) {\n    RunCommand cmd = RUN_CONTINUE;\n    if (flags.singlestep_to_event > 0 &&\n        replay_session->trace_reader().time() >= flags.singlestep_to_event) {\n      cmd = RUN_SINGLESTEP;\n      fputs(\"Stepping from: \", stderr);\n      ReplayTask* t = replay_session->current_task()->as_replay();\n      t->regs().print_register_file_compact(stderr);\n      fputc(' ', stderr);\n      t->extra_regs().print_register_file_compact(stderr);\n      fprintf(stderr, \" ticks:%\" PRId64 \"\\n\", t->tick_count());\n    }\n\n    FrameTime before_time = replay_session->trace_reader().time();\n    auto result = replay_session->replay_step(cmd);\n    FrameTime after_time = replay_session->trace_reader().time();\n    DEBUG_ASSERT(after_time >= before_time && after_time <= before_time + 1);\n\n    if (result.status == REPLAY_TRANSIENT_ERROR) {\n      // Restart the replay from the beginning\n      LOG(warn) << \"Transient error while replaying event \"\n        << after_time << \", re-replaying execution from the beginning\";\n      replay_session =\n        ReplaySession::create(trace_dir, session_flags(flags, true));\n      replay_session->set_suppress_stdio_before_event(printed_stdio_up_to_event + 1);\n      continue;\n    }\n\n    if (!last_dump_rectime) {\n      last_dump_rectime = replay_session->trace_reader().recording_time();\n    }\n    if (after_time > before_time && before_time > printed_stdio_up_to_event) {\n      printed_stdio_up_to_event = before_time;\n    }\n\n    ++step_count;\n    if (flags.dump_interval > 0 && step_count % flags.dump_interval == 0) {\n      struct timeval now;\n      gettimeofday(&now, NULL);\n      double rectime = replay_session->trace_reader().recording_time();\n      uint64_t elapsed_usec = to_microseconds(now) - to_microseconds(last_dump_time);\n      Session::Statistics stats = replay_session->statistics();\n      fprintf(stderr,\n          \"[ReplayStatistics] ticks %lld syscalls %lld bytes_written %lld \"\n          \"microseconds %lld %%realtime %.0f%%\\n\",\n          (long long)(stats.ticks_processed - last_stats.ticks_processed),\n          (long long)(stats.syscalls_performed - last_stats.syscalls_performed),\n          (long long)(stats.bytes_written - last_stats.bytes_written),\n          (long long)elapsed_usec,\n          100.0 * ((rectime - last_dump_rectime) * 1.0e6) / (double)elapsed_usec\n        );\n      last_dump_time = now;\n      last_stats = stats;\n      last_dump_rectime = rectime;\n    }\n\n    if (result.status == REPLAY_EXITED) {\n      break;\n    }\n    DEBUG_ASSERT(result.status == REPLAY_CONTINUE);\n    DEBUG_ASSERT(result.break_status.watchpoints_hit.empty());\n    DEBUG_ASSERT(!result.break_status.breakpoint_hit);\n    DEBUG_ASSERT(cmd == RUN_SINGLESTEP ||\n                 !result.break_status.singlestep_complete);\n  }\n\n  LOG(info) << \"Replayer successfully finished\";\n}\n\n/* Handling ctrl-C during replay:\n * We want the entire group of processes to remain a single process group\n * since that allows shell job control to work best.\n * We want ctrl-C to not reach tracees, because that would disturb replay.\n * That's taken care of by Task::set_up_process.\n * We allow terminal SIGINT to go directly to the parent and the child (rr).\n * rr's SIGINT handler |handle_SIGINT_in_child| just interrupts the replay\n * if we're in the process of replaying to a target event, otherwise it\n * does nothing.\n * Before the parent execs gdb, its SIGINT handler does nothing. After exec,\n * the signal handler is reset to default so gdb behaves as normal (which is\n * why we use a signal handler instead of SIG_IGN).\n */\nstatic void handle_SIGINT_in_parent(int sig) {\n  DEBUG_ASSERT(sig == SIGINT);\n  // Just ignore it.\n}\n\nstatic volatile bool stop_replaying_to_target;\n\nstatic void handle_SIGINT_in_child(int sig) {\n  DEBUG_ASSERT(sig == SIGINT);\n  stop_replaying_to_target = true;\n}\n\nstatic DebuggerType identify_debugger(const string& debugger_name) {\n  string debugger_base_name = debugger_name;\n  base_name(debugger_base_name);\n  if (debugger_base_name.find(\"lldb\") != string::npos) {\n    return DebuggerType::LLDB;\n  }\n  return DebuggerType::GDB;\n}\n\nstatic int replay(const string& trace_dir, const ReplayFlags& flags) {\n  GdbServer::Target target;\n  switch (flags.process_created_how) {\n    case ReplayFlags::CREATED_EXEC:\n      target.pid = flags.target_process;\n      target.require_exec = true;\n      break;\n    case ReplayFlags::CREATED_FORK:\n      target.pid = flags.target_process;\n      target.require_exec = false;\n      break;\n    case ReplayFlags::CREATED_NONE:\n      break;\n  }\n  target.event = flags.goto_event;\n\n  // If we're not going to autolaunch the debugger, don't go\n  // through the rigamarole to set that up.  All it does is\n  // complicate the process tree and confuse users.\n  if (flags.dont_launch_debugger) {\n    if (target.event == numeric_limits<decltype(target.event)>::max()) {\n      serve_replay_no_debugger(trace_dir, flags);\n    } else {\n      auto session = ReplaySession::create(trace_dir, session_flags(flags, false));\n      GdbServer::ConnectionFlags conn_flags;\n      conn_flags.dbg_port = flags.dbg_port;\n      conn_flags.dbg_host = flags.dbg_host;\n      conn_flags.debugger_name = flags.gdb_binary_file_path;\n      conn_flags.keep_listening = flags.keep_listening;\n      conn_flags.serve_files = flags.serve_files;\n      // For now, assume the remote target is GDB-compatible. At some point\n      // we could add a flag to control this.\n      GdbServer::serve_replay(session, target, &stop_replaying_to_target,\n                              DebuggerType::GDB, conn_flags);\n    }\n\n    // Everything should have been cleaned up by now.\n    check_for_leaks();\n    return 0;\n  }\n\n  int debugger_params_pipe[2];\n  if (pipe2(debugger_params_pipe, O_CLOEXEC)) {\n    FATAL() << \"Couldn't open debugger params pipe.\";\n  }\n  DebuggerType debugger_type = identify_debugger(flags.gdb_binary_file_path);\n  if (0 == (waiting_for_child = fork())) {\n    // Ensure only the parent has the read end of the pipe open. Then if\n    // the parent dies, our writes to the pipe will error out.\n    close(debugger_params_pipe[0]);\n\n    {\n      prctl(PR_SET_PDEATHSIG, SIGTERM, 0, 0, 0);\n\n      ScopedFd debugger_params_write_pipe(debugger_params_pipe[1]);\n      auto session = ReplaySession::create(trace_dir, session_flags(flags, false));\n      GdbServer::ConnectionFlags conn_flags;\n      conn_flags.dbg_port = flags.dbg_port;\n      conn_flags.dbg_host = flags.dbg_host;\n      conn_flags.debugger_params_write_pipe = &debugger_params_write_pipe;\n      conn_flags.serve_files = flags.serve_files;\n      if (target.event == -1 && target.pid == 0) {\n        // If `replay -e` is specified without a pid, go to the exit\n        // of the first process (rather than the first exit of a process).\n        target.pid = session->trace_reader().peek_frame().tid();\n      }\n\n      struct sigaction sa;\n      memset(&sa, 0, sizeof(sa));\n      sa.sa_flags = SA_RESTART;\n      sa.sa_handler = handle_SIGINT_in_child;\n      if (sigaction(SIGINT, &sa, nullptr)) {\n        FATAL() << \"Couldn't set sigaction for SIGINT.\";\n      }\n\n      GdbServer::serve_replay(session, target, &stop_replaying_to_target,\n                              debugger_type, conn_flags);\n    }\n    // Everything should have been cleaned up by now.\n    check_for_leaks();\n    return 0;\n  }\n  // Ensure only the child has the write end of the pipe open. Then if\n  // the child dies, our reads from the pipe will return EOF.\n  close(debugger_params_pipe[1]);\n  LOG(debug) << getpid() << \": forked debugger server \" << waiting_for_child;\n\n  struct sigaction sa;\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_flags = SA_RESTART;\n  sa.sa_handler = handle_SIGINT_in_parent;\n  if (sigaction(SIGINT, &sa, nullptr)) {\n    FATAL() << \"Couldn't set sigaction for SIGINT.\";\n  }\n\n  {\n    ScopedFd params_pipe_read_fd(debugger_params_pipe[0]);\n    launch_debugger(params_pipe_read_fd, flags.gdb_binary_file_path,\n                    debugger_type, flags.gdb_options, flags.serve_files);\n  }\n\n  // Child must have died before we were able to get debugger parameters\n  // and exec gdb. Exit with the exit status of the child.\n  while (true) {\n    WaitResult result = WaitManager::wait_exit(WaitOptions(waiting_for_child));\n    if (result.code != WAIT_OK) {\n      FATAL() << \"Failed to wait for child \" << waiting_for_child;\n    }\n    LOG(debug) << getpid() << \": waitpid(\" << waiting_for_child << \") returned status \"\n               << result.status;\n    LOG(info) << \"Debugger server died.  Exiting.\";\n    exit(result.status.type() == WaitStatus::EXIT ? result.status.exit_code() : 1);\n  }\n\n  return 0;\n}\n\nint ReplayCommand::run(vector<string>& args) {\n  bool found_dir = false;\n  string trace_dir;\n  ReplayFlags flags;\n\n  while (!args.empty()) {\n    if (parse_replay_arg(args, flags)) {\n      continue;\n    }\n    if (parse_literal(args, \"--\")) {\n      flags.gdb_options.insert(flags.gdb_options.end(), args.begin(),\n                               args.end());\n      break;\n    }\n    if (!found_dir && parse_optional_trace_dir(args, &trace_dir)) {\n      found_dir = true;\n      continue;\n    }\n    print_help(stderr);\n    return 1;\n  }\n\n  if (!flags.target_command.empty()) {\n    flags.target_process =\n        find_pid_for_command(trace_dir, flags.target_command);\n    if (flags.target_process <= 0) {\n      fprintf(stderr, \"No process '%s' found. Try 'rr ps'.\\n\",\n              flags.target_command.c_str());\n      return 2;\n    }\n  }\n  if (flags.process_created_how != ReplayFlags::CREATED_NONE) {\n    if (!pid_exists(trace_dir, flags.target_process)) {\n      fprintf(stderr, \"No process %d found in trace. Try 'rr ps'.\\n\",\n              flags.target_process);\n      return 2;\n    }\n    if (flags.process_created_how == ReplayFlags::CREATED_EXEC &&\n        !pid_execs(trace_dir, flags.target_process)) {\n      fprintf(stderr, \"Process %d never exec()ed. Try 'rr ps', or use \"\n                      \"'-f'.\\n\",\n              flags.target_process);\n      return 2;\n    }\n  }\n  if (flags.dump_interval > 0 && !flags.dont_launch_debugger) {\n    fprintf(stderr, \"--stats requires -a\\n\");\n    print_help(stderr);\n    return 2;\n  }\n  if (flags.retry_transient_errors && flags.dump_interval) {\n    fprintf(stderr, \"--retry-transient-errors is not compatible with --dump-interval\");\n    print_help(stderr);\n    return 2;\n  }\n  if (flags.retry_transient_errors && flags.singlestep_to_event) {\n    fprintf(stderr, \"--retry-transient-errors is not compatible with --singlestep-to-event\");\n    print_help(stderr);\n    return 2;\n  }\n  if (flags.retry_transient_errors && !flags.dont_launch_debugger) {\n    fprintf(stderr, \"--retry-transient-errors requires -a (for now)\");\n    print_help(stderr);\n    return 2;\n  }\n\n  assert_prerequisites();\n\n  if (running_under_rr()) {\n    if (!Flags::get().suppress_environment_warnings) {\n      fprintf(stderr, \"rr: rr pid %d running under parent %d. Good luck.\\n\",\n              getpid(), getppid());\n    }\n    if (trace_dir.empty()) {\n      fprintf(stderr,\n              \"rr: No trace-dir supplied. You'll try to replay the \"\n              \"recording of this rr and have a bad time. Bailing out.\\n\");\n      return 3;\n    }\n  }\n\n  if (flags.keep_listening && flags.dbg_port == -1) {\n    fprintf(stderr,\n            \"Cannot use --keep-listening (-k) without --dbgport (-s).\\n\");\n    return 4;\n  }\n\n  return replay(trace_dir, flags);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ReplayCommand.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REPLAY_COMMAND_H_\n#define RR_REPLAY_COMMAND_H_\n\n#include \"Command.h\"\n\nnamespace rr {\n\nclass ReplayCommand : public Command {\npublic:\n  virtual int run(std::vector<std::string>& args) override;\n\n  static ReplayCommand* get() { return &singleton; }\n\nprotected:\n  ReplayCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static ReplayCommand singleton;\n};\n\n} // namespace rr\n\n#endif // RR_REPLAY_COMMAND_H_\n"
  },
  {
    "path": "src/ReplaySession.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define USE_BREAKPOINT_TARGET 1\n\n#include \"ReplaySession.h\"\n\n#include <linux/futex.h>\n#include <syscall.h>\n#include <sys/prctl.h>\n\n#include <algorithm>\n#include <ostream>\n#include <sstream>\n#include <unordered_map>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"Flags.h\"\n#include \"ProcessorTraceDecoder.h\"\n#include \"processor_trace_check.h\"\n#include \"ReplayTask.h\"\n#include \"ThreadGroup.h\"\n#include \"core.h\"\n#include \"fast_forward.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"replay_syscall.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic void debug_memory(ReplayTask* t) {\n  FrameTime current_time = t->current_frame_time();\n  if (should_dump_memory(t->current_trace_frame().event(), current_time)) {\n    dump_process_memory(t, current_time, \"rep\");\n  }\n  if (t->session().done_initial_exec() &&\n      should_checksum(t->current_trace_frame().event(), current_time)) {\n    /* Validate the checksum we computed during the\n     * recording phase. */\n    validate_process_memory(t, current_time);\n  }\n}\n\nstatic void split_at_address(ReplaySession::MemoryRanges& ranges,\n                             remote_ptr<void> addr) {\n  ReplaySession::MemoryRanges::iterator it =\n      ranges.lower_bound(MemoryRange(addr, addr + 1));\n  if (it != ranges.end() && it->contains(addr) && it->start() != addr) {\n    MemoryRange r1(it->start(), addr);\n    MemoryRange r2(addr, it->end());\n    ranges.erase(it);\n    ranges.insert(r1);\n    ranges.insert(r2);\n  }\n}\n\nvoid ReplaySession::delete_range(ReplaySession::MemoryRanges& ranges,\n                                 const MemoryRange& r) {\n  split_at_address(ranges, r.start());\n  split_at_address(ranges, r.end());\n  auto first = ranges.lower_bound(MemoryRange(r.start(), r.start() + 1));\n  auto last = ranges.lower_bound(MemoryRange(r.end(), r.end() + 1));\n  ranges.erase(first, last);\n}\n\nconst ReplaySession::MemoryRanges& ReplaySession::always_free_address_space(\n    PerfTradeoff perf_tradeoff) {\n  shared_ptr<MemoryRanges>& result =\n      perf_tradeoff == ACCURATE ? always_free_address_space_accurate :\n        always_free_address_space_fast;\n  if (!result->empty()) {\n    return *result;\n  }\n\n  remote_ptr<void> addressable_min = remote_ptr<void>(64 * 1024);\n  // Assume 64-bit address spaces with the 47-bit user-space limitation,\n  // for now.\n  remote_ptr<void> addressable_max = uintptr_t(\n      sizeof(void*) == 8 ? uint64_t(1) << 47 : (uint64_t(1) << 32) - page_size());\n  result->insert(MemoryRange(addressable_min, addressable_max));\n  TraceReader tmp_reader(trace_reader());\n  bool found;\n  while (true) {\n    KernelMapping km = tmp_reader.read_mapped_region(\n        nullptr, &found, TraceReader::DONT_VALIDATE, TraceReader::ANY_TIME);\n    if (!found) {\n      break;\n    }\n    // We can use PROT_NONE space, since any access of it by the application\n    // would have triggered a SIGSEGV.\n    // This is important when processing traces recorded with sanitizers compiled\n    // in.\n    // If it's mapped PROT_NONE but later mprotect() is used to make it usable, that\n    // is handled below. In FAST mode we don't use this memory, since we don't\n    // want to scan the trace frames.\n    if (perf_tradeoff == ACCURATE && km.prot() == PROT_NONE) {\n      continue;\n    }\n    delete_range(*result, km);\n  }\n  while (perf_tradeoff == ACCURATE && !tmp_reader.at_end()) {\n    auto frame = tmp_reader.read_frame();\n    auto event = frame.event();\n    // If a region was ever mprotected to something that's not PROT_NONE,\n    // or had PR_SET_VMA_ANON_NAME called on it, we need to delete it as well.\n    if (event.is_syscall_event()) {\n      auto syscall_event = event.Syscall();\n      if (is_mprotect_syscall(syscall_event.number, syscall_event.arch()) ||\n          is_pkey_mprotect_syscall(syscall_event.number, syscall_event.arch())) {\n        auto regs = frame.regs();\n        if (regs.arg3() != PROT_NONE) {\n          remote_ptr<void> start = regs.arg1();\n          size_t size = regs.arg2();\n          delete_range(*result, MemoryRange(start, size));\n        }\n      }\n      if (is_prctl_syscall(syscall_event.number, syscall_event.arch())) {\n        auto regs = frame.regs();\n        if (regs.arg2() == PR_SET_VMA_ANON_NAME) {\n          remote_ptr<void> start = regs.arg3();\n          size_t size = regs.arg4();\n          delete_range(*result, MemoryRange(start, size));\n        }\n      }\n    } else if (event.is_syscallbuf_flush_event()) {\n      auto syscallbuf_flush_event = event.SyscallbufFlush();\n      for (auto& record : syscallbuf_flush_event.mprotect_records) {\n        if (record.prot != PROT_NONE) {\n          delete_range(*result, MemoryRange(record.start, record.size));\n        }\n      }\n    }\n  }\n  delete_range(*result, MemoryRange(AddressSpace::rr_page_start(),\n                                    AddressSpace::rr_page_end()));\n  return *result;\n}\n\nstatic bool tracee_xsave_enabled(const TraceReader& trace_in) {\n  const CPUIDRecord* record =\n    find_cpuid_record(trace_in.cpuid_records(), CPUID_GETFEATURES, 0);\n  return (record->out.ecx & OSXSAVE_FEATURE_FLAG) != 0;\n}\n\nstatic void check_xsave_compatibility(const TraceReader& trace_in) {\n  if (!tracee_xsave_enabled(trace_in)) {\n    // Tracee couldn't use XSAVE so everything should be fine.\n    // If it didn't detect absence of XSAVE and actually executed an XSAVE\n    // and got a fault then replay will probably diverge :-(\n    return;\n  }\n  if (!xsave_enabled()) {\n    // Replaying on a super old CPU that doesn't even support XSAVE!\n    if (!Flags::get().suppress_environment_warnings) {\n      fprintf(stderr, \"rr: Tracees had XSAVE but XSAVE is not available \"\n              \"now; Replay will probably fail because glibc dynamic loader \"\n              \"uses XSAVE\\n\\n\");\n    }\n    return;\n  }\n\n  uint64_t tracee_xcr0 = trace_in.xcr0();\n  uint64_t our_xcr0 = xcr0();\n  const CPUIDRecord* record =\n    find_cpuid_record(trace_in.cpuid_records(), CPUID_GETXSAVE, 1);\n  bool tracee_xsavec = record && (record->out.eax & XSAVEC_FEATURE_FLAG);\n  CPUIDData data = cpuid(CPUID_GETXSAVE, 1);\n  bool our_xsavec = (data.eax & XSAVEC_FEATURE_FLAG) != 0;\n  if (tracee_xsavec && !our_xsavec &&\n      !Flags::get().suppress_environment_warnings) {\n    fprintf(stderr, \"rr: Tracees had XSAVEC but XSAVEC is not available \"\n            \"now; Replay will probably fail because glibc dynamic loader \"\n            \"uses XSAVEC\\n\\n\");\n  }\n\n  if (tracee_xcr0 != our_xcr0) {\n    if (!Flags::get().suppress_environment_warnings) {\n      // If the tracee used XSAVE instructions which write different components\n      // to XSAVE instructions executed on our CPU, or examines XCR0 directly,\n      // This will cause divergence. The dynamic linker examines XCR0 so this\n      // is nearly guaranteed.\n      cerr << \"Trace XCR0 value \" << HEX(tracee_xcr0) << \" != our XCR0 \"\n          << \"value \" << HEX(our_xcr0) << \"; Replay will probably fail \"\n          << \"because glibc dynamic loader examines XCR0\\n\\n\";\n    }\n  }\n\n  bool check_alignment = tracee_xsavec && our_xsavec;\n  // Check that sizes and offsets of supported XSAVE areas area all identical.\n  // An Intel employee promised this on a mailing list...\n  // https://lists.xen.org/archives/html/xen-devel/2013-09/msg00484.html\n  for (int feature = 2; feature <= 63; ++feature) {\n    if (!(tracee_xcr0 & our_xcr0 & (uint64_t(1) << feature))) {\n      continue;\n    }\n    record =\n      find_cpuid_record(trace_in.cpuid_records(), CPUID_GETXSAVE, feature);\n    CPUIDData data = cpuid(CPUID_GETXSAVE, feature);\n    if (!record || record->out.eax != data.eax ||\n        record->out.ebx != data.ebx ||\n        (check_alignment && (record->out.ecx & 2) != (data.ecx & 2))) {\n      CLEAN_FATAL()\n          << \"XSAVE offset/size/alignment differs for feature \" << feature\n          << \"; H. Peter Anvin said this would never happen!\";\n    }\n  }\n}\n\nReplaySession::ReplaySession(const std::string& dir, const Flags& flags)\n    : emu_fs(EmuFs::create()),\n      trace_in(dir),\n      trace_frame(),\n      current_step(),\n      ticks_at_start_of_event(0),\n      flags_(flags),\n      skip_next_execution_event(false),\n      replay_stops_at_first_execve_(flags.replay_stops_at_first_execve),\n      detected_transient_error_(false),\n      trace_start_time(0),\n      suppress_stdio_before_event_(0),\n      always_free_address_space_fast(make_shared<MemoryRanges>()),\n      always_free_address_space_accurate(make_shared<MemoryRanges>()) {\n  if (trace_in.required_forward_compatibility_version() > FORWARD_COMPATIBILITY_VERSION) {\n    CLEAN_FATAL()\n      << \"This rr build is too old to replay the trace (we support forward compatibility version \"\n      << FORWARD_COMPATIBILITY_VERSION << \" but the trace needs \" << trace_in.required_forward_compatibility_version() << \")\";\n  }\n\n  ticks_semantics_ = trace_in.ticks_semantics();\n  rrcall_base_ = trace_in.rrcall_base();\n  syscallbuf_fds_disabled_size_ = trace_in.syscallbuf_fds_disabled_size();\n  syscallbuf_hdr_size_ = trace_in.syscallbuf_hdr_size();\n\n  if (!flags.redirect_stdio_file.empty()) {\n    tracee_output_fd_ = make_shared<ScopedFd>(flags.redirect_stdio_file.c_str(), O_CREAT | O_TRUNC | O_WRONLY, 0600);\n    if (!tracee_output_fd_->is_open()) {\n      FATAL() << \"Can't open/create tracee output file \" << flags.redirect_stdio_file;\n    }\n  }\n\n  memset(&last_siginfo_, 0, sizeof(last_siginfo_));\n  advance_to_next_trace_frame();\n\n  trace_start_time = trace_frame.monotonic_time();\n\n  if (!flags.replay_stops_at_first_execve) {\n    if (!PerfCounters::supports_ticks_semantics(ticks_semantics_)) {\n      CLEAN_FATAL()\n          << \"Trace was recorded on a machine that defines ticks differently\\n\"\n             \"to this machine; replay will not work.\";\n    }\n\n    if (is_x86ish(trace_in.arch())) {\n      if (trace_in.uses_cpuid_faulting() && !has_cpuid_faulting()) {\n        CLEAN_FATAL()\n            << \"Trace was recorded with CPUID faulting enabled, but this\\n\"\n              \"system does not support CPUID faulting.\";\n      }\n      if (!has_cpuid_faulting() && !cpuid_compatible(trace_in.cpuid_records())) {\n        CLEAN_FATAL()\n            << \"Trace was recorded on a machine with different CPUID values\\n\"\n              \"and CPUID faulting is not enabled; replay will not work.\";\n      }\n\n      check_xsave_compatibility(trace_in);\n    }\n  }\n\n  set_intel_pt_enabled(flags.intel_pt_start_checking_event >= 0);\n\n  check_virtual_address_size();\n\n  bool cpu_improperly_configured_known, cpu_improperly_configured;\n  cpu_improperly_configured = trace_in.cpu_improperly_configured(&cpu_improperly_configured_known);\n  if (cpu_improperly_configured_known && cpu_improperly_configured) {\n    if (rr::Flags::get().force_things) {\n      LOG(warn) << \"CPU was improperly configured at recording but forcing anyways.\";\n    } else {\n      CLEAN_FATAL() << \"This trace was recorded on a CPU determined to be improperly configured \" <<\n        \"but rr's automated checks were overridden by the user. If you really want to \" <<\n        \"replay this trace override those checks again with -F\";\n    }\n  }\n}\n\nReplaySession::ReplaySession(const ReplaySession& other)\n    : Session(other),\n      emu_fs(EmuFs::create()),\n      tracee_output_fd_(other.tracee_output_fd_),\n      trace_in(other.trace_in),\n      trace_frame(other.trace_frame),\n      current_step(other.current_step),\n      ticks_at_start_of_event(other.ticks_at_start_of_event),\n      cpuid_bug_detector(other.cpuid_bug_detector),\n      last_siginfo_(other.last_siginfo_),\n      flags_(other.flags_),\n      fast_forward_status(other.fast_forward_status),\n      last_task_tuid(other.last_task_tuid),\n      skip_next_execution_event(other.skip_next_execution_event),\n      replay_stops_at_first_execve_(other.replay_stops_at_first_execve_),\n      detected_transient_error_(other.detected_transient_error_),\n      trace_start_time(other.trace_start_time),\n      suppress_stdio_before_event_(other.suppress_stdio_before_event_),\n      always_free_address_space_fast(other.always_free_address_space_fast),\n      always_free_address_space_accurate(other.always_free_address_space_accurate) {}\n\nReplaySession::~ReplaySession() {\n  // We won't permanently leak any OS resources by not ensuring\n  // we've cleaned up here, but sessions can be created and\n  // destroyed many times, and we don't want to temporarily hog\n  // resources.\n  kill_all_tasks();\n  syscall_bp_vm = nullptr;\n  DEBUG_ASSERT(task_map.empty() && vm_map.empty());\n  DEBUG_ASSERT(emufs().size() == 0);\n}\n\nvoid ReplaySession::check_virtual_address_size() const\n{\n  uint8_t virtual_address_size_needed = trace_in.max_virtual_address_size();\n  if (virtual_address_size_supported(virtual_address_size_needed)) {\n    return;\n  }\n\n  if (rr::Flags::get().force_things) {\n    LOG(warn) << \"Virtual address size is unsupported but forcing anyways.\";\n    return;\n  }\n\n  CLEAN_FATAL() << \"The trace uses \" << (uint32_t)virtual_address_size_needed <<\n      \" bit virtual addresses but this system does not support that size.\";\n}\n\nReplaySession::shr_ptr ReplaySession::clone() {\n  LOG(debug) << \"Deepforking ReplaySession \" << this << \" ...\";\n\n  finish_initializing();\n  clear_syscall_bp();\n\n  shr_ptr session(new ReplaySession(*this));\n  LOG(debug) << \"  deepfork session is \" << session.get();\n\n  copy_state_to(*session, emufs(), session->emufs());\n\n  return session;\n}\n\n/**\n * Return true if it's possible/meaningful to make a checkpoint at the\n * |frame| that |t| will replay.\n */\nstatic bool can_checkpoint_at(const Event& ev) {\n  if (ev.has_ticks_slop()) {\n    return false;\n  }\n  switch (ev.type()) {\n    case EV_EXIT:\n    // At exits, we can't clone the exiting tasks, so\n    // don't event bother trying to checkpoint.\n    case EV_SYSCALLBUF_RESET:\n    // RESETs are usually inserted in between syscall\n    // entry/exit.  Do not attempting to checkpoint at\n    // RESETs.  Users would never want to do that anyway.\n    case EV_TRACE_TERMINATION:\n      // There's nothing to checkpoint at the end of a trace.\n      return false;\n    default:\n      return true;\n  }\n}\n\nbool ReplaySession::can_clone() {\n  finish_initializing();\n\n  ReplayTask* t = current_task();\n  return t && done_initial_exec() && can_checkpoint_at(current_trace_frame().event());\n}\n\nDiversionSession::shr_ptr ReplaySession::clone_diversion() {\n  finish_initializing();\n  clear_syscall_bp();\n\n  LOG(debug) << \"Deepforking ReplaySession \" << this\n             << \" to DiversionSession...\";\n\n  DiversionSession::shr_ptr session(new DiversionSession(cpu_binding()));\n  session->ticks_semantics_ = ticks_semantics_;\n  session->tracee_socket = tracee_socket;\n  session->tracee_socket_fd_number = tracee_socket_fd_number;\n  session->rrcall_base_ = rrcall_base_;\n  session->syscallbuf_fds_disabled_size_ = syscallbuf_fds_disabled_size_;\n  LOG(debug) << \"  deepfork session is \" << session.get();\n\n  copy_state_to(*session, emufs(), session->emufs());\n  session->finish_initializing();\n\n  return session;\n}\n\nTask* ReplaySession::new_task(pid_t tid, pid_t rec_tid, uint32_t serial,\n                              SupportedArch a, const std::string& name) {\n  return new ReplayTask(*this, tid, rec_tid, serial, a, name);\n}\n\n/*static*/ ReplaySession::shr_ptr ReplaySession::create(const string& dir,\n                                                        const ReplaySession::Flags& flags) {\n  shr_ptr session(new ReplaySession(dir, flags));\n\n  // It doesn't really matter what we use for argv/env here, since\n  // replay_syscall's process_execve is going to follow the recording and\n  // ignore the parameters.\n  string exe_path;\n  vector<string> argv;\n  vector<string> env;\n\n  session->do_bind_cpu();\n  ScopedFd error_fd = session->create_spawn_task_error_pipe();\n  ReplayTask* t = static_cast<ReplayTask*>(\n      Task::spawn(*session, error_fd, &session->tracee_socket_fd(),\n                  &session->tracee_socket_receiver_fd(),\n                  &session->tracee_socket_fd_number,\n                  exe_path, argv, env,\n                  session->trace_reader().peek_frame().tid()));\n  session->on_create(t);\n\n  return session;\n}\n\nBindCPU ReplaySession::cpu_binding() const {\n  if (flags_.cpu_unbound) {\n    return BindCPU(BindCPU::UNBOUND);\n  }\n  return Session::cpu_binding();\n}\n\nvoid ReplaySession::advance_to_next_trace_frame() {\n  if (trace_in.at_end()) {\n    trace_frame = TraceFrame(trace_frame.time(), 0, Event::trace_termination(),\n                             trace_frame.ticks(), trace_frame.monotonic_time());\n    return;\n  }\n\n  trace_frame = trace_in.read_frame();\n}\n\nbool ReplaySession::is_ignored_signal(int sig) {\n  switch (sig) {\n    // TIME_SLICE_SIGNALs can be queued but not delivered before we stop\n    // execution for some other reason. Ignore them.\n    case PerfCounters::TIME_SLICE_SIGNAL:\n      return true;\n    default:\n      return false;\n  }\n}\n\n/* Why a skid region?  Interrupts generated by perf counters don't\n * fire at exactly the programmed point (as of 2013 kernel/HW);\n * there's a variable slack region, which is technically unbounded.\n * This means that an interrupt programmed for retired branch k might\n * fire at |k + 50|, for example.  To counteract the slack, we program\n * interrupts just short of our target, by the |SKID_SIZE| region\n * below, and then more slowly advance to the real target.\n *\n * How was this magic number determined?  Trial and error: we want it\n * to be as small as possible for efficiency, but not so small that\n * overshoots are observed.  If all other possible causes of overshoot\n * have been ruled out, like memory divergence, then you'll know that\n * this magic number needs to be increased if the following symptom is\n * observed during replay.  Running with DEBUGLOG enabled (see above),\n * a sequence of log messages like the following will appear\n *\n * 1. programming interrupt for [target - SKID_SIZE] ticks\n * 2. Error: Replay diverged.  Dumping register comparison.\n * 3. Error: [list of divergent registers; arbitrary]\n * 4. Error: overshot target ticks=[target] by [i]\n *\n * The key is that no other replayer log messages occur between (1)\n * and (2).  This spew means that the replayer programmed an interrupt\n * for ticks=[target-SKID_SIZE], but the tracee was actually interrupted\n * at ticks=[target+i].  And that in turn means that the kernel/HW\n * skidded too far past the programmed target for rr to handle it.\n *\n * If that occurs, the SKID_SIZE needs to be increased by at least\n * [i].\n *\n * NB: there are probably deeper reasons for the target slack that\n * could perhaps let it be deduced instead of arrived at empirically;\n * perhaps pipeline depth and things of that nature are involved.  But\n * those reasons if they exit are currently not understood.\n */\nstatic bool compute_ticks_request(\n    ReplayTask* t, const ReplaySession::StepConstraints& constraints,\n    TicksRequest* ticks_request) {\n  *ticks_request = RESUME_UNLIMITED_TICKS;\n  if (constraints.ticks_target > 0) {\n    Ticks ticks_period =\n        constraints.ticks_target - t->hpc.skid_size() - t->tick_count();\n    if (ticks_period <= 0) {\n      // Behave as if we actually executed something. Callers assume we did.\n      t->clear_wait_status();\n      return false;\n    }\n    if (ticks_period > MAX_TICKS_REQUEST) {\n      // Avoid overflow. The execution will stop early but we'll treat that\n      // just like a stray TIME_SLICE_SIGNAL and continue as needed.\n      *ticks_request = MAX_TICKS_REQUEST;\n    } else {\n      *ticks_request = (TicksRequest)ticks_period;\n    }\n  }\n  return true;\n}\n\nstatic void perform_interrupted_syscall(ReplayTask* t) {\n  t->finish_emulated_syscall();\n  AutoRemoteSyscalls remote(t);\n  const Registers& r = t->regs();\n  long ret = remote.syscall(r.original_syscallno(), r.arg1(), r.arg2(),\n                            r.arg3(), r.arg4(), r.arg5(), r.arg6());\n  remote.regs().set_syscall_result(ret);\n}\n\nbool ReplaySession::handle_unrecorded_cpuid_fault(\n    ReplayTask* t, const StepConstraints& constraints) {\n  if (t->stop_sig() != SIGSEGV || !has_cpuid_faulting() ||\n      trace_in.uses_cpuid_faulting() ||\n      special_instruction_at(t, t->ip()).opcode != SpecialInstOpcode::X86_CPUID) {\n    return false;\n  }\n  // OK, this is a case where we did not record using CPUID faulting but we are\n  // replaying with CPUID faulting and the tracee just executed a CPUID.\n  // We try to find the results in the \"all CPUID leaves\" we saved.\n\n  const vector<CPUIDRecord>& records = trace_in.cpuid_records();\n  Registers r = t->regs();\n  const CPUIDRecord* rec = find_cpuid_record(records, r.ax(), r.cx());\n  if (rec) {\n    if (rec->ecx_in == UINT32_MAX &&\n        (r.ax() == CPUID_AMD_CACHE_TOPOLOGY || r.ax() == CPUID_AMD_PLATFORM_QOS)) {\n      const CPUIDRecord* rec2 = find_cpuid_record(records, CPUID_GETVENDORSTRING, 0);\n      if (!rec2 || is_cpu_vendor_amd(rec2->out)) {\n        LOG(error) << \"Can't find extended AMD CPUID records. Replay will likely fail. \" <<\n          \"Please re-record the trace with an up-to-date version of rr.\";\n      }\n    }\n    r.set_cpuid_output(rec->out.eax, rec->out.ebx, rec->out.ecx, rec->out.edx);\n  } else {\n    LOG(warn) << \"Can't find CPUID record for request AX=\" << HEX(r.ax())\n              << \" CX=\" << HEX(r.cx()) << \"; defaulting to 0/0/0/0\";\n    r.set_cpuid_output(0, 0, 0, 0);\n  }\n  r.set_ip(r.ip() + special_instruction_len(SpecialInstOpcode::X86_CPUID));\n  t->set_regs(r);\n  // Clear SIGSEGV status since we're handling it\n  t->set_status(constraints.is_singlestep() ? WaitStatus::for_stop_sig(SIGTRAP)\n                                            : WaitStatus());\n  return true;\n}\n\n/**\n * Continue until reaching either the \"entry\" of an emulated syscall,\n * or the entry or exit of an executed syscall.  |emu| is nonzero when\n * we're emulating the syscall.  Return COMPLETE when the next syscall\n * boundary is reached, or INCOMPLETE if advancing to the boundary was\n * interrupted by an unknown trap.\n * When |syscall_trace_frame| is non-null, we continue to the syscall by\n * setting a breakpoint instead of running until we execute a system\n * call instruction. In that case we will not actually enter the kernel.\n */\nCompletion ReplaySession::cont_syscall_boundary(\n    ReplayTask* t, const StepConstraints& constraints) {\n  TicksRequest ticks_request = RESUME_UNLIMITED_TICKS;\n  if (constraints.ticks_target <= trace_frame.ticks()) {\n    if (!compute_ticks_request(t, constraints, &ticks_request)) {\n      return INCOMPLETE;\n    }\n  }\n\n  if (constraints.command == RUN_SINGLESTEP_FAST_FORWARD) {\n    // ignore ticks_period. We can't add more than one tick during a\n    // fast_forward so it doesn't matter.\n    fast_forward_status |= fast_forward_through_instruction(\n        t, RESUME_SYSEMU_SINGLESTEP, constraints.stop_before_states);\n  } else {\n    ResumeRequest resume_how =\n        constraints.is_singlestep() ? RESUME_SYSEMU_SINGLESTEP : RESUME_SYSEMU;\n    bool ok = t->resume_execution(resume_how, RESUME_WAIT_NO_EXIT, ticks_request);\n    ASSERT(t, ok) << \"Tracee died unexpectedly\";\n  }\n\n  switch (t->stop_sig()) {\n    case 0:\n      break;\n    case PerfCounters::TIME_SLICE_SIGNAL:\n      // This would normally be triggered by constraints.ticks_target but it's\n      // also possible to get stray signals here.\n      return INCOMPLETE;\n    case SIGSEGV:\n      if (handle_unrecorded_cpuid_fault(t, constraints)) {\n        return INCOMPLETE;\n      }\n      break;\n    case SIGTRAP:\n      return INCOMPLETE;\n    default:\n      break;\n  }\n  if (t->stop_sig()) {\n    ASSERT(t, false) << \"Replay got unrecorded signal \" << t->get_siginfo();\n  }\n\n  if (t->seccomp_bpf_enabled &&\n      syscall_seccomp_ordering_ == PTRACE_SYSCALL_BEFORE_SECCOMP_UNKNOWN) {\n    ASSERT(t, !constraints.is_singlestep());\n    if (t->ptrace_event() == PTRACE_EVENT_SECCOMP) {\n      syscall_seccomp_ordering_ = SECCOMP_BEFORE_PTRACE_SYSCALL;\n    } else {\n      syscall_seccomp_ordering_ = PTRACE_SYSCALL_BEFORE_SECCOMP;\n    }\n    // Eat the following event, either a seccomp or syscall notification\n    bool ok = t->resume_execution(RESUME_SYSEMU, RESUME_WAIT_NO_EXIT, ticks_request);\n    ASSERT(t, ok) << \"Tracee died unexpectedly\";\n  }\n\n  t->apply_syscall_entry_regs();\n\n  auto type = AddressSpace::rr_page_syscall_from_exit_point(t->arch(), t->ip());\n  if (type && type->traced == AddressSpace::UNTRACED &&\n      type->enabled == AddressSpace::REPLAY_ONLY) {\n    // Actually perform it. We can hit these when replaying through syscallbuf\n    // code that was interrupted.\n    perform_interrupted_syscall(t);\n    return INCOMPLETE;\n  }\n\n  return COMPLETE;\n}\n\nvoid ReplaySession::clear_syscall_bp() {\n  if (syscall_bp_vm) {\n    syscall_bp_vm->remove_breakpoint(syscall_bp_addr, BKPT_INTERNAL);\n    syscall_bp_vm = nullptr;\n    syscall_bp_addr = nullptr;\n  }\n}\n\n/**\n * Make it look like |t| entered the syscall at |syscall_instruction|\n */\nstatic void emulate_syscall_entry(ReplayTask* t, const TraceFrame& frame,\n                                  remote_code_ptr syscall_instruction) {\n  Registers r = t->regs();\n  r.set_ip(syscall_instruction.increment_by_syscall_insn_length(t->arch()));\n  r.emulate_syscall_entry();\n  t->set_regs(r);\n  t->canonicalize_regs(frame.event().Syscall().arch());\n  t->validate_regs();\n}\n\n/**\n * Advance to the next syscall entry (or virtual entry) according to\n * |step|.  Return COMPLETE if successful, or INCOMPLETE if an unhandled trap\n * occurred.\n */\nCompletion ReplaySession::enter_syscall(ReplayTask* t,\n                                        const StepConstraints& constraints) {\n  if (t->regs().matches(trace_frame.regs()) &&\n      t->tick_count() == trace_frame.ticks()) {\n    // We already entered the syscall via an ENTERING_SYSCALL_PTRACE\n    ASSERT(t,\n           current_trace_frame().event().Syscall().state == ENTERING_SYSCALL);\n  } else {\n    remote_code_ptr syscall_instruction;\n\n    if (done_initial_exec()) {\n      syscall_instruction =\n          current_trace_frame().regs().ip().decrement_by_syscall_insn_length(\n              t->arch());\n      // If the breakpoint already exists, it must have been from a previous\n      // invocation of this function for the same event (once the event\n      // completes, the breakpoint is cleared).\n      DEBUG_ASSERT(!syscall_bp_vm || (syscall_bp_vm == t->vm() &&\n                                      syscall_instruction == syscall_bp_addr &&\n                                      t->vm()->get_breakpoint_type_at_addr(\n                                          syscall_instruction) != BKPT_NONE));\n      // Skip this optimization if we can't set the breakpoint, or if it's\n      // in writeable or shared memory, since in those cases it could be\n      // overwritten by the tracee. It could even be dynamically generated and\n      // not generated yet.\n      if (!syscall_bp_vm &&\n          t->vm()->is_breakpoint_in_private_read_only_memory(\n              syscall_instruction)) {\n        if (t->vm()->add_breakpoint(syscall_instruction, BKPT_INTERNAL)) {\n          syscall_bp_vm = t->vm();\n          syscall_bp_addr = syscall_instruction;\n        }\n      }\n    }\n\n    if (cont_syscall_boundary(t, constraints) == INCOMPLETE) {\n      bool reached_target = syscall_bp_vm && SIGTRAP == t->stop_sig() &&\n                            t->ip().undo_executed_bkpt(t->arch()) ==\n                                syscall_instruction;\n      if (reached_target) {\n        // Check if we've hit a user break/watchpoint\n        if (t->vm()->get_breakpoint_type_at_addr(syscall_instruction) != BKPT_INTERNAL) {\n          reached_target = false;\n        }\n        else if (t->vm()->is_exec_watchpoint(syscall_instruction)) {\n          reached_target = false;\n        }\n      }\n      if (reached_target) {\n        emulate_syscall_entry(t, current_trace_frame(), syscall_instruction);\n        clear_syscall_bp();\n      } else {\n        return INCOMPLETE;\n      }\n    } else {\n      // If we use the breakpoint optimization, we must get a SIGTRAP before\n      // reaching a syscall, so cont_syscall_boundary must return INCOMPLETE.\n      if (syscall_bp_vm) {\n        ASSERT(t, false)\n            << \"Expected syscall_bp_vm to be clear but it's \" << syscall_bp_vm->leader_tid()\n            << \"'s address space with a breakpoint at \" << syscall_bp_addr\n            << \" while we're at \" << t->ip();\n      }\n      t->canonicalize_regs(current_trace_frame().event().Syscall().arch());\n      t->validate_regs();\n      t->finish_emulated_syscall();\n    }\n  }\n\n  if (current_trace_frame().event().Syscall().state == ENTERING_SYSCALL) {\n    rep_after_enter_syscall(t);\n  }\n  return COMPLETE;\n}\n\n/**\n * Advance past the reti (or virtual reti) according to |step|.\n * Return COMPLETE if successful, or INCOMPLETE if an unhandled trap occurred.\n */\nCompletion ReplaySession::exit_syscall(ReplayTask* t) {\n  t->on_syscall_exit(current_step.syscall.number, current_step.syscall.arch,\n                     current_trace_frame().regs());\n\n  t->apply_all_data_records_from_trace();\n  t->set_return_value_from_trace();\n\n  uint32_t flags = 0;\n  if (t->arch() == SupportedArch::x86 &&\n      (X86Arch::pwrite64 == current_step.syscall.number ||\n       X86Arch::pread64 == current_step.syscall.number)) {\n    flags |= ReplayTask::IGNORE_ESI;\n  }\n  t->validate_regs(flags);\n\n  return COMPLETE;\n}\n\nvoid ReplaySession::check_pending_sig(ReplayTask* t) {\n  if (!t->stop_sig()) {\n    ASSERT(t, false) << \"Replaying `\" << trace_frame.event()\n                     << \"': expecting tracee signal or trap, but instead at `\"\n                     << syscall_name(t->regs().original_syscallno(),\n                                     t->detect_syscall_arch())\n                     << \"' (ticks: \" << t->tick_count() << \")\";\n  }\n}\n\nstatic bool do_replay_assist(Task* t) {\n  auto orig_ip = t->ip();\n  auto exit_ip = orig_ip.advance_past_executed_bkpt(t->arch());\n  auto type = AddressSpace::rr_page_syscall_from_exit_point(t->arch(), exit_ip);\n  if (!type || type->enabled != AddressSpace::REPLAY_ASSIST) {\n    return false;\n  }\n  auto next_rec_ptr = t->next_syscallbuf_record();\n  auto next_rec = t->read_mem(next_rec_ptr);\n  ASSERT(t, next_rec.replay_assist);\n  Registers regs = t->regs();\n  regs.set_syscall_result(next_rec.ret);\n  t->on_syscall_exit(next_rec.syscallno, t->arch(), regs);\n  if (orig_ip != exit_ip) {\n    auto r = t->regs();\n    r.set_ip(exit_ip);\n    t->set_regs(r);\n  }\n  return true;\n}\n\n/**\n * Advance |t| to the next signal or trap according to |constraints.command|.\n *\n * Default |resume_how| is RESUME_SYSEMU for error checking:\n * since the next event is supposed to be a signal, entering a syscall here\n * means divergence.  There shouldn't be any straight-line execution overhead\n * for SYSEMU vs. CONT, so the difference in cost should be negligible.\n *\n * Some callers pass RESUME_CONT because they want to execute any syscalls\n * encountered.\n *\n * If we return INCOMPLETE, callers need to recalculate the constraints and\n * tick_request and try again. We may return INCOMPLETE because we successfully\n * processed a CPUID trap.\n */\nCompletion ReplaySession::continue_or_step(ReplayTask* t,\n                                           const StepConstraints& constraints,\n                                           TicksRequest tick_request,\n                                           ResumeRequest resume_how) {\n  if (constraints.command == RUN_SINGLESTEP) {\n    bool ok = t->resume_execution(RESUME_SINGLESTEP, RESUME_WAIT_NO_EXIT, tick_request);\n    ASSERT(t, ok) << \"Tracee died unexpectedly\";\n    handle_unrecorded_cpuid_fault(t, constraints);\n  } else if (constraints.command == RUN_SINGLESTEP_FAST_FORWARD) {\n    fast_forward_status |= fast_forward_through_instruction(\n        t, RESUME_SINGLESTEP, constraints.stop_before_states);\n    handle_unrecorded_cpuid_fault(t, constraints);\n  } else {\n    bool ok = t->resume_execution(resume_how, RESUME_WAIT_NO_EXIT, tick_request);\n    ASSERT(t, ok) << \"Tracee died unexpectedly\";\n    if (t->stop_sig() == 0) {\n      auto type = AddressSpace::rr_page_syscall_from_exit_point(t->arch(), t->ip());\n      if (type && type->traced == AddressSpace::UNTRACED) {\n        // If we recorded an rr replay of an application doing a\n        // syscall-buffered 'mprotect', the replay's `flush_syscallbuf`\n        // PTRACE_CONT'ed to execute the mprotect syscall and nothing was\n        // recorded for that until we hit the replay's breakpoint, when we\n        // record a SIGTRAP. However, when we replay that SIGTRAP via\n        // `emulate_deterministic_signal`, we call `continue_or_step`\n        // with `RESUME_SYSEMU` (to detect bugs when we reach a stray\n        // syscall instead of the SIGTRAP). So, we'll stop for the\n        // `mprotect` syscall here. We need to execute it and continue\n        // as if it wasn't hit.\n        // (Alternatively we could just replay with RESUME_CONT, but that\n        // would make it harder to track down bugs. There is a performance hit\n        // to stopping for each mprotect, but replaying recordings of replays\n        // is not fast anyway.)\n        t->apply_syscall_entry_regs();\n        perform_interrupted_syscall(t);\n        return INCOMPLETE;\n      }\n    } else if (t->stop_sig() == SIGTRAP) {\n      // Detect replay assist but handle it later in flush_syscallbuf\n      auto type = AddressSpace::rr_page_syscall_from_exit_point(t->arch(), t->ip().advance_past_executed_bkpt(t->arch()));\n      if (type && type->enabled == AddressSpace::REPLAY_ASSIST) {\n        t->apply_syscall_entry_regs();\n        return INCOMPLETE;\n      }\n    } else if (handle_unrecorded_cpuid_fault(t, constraints)) {\n      return INCOMPLETE;\n    }\n  }\n  check_pending_sig(t);\n  return COMPLETE;\n}\n\nstatic void guard_overshoot(ReplayTask* t, const Registers& target_regs,\n                            Ticks target_ticks, Ticks remaining_ticks,\n                            const Registers* closest_matching_regs) {\n  if (remaining_ticks < 0) {\n    remote_code_ptr target_ip = target_regs.ip();\n\n    /* Cover up the internal breakpoint that we may have\n     * set, and restore the tracee's $ip to what it would\n     * have been had it not hit the breakpoint (if it did\n     * hit the breakpoint).*/\n    t->vm()->remove_breakpoint(target_ip, BKPT_INTERNAL);\n    if (t->regs().ip().undo_executed_bkpt(t->arch()) == target_ip) {\n      t->move_ip_before_breakpoint();\n    }\n    if (closest_matching_regs) {\n      ASSERT(t, false) << \"overshot target ticks=\" << target_ticks << \" by \"\n        << -remaining_ticks << \"; target registers at ticks target mismatched: \"\n        << \"replay != rec: \" << t->regs().compare_with(*closest_matching_regs);\n    } else {\n      ASSERT(t, false) << \"overshot target ticks=\" << target_ticks << \" by \"\n        << -remaining_ticks << \"; target registers mismatched: \"\n        << \"replay != rec: \" << t->regs().compare_with(target_regs);\n    }\n  }\n}\n\nstatic void guard_unexpected_signal(ReplayTask* t) {\n  if (ReplaySession::is_ignored_signal(t->stop_sig()) ||\n      SIGTRAP == t->stop_sig()) {\n    return;\n  }\n\n  if (t->stop_sig()) {\n    ASSERT(t, false) << \"Replay got unrecorded signal \"\n                     << signal_name(t->stop_sig()) << \" while awaiting signal\"\n                     << \"\\n\" << t->get_siginfo();\n  } else if (t->status().is_syscall()) {\n    ASSERT(t, false) << \"Replay got unrecorded syscall \"\n                     << syscall_name(t->regs().original_syscallno(), t->arch())\n                     << \" while awaiting signal\";\n  }\n}\n\nstatic bool is_same_execution_point(ReplayTask* t, const Registers& rec_regs,\n                                    const ExtraRegisters& rec_extra_regs,\n                                    Ticks ticks_left,\n                                    Registers* mismatched_regs,\n                                    const Registers** mismatched_regs_ptr,\n                                    bool in_syscallbuf) {\n  if (ticks_left != 0) {\n    if (IS_LOGGING(debug)) {\n      LOG(debug) << \"  not same execution point: \" << ticks_left\n                 << \" ticks left (@\" << rec_regs.ip() << \")\"\n                 << \" replay vs rec: \" << t->regs().compare_with(rec_regs);\n    }\n    return false;\n  }\n  if (in_syscallbuf) {\n    // In the syscallbuf, only check IP. The values of registers may diverge between\n    // recording and replay.\n    // If this is too loose (i.e. we can reach the same IP with no ticks in between),\n    // we should add instructions to the syscallbuf code to explicitly increase the tick\n    // count, e.g. dummy conditional branches.\n    if (t->ip() != rec_regs.ip()) {\n      LOG(debug) << \"  not same execution point: expected IP \" << rec_regs.ip()\n                 << \", got \" << t->ip();\n      *mismatched_regs = t->regs();\n      *mismatched_regs_ptr = mismatched_regs;\n      return false;\n    }\n  } else if (!t->regs().matches(rec_regs)) {\n    if (IS_LOGGING(debug)) {\n      LOG(debug) << \"  not same execution point: regs differ (@\" << rec_regs.ip()\n                 << \") replay vs rec: \" << t->regs().compare_with(rec_regs);\n    }\n    *mismatched_regs = t->regs();\n    *mismatched_regs_ptr = mismatched_regs;\n    return false;\n  } else if (!t->extra_regs().matches(rec_extra_regs)) {\n    if (IS_LOGGING(debug)) {\n      LOG(debug) << \"  not same execution point: extra regs differ (@\" << rec_regs.ip()\n                 << \") replay vs rec: \" << t->extra_regs().compare_with(rec_extra_regs);\n    }\n    return false;\n  }\n  LOG(debug) << \"  same execution point\";\n  return true;\n}\n\n/**\n * Run execution forwards for |t| until |ticks| is reached, and the $ip\n * reaches the recorded $ip.  Return COMPLETE if successful or INCOMPLETE if an\n * unhandled interrupt occurred.  |sig| is the pending signal to be\n * delivered; it's only used to distinguish debugger-related traps\n * from traps related to replaying execution.  |ticks| is an inout param\n * that will be decremented by branches retired during this attempted\n * step.\n * If in_syscallbuf_syscall_hook is non-null we'll stop if execution\n * reaches that address and return COMPLETE.\n */\nCompletion ReplaySession::emulate_async_signal(\n    ReplayTask* t, const StepConstraints& constraints, Ticks ticks,\n    remote_code_ptr in_syscallbuf_syscall_hook) {\n  bool in_syscallbuf = !in_syscallbuf_syscall_hook.is_null();\n\n  const Registers& regs = trace_frame.regs();\n  const ExtraRegisters& extra_regs = trace_frame.extra_regs();\n  remote_code_ptr ip = regs.ip();\n\n  /* Step 1: advance to the target ticks (minus a slack region) as\n   * quickly as possible by programming the hpc. */\n  Ticks ticks_left = ticks - t->tick_count();\n\n  LOG(debug) << \"advancing \" << ticks_left << \" ticks to reach \" << ticks << \"/\"\n             << ip;\n\n  auto skid_size = t->hpc.skid_size();\n  /* XXX should we only do this if (ticks > 10000)? */\n  while (ticks_left - skid_size > skid_size) {\n    LOG(debug) << \"  programming interrupt for \"\n               << (ticks_left - skid_size) << \" ticks\";\n\n    // Avoid overflow. If ticks_left > MAX_TICKS_REQUEST, execution will stop\n    // early but we'll treat that just like a stray TIME_SLICE_SIGNAL and\n    // continue as needed.\n    if (in_syscallbuf_syscall_hook) {\n      // Advance no further than syscall_hook.\n      t->vm()->add_breakpoint(in_syscallbuf_syscall_hook, BKPT_INTERNAL);\n    }\n    continue_or_step(t, constraints,\n                     (TicksRequest)(min<Ticks>(MAX_TICKS_REQUEST, ticks_left) -\n                                    skid_size));\n    guard_unexpected_signal(t);\n    if (in_syscallbuf_syscall_hook) {\n      t->vm()->remove_breakpoint(in_syscallbuf_syscall_hook, BKPT_INTERNAL);\n    }\n\n    ticks_left = ticks - t->tick_count();\n\n    if (SIGTRAP == t->stop_sig()) {\n      if (t->ip().undo_executed_bkpt(t->arch()) == in_syscallbuf_syscall_hook) {\n        t->move_ip_before_breakpoint();\n        // Advance no further.\n        return COMPLETE;\n      }\n      /* We proved we're not at the execution\n       * target, and we haven't set any internal\n       * breakpoints, and we're not temporarily\n       * internally single-stepping, so we must have\n       * hit a debugger breakpoint or the debugger\n       * was single-stepping the tracee.  (The\n       * debugging code will verify that.) */\n      return INCOMPLETE;\n    }\n  }\n  guard_overshoot(t, regs, ticks, ticks_left, NULL);\n\n  /* True when our advancing has triggered a tracee SIGTRAP that needs to\n   * be dealt with. */\n  bool pending_SIGTRAP = false;\n  bool did_set_internal_breakpoints = false;\n  bool did_set_bpf_breakpoint = false;\n  RunCommand SIGTRAP_run_command = RUN_CONTINUE;\n\n  /* Step 2: more slowly, find our way to the target ticks and\n   * execution point.  We set an internal breakpoint on the\n   * target $ip and then resume execution.  When that *internal*\n   * breakpoint is hit (i.e., not one incidentally also set on\n   * that $ip by the debugger), we check again if we're at the\n   * target ticks and execution point.  If not, we temporarily\n   * remove the breakpoint, single-step over the insn, and\n   * repeat.\n   *\n   * What we really want to do is set a (precise)\n   * retired-instruction interrupt and do away with all this\n   * cruft. */\n  Registers mismatched_regs;\n  const Registers* mismatched_regs_ptr = NULL;\n  while (true) {\n    /* Invariants here are\n     *  o ticks_left is up-to-date\n     *  o ticks_left >= 0\n     *\n     * Possible state of the execution of |t|\n     *  0. at a debugger trap (breakpoint, watchpoint, stepi)\n     *  1. at an internal breakpoint\n     *  2. at the execution target\n     *  3. not at the execution target, but incidentally\n     *     at the target $ip\n     *  4. otherwise not at the execution target\n     *\n     * Determining whether we're at a debugger trap is\n     * surprisingly complicated. */\n    bool at_target = is_same_execution_point(\n        t, regs, extra_regs, ticks_left, &mismatched_regs, &mismatched_regs_ptr, in_syscallbuf);\n    if (pending_SIGTRAP) {\n      TrapReasons trap_reasons = t->compute_trap_reasons();\n      BreakpointType breakpoint_type =\n          t->vm()->get_breakpoint_type_for_retired_insn(t->ip());\n\n      if (constraints.is_singlestep()) {\n        ASSERT(t, trap_reasons.singlestep);\n      }\n      if (constraints.is_singlestep() ||\n          (trap_reasons.watchpoint && t->vm()->has_any_watchpoint_changes()) ||\n          (trap_reasons.breakpoint && BKPT_USER == breakpoint_type)) {\n        /* Case (0) above: interrupt for the debugger. */\n        LOG(debug) << \"    trap was debugger singlestep/breakpoint\";\n        if (did_set_internal_breakpoints) {\n          t->vm()->remove_breakpoint(ip, BKPT_INTERNAL);\n          if (in_syscallbuf_syscall_hook) {\n            t->vm()->remove_breakpoint(in_syscallbuf_syscall_hook, BKPT_INTERNAL);\n          }\n        }\n        return INCOMPLETE;\n      }\n\n      if (trap_reasons.breakpoint) {\n        // We didn't hit a user breakpoint, and executing an explicit\n        // breakpoint instruction in the tracee would have triggered a\n        // deterministic signal instead of an async one.\n        // So we must have hit our internal breakpoint.\n        ASSERT(t, did_set_internal_breakpoints || did_set_bpf_breakpoint);\n        // We didn't do an internal singlestep, and if we'd done a\n        // user-requested singlestep we would have hit the above case.\n        ASSERT(t, !trap_reasons.singlestep);\n        if (did_set_internal_breakpoints) {\n          if (t->ip().undo_executed_bkpt(t->arch()) == in_syscallbuf_syscall_hook) {\n            t->vm()->remove_breakpoint(ip, BKPT_INTERNAL);\n            t->vm()->remove_breakpoint(in_syscallbuf_syscall_hook, BKPT_INTERNAL);\n            t->move_ip_before_breakpoint();\n            return COMPLETE;\n          }\n          ASSERT(t, regs.ip() == t->ip().undo_executed_bkpt(t->arch()));\n        } else {\n          LOG(debug) << \"    fast-forwarded through \" << t->hpc.bpf_skips() << \" breakpoint hits with bpf\";\n        }\n        /* Case (1) above: cover the tracks of\n         * our internal breakpoint, and go\n         * check again if we're at the\n         * target. */\n        LOG(debug) << \"    trap was for target $ip\";\n\n        pending_SIGTRAP = false;\n        if (did_set_internal_breakpoints) {\n          t->move_ip_before_breakpoint();\n        }\n        /* We just backed up the $ip, but\n         * rewound it over an |int $3|\n         * instruction, which couldn't have\n         * retired a branch.  So we don't need\n         * to adjust |tick_count()|. */\n        continue;\n      }\n\n      /* Otherwise, either we did an internal singlestep or a hardware\n       * watchpoint fired but values didn't change. */\n      if (trap_reasons.singlestep) {\n        ASSERT(t, is_singlestep(SIGTRAP_run_command));\n        LOG(debug) << \"    (SIGTRAP; stepi'd target $ip)\";\n      } else {\n        ASSERT(t, trap_reasons.watchpoint);\n        LOG(debug) << \"    (SIGTRAP; HW watchpoint fired without changes)\";\n      }\n    }\n\n    /* We had to keep the internal breakpoint set (if it\n     * was when we entered the loop) for the checks above.\n     * But now we're either done (at the target) or about\n     * to resume execution in one of a variety of ways,\n     * and it's simpler to start out knowing that the\n     * breakpoint isn't set. */\n    if (did_set_internal_breakpoints) {\n      t->vm()->remove_breakpoint(ip, BKPT_INTERNAL);\n      if (in_syscallbuf_syscall_hook) {\n        t->vm()->remove_breakpoint(in_syscallbuf_syscall_hook, BKPT_INTERNAL);\n      }\n      did_set_internal_breakpoints = false;\n    }\n    did_set_bpf_breakpoint = false;\n\n    if (at_target) {\n      /* Case (2) above: done. */\n      return COMPLETE;\n    }\n\n    /* At this point, we've proven that we're not at the\n     * target execution point, and we've ensured the\n     * internal breakpoints are unset. */\n    if (USE_BREAKPOINT_TARGET && regs.ip() != t->regs().ip()) {\n      /* Case (4) above: set a breakpoint on the\n       * target $ip and PTRACE_CONT in an attempt to\n       * execute as many non-trapped insns as we\n       * can.  (Unless the debugger is stepping, of\n       * course.)  Trapping and checking\n       * are-we-at-target is slow.  It bears\n       * repeating that the ideal implementation\n       * would be programming a precise counter\n       * interrupt (insns-retired best of all), but\n       * we're forced to be conservative by observed\n       * imprecise counters.  This should still be\n       * no slower than single-stepping our way to\n       * the target execution point. */\n      LOG(debug) << \"    breaking on target $ip\";\n      if (is_x86_string_instruction_at(t, ip) || !t->hpc.accelerate_async_signal(regs)) {\n        t->vm()->add_breakpoint(ip, BKPT_INTERNAL);\n\n        if (in_syscallbuf_syscall_hook) {\n          t->vm()->add_breakpoint(in_syscallbuf_syscall_hook, BKPT_INTERNAL);\n        }\n        did_set_internal_breakpoints = true;\n      } else {\n        did_set_bpf_breakpoint = true;\n      }\n      continue_or_step(t, constraints, RESUME_UNLIMITED_TICKS);\n      SIGTRAP_run_command = constraints.command;\n    } else {\n      /* Case (3) above: we can't put a breakpoint\n       * on the $ip, because resuming execution\n       * would just trap and we'd be back where we\n       * started.  Single-step or fast-forward past it. */\n      LOG(debug) << \"    (fast-forwarding over target $ip)\";\n      /* Just do whatever the user asked for if the user requested\n       * singlestepping\n       * or there is user breakpoint at the run address. The latter is safe\n       * because the breakpoint will be triggered immediately. This gives us the\n       * invariant that an internal singlestep never triggers a user breakpoint.\n       */\n      if (constraints.command == RUN_SINGLESTEP ||\n          t->vm()->get_breakpoint_type_at_addr(t->regs().ip()) == BKPT_USER) {\n        continue_or_step(t, constraints, RESUME_UNLIMITED_TICKS);\n        SIGTRAP_run_command = constraints.command;\n      } else {\n        vector<const Registers*> states = constraints.stop_before_states;\n        // This state may not be relevant if we don't have the correct tick\n        // count yet. But it doesn't hurt to push it on anyway.\n        states.push_back(&regs);\n        fast_forward_status |=\n            fast_forward_through_instruction(t, RESUME_SINGLESTEP, states);\n        SIGTRAP_run_command = RUN_SINGLESTEP_FAST_FORWARD;\n        check_pending_sig(t);\n      }\n    }\n    pending_SIGTRAP = SIGTRAP == t->stop_sig();\n\n    /* Maintain the \"'ticks_left'-is-up-to-date\"\n     * invariant. */\n    ticks_left = ticks - t->tick_count();\n\n    /* Sometimes (e.g. in the ptrace_signal_32 test), we're in almost\n     * the correct state when we enter |advance_to|, except that exotic\n     * registers (i.e. segment registers) need to be normalized by the kernel\n     * by continuing and hitting a deterministic signal without actually\n     * advancing execution. So we allow |advance_to| to proceed and actually\n     * reach the desired state.\n     */\n    if (!is_same_execution_point(t, regs, extra_regs, ticks_left, &mismatched_regs,\n                                 &mismatched_regs_ptr, in_syscallbuf)) {\n      guard_unexpected_signal(t);\n    }\n\n    guard_overshoot(t, regs, ticks, ticks_left, mismatched_regs_ptr);\n  }\n}\n\nstatic bool is_fatal_default_action(int sig) {\n  signal_action action = default_action(sig);\n  return action == DUMP_CORE || action == TERMINATE;\n}\n\n/**\n * Emulates delivery of |sig| to |oldtask|.  Returns INCOMPLETE if\n * emulation was interrupted, COMPLETE if completed.\n */\nCompletion ReplaySession::emulate_signal_delivery(ReplayTask* oldtask) {\n  ReplayTask* t = current_task();\n  if (!t) {\n    // Trace terminated abnormally.  We'll pop out to code\n    // that knows what to do.\n    return INCOMPLETE;\n  }\n  ASSERT(oldtask, t == oldtask) << \"emulate_signal_delivery changed task\";\n\n  const Event& ev = trace_frame.event();\n  ASSERT(t, ev.type() == EV_SIGNAL_DELIVERY || ev.type() == EV_SIGNAL_HANDLER)\n      << \"Unexpected signal disposition\";\n  // Entering a signal handler seems to clear FP/SSE registers for some\n  // reason. So we saved those cleared values, and now we restore that\n  // state so they're cleared during replay.\n  if (ev.type() == EV_SIGNAL_HANDLER) {\n    t->set_extra_regs(trace_frame.extra_regs());\n  }\n\n  /* Restore the signal-hander frame data, if there was one. */\n  t->apply_data_record_from_trace();\n  // Note that fatal signals are not actually injected into the task!\n  // This is very important; we must never actually inject fatal signals\n  // into a task. All replay task death must go through exit_task.\n  /* If this signal had a user handler, and we just set up the\n   * callframe, and we need to restore the $sp for continued\n   * execution. */\n  t->set_regs(trace_frame.regs());\n\n  t->validate_regs();\n  return COMPLETE;\n}\n\nvoid ReplaySession::check_ticks_consistency(ReplayTask* t, const Event& ev) {\n  if (!done_initial_exec()) {\n    return;\n  }\n\n  Ticks ticks_now = t->tick_count();\n  Ticks trace_ticks = trace_frame.ticks();\n\n  ASSERT(t, ticks_now == trace_ticks)\n      << \"ticks mismatch for '\" << ev << \"'; expected \" << trace_ticks\n      << \", got \" << ticks_now << \"\";\n}\n\nstatic bool treat_signal_event_as_deterministic(const SignalEvent& ev) {\n  if (ev.siginfo.si_signo == SIGBUS) {\n    return false;\n  }\n  if (ev.siginfo.si_signo == SIGSEGV && ev.siginfo.si_code == SEGV_PKUERR) {\n    // We don't set up memory protection key state, so pkey-triggered signals\n    // won't happen.\n    return false;\n  }\n  return ev.deterministic == DETERMINISTIC_SIG;\n}\n\n/**\n * Advance to the delivery of the deterministic signal |sig| and\n * update registers to what was recorded.  Return COMPLETE if successful or\n * INCOMPLETE if an unhandled interrupt occurred.\n */\nCompletion ReplaySession::emulate_deterministic_signal(\n    ReplayTask* t, int sig, const StepConstraints& constraints) {\n  const Event& ev = trace_frame.event();\n\n  while (true) {\n    if (t->regs().matches(trace_frame.regs()) &&\n        t->tick_count() == trace_frame.ticks() &&\n        EV_INSTRUCTION_TRAP != ev.type()) {\n      // We're already at the target. This can happen when multiple signals\n      // are delivered with no intervening execution. It *can't* happen\n      // when we're supposed to be emulating an instruction trap.\n      // XXX I guess in theory we could have multiple signals arriving\n      // at the same state but with intervening execution that we're supposed\n      // to replay, but won't :-(.\n      return COMPLETE;\n    }\n\n    auto complete = continue_or_step(t, constraints, RESUME_UNLIMITED_TICKS);\n    if (complete == COMPLETE && !is_ignored_signal(t->stop_sig())) {\n      break;\n    }\n  }\n\n  if (SIGTRAP == t->stop_sig()) {\n    TrapReasons trap_reasons = t->compute_trap_reasons();\n    if (trap_reasons.singlestep || trap_reasons.watchpoint) {\n      // Singlestep or watchpoint must have been debugger-requested\n      return INCOMPLETE;\n    }\n    if (trap_reasons.breakpoint) {\n      // An explicit breakpoint instruction in the tracee would produce a\n      // |breakpoint| reason as we emulate the deterministic SIGTRAP.\n      BreakpointType type =\n          t->vm()->get_breakpoint_type_for_retired_insn(t->ip());\n      if (BKPT_NONE != type) {\n        ASSERT(t, BKPT_USER == type);\n        return INCOMPLETE;\n      }\n    }\n  }\n  ASSERT(t, t->stop_sig() == sig)\n      << \"Replay got unrecorded signal \" << signal_name(t->stop_sig())\n      << \" (expecting \" << signal_name(sig) << \")\"\n      << \"\\n\" << t->get_siginfo();\n  check_ticks_consistency(t, ev);\n\n  if (EV_INSTRUCTION_TRAP == ev.type()) {\n    t->set_regs(trace_frame.regs());\n  }\n\n  return COMPLETE;\n}\n\n/**\n * Restore the recorded syscallbuf data to the tracee, preparing the\n * tracee for replaying the records.\n */\nvoid ReplaySession::prepare_syscallbuf_records(ReplayTask* t, Ticks ticks) {\n  // Read the recorded syscall buffer back into the buffer\n  // region.\n  TraceReader::RawData buf;\n  bool ok = t->trace_reader().read_raw_data_for_frame(buf);\n  size_t hdr_size = syscallbuf_hdr_size();\n  ASSERT(t, ok);\n  ASSERT(t, buf.data.size() >= hdr_size);\n  ASSERT(t, buf.data.size() <= t->syscallbuf_size);\n  ASSERT(t, buf.addr == t->syscallbuf_child.cast<void>());\n\n  struct syscallbuf_hdr recorded_hdr;\n  memcpy(&recorded_hdr, buf.data.data(), hdr_size);\n  // Don't overwrite syscallbuf_hdr. That needs to keep tracking the current\n  // syscallbuf state.\n  t->write_bytes_helper(t->syscallbuf_child.cast<void>() + hdr_size,\n                        buf.data.size() - hdr_size,\n                        buf.data.data() + hdr_size);\n\n  ASSERT(t, recorded_hdr.num_rec_bytes + hdr_size <= t->syscallbuf_size);\n\n  current_step.flush.stop_breakpoint_offset = recorded_hdr.num_rec_bytes / 8;\n  current_step.flush.recorded_ticks = ticks;\n\n  LOG(debug) << \"Prepared \" << (uint32_t)recorded_hdr.num_rec_bytes\n             << \" bytes of syscall records\";\n}\n\n#define PRELOAD_GLOBALS_FIELD_AFTER_SYSCALLBUF_FDS_DISABLED(t, f) \\\n    REMOTE_PTR_FIELD_MINUS_OFFSET(t->preload_globals, f,          \\\n      SYSCALLBUF_FDS_DISABLED_SIZE - t->session().syscallbuf_fds_disabled_size())\n\nstatic string mprotect_record_string(const mprotect_record& record) {\n  stringstream s;\n  s << HEX(record.start) << \",\" << HEX(record.size) << \",\"\n    << prot_flags_string(record.prot);\n  return s.str();\n}\n\n/**\n * Returns mprotect_record_count\n */\nstatic uint32_t apply_mprotect_records(ReplayTask* t,\n                                       uint32_t skip_mprotect_records) {\n  uint32_t final_mprotect_record_count =\n      t->read_mem(REMOTE_PTR_FIELD(t->syscallbuf_child, mprotect_record_count));\n  if (skip_mprotect_records < final_mprotect_record_count) {\n    auto mprotect_records_ptr =\n        PRELOAD_GLOBALS_FIELD_AFTER_SYSCALLBUF_FDS_DISABLED(t, mprotect_records[0]);\n    auto records =\n        t->read_mem(mprotect_records_ptr + skip_mprotect_records,\n                    final_mprotect_record_count - skip_mprotect_records);\n    auto recorded_records =\n        t->current_trace_frame().event().SyscallbufFlush().mprotect_records;\n    uint32_t completed_count = t->read_mem(REMOTE_PTR_FIELD(\n        t->syscallbuf_child, mprotect_record_count_completed));\n    size_t record_index = skip_mprotect_records;\n    for (const auto& r : records) {\n      if (record_index >= completed_count) {\n        auto km = t->vm()->read_kernel_mapping(t, r.start);\n        if (km.prot() != r.prot) {\n          // mprotect didn't happen yet.\n          continue;\n        }\n      } else {\n        auto& recorded_r = recorded_records[record_index];\n        ASSERT(t, r.start == recorded_r.start &&\n               r.size == recorded_r.size &&\n               r.prot == recorded_r.prot)\n          << \"Mismatched mprotect record \" << record_index\n          << \": recorded \" << mprotect_record_string(recorded_r)\n          << \", got \" << mprotect_record_string(r);\n      }\n      t->vm()->protect(t, r.start, r.size, r.prot);\n      if (running_under_rr()) {\n        syscall(SYS_rrcall_mprotect_record, t->tid, (uintptr_t)r.start,\n                (uintptr_t)r.size, r.prot);\n      }\n      ++record_index;\n    }\n  }\n  return final_mprotect_record_count;\n}\n\nstatic void write_breakpoint_value(ReplayTask *t, uint64_t breakpoint_value, uint32_t flags = 0)\n{\n  if (t->session().has_trace_quirk(TraceReader::UsesGlobalsInReplay)) {\n    t->write_mem(\n      PRELOAD_GLOBALS_FIELD_AFTER_SYSCALLBUF_FDS_DISABLED(t, reserved_legacy_breakpoint_value),\n      breakpoint_value, nullptr, flags);\n  } else {\n    t->write_mem(remote_ptr<uint64_t>(RR_PAGE_BREAKPOINT_VALUE),\n      breakpoint_value, nullptr, flags);\n  }\n}\n\ntemplate <typename Arch>\nstatic void maybe_handle_rseq_arch(ReplayTask* t) {\n  auto remote_locals = AddressSpace::preload_thread_locals_start()\n    .cast<preload_thread_locals<Arch>>();\n  if (!remote_locals) {\n    return;\n  }\n  auto rseq_ptr = REMOTE_PTR_FIELD(remote_locals, rseq);\n  auto rseq = t->read_mem(rseq_ptr);\n  if (rseq.len) {\n    t->rseq_state = make_unique<RseqState>(rseq.rseq.rptr(), rseq.sig);\n  }\n}\n\nstatic void maybe_handle_rseq(ReplayTask* t) {\n  RR_ARCH_FUNCTION(maybe_handle_rseq_arch, t->arch(), t);\n}\n\n/**\n * Replay all the syscalls recorded in the interval between |t|'s\n * current execution point and the next non-syscallbuf event (the one\n * that flushed the buffer).  Return COMPLETE if successful or INCOMPLETE if an\n * unhandled interrupt occurred.\n */\nCompletion ReplaySession::flush_syscallbuf(ReplayTask* t,\n                                           const StepConstraints& constraints) {\n  bool legacy_breakpoint_mode = t->vm()->legacy_breakpoint_mode();\n  bool user_breakpoint_at_addr = false;\n  remote_code_ptr remote_brkpt_addr;\n  while (true) {\n    auto next_rec = t->next_syscallbuf_record();\n    uint32_t skip_mprotect_records = t->read_mem(\n        REMOTE_PTR_FIELD(t->syscallbuf_child, mprotect_record_count_completed));\n\n    TicksRequest ticks_request;\n    if (!compute_ticks_request(t, constraints, &ticks_request)) {\n      return INCOMPLETE;\n    }\n\n    // We don't use this in new traces, but we retain this for replayability\n    if (legacy_breakpoint_mode) {\n      remote_brkpt_addr =\n        t->vm()->stopping_breakpoint_table().to_data_ptr<void>().as_int() +\n          current_step.flush.stop_breakpoint_offset *\n            t->vm()->stopping_breakpoint_table_entry_size();\n      bool added = t->vm()->add_breakpoint(remote_brkpt_addr, BKPT_INTERNAL);\n      ASSERT(t, added);\n    } else {\n      LOG(debug) << \"Adding breakpoint\";\n      write_breakpoint_value(t,\n        (uint64_t)current_step.flush.stop_breakpoint_offset);\n    }\n\n    auto complete =\n        continue_or_step(t, constraints, ticks_request, RESUME_CONT);\n\n    if (legacy_breakpoint_mode) {\n      user_breakpoint_at_addr =\n          t->vm()->get_breakpoint_type_at_addr(remote_brkpt_addr) != BKPT_INTERNAL;\n      t->vm()->remove_breakpoint(remote_brkpt_addr,\n                                 BKPT_INTERNAL);\n    } else {\n      LOG(debug) << \"Removing breakpoint \" << t->status();\n      write_breakpoint_value(t, (uint64_t)-1);\n    }\n\n    // Account for buffered syscalls just completed\n    auto end_rec = t->next_syscallbuf_record();\n    while (next_rec != end_rec) {\n      accumulate_syscall_performed();\n      next_rec = next_rec.as_int() + t->stored_record_size(next_rec);\n    }\n\n    // Apply the mprotect records we just completed.\n    apply_mprotect_records(t, skip_mprotect_records);\n\n    if (complete == INCOMPLETE && t->stop_sig() == SIGTRAP) {\n      do_replay_assist(t);\n    }\n\n    if (t->stop_sig() == PerfCounters::TIME_SLICE_SIGNAL) {\n      // This would normally be triggered by constraints.ticks_target but it's\n      // also possible to get stray signals here.\n      return INCOMPLETE;\n    }\n\n    if (complete == COMPLETE && !is_ignored_signal(t->stop_sig())) {\n      break;\n    }\n  }\n\n  if (legacy_breakpoint_mode) {\n    ASSERT(t, t->stop_sig() == SIGTRAP)\n        << \"Replay got unexpected signal (or none) \" << t->stop_sig();\n    if (t->ip().undo_executed_bkpt(t->arch()) ==\n            remote_code_ptr(remote_brkpt_addr) &&\n        !user_breakpoint_at_addr) {\n      Registers r = t->regs();\n      r.set_ip(remote_brkpt_addr);\n      t->set_regs(r);\n    } else {\n      return INCOMPLETE;\n    }\n  } else {\n    if (t->stop_sig() == SIGTRAP) {\n      return INCOMPLETE;\n    }\n\n    Registers r = t->regs();\n    ASSERT(t, t->stop_sig() == SIGSEGV && r.ip() == t->vm()->do_breakpoint_fault_addr())\n        << \"Replay got unexpected signal (or none) \" << t->stop_sig()\n        << \" ip \" << r.ip() << \" breakpoint_fault_addr \" << t->vm()->do_breakpoint_fault_addr();\n    r.set_ip(r.ip().increment_by_movrm_insn_length(t->arch()));\n    t->set_regs(r);\n\n    if (current_step.flush.recorded_ticks <= t->tick_count() && has_trace_quirk(TraceReader::BufferedSyscallForcedTick)) {\n      // We've reached the breakpoint and executed at least as many ticks as were recorded for the FLUSH_SYSCALLBUF.\n      // That means the flush was actually performed before we left the syscallbuf code, i.e. due to a SIGKILL\n      // in syscallbuf code. We will have recorded another execution event that triggered a flush, but just ignore it,\n      // since we probably already passed it and this task is about to die anyway.\n      skip_next_execution_event = true;\n    }\n  }\n\n  maybe_handle_rseq(t);\n  t->apply_all_data_records_from_trace();\n  return COMPLETE;\n}\n\nCompletion ReplaySession::patch_ip(ReplayTask* t, const StepConstraints& constraints)\n{\n  TicksRequest ticks_request;\n  if (!compute_ticks_request(t, constraints, &ticks_request)) {\n    return INCOMPLETE;\n  }\n\n  remote_code_ptr vsyscall_entry = current_trace_frame().regs().ip();\n  bool added = t->vm()->add_breakpoint(vsyscall_entry, BKPT_INTERNAL);\n  ASSERT(t, added);\n  auto complete = continue_or_step(t, constraints, ticks_request, RESUME_CONT);\n  TrapReasons reasons;\n  if (complete == COMPLETE && t->stop_sig() == SIGTRAP) {\n    reasons = t->compute_trap_reasons();\n  }\n  t->vm()->remove_breakpoint(vsyscall_entry, BKPT_INTERNAL);\n\n  if (complete == INCOMPLETE) {\n    return complete;\n  }\n\n  if (t->stop_sig() == PerfCounters::TIME_SLICE_SIGNAL) {\n    // This would normally be triggered by constraints.ticks_target but it's\n    // also possible to get stray signals here.\n    return INCOMPLETE;\n  }\n\n  ASSERT(t, t->stop_sig() == SIGTRAP)\n      << \"Replay got unexpected signal (or none) \" << t->stop_sig();\n  if (!reasons.breakpoint || t->ip().undo_executed_bkpt(t->arch()) != vsyscall_entry) {\n    return INCOMPLETE;\n  }\n\n  apply_patch_data(t);\n  Registers r = t->regs();\n  r.set_ip(vsyscall_entry);\n  t->set_regs(r);\n  return COMPLETE;\n}\n\nvoid ReplaySession::apply_patch_data(ReplayTask* t) {\n  // All patching effects have been recorded to the trace.\n  // First, replay any memory mapping done by Monkeypatcher. There should be\n  // at most one but we might as well be general.\n  while (true) {\n    TraceReader::MappedData data;\n    bool found;\n    KernelMapping km = t->trace_reader().read_mapped_region(&data, &found);\n    if (!found) {\n      break;\n    }\n    AutoRemoteSyscalls remote(t);\n    ASSERT(t, km.flags() & MAP_ANONYMOUS);\n    remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),\n                                            km.flags() | MAP_FIXED, -1, 0);\n    t->vm()->map(t, km.start(), km.size(), km.prot(), km.flags(), 0, string(),\n                 KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,\n                 &km);\n    t->vm()->mapping_flags_of(km.start()) |=\n        AddressSpace::Mapping::IS_PATCH_STUBS;\n  }\n\n  // Now replay all data records.\n  t->apply_all_data_records_from_trace();\n}\n\nCompletion ReplaySession::patch_next_syscall(\n    ReplayTask* t, const StepConstraints& constraints, bool before_syscall) {\n  if (before_syscall) {\n    if (cont_syscall_boundary(t, constraints) == INCOMPLETE) {\n      return INCOMPLETE;\n    }\n\n    t->canonicalize_regs(t->arch());\n    t->exit_syscall_and_prepare_restart(t->arch());\n  }\n  apply_patch_data(t);\n  return COMPLETE;\n}\n\n/**\n * Return true if replaying |ev| by running |step| should result in\n * the target task having the same ticks value as it did during\n * recording.\n */\nstatic bool has_deterministic_ticks(const Event& ev,\n                                    const ReplayTraceStep& step) {\n  if (ev.has_ticks_slop()) {\n    return false;\n  }\n  // We won't necessarily reach the same ticks when replaying an\n  // async signal, due to debugger interrupts and other\n  // implementation details.  This is checked in |advance_to()|\n  // anyway.\n  return TSTEP_PROGRAM_ASYNC_SIGNAL_INTERRUPT != step.action;\n}\n\nvoid ReplaySession::check_approaching_ticks_target(\n    ReplayTask* t, const StepConstraints& constraints,\n    BreakStatus& break_status) {\n  if (constraints.ticks_target > 0) {\n    Ticks ticks_left = constraints.ticks_target - t->tick_count();\n    if (ticks_left <= t->hpc.skid_size()) {\n      break_status.approaching_ticks_target = true;\n    }\n  }\n}\n\nCompletion ReplaySession::advance_to_ticks_target(\n    ReplayTask* t, const StepConstraints& constraints) {\n  while (true) {\n    TicksRequest ticks_request;\n    if (!compute_ticks_request(t, constraints, &ticks_request)) {\n      return INCOMPLETE;\n    }\n    continue_or_step(t, constraints, ticks_request);\n    if (SIGTRAP == t->stop_sig()) {\n      return INCOMPLETE;\n    }\n  }\n}\n\n/**\n * Try to execute |step|, adjusting for |req| if needed.  Return COMPLETE if\n * |step| was made, or INCOMPLETE if there was a trap or |step| needs\n * more work.\n */\nCompletion ReplaySession::try_one_trace_step(\n    ReplayTask* t, const StepConstraints& constraints) {\n  if (constraints.ticks_target > 0 && !trace_frame.event().has_ticks_slop() &&\n      current_trace_frame().ticks() > constraints.ticks_target) {\n    // Instead of doing this step, just advance to the ticks_target, since\n    // that happens before this event completes.\n    // Unfortunately we can't do this for TSTEP_FLUSH_SYSCALLBUF\n    // because its tick count can't be trusted.\n    // cont_syscall_boundary handles the ticks constraint for those cases.\n    return advance_to_ticks_target(t, constraints);\n  }\n\n  switch (current_step.action) {\n    case TSTEP_RETIRE:\n      return COMPLETE;\n    case TSTEP_ENTER_SYSCALL:\n      return enter_syscall(t, constraints);\n    case TSTEP_EXIT_SYSCALL:\n      return exit_syscall(t);\n    case TSTEP_DETERMINISTIC_SIGNAL:\n      return emulate_deterministic_signal(t, current_step.target.signo,\n                                          constraints);\n    case TSTEP_PROGRAM_ASYNC_SIGNAL_INTERRUPT: {\n      Completion completion = emulate_async_signal(t, constraints, current_step.target.ticks, current_step.target.in_syscallbuf_syscall_hook);\n      if (completion == COMPLETE) {\n        remote_code_ptr rseq_new_ip = t->ip();\n        bool invalid_rseq_cs;\n        if (t->should_apply_rseq_abort(current_trace_frame().event().type(), &rseq_new_ip, &invalid_rseq_cs)\n            && t->ip() != rseq_new_ip) {\n          Registers r = t->regs();\n          r.set_ip(rseq_new_ip);\n          t->set_regs(r);\n        }\n        t->apply_all_data_records_from_trace();\n      }\n      return completion;\n    }\n    case TSTEP_DELIVER_SIGNAL:\n      return emulate_signal_delivery(t);\n    case TSTEP_FLUSH_SYSCALLBUF:\n      return flush_syscallbuf(t, constraints);\n    case TSTEP_PATCH_IP:\n      return patch_ip(t, constraints);\n    case TSTEP_PATCH_SYSCALL:\n      return patch_next_syscall(t, constraints, true);\n    case TSTEP_PATCH_AFTER_SYSCALL:\n      return patch_next_syscall(t, constraints, false);\n    case TSTEP_EXIT_TASK:\n      return exit_task(t);\n    default:\n      FATAL() << \"Unhandled step type \" << current_step.action;\n      return COMPLETE;\n  }\n}\n\n/**\n * Task death during replay always goes through here (except for\n * Session::kill_all_tasks when we forcibly kill all tasks in the session at\n * once). |exit| and |exit_group| syscalls are both emulated so the real\n * task doesn't die until we reach the EXIT events in the trace.\n * This ensures the real tasks are alive and available as long as our Task\n * object exists, which simplifies code like Session cloning.\n *\n * Killing tasks with fatal signals doesn't work because a fatal signal will\n * try to kill all the tasks in the thread group. Instead we inject an |exit|\n * syscall, which is apparently the only way to kill one specific thread.\n */\nstatic void end_task(ReplayTask* t) {\n  ASSERT(t, t->ptrace_event() != PTRACE_EVENT_EXIT);\n\n  t->destroy_buffers();\n\n  Registers r = t->regs();\n  remote_code_ptr syscall_ip = t->vm()->privileged_traced_syscall_ip();\n  if (!syscall_ip) {\n    // Fall back to unprivileged. If someone uses a seccomp policy to\n    // block `exit` *and* unmaps the rr page, they lose.\n    syscall_ip = t->vm()->traced_syscall_ip();\n  }\n  r.set_ip(syscall_ip);\n  r.set_syscallno(syscall_number_for_exit(t->arch()));\n  t->set_regs(r);\n  // Enter the syscall.\n  bool ok = t->resume_execution(RESUME_CONT, RESUME_WAIT, RESUME_NO_TICKS);\n  ASSERT(t, ok) << \"Tracee died unexpectedly\";\n  if (t->session().done_initial_exec()) {\n    ASSERT(t, t->ptrace_event() == PTRACE_EVENT_EXIT);\n    t->did_handle_ptrace_exit_event();\n  } else {\n    // If we never execed, the trace is totally hosed,\n    // just clean up.\n    t->did_kill();\n  }\n  t->detach();\n  delete t;\n}\n\nCompletion ReplaySession::exit_task(ReplayTask* t) {\n  ASSERT(t, !t->seen_ptrace_exit_event());\n  // Apply robust-futex updates captured during recording.\n  t->apply_all_data_records_from_trace();\n  end_task(t);\n  /* |t| is dead now. */\n  return COMPLETE;\n}\n\nReplayTask* ReplaySession::revive_task_for_exec() {\n  const Event& ev = trace_frame.event();\n  if (!ev.is_syscall_event() || !ev.Syscall().is_exec()) {\n    FATAL() << \"Can't find task, but we're not in an execve\";\n  }\n\n  ThreadGroup* tg = nullptr;\n  for (auto& p : thread_group_map_) {\n    if (p.second->tgid == trace_frame.tid()) {\n      tg = p.second;\n      break;\n    }\n  }\n  if (!tg) {\n    FATAL()\n        << \"Dead task tid should be task-group leader, but we can't find it\";\n  }\n  if (tg->task_set().size() != 1) {\n    FATAL() << \"Should only be one task left in the taskgroup\";\n  }\n\n  ReplayTask* t = static_cast<ReplayTask*>(*tg->task_set().begin());\n  LOG(debug) << \"Changing task tid from \" << t->rec_tid << \" to \"\n             << trace_frame.tid();\n  task_map.erase(t->rec_tid);\n  t->rec_tid = trace_frame.tid();\n  t->serial = next_task_serial();\n  task_map.insert(make_pair(t->rec_tid, t));\n  // The real tid is not changing yet. It will, in process_execve.\n  return t;\n}\n\n/**\n * Set up rep_trace_step state in t's Session to start replaying towards\n * the event given by the session's current_trace_frame --- but only if\n * it's not already set up.\n * Return true if we should continue replaying, false if the debugger\n * requested a restart. If this returns false, t's Session state was not\n * modified.\n */\nReplayTask* ReplaySession::setup_replay_one_trace_frame(ReplayTask* t) {\n  const Event& ev = trace_frame.event();\n\n  if (!t) {\n    t = revive_task_for_exec();\n  }\n\n  if (t->tuid() != last_task_tuid) {\n    t->will_schedule();\n    last_task_tuid = t->tuid();\n  }\n\n  LOG(debug) << \"[event \" << trace_frame.time() << \"] \" << t->rec_tid\n             << \": replaying \" << Event(ev) << \"; state \"\n             << (ev.is_syscall_event() ? state_name(ev.Syscall().state)\n                                       : \" (none)\");\n  if (t->syscallbuf_child) {\n    LOG(debug) << \"    (syscllbufsz:\"\n               << (uint32_t)t->read_mem(\n                      REMOTE_PTR_FIELD(t->syscallbuf_child, num_rec_bytes))\n               << \", abrtcmt:\" << bool(t->read_mem(REMOTE_PTR_FIELD(\n                                      t->syscallbuf_child, abort_commit)))\n               << \", locked:\" << bool(t->read_mem(REMOTE_PTR_FIELD(\n                                     t->syscallbuf_child, locked)))\n               << \")\";\n  }\n\n  /* Ask the trace-interpretation code what to do next in order\n   * to retire the current frame. */\n  memset(&current_step, 0, sizeof(current_step));\n\n  switch (ev.type()) {\n    case EV_EXIT:\n      current_step.action = TSTEP_EXIT_TASK;\n      break;\n    case EV_SYSCALLBUF_ABORT_COMMIT:\n      t->write_mem(REMOTE_PTR_FIELD(t->syscallbuf_child, abort_commit),\n                   (uint8_t)1);\n      t->apply_all_data_records_from_trace();\n      current_step.action = TSTEP_RETIRE;\n      break;\n    case EV_SYSCALLBUF_FLUSH:\n      current_step.action = TSTEP_FLUSH_SYSCALLBUF;\n      prepare_syscallbuf_records(t, trace_frame.ticks());\n      break;\n    case EV_SYSCALLBUF_RESET:\n      // Reset syscallbuf_hdr->num_rec_bytes and zero out the recorded data.\n      // Zeroing out the data is important because we only save and restore\n      // the recorded data area when making checkpoints. We want the checkpoint\n      // to have the same syscallbuf contents as its original, i.e. zero outside\n      // the recorded data area. This is important because stray reads such\n      // as those performed by return_addresses should be consistent.\n      t->reset_syscallbuf();\n      current_step.action = TSTEP_RETIRE;\n      break;\n    case EV_PATCH_SYSCALL:\n      if (ev.PatchSyscall().patch_after_syscall) {\n        current_step.action = TSTEP_PATCH_AFTER_SYSCALL;\n      } else if (ev.PatchSyscall().patch_trapping_instruction ||\n                 ev.PatchSyscall().patch_vsyscall) {\n        current_step.action = TSTEP_PATCH_IP;\n      } else {\n        current_step.action = TSTEP_PATCH_SYSCALL;\n      }\n      break;\n    case EV_SCHED:\n      if (skip_next_execution_event) {\n        current_step.action = TSTEP_NONE;\n        break;\n      }\n      current_step.action = TSTEP_PROGRAM_ASYNC_SIGNAL_INTERRUPT;\n      current_step.target.ticks = trace_frame.ticks();\n      current_step.target.signo = 0;\n      current_step.target.in_syscallbuf_syscall_hook = ev.Sched().in_syscallbuf_syscall_hook.register_value();\n      if (current_step.target.in_syscallbuf_syscall_hook) {\n        t->note_sched_in_syscallbuf_syscall_hook();\n      }\n      break;\n    case EV_INSTRUCTION_TRAP:\n      current_step.action = TSTEP_DETERMINISTIC_SIGNAL;\n      current_step.target.ticks = -1;\n      current_step.target.signo = SIGSEGV;\n      current_step.target.in_syscallbuf_syscall_hook = 0;\n      break;\n    case EV_GROW_MAP:\n      process_grow_map(t);\n      current_step.action = TSTEP_RETIRE;\n      break;\n    case EV_SIGNAL: {\n      if (skip_next_execution_event) {\n        current_step.action = TSTEP_NONE;\n        break;\n      }\n      last_siginfo_ = ev.Signal().siginfo;\n      if (treat_signal_event_as_deterministic(ev.Signal())) {\n        current_step.action = TSTEP_DETERMINISTIC_SIGNAL;\n        current_step.target.signo = ev.Signal().siginfo.si_signo;\n        current_step.target.ticks = -1;\n      } else {\n        current_step.action = TSTEP_PROGRAM_ASYNC_SIGNAL_INTERRUPT;\n        current_step.target.signo = ev.Signal().siginfo.si_signo;\n        current_step.target.ticks = trace_frame.ticks();\n      }\n      current_step.target.in_syscallbuf_syscall_hook = 0;\n      break;\n    }\n    case EV_SIGNAL_DELIVERY:\n    case EV_SIGNAL_HANDLER:\n      current_step.action = TSTEP_DELIVER_SIGNAL;\n      current_step.target.signo = ev.Signal().siginfo.si_signo;\n      current_step.target.in_syscallbuf_syscall_hook = 0;\n      break;\n    case EV_SYSCALL:\n      if (skip_next_execution_event) {\n        current_step.action = TSTEP_NONE;\n        break;\n      }\n      if (trace_frame.event().Syscall().state == ENTERING_SYSCALL ||\n          trace_frame.event().Syscall().state == ENTERING_SYSCALL_PTRACE) {\n        rep_prepare_run_to_syscall(t, &current_step);\n      } else {\n        rep_process_syscall(t, &current_step);\n        if (current_step.action == TSTEP_RETIRE) {\n          t->on_syscall_exit(current_step.syscall.number,\n                             current_step.syscall.arch, trace_frame.regs());\n          if (t->arch() == aarch64 && t->regs().syscall_may_restart()) {\n            // If we're restarting a system call, we may have to apply register\n            // modifications to match what the kernel does. Whether or not we need\n            // to do this depends on the ordering of the kernel's register\n            // modification and the signal stop that interrupted the system\n            // call. On x86, the ptrace stop happens first, and then all\n            // register modifications happen. On aarch64, some register\n            // modifications happen [1], then the ptrace stop and then\n            // potentially more register modifications. Any register\n            // modifications that happen after the ptrace signal stop will\n            // get recorded in the signal frame and thus don't need any\n            // special handling. However, for register modifications that\n            // happen before the signal stop, we need to apply them here.\n            // On x86, there are none, but on aarch64, we need to restore arg1\n            // and pc.\n            // [1] https://github.com/torvalds/linux/blob/caffb99b6929f41a69edbb5aef3a359bf45f3315/arch/arm64/kernel/signal.c#L855-L862\n            Registers r = t->regs();\n            r.set_arg1(r.orig_arg1());\n            r.set_ip(r.ip().decrement_by_syscall_insn_length(t->arch()));\n            t->set_regs(r);\n          }\n        }\n      }\n      break;\n    default:\n      FATAL() << \"Unexpected event \" << ev;\n  }\n\n  skip_next_execution_event = false;\n  return t;\n}\n\nbool ReplaySession::next_step_is_successful_exec_syscall_exit() {\n  const Event& ev = trace_frame.event();\n  return current_step.action == TSTEP_NONE &&\n         ev.is_syscall_event() &&\n         ev.Syscall().is_exec() &&\n         ev.Syscall().state == EXITING_SYSCALL &&\n         !trace_frame.regs().syscall_failed();\n}\n\nReplayResult ReplaySession::replay_step(const StepConstraints& constraints) {\n  finish_initializing();\n\n  ReplayResult result(REPLAY_CONTINUE);\n  if (detected_transient_error_) {\n    result.status = REPLAY_TRANSIENT_ERROR;\n    return result;\n  }\n\n  if (EV_TRACE_TERMINATION == trace_frame.event().type()) {\n    result.status = REPLAY_EXITED;\n    return result;\n  }\n\n  /* If we restored from a checkpoint, the steps might have been\n   * computed already in which case step.action will not be TSTEP_NONE.\n   */\n  ReplayTask* t = current_task();\n  if (current_step.action == TSTEP_NONE) {\n    t = setup_replay_one_trace_frame(t);\n    if (current_step.action == TSTEP_NONE) {\n      // Already at the destination event.\n      advance_to_next_trace_frame();\n    }\n    if (current_step.action == TSTEP_EXIT_TASK) {\n      result.break_status.task_context = TaskContext(t);\n      result.break_status.task_exit = true;\n    }\n    return result;\n  }\n\n  fast_forward_status = FastForwardStatus();\n\n  // Now we know |t| hasn't died, so save it in break_status.\n  result.break_status.task_context = TaskContext(t);\n\n  /* Advance towards fulfilling |current_step|. */\n  Completion complete = try_one_trace_step(t, constraints);\n  if (detected_transient_error_) {\n    result.status = REPLAY_TRANSIENT_ERROR;\n    return result;\n  }\n  if (complete == INCOMPLETE) {\n    if (EV_TRACE_TERMINATION == trace_frame.event().type()) {\n      // An irregular trace step had to read the\n      // next trace frame, and that frame was an\n      // early-termination marker.  Otherwise we\n      // would have seen the marker above.\n      result.status = REPLAY_EXITED;\n      return result;\n    }\n\n    // We got INCOMPLETE because there was some kind of debugger trap or\n    // we got close to ticks_target.\n    result.break_status = diagnose_debugger_trap(t, constraints.command);\n    ASSERT(t, !result.break_status.signal)\n        << \"Expected either SIGTRAP at $ip \" << t->ip()\n        << \" or USER breakpoint just after it\";\n    ASSERT(t,\n           !result.break_status.singlestep_complete ||\n               constraints.is_singlestep());\n\n    check_approaching_ticks_target(t, constraints, result.break_status);\n    result.did_fast_forward = fast_forward_status.did_fast_forward;\n    result.incomplete_fast_forward = fast_forward_status.incomplete_fast_forward;\n    return result;\n  }\n\n  result.did_fast_forward = fast_forward_status.did_fast_forward;\n  result.incomplete_fast_forward = fast_forward_status.incomplete_fast_forward;\n\n  // If try_one_trace_step set extra-registers already, the values it used from the frame\n  // will already have FIP/FDP cleared if necessary. Clearing them again here is fine.\n  if (trace_reader().clear_fip_fdp() &&\n      current_step.action != TSTEP_EXIT_TASK)\n      /* TSTEP_EXIT_TASK means the task object got already\n         deleted above in try_one_trace_step/exit_task/end_task. */\n  {\n    const ExtraRegisters* maybe_extra = t->extra_regs_fallible();\n    if (maybe_extra) {\n      ExtraRegisters extra_registers = *maybe_extra;\n      extra_registers.clear_fip_fdp();\n      t->set_extra_regs(extra_registers);\n    }\n  }\n\n  switch (current_step.action) {\n    case TSTEP_DETERMINISTIC_SIGNAL:\n    case TSTEP_PROGRAM_ASYNC_SIGNAL_INTERRUPT:\n      if (current_step.target.signo) {\n        if (trace_frame.event().type() != EV_INSTRUCTION_TRAP) {\n          ASSERT(t, current_step.target.signo == last_siginfo_.si_signo);\n          result.break_status.signal =\n              unique_ptr<siginfo_t>(new siginfo_t(last_siginfo_));\n        }\n        if (constraints.is_singlestep()) {\n          result.break_status.singlestep_complete = true;\n        }\n      }\n      break;\n    case TSTEP_DELIVER_SIGNAL:\n      // When we deliver a terminating signal, do not let the singlestep\n      // complete; proceed on to report our synthetic SIGKILL or task death.\n      if (constraints.is_singlestep() &&\n          !(trace_frame.event().type() == EV_SIGNAL_DELIVERY &&\n            is_fatal_default_action(current_step.target.signo))) {\n        result.break_status.singlestep_complete = true;\n      }\n      break;\n    case TSTEP_EXIT_TASK:\n      result.break_status.task_context = TaskContext();\n      t = nullptr;\n      DEBUG_ASSERT(!result.break_status.any_break());\n      break;\n    case TSTEP_ENTER_SYSCALL:\n      cpuid_bug_detector.notify_reached_syscall_during_replay(t);\n      break;\n    case TSTEP_EXIT_SYSCALL:\n      if (constraints.is_singlestep()) {\n        result.break_status.singlestep_complete = true;\n      }\n      break;\n    default:\n      break;\n  }\n\n  if (t) {\n    const Event& ev = trace_frame.event();\n    if (done_initial_exec() && ev.is_syscall_event() &&\n        rr::Flags::get().check_cached_mmaps) {\n      t->vm()->verify(t);\n    }\n\n    if (has_deterministic_ticks(ev, current_step)) {\n      check_ticks_consistency(t, ev);\n    }\n\n    debug_memory(t);\n    check_intel_pt_if_enabled(t);\n\n    check_for_watchpoint_changes(t, result.break_status);\n    check_approaching_ticks_target(t, constraints, result.break_status);\n  }\n\n  advance_to_next_trace_frame();\n  // Record that this step completed successfully.\n  current_step.action = TSTEP_NONE;\n\n  ReplayTask* next_task = current_task();\n  if (next_task && done_initial_exec()) {\n    if (!next_task->vm()->first_run_event()) {\n      next_task->vm()->set_first_run_event(trace_frame.time());\n    }\n    if (!next_task->thread_group()->first_run_event()) {\n      next_task->thread_group()->set_first_run_event(trace_frame.time());\n    }\n  }\n  if (next_task) {\n    ticks_at_start_of_event = next_task->tick_count();\n  }\n\n  return result;\n}\n\nReplayTask* ReplaySession::find_task(pid_t rec_tid) const {\n  return static_cast<ReplayTask*>(Session::find_task(rec_tid));\n}\n\nReplayTask* ReplaySession::find_task(const TaskUid& tuid) const {\n  return static_cast<ReplayTask*>(Session::find_task(tuid));\n}\n\ndouble ReplaySession::get_trace_start_time(){\n  return trace_start_time;\n}\n\nvoid ReplaySession::prepare_to_detach_tasks() {\n  finish_initializing();\n\n  for (auto& entry : task_map) {\n    Task* t = entry.second;\n    t->flush_regs();\n  }\n}\n\nvoid ReplaySession::forget_tasks() {\n  while (!task_map.empty()) {\n    Task* t = task_map.begin()->second;\n    t->forget();\n    delete t;\n  }\n  while (!vm_map.empty()) {\n    AddressSpace* a = vm_map.begin()->second;\n    delete a;\n  }\n}\n\nvoid ReplaySession::detach_tasks(pid_t new_ptracer, ScopedFd& new_tracee_socket_receiver) {\n  // First tell Yama to let new_ptracer ptrace the tracees.\n  // Do this before sending SIGSTOP to any tracees because SIGSTOP\n  // might stop threads before we do their PR_SET_PTRACER.\n  // Also push the new control socket into all tracees.\n  for (auto& entry : task_map) {\n    Task* t = entry.second;\n    AutoRemoteSyscalls remote(t);\n    long ret = remote.syscall(syscall_number_for_prctl(t->arch()), PR_SET_PTRACER, new_ptracer);\n    ASSERT(t, ret >= 0 || ret == -EINVAL) << \"Failed PR_SET_PTRACER\";\n    remote.infallible_send_fd_dup(new_tracee_socket_receiver, tracee_socket_fd_number, 0);\n  }\n  // Now PTRACE_DETACH and stop them all with SIGSTOP.\n  for (auto& entry : task_map) {\n    Task* t = entry.second;\n    t->flush_regs();\n    errno = 0;\n    t->fallible_ptrace(PTRACE_DETACH, nullptr, (void*)SIGSTOP);\n    ASSERT(t, !errno) << \"failed to detach, with errno \" << errno;\n  }\n  forget_tasks();\n}\n\nvoid ReplaySession::reattach_tasks(ScopedFd new_tracee_socket, ScopedFd new_tracee_socket_receiver) {\n  tracee_socket = make_shared<ScopedFd>(std::move(new_tracee_socket));\n  tracee_socket_receiver = make_shared<ScopedFd>(std::move(new_tracee_socket_receiver));\n  // Seize all tasks.\n  for (auto& entry : task_map) {\n    Task* t = entry.second;\n    long ret = Task::ptrace_seize(t->tid, *this);\n    ASSERT(t, ret >= 0) << \"Failed to PTRACE_SEIZE\";\n  }\n  // Get stop events for all tasks\n  for (auto& entry : task_map) {\n    Task* t = entry.second;\n    if (!t->wait()) {\n      FATAL() << \"Task \" << t->tid << \" killed unexpectedly\";\n    }\n    WaitStatus status = t->status();\n    // Normally the SIGSTOP from detach_tasks() will have been delivered to the tracee\n    // while it was detached, putting it into a group stop, so we'll see the group stop\n    // status here. However it is possible for the SIGSTOP to be queued but not delivered\n    // because the tracee hasn't been scheduled yet. In that case we might see the\n    // SIGSTOP signal stop here instead.\n    if (status.group_stop() != SIGSTOP && status.stop_sig() != SIGSTOP) {\n      FATAL() << \"Unexpected stop \" << status << \" for \" << t->tid;\n    }\n    t->clear_wait_status();\n    t->open_mem_fd();\n  }\n}\n\nbool ReplaySession::mark_stdio() const {\n  return Session::mark_stdio() &&\n    current_frame_time() >= suppress_stdio_before_event_;\n}\n\nbool ReplaySession::echo_stdio() const {\n  return flags().redirect_stdio && visible_execution_ &&\n    current_frame_time() >= suppress_stdio_before_event_;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ReplaySession.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REPLAY_SESSION_H_\n#define RR_REPLAY_SESSION_H_\n\n#include <memory>\n#include <ostream>\n#include <set>\n\n#include \"AddressSpace.h\"\n#include \"CPUIDBugDetector.h\"\n#include \"DiversionSession.h\"\n#include \"TraceStream.h\"\n#include \"EmuFs.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n#include \"fast_forward.h\"\n\nstruct syscallbuf_hdr;\n\nnamespace rr {\n\nclass ReplayTask;\n\n/**\n * ReplayFlushBufferedSyscallState is saved in Session and cloned with its\n * Session, so it needs to be simple data, i.e. not holding pointers to\n * per-Session data.\n */\nstruct ReplayFlushBufferedSyscallState {\n  /* The offset in the syscallbuf (in 8-byte units) at which we want to stop */\n  uintptr_t stop_breakpoint_offset;\n  /* This includes slop */\n  Ticks recorded_ticks;\n};\n\n/**\n * Describes the next step to be taken in order to replay a trace\n * frame.\n */\nenum ReplayTraceStepType {\n  TSTEP_NONE,\n\n  /* Enter/exit a syscall.  |syscall| describe what should be\n   * done at entry/exit. */\n  TSTEP_ENTER_SYSCALL,\n  TSTEP_EXIT_SYSCALL,\n\n  /* Advance to the deterministic signal |signo|. */\n  TSTEP_DETERMINISTIC_SIGNAL,\n\n  /* Advance until |target.ticks| have been retired and then\n   * |target.ip| is reached. */\n  TSTEP_PROGRAM_ASYNC_SIGNAL_INTERRUPT,\n\n  /* Deliver signal |signo|. */\n  TSTEP_DELIVER_SIGNAL,\n\n  /* Replay the upcoming buffered syscalls.  |flush| tracks the\n   * replay state.*/\n  TSTEP_FLUSH_SYSCALLBUF,\n\n  /* Replay until we enter the next syscall, then patch it. */\n  TSTEP_PATCH_SYSCALL,\n\n  /* Replay until we exit the next syscall, then patch it. */\n  TSTEP_PATCH_AFTER_SYSCALL,\n\n  /* Replay until we hit the ip recorded in the event, then patch the site. */\n  TSTEP_PATCH_IP,\n\n  /* Exit the task */\n  TSTEP_EXIT_TASK,\n\n  /* Frame has been replayed, done. */\n  TSTEP_RETIRE,\n};\n\n/**\n * rep_trace_step is saved in Session and cloned with its Session, so it needs\n * to be simple data, i.e. not holding pointers to per-Session data.\n */\nstruct ReplayTraceStep {\n  ReplayTraceStepType action;\n\n  union {\n    struct {\n      /* The architecture of the syscall */\n      SupportedArch arch;\n      /* The syscall number we expect to\n       * enter/exit. */\n      int number;\n    } syscall;\n\n    struct {\n      Ticks ticks;\n      int signo;\n      // Not remote_code_ptr because this has to have plain data\n      uint64_t in_syscallbuf_syscall_hook;\n    } target;\n\n    ReplayFlushBufferedSyscallState flush;\n  };\n};\n\nenum ReplayStatus {\n  // Some execution was replayed. replay_step() can be called again.\n  REPLAY_CONTINUE,\n  // All tracees are dead. replay_step() should not be called again.\n  REPLAY_EXITED,\n  // Replay failed and this session is dead, but trying again with a\n  // new session might work.\n  REPLAY_TRANSIENT_ERROR,\n};\n\nstruct ReplayResult {\n  ReplayResult(ReplayStatus status = REPLAY_CONTINUE)\n      : status(status), did_fast_forward(false), incomplete_fast_forward(false) {}\n  ReplayStatus status;\n  BreakStatus break_status;\n  // True if we did a fast-forward operation, in which case\n  // break_status.singlestep_complete might indicate the completion of more\n  // than one instruction.\n  bool did_fast_forward;\n  // True if we fast-forward-singlestepped a string instruction but it has at least\n  // one iteration to go. did_fast_forward may be false in this case if the\n  // instruction executes exactly twice.\n  bool incomplete_fast_forward;\n};\n\n/**\n * An indicator of how much progress the ReplaySession has made within a given\n * (FrameTime, Ticks) pair. These can only be used for comparisons, to\n * check whether two ReplaySessions are in the same state and to help\n * order their states temporally.\n */\nclass ReplayStepKey {\npublic:\n  /**\n   * Construct the \"none\" key; this value is before or equal to every other\n   * key value.\n   */\n  ReplayStepKey() : action(TSTEP_NONE) {}\n  explicit ReplayStepKey(ReplayTraceStepType action) : action(action) {}\n\n  bool operator==(const ReplayStepKey& other) const {\n    return action == other.action;\n  }\n  bool operator<(const ReplayStepKey& other) const {\n    return action < other.action;\n  }\n\n  bool in_execution() const { return action != TSTEP_NONE; }\n  int as_int() const { return (int)action; }\n\nprivate:\n  ReplayTraceStepType action;\n};\n\n/** Encapsulates additional session state related to replay. */\nclass ReplaySession final : public Session {\npublic:\n  typedef std::shared_ptr<ReplaySession> shr_ptr;\n\n  ~ReplaySession();\n\n  virtual Task* new_task(pid_t tid, pid_t rec_tid, uint32_t serial,\n                         SupportedArch a, const std::string& name) override;\n\n  using Session::clone;\n  /**\n   * Return a semantic copy of all the state managed by this,\n   * that is the entire tracee tree and the state it depends on.\n   * Any mutations of the returned Session can't affect the\n   * state of this, and vice versa.\n   *\n   * This operation is also called \"checkpointing\" the replay\n   * session.\n   *\n   * The returned clone is only partially initialized. This uses less\n   * system resources than a fully-initialized session, so if you're going\n   * to keep a session around inactive, keep the clone and not the original\n   * session. Partially initialized sessions automatically finish\n   * initializing when necessary.\n   */\n  shr_ptr clone();\n\n  /**\n   * Return true if we're in a state where it's OK to clone. For example,\n   * we can't clone in some syscalls.\n   */\n  bool can_clone();\n\n  /**\n   * Like |clone()|, but return a session in \"diversion\" mode,\n   * which allows free execution.\n   */\n  DiversionSession::shr_ptr clone_diversion();\n\n  EmuFs& emufs() const { return *emu_fs; }\n\n  TraceReader& trace_reader() { return trace_in; }\n  const TraceReader& trace_reader() const { return trace_in; }\n\n  /**\n   * The trace record that we are working on --- the next event\n   * for replay to reach.\n   */\n  const TraceFrame& current_trace_frame() const { return trace_frame; }\n  /**\n   * Time of the current frame\n   */\n  FrameTime current_frame_time() const { return trace_frame.time(); }\n\n  /**\n   * The Task for the current trace record.\n   */\n  ReplayTask* current_task() {\n    finish_initializing();\n    return find_task(trace_frame.tid());\n  }\n\n  ReplayTask* find_task(pid_t rec_tid) const;\n  ReplayTask* find_task(const TaskUid& tuid) const;\n\n  /**\n   * Returns true if the next step for this session is to exit a syscall with\n   * the given number.\n   */\n  bool next_step_is_successful_exec_syscall_exit();\n\n  /**\n   * The current ReplayStepKey.\n   */\n  ReplayStepKey current_step_key() const {\n    return ReplayStepKey(current_step.action);\n  }\n\n  Ticks ticks_at_start_of_current_event() const {\n    return ticks_at_start_of_event;\n  }\n\n  struct Flags {\n    Flags()\n      : redirect_stdio(false)\n      , share_private_mappings(false)\n      , replay_stops_at_first_execve(false)\n      , cpu_unbound(false)\n      , transient_errors_fatal(false)\n      , intel_pt_start_checking_event(-1) {}\n    Flags(const Flags&) = default;\n    bool redirect_stdio;\n    std::string redirect_stdio_file;\n    bool share_private_mappings;\n    bool replay_stops_at_first_execve;\n    bool cpu_unbound;\n    bool transient_errors_fatal;\n    FrameTime intel_pt_start_checking_event;\n  };\n\n  /**\n   * Create a replay session that will use the trace directory specified\n   * by 'dir', or the latest trace if 'dir' is not supplied.\n   */\n  static shr_ptr create(const std::string& dir, const Flags& flags);\n\n  struct StepConstraints {\n    explicit StepConstraints(RunCommand command)\n        : command(command), ticks_target(0) {}\n    RunCommand command;\n    Ticks ticks_target;\n    // When the RunCommand is RUN_SINGLESTEP_FAST_FORWARD, stop if the next\n    // singlestep would enter one of the register states in this list.\n    // RUN_SINGLESTEP_FAST_FORWARD will always singlestep at least once\n    // regardless.\n    std::vector<const Registers*> stop_before_states;\n\n    bool is_singlestep() const {\n      return command == RUN_SINGLESTEP ||\n             command == RUN_SINGLESTEP_FAST_FORWARD;\n    }\n  };\n  /**\n   * Take a single replay step.\n   * Outside of replay_step, no internal breakpoints will be set for any\n   * task in this session.\n   * If ticks_target is nonzero, stop before the current task's ticks\n   * reaches ticks_target (but not too far before, unless we hit a breakpoint).\n   * Only useful for RUN_CONTINUE.\n   * Always stops on a switch to a new task.\n   */\n  ReplayResult replay_step(const StepConstraints& constraints);\n  ReplayResult replay_step(RunCommand command) {\n    return replay_step(StepConstraints(command));\n  }\n\n  virtual ReplaySession* as_replay() override { return this; }\n  virtual bool need_performance_counters() const override { return !replay_stops_at_first_execve_; }\n\n  SupportedArch arch() { return trace_in.arch(); }\n\n  /**\n   * Return true if |sig| is a signal that may be generated during\n   * replay but should be ignored.  For example, SIGCHLD can be\n   * delivered at almost point during replay when tasks exit, but it's\n   * not part of the recording and shouldn't be delivered.\n   *\n   * TODO: can we do some clever sigprocmask'ing to avoid pending\n   * signals altogether?\n   */\n  static bool is_ignored_signal(int sig);\n\n  const Flags& flags() const { return flags_; }\n\n  typedef std::set<MemoryRange, MappingComparator> MemoryRanges;\n  enum PerfTradeoff {\n    FAST,\n    ACCURATE,\n  };\n  /**\n   * Returns an ordered set of MemoryRanges representing the address space\n   * that is never allocated by any process in the whole lifetime of the trace.\n   * When `perf_tradeoff` is `FAST`, we try to quickly return whatever we can.\n   * When it's `ACCURATE`, we do a much slower pass that can identify more memory.\n   * `ACCURATE` will always identify a superset of the memory identified by\n   * `FAST`.\n   * This memoizes its results so it's fast to call many times.\n   */\n  const MemoryRanges& always_free_address_space(\n    PerfTradeoff perf_tradeoff = ACCURATE);\n  static void delete_range(ReplaySession::MemoryRanges& ranges,\n                           const MemoryRange& r);\n\n  double get_trace_start_time();\n\n  virtual TraceStream* trace_stream() override { return &trace_in; }\n\n  virtual BindCPU cpu_binding() const override;\n\n  bool has_trace_quirk(TraceReader::TraceQuirks quirk) { return trace_in.quirks() & quirk; }\n\n  virtual int tracee_output_fd(int dflt) override {\n    return tracee_output_fd_.get() ? tracee_output_fd_->get() : dflt;\n  }\n\n  /**\n   * Get ready to detach these tasks and reattach them in a child process. Call this\n   * before forking the child.\n   */\n  void prepare_to_detach_tasks();\n  /**\n   * This ReplaySession is in a forked child. The real ReplaySession is still running in\n   * the parent, so we don't really own tasks and other shared resources. Forget about\n   * them so we don't try to tear them down when this ReplaySession is destroyed.\n   */\n  void forget_tasks();\n  /**\n   * The shared resources associated with this ReplaySession are being transferred to\n   * the child process `new_ptracer`. Prepare them for transfer (e.g. ptrace-detach the\n   * tracees) and prepare them to be traced by `new_ptracer`, and forget about them.\n   * `new_sock_fd` is the new control fd pushed into all tasks.\n   */\n  void detach_tasks(pid_t new_ptracer, ScopedFd& new_tracee_socket_receiver);\n  /**\n   * The shared resources associated with this ReplaySession are being transferred to\n   * the child process `new_ptracer`. Receive them in the child process by ptrace-attaching\n   * to them etc.\n   * `new_sock_fd` is the control fd that has been assigned to all tasks,\n   * `new_sock_receiver_fd` is its receiver end.\n   */\n  void reattach_tasks(ScopedFd new_tracee_socket, ScopedFd new_tracee_socket_receiver);\n\n  void notify_detected_transient_error() { detected_transient_error_ = true; }\n\n  void set_suppress_stdio_before_event(FrameTime event) { suppress_stdio_before_event_ = event; }\n  bool mark_stdio() const override;\n  bool echo_stdio() const;\n\nprivate:\n  ReplaySession(const std::string& dir, const Flags& flags);\n  ReplaySession(const ReplaySession& other);\n\n  void check_virtual_address_size() const;\n\n  ReplayTask* revive_task_for_exec();\n  ReplayTask* setup_replay_one_trace_frame(ReplayTask* t);\n  void advance_to_next_trace_frame();\n  Completion emulate_signal_delivery(ReplayTask* oldtask);\n  Completion try_one_trace_step(ReplayTask* t,\n                                const StepConstraints& step_constraints);\n  Completion cont_syscall_boundary(ReplayTask* t,\n                                   const StepConstraints& constraints);\n  Completion enter_syscall(ReplayTask* t, const StepConstraints& constraints);\n  Completion exit_syscall(ReplayTask* t);\n  Completion exit_task(ReplayTask* t);\n  bool handle_unrecorded_cpuid_fault(ReplayTask* t,\n                                     const StepConstraints& constraints);\n  void check_ticks_consistency(ReplayTask* t, const Event& ev);\n  void check_pending_sig(ReplayTask* t);\n  Completion continue_or_step(ReplayTask* t, const StepConstraints& constraints,\n                              TicksRequest tick_request,\n                              ResumeRequest resume_how = RESUME_SYSEMU);\n  Completion advance_to_ticks_target(ReplayTask* t,\n                                     const StepConstraints& constraints);\n  Completion emulate_deterministic_signal(ReplayTask* t, int sig,\n                                          const StepConstraints& constraints);\n  Completion emulate_async_signal(ReplayTask* t,\n                                  const StepConstraints& constraints,\n                                  Ticks ticks,\n                                  remote_code_ptr in_syscallbuf_syscall_hook);\n  void prepare_syscallbuf_records(ReplayTask* t, Ticks ticks);\n  Completion flush_syscallbuf(ReplayTask* t,\n                              const StepConstraints& constraints);\n  Completion patch_next_syscall(ReplayTask* t,\n                                const StepConstraints& constraints,\n                                bool before_syscall);\n  Completion patch_ip(ReplayTask* t, const StepConstraints& constraints);\n  void apply_patch_data(ReplayTask* t);\n  void check_approaching_ticks_target(ReplayTask* t,\n                                      const StepConstraints& constraints,\n                                      BreakStatus& break_status);\n\n  void clear_syscall_bp();\n\n  std::shared_ptr<EmuFs> emu_fs;\n  std::shared_ptr<ScopedFd> tracee_output_fd_;\n  TraceReader trace_in;\n  TraceFrame trace_frame;\n  ReplayTraceStep current_step;\n  Ticks ticks_at_start_of_event;\n  CPUIDBugDetector cpuid_bug_detector;\n  siginfo_t last_siginfo_;\n  Flags flags_;\n  FastForwardStatus fast_forward_status;\n  TaskUid last_task_tuid;\n  bool skip_next_execution_event;\n  bool replay_stops_at_first_execve_;\n  bool detected_transient_error_;\n\n  // The clock_gettime(CLOCK_MONOTONIC) timestamp of the first trace event, used\n  // during 'replay' to calculate the elapsed time between the first event and\n  // all other recorded events in the timeline during the 'record' phase.\n  double trace_start_time;\n\n  FrameTime suppress_stdio_before_event_;\n\n  std::shared_ptr<AddressSpace> syscall_bp_vm;\n  remote_code_ptr syscall_bp_addr;\n\n  std::shared_ptr<MemoryRanges> always_free_address_space_fast;\n  std::shared_ptr<MemoryRanges> always_free_address_space_accurate;\n};\n\nvoid emergency_check_intel_pt(ReplayTask* t, std::ostream& stream);\n\n} // namespace rr\n\n#endif // RR_REPLAY_SESSION_H_\n"
  },
  {
    "path": "src/ReplayTask.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ReplayTask.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"PreserveFileMonitor.h\"\n#include \"ReplaySession.h\"\n#include \"log.h\"\n#include \"rr/rr.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nReplayTask::ReplayTask(ReplaySession& session, pid_t _tid, pid_t _rec_tid,\n                       uint32_t serial, SupportedArch a,\n                       const std::string& name)\n    : Task(session, _tid, _rec_tid, serial, a),\n      name_(name),\n      seen_sched_in_syscallbuf_syscall_hook(false)\n{}\n\nReplaySession& ReplayTask::session() const {\n  return *Task::session().as_replay();\n}\n\nTraceReader& ReplayTask::trace_reader() const {\n  return session().trace_reader();\n}\n\ntemplate <typename Arch>\nvoid ReplayTask::init_buffers_arch() {\n  apply_all_data_records_from_trace();\n\n  AutoRemoteSyscalls remote(this);\n\n  remote_ptr<rrcall_init_buffers_params<Arch>> child_args = regs().arg1();\n  auto args = read_mem(child_args);\n\n  if (args.syscallbuf_ptr) {\n    syscallbuf_size = args.syscallbuf_size;\n    init_syscall_buffer(remote, args.syscallbuf_ptr);\n    desched_fd_child = args.desched_counter_fd;\n    // Prevent the child from closing this fd\n    fds->add_monitor(this, desched_fd_child, new PreserveFileMonitor());\n\n    // Skip mmap record. It exists mainly to inform non-replay code\n    // (e.g. RemixModule) that this memory will be mapped.\n    trace_reader().read_mapped_region();\n\n    if (args.cloned_file_data_fd >= 0) {\n      cloned_file_data_fd_child = args.cloned_file_data_fd;\n      cloned_file_data_fname = trace_reader().file_data_clone_file_name(tuid());\n      ScopedFd clone_file(cloned_file_data_fname.c_str(), O_RDONLY);\n      ASSERT(this, clone_file.is_open());\n      remote.infallible_send_fd_dup(clone_file, cloned_file_data_fd_child, O_CLOEXEC);\n      fds->add_monitor(this, cloned_file_data_fd_child, new PreserveFileMonitor());\n    }\n  }\n\n  remote.regs().set_syscall_result(syscallbuf_child);\n}\n\nvoid ReplayTask::init_buffers() {\n  RR_ARCH_FUNCTION(init_buffers_arch, arch());\n}\n\nvoid ReplayTask::post_exec_syscall(const string& replay_exe, const string& original_replay_exe) {\n  Task::post_exec(replay_exe);\n\n  // Perform post-exec-syscall tasks now (e.g. opening mem_fd) before we\n  // switch registers. This lets us perform AutoRemoteSyscalls using the\n  // regular stack instead of having to search the address space for usable\n  // pages (which is error prone, e.g. if we happen to find the scratch space\n  // allocated by an rr recorder under which we're running).\n  Task::post_exec_syscall(original_replay_exe);\n\n  // Delay setting the replay_regs until here so the original registers\n  // are set while we populate AddressSpace. We need that for the kernel\n  // to identify the original stack region correctly.\n  set_regs(current_trace_frame().regs());\n  extra_registers = current_trace_frame().extra_regs();\n  ASSERT(this, !extra_registers.empty());\n  set_extra_regs(extra_registers);\n}\n\nvoid ReplayTask::set_name(AutoRemoteSyscalls& remote, const std::string& name) {\n  name_ = name;\n  Task::set_name(remote, \"rr:\" + name);\n}\n\nvoid ReplayTask::did_prctl_set_prname(remote_ptr<void> child_addr) {\n  char buf[16];\n  // The null-terminated name might start within the last 16 bytes of a memory\n  // mapping.\n  ssize_t bytes = read_bytes_fallible(child_addr, sizeof(buf), buf);\n  // If there was no readable data then this shouldn't be called\n  ASSERT(this, bytes > 0);\n  // Make sure the final byte is null if the string needed to be truncated\n  buf[bytes - 1] = 0;\n  AutoRemoteSyscalls remote(this);\n  set_name(remote, buf);\n}\n\nvoid ReplayTask::validate_regs(uint32_t flags) {\n  /* don't validate anything before execve is done as the actual\n   * process did not start prior to this point */\n  if (!session().done_initial_exec()) {\n    return;\n  }\n  if (seen_sched_in_syscallbuf_syscall_hook) {\n    /* Registers may diverge here */\n    return;\n  }\n\n  Registers rec_regs = current_trace_frame().regs();\n\n  if (flags & IGNORE_ESI) {\n    if (regs().arg4() != rec_regs.arg4()) {\n      LOG(warn) << \"Probably saw kernel bug mutating $esi across pread/write64 \"\n                   \"call: recorded:\"\n                << HEX(rec_regs.arg4()) << \"; replaying:\" << regs().arg4()\n                << \".  Fudging registers.\";\n      rec_regs.set_arg4(regs().arg4());\n    }\n  }\n\n  /* TODO: add perf counter validations (hw int, page faults, insts) */\n  Registers::Comparison comparison = regs().compare_with(rec_regs);\n  ASSERT(this, !comparison.mismatch_count) << \"Mismatched registers, replay vs rec: \"\n      << comparison;\n}\n\nconst TraceFrame& ReplayTask::current_trace_frame() const {\n  return session().current_trace_frame();\n}\n\nFrameTime ReplayTask::current_frame_time() const {\n  return current_trace_frame().time();\n}\n\n// Returns number of bytes written (including holes)\nstatic size_t write_data_with_holes(ReplayTask* t,\n                                    const TraceReader::RawDataWithHoles& buf) {\n  unique_ptr<AutoRemoteSyscalls> remote;\n  size_t data_offset = 0;\n  size_t addr_offset = 0;\n  auto holes_iter = buf.holes.begin();\n  while (data_offset < buf.data.size() || holes_iter != buf.holes.end()) {\n    if (holes_iter != buf.holes.end() && holes_iter->offset == addr_offset) {\n      t->write_zeroes(&remote, buf.addr + addr_offset, holes_iter->size);\n      addr_offset += holes_iter->size;\n      ++holes_iter;\n      continue;\n    }\n    size_t data_end = buf.data.size();\n    if (holes_iter != buf.holes.end()) {\n      data_end = data_offset + holes_iter->offset - addr_offset;\n    }\n    bool ok = true;\n    ssize_t nwritten = t->write_bytes_helper(buf.addr + addr_offset, data_end - data_offset,\n                                             buf.data.data() + data_offset,&ok);\n\n    ASSERT(t, ok || buf.size_validation == MemWriteSizeValidation::CONSERVATIVE)\n        << \"Should have written \" << buf.data.size() << \" bytes to \" << (buf.addr + addr_offset)\n        << \", but only wrote \" << nwritten;\n\n    addr_offset += data_end - data_offset;\n    data_offset = data_end;\n  }\n  return addr_offset;\n}\n\nvoid ReplayTask::apply_data_record_from_trace() {\n  TraceReader::RawDataWithHoles buf;\n  bool ok = trace_reader().read_raw_data_for_frame_with_holes(buf);\n  ASSERT(this, ok);\n  if (buf.addr.is_null()) {\n    return;\n  }\n  auto t = session().find_task(buf.rec_tid);\n  size_t size = write_data_with_holes(t, buf);\n  t->vm()->maybe_update_breakpoints(t, buf.addr.cast<uint8_t>(), size);\n}\n\nvoid ReplayTask::apply_all_data_records_from_trace() {\n  TraceReader::RawDataWithHoles buf;\n  while (trace_reader().read_raw_data_for_frame_with_holes(buf)) {\n    if (buf.addr.is_null()) {\n      continue;\n    }\n    auto t = session().find_task(buf.rec_tid);\n    size_t size = write_data_with_holes(t, buf);\n    t->vm()->maybe_update_breakpoints(t, buf.addr.cast<uint8_t>(), size);\n  }\n}\n\nvoid ReplayTask::set_return_value_from_trace() {\n  Registers r = regs();\n  r.set_syscall_result(current_trace_frame().regs().syscall_result());\n  // In some cases (e.g. syscalls forced to return an error by tracee\n  // seccomp filters) we need to emulate a change to the original_syscallno\n  // (to -1 in that case).\n  r.set_original_syscallno(current_trace_frame().regs().original_syscallno());\n  if (r.original_syscallno() == session().syscall_number_for_rrcall_rdtsc()) {\n    ASSERT(this, is_x86ish(arch()));\n    // EAX has been set via set_syscall_result above\n    r.set_dx(current_trace_frame().regs().dx());\n  }\n  set_regs(r);\n}\n\nvoid ReplayTask::set_real_tid_and_update_serial(pid_t tid) {\n  hpc.set_tid(tid);\n  this->tid = tid;\n  serial = session().next_task_serial();\n}\n\nconst ExtraRegisters& ReplayTask::extra_regs() {\n  if (!extra_regs_fallible()) {\n    ASSERT(this, false) << \"Can't find task for infallible extra_regs\";\n  }\n  return extra_registers;\n}\n\nbool ReplayTask::post_vm_clone(CloneReason reason, int flags, Task* origin) {\n  if (Task::post_vm_clone(reason, flags, origin) &&\n      reason == TRACEE_CLONE &&\n      trace_reader().preload_thread_locals_recorded()) {\n    // Consume the mapping.\n    TraceReader::MappedData data;\n    KernelMapping km = trace_reader().read_mapped_region(&data);\n    ASSERT(this, km.start() == AddressSpace::preload_thread_locals_start() &&\n           km.size() == page_size());\n    return true;\n  }\n\n  return false;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ReplayTask.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REPLAY_TASK_H_\n#define RR_REPLAY_TASK_H_\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"Task.h\"\n\nnamespace rr {\n\nclass TraceFrame;\n\n/**\n * Every Task owned by a ReplaySession is a ReplayTask. Functionality that\n * only applies during replay belongs here.\n */\nclass ReplayTask final : public Task {\npublic:\n  ReplayTask(ReplaySession& session, pid_t _tid, pid_t _rec_tid,\n             uint32_t serial, SupportedArch a,\n             const std::string& name);\n\n  ReplaySession& session() const;\n  TraceReader& trace_reader() const;\n\n  /**\n   * Initialize tracee buffers in this, i.e., implement\n   * RRCALL_init_syscall_buffer.  This task must be at the point\n   * of *exit from* the rrcall.  Registers will be updated with\n   * the return value from the rrcall, which is also returned\n   * from this call..\n   */\n  void init_buffers();\n  /**\n   * Call this method when the exec has completed.\n   * `replay_exe` is the name of the real executable file in the trace if we have one,\n   * otherwise the name of the original executable file. This gets passed to gdb\n   * as a best-effort to give gdb a file to look at.\n   * `original_replay_exe` is the name of the original executable file.\n   */\n  void post_exec_syscall(const std::string& replay_exe, const std::string& original_replay_exe);\n\n  void set_name(AutoRemoteSyscalls& remote, const std::string& name) override;\n\n  void did_prctl_set_prname(remote_ptr<void> child_addr) override;\n\n  enum {\n    /* The x86 linux 3.5.0-36 kernel packaged with Ubuntu\n     * 12.04 has been observed to mutate $esi across\n     * syscall entry/exit.  (This has been verified\n     * outside of rr as well; not an rr bug.)  It's not\n     * clear whether this is a ptrace bug or a kernel bug,\n     * but either way it's not supposed to happen.  So we\n     * allow validate_args to cover up that bug. */\n    IGNORE_ESI = 0x01\n  };\n  /** Assert that the current register values match the values in the\n   *  current trace record.\n   */\n  void validate_regs(uint32_t flags = 0);\n  const TraceFrame& current_trace_frame() const;\n  FrameTime current_frame_time() const;\n\n  /** Restore the next chunk of this frame's saved data from the trace to this. */\n  void apply_data_record_from_trace();\n  /** Restore all remaining chunks of saved data for the current trace frame. */\n  void apply_all_data_records_from_trace();\n\n  /**\n   * Set the syscall-return-value register of this to what was\n   * saved in the current trace frame.\n   */\n  void set_return_value_from_trace();\n\n  /**\n   * Used when an execve changes the tid of a non-main-thread to the\n   * thread-group leader.\n   */\n  void set_real_tid_and_update_serial(pid_t tid);\n\n  /** Return the extra registers of this. Asserts if the task died. */\n  const ExtraRegisters& extra_regs();\n\n  void note_sched_in_syscallbuf_syscall_hook() {\n    seen_sched_in_syscallbuf_syscall_hook = true;\n  }\n\n  std::string name() const override {\n    return name_;\n  }\n\nprivate:\n  template <typename Arch> void init_buffers_arch();\n\n  bool post_vm_clone(CloneReason reason, int flags, Task* origin) override;\n\n  std::string name_;\n\n  // Set to true when we see a sched event with in_syscallbuf_syscall_hook set.\n  bool seen_sched_in_syscallbuf_syscall_hook;\n};\n\n} // namespace rr\n\n#endif /* RR_REPLAY_TASK_H_ */\n"
  },
  {
    "path": "src/ReplayTimeline.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ReplayTimeline.h\"\n\n#include <math.h>\n#include <sstream>\n\n#include \"core.h\"\n#include \"fast_forward.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nReplayTimeline::InternalMark::~InternalMark() {\n  if (owner && checkpoint) {\n    owner->remove_mark_with_checkpoint(proto.key);\n  }\n}\n\nvoid ReplayTimeline::InternalMark::full_print(FILE* out) const {\n  ostringstream buf;\n  buf << proto.key;\n  fprintf(out, \"{%s,regs:\", buf.str().c_str());\n  proto.regs.print_register_file(out);\n  fputs(\",return_addresses=[\", out);\n  for (int i = 0; i < ReturnAddressList::MAX_COUNT; ++i) {\n    fprintf(out, \"%p\", (void*)proto.return_addresses.addresses[i].as_int());\n    if (i + 1 < ReturnAddressList::MAX_COUNT) {\n      fputc(',', out);\n    }\n  }\n  fputs(\"]}\", out);\n}\n\nostream& operator<<(ostream& s, const ReplayTimeline::MarkKey& o) {\n  return s << \"time:\" << o.trace_time << \",ticks:\" << o.ticks\n           << \",st:\" << o.step_key.as_int();\n}\n\nostream& operator<<(ostream& s, const ReplayTimeline::InternalMark& o) {\n  return s << o.proto;\n}\n\nostream& operator<<(ostream& s, const ReplayTimeline::Mark& o) {\n  if (!o.ptr) {\n    return s << \"{null}\";\n  }\n  return s << *o.ptr.get();\n}\n\nostream& operator<<(ostream& s, const ReplayTimeline::ProtoMark& o) {\n  return s << \"{\" << o.key << \",regs_ip:\" << o.regs.ip() << \"}\";\n}\n\nbool ReplayTimeline::less_than(const Mark& m1, const Mark& m2) {\n  DEBUG_ASSERT(m1.ptr->owner == m2.ptr->owner);\n  if (m1.ptr->proto.key < m2.ptr->proto.key) {\n    return true;\n  }\n  if (m2.ptr->proto.key < m1.ptr->proto.key) {\n    return false;\n  }\n  if (!m1.ptr->owner) {\n    return false;\n  }\n  for (shared_ptr<InternalMark>& m : m1.ptr->owner->marks[m1.ptr->proto.key]) {\n    if (m == m2.ptr) {\n      return false;\n    }\n    if (m == m1.ptr) {\n      return true;\n    }\n  }\n  DEBUG_ASSERT(0 && \"Marks missing from vector, invariants broken!\");\n  return false;\n}\n\nReplayTimeline::ReplayTimeline(std::shared_ptr<ReplaySession> session)\n    : current(std::move(session)),\n      breakpoints_applied(false),\n      reverse_execution_barrier_event_(0) {\n  current->set_visible_execution(false);\n}\n\nReplayTimeline::~ReplayTimeline() {\n  for (auto it : marks) {\n    for (shared_ptr<InternalMark>& itv : it.second) {\n      itv->owner = nullptr;\n      itv->checkpoint = nullptr;\n    }\n  }\n}\n\nstatic bool equal_regs(const Registers& r1, const Registers& r2) {\n  // Compare ip()s first since they will usually fail to match, especially\n  // when we're comparing InternalMarks with the same MarkKey\n  return r1.ip() == r2.ip() && r1.matches(r2);\n}\n\nbool ReplayTimeline::InternalMark::equal_states(ReplaySession& session) const {\n  return proto.equal_states(session);\n}\n\nbool ReplayTimeline::ProtoMark::equal_states(ReplaySession& session) const {\n  if (session_mark_key(session) != key) {\n    return false;\n  }\n  ReplayTask* t = session.current_task();\n  return equal_regs(regs, t->regs()) &&\n         return_addresses == ReturnAddressList(t);\n}\n\nReplayTimeline::ProtoMark ReplayTimeline::proto_mark() const {\n  ReplayTask* t = current->current_task();\n  if (t) {\n    return ProtoMark(current_mark_key(), t);\n  }\n  return ProtoMark(current_mark_key());\n}\n\nshared_ptr<ReplayTimeline::InternalMark> ReplayTimeline::current_mark() const {\n  auto it = marks.find(current_mark_key());\n  // Avoid creating an entry in 'marks' if it doesn't already exist\n  if (it != marks.end()) {\n    for (const shared_ptr<InternalMark>& m : it->second) {\n      if (m->equal_states(*current)) {\n        return m;\n      }\n    }\n  }\n  return shared_ptr<InternalMark>();\n}\n\nReplayTimeline::Mark ReplayTimeline::mark() {\n  Mark result;\n  auto cm = current_mark();\n  if (cm) {\n    swap(cm, result.ptr);\n    return result;\n  }\n\n  MarkKey key = current_mark_key();\n  shared_ptr<InternalMark> m = make_shared<InternalMark>(this, *current, key);\n\n  auto& mark_vector = marks[key];\n  if (mark_vector.empty()) {\n    mark_vector.push_back(m);\n  } else if (mark_vector[mark_vector.size() - 1] == current_at_or_after_mark) {\n    mark_vector.push_back(m);\n  } else {\n    // Now the hard part: figuring out where to put it in the list of existing\n    // marks.\n    unapply_breakpoints_and_watchpoints();\n    ReplaySession::shr_ptr tmp_session = current->clone();\n    vector<shared_ptr<InternalMark>>::iterator mark_index = mark_vector.end();\n\n    // We could set breakpoints at the marks and then continue with an\n    // interrupt set to fire when our tick-count increases. But that requires\n    // new replay functionality (probably a new RunCommand), so for now, do the\n    // simplest thing and just single-step until we find where to put the new\n    // mark(s).\n    vector<shared_ptr<InternalMark>> new_marks;\n    new_marks.push_back(m);\n\n    LOG(debug) << \"mark() replaying to find mark location for \" << *m;\n\n    // Allow coalescing of multiple repetitions of a single x86 string\n    // instruction (as long as we don't reach one of our mark_vector states).\n    ReplaySession::StepConstraints constraints(RUN_SINGLESTEP_FAST_FORWARD);\n    for (auto& mv : mark_vector) {\n      constraints.stop_before_states.push_back(&mv->proto.regs);\n    }\n\n    while (true) {\n      auto result = tmp_session->replay_step(constraints);\n      if (session_mark_key(*tmp_session) != key ||\n          result.status != REPLAY_CONTINUE) {\n        break;\n      }\n      if (!result.break_status.singlestep_complete) {\n        continue;\n      }\n\n      for (auto it = mark_vector.begin(); it != mark_vector.end(); ++it) {\n        shared_ptr<InternalMark>& existing_mark = *it;\n        if (existing_mark->equal_states(*tmp_session)) {\n          if (!result.did_fast_forward && !result.break_status.signal) {\n            new_marks.back()->singlestep_to_next_mark_no_signal = true;\n          }\n          mark_index = it;\n          break;\n        }\n      }\n      if (mark_index != mark_vector.end()) {\n        break;\n      }\n\n      // Some callers singlestep through N instructions, all with the same\n      // MarkKey, requesting a Mark after each step. If there's a Mark at the\n      // end of the N instructions, this could mean N(N+1)/2 singlestep\n      // operations total. To avoid that, add all the intermediate states to\n      // the mark map now, so the first mark() call will perform N singlesteps\n      // and the rest will perform none.\n      if (!result.did_fast_forward && !result.break_status.signal) {\n        new_marks.back()->singlestep_to_next_mark_no_signal = true;\n      }\n      new_marks.push_back(make_shared<InternalMark>(this, *tmp_session, key));\n    }\n\n    // mark_index is the current index of the next mark after 'current'. So\n    // insert our new marks at mark_index.\n    mark_vector.insert(mark_index, new_marks.begin(), new_marks.end());\n  }\n  swap(m, result.ptr);\n  current_at_or_after_mark = result.ptr;\n  return result;\n}\n\nvoid ReplayTimeline::mark_after_singlestep(const Mark& from,\n                                           const ReplayResult& result) {\n  DEBUG_ASSERT(result.break_status.singlestep_complete);\n  Mark m = mark();\n  if (!result.did_fast_forward && m.ptr->proto.key == from.ptr->proto.key &&\n      !result.break_status.signal) {\n    auto& mark_vector = marks[m.ptr->proto.key];\n    for (size_t i = 0; i < mark_vector.size(); ++i) {\n      if (mark_vector[i] == from.ptr) {\n        if (i + 1 >= mark_vector.size() || mark_vector[i + 1] != m.ptr) {\n          ssize_t m_prev = -1;\n          for (size_t j = 0; j < mark_vector.size(); ++j) {\n            LOG(debug) << \"  mark_vector[\" << j << \"] \" << *mark_vector[j];\n            if (mark_vector[j] == m.ptr && j > 0) {\n              m_prev = j - 1;\n            }\n          }\n          if (m_prev >= 0) {\n            fprintf(stderr, \"Probable previous-to-duplicated-state at %d:\", (int)m_prev);\n            mark_vector[m_prev]->full_print(stderr);\n            fprintf(stderr, \"Probable previous-to-duplicated-state at %d:\", (int)i);\n            from.ptr->full_print(stderr);\n            fprintf(stderr, \"Probable duplicated state at %d:\", (int)m_prev + 1);\n            m.ptr->full_print(stderr);\n          }\n          ASSERT(result.break_status.task(), false)\n              << \" Probable duplicated states leading to \" << m << \" at index \" << i + 1;\n        }\n        break;\n      }\n    }\n    from.ptr->singlestep_to_next_mark_no_signal = true;\n  }\n}\n\nReplayTimeline::Mark ReplayTimeline::find_singlestep_before(const Mark& mark) {\n  auto& mark_vector = marks[mark.ptr->proto.key];\n  ssize_t i;\n  for (i = mark_vector.size() - 1; i >= 0; --i) {\n    if (mark_vector[i] == mark.ptr) {\n      break;\n    }\n  }\n  DEBUG_ASSERT(i >= 0 && \"Mark not in vector???\");\n\n  Mark m;\n  if (i == 0) {\n    return m;\n  }\n  if (!mark_vector[i - 1]->singlestep_to_next_mark_no_signal) {\n    return m;\n  }\n  m.ptr = mark_vector[i - 1];\n  return m;\n}\n\nReplayTimeline::Mark ReplayTimeline::lazy_reverse_singlestep(const Mark& from,\n                                                             ReplayTask* t) {\n  if (!no_watchpoints_hit_interval_start || !no_watchpoints_hit_interval_end) {\n    return Mark();\n  }\n  Mark m = find_singlestep_before(from);\n  if (m && m >= no_watchpoints_hit_interval_start &&\n      m < no_watchpoints_hit_interval_end &&\n      !has_breakpoint_at_address(t, from.ptr->proto.regs.ip())) {\n    return m;\n  }\n  return Mark();\n}\n\nReplayTimeline::Mark ReplayTimeline::add_explicit_checkpoint() {\n  DEBUG_ASSERT(current->can_clone());\n\n  Mark m = mark();\n  if (!m.ptr->checkpoint) {\n    unapply_breakpoints_and_watchpoints();\n    m.ptr->checkpoint = current->clone();\n    auto key = m.ptr->proto.key;\n    if (marks_with_checkpoints.find(key) == marks_with_checkpoints.end()) {\n      marks_with_checkpoints[key] = 1;\n    } else {\n      marks_with_checkpoints[key]++;\n    }\n  }\n  ++m.ptr->checkpoint_refcount;\n  return m;\n}\n\nvoid ReplayTimeline::remove_mark_with_checkpoint(const MarkKey& key) {\n  DEBUG_ASSERT(marks_with_checkpoints[key] > 0);\n  if (--marks_with_checkpoints[key] == 0) {\n    marks_with_checkpoints.erase(key);\n  }\n}\n\nvoid ReplayTimeline::remove_explicit_checkpoint(const Mark& mark) {\n  DEBUG_ASSERT(mark.ptr->checkpoint_refcount > 0);\n  if (--mark.ptr->checkpoint_refcount == 0) {\n    mark.ptr->checkpoint = nullptr;\n    remove_mark_with_checkpoint(mark.ptr->proto.key);\n  }\n}\n\nvoid ReplayTimeline::seek_to_before_key(const MarkKey& key) {\n  auto it = marks_with_checkpoints.lower_bound(key);\n  // 'it' points to the first value equivalent to or greater than 'key'.\n  auto current_key = current_mark_key();\n  if (it == marks_with_checkpoints.begin()) {\n    if (current_key < key) {\n      // We can use the current session, so do nothing.\n    } else {\n      // nowhere earlier to go, so restart from beginning.\n      current = ReplaySession::create(current->trace_reader().dir(), current->flags());\n      breakpoints_applied = false;\n      current_at_or_after_mark = nullptr;\n    }\n  } else {\n    --it;\n    // 'it' is now at the last checkpoint before 'key'\n    if (it->first < current_key && current_key < key) {\n      // Current state is closer to the destination than any checkpoint we\n      // have, so do nothing.\n    } else {\n      // Return one of the checkpoints at *it.\n      current = nullptr;\n      for (const auto& mark_it : marks[it->first]) {\n        if (mark_it->checkpoint) {\n          current = mark_it->checkpoint->clone();\n          // At this point, mark_it->checkpoint is fully initialized but current\n          // is not. Swap them so that mark_it->checkpoint is not fully\n          // initialized, to reduce resource usage.\n          swap(current, mark_it->checkpoint);\n          breakpoints_applied = false;\n          current_at_or_after_mark = mark_it;\n          break;\n        }\n      }\n      DEBUG_ASSERT(current);\n    }\n  }\n}\n\nvoid ReplayTimeline::seek_up_to_mark(const Mark& mark) {\n  if (current_mark_key() == mark.ptr->proto.key) {\n    Mark cm = this->mark();\n    if (cm <= mark) {\n      // close enough, stay where we are\n      return;\n    }\n  }\n\n  // Check if any of the marks with the same key as 'mark', but not after\n  // 'mark', are usable.\n  auto& mark_vector = marks[mark.ptr->proto.key];\n  bool at_or_before_mark = false;\n  for (ssize_t i = mark_vector.size() - 1; i >= 0; --i) {\n    auto& m = mark_vector[i];\n    if (m == mark.ptr) {\n      at_or_before_mark = true;\n    }\n    if (at_or_before_mark && m->checkpoint) {\n      current = m->checkpoint->clone();\n      // At this point, m->checkpoint is fully initialized but current\n      // is not. Swap them so that m->checkpoint is not fully\n      // initialized, to reduce resource usage.\n      swap(current, m->checkpoint);\n      breakpoints_applied = false;\n      current_at_or_after_mark = m;\n      return;\n    }\n  }\n\n  return seek_to_before_key(mark.ptr->proto.key);\n}\n\nReplaySession::StepConstraints\nReplayTimeline::ReplayStepToMarkStrategy::setup_step_constraints() {\n  ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n  if (singlesteps_to_perform > 0) {\n    constraints.command = RUN_SINGLESTEP_FAST_FORWARD;\n    --singlesteps_to_perform;\n  }\n  return constraints;\n}\n\nvoid ReplayTimeline::update_strategy_and_fix_watchpoint_quirk(\n    ReplayStepToMarkStrategy& strategy,\n    const ReplaySession::StepConstraints& constraints, ReplayResult& result,\n    const ProtoMark& before) {\n  if (constraints.command == RUN_CONTINUE &&\n      fix_watchpoint_coalescing_quirk(result, before)) {\n    // It's quite common for x86 string instructions to trigger the same\n    // watchpoint several times in consecutive instructions, e.g. if we're\n    // doing a \"rep movsb\" over an 8-byte watchpoint. 8 invocations of\n    // fix_watchpoint_coalescing_quirk could require 8 replays from some\n    // previous checkpoint. To avoid that, after\n    // fix_watchpoint_coalescing_quirk has fired once, singlestep the\n    // next 7 times.\n    strategy.singlesteps_to_perform = 7;\n  }\n}\n\nvoid ReplayTimeline::seek_to_ticks(FrameTime time, Ticks ticks) {\n  seek_to_before_key(MarkKey(time, ticks, ReplayStepKey()));\n  unapply_breakpoints_and_watchpoints();\n\n  while (current->trace_reader().time() < time) {\n    ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n    ReplayResult result = current->replay_step(constraints);\n    if (result.status != REPLAY_CONTINUE) {\n      FATAL() << \"Trace finished before target was reached\";\n    }\n  }\n\n  ReplayTask* t = current->current_task();\n  if (t->tick_count() < ticks) {\n    // First step using the ticks counter until we enter the skid region\n    ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n    while (true) {\n      constraints.ticks_target = ticks;\n      ReplayResult result = current->replay_step(constraints);\n      if (result.break_status.approaching_ticks_target) {\n        break;\n      }\n    }\n\n    // Then singlestep until we hit our ticks target\n    while (t->tick_count() < ticks) {\n      current->replay_step(RUN_SINGLESTEP_FAST_FORWARD);\n    }\n  }\n}\n\nReplayResult ReplayTimeline::replay_step_to_mark(\n    const Mark& mark, ReplayStepToMarkStrategy& strategy) {\n  ReplayTask* t = current->current_task();\n  ProtoMark before = proto_mark();\n  ASSERT(t, before.key <= mark.ptr->proto.key)\n      << \"Current mark \" << before << \" is already after target \" << mark;\n  ReplayResult result;\n  if (current->trace_reader().time() < mark.ptr->proto.key.trace_time) {\n    // Easy case: each RUN_CONTINUE can only advance by at most one\n    // trace event, so do one. But do a singlestep if our strategy suggests\n    // we should.\n    ReplaySession::StepConstraints constraints =\n        strategy.setup_step_constraints();\n    result = current->replay_step(constraints);\n    update_strategy_and_fix_watchpoint_quirk(strategy, constraints, result,\n                                             before);\n    return result;\n  }\n\n  ASSERT(t, current->trace_reader().time() == mark.ptr->proto.key.trace_time);\n  // t must remain valid through here since t can only die when we complete\n  // an event, and we're not going to complete another event before\n  // reaching the mark ... apart from where we call\n  // fix_watchpoint_coalescing_quirk.\n\n  if (t->tick_count() < mark.ptr->proto.key.ticks) {\n    // Try to make progress by just continuing with a ticks constraint\n    // set to stop us before the mark. This is efficient in the worst case,\n    // when we must execute lots of instructions to reach the mark.\n    ReplaySession::StepConstraints constraints =\n        strategy.setup_step_constraints();\n    constraints.ticks_target = mark.ptr->proto.key.ticks - 1;\n    if (constraints.ticks_target > 0) {\n      result = current->replay_step(constraints);\n      bool approaching_ticks_target =\n        result.break_status.approaching_ticks_target;\n      result.break_status.approaching_ticks_target = false;\n      // We can't be at the mark yet.\n      ASSERT(t, t->tick_count() < mark.ptr->proto.key.ticks);\n      // If there's a break indicated, we should return that to the\n      // caller without doing any more work\n      if (!approaching_ticks_target || result.break_status.any_break()) {\n        update_strategy_and_fix_watchpoint_quirk(strategy, constraints, result,\n                                                 before);\n        return result;\n      }\n    }\n    // We may not have made any progress so we'll need to try another strategy\n  }\n\n  remote_code_ptr mark_addr_code = mark.ptr->proto.regs.ip();\n  remote_ptr<void> mark_addr = mark_addr_code.to_data_ptr<void>();\n\n  // Try adding a breakpoint at the required IP and running to it.\n  // We can't do this if we're currently at the IP, since we'd make no progress.\n  // However, we need to be careful, since there are two related situations when\n  // the instruction at the mark ip is never actually executed. The first\n  // happens if the IP is invalid entirely, the second if it is valid, but\n  // not executable. In either case we need to fall back to the (slower, but\n  // more generic) code below.\n  if (t->regs().ip() != mark_addr_code && t->vm()->has_mapping(mark_addr) &&\n      (t->vm()->mapping_of(mark_addr).map.prot() & PROT_EXEC)) {\n    bool succeeded = t->vm()->add_breakpoint(mark_addr_code, BKPT_USER);\n    ASSERT(t, succeeded);\n    ReplaySession::StepConstraints constraints =\n        strategy.setup_step_constraints();\n    result = current->replay_step(constraints);\n    t->vm()->remove_breakpoint(mark_addr_code, BKPT_USER);\n    // If we hit our breakpoint and there is no client breakpoint there,\n    // pretend we didn't hit it.\n    if (result.break_status.breakpoint_hit &&\n        !has_breakpoint_at_address(t, t->ip())) {\n      result.break_status.breakpoint_hit = false;\n    }\n    update_strategy_and_fix_watchpoint_quirk(strategy, constraints, result,\n                                             before);\n    return result;\n  }\n\n  // At required IP, but not in the correct state. Singlestep over this IP.\n  // We need the FAST_FORWARD option in case the mark state occurs after\n  // many iterations of a string instruction at this address.\n  ReplaySession::StepConstraints constraints(RUN_SINGLESTEP_FAST_FORWARD);\n  // We don't want to fast-forward past the mark state, so give the mark\n  // state as a state we should stop before. FAST_FORWARD always does at\n  // least one singlestep so one call to replay_step_to_mark will fast-forward\n  // to the state before the mark and return, then the next call to\n  // replay_step_to_mark will singlestep into the mark state.\n  constraints.stop_before_states.push_back(&mark.ptr->proto.regs);\n  result = current->replay_step(constraints);\n  // Hide internal singlestep but preserve other break statuses\n  result.break_status.singlestep_complete = false;\n  return result;\n}\n\nvoid ReplayTimeline::seek_to_proto_mark(const ProtoMark& pmark) {\n  seek_to_before_key(pmark.key);\n  unapply_breakpoints_and_watchpoints();\n  while (!pmark.equal_states(*current)) {\n    if (current->trace_reader().time() < pmark.key.trace_time) {\n      ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n      current->replay_step(constraints);\n    } else {\n      ReplayTask* t = current->current_task();\n      remote_code_ptr mark_addr = pmark.regs.ip();\n      if (t->regs().ip() == mark_addr &&\n          current->current_step_key().in_execution()) {\n        // At required IP, but not in the correct state. Singlestep over\n        // this IP.\n        ReplaySession::StepConstraints constraints(RUN_SINGLESTEP_FAST_FORWARD);\n        constraints.stop_before_states.push_back(&pmark.regs);\n        current->replay_step(constraints);\n      } else {\n        // Get a shared reference to t->vm() in case t dies during replay_step\n        shared_ptr<AddressSpace> vm = t->vm();\n        vm->add_breakpoint(mark_addr, BKPT_USER);\n        current->replay_step(RUN_CONTINUE);\n        vm->remove_breakpoint(mark_addr, BKPT_USER);\n      }\n    }\n  }\n}\n\nvoid ReplayTimeline::seek_to_mark(const Mark& mark) {\n  seek_up_to_mark(mark);\n  while (current_mark() != mark.ptr) {\n    unapply_breakpoints_and_watchpoints();\n    ReplayStepToMarkStrategy strategy;\n    replay_step_to_mark(mark, strategy);\n  }\n  current_at_or_after_mark = mark.ptr;\n  // XXX handle cases where breakpoints can't yet be applied\n}\n\n/**\n * Intel CPUs (and maybe others) coalesce iterations of REP-prefixed string\n * instructions so that a watchpoint on a byte at location L can fire after\n * the iteration that writes byte L+63 (or possibly more?).\n * This causes problems for rr since this coalescing doesn't happen when we\n * single-step.\n * This function is called after doing a ReplaySession::replay_step with\n * command == RUN_CONTINUE. RUN_SINGLESTEP and RUN_SINGLESTEP_FAST_FORWARD\n * disable this coalescing (the latter, because it's aware of watchpoints\n * and single-steps when it gets too close to them).\n * |before| is the state before we did the replay_step.\n * If a watchpoint fired, and it looks like it could have fired during a\n * string instruction, we'll backup to |before| and replay forward, stopping\n * before the breakpoint could fire and single-stepping to make sure the\n * coalescing quirk doesn't happen.\n * Returns true if we might have fixed something.\n */\nbool ReplayTimeline::fix_watchpoint_coalescing_quirk(ReplayResult& result,\n                                                     const ProtoMark& before) {\n  if (result.status == REPLAY_EXITED ||\n      result.break_status.data_watchpoints_hit().empty()) {\n    // no watchpoint hit. Nothing to fix.\n    return false;\n  }\n  if (!maybe_at_or_after_x86_string_instruction(result.break_status.task())) {\n    return false;\n  }\n\n  TaskUid after_tuid = result.break_status.task()->tuid();\n  Ticks after_ticks = result.break_status.task()->tick_count();\n  LOG(debug) << \"Fixing x86-string coalescing quirk from \" << before << \" to \"\n             << proto_mark() << \" (final cx \"\n             << result.break_status.task()->regs().cx() << \")\";\n\n  seek_to_proto_mark(before);\n\n  // Keep going until the watchpoint fires. It will either fire early, or at\n  // the same time as some other break.\n  apply_breakpoints_and_watchpoints();\n  bool approaching_ticks_target = false;\n  while (true) {\n    ReplayTask* t = current->current_task();\n    if (t->tuid() == after_tuid) {\n      if (approaching_ticks_target) {\n        // We don't need to set any stop_before_states here.\n        // RUN_SINGLESTEP_FAST_FORWARD always avoids the coalescing quirk, so\n        // if a watchpoint is triggered by the string instruction at\n        // string_instruction_ip, it will have the correct timing.\n        result = current->replay_step(RUN_SINGLESTEP_FAST_FORWARD);\n        if (!result.break_status.data_watchpoints_hit().empty()) {\n          LOG(debug) << \"Fixed x86-string coalescing quirk; now at \"\n                     << current_mark_key() << \" (new cx \"\n                     << result.break_status.task()->regs().cx() << \")\";\n          break;\n        }\n      } else {\n        ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n        constraints.ticks_target = after_ticks - 1;\n        result = current->replay_step(constraints);\n        approaching_ticks_target = result.break_status.approaching_ticks_target;\n      }\n      ASSERT(t, t->tick_count() <= after_ticks) << \"We went too far!\";\n    } else {\n      current->replay_step(RUN_CONTINUE);\n    }\n  }\n  return true;\n}\n\nbool ReplayTimeline::add_breakpoint(\n    ReplayTask* t, remote_code_ptr addr,\n    std::unique_ptr<BreakpointCondition> condition) {\n  if (has_breakpoint_at_address(t, addr)) {\n    remove_breakpoint(t, addr);\n  }\n  // Apply breakpoints now; we need to actually try adding this breakpoint\n  // to see if it works.\n  apply_breakpoints_and_watchpoints();\n  if (!t->vm()->add_breakpoint(addr, BKPT_USER)) {\n    return false;\n  }\n  breakpoints.insert(make_tuple(t->vm()->uid(), addr, std::move(condition)));\n  return true;\n}\n\nvoid ReplayTimeline::remove_breakpoint(ReplayTask* t, remote_code_ptr addr) {\n  if (breakpoints_applied) {\n    t->vm()->remove_breakpoint(addr, BKPT_USER);\n  }\n  ASSERT(t, has_breakpoint_at_address(t, addr));\n  auto it = breakpoints.lower_bound(make_tuple(t->vm()->uid(), addr, nullptr));\n  breakpoints.erase(it);\n}\n\nbool ReplayTimeline::has_breakpoint_at_address(ReplayTask* t,\n                                               remote_code_ptr addr) {\n  auto it = breakpoints.lower_bound(make_tuple(t->vm()->uid(), addr, nullptr));\n  return it != breakpoints.end() && get<0>(*it) == t->vm()->uid() &&\n         get<1>(*it) == addr;\n}\n\nbool ReplayTimeline::add_watchpoint(ReplayTask* t, remote_ptr<void> addr,\n                                    size_t num_bytes, WatchType type,\n                                    unique_ptr<BreakpointCondition> condition) {\n  if (has_watchpoint_at_address(t, addr, num_bytes, type)) {\n    remove_watchpoint(t, addr, num_bytes, type);\n  }\n  // Apply breakpoints now; we need to actually try adding this breakpoint\n  // to see if it works.\n  apply_breakpoints_and_watchpoints();\n  if (!t->vm()->add_watchpoint(addr, num_bytes, type)) {\n    return false;\n  }\n  watchpoints.insert(\n      make_tuple(t->vm()->uid(), addr, num_bytes, type, std::move(condition)));\n  no_watchpoints_hit_interval_start = no_watchpoints_hit_interval_end =\n      Mark();\n  return true;\n}\n\nvoid ReplayTimeline::remove_watchpoint(ReplayTask* t, remote_ptr<void> addr,\n                                       size_t num_bytes, WatchType type) {\n  if (breakpoints_applied) {\n    t->vm()->remove_watchpoint(addr, num_bytes, type);\n  }\n  ASSERT(t, has_watchpoint_at_address(t, addr, num_bytes, type));\n  auto it = watchpoints.lower_bound(\n      make_tuple(t->vm()->uid(), addr, num_bytes, type, nullptr));\n  watchpoints.erase(it);\n}\n\nbool ReplayTimeline::has_watchpoint_at_address(ReplayTask* t,\n                                               remote_ptr<void> addr,\n                                               size_t num_bytes,\n                                               WatchType type) {\n  auto it = watchpoints.lower_bound(\n      make_tuple(t->vm()->uid(), addr, num_bytes, type, nullptr));\n  return it != watchpoints.end() && get<0>(*it) == t->vm()->uid() &&\n         get<1>(*it) == addr && get<2>(*it) == num_bytes && get<3>(*it) == type;\n}\n\nvoid ReplayTimeline::remove_breakpoints_and_watchpoints() {\n  unapply_breakpoints_and_watchpoints();\n  breakpoints.clear();\n  watchpoints.clear();\n}\n\nvoid ReplayTimeline::apply_breakpoints_internal() {\n  for (auto& bp : breakpoints) {\n    AddressSpace* vm = current->find_address_space(get<0>(bp));\n    // XXX handle cases where we can't apply a breakpoint right now. Later\n    // during replay the address space might be created (or new mappings might\n    // be created) and we should reapply breakpoints then.\n    if (vm) {\n      vm->add_breakpoint(get<1>(bp), BKPT_USER);\n    }\n  }\n  for (auto& wp : watchpoints) {\n    AddressSpace* vm = current->find_address_space(get<0>(wp));\n    if (vm && get<3>(wp) == WATCH_EXEC) {\n      vm->add_watchpoint(get<1>(wp), get<2>(wp), get<3>(wp));\n    }\n  }\n}\n\nvoid ReplayTimeline::apply_breakpoints_and_watchpoints() {\n  if (breakpoints_applied) {\n    return;\n  }\n  breakpoints_applied = true;\n  apply_breakpoints_internal();\n  for (auto& wp : watchpoints) {\n    AddressSpace* vm = current->find_address_space(get<0>(wp));\n    // XXX handle cases where we can't apply a watchpoint right now. Later\n    // during replay the address space might be created (or new mappings might\n    // be created) and we should reapply watchpoints then.\n    // XXX we could make this more efficient by providing a method to set\n    // several watchpoints at once on a given AddressSpace.\n    if (vm && get<3>(wp) != WATCH_EXEC) {\n      vm->add_watchpoint(get<1>(wp), get<2>(wp), get<3>(wp));\n    }\n  }\n}\n\nvoid ReplayTimeline::unapply_breakpoints_internal() {\n  for (auto& bp : breakpoints) {\n    AddressSpace* vm = current->find_address_space(get<0>(bp));\n    if (vm) {\n      vm->remove_breakpoint(get<1>(bp), BKPT_USER);\n    }\n    for (auto& wp : watchpoints) {\n      AddressSpace* vm = current->find_address_space(get<0>(wp));\n      if (vm && get<3>(wp) == WATCH_EXEC) {\n        vm->remove_watchpoint(get<1>(wp), get<2>(wp), get<3>(wp));\n      }\n    }\n  }\n}\n\nvoid ReplayTimeline::unapply_breakpoints_and_watchpoints() {\n  if (!breakpoints_applied) {\n    return;\n  }\n  breakpoints_applied = false;\n  unapply_breakpoints_internal();\n  for (auto& wp : watchpoints) {\n    AddressSpace* vm = current->find_address_space(get<0>(wp));\n    if (vm && get<3>(wp) != WATCH_EXEC) {\n      vm->remove_watchpoint(get<1>(wp), get<2>(wp), get<3>(wp));\n    }\n  }\n}\n\nReplayResult ReplayTimeline::singlestep_with_breakpoints_disabled() {\n  apply_breakpoints_and_watchpoints();\n  unapply_breakpoints_internal();\n  auto result = current->replay_step(RUN_SINGLESTEP);\n  apply_breakpoints_internal();\n  return result;\n}\n\nbool ReplayTimeline::is_start_of_reverse_execution_barrier_event() {\n  if (current->trace_reader().time() != reverse_execution_barrier_event_ ||\n      current->current_step_key().in_execution()) {\n    return false;\n  }\n  LOG(debug) << \"Found reverse execution barrier at \" << mark();\n  return true;\n}\n\nbool ReplayTimeline::run_forward_to_intermediate_point(const Mark& end,\n                                                       ForceProgress force) {\n  unapply_breakpoints_and_watchpoints();\n\n  LOG(debug) << \"Trying to find intermediate point between \"\n             << current_mark_key() << \" and \" << end\n             << (force == FORCE_PROGRESS ? \" (forced)\" : \"\");\n\n  FrameTime now = current->trace_reader().time();\n  FrameTime mid = (now + end.ptr->proto.key.trace_time) / 2;\n  if (now < mid && mid < end.ptr->proto.key.trace_time) {\n    ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n    while (current->trace_reader().time() < mid) {\n      current->replay_step(constraints);\n    }\n    DEBUG_ASSERT(current->trace_reader().time() == mid);\n    LOG(debug) << \"Ran forward to mid event \" << current_mark_key();\n    return true;\n  }\n\n  if (current->trace_reader().time() < end.ptr->proto.key.trace_time &&\n      end.ptr->ticks_at_event_start < end.ptr->proto.key.ticks) {\n    ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n    while (current->trace_reader().time() < end.ptr->proto.key.trace_time) {\n      current->replay_step(constraints);\n    }\n    DEBUG_ASSERT(current->trace_reader().time() ==\n                 end.ptr->proto.key.trace_time);\n    LOG(debug) << \"Ran forward to event \" << current_mark_key();\n    return true;\n  }\n\n  ReplayTask* t = current->current_task();\n  if (!t) {\n    LOG(debug) << \"Made no progress\";\n    return false;\n  }\n\n  Ticks start_ticks = t->tick_count();\n  Ticks end_ticks = current->current_trace_frame().ticks();\n  if (end.ptr->proto.key.trace_time == current->trace_reader().time()) {\n    end_ticks = min(end_ticks, end.ptr->proto.key.ticks);\n  }\n  ASSERT(t, start_ticks <= end_ticks);\n  Ticks target = min(end_ticks, (start_ticks + end_ticks) / 2);\n  ProtoMark m = proto_mark();\n  if (target != end_ticks) {\n    // We can only try stepping if we won't end up at `end`\n    ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n    constraints.ticks_target = target;\n    ReplayResult result = current->replay_step(constraints);\n    if (!m.equal_states(*current)) {\n      while (t->tick_count() < target &&\n             !result.break_status.approaching_ticks_target) {\n        result = current->replay_step(constraints);\n      }\n      LOG(debug) << \"Ran forward to \" << current_mark_key();\n      return true;\n    }\n    DEBUG_ASSERT(result.break_status.approaching_ticks_target);\n    DEBUG_ASSERT(t->tick_count() == start_ticks);\n  }\n\n  // We didn't make any progress that way.\n  // Normally we should just give up now and let reverse_continue keep\n  // running and hitting breakpoints etc since we're pretty close to the\n  // target already and the overhead of what we have to do here otherwise\n  // can be high. But there's a pathological case where reverse_continue\n  // is hitting a breakpoint on each iteration of a string instruction.\n  // If that's happening then we will be told to force progress.\n  if (force == FORCE_PROGRESS) {\n    // Let's try a fast-forward singlestep to jump over an x86 string\n    // instruction that may be triggering a lot of breakpoint hits. Make\n    // sure\n    // we stop before |end|.\n    ReplaySession::shr_ptr tmp_session;\n    if (start_ticks + 1 >= end_ticks) {\n      // This singlestep operation might leave us at |end|, which is not\n      // allowed. So make a backup of the current state.\n      tmp_session = current->clone();\n      LOG(debug) << \"Created backup tmp_session\";\n    }\n    ReplaySession::StepConstraints constraints =\n        ReplaySession::StepConstraints(RUN_SINGLESTEP_FAST_FORWARD);\n    constraints.stop_before_states.push_back(&end.ptr->proto.regs);\n    ReplayResult result = current->replay_step(constraints);\n    if (at_mark(end)) {\n      DEBUG_ASSERT(tmp_session);\n      current = std::move(tmp_session);\n      LOG(debug) << \"Singlestepping arrived at |end|, restoring session\";\n    } else if (!m.equal_states(*current)) {\n      LOG(debug) << \"Did fast-singlestep forward to \" << current_mark_key();\n      return true;\n    }\n  }\n\n  LOG(debug) << \"Made no progress\";\n  return false;\n}\n\n/**\n * Don't allow more than this number of breakpoint/watchpoint stops\n * in a given replay interval. If we hit more than this, try to split\n * the interval in half and replay with watchpoints/breakpoints in the latter\n * half.\n */\nstatic const int stop_count_limit = 20;\n\nstatic ReplayTask* to_replay_task(const BreakStatus& status) {\n  return static_cast<ReplayTask*>(status.task());\n}\n\nstatic bool arch_watch_fires_before_instr(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n    case x86_64:\n      return false;\n    case aarch64:\n      return true;\n    default:\n      FATAL() << \"Unknown architecture\";\n      return false;\n  }\n}\n\nReplayResult ReplayTimeline::reverse_continue(\n    const std::function<bool(ReplayTask* t, const BreakStatus &)>& stop_filter,\n    const std::function<bool()>& interrupt_check) {\n  Mark end = mark();\n  LOG(debug) << \"ReplayTimeline::reverse_continue from \" << end;\n\n  bool last_stop_is_watch = false;\n  bool last_stop_is_signal = false;\n  ReplayResult final_result;\n  TaskUid final_tuid;\n  Ticks final_ticks = 0;\n  Mark dest;\n  vector<Mark> restart_points;\n\n  while (!dest) {\n    Mark start = mark();\n    bool checkpoint_at_first_break;\n    if (start >= end) {\n      checkpoint_at_first_break = true;\n      if (restart_points.empty()) {\n        seek_to_before_key(end.ptr->proto.key);\n        start = mark();\n        if (start >= end) {\n          LOG(debug) << \"Couldn't seek to before \" << end << \", returning exit\";\n          // Can't go backwards. Call this an exit.\n          final_result.status = REPLAY_EXITED;\n          final_result.break_status = BreakStatus();\n          return final_result;\n        }\n        LOG(debug) << \"Seeked backward from \" << end << \" to \" << start;\n      } else {\n        Mark seek = restart_points.back();\n        restart_points.pop_back();\n        seek_to_mark(seek);\n        LOG(debug) << \"Seeked directly backward from \" << start << \" to \"\n                   << seek;\n        start = std::move(seek);\n      }\n    } else {\n      checkpoint_at_first_break = false;\n    }\n    maybe_add_reverse_exec_checkpoint(EXPECT_SHORT_REVERSE_EXECUTION);\n\n    LOG(debug) << \"reverse-continue continuing forward from \" << start\n               << \" up to \" << end;\n\n    bool at_breakpoint = false;\n    bool before_watchpoint = false;\n    ReplayStepToMarkStrategy strategy;\n    int stop_count = 0;\n    bool made_progress_between_stops = false;\n    remote_code_ptr avoidable_stop_ip;\n    Ticks avoidable_stop_ticks = 0;\n    while (true) {\n      ReplayResult result;\n      if (at_breakpoint) {\n        result = singlestep_with_breakpoints_disabled();\n      } else if (before_watchpoint) {\n        // N.B.: This state is only reached on architectures where watchpoints\n        // fire *before* applying instruction effects (e.g. aarch64)\n        unapply_breakpoints_and_watchpoints();\n        result = current->replay_step(RUN_SINGLESTEP);\n      } else {\n        apply_breakpoints_and_watchpoints();\n        result = replay_step_to_mark(end, strategy);\n        // This will remove all reverse-exec checkpoints ahead of the\n        // current time, and add new ones if necessary. This should be\n        // helpful if we have to reverse-continue far back in time, where\n        // the interval between 'start' and 'end' could be lengthy; we'll\n        // populate the interval with new checkpoints, speeding up\n        // the following seek and possibly future operations.\n      }\n      at_breakpoint = result.break_status.hardware_or_software_breakpoint_hit();\n      bool avoidable_stop = result.break_status.breakpoint_hit ||\n                            !result.break_status.watchpoints_hit.empty();\n      if (avoidable_stop) {\n        made_progress_between_stops =\n            avoidable_stop_ip != result.break_status.task()->ip() ||\n            avoidable_stop_ticks != result.break_status.task()->tick_count();\n        avoidable_stop_ip = result.break_status.task()->ip();\n        avoidable_stop_ticks = result.break_status.task()->tick_count();\n      }\n      before_watchpoint = false;\n\n      evaluate_conditions(result);\n      if (result.break_status.any_break() &&\n          !stop_filter(to_replay_task(result.break_status), result.break_status)) {\n        result.break_status = BreakStatus();\n      }\n\n      maybe_add_reverse_exec_checkpoint(EXPECT_SHORT_REVERSE_EXECUTION);\n      if (checkpoint_at_first_break && dest != start &&\n          result.break_status.any_break()) {\n        checkpoint_at_first_break = false;\n        set_short_checkpoint();\n      }\n\n      if (!result.break_status.data_watchpoints_hit().empty() ||\n          result.break_status.signal) {\n        dest = mark();\n        if (result.break_status.signal) {\n          LOG(debug) << \"Found signal break at \" << dest;\n          last_stop_is_watch = false;\n          last_stop_is_signal = true;\n        } else {\n          LOG(debug) << \"Found watch break at \" << dest << \", addr=\"\n                     << result.break_status.data_watchpoints_hit()[0].addr;\n          if (arch_watch_fires_before_instr(current->arch())) {\n            before_watchpoint = true;\n          }\n          last_stop_is_signal = false;\n          last_stop_is_watch = true;\n        }\n        final_result = result;\n        final_tuid = result.break_status.task()\n                         ? result.break_status.task()->tuid()\n                         : TaskUid();\n        final_ticks = result.break_status.task()\n                          ? result.break_status.task()->tick_count()\n                          : 0;\n      }\n      DEBUG_ASSERT(result.status == REPLAY_CONTINUE);\n\n      if (is_start_of_reverse_execution_barrier_event()) {\n        dest = mark();\n        final_result = result;\n        final_result.break_status.task_context =\n            TaskContext(current->current_task());\n        final_result.break_status.task_exit = true;\n        final_tuid = final_result.break_status.task()->tuid();\n        final_ticks = result.break_status.task()->tick_count();\n        last_stop_is_watch = false;\n        last_stop_is_signal = false;\n      }\n\n      if (at_mark(end)) {\n        // In the next iteration, retry from an earlier checkpoint.\n        end = start;\n        break;\n      }\n\n      // If there is a breakpoint at the current ip() where we start a\n      // reverse-continue, gdb expects us to skip it.\n      if (result.break_status.hardware_or_software_breakpoint_hit()) {\n        dest = mark();\n        LOG(debug) << \"Found breakpoint break at \" << dest;\n        final_result = result;\n        final_tuid = result.break_status.task()\n                         ? result.break_status.task()->tuid()\n                         : TaskUid();\n        final_ticks = result.break_status.task()\n                          ? result.break_status.task()->tick_count()\n                          : 0;\n        last_stop_is_watch = false;\n        last_stop_is_signal = false;\n      }\n\n      if (interrupt_check()) {\n        LOG(debug) << \"Interrupted at \" << end;\n        seek_to_mark(end);\n        final_result = ReplayResult();\n        final_result.break_status.task_context =\n            TaskContext(current->current_task());\n        return final_result;\n      }\n\n      if (avoidable_stop) {\n        ++stop_count;\n        if (stop_count > stop_count_limit) {\n          Mark before_running = mark();\n          if (run_forward_to_intermediate_point(end,\n                                                made_progress_between_stops\n                                                    ? DONT_FORCE_PROGRESS\n                                                    : FORCE_PROGRESS)) {\n            DEBUG_ASSERT(!at_mark(end));\n            // We made some progress towards |end| with breakpoints/watchpoints\n            // disabled, without reaching |end|. Continuing running forward from\n            // here with breakpoints/watchpoints enabled. If we need to seek\n            // backwards again, try resuming from the point where we disabled\n            // breakpoints/watchpoints.\n            if (dest) {\n              restart_points.push_back(start);\n            }\n            restart_points.push_back(before_running);\n            dest = Mark();\n            break;\n          }\n        }\n      }\n    }\n  }\n\n  if (last_stop_is_watch || last_stop_is_signal) {\n    if (last_stop_is_watch && arch_watch_fires_before_instr(current->arch())) {\n      // GDB expect reverse continue to stop before reversing past the watchpoint\n      // (i.e. pc points to end of instruction) on aarch64\n      // but the dest is pointing to the beginning of the instruction\n      // so we need to single step the instruction at dest.\n      LOG(debug) << \"Single step past the watchpoint\" << dest;\n      seek_to_mark(dest);\n      unapply_breakpoints_and_watchpoints();\n      current->replay_step(RUN_SINGLESTEP);\n    } else {\n      LOG(debug)\n        << \"Performing final reverse-singlestep to pass over watch/signal\";\n      auto stop_filter = [&](ReplayTask* t,const BreakStatus &) { return t->tuid() == final_tuid; };\n      reverse_singlestep(dest, final_tuid, final_ticks, stop_filter,\n                         interrupt_check);\n    }\n  } else {\n    LOG(debug) << \"Seeking to final destination \" << dest;\n    seek_to_mark(dest);\n  }\n  // fix break_status.task since the actual ReplayTask* may have changed\n  // since we saved final_result\n  final_result.break_status.task_context =\n      TaskContext(current->find_task(final_tuid));\n  // Hide any singlestepping we did, since a continue operation should\n  // never return a singlestep status\n  final_result.break_status.singlestep_complete = false;\n  return final_result;\n}\n\nvoid ReplayTimeline::update_observable_break_status(\n    ReplayTimeline::Mark& now, const ReplayResult& result) {\n  now = mark();\n  if (!no_watchpoints_hit_interval_start ||\n      !result.break_status.watchpoints_hit.empty()) {\n    no_watchpoints_hit_interval_start = now;\n  }\n}\n\nReplayResult ReplayTimeline::reverse_singlestep(\n    const Mark& origin, const TaskUid& step_tuid, Ticks step_ticks,\n    const std::function<bool(ReplayTask* t,const BreakStatus &)>& stop_filter,\n    const std::function<bool()>& interrupt_check) {\n  LOG(debug) << \"ReplayTimeline::reverse_singlestep from \" << origin;\n\n  Mark outer = origin;\n  Ticks ticks_target = step_ticks - 1;\n\n  while (true) {\n    Mark end = outer;\n    Mark start;\n    bool seen_barrier = false;\n\n    while (true) {\n      MarkKey current_key = end.ptr->proto.key;\n\n      while (true) {\n        if (end.ptr->proto.key.trace_time != current_key.trace_time ||\n            end.ptr->proto.key.ticks != current_key.ticks) {\n          break;\n        }\n        seek_to_before_key(current_key);\n        maybe_add_reverse_exec_checkpoint(EXPECT_SHORT_REVERSE_EXECUTION);\n        if (current_mark_key() == current_key) {\n          // Can't go further back. Treat this as an exit.\n          LOG(debug) << \"Couldn't seek to before \" << end << \", returning exit\";\n          ReplayResult result;\n          result.status = REPLAY_EXITED;\n          result.break_status = BreakStatus();\n          return result;\n        }\n        LOG(debug) << \"Seeked backward from \" << current_key << \" to \"\n                   << current_mark_key();\n        current_key = current_mark_key();\n      }\n\n      start = mark();\n      LOG(debug) << \"Running forward from \" << start;\n      // Now run forward until we're reasonably close to the correct tick value.\n      ReplaySession::StepConstraints constraints(RUN_CONTINUE);\n      bool approaching_ticks_target = false;\n      bool seen_other_task_break = false;\n      while (!at_mark(end)) {\n        ReplayTask* t = current->current_task();\n        if (stop_filter(t, BreakStatus()) && current->done_initial_exec()) {\n          if (t->tuid() == step_tuid) {\n            if (t->tick_count() >= ticks_target) {\n              // Don't step any further.\n              LOG(debug) << \"Approaching ticks target\";\n              approaching_ticks_target = true;\n              break;\n            }\n            unapply_breakpoints_and_watchpoints();\n            constraints.ticks_target =\n                constraints.command == RUN_CONTINUE ? ticks_target : 0;\n            ReplayResult result;\n            result = current->replay_step(constraints);\n            if (result.break_status.approaching_ticks_target) {\n              LOG(debug) << \"   approached ticks target at \"\n                         << current_mark_key();\n              constraints =\n                  ReplaySession::StepConstraints(RUN_SINGLESTEP_FAST_FORWARD);\n            }\n          } else {\n            if (seen_other_task_break) {\n              unapply_breakpoints_and_watchpoints();\n            } else {\n              apply_breakpoints_and_watchpoints();\n            }\n            constraints.ticks_target = 0;\n            ReplayResult result = current->replay_step(RUN_CONTINUE);\n            if (result.break_status.any_break()) {\n              seen_other_task_break = true;\n            }\n          }\n        } else {\n          unapply_breakpoints_and_watchpoints();\n          constraints.ticks_target = 0;\n          current->replay_step(RUN_CONTINUE);\n        }\n        if (is_start_of_reverse_execution_barrier_event()) {\n          seen_barrier = true;\n        }\n        maybe_add_reverse_exec_checkpoint(EXPECT_SHORT_REVERSE_EXECUTION);\n      }\n\n      if (approaching_ticks_target || seen_barrier) {\n        break;\n      }\n      if (seen_other_task_break) {\n        // We saw a break in another task that the debugger cares about, but\n        // that's not the stepping task. At this point reverse-singlestep\n        // will move back past that break, so We'll need to report that break\n        // instead of the singlestep.\n        return reverse_continue(stop_filter, interrupt_check);\n      }\n      end = start;\n    }\n    DEBUG_ASSERT(stop_filter(current->current_task(), BreakStatus()) || seen_barrier);\n\n    Mark destination_candidate;\n    Mark step_start = set_short_checkpoint();\n    ReplayResult destination_candidate_result;\n    TaskUid destination_candidate_tuid;\n    // True when the singlestep starting at the destination candidate saw\n    // another task break.\n    bool destination_candidate_saw_other_task_break = false;\n\n    if (is_start_of_reverse_execution_barrier_event()) {\n      destination_candidate = mark();\n      destination_candidate_result.break_status.task_exit = true;\n      destination_candidate_tuid = current->current_task()->tuid();\n    }\n\n    no_watchpoints_hit_interval_start = Mark();\n    bool seen_other_task_break = false;\n    while (true) {\n      Mark now;\n      ReplayResult result;\n      if (stop_filter(current->current_task(), BreakStatus())) {\n        apply_breakpoints_and_watchpoints();\n        if (current->current_task()->tuid() == step_tuid) {\n          Mark before_step = mark();\n          ReplaySession::StepConstraints constraints(\n              RUN_SINGLESTEP_FAST_FORWARD);\n          constraints.stop_before_states.push_back(&end.ptr->proto.regs);\n          result = current->replay_step(constraints);\n          ReplayResult result_with_breakpoints_and_watchpoints = result;\n          update_observable_break_status(now, result);\n          bool stopped_before_watchpoint =\n            !result.break_status.data_watchpoints_hit().empty() &&\n            arch_watch_fires_before_instr(current->arch());\n          if (result.break_status.hardware_or_software_breakpoint_hit() ||\n              stopped_before_watchpoint) {\n            // If we hit a breakpoint while singlestepping, we didn't\n            // make any progress.\n            unapply_breakpoints_and_watchpoints();\n            result = current->replay_step(constraints);\n            update_observable_break_status(now, result);\n          }\n          if (result.break_status.singlestep_complete) {\n            mark_after_singlestep(before_step, result);\n            if (now > end) {\n              // This last step is not usable.\n              LOG(debug) << \"   not usable, stopping now\";\n              break;\n            } else if (now == end &&\n                       result.break_status.signal &&\n                       result.break_status.signal->si_signo == SIGTRAP &&\n                       is_advanced_pc_and_signaled_instruction(result.break_status.task(),\n                                                               result.break_status.task()->ip())) {\n              LOG(debug) << \"   singlestepped exactly to instruction that advances pc and signals (e.g. int3),\"\n                         << \" pretending we stopped earlier.\";\n              break;\n            }\n            if (stopped_before_watchpoint) {\n              // On ARM, watchpoints fire before the instruction executes.\n              // This instruction triggered the watchpoint so we need to\n              // stop before the instruction is reverse-executed, i.e. after\n              // it actually executed.\n              destination_candidate = now;\n            } else {\n              destination_candidate = step_start;\n            }\n            LOG(debug) << \"Setting candidate after step: \"\n                       << destination_candidate;\n            destination_candidate_result = result_with_breakpoints_and_watchpoints;\n            destination_candidate_tuid = result.break_status.task()->tuid();\n            destination_candidate_saw_other_task_break = seen_other_task_break;\n            seen_other_task_break = false;\n            step_start = now;\n          }\n        } else {\n          result = current->replay_step(RUN_CONTINUE);\n          update_observable_break_status(now, result);\n          if (result.break_status.any_break()) {\n            seen_other_task_break = true;\n          }\n          if (result.break_status.hardware_or_software_breakpoint_hit() ||\n              (!result.break_status.data_watchpoints_hit().empty() &&\n               arch_watch_fires_before_instr(current->arch()))) {\n            unapply_breakpoints_and_watchpoints();\n            result = current->replay_step(RUN_SINGLESTEP_FAST_FORWARD);\n            update_observable_break_status(now, result);\n            if (result.break_status.any_break()) {\n              seen_other_task_break = true;\n            }\n          }\n        }\n      } else {\n        unapply_breakpoints_and_watchpoints();\n        result = current->replay_step(RUN_CONTINUE);\n        no_watchpoints_hit_interval_start = Mark();\n        now = mark();\n      }\n\n      if (is_start_of_reverse_execution_barrier_event()) {\n        destination_candidate = mark();\n        LOG(debug) << \"Setting candidate to barrier \" << destination_candidate;\n        destination_candidate_result = result;\n        destination_candidate_result.break_status.task_exit = true;\n        destination_candidate_tuid = current->current_task()->tuid();\n        destination_candidate_saw_other_task_break = false;\n        seen_other_task_break = false;\n      }\n\n      if (now >= end) {\n        LOG(debug) << \"Stepped to \" << now << \" (>= \" << end << \"), stopping\";\n        break;\n      }\n      maybe_add_reverse_exec_checkpoint(EXPECT_SHORT_REVERSE_EXECUTION);\n    }\n    no_watchpoints_hit_interval_end =\n        no_watchpoints_hit_interval_start ? end : Mark();\n\n    if (seen_other_task_break || destination_candidate_saw_other_task_break) {\n      // We saw a break in another task that the debugger cares about, but\n      // that's not the stepping task. Report that break instead of the\n      // singlestep.\n      return reverse_continue(stop_filter, interrupt_check);\n    }\n\n    if (destination_candidate) {\n      LOG(debug) << \"Found destination \" << destination_candidate;\n      seek_to_mark(destination_candidate);\n      destination_candidate_result.break_status.task_context =\n          TaskContext(current->find_task(destination_candidate_tuid));\n      DEBUG_ASSERT(destination_candidate_result.break_status.task());\n      evaluate_conditions(destination_candidate_result);\n      return destination_candidate_result;\n    }\n\n    // No destination candidate found. Search further backward.\n    outer = start;\n  }\n}\n\nvoid ReplayTimeline::evaluate_conditions(ReplayResult& result) {\n  ReplayTask* t = to_replay_task(result.break_status);\n  if (!t) {\n    return;\n  }\n\n  auto auid = t->vm()->uid();\n\n  if (result.break_status.breakpoint_hit) {\n    auto addr = t->ip();\n    auto it = breakpoints.lower_bound(make_tuple(auid, addr, nullptr));\n    bool hit = false;\n    while (it != breakpoints.end() && get<0>(*it) == auid &&\n           get<1>(*it) == addr) {\n      const unique_ptr<BreakpointCondition>& cond = get<2>(*it);\n      if (!cond || cond->evaluate(t)) {\n        hit = true;\n        break;\n      }\n      ++it;\n    }\n    if (!hit) {\n      result.break_status.breakpoint_hit = false;\n    }\n  }\n\n  for (auto i = result.break_status.watchpoints_hit.begin();\n       i != result.break_status.watchpoints_hit.end();) {\n    auto& w = *i;\n    auto it = watchpoints.lower_bound(\n        make_tuple(auid, w.addr, w.num_bytes, w.type, nullptr));\n    bool hit = false;\n    while (it != watchpoints.end() && get<0>(*it) == auid &&\n           get<1>(*it) == w.addr && get<2>(*it) == w.num_bytes &&\n           get<3>(*it) == w.type) {\n      const unique_ptr<BreakpointCondition>& cond = get<4>(*it);\n      if (!cond || cond->evaluate(t)) {\n        hit = true;\n        break;\n      }\n      ++it;\n    }\n    if (hit) {\n      ++i;\n    } else {\n      i = result.break_status.watchpoints_hit.erase(i);\n    }\n  }\n}\n\nReplayResult ReplayTimeline::replay_step_forward(RunCommand command) {\n  DEBUG_ASSERT(command != RUN_SINGLESTEP_FAST_FORWARD);\n\n  ReplayResult result;\n  apply_breakpoints_and_watchpoints();\n  ProtoMark before = proto_mark();\n  current->set_visible_execution(true);\n  ReplaySession::StepConstraints constraints(command);\n  result = current->replay_step(constraints);\n  current->set_visible_execution(false);\n  if (command == RUN_CONTINUE) {\n    // Since it's easy for us to fix the coalescing quirk for forward\n    // execution, we may as well do so. It's nice to have forward execution\n    // behave consistently with reverse execution.\n    fix_watchpoint_coalescing_quirk(result, before);\n    // Hide any singlestepping we did\n    result.break_status.singlestep_complete = false;\n  }\n  maybe_add_reverse_exec_checkpoint(LOW_OVERHEAD);\n\n  bool did_hit_breakpoint =\n      result.break_status.hardware_or_software_breakpoint_hit();\n  evaluate_conditions(result);\n  if (did_hit_breakpoint && !result.break_status.any_break()) {\n    // Singlestep past the breakpoint\n    current->set_visible_execution(true);\n    result = singlestep_with_breakpoints_disabled();\n    if (command == RUN_CONTINUE) {\n      result.break_status.singlestep_complete = false;\n    }\n    current->set_visible_execution(false);\n  }\n  return result;\n}\n\nReplayResult ReplayTimeline::reverse_singlestep(\n    const TaskUid& tuid, Ticks tuid_ticks,\n    const std::function<bool(ReplayTask* t, const BreakStatus &)>& stop_filter,\n    const std::function<bool()>& interrupt_check) {\n  return reverse_singlestep(mark(), tuid, tuid_ticks, stop_filter,\n                            interrupt_check);\n}\n\nReplayTimeline::Progress ReplayTimeline::estimate_progress() {\n  Session::Statistics stats = current->statistics();\n  // The following parameters were estimated by running Firefox startup\n  // and shutdown in an opt build on a Lenovo W530 laptop, replaying with\n  // DUMP_STATS_PERIOD set to 100 (twice, and using only values from the\n  // second run, to ensure caches are warm), and then minimizing least-squares\n  // error.\n  static const double microseconds_per_tick = 0.0020503143;\n  static const double microseconds_per_syscall = 39.6793587609;\n  static const double microseconds_per_byte_written = 0.001833611;\n  static const double microseconds_constant = 997.8257239043;\n  return Progress(microseconds_per_tick * stats.ticks_processed +\n                  microseconds_per_syscall * stats.syscalls_performed +\n                  microseconds_per_byte_written * stats.bytes_written +\n                  microseconds_constant);\n}\n\n/*\n * Checkpointing strategy:\n *\n * We define a series of intervals of increasing length, each one ending at\n * the current replay position. In each interval N, we allow at most N\n * checkpoints. We ensure that interval lengths grow exponentially (in the\n * limit), so the maximum number of checkpoints for a given execution length\n * L is O(log L).\n *\n * Interval N has length inter_checkpoint_interval to the\n * power of checkpoint_interval_exponent.\n * We allow at most N checkpoints in interval N.\n * To discard excess checkpoints, first pick the smallest interval N with\n * too many checkpoints, and discard the latest checkpoint in interval N\n * that is not in interval N-1. Repeat until there are no excess checkpoints.\n * All checkpoints after the current replay point are always discarded.\n * The script checkpoint-visualizer.html simulates this algorithm and\n * visualizes its results.\n * The implementation here is quite naive, but that's OK because we will\n * never have a large number of checkpoints.\n */\n\n/**\n * Try to space out our checkpoints by a minimum of this much in LOW_OVERHEAD\n * mode.\n * This is currently aiming for about 0.5s of replay time, so a reverse step or\n * continue whose destination is within 0.5 should take at most a second.\n * Also, based on a guesstimate that taking checkpoints of Firefox requires\n * about 50ms, this would make checkpointing overhead about 10% of replay time,\n * which sounds reasonable.\n */\nstatic ReplayTimeline::Progress low_overhead_inter_checkpoint_interval = 500000;\n\n/**\n * Space out checkpoints linearly by this much in\n * EXPECT_SHORT_REVERSE_EXECUTION mode, until we reach\n * low_overhead_inter_checkpoint_interval.\n */\nstatic ReplayTimeline::Progress\n    expecting_reverse_exec_inter_checkpoint_interval = 100000;\n\n/**\n * Make each interval this much bigger than the previous.\n */\nstatic float checkpoint_interval_exponent = 2;\n\nstatic ReplayTimeline::Progress inter_checkpoint_interval(\n    ReplayTimeline::CheckpointStrategy strategy) {\n  return strategy == ReplayTimeline::LOW_OVERHEAD\n             ? low_overhead_inter_checkpoint_interval\n             : expecting_reverse_exec_inter_checkpoint_interval;\n}\n\nstatic ReplayTimeline::Progress next_interval_length(\n    ReplayTimeline::Progress len) {\n  if (len >= low_overhead_inter_checkpoint_interval) {\n    return (ReplayTimeline::Progress)ceil(checkpoint_interval_exponent * len);\n  }\n  return len + expecting_reverse_exec_inter_checkpoint_interval;\n}\n\nvoid ReplayTimeline::maybe_add_reverse_exec_checkpoint(\n    CheckpointStrategy strategy) {\n  discard_future_reverse_exec_checkpoints();\n\n  Progress now = estimate_progress();\n  auto it = reverse_exec_checkpoints.rbegin();\n  if (it != reverse_exec_checkpoints.rend() &&\n      it->second >= now - inter_checkpoint_interval(strategy)) {\n    // Latest checkpoint is close enough; we don't need to do anything.\n    return;\n  }\n\n  if (!current->can_clone()) {\n    // We can't create a checkpoint right now.\n    return;\n  }\n\n  // We always discard checkpoints before adding the new one to reduce the\n  // maximum checkpoint count by one.\n  discard_past_reverse_exec_checkpoints(strategy);\n\n  Mark m = add_explicit_checkpoint();\n  LOG(debug) << \"Creating reverse-exec checkpoint at \" << m;\n  reverse_exec_checkpoints[m] = now;\n}\n\nvoid ReplayTimeline::discard_future_reverse_exec_checkpoints() {\n  Progress now = estimate_progress();\n  while (true) {\n    auto it = reverse_exec_checkpoints.rbegin();\n    if (it == reverse_exec_checkpoints.rend() || it->second <= now) {\n      break;\n    }\n    LOG(debug) << \"Discarding reverse-exec future checkpoint at \"\n               << *it->first.ptr;\n    remove_explicit_checkpoint(it->first);\n    reverse_exec_checkpoints.erase(it->first);\n  }\n}\n\nvoid ReplayTimeline::discard_past_reverse_exec_checkpoints(\n    CheckpointStrategy strategy) {\n  Progress now = estimate_progress();\n  // No checkpoints are allowed in the first interval, since we're about to\n  // add one there.\n  int checkpoints_allowed = 0;\n  int checkpoints_in_range = 0;\n  auto it = reverse_exec_checkpoints.rbegin();\n  vector<Mark> checkpoints_to_delete;\n  for (Progress len = inter_checkpoint_interval(strategy);;\n       len = next_interval_length(len)) {\n    Progress start = now - len;\n    // Count checkpoints >= start, starting at 'it', and leave the first\n    // checkpoint entry < start in 'tmp_it'.\n    auto tmp_it = it;\n    while (tmp_it != reverse_exec_checkpoints.rend() &&\n           tmp_it->second >= start) {\n      ++checkpoints_in_range;\n      ++tmp_it;\n    }\n    // Delete excess checkpoints starting with 'it'.\n    while (checkpoints_in_range > checkpoints_allowed) {\n      checkpoints_to_delete.push_back(it->first);\n      --checkpoints_in_range;\n      ++it;\n    }\n    ++checkpoints_allowed;\n    it = tmp_it;\n    if (it == reverse_exec_checkpoints.rend()) {\n      break;\n    }\n  }\n\n  for (auto& m : checkpoints_to_delete) {\n    LOG(debug) << \"Discarding reverse-exec checkpoint at \" << m;\n    remove_explicit_checkpoint(m);\n    reverse_exec_checkpoints.erase(m);\n  }\n}\n\nReplayTimeline::Mark ReplayTimeline::set_short_checkpoint() {\n  if (!can_add_checkpoint()) {\n    return mark();\n  }\n\n  // Add checkpoint before removing one in case m ==\n  // reverse_exec_short_checkpoint\n  Mark m = add_explicit_checkpoint();\n  LOG(debug) << \"Creating short-checkpoint at \" << m;\n  if (reverse_exec_short_checkpoint) {\n    LOG(debug) << \"Discarding old short-checkpoint at \"\n               << reverse_exec_short_checkpoint;\n    remove_explicit_checkpoint(reverse_exec_short_checkpoint);\n  }\n  swap(m, reverse_exec_short_checkpoint);\n  return reverse_exec_short_checkpoint;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ReplayTimeline.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REPLAY_TIMELINE_H_\n#define RR_REPLAY_TIMELINE_H_\n\n#include <iostream>\n#include <map>\n#include <memory>\n#include <tuple>\n#include <vector>\n\n#include \"BreakpointCondition.h\"\n#include \"Registers.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"ReturnAddressList.h\"\n#include \"TraceFrame.h\"\n\nnamespace rr {\n\nenum RunDirection { RUN_FORWARD, RUN_BACKWARD };\n\n/**\n * This class manages a set of ReplaySessions corresponding to different points\n * in the same recording. It provides an API for explicitly managing\n * checkpoints along this timeline and navigating to specific events.\n */\nclass ReplayTimeline {\nprivate:\n  struct InternalMark;\n\npublic:\n  ReplayTimeline(std::shared_ptr<ReplaySession> session);\n  ~ReplayTimeline();\n\n  /**\n   * An estimate of how much progress a session has made. This should roughly\n   * correlate to the time required to replay from the start of a session\n   * to the current point, in microseconds.\n   */\n  typedef int64_t Progress;\n\n  /**\n   * A Mark references a precise point in time during the replay.\n   * It can have an associated ReplaySession checkpoint.\n   * It's mainly just a wrapper around InternalMark, but\n   * InternalMark does not contain enough state to determine the\n   * relative ordering of two Marks. So ReplayTimeline maintains\n   * a database of Marks stored in time order to let us do such\n   * comparisons.\n   */\n  class Mark {\n  public:\n    Mark() {}\n\n    bool operator<(const Mark& other) const {\n      return ReplayTimeline::less_than(*this, other);\n    }\n    bool operator>(const Mark& other) const { return other < *this; }\n    bool operator<=(const Mark& other) const { return !(*this > other); }\n    bool operator>=(const Mark& other) const { return !(*this < other); }\n    bool operator==(const Mark& other) const { return ptr == other.ptr; }\n    bool operator!=(const Mark& other) const { return !(*this == other); }\n    operator bool() const { return ptr != nullptr; }\n\n    /**\n     * Return the values of the general-purpose registers at this mark.\n     */\n    const Registers& regs() const { return ptr->proto.regs; }\n    const ExtraRegisters& extra_regs() const { return ptr->extra_regs; }\n\n    FrameTime time() const { return ptr->proto.key.trace_time; }\n\n  private:\n    friend class ReplayTimeline;\n    friend std::ostream& operator<<(std::ostream& s, const Mark& o);\n\n    Mark(std::shared_ptr<InternalMark>& weak) { swap(ptr, weak); }\n\n    std::shared_ptr<InternalMark> ptr;\n  };\n\n  /**\n   * The current state. The current state can be moved forward or backward\n   * using ReplaySession's APIs. Do not set breakpoints on its tasks directly.\n   * Use ReplayTimeline's breakpoint methods.\n   */\n  ReplaySession& current_session() { return *current; }\n  const ReplaySession& current_session() const { return *current; }\n\n  /**\n   * Return a mark for the current state. A checkpoint need not be retained,\n   * but this mark can be seeked to later.\n   * This can be expensive in some (perhaps unusual) situations since we\n   * may need to clone the current session and run it a bit, to figure out\n   * where we are relative to other Marks. So don't call this unless you\n   * need it.\n   */\n  Mark mark();\n\n  /**\n   * Indicates that the current replay position is the result of\n   * singlestepping from 'from'.\n   */\n  void mark_after_singlestep(const Mark& from, const ReplayResult& result);\n\n  /**\n   * Returns true if it's safe to add a checkpoint here.\n   */\n  bool can_add_checkpoint() const { return current->can_clone(); }\n\n  /**\n   * Ensure that the current session is explicitly checkpointed.\n   * Explicit checkpoints are reference counted.\n   * Only call this if can_add_checkpoint would return true.\n   */\n  Mark add_explicit_checkpoint();\n\n  /**\n   * Remove an explicit checkpoint reference count for this mark.\n   */\n  void remove_explicit_checkpoint(const Mark& mark);\n\n  /**\n   * Return true if we're currently at the given mark.\n   */\n  bool at_mark(const Mark& mark) const { return current_mark() == mark.ptr; }\n\n  // Add/remove breakpoints and watchpoints. Use these APIs instead\n  // of operating on the task directly, so that ReplayTimeline can track\n  // breakpoints and automatically move them across sessions as necessary.\n  // Only one breakpoint for a given address space/addr combination can be set;\n  // setting another for the same address space/addr will replace the first.\n  // Likewise only one watchpoint for a given task/addr/num_bytes/type can be\n  // set. gdb expects that setting two breakpoints on the same address and then\n  // removing one removes both.\n  bool add_breakpoint(ReplayTask* t, remote_code_ptr addr,\n                      std::unique_ptr<BreakpointCondition> condition = nullptr);\n  // You can't remove a breakpoint with a specific condition, so don't\n  // place multiple breakpoints with conditions on the same location.\n  void remove_breakpoint(ReplayTask* t, remote_code_ptr addr);\n  bool add_watchpoint(ReplayTask* t, remote_ptr<void> addr, size_t num_bytes,\n                      WatchType type,\n                      std::unique_ptr<BreakpointCondition> condition = nullptr);\n  // You can't remove a watchpoint with a specific condition, so don't\n  // place multiple breakpoints with conditions on the same location.\n  void remove_watchpoint(ReplayTask* t, remote_ptr<void> addr, size_t num_bytes,\n                         WatchType type);\n  void remove_breakpoints_and_watchpoints();\n  bool has_breakpoint_at_address(ReplayTask* t, remote_code_ptr addr);\n  bool has_watchpoint_at_address(ReplayTask* t, remote_ptr<void> addr,\n                                 size_t num_bytes, WatchType type);\n\n  /**\n   * Ensure that reverse execution never proceeds into an event before\n   * |event|. Reverse execution will stop with a |task_exit| break status when\n   * at the beginning of this event.\n   */\n  void set_reverse_execution_barrier_event(FrameTime event) {\n    reverse_execution_barrier_event_ = event;\n  }\n  FrameTime reverse_execution_barrier_event() {\n    return reverse_execution_barrier_event_;\n  }\n\n  // State-changing APIs. These may alter state associated with\n  // current_session().\n\n  /**\n   * Reset the current session to the last available session before event\n   * 'time'. Useful if you want to run up to that event.\n   */\n  void seek_to_before_event(FrameTime time) {\n    return seek_to_before_key(MarkKey(time, 0, ReplayStepKey()));\n  }\n\n  /**\n   * Seek the timeline to just before tick count `ticks` during event `time`.\n   */\n  void seek_to_ticks(FrameTime time, Ticks ticks);\n\n  /**\n   * Reset the current session to the last checkpointed session before (or at)\n   * the mark. Will return at the mark if this mark was explicitly checkpointed\n   * previously (and not deleted).\n   */\n  void seek_up_to_mark(const Mark& mark);\n\n  /**\n   * Sets current session to 'mark' by restoring the nearest useful checkpoint\n   * and executing forwards if necessary.\n   */\n  void seek_to_mark(const Mark& mark);\n\n  /**\n   * Replay 'current'.\n   * If there is a breakpoint at the current task's current ip(), then\n   * when running forward we will immediately break at the breakpoint. When\n   * running backward we will ignore the initial \"hit\" of the breakpoint ---\n   * this is the behavior gdb expects.\n   * Likewise, if there is a breakpoint at the current task's current ip(),\n   * then running forward will immediately break at the breakpoint, but\n   * running backward will ignore the initial \"hit\" of the breakpoint; this is\n   * what gdb expects.\n   *\n   * replay_step_forward only does one replay step. That means we'll only\n   * execute code in current_session().current_task().\n   */\n  ReplayResult replay_step_forward(RunCommand command);\n\n  ReplayResult reverse_continue(\n      const std::function<bool(ReplayTask* t, const BreakStatus &)>& stop_filter,\n      const std::function<bool()>& interrupt_check);\n  ReplayResult reverse_singlestep(\n      const TaskUid& tuid, Ticks tuid_ticks,\n      const std::function<bool(ReplayTask* t, const BreakStatus &)>& stop_filter,\n      const std::function<bool()>& interrupt_check);\n\n  /**\n   * Try to identify an existing Mark which is known to be one singlestep\n   * before 'from', and for which we know singlestepping to 'from' would\n   * trigger no break statuses other than \"singlestep_complete\".\n   * If we can't, return a null Mark.\n   * Will only return a Mark for the same executing task as 'from', which\n   * must be 't'.\n   */\n  Mark lazy_reverse_singlestep(const Mark& from, ReplayTask* t);\n\n  /**\n   * Different strategies for placing automatic checkpoints.\n   */\n  enum CheckpointStrategy {\n    /**\n     * Use this when we want to bound the overhead of checkpointing to be\n     * insignificant relative to the cost of forward execution.\n     */\n    LOW_OVERHEAD,\n    /**\n     * Use this when we expect reverse execution to happen soon, to a\n     * destination not far behind the current execution point. In this case\n     * it's worth increasing checkpoint density.\n     * We pass this when we have opportunities to make checkpoints during\n     * reverse_continue or reverse_singlestep, since it's common for short\n     * reverse-executions to follow other reverse-execution.\n     */\n    EXPECT_SHORT_REVERSE_EXECUTION\n  };\n\n  /**\n   * We track the set of breakpoints/watchpoints requested by the client.\n   * When we switch to a new ReplaySession, these need to be reapplied before\n   * replaying that session, but we do this lazily.\n   * apply_breakpoints_and_watchpoints() forces the breakpoints/watchpoints\n   * to be applied to the current session.\n   * Our checkpoints never have breakpoints applied.\n   */\n  void apply_breakpoints_and_watchpoints();\n\nprivate:\n  /**\n   * A MarkKey consists of FrameTime + Ticks + ReplayStepKey. These values\n   * do not uniquely identify a program state, but they are intrinsically\n   * totally ordered. The ReplayTimeline::marks database is an ordered\n   * map from MarkKeys to a time-ordered list of Marks associated with each\n   * MarkKey.\n   */\n  struct MarkKey {\n    MarkKey(FrameTime trace_time, Ticks ticks, ReplayStepKey step_key)\n        : trace_time(trace_time), ticks(ticks), step_key(step_key) {}\n    MarkKey(const MarkKey& other) = default;\n    MarkKey& operator=(const MarkKey& other) = default;\n    FrameTime trace_time;\n    Ticks ticks;\n    ReplayStepKey step_key;\n    bool operator<(const MarkKey& other) const {\n      if (trace_time < other.trace_time) {\n        return true;\n      }\n      if (trace_time > other.trace_time) {\n        return false;\n      }\n      if (ticks < other.ticks) {\n        return true;\n      }\n      if (ticks > other.ticks) {\n        return false;\n      }\n      return step_key < other.step_key;\n    }\n    bool operator<=(const MarkKey& other) const { return !(other < *this); }\n    bool operator>(const MarkKey& other) const { return other < *this; }\n    bool operator>=(const MarkKey& other) const { return !(*this < other); }\n    bool operator==(const MarkKey& other) const {\n      return trace_time == other.trace_time && ticks == other.ticks &&\n             step_key == other.step_key;\n    }\n    bool operator!=(const MarkKey& other) const { return !(*this == other); }\n  };\n  friend std::ostream& operator<<(std::ostream& s, const MarkKey& o);\n\n  /**\n   * All the information we'll need to construct a mark lazily.\n   * Marks are expensive to create since we may have to restore\n   * a previous session state so we can replay forward to find out\n   * how the Mark should be ordered relative to other Marks with the same\n   * MarkKey. So instead of creating a Mark for the current moment\n   * whenever we *might* need to return to that moment, create a ProtoMark\n   * instead. This contains a snapshot of enough state to create a full\n   * Mark later.\n   * MarkKey + Registers + ReturnAddressList are assumed to identify a unique\n   * program state.\n   */\n  struct ProtoMark {\n    ProtoMark(const MarkKey& key, ReplayTask* t)\n        : key(key), regs(t->regs()), return_addresses(ReturnAddressList(t)) {}\n    ProtoMark(const MarkKey& key) : key(key) {}\n\n    bool equal_states(ReplaySession& session) const;\n\n    MarkKey key;\n    Registers regs;\n    ReturnAddressList return_addresses;\n  };\n\n  /**\n   * Everything we know about the tracee state for a particular Mark.\n   * This data alone does not allow us to determine the time ordering\n   * of two Marks.\n   */\n  struct InternalMark {\n    InternalMark(ReplayTimeline* owner, ReplaySession& session,\n                 const MarkKey& key)\n        : owner(owner),\n          proto(key),\n          ticks_at_event_start(session.ticks_at_start_of_current_event()),\n          checkpoint_refcount(0),\n          singlestep_to_next_mark_no_signal(false) {\n      ReplayTask* t = session.current_task();\n      if (t) {\n        proto = ProtoMark(key, t);\n        extra_regs = t->extra_regs();\n      }\n    }\n    ~InternalMark();\n\n    bool operator<(const std::shared_ptr<InternalMark> other);\n\n    bool equal_states(ReplaySession& session) const;\n    void full_print(FILE* out) const;\n\n    ReplayTimeline* owner;\n    // Reuse ProtoMark to contain the MarkKey + Registers + ReturnAddressList.\n    ProtoMark proto;\n    ExtraRegisters extra_regs;\n    // Optional checkpoint for this Mark.\n    ReplaySession::shr_ptr checkpoint;\n    Ticks ticks_at_event_start;\n    // Number of users of `checkpoint`.\n    uint32_t checkpoint_refcount;\n    // The next InternalMark in the ReplayTimeline's Mark vector is the result\n    // of singlestepping from this mark *and* no signal is reported in the\n    // break_status when doing such a singlestep.\n    bool singlestep_to_next_mark_no_signal;\n  };\n  friend struct InternalMark;\n  friend std::ostream& operator<<(std::ostream& s, const InternalMark& o);\n  friend std::ostream& operator<<(std::ostream& s, const ProtoMark& o);\n\n  /**\n   * unapply_breakpoints_and_watchpoints() forces the breakpoints/watchpoints\n   * to not be applied to the current session. Use this when we need to\n   * clone the current session or replay the current session without\n   * triggering breakpoints.\n   */\n  void unapply_breakpoints_and_watchpoints();\n\n  void apply_breakpoints_internal();\n  void unapply_breakpoints_internal();\n\n  static MarkKey session_mark_key(ReplaySession& session) {\n    ReplayTask* t = session.current_task();\n    return MarkKey(session.trace_reader().time(), t ? t->tick_count() : 0,\n                   session.current_step_key());\n  }\n  MarkKey current_mark_key() const { return session_mark_key(*current); }\n\n  ProtoMark proto_mark() const;\n  void seek_to_proto_mark(const ProtoMark& pmark);\n\n  // Returns a shared pointer to the mark if there is one for the current state.\n  std::shared_ptr<InternalMark> current_mark() const;\n  void remove_mark_with_checkpoint(const MarkKey& key);\n  void seek_to_before_key(const MarkKey& key);\n  enum ForceProgress { FORCE_PROGRESS, DONT_FORCE_PROGRESS };\n  // Run forward towards the midpoint of the current position and |end|.\n  // Must stop before we reach |end|.\n  // Returns false if we made no progress.\n  bool run_forward_to_intermediate_point(const Mark& end, ForceProgress force);\n  struct ReplayStepToMarkStrategy {\n    ReplayStepToMarkStrategy() : singlesteps_to_perform(0) {}\n    ReplaySession::StepConstraints setup_step_constraints();\n    uint32_t singlesteps_to_perform;\n  };\n  void update_strategy_and_fix_watchpoint_quirk(\n      ReplayStepToMarkStrategy& strategy,\n      const ReplaySession::StepConstraints& constraints, ReplayResult& result,\n      const ProtoMark& before);\n  // Take a single replay step towards |mark|. Stop before or at |mark|, and\n  // stop if any breakpoint/watchpoint/signal is hit.\n  // Maintain current strategy state in |strategy|. Passing the same\n  // |strategy| object to consecutive replay_step_to_mark invocations helps\n  // optimize performance.\n  ReplayResult replay_step_to_mark(const Mark& mark,\n                                   ReplayStepToMarkStrategy& strategy);\n  ReplayResult singlestep_with_breakpoints_disabled();\n  bool fix_watchpoint_coalescing_quirk(ReplayResult& result,\n                                       const ProtoMark& before);\n  Mark find_singlestep_before(const Mark& mark);\n  bool is_start_of_reverse_execution_barrier_event();\n\n  void update_observable_break_status(ReplayTimeline::Mark& now,\n                                      const ReplayResult& result);\n  ReplayResult reverse_singlestep(\n      const Mark& origin, const TaskUid& step_tuid, Ticks step_ticks,\n      const std::function<bool(ReplayTask* t, const BreakStatus &)>& stop_filter,\n      const std::function<bool()>& interrupt_check);\n\n  // Reasonably fast since it just relies on checking the mark map.\n  static bool less_than(const Mark& m1, const Mark& m2);\n\n  Progress estimate_progress();\n\n  /**\n   * Called when the current session has moved forward to a new execution\n   * point and we might want to make a checkpoint to support reverse-execution.\n   * If this adds a checkpoint, it will call\n   * discard_past_reverse_exec_checkpoints\n   * first.\n   */\n  void maybe_add_reverse_exec_checkpoint(CheckpointStrategy strategy);\n  /**\n   * Discard some reverse-exec checkpoints in the past, if necessary. We do\n   * this to stop the number of checkpoints growing out of control.\n   */\n  void discard_past_reverse_exec_checkpoints(CheckpointStrategy strategy);\n  /**\n   * Discard all reverse-exec checkpoints that are in the future (they're\n   * useless).\n   */\n  void discard_future_reverse_exec_checkpoints();\n\n  Mark set_short_checkpoint();\n\n  /**\n   * If result.break_status hit watchpoints or breakpoints, evaluate their\n   * conditions and clear the break_status flags if the conditions don't hold.\n   */\n  void evaluate_conditions(ReplayResult& result);\n\n  // Never null.\n  ReplaySession::shr_ptr current;\n  // current is known to be at or after this mark\n  std::shared_ptr<InternalMark> current_at_or_after_mark;\n\n  /**\n   * All known marks.\n   *\n   * An InternalMark appears in a ReplayTimeline 'marks' map if and only if\n   * that ReplayTimeline is the InternalMark's 'owner'. ReplayTimeline's\n   * destructor clears the 'owner' of all marks in the map.\n   *\n   * For each MarkKey, the InternalMarks are stored in execution order.\n   *\n   * The key problem we're dealing with here is that we don't have any state\n   * that we can use to compute a total time order on Marks. MarkKeys are\n   * totally ordered, but different program states can have the same MarkKey\n   * (i.e. same retired conditional branch count). The only way to determine\n   * the time ordering of two Marks m1 and m2 is to actually replay the\n   * execution until we see m1 and m2 and observe which one happened first.\n   * We record that ordering for all Marks by storing all the Marks for a given\n   * MarkKey in vector ordered by time.\n   * Determining this order is expensive so we avoid creating Marks unless we\n   * really need to! If we're at a specific point in time and we *may* need to\n   * create a Mark for this point later, create a ProtoMark instead to\n   * capture enough state so that a Mark can later be created if needed.\n   *\n   * We assume there will be a limited number of InternalMarks per MarkKey.\n   * This should be true because ReplayTask::tick_count() should increment\n   * frequently during execution. In some cases we see hundreds of elements\n   * but that's not too bad.\n   */\n  std::map<MarkKey, std::vector<std::shared_ptr<InternalMark>>> marks;\n\n  /**\n   * All mark keys with at least one checkpoint. The value is the number of\n   * checkpoints. There can be multiple checkpoints for a given MarkKey\n   * because a MarkKey may have multiple corresponding Marks.\n   */\n  std::map<MarkKey, uint32_t> marks_with_checkpoints;\n\n  std::set<std::tuple<AddressSpaceUid, remote_code_ptr,\n                      std::unique_ptr<BreakpointCondition>>>\n      breakpoints;\n  std::set<std::tuple<AddressSpaceUid, remote_ptr<void>, size_t, WatchType,\n                      std::unique_ptr<BreakpointCondition>>>\n      watchpoints;\n  bool breakpoints_applied;\n\n  FrameTime reverse_execution_barrier_event_;\n\n  /**\n   * Checkpoints used to accelerate reverse execution.\n   */\n  std::map<Mark, Progress> reverse_exec_checkpoints;\n\n  /**\n   * When these are non-null, then when singlestepping from\n   * no_break_interval_start to no_break_interval_end, none of the currently\n   * set watchpoints fire.\n   */\n  Mark no_watchpoints_hit_interval_start;\n  Mark no_watchpoints_hit_interval_end;\n\n  /**\n   * A single checkpoint that's very close to the current point, used to\n   * accelerate a sequence of reverse singlestep operations.\n   */\n  Mark reverse_exec_short_checkpoint;\n};\n\nstd::ostream& operator<<(std::ostream& s, const ReplayTimeline::Mark& o);\n\n} // namespace rr\n\n#endif // RR_REPLAY_TIMELINE_H_\n"
  },
  {
    "path": "src/RerunCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <sys/time.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <limits>\n\n#include \"Command.h\"\n#include \"ExportImportCheckpoints.h\"\n#include \"Flags.h\"\n#include \"GdbServer.h\"\n#include \"ReplaySession.h\"\n#include \"ScopedFd.h\"\n#include \"TraceField.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"main.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n/**\n * 'rerun' is intended to be a more powerful form of 'rr replay -a'. It does\n * a replay without debugging support, but it provides options for tracing and\n * dumping tracee state. Initially it supports singlestepping through a range\n * of trace events, dumping selected register values after each step.\n */\nclass RerunCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  RerunCommand(const char* name, const char* help) : Command(name, help) {}\n  // command_for_checkpoint is an in and out parameter.\n  int run_internal(CommandForCheckpoint& command_for_checkpoint);\n\n  static RerunCommand singleton;\n};\n\nRerunCommand RerunCommand::singleton(\n    \"rerun\",\n    \" rr rerun [OPTION]... [<trace-dir>]\\n\"\n    \"  -e, --trace-end=<EVENT>    end tracing at <EVENT>\\n\"\n    \"  -f, --function=<ADDR>      when starting tracing, push sentinel return\\n\"\n    \"                             address and jump to <ADDR> to fake call\\n\"\n    \"  --singlestep=<REGS>        dump <REGS> after each singlestep\\n\"\n    \"  --event-regs=<REGS>        dump <REGS> after each event\\n\"\n    \"  --export-checkpoints=<EVENT>,<NUM>,<FILE>\\n\"\n    \"                             Run to start of <EVENT> and then export checkpoints over\\n\"\n    \"                             Unix socket at <FILE>. Exit after <NUM>\\n\"\n    \"                             connections to the socket.\\n\"\n    \"  --import-checkpoint=<FILE> Start the replay by importing a checkpoint from\\n\"\n    \"                             another rr instance exporting checkpoints at\\n\"\n    \"                             <FILE>\\n\"\n    \"  -r, --raw                  dump registers in raw format\\n\"\n    \"  -s, --trace-start=<EVENT>  start tracing at <EVENT>\\n\"\n    \"  -u, --cpu-unbound          allow replay to run on any CPU. Default is\\n\"\n    \"                             to run on the CPU stored in the trace.\\n\"\n    \"                             Note that this may diverge from the recording\\n\"\n    \"                             in some cases.\\n\"\n    \"\\n\"\n    \"<REGS> is a comma-separated sequence of 'event','icount','ip','ticks',\\n\"\n    \"'flags','gp_x16','xmm_x16','ymm_x16'. For the 'x16' cases, we always output\\n\"\n    \"16 values, the latter 8 of which are zero for x86-32. GP registers are in\\n\"\n    \"architectural order (AX,CX,DX,BX,SP,BP,SI,DI,R8-R15). All data is output\\n\"\n    \"in little-endian binary format; records are separated by \\\\n. String\\n\"\n    \"instruction repetitions are treated as a single instruction if not\\n\"\n    \"interrupted. A 'singlestep' includes events such as system-call-exit\\n\"\n    \"where tracee state changes without any user-level instructions actually\\n\"\n    \"being executed.\\n\");\n\nstruct RerunFlags {\n  FrameTime trace_start;\n  FrameTime trace_end;\n  remote_code_ptr function;\n  vector<TraceField> singlestep_trace;\n  vector<TraceField> event_trace;\n  string import_checkpoint_socket;\n  string export_checkpoints_socket;\n  FrameTime export_checkpoints_event;\n  int export_checkpoints_count;\n  bool raw;\n  bool cpu_unbound;\n\n  RerunFlags()\n      : trace_start(0),\n        trace_end(numeric_limits<decltype(trace_end)>::max()),\n        export_checkpoints_event(0),\n        export_checkpoints_count(0),\n        raw(false),\n        cpu_unbound(false) {}\n};\n\nstatic bool parse_rerun_arg(vector<string>& args, RerunFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = {\n    { 1, \"singlestep\", HAS_PARAMETER },\n    { 2, \"event-regs\", HAS_PARAMETER },\n    { 3, \"export-checkpoints\", HAS_PARAMETER },\n    { 4, \"import-checkpoint\", HAS_PARAMETER },\n    { 'e', \"trace-end\", HAS_PARAMETER },\n    { 'f', \"function\", HAS_PARAMETER },\n    { 'r', \"raw\", NO_PARAMETER },\n    { 's', \"trace-start\", HAS_PARAMETER },\n    { 'u', \"cpu-unbound\", NO_PARAMETER }\n  };\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 1:\n      if (!parse_trace_fields(opt.value, &flags.singlestep_trace)) {\n        return false;\n      }\n      break;\n    case 2:\n      if (!parse_trace_fields(opt.value, &flags.event_trace)) {\n        return false;\n      }\n      break;\n    case 3:\n      if (!parse_export_checkpoints(opt.value, flags.export_checkpoints_event, flags.export_checkpoints_count, flags.export_checkpoints_socket)) {\n        return false;\n      }\n      break;\n    case 4:\n      flags.import_checkpoint_socket = opt.value;\n      break;\n    case 'e':\n      if (!opt.verify_valid_int(1, UINT32_MAX)) {\n        return false;\n      }\n      flags.trace_end = opt.int_value;\n      break;\n    case 'f': {\n      char* endptr;\n      flags.function = strtoul(opt.value.c_str(), &endptr, 0);\n      if (*endptr) {\n        fprintf(stderr, \"Invalid function address %s\\n\", opt.value.c_str());\n        return false;\n      }\n      break;\n    }\n    case 'r':\n      flags.raw = true;\n      break;\n    case 's':\n      if (!opt.verify_valid_int(1, UINT32_MAX)) {\n        return false;\n      }\n      flags.trace_start = opt.int_value;\n      break;\n    case 'u':\n      flags.cpu_unbound = true;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown option\");\n  }\n  return true;\n}\n\nstatic bool treat_event_completion_as_singlestep_complete(const Event& ev) {\n  switch (ev.type()) {\n    case EV_PATCH_SYSCALL:\n      return !ev.PatchSyscall().patch_vsyscall;\n    case EV_INSTRUCTION_TRAP:\n    case EV_SYSCALL:\n      return true;\n    default:\n      return false;\n  }\n}\n\n/**\n * Return true if the final \"event\" state change doesn't really change any\n * user-visible state and is therefore not to be considered a singlestep for\n * our purposes.\n */\nstatic bool ignore_singlestep_for_event(const Event& ev) {\n  switch (ev.type()) {\n    // These don't actually change user-visible state, so we skip them.\n    case EV_SIGNAL:\n    case EV_SIGNAL_DELIVERY:\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic const uint64_t sentinel_ret_address = 9;\n\nstatic void run_diversion_function(ReplaySession& replay, Task* task,\n                                   const RerunFlags& flags) {\n  DiversionSession::shr_ptr diversion_session = replay.clone_diversion();\n  ReplayTask* t = diversion_session->find_task(task->tuid())->as_replay();\n  Registers regs = t->regs();\n  // align stack\n  auto sp = remote_ptr<uint64_t>(regs.sp().as_int() & ~uintptr_t(0xf)) - 1;\n  t->write_mem(sp.cast<uint64_t>(), sentinel_ret_address);\n  regs.set_sp(sp);\n  regs.set_ip(flags.function);\n  regs.set_di(0);\n  regs.set_si(0);\n  t->set_regs(regs);\n  RunCommand cmd =\n      flags.singlestep_trace.empty() ? RUN_CONTINUE : RUN_SINGLESTEP;\n\n  while (true) {\n    DiversionSession::DiversionResult result =\n        diversion_session->diversion_step(t, cmd);\n    print_trace_fields(t, 0, 0, flags.raw, flags.singlestep_trace, stdout);\n    if (result.break_status.signal) {\n      if (result.break_status.signal->si_signo == SIGSEGV &&\n          result.break_status.signal->si_addr == (void*)sentinel_ret_address) {\n        return;\n      }\n      ASSERT(task, false) << \"Unexpected signal \"\n                          << *result.break_status.signal;\n    }\n\n    if (result.status == DiversionSession::DiversionStatus::DIVERSION_EXITED) {\n        LOG(debug) << \"DIVERSION_EXITED, breaking out of diversion_step() loop\";\n        break;\n    }\n  }\n}\n\nstatic ReplaySession::Flags session_flags(const RerunFlags& flags) {\n  ReplaySession::Flags result;\n  result.redirect_stdio = false;\n  result.share_private_mappings = false;\n  result.cpu_unbound = flags.cpu_unbound;\n  return result;\n}\n\nstatic int rerun(const string& trace_dir, const RerunFlags& flags, CommandForCheckpoint& command_for_checkpoint) {\n  ScopedFd export_checkpoints_socket;\n  // Construct the listening socket immediately so importers can connect early and block without polling.\n  // If we need to import a checkpoint, we pass the socket in command_for_checkpoint.fds to the checkpoint\n  // exporter's child process.\n  if (flags.export_checkpoints_event) {\n    if (command_for_checkpoint.session) {\n      export_checkpoints_socket = std::move(command_for_checkpoint.fds.front());\n    } else {\n      export_checkpoints_socket = bind_export_checkpoints_socket(flags.export_checkpoints_count, flags.export_checkpoints_socket);\n    }\n  }\n\n  ReplaySession::shr_ptr replay_session;\n  if (command_for_checkpoint.session) {\n    replay_session = std::move(command_for_checkpoint.session);\n  } else if (flags.import_checkpoint_socket.empty()) {\n    replay_session = ReplaySession::create(trace_dir, session_flags(flags));\n    // Now that we've spawned the replay, raise our resource limits if\n    // possible.\n    raise_resource_limits();\n  } else {\n    vector<ScopedFd> fds;\n    if (export_checkpoints_socket.is_open()) {\n      fds.push_back(std::move(export_checkpoints_socket));\n    }\n    return invoke_checkpoint_command(flags.import_checkpoint_socket, command_for_checkpoint.args, std::move(fds));\n  }\n\n  uint64_t instruction_count_within_event = 0;\n  bool done_first_step = false;\n  bool need_to_singlestep = !flags.singlestep_trace.empty();\n  for (auto& v : flags.event_trace) {\n    if (v.kind == TRACE_INSTRUCTION_COUNT) {\n      need_to_singlestep = true;\n    }\n  }\n\n  while (replay_session->trace_reader().time() < flags.trace_end) {\n    RunCommand cmd = RUN_CONTINUE;\n\n    auto old_task_p = replay_session->current_task();\n    ReplayTask* old_task = old_task_p ? old_task_p->as_replay() : nullptr;\n    auto old_task_tuid = old_task ? old_task->tuid() : TaskUid();\n    remote_code_ptr old_ip = old_task ? old_task->ip() : remote_code_ptr();\n    FrameTime before_time = replay_session->trace_reader().time();\n    if (replay_session->done_initial_exec() &&\n        before_time >= flags.trace_start) {\n      if (!done_first_step) {\n        if (!flags.function.is_null()) {\n          run_diversion_function(*replay_session, old_task, flags);\n          return 0;\n        }\n\n        done_first_step = true;\n        print_trace_fields(old_task, before_time - 1, instruction_count_within_event,\n                           flags.raw, flags.singlestep_trace, stdout);\n      }\n\n      if (need_to_singlestep) {\n        cmd = RUN_SINGLESTEP_FAST_FORWARD;\n      }\n    }\n\n    Event replayed_event = replay_session->current_trace_frame().event();\n\n    auto result = replay_session->replay_step(cmd);\n    if (result.status == REPLAY_EXITED) {\n      break;\n    }\n\n    FrameTime after_time = replay_session->trace_reader().time();\n    if (cmd != RUN_CONTINUE) {\n      // The old_task may have exited (and been deallocated) in the `replay_session->replay_step(cmd)` above.\n      // So we need to try and obtain it from the session again to make sure it still exists.\n      Task* old_task_p = old_task_tuid.tid() ? replay_session->find_task(old_task_tuid) : nullptr;\n      ReplayTask* old_task = old_task_p ? old_task_p->as_replay() : nullptr;\n      remote_code_ptr after_ip = old_task ? old_task->ip() : remote_code_ptr();\n      DEBUG_ASSERT(after_time >= before_time && after_time <= before_time + 1);\n\n      DEBUG_ASSERT(result.status == REPLAY_CONTINUE);\n      DEBUG_ASSERT(result.break_status.watchpoints_hit.empty());\n      DEBUG_ASSERT(!result.break_status.breakpoint_hit);\n      DEBUG_ASSERT(cmd == RUN_SINGLESTEP_FAST_FORWARD ||\n                   !result.break_status.singlestep_complete);\n\n      // Treat singlesteps that partially executed a string instruction (that\n      // was not interrupted) as not really singlestepping.\n      bool singlestep_really_complete =\n          result.break_status.singlestep_complete &&\n          // ignore_singlestep_for_event only matters if we really completed the\n          // event\n          (!ignore_singlestep_for_event(replayed_event) ||\n           before_time == after_time) &&\n          (!result.incomplete_fast_forward || old_ip != after_ip ||\n           before_time < after_time);\n      if (cmd == RUN_SINGLESTEP_FAST_FORWARD &&\n          (singlestep_really_complete ||\n           (before_time < after_time &&\n            treat_event_completion_as_singlestep_complete(replayed_event)))) {\n        print_trace_fields(old_task, before_time, instruction_count_within_event,\n                           flags.raw, flags.singlestep_trace, stdout);\n      }\n\n      if (singlestep_really_complete) {\n        instruction_count_within_event += 1;\n      }\n    }\n    if (before_time < after_time) {\n      LOG(debug) << \"Completed event \" << before_time\n                 << \" instruction_count=\" << instruction_count_within_event;\n      print_trace_fields(old_task, before_time, instruction_count_within_event,\n                         flags.raw, flags.event_trace, stdout);\n      instruction_count_within_event = 1;\n    }\n\n    if (after_time == flags.export_checkpoints_event) {\n      command_for_checkpoint = export_checkpoints(std::move(replay_session),\n          flags.export_checkpoints_count,\n          export_checkpoints_socket, flags.export_checkpoints_socket);\n      return 0;\n    }\n  }\n\n  LOG(info) << \"Rerun successfully finished\";\n  return 0;\n}\n\nint RerunCommand::run_internal(CommandForCheckpoint& command_for_checkpoint) {\n  // parse args first\n  bool found_dir = false;\n  string trace_dir;\n  RerunFlags flags;\n  vector<string> args = command_for_checkpoint.args;\n\n  while (!args.empty()) {\n    if (parse_rerun_arg(args, flags)) {\n      continue;\n    }\n    if (!found_dir && parse_optional_trace_dir(args, &trace_dir)) {\n      found_dir = true;\n      continue;\n    }\n    print_help(stderr);\n    return 1;\n  }\n\n  assert_prerequisites();\n\n  if (running_under_rr()) {\n    if (!Flags::get().suppress_environment_warnings) {\n      fprintf(stderr, \"rr: rr pid %d running under parent %d. Good luck.\\n\",\n              getpid(), getppid());\n    }\n    if (trace_dir.empty()) {\n      fprintf(stderr,\n              \"rr: No trace-dir supplied. You'll try to rerun the \"\n              \"recording of this rr and have a bad time. Bailing out.\\n\");\n      return 3;\n    }\n  }\n\n  return rerun(trace_dir, flags, command_for_checkpoint);\n}\n\nint RerunCommand::run(vector<string>& args) {\n  CommandForCheckpoint command_for_checkpoint;\n  command_for_checkpoint.args = std::move(args);\n  while (true) {\n    ScopedFd exit_notification_fd = std::move(command_for_checkpoint.exit_notification_fd);\n    int ret = run_internal(command_for_checkpoint);\n    if (!command_for_checkpoint.session) {\n      if (exit_notification_fd.is_open()) {\n        notify_normal_exit(exit_notification_fd);\n      }\n      return ret;\n    }\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ReturnAddressList.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ReturnAddressList.h\"\n\n#include \"Task.h\"\n\nnamespace rr {\n\nstatic bool read_bytes_no_breakpoints(Task* t, remote_ptr<void> p, ssize_t size,\n                                      void* out) {\n  if (t->read_bytes_fallible(p, size, out) != size) {\n    return false;\n  }\n  t->vm()->replace_breakpoints_with_original_values(static_cast<uint8_t*>(out),\n      size, p.cast<uint8_t>());\n  return true;\n}\n\ntemplate <typename Arch>\nstatic void return_addresses_x86ish(ReturnAddressList* result, Task* t) {\n  // Immediately after a function call the return address is on the stack at\n  // SP. After BP is pushed, but before it's initialized for the new stack\n  // frame, the return address is on the stack at SP+wordsize. Just\n  // capture those words now. We could inspect the code for known prologs/\n  // epilogs but that misses cases such as calling into optimized code\n  // or PLT stubs (which start with 'jmp'). Since it doesn't matter if we\n  // capture addresses that aren't real return addresses, just capture those\n  // words unconditionally.\n  typename Arch::size_t frame[2];\n  int next_address = 0;\n  // Make sure the data we fetch here does not depend on where breakpoints have\n  // been set. We don't want these results to vary because we call this in\n  // some contexts with internal breakpoints set and in other contexts without\n  // them set.\n  if (read_bytes_no_breakpoints(t, t->regs().sp(), sizeof(frame), frame)) {\n    result->addresses[0] = frame[0];\n    result->addresses[1] = frame[1];\n    next_address = 2;\n  }\n\n  remote_ptr<void> bp = t->regs().bp();\n  for (int i = next_address; i < ReturnAddressList::X86_COUNT; ++i) {\n    if (!read_bytes_no_breakpoints(t, bp, sizeof(frame), frame)) {\n      break;\n    }\n    result->addresses[i] = frame[1];\n    bp = frame[0];\n  }\n}\n\ntemplate <typename Arch>\nvoid return_addresses_arch(ReturnAddressList* result, Task* t);\n\ntemplate <> void return_addresses_arch<X86Arch>(ReturnAddressList* result, Task* t) {\n  return_addresses_x86ish<X86Arch>(result, t);\n}\n\ntemplate <> void return_addresses_arch<X64Arch>(ReturnAddressList* result, Task* t) {\n  return_addresses_x86ish<X64Arch>(result, t);\n}\n\ntemplate <> void return_addresses_arch<ARM64Arch>(ReturnAddressList* result, Task*) {\n  // On aarch64, we track all taken branches, so tracking return addresses should\n  // not be necessary.\n  DEBUG_ASSERT(ReturnAddressList::AARCH64_COUNT == 0);\n  for (size_t i = 0; i < array_length(result->addresses); ++i) {\n    result->addresses[i] = nullptr;\n  }\n}\n\nstatic void compute_return_addresses(ReturnAddressList* result, Task* t) {\n  RR_ARCH_FUNCTION(return_addresses_arch, t->arch(), result, t);\n}\n\nReturnAddressList::ReturnAddressList(Task* t) {\n  compute_return_addresses(this, t);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ReturnAddressList.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_RETURNADDRESSLIST_H_\n#define RR_RETURNADDRESSLIST_H_\n\n#include <string.h>\n\n#include \"remote_ptr.h\"\n\nnamespace rr {\n\nclass Task;\n\n/**\n * A list of return addresses extracted from the stack. The tuple\n * (perfcounter ticks, regs, return addresses) may be needed to disambiguate\n * states that aren't unique in (perfcounter ticks, regs).\n * When return addresses can't be extracted, some suffix of the list may be\n * all zeroes.\n */\nstruct ReturnAddressList {\n  enum { AARCH64_COUNT = 0, X86_COUNT = 8, MAX_COUNT = X86_COUNT };\n  remote_ptr<void> addresses[MAX_COUNT];\n\n  /**\n   * Capture return addresses from |t|'s stack. The returned\n   * address list may not be actual return addresses (in optimized code,\n   * will probably not be), but they will be a function of the task's current\n   * state, so may be useful for distinguishing this state from other states.\n   */\n  ReturnAddressList() {\n    for (size_t i = 0; i < MAX_COUNT; ++i) {\n      addresses[i] = nullptr;\n    }\n  }\n  explicit ReturnAddressList(Task* t);\n\n  bool operator==(const ReturnAddressList& other) const {\n    return memcmp(addresses, other.addresses, sizeof(addresses)) == 0;\n  }\n  bool operator!=(const ReturnAddressList& other) const {\n    return !(*this == other);\n  }\n};\n\n} // namespace rr\n\n#endif /* RR_RETURNADDRESSLIST_H_ */\n"
  },
  {
    "path": "src/RmCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <ftw.h>\n#include <stdio.h>\n\n#include <vector>\n\n#include \"Command.h\"\n#include \"TraceStream.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass RmCommand : public Command {\npublic:\n  virtual int run(vector<string>& args);\n\nprotected:\n  RmCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static RmCommand singleton;\n};\n\nRmCommand RmCommand::singleton(\n    \"rm\", \" rr rm <trace> [OPTION]...\\n\"\n          \"  -f, --force, remove folder even if not identifiable as trace.\\n\");\n\nstruct RmFlags {\n  bool force;\n  RmFlags() : force(false) {}\n};\n\nstatic bool parse_rm_arg(vector<string>& args, RmFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = { { 'f', \"force\", NO_PARAMETER } };\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 'f':\n      flags.force = true;\n      break;\n    default:\n      assert(0 && \"Unknown option\");\n  }\n\n  return true;\n}\n\nstatic int _rm_cb(const char* path, const struct stat*, int, struct FTW*) {\n  int ret = remove(path);\n  if (ret) {\n    perror(path);\n  }\n  return ret;\n}\n\nstatic bool remove_all(const string& path) {\n  int ret = nftw(path.c_str(), _rm_cb, 16, FTW_DEPTH | FTW_PHYS);\n  if (ret) {\n    perror(path.c_str());\n    return false;\n  }\n  return true;\n}\n\nstatic int rm(const string& trace, const RmFlags& flags, FILE* out) {\n  string reason;\n  if (!is_valid_trace_name(trace, &reason)) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Trace name is invalid: %s\\n\"\n            \"\\n\",\n            reason.c_str());\n    return 1;\n  }\n\n  string trace_path = resolve_trace_name(trace);\n\n  if (access(trace_path.c_str(), F_OK) != 0) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Cannot remove non-existent / unaccessible trace '%s':\"\n            \" errno %d\\n\"\n            \"\\n\",\n            trace_path.c_str(), errno);\n    return 1;\n  }\n\n  // resolve symlinks like latest_trace\n  trace_path = real_path(trace_path);\n\n  if (!flags.force && !is_trace(trace_path)) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Could not identify '%s' as a trace, use -f to remove anyway\"\n            \" (errno %d).\\n\"\n            \"\\n\",\n            trace_path.c_str(), errno);\n    return 1;\n  }\n\n  // remove symlink before removing trace in case the former fails\n  // a bad symlink might crash other things later such as rr ls, midas\n  if (is_latest_trace(trace_path)) {\n    if (!remove_latest_trace_symlink()) {\n      return 1;\n    }\n  }\n\n  if (!remove_all(trace_path)) {\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Could not remove trace '%s'\\n\"\n            \"\\n\",\n            trace_path.c_str());\n    return 1;\n  } else {\n    fprintf(out, \"rr: Removed trace '%s'\\n\", trace_path.c_str());\n    return 0;\n  }\n}\n\nint RmCommand::run(vector<string>& args) {\n  bool found_trace = false;\n  string trace;\n  RmFlags flags;\n\n  while (!args.empty()) {\n    if (parse_rm_arg(args, flags)) {\n      continue;\n    }\n    // use parse_optional_trace_dir to parse trace name\n    if (!found_trace && parse_optional_trace_dir(args, &trace)) {\n      found_trace = true;\n      continue;\n    }\n    print_help(stderr);\n    return 1;\n  };\n\n  if (!found_trace) {\n    print_help(stderr);\n    return 1;\n  }\n\n  return rm(trace, flags, stdout);\n};\n\n} // namespace rr\n"
  },
  {
    "path": "src/Scheduler.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n//#define MONITOR_UNSWITCHABLE_WAITS\n\n#include \"Scheduler.h\"\n\n#include <math.h>\n#include <signal.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/syscall.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <algorithm>\n\n#include \"CPUs.h\"\n#include \"Flags.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"TraceeAttentionSet.h\"\n#include \"WaitManager.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nFILE_CACHE_LOG_MODULE();\n\n// Probability of making a thread low priority. Keep this reasonably low\n// because the goal is to victimize some specific threads\nstatic double low_priority_probability = 0.1;\n// Give main threads a higher probability of being low priority because\n// many tests are basically main-thread-only\nstatic double main_thread_low_priority_probability = 0.3;\nstatic double very_short_timeslice_probability = 0.1;\n// For low priority tasks, assign some probability of being treated\n// as medium priority until their first yield.\n// This lets a low priority task run until it unblocks the execution of\n// a high-priority task and then never run again during a\n// high-priority-only interval. See the `startup` test.\nstatic double postpone_low_priority_until_after_yield = 0.2;\nstatic Ticks very_short_timeslice_max_duration = 100;\nstatic double short_timeslice_probability = 0.1;\nstatic Ticks short_timeslice_max_duration = 10000;\n// Time between priority refreshes is uniformly distributed from 0 to 20s\nstatic double priorities_refresh_max_interval = 20;\n\n/*\n * High-Priority-Only Intervals\n *\n * We assume that for a test failure we want to reproduce, we will reproduce a\n * failure if we completely avoid scheduling a certain thread for a period of\n * D seconds, where the start of that period must fall between S and S+T\n * seconds since the start of the test. All these constants are unknown to\n * rr, but we assume 1ms <= D <= 2s.\n *\n * Since we only need to reproduce any particular bug once, it would be best\n * to have roughly similar probabilities for reproducing each bug given its\n * unknown parameters. It's unclear what is the optimal approach here, but\n * here's ours:\n *\n * First we have to pick the right thread to treat as low priority --- without\n * making many other threads low priority, since they might need to run while\n * our victim thread is being starved. So we give each thread a 0.1 probability\n * of being low priority, except for the main thread which we make 0.3, since\n * starving the main thread is often very interesting.\n * Then we guess a value D' for D. We uniformly choose between 1ms, 2ms, 4ms,\n * 8ms, ..., 1s, 2s. Out of these 12 possibilities, one is between D and 2xD.\n * We adopt the goal of high-priority-only intervals consume at most 20% of\n * running time. Then to maximise the probability of triggering the test\n * failure, we start high-priority-only intervals as often as possible,\n * i.e. one for D' seconds starting every 5xD' seconds.\n * The start time of the first interval is chosen to be between 0 and 4xD'.\n * To make sure we capture startup effects, we choose 0 with probability 0.25\n * and uniformly between 0 and 4xD' otherwise.\n * Then, if we guessed D' and the low-priority thread correctly, the\n * probability of triggering the test failure is 1 if T >= 4xD', T/4xD'\n * otherwise, i.e. >= T/8xD. (Higher values of D' than optimal can also trigger\n * failures, but at reduced probabilities since we can schedule them less\n * often.)\n */\nstatic double min_high_priority_only_duration = 0.001;\nstatic int high_priority_only_duration_steps = 12;\nstatic double high_priority_only_duration_step_factor = 2;\n// Allow this much of overall runtime to be in the \"high priority only\" interval\nstatic double high_priority_only_fraction = 0.2;\nstatic double start_high_priority_only_immediately_probability = 0.25;\n\nScheduler::Scheduler(RecordSession& session)\n    : reschedule_count(0),\n      session(session),\n      task_priority_set_total_count(0),\n      current_(nullptr),\n      current_timeslice_end_(0),\n      high_priority_only_intervals_refresh_time(0),\n      high_priority_only_intervals_start(0),\n      high_priority_only_intervals_duration(0),\n      high_priority_only_intervals_period(0),\n      priorities_refresh_time(0),\n      max_ticks_(DEFAULT_MAX_TICKS),\n      must_run_task(nullptr),\n      pretend_num_cores_(1),\n      in_exec_tgid(0),\n      ntasks_stopped(0),\n      always_switch(false),\n      enable_chaos(false),\n      enable_poll(false),\n      last_reschedule_in_high_priority_only_interval(false),\n      unlimited_ticks_mode(false) {\n  std::random_device rd;\n  random.seed(rd());\n  regenerate_affinity_mask();\n}\n\n/**\n * Compute an affinity mask to report via sched_getaffinity.\n * This mask should include whatever CPU number the task is\n * actually running on, otherwise we may confuse applications.\n * The mask should also match the number of CPUs we're pretending\n * to have.\n */\nvoid Scheduler::regenerate_affinity_mask() {\n  int cpu = session.trace_writer().bound_to_cpu();\n  if (cpu < 0) {\n    // We only run one thread at a time but we're not limiting\n    // where that thread can run, so report all available CPUs\n    // in the affinity mask even though that doesn't match\n    // pretend_num_cores. We only run unbound during tests or\n    // when explicitly requested by the user.\n    return;\n  }\n  auto initial_affinity = CPUs::get().initial_affinity();\n  if (find(initial_affinity.begin(), initial_affinity.end(), cpu)\n      == initial_affinity.end()) {\n    LOGM(warn) << \"Bound CPU \" << cpu << \" not in affinity mask\";\n    // Use the original affinity mask since something strange is\n    // going on.\n    return;\n  }\n  // Try to limit the CPU numbers we generate to the ones that\n  // actually exist on this system, but generate fake ones if there\n  // aren't enough.\n  int faked_num_cpus = sysconf(_SC_NPROCESSORS_CONF);\n  if (faked_num_cpus < pretend_num_cores_) {\n    faked_num_cpus = pretend_num_cores_;\n  }\n  // generate random CPU numbers that fit into the CPU mask\n  vector<int> other_cpus;\n  for (int i = 0; i < faked_num_cpus; ++i) {\n    if (i != cpu) {\n      other_cpus.push_back(i);\n    }\n  }\n  shuffle(other_cpus.begin(), other_cpus.end(), random);\n  CPU_ZERO(&pretend_affinity_mask_);\n  CPU_SET(cpu, &pretend_affinity_mask_);\n  for (int i = 0; i < pretend_num_cores_ - 1; ++i) {\n    CPU_SET(other_cpus[i], &pretend_affinity_mask_);\n  }\n}\n\nvoid Scheduler::set_enable_chaos(bool enable_chaos) {\n  this->enable_chaos = enable_chaos;\n\n  /* When chaos mode is enabled, pretend to have 1-8 cores at random, otherwise\n   * return 1 to maximize throughput (since effectively we really only have\n   * one core).\n   */\n  pretend_num_cores_ = enable_chaos ? (random() % 8 + 1) : 1;\n  regenerate_affinity_mask();\n}\n\nvoid Scheduler::set_num_cores(int cores) {\n  pretend_num_cores_ = cores;\n  regenerate_affinity_mask();\n}\n\nstatic double random_frac() { return double(random() % INT32_MAX) / INT32_MAX; }\n\nstatic const int CHAOS_MODE_HIGH_PRIORITY = 0;\nstatic const int CHAOS_MODE_MEDIUM_PRIORITY_UNTIL_NEXT_YIELD = 1;\nstatic const int CHAOS_MODE_LOW_PRIORITY = 2;\n\nint Scheduler::choose_random_priority(RecordTask* t) {\n  double prob = t->tgid() == t->tid ? main_thread_low_priority_probability\n                                    : low_priority_probability;\n  if (random_frac() < prob) {\n    if (random_frac() < postpone_low_priority_until_after_yield) {\n      return CHAOS_MODE_MEDIUM_PRIORITY_UNTIL_NEXT_YIELD;\n    }\n    return CHAOS_MODE_LOW_PRIORITY;\n  }\n  return CHAOS_MODE_HIGH_PRIORITY;\n}\n\nstatic bool treat_syscall_as_nonblocking(int syscallno, SupportedArch arch) {\n  return is_sched_yield_syscall(syscallno, arch) ||\n         is_exit_syscall(syscallno, arch) ||\n         is_exit_group_syscall(syscallno, arch);\n}\n\nclass WaitAggregator {\npublic:\n  explicit WaitAggregator(int num_waits_before_polling_stops) :\n    num_waits_before_polling_stops(num_waits_before_polling_stops),\n    did_poll_stops(false) {}\n  bool try_wait(RecordTask* t);\n  // Return a list of tasks that we should check for unexpected exits.\n  const vector<RecordTask*>& exit_candidates() { return exit_candidates_; }\n  static bool try_wait_exit(RecordTask* t);\nprivate:\n  int num_waits_before_polling_stops;\n  // We defer making an actual wait syscall until we really need to.\n  // This records whether poll_stops has been called already.\n  bool did_poll_stops;\n  vector<RecordTask*> exit_candidates_;\n};\n\nbool WaitAggregator::try_wait(RecordTask* t) {\n  if (!did_poll_stops) {\n    if (num_waits_before_polling_stops > 0) {\n      --num_waits_before_polling_stops;\n    } else {\n      WaitManager::poll_stops();\n      did_poll_stops = true;\n    }\n  }\n\n  // Check if there is a status change for us.\n  WaitOptions options(t->tid);\n  // Rely on already-polled stops if we have them (don't do another syscall)\n  options.can_perform_syscall = !did_poll_stops;\n  options.block_seconds = 0;\n  WaitResult result = WaitManager::wait_stop(options);\n  if (result.code != WAIT_OK) {\n    exit_candidates_.push_back(t);\n    return false;\n  }\n  LOGM(debug) << \"wait on \" << t->tid << \" returns \" << result.status;\n  // If did_waitpid fails then the task left the stop prematurely\n  // due to SIGKILL or equivalent, and we should report that we did not get\n  // a stop.\n  return t->did_waitpid(result.status);\n}\n\nbool WaitAggregator::try_wait_exit(RecordTask* t) {\n  WaitOptions options(t->tid);\n  options.block_seconds = 0;\n  // Either we died/are dying unexpectedly, or we were in exec and changed the tid,\n  // or we're not dying at all.\n  // Try to differentiate the first two situations by seeing if there is an exit\n  // notification ready for us to de-queue, in which case we synthesize an\n  // exit event (but don't actually reap the task, instead leaving that\n  // for the generic cleanup code).\n  options.consume = false;\n  WaitResult result = WaitManager::wait_exit(options);\n  switch (result.code) {\n    case WAIT_OK: {\n      bool ok = t->did_waitpid(result.status);\n      ASSERT(t, ok) << \"did_waitpid shouldn't fail for exit statuses\";\n      return true;\n    }\n    case WAIT_NO_STATUS:\n      // This can happen when the task is in zap_pid_ns_processes waiting for all tasks\n      // in the pid-namespace to exit. It's not in a signal stop, but it's also not\n      // ready to be reaped yet, yet we're still tracing it. Don't wait on this\n      // task, we should be able to reap it later.\n      // But most likely this task is just still blocked.\n      return false;\n    case WAIT_NO_CHILD:\n    default:\n      return false;\n  }\n}\n\n/**\n * Returns true if we should return t as the runnable task. Otherwise we\n * should check the next task. Note that if this returns true get_next_thread\n * |must| return t as the runnable task, otherwise we will lose an event and\n * probably deadlock!!!\n */\nbool Scheduler::is_task_runnable(RecordTask* t, WaitAggregator& wait_aggregator, bool* by_waitpid) {\n  ASSERT(t, !must_run_task) << \"is_task_runnable called again after it \"\n                               \"returned a task that must run!\";\n\n  if (t->detached_proxy) {\n    LOGM(debug) << \"  \" << t->tid << \" is a detached proxy\";\n    return false;\n  }\n\n  if (t->waiting_for_reap) {\n    if (t->may_reap()) {\n      LOGM(debug) << \"  \" << t->tid << \" is waiting to be reaped, and can be reaped\";\n      return true;\n    }\n    LOGM(debug) << \"  \" << t->tid << \" is waiting to be reaped, but can't be reaped yet\";\n    return false;\n  }\n\n  LOGM(debug) << \"Task event is \" << t->ev();\n  if (!t->may_be_blocked() && (t->is_stopped() || t->was_reaped())) {\n    LOGM(debug) << \"  \" << t->tid << \" isn't blocked\";\n    if (t->schedule_frozen) {\n      LOGM(debug) << \"  \" << t->tid << \"  but is frozen\";\n      return false;\n    }\n    return true;\n  }\n\n  if (t->emulated_stop_type != NOT_STOPPED) {\n    if (t->is_stopped() && t->is_signal_pending(SIGCONT)) {\n      // We have to do this here. RecordTask::signal_delivered can't do it\n      // in the case where t->is_stopped(), because if we don't PTRACE_CONT\n      // the task, we'll never see the SIGCONT.\n      t->emulate_SIGCONT();\n      // We shouldn't run any user code since there is at least one signal\n      // pending.\n      if (t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n        *by_waitpid = true;\n        must_run_task = t;\n        LOGM(debug) << \"  Got \" << t->tid\n                   << \" out of emulated stop due to pending SIGCONT\";\n        return true;\n      }\n      // Tracee exited unexpectedly. Reexamine it now in case it has a new\n      // status we can use. Note that we cleared `t->emulated_stop_type`\n      // so we won't end up here again.\n      return is_task_runnable(t, wait_aggregator, by_waitpid);\n    } else {\n      LOGM(debug) << \"  \" << t->tid << \" is stopped by ptrace or signal\";\n      // We have no way to detect a SIGCONT coming from outside the tracees.\n      // We just have to poll SigPnd in /proc/<pid>/status.\n      enable_poll = true;\n      // We also need to check if the task got killed.\n      WaitAggregator::try_wait_exit(t);\n      // N.B.: If we supported ptrace exit notifications for killed tracee's\n      // that would need handling here, but we don't at the moment.\n      if (t->seen_ptrace_exit_event()) {\n        LOGM(debug) << \"  ... but it died\";\n        return true;\n      }\n      if (t->is_stopped()) {\n        return false;\n      }\n      // If we're not stopped, we need to get to the stop.\n      // AFAIK we can only get here with group stops, which are eagerly applied\n      // to every task in the group. If I'm wrong, die here.\n      ASSERT(t, t->emulated_stop_type == GROUP_STOP);\n      LOGM(debug) << \"  interrupting and waiting\";\n      t->do_ptrace_interrupt();\n      // Wait on the task to get the kernel to kick it into the group stop.\n      // If it died, we can deal with it later.\n      return t->wait();\n    }\n  }\n\n  if (t->seen_ptrace_exit_event() && !t->handled_ptrace_exit_event()) {\n    LOGM(debug) << \"  \" << t->tid << \" has a pending PTRACE_EVENT_EXIT to process; we can run it\";\n    return true;\n  } else if (t->waiting_for_ptrace_exit && !t->was_reaped()) {\n    LOGM(debug) << \"  \" << t->tid << \" is waiting to exit; checking status ...\";\n  } else if (t->is_stopped() || t->was_reaped()) {\n    LOGM(debug) << \"  \" << t->tid << \"  was already stopped with status \" << t->status();\n    if (t->schedule_frozen && t->status().ptrace_event() != PTRACE_EVENT_SECCOMP) {\n      LOGM(debug) << \"   but is frozen\";\n      return false;\n    }\n    // If we have may_be_blocked, but we aren't running, then somebody noticed\n    // this event earlier and already called did_waitpid for us. Just pretend\n    // we did that here.\n    *by_waitpid = true;\n    must_run_task = t;\n    return true;\n  } else if (EV_SYSCALL == t->ev().type() &&\n      PROCESSING_SYSCALL == t->ev().Syscall().state &&\n      treat_syscall_as_nonblocking(t->ev().Syscall().number, t->arch())) {\n    if (t->schedule_frozen) {\n      LOGM(debug) << \"  \" << t->tid << \" is frozen in sched_yield\";\n      return false;\n    }\n    // These syscalls never really block but the kernel may report that\n    // the task is not stopped yet if we pass WNOHANG. To make them\n    // behave predictably, do a blocking wait.\n    if (!t->wait()) {\n      // Task got SIGKILL or equivalent while trying to process the stop.\n      // Ignore this event and we'll process the new status later.\n      return false;\n    }\n    *by_waitpid = true;\n    must_run_task = t;\n    LOGM(debug) << \"  \" << syscall_name(t->ev().Syscall().number, t->arch())\n      << \" ready with status \" << t->status();\n    return true;\n  } else {\n    LOGM(debug) << \"  \" << t->tid << \" is blocked on \" << t->ev()\n              << \"; checking status ...\";\n  }\n\n  bool did_wait_for_t;\n  did_wait_for_t = wait_aggregator.try_wait(t);\n  if (did_wait_for_t) {\n    LOGM(debug) << \"  ready with status \" << t->status();\n    if (t->schedule_frozen && t->status().ptrace_event() != PTRACE_EVENT_SECCOMP) {\n      LOGM(debug) << \"   but is frozen\";\n      return false;\n    }\n    *by_waitpid = true;\n    must_run_task = t;\n    return true;\n  }\n  LOGM(debug) << \"  still blocked\";\n  // Try next task\n  return false;\n}\n\nRecordTask* Scheduler::find_next_runnable_task(WaitAggregator& wait_aggregator,\n                                               map<int, vector<RecordTask*>>& attention_set_by_priority,\n                                               bool* by_waitpid, int priority_threshold) {\n  *by_waitpid = false;\n\n  // The outer loop has one iteration per unique priority value.\n  // The inner loop iterates over all tasks with that priority.\n  for (auto& task_priority_set_entry : task_priority_set) {\n    int priority = task_priority_set_entry.first;\n    if (priority > priority_threshold) {\n      return nullptr;\n    }\n\n    SamePriorityTasks& same_priority_tasks = task_priority_set_entry.second;\n    if (enable_chaos) {\n      vector<RecordTask*> tasks;\n      for (RecordTask* t : same_priority_tasks.tasks) {\n        tasks.push_back(t);\n      }\n      shuffle(tasks.begin(), tasks.end(), random);\n      for (RecordTask* next : tasks) {\n        if (is_task_runnable(next, wait_aggregator, by_waitpid)) {\n          return next;\n        }\n      }\n    } else {\n      if (same_priority_tasks.consecutive_uses_of_attention_set < 20) {\n        ++same_priority_tasks.consecutive_uses_of_attention_set;\n        vector<RecordTask*>& attention_set = attention_set_by_priority[priority];\n        sort(attention_set.begin(), attention_set.end(),\n            [](RecordTask* a, RecordTask* b) -> bool {\n              return a->scheduler_token < b->scheduler_token;\n            });\n        for (RecordTask* t : attention_set) {\n          if (is_task_runnable(t, wait_aggregator, by_waitpid)) {\n            return t;\n          }\n        }\n      }\n      same_priority_tasks.consecutive_uses_of_attention_set = 0;\n\n      // Every time we schedule a new task we put it last on the list.\n      // Thus starting from the beginning essentially gives us round-robin\n      // behavior at each task priority level.\n      for (RecordTask* t : same_priority_tasks.tasks) {\n        if (is_task_runnable(t, wait_aggregator, by_waitpid)) {\n          return t;\n        }\n      }\n    }\n  }\n\n  return nullptr;\n}\n\nvoid Scheduler::setup_new_timeslice() {\n  Ticks max_timeslice_duration = max_ticks_;\n  if (enable_chaos) {\n    // Hypothesis: some bugs require short timeslices to expose. But we don't\n    // want the average timeslice to be too small. So make 10% of timeslices\n    // very short, 10% short-ish, and the rest uniformly distributed between 0\n    // and |max_ticks_|.\n    double timeslice_kind_frac = random_frac();\n    if (timeslice_kind_frac < very_short_timeslice_probability) {\n      max_timeslice_duration = very_short_timeslice_max_duration;\n    } else if (timeslice_kind_frac <\n               very_short_timeslice_probability + short_timeslice_probability) {\n      max_timeslice_duration = short_timeslice_max_duration;\n    } else {\n      max_timeslice_duration = max_ticks_;\n    }\n  }\n  current_timeslice_end_ = current_->tick_count() +\n                           (random() % min(max_ticks_, max_timeslice_duration));\n}\n\nvoid Scheduler::maybe_reset_priorities(double now) {\n  if (!enable_chaos || priorities_refresh_time > now) {\n    return;\n  }\n  // Reset task priorities again at some point in the future.\n  priorities_refresh_time =\n      now + random_frac() * priorities_refresh_max_interval;\n  vector<RecordTask*> tasks;\n  for (auto p : task_priority_set) {\n    for (RecordTask* t : p.second.tasks) {\n      tasks.push_back(t);\n    }\n  }\n  for (RecordTask* t : task_round_robin_queue) {\n    tasks.push_back(t);\n  }\n  for (RecordTask* t : tasks) {\n    update_task_priority_internal(t, choose_random_priority(t));\n  }\n}\n\nvoid Scheduler::notify_descheduled(RecordTask* t) {\n  if (!enable_chaos || t->priority != CHAOS_MODE_MEDIUM_PRIORITY_UNTIL_NEXT_YIELD) {\n    return;\n  }\n  LOGM(debug) << \"Lowering priority of \" << t->tid << \" after descheduling\";\n  update_task_priority_internal(t, CHAOS_MODE_LOW_PRIORITY);\n}\n\nvoid Scheduler::maybe_reset_high_priority_only_intervals(double now) {\n  if (!enable_chaos || high_priority_only_intervals_refresh_time > now) {\n    return;\n  }\n  int duration_step = 11;\n  high_priority_only_intervals_duration =\n      min_high_priority_only_duration *\n      pow(high_priority_only_duration_step_factor, duration_step);\n  high_priority_only_intervals_period =\n      high_priority_only_intervals_duration / high_priority_only_fraction;\n  high_priority_only_intervals_start = now;\n  if (random_frac() >= start_high_priority_only_immediately_probability) {\n    high_priority_only_intervals_start +=\n        random_frac() * (high_priority_only_intervals_period -\n                         high_priority_only_intervals_duration);\n  }\n  high_priority_only_intervals_refresh_time =\n      now +\n      min_high_priority_only_duration *\n          pow(high_priority_only_duration_step_factor,\n              high_priority_only_duration_steps - 1) /\n          high_priority_only_fraction;\n}\n\nbool Scheduler::in_high_priority_only_interval(double now) {\n  if (now < high_priority_only_intervals_start) {\n    return false;\n  }\n  double mod = fmod(now - high_priority_only_intervals_start,\n                    high_priority_only_intervals_period);\n  return mod < high_priority_only_intervals_duration;\n}\n\nbool Scheduler::treat_as_high_priority(RecordTask* t) {\n  return t->priority < CHAOS_MODE_LOW_PRIORITY;\n}\n\nvoid Scheduler::validate_scheduled_task() {\n  ASSERT(current_, !must_run_task || must_run_task == current_);\n  ASSERT(current_,\n         task_round_robin_queue.empty() ||\n             current_ == task_round_robin_queue.front());\n}\n\n/**\n * Wait for any tracee to change state, returning that tracee's `tid` and\n * `status` in the corresponding arguments. Optionally a maximum wait time\n * may be specified in `timeout`. Returns true if the wait was successful\n * and `tid` and `status` are valid, or false if the wait was interrupted\n * (by timeout or some other signal).\n */\nstatic WaitResultCode wait_any(pid_t& tid, WaitStatus& status, double timeout) {\n  WaitOptions options;\n  if (timeout > 0) {\n    options.block_seconds = timeout;\n  }\n  WaitResult result = WaitManager::wait_stop_or_exit(options);\n  switch (result.code) {\n    case WAIT_OK:\n      tid = result.tid;\n      status = result.status;\n      break;\n    case WAIT_NO_STATUS:\n      LOGM(debug) << \"  wait interrupted\";\n      break;\n    case WAIT_NO_CHILD:\n      LOGM(debug) << \"  no child to wait for\";\n      break;\n    default:\n      FATAL() << \"Unknown result code\";\n      break;\n  }\n  return result.code;\n}\n\n/**\n * Look up the task in `session` that currently has thread id `tid`, handling\n * a few corner cases like a thread execing and changing id and a thread\n * that previously detached. Returns null if task that was waited for is not\n * managed by the current session (e.g. it is dead or was previously detached).\n */\nstatic RecordTask* find_waited_task(RecordSession& session, pid_t tid, WaitStatus status)\n{\n  RecordTask* waited = session.find_task(tid);\n  if (status.ptrace_event() == PTRACE_EVENT_EXEC) {\n    if (waited && waited->waiting_for_reap) {\n      // We didn't reap this task yet but it's being replaced anyway. Get rid of it\n      // so we can replace it.\n      delete waited;\n      waited = nullptr;\n    }\n    if (!waited) {\n      // The thread-group-leader died and now the exec'ing thread has\n      // changed its thread ID to be thread-group leader.\n      waited = session.revive_task_for_exec(tid);\n    }\n  }\n\n  if (!waited) {\n    // See if this is one of our detached proxies' original tids.\n    waited = session.find_detached_proxy_task(tid);\n    if (!waited) {\n      LOGM(debug) << \"    ... but it's dead\";\n      return nullptr;\n    }\n\n    ASSERT(waited, waited->detached_proxy);\n    LOGM(debug) << \"    ... but it's a detached proxy\";\n    switch (status.type()) {\n      case WaitStatus::PTRACE_EVENT:\n        if (status.ptrace_event() == PTRACE_EVENT_EXIT) {\n          // Proxy was killed, perhaps via SIGKILL.\n          // Forward that to the real task.\n          ::kill(waited->rec_tid, SIGKILL);\n          LOGM(debug) << \"        ... sending SIGKILL to detached process \" << waited->rec_tid;;\n        } else {\n          ASSERT(waited, false) << \"Unexpected proxy ptrace event \" << status;\n        }\n        break;\n      case WaitStatus::SIGNAL_STOP:\n        // forward the signal to the real task, don't deliver it to the proxy.\n        ::kill(waited->rec_tid, status.stop_sig());\n        LOGM(debug) << \"        ... sending \" << signal_name(status.stop_sig()) <<\n          \" to detached process \" << waited->rec_tid;;\n        break;\n      default:\n        ASSERT(waited, false) << \"Unexpected proxy event \" << status;\n        break;\n    }\n    return nullptr;\n  }\n\n  if (waited->detached_proxy) {\n    if (!waited->did_waitpid(status)) {\n      // Proxy died unexpectedly during the waitpid, just ignore\n      // the stop.\n      return nullptr;\n    }\n    pid_t parent_rec_tid = waited->get_parent_pid();\n    LOGM(debug) << \"    ... but it's a detached process.\";\n    RecordTask *parent = session.find_task(parent_rec_tid);\n    if (parent && !waited->emulated_stop_pending) {\n      LOGM(debug) << \"    ... notifying parent.\";\n      waited->emulated_stop_type = CHILD_STOP;\n      waited->emulated_stop_pending = true;\n      waited->emulated_SIGCHLD_pending = true;\n      waited->emulated_stop_code = status;\n      parent->send_synthetic_SIGCHLD_if_necessary();\n    }\n    if (status.type() == WaitStatus::EXIT || status.type() == WaitStatus::FATAL_SIGNAL) {\n      if (waited->thread_group()->tgid == waited->tid) {\n        waited->thread_group()->exit_status = status;\n      }\n      if (!parent) {\n        // The task is now dead, but so is our parent, so none of our\n        // tasks care about this. We can now delete the proxy task.\n        // This will also reap the rec_tid of the proxy task.\n        delete waited;\n        // If there is a parent, we'll kill this task when the parent reaps it\n        // in our wait() emulation.\n      }\n    }\n\n    return nullptr;\n  }\n  return waited;\n}\n\nbool Scheduler::may_use_unlimited_ticks() {\n  return ntasks_stopped == 1 && !enable_chaos;\n}\n\nvoid Scheduler::started_task(RecordTask* t) {\n  LOGM(debug) << \"Starting \" << t->tid;\n  if (may_use_unlimited_ticks()) {\n    unlimited_ticks_mode = true;\n  }\n  --ntasks_stopped;\n  ASSERT(t, ntasks_stopped >= 0);\n}\n\nvoid Scheduler::stopped_task(RecordTask* t) {\n  LOGM(debug) << \"Stopping \" << t->tid;\n  ++ntasks_stopped;\n  // When a task is created/cloned it temporarily can be stopped\n  // but not in our task set.\n  ASSERT(t, ntasks_stopped <= static_cast<int>(session.tasks().size()) + 1);\n}\n\nScheduler::Rescheduled Scheduler::reschedule(Switchable switchable) {\n  Rescheduled result;\n  result.interrupted_by_signal = false;\n  result.by_waitpid = false;\n  result.started_new_timeslice = false;\n\n  LOGM(debug) << \"Scheduling next task (\" <<\n    ((switchable == PREVENT_SWITCH) ? \"PREVENT_SWITCH)\" : \"ALLOW_SWITCH)\");\n\n  must_run_task = nullptr;\n  enable_poll = false;\n\n  double now = monotonic_now_sec();\n  double timeout = interrupt_after_elapsed_time();\n\n  maybe_reset_priorities(now);\n\n  if (current_ && switchable == PREVENT_SWITCH) {\n    LOGM(debug) << \"  (\" << current_->tid << \" is un-switchable at \"\n               << current_->ev() << \")\";\n    if (!current_->is_stopped()) {\n      /* |current| is un-switchable, but already running. Wait for it to change\n      * state before \"scheduling it\", so avoid busy-waiting with our client. */\n      LOGM(debug) << \"  and running; waiting for state change\";\n      while (true) {\n        if (unlimited_ticks_mode) {\n          LOGM(debug) << \"Using unlimited ticks mode\";\n          // Unlimited ticks mode means that there is only one non-blocked task.\n          // We run it without a timeslice to avoid unnecessary switches to the\n          // tracer. However, this does mean we need to be on the look out for\n          // other tasks becoming runnable, which we usually check on timeslice\n          // expiration.\n          ASSERT(current_, !ntasks_stopped);\n          pid_t tid;\n          WaitStatus status;\n          WaitResultCode wait_result = wait_any(tid, status, -1);\n          if (wait_result == WAIT_NO_STATUS) {\n            ASSERT(current_, !must_run_task);\n            result.interrupted_by_signal = true;\n            return result;\n          }\n          ASSERT(current_, wait_result == WAIT_OK);\n          RecordTask *waited = find_waited_task(session, tid, status);\n          if (!waited) {\n            continue;\n          }\n          if (!waited->did_waitpid(status)) {\n            // Tracee exited stop prematurely due to SIGKILL or equivalent.\n            // Pretend the stop didn't happen.\n            continue;\n          }\n          result.by_waitpid = true;\n          LOGM(debug) << \"  new status is \" << current_->status();\n          // Another task just became runnable, we're no longer in unlimited\n          // ticks mode\n          unlimited_ticks_mode = false;\n          if (waited == current_) {\n            break;\n          }\n          // If we got some other event, make sure the current thread has run\n          // at least a little bit. We could change the ticks period here to\n          // re-enable normal timeslice behavior, but we don't want to rely on\n          // the kernel/hardware correctly changing the ticks period while the\n          // counters are running. So instead, we just give it the remainder of\n          // a 50ms time slice, after which the wait() call below will manually\n          // PTRACE_INTERRUPT it.\n          double elapsed = now - monotonic_now_sec();\n          timeout = elapsed > 0.05 ? 0.0 : 0.05 - elapsed;\n          LOGM(debug) << \"  But that's not our current task...\";\n        } else {\n          if (current_->wait(timeout)) {\n            result.by_waitpid = true;\n            LOGM(debug) << \"  new status is \" << current_->status();\n          } else {\n            // A SIGKILL or equivalent kicked the task out of the stop.\n            // We are now running towards PTRACE_EVENT_EXIT or zombie status.\n            // Even though we're PREVENT_SWITCH, we still have to switch.\n            // The task won't be stopped so this is handled below.\n          }\n          break;\n        }\n      }\n#ifdef MONITOR_UNSWITCHABLE_WAITS\n      double wait_duration = monotonic_now_sec() - now;\n      if (wait_duration >= 0.010) {\n        LOGM(warn) << \"Waiting for unswitchable \" << current_->ev()\n                   << \" took \" << 1000.0 * wait_duration << \"ms\";\n      }\n#endif\n    }\n    if (current_->is_stopped() || current_->was_reaped()) {\n      validate_scheduled_task();\n      return result;\n    }\n  }\n\n  unlimited_ticks_mode = false;\n\n  RecordTask* next = nullptr;\n  // While a threadgroup is in execve, treat all tasks as blocked.\n  while (!in_exec_tgid) {\n    maybe_reset_high_priority_only_intervals(now);\n    last_reschedule_in_high_priority_only_interval =\n        in_high_priority_only_interval(now);\n    WaitAggregator wait_aggregator((task_priority_set_total_count + task_round_robin_queue.size())/100 + 1);\n\n    map<int, vector<RecordTask*>> attention_set_by_priority;\n    for (pid_t tid : TraceeAttentionSet::read()) {\n      if (current_ && current_->tid == tid) {\n        // current_ will almost always be in the attention set because of\n        // ptrace-stop activity related to when we last ran it.\n        // It's fairer to leave it out of the attention set.\n        continue;\n      }\n      RecordTask* t = session.find_task(tid);\n      if (t) {\n        attention_set_by_priority[t->priority].push_back(t);\n      }\n    }\n\n    if (current_) {\n      // Determine if we should run current_ again\n      RecordTask* round_robin_task = get_round_robin_task();\n      if (!round_robin_task) {\n        next = find_next_runnable_task(wait_aggregator, attention_set_by_priority, &result.by_waitpid,\n                                       current_->priority - 1);\n        if (next) {\n          // There is a runnable higher-priority task. Run it.\n          break;\n        }\n      }\n      // To run current_ again:\n      // -- its timeslice must not have expired\n      // -- it must be high priority if we're in a high-priority-only interval\n      // -- it must be the head of the round-robin queue or the queue is empty\n      // (this might not hold if it was at the head of the queue but we\n      // rejected current_ and popped it in a previous iteration of this loop)\n      // -- it must be runnable, and not in an unstable exit.\n      if (!always_switch &&\n          (!round_robin_task || round_robin_task == current_) &&\n          (treat_as_high_priority(current_) ||\n           !last_reschedule_in_high_priority_only_interval) &&\n          current_->tick_count() < current_timeslice_end() &&\n          is_task_runnable(current_, wait_aggregator, &result.by_waitpid)) {\n        LOGM(debug) << \"  Carrying on with task \" << current_->tid;\n        validate_scheduled_task();\n        return result;\n      }\n      // Having rejected current_, be prepared to run the next task in the\n      // round-robin queue.\n      maybe_pop_round_robin_task(current_);\n    }\n\n    LOGM(debug) << \"  need to reschedule\";\n\n    next = get_round_robin_task();\n    if (next) {\n      LOGM(debug) << \"Trying task \" << next->tid << \" from yield queue\";\n      if (is_task_runnable(next, wait_aggregator, &result.by_waitpid)) {\n        break;\n      }\n      maybe_pop_round_robin_task(next);\n      continue;\n    }\n\n    next = find_next_runnable_task(wait_aggregator, attention_set_by_priority, &result.by_waitpid, INT32_MAX);\n    if (!next && !wait_aggregator.exit_candidates().empty()) {\n      // We need to check for tasks that have unexpectedly exited.\n      // First check if there is any exit status pending. Normally there won't be.\n      WaitOptions options;\n      options.block_seconds = 0;\n      options.consume = false;\n      // We check for a stop_or_exit even though we'd really like to check for\n      // just an exit. Unfortunately wait_exit does not work properly if we\n      // don't consume the status and want to wait on any tracee.\n      // If we have a stop, that's OK, we'll just do extra work here.\n      WaitResult result = WaitManager::wait_stop_or_exit(options);\n      if (result.code == WAIT_OK) {\n        // Check which candidate has exited, if any.\n        for (RecordTask* t : wait_aggregator.exit_candidates()) {\n          if (WaitAggregator::try_wait_exit(t)) {\n            next = t;\n            break;\n          }\n        }\n      }\n    }\n\n    if (next && !treat_as_high_priority(next) &&\n        last_reschedule_in_high_priority_only_interval) {\n      if (result.by_waitpid) {\n        LOGM(debug)\n            << \"Waking up low-priority task with by_waitpid; not sleeping\";\n        // We must run this low-priority task. Fortunately it's just waking\n        // up from a blocking syscall; we'll record the syscall event and then\n        // (unless it was an interrupted syscall) we'll return to\n        // get_next_thread, which will either run a higher priority thread\n        // or (more likely) reach here again but in the !*by_waitpid case.\n      } else {\n        LOGM(debug)\n            << \"Waking up low-priority task without by_waitpid; sleeping\";\n        sleep_time(0.001);\n        now = monotonic_now_sec();\n        continue;\n      }\n    }\n    break;\n  }\n\n  if (next) {\n    LOGM(debug) << \"  selecting task \" << next->tid;\n  } else {\n    // All the tasks are blocked.\n    // Wait for the next one to change state.\n\n    // Clear the round-robin queue since we will no longer be able to service\n    // those tasks in-order.\n    while (RecordTask* t = get_round_robin_task()) {\n      maybe_pop_round_robin_task(t);\n    }\n\n    LOGM(debug) << \"  all tasks blocked, waiting for runnable (\"\n               << task_priority_set_total_count << \" total)\";\n\n    WaitStatus status;\n    do {\n      double timeout = enable_poll ? 1 : 0;\n      pid_t tid;\n      WaitResultCode wait_result = wait_any(tid, status, timeout);\n      if (wait_result == WAIT_NO_STATUS) {\n        if (must_run_task) {\n          FATAL() << \"must_run_task but no status?\";\n        }\n        result.interrupted_by_signal = true;\n        return result;\n      }\n      if (wait_result == WAIT_NO_CHILD) {\n        // It's possible that the original thread group was detached,\n        // and the only thing left we were waiting for, in which case we\n        // get ECHILD here. Just abort this record step, so the caller\n        // can end the record session.\n        return result;\n      }\n      LOGM(debug) << \"  \" << tid << \" changed status to \" << status;\n      next = find_waited_task(session, tid, status);\n      now = -1; // invalid, don't use\n      if (next) {\n        ASSERT(next,\n               next->may_be_blocked() ||\n                   status.ptrace_event() == PTRACE_EVENT_EXIT ||\n                   status.reaped())\n            << \"Scheduled task should have been blocked\";\n        if (!next->did_waitpid(status)) {\n          next = nullptr;\n        } else if (in_exec_tgid && next->tgid() != in_exec_tgid) {\n          // Some threadgroup is doing execve and this task isn't in\n          // that threadgroup. Don't schedule this task until the execve\n          // is complete.\n          LOGM(debug) << \"  ... but threadgroup \" << in_exec_tgid << \" is in execve, so ignoring for now\";\n          next = nullptr;\n        }\n      }\n    } while (!next);\n    result.by_waitpid = true;\n    must_run_task = next;\n  }\n\n  if (current_ && current_ != next) {\n    notify_descheduled(current_);\n    if (is_logging_enabled(LOG_debug, __FILE__)) {\n      LOGM(debug) << \"Switching from \" << current_->tid << \"(\" << current_->name()\n                  << \") to \" << next->tid << \"(\" << next->name() << \") (priority \"\n                  << current_->priority << \" to \" << next->priority << \") at \"\n                  << current_->trace_writer().time();\n    }\n  }\n\n  maybe_reset_high_priority_only_intervals(now);\n  current_ = next;\n  if (!current_->in_round_robin_queue) {\n    // Move it to the end of the per-priority task list\n    remove_from_task_priority_set(current_);\n    insert_into_task_priority_set(current_);\n  }\n  validate_scheduled_task();\n  setup_new_timeslice();\n  result.started_new_timeslice = true;\n  return result;\n}\n\ndouble Scheduler::interrupt_after_elapsed_time() const {\n  // Where does the 3 seconds come from?  No especially\n  // good reason.  We want this to be pretty high,\n  // because it's a last-ditch recovery mechanism, not a\n  // primary thread scheduler.  Though in theory the\n  // PTRACE_INTERRUPT's shouldn't interfere with other\n  // events, that's hard to test thoroughly so try to\n  // avoid it.\n  double delay = 3;\n  if (enable_chaos) {\n    double now = monotonic_now_sec();\n    if (high_priority_only_intervals_start) {\n      double next_interval_start =\n          (floor((now - high_priority_only_intervals_start) /\n                 high_priority_only_intervals_period) +\n           1) *\n              high_priority_only_intervals_period +\n          high_priority_only_intervals_start;\n      delay = min(delay, next_interval_start - now);\n    }\n    if (high_priority_only_intervals_refresh_time) {\n      delay = min(delay, high_priority_only_intervals_refresh_time - now);\n    }\n    if (priorities_refresh_time) {\n      delay = min(delay, priorities_refresh_time - now);\n    }\n  }\n  return max(0.001, delay);\n}\n\nbool Scheduler::CompareByScheduleOrder::operator()(\n        RecordTask* a, RecordTask* b) const {\n  return a->scheduler_token < b->scheduler_token;\n}\n\nvoid Scheduler::insert_into_task_priority_set(RecordTask* t) {\n  t->scheduler_token = ++reschedule_count;\n  task_priority_set[t->priority].tasks.insert(t);\n  ++task_priority_set_total_count;\n}\n\nvoid Scheduler::remove_from_task_priority_set(RecordTask* t) {\n  task_priority_set[t->priority].tasks.erase(t);\n  --task_priority_set_total_count;\n}\n\nvoid Scheduler::on_create(RecordTask* t) {\n  DEBUG_ASSERT(!t->in_round_robin_queue);\n  if (enable_chaos) {\n    // new tasks get a random priority\n    t->priority = choose_random_priority(t);\n  }\n  insert_into_task_priority_set(t);\n  unlimited_ticks_mode = false;\n}\n\nvoid Scheduler::on_destroy(RecordTask* t) {\n  if (t == current_) {\n    current_ = nullptr;\n  }\n  // When the last task in a threadgroup undergoing execve dies,\n  // the execve is over.\n  if (t->tgid() == in_exec_tgid &&\n      t->thread_group()->task_set().size() == 1) {\n    in_exec_tgid = 0;\n  }\n\n  if (t->in_round_robin_queue) {\n    auto iter =\n        find(task_round_robin_queue.begin(), task_round_robin_queue.end(), t);\n    task_round_robin_queue.erase(iter);\n  } else {\n    remove_from_task_priority_set(t);\n  }\n}\n\nvoid Scheduler::update_task_priority(RecordTask* t, int value) {\n  if (!enable_chaos) {\n    update_task_priority_internal(t, value);\n  }\n}\n\nvoid Scheduler::in_stable_exit(RecordTask* t) {\n  update_task_priority_internal(t, t->priority);\n}\n\nvoid Scheduler::update_task_priority_internal(RecordTask* t, int value) {\n  if (t->stable_exit && !enable_chaos) {\n    // Tasks in a stable exit have the highest priority. We should force them\n    // to complete exiting ASAP to clean up resources. They may not be runnable\n    // due to waiting for PTRACE_EVENT_EXIT to complete.\n    value = -9999;\n  }\n  if (t->priority == value) {\n    return;\n  }\n  if (t->in_round_robin_queue) {\n    t->priority = value;\n    return;\n  }\n  remove_from_task_priority_set(t);\n  t->priority = value;\n  insert_into_task_priority_set(t);\n}\n\nstatic bool round_robin_scheduling_enabled() {\n  static bool disabled = getenv(\"RR_DISABLE_ROUND_ROBIN\") != nullptr;\n  return !disabled;\n}\n\nvoid Scheduler::schedule_one_round_robin(RecordTask* t) {\n  if (!round_robin_scheduling_enabled()) {\n    LOGM(debug) << \"Would schedule round-robin because of task \" << t->tid << \", but disabled\";\n    return;\n  }\n\n  LOGM(debug) << \"Scheduling round-robin because of task \" << t->tid;\n\n  ASSERT(t, t == current_);\n  maybe_pop_round_robin_task(t);\n  ASSERT(t, !t->in_round_robin_queue);\n\n  for (auto p : task_priority_set) {\n    for (RecordTask* tt : p.second.tasks) {\n      if (tt != t && !tt->in_round_robin_queue) {\n        task_round_robin_queue.push_back(tt);\n        tt->in_round_robin_queue = true;\n      }\n    }\n  }\n  task_priority_set.clear();\n  task_round_robin_queue.push_back(t);\n  t->in_round_robin_queue = true;\n  expire_timeslice();\n}\n\nRecordTask* Scheduler::get_round_robin_task() {\n  return task_round_robin_queue.empty() ? nullptr\n                                        : task_round_robin_queue.front();\n}\n\nvoid Scheduler::maybe_pop_round_robin_task(RecordTask* t) {\n  if (task_round_robin_queue.empty() || t != task_round_robin_queue.front()) {\n    return;\n  }\n  task_round_robin_queue.pop_front();\n  t->in_round_robin_queue = false;\n  insert_into_task_priority_set(t);\n}\n\nvoid Scheduler::did_enter_execve(RecordTask* t) {\n  ASSERT(t, !in_exec_tgid) <<\n    \"Entering execve while another execve is already happening in tgid \" << in_exec_tgid;\n  in_exec_tgid = t->tgid();\n}\n\nvoid Scheduler::did_exit_execve(RecordTask* t) {\n  ASSERT(t, in_exec_tgid == t->tgid()) <<\n    \"Exiting an execve we didn't know about\";\n  in_exec_tgid = 0;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Scheduler.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REC_SCHED_H_\n#define RR_REC_SCHED_H_\n\n#include <sched.h>\n\n#include <deque>\n#include <map>\n#include <random>\n#include <set>\n#include <vector>\n\n#include \"Ticks.h\"\n#include \"TraceFrame.h\"\n#include \"core.h\"\n#include \"util.h\"\n\nnamespace rr {\n\nclass RecordSession;\nclass RecordTask;\nclass WaitAggregator;\n\n/**\n * Overview of rr scheduling:\n *\n * rr honours priorities set by setpriority(2) --- even in situations where the\n * kernel doesn't, e.g. when a non-privileged task tries to increase its\n * priority. Normally rr honors priorities strictly by scheduling the highest\n * priority runnable task; tasks with equal priorities are scheduled in\n * round-robin fashion. Strict priority scheduling helps find bugs due to\n * starvation.\n *\n * When a task calls sched_yield we temporarily switch to a completely\n * fair scheduler that ignores priorities. All tasks are placed on a queue\n * and while the queue is non-empty we take the next task from the queue and\n * run it for a quantum if it's runnable. We do this because tasks calling\n * sched_yield are often expecting some kind of fair scheduling and may deadlock\n * (e.g. trying to acquire a spinlock) if some other tasks don't get a chance\n * to run.\n *\n * The scheduler only runs during recording. During replay we're just replaying\n * the recorded scheduling decisions.\n *\n * The main interface to the scheduler is |get_next_thread|. This gets called\n * after every rr event to decide which task to run next.\n *\n * The scheduler gives the current task a 'timeslice', a ticks deadline after\n * which we will try to switch to another task. So |get_next_thread| first\n * checks whether the currently running task has exceeded that deadline. If\n * not, and the current task is runnable, we schedule it again. If it's blocked\n * or has exceeded its deadline, we search for another task to run:\n * taking tasks from the round-robin queue until we find one that's runnable,\n * and then if the round-robin queue is empty, choosing the highest-priority\n * task that's runnable. If the highest-priority runnable task has the same\n * priority as the current task, choose the next runnable task after the\n * current task (so equal priority tasks run in round-robin order).\n *\n * The main parameter to the scheduler is |max_ticks|, which controls the\n * length of each timeslice.\n */\nclass Scheduler {\npublic:\n  /**\n   * Like most task schedulers, there are conflicting goals to balance. Lower\n   * max-ticks generally makes the application more \"interactive\", generally\n   * speaking lower latency. (And wrt catching bugs, this setting generally\n   * creates more opportunity for bugs to arise in multi-threaded/process\n   * applications.) This comes at the cost of more overhead from scheduling and\n   * context switching. Context switches during recording are expensive because\n   * we must context switch to the rr process and then to the next tracee task.\n   * Increasing max-ticks generally gives the application higher throughput.\n   *\n   * Using ticks (retired conditional branches) to compute timeslices is quite\n   * crude, since they don't correspond to any unit of time in general.\n   * Hopefully that can be improved, but empirical data from Firefox\n   * demonstrate, surprisingly consistently, a distribution of insns/rcb massed\n   * around 10. Somewhat arbitrarily guessing ~4cycles/insn on average\n   * (fair amount of pointer chasing), that implies for a nominal 2GHz CPU\n   * 50,000 ticks per millisecond. We choose the default max ticks to give us\n   * 50ms timeslices, i.e. 2,500,000 ticks.\n   */\n  enum { DEFAULT_MAX_TICKS = 2500000 };\n  /**\n   * Don't allow max_ticks to get above this value.\n   */\n  enum { MAX_MAX_TICKS = 1000000000 };\n\n  Scheduler(RecordSession& session);\n\n  void set_max_ticks(Ticks max_ticks) {\n    DEBUG_ASSERT(max_ticks <= MAX_MAX_TICKS);\n    max_ticks_ = max_ticks;\n  }\n  Ticks max_ticks() { return max_ticks_; }\n  void set_always_switch(bool always_switch) {\n    this->always_switch = always_switch;\n  }\n  void set_enable_chaos(bool enable_chaos);\n  void set_num_cores(int cores);\n\n  /**\n   * Schedule a new runnable task (which may be the same as current()).\n   *\n   * The new current() task is guaranteed to either have already been\n   * runnable, or have been made runnable by a waitpid status change (in\n   * which case, result.by_waitpid will be true.\n   * \n   * After this, if Rescheduled::interrupted_by_signal is false,\n   * and there is a new current task, its is_stopped() must\n   * be true.\n   */\n  struct Rescheduled {\n    bool interrupted_by_signal;\n    bool by_waitpid;\n    bool started_new_timeslice;\n  };\n  Rescheduled reschedule(Switchable switchable);\n\n  /**\n   * Set the priority of |t| to |value| and update related\n   * state.\n   */\n  void update_task_priority(RecordTask* t, int value);\n\n  /**\n   * Do one round of round-robin scheduling if we're not already doing one.\n   * If we start round-robin scheduling now, make last_task the last\n   * task to be scheduled.\n   * If the task_round_robin_queue is empty this moves all tasks into it,\n   * putting last_task last.\n   */\n  void schedule_one_round_robin(RecordTask* last_task);\n\n  void on_create(RecordTask* t);\n  /**\n   * De-register a thread. This function should be called when a thread exits.\n   */\n  void on_destroy(RecordTask* t);\n\n  RecordTask* current() const { return current_; }\n  void set_current(RecordTask* t) { current_ = t; }\n\n  Ticks current_timeslice_end() const { return current_timeslice_end_; }\n\n  void expire_timeslice() { current_timeslice_end_ = 0; }\n\n  double interrupt_after_elapsed_time() const;\n\n  /**\n   * Return the number of cores we should report to applications.\n   */\n  int pretend_num_cores() const { return pretend_num_cores_; }\n  /**\n   * Return the processor affinity masks we should report to applications.\n   */\n  const cpu_set_t& pretend_affinity_mask() const {\n    return pretend_affinity_mask_;\n  }\n\n  void in_stable_exit(RecordTask* t);\n\n  /**\n   * In unlimited ticks mode, only one task is runnable while every other task\n   * is blocked in the kernel. Check whether we're in that situation.\n   */\n  bool may_use_unlimited_ticks();\n\n  /**\n   * Let the scheduler know that the previously stopped task has resumed.\n   */\n  void started_task(RecordTask* t);\n\n  /**\n   * Let the scheduler know that the previously running task has reached a kernel stop\n   * (typically a ptrace stop). Tasks that are blocked but not in a stop\n   * are still \"running\" for our purposes here.\n   */\n  void stopped_task(RecordTask* t);\n\n  /**\n   * Let the scheduler know that the task has entered an execve.\n   */\n  void did_enter_execve(RecordTask* t);\n  /**\n   * Let the scheduler know that the task has exited an execve.\n   */\n  void did_exit_execve(RecordTask* t);\n\nprivate:\n  struct CompareByScheduleOrder {\n    bool operator()(RecordTask* a, RecordTask* b) const;\n  };\n  struct SamePriorityTasks {\n    // Tasks ordered in of last-scheduled, most recently scheduled last\n    std::set<RecordTask*, CompareByScheduleOrder> tasks;\n    int consecutive_uses_of_attention_set;\n\n    SamePriorityTasks() : consecutive_uses_of_attention_set(0) {}\n  };\n  // Tasks sorted by priority.\n  typedef std::map<int, SamePriorityTasks> TaskPrioritySet;\n  typedef std::deque<RecordTask*> TaskQueue;\n  typedef std::default_random_engine Random;\n\n  /**\n   * Pull a task from the round-robin queue if available. Otherwise,\n   * find the highest-priority task that is runnable. If the highest-priority\n   * runnable task has the same priority as 't', return 't' or\n   * the next runnable task after 't' in round-robin order.\n   * Sets 'by_waitpid' to true if we determined the task was runnable by\n   * calling waitpid on it and observing a state change. This task *must*\n   * be returned by get_next_thread, and is_task_runnable must not be called\n   * on it again until it has run.\n   * Considers only tasks with priority <= priority_threshold.\n   */\n  RecordTask* find_next_runnable_task(WaitAggregator& wait_aggregator,\n                                      std::map<int, std::vector<RecordTask*>>& attention_set_by_priority,\n                                      bool* by_waitpid, int priority_threshold);\n  /**\n   * Returns the first task in the round-robin queue or null if it's empty,\n   * removing it from the round-robin queue.\n   */\n  RecordTask* get_round_robin_task();\n  void maybe_pop_round_robin_task(RecordTask* t);\n  void setup_new_timeslice();\n  void maybe_reset_priorities(double now);\n  void notify_descheduled(RecordTask* t);\n  int choose_random_priority(RecordTask* t);\n  void update_task_priority_internal(RecordTask* t, int value);\n  void maybe_reset_high_priority_only_intervals(double now);\n  bool in_high_priority_only_interval(double now);\n  bool treat_as_high_priority(RecordTask* t);\n  bool is_task_runnable(RecordTask* t, WaitAggregator& wait_aggregator, bool* by_waitpid);\n  void validate_scheduled_task();\n  void regenerate_affinity_mask();\n\n  void insert_into_task_priority_set(RecordTask* t);\n  void remove_from_task_priority_set(RecordTask* t);\n\n  uint64_t reschedule_count;\n\n  Random random;\n\n  RecordSession& session;\n\n  /**\n   * Every task of this session is either in task_priority_set\n   * (when in_round_robin_queue is false), or in task_round_robin_queue\n   * (when in_round_robin_queue is true).\n   *\n   * task_priority_set is a set of pairs of (task->priority, task). This\n   * lets us efficiently iterate over the tasks with a given priority, or\n   * all tasks in priority order.\n   */\n  TaskPrioritySet task_priority_set;\n  size_t task_priority_set_total_count;\n  TaskQueue task_round_robin_queue;\n\n  /**\n   * The currently scheduled task. This may be nullptr if the last scheduled\n   * task\n   * has been destroyed.\n   */\n  RecordTask* current_;\n  Ticks current_timeslice_end_;\n\n  /**\n   * At this time (or later) we should refresh these values.\n   */\n  double high_priority_only_intervals_refresh_time;\n  double high_priority_only_intervals_start;\n  double high_priority_only_intervals_duration;\n  double high_priority_only_intervals_period;\n  /**\n   * At this time (or later) we should rerandomize RecordTask priorities.\n   */\n  double priorities_refresh_time;\n\n  Ticks max_ticks_;\n\n  RecordTask* must_run_task;\n\n  cpu_set_t pretend_affinity_mask_;\n  int pretend_num_cores_;\n\n  /**\n   * If nonzero, the threadgroup ID of a threadgroup where one of the\n   * threads is currently in an execve.\n   */\n  pid_t in_exec_tgid;\n\n  /**\n   * The number of tasks that have is_stopped_ set.\n   */\n  int ntasks_stopped;\n\n  /**\n   * When true, context switch at every possible point.\n   */\n  bool always_switch;\n  /**\n   * When true, make random scheduling decisions to try to increase the\n   * probability of finding buggy schedules.\n   */\n  bool enable_chaos;\n\n  bool enable_poll;\n  bool last_reschedule_in_high_priority_only_interval;\n\n  bool unlimited_ticks_mode;\n};\n\n} // namespace rr\n\n#endif /* RR_REC_SCHED_H_ */\n"
  },
  {
    "path": "src/ScopedFd.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_SCOPED_FD_H_\n#define RR_SCOPED_FD_H_\n\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE\n#endif\n#include <fcntl.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#include \"log.h\"\n\nnamespace rr {\n\n/**\n * RAII helper to open a file and then close the fd when the helper\n * goes out of scope.\n */\nclass ScopedFd {\npublic:\n  ScopedFd() : fd(-1) {}\n  explicit ScopedFd(int fd) : fd(fd) {}\n  ScopedFd(const char* pathname, int flags, mode_t mode = 0)\n      : fd(open(pathname, flags, mode)) {}\n  ScopedFd(ScopedFd&& other) : fd(other.fd) { other.fd = -1; }\n  ~ScopedFd() { close(); }\n\n  ScopedFd& operator=(ScopedFd&& other) {\n    close();\n    fd = other.fd;\n    other.fd = -1;\n    return *this;\n  }\n\n  operator int() const { return get(); }\n  int get() const { return fd; }\n  int extract() {\n    int result = fd;\n    fd = -1;\n    return result;\n  }\n\n  bool is_open() const { return fd >= 0; }\n  void close() {\n    if (fd >= 0) {\n      int err = ::close(fd);\n      // With EINTR/EIO, it is unspecified whether fd will be\n      // closed, but on Linux, it is always removed from the FD\n      // table, so the close was successful for our purposes.\n      if (err != 0 && err != -EINTR && err != -EIO) {\n        FATAL() << \"Unexpected error while closing fd \" << fd;\n      }\n    }\n    fd = -1;\n  }\n\n  static ScopedFd openat(const ScopedFd &dir, const char* pathname,\n                         int flags, mode_t mode = 0) {\n    return ScopedFd(::openat(dir.get(), pathname, flags, mode));\n  }\n\nprivate:\n  int fd;\n};\n\n} // namespace rr\n\n#endif // RR_SCOPED_FD_H\n"
  },
  {
    "path": "src/SeccompFilterRewriter.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"SeccompFilterRewriter.h\"\n\n#include <linux/filter.h>\n#include <linux/seccomp.h>\n\n#include <algorithm>\n\n#include \"AddressSpace.h\"\n#include \"AutoRemoteSyscalls.h\"\n#include \"RecordTask.h\"\n#include \"Registers.h\"\n#include \"ThreadGroup.h\"\n#include \"kernel_abi.h\"\n#include \"log.h\"\n#include \"seccomp-bpf.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic void set_syscall_result(RecordTask* t, long ret) {\n  Registers r = t->regs();\n  r.set_syscall_result(ret);\n  t->set_regs(r);\n}\n\nstatic void pass_through_seccomp_filter(RecordTask* t) {\n  long ret;\n  {\n    AutoRemoteSyscalls remote(t);\n    ret = remote.syscall(t->regs().original_syscallno(), t->regs().orig_arg1(),\n                         t->regs().arg2(), t->regs().arg3());\n  }\n  set_syscall_result(t, ret);\n  ASSERT(t, t->regs().syscall_failed());\n}\n\ntemplate <typename Arch>\nstatic void install_patched_seccomp_filter_arch(\n    RecordTask* t, unordered_map<uint32_t, uint16_t>& result_to_index,\n    vector<uint32_t>& index_to_result) {\n  // Take advantage of the fact that the filter program is arg3() in both\n  // prctl and seccomp syscalls.\n  bool ok = true;\n  auto prog =\n      t->read_mem(remote_ptr<typename Arch::sock_fprog>(t->regs().arg3()), &ok);\n  if (!ok) {\n    // We'll probably return EFAULT but a kernel that doesn't support\n    // seccomp(2) should return ENOSYS instead, so just run the original\n    // system call to get the correct error.\n    pass_through_seccomp_filter(t);\n    return;\n  }\n  auto code = t->read_mem(prog.filter.rptr(), prog.len, &ok);\n  if (!ok) {\n    pass_through_seccomp_filter(t);\n    return;\n  }\n  // Convert all returns to TRACE returns so that rr can handle them.\n  // See handle_ptrace_event in RecordSession.\n  for (auto& u : code) {\n    if (BPF_CLASS(u.code) == BPF_RET) {\n      ASSERT(t, BPF_RVAL(u.code) == BPF_K)\n          << \"seccomp-bpf program uses BPF_RET with A/X register, not \"\n             \"supported\";\n      if (u.k != SECCOMP_RET_ALLOW) {\n        if (result_to_index.find(u.k) == result_to_index.end()) {\n          ASSERT(t,\n                 SeccompFilterRewriter::BASE_CUSTOM_DATA +\n                         index_to_result.size() <\n                     SECCOMP_RET_DATA)\n              << \"Too many distinct constants used in seccomp-bpf programs\";\n          result_to_index[u.k] = index_to_result.size();\n          index_to_result.push_back(u.k);\n        }\n        u.k = (SeccompFilterRewriter::BASE_CUSTOM_DATA + result_to_index[u.k]) |\n              SECCOMP_RET_TRACE;\n      }\n    }\n  }\n\n  SeccompFilter<typename Arch::sock_filter> f;\n  for (auto& e : AddressSpace::rr_page_syscalls()) {\n    if (e.privileged == AddressSpace::PRIVILEGED) {\n      auto ip = AddressSpace::rr_page_syscall_exit_point(e.traced, e.privileged,\n                                                         e.enabled,\n                                                         Arch::arch());\n      f.allow_syscalls_from_callsite(ip);\n    }\n  }\n  f.filters.insert(f.filters.end(), code.begin(), code.end());\n\n  long ret;\n  {\n    AutoRemoteSyscalls remote(t);\n    AutoRestoreMem mem(\n        remote, nullptr,\n        sizeof(prog) + f.filters.size() * sizeof(typename Arch::sock_filter));\n    auto code_ptr = mem.get().cast<typename Arch::sock_filter>();\n    t->write_mem(code_ptr, f.filters.data(), f.filters.size());\n    prog.len = f.filters.size();\n    prog.filter = code_ptr;\n    auto prog_ptr = remote_ptr<void>(code_ptr + f.filters.size())\n                        .cast<typename Arch::sock_fprog>();\n    t->write_mem(prog_ptr, prog);\n\n    ret = remote.syscall(t->regs().original_syscallno(), t->regs().orig_arg1(),\n                         t->regs().arg2(), prog_ptr);\n  }\n  set_syscall_result(t, ret);\n\n  if (!t->regs().syscall_failed()) {\n    if (is_seccomp_syscall(t->regs().original_syscallno(), t->arch()) &&\n        (t->regs().arg2() & SECCOMP_FILTER_FLAG_TSYNC)) {\n      for (Task* tt : t->thread_group()->task_set()) {\n        static_cast<RecordTask*>(tt)->prctl_seccomp_status = 2;\n      }\n    } else {\n      t->prctl_seccomp_status = 2;\n    }\n  }\n}\n\nvoid SeccompFilterRewriter::install_patched_seccomp_filter(RecordTask* t) {\n  RR_ARCH_FUNCTION(install_patched_seccomp_filter_arch, t->arch(), t,\n                   result_to_index, index_to_result);\n}\n\nbool SeccompFilterRewriter::map_filter_data_to_real_result(RecordTask* t,\n                                                           uint16_t value,\n                                                           uint32_t* result) {\n  if (value < BASE_CUSTOM_DATA) {\n    return false;\n  }\n  ASSERT(t, value < BASE_CUSTOM_DATA + index_to_result.size());\n  *result = index_to_result[value - BASE_CUSTOM_DATA];\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/SeccompFilterRewriter.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_SECCOMP_FILTER_REWRITER_H_\n#define RR_SECCOMP_FILTER_REWRITER_H_\n\n#include <cstdint>\n#include <unordered_map>\n#include <vector>\n\n#include \"core.h\"\n\n/**\n * When seccomp decides not to execute a syscall the kernel returns to userspace\n * without modifying the registers. There is no negative return value to\n * indicate that whatever side effects the syscall would happen did not take\n * place. This is a problem for rr, because for syscalls that require special\n * handling, we'll be performing that handling even though the syscall didn't\n * actually happen.\n *\n * To get around this we can use the same mechanism that is used to skip the\n * syscall in the kernel to skip it ourselves: original_syscallno. We can't\n * use the traditional value of -1 though, because the kernel initializes\n * original_syscallno to -1 when delivering signals, and exiting sigreturn\n * will restore that. Not recording the side effects of sigreturn would be\n * bad. Instead we use -2, which still causes skipping the syscall when\n * given to the kernel as original_syscallno, but is never generated by the\n * kernel itself.\n */\n#define SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO -2\n\nnamespace rr {\n\nclass RecordTask;\n\n/**\n * Object to support install_patched_seccomp_filter.\n */\nclass SeccompFilterRewriter {\npublic:\n  /**\n   * Assuming |t| is set up for a prctl or seccomp syscall that\n   * installs a seccomp-bpf filter, patch the filter to signal the tracer\n   * instead of silently delivering an errno, and install it.\n   */\n  void install_patched_seccomp_filter(RecordTask* t);\n\n  /**\n   * Returns false if the input value is not valid. In this case a\n   * PTRACE_EVENT_EXIT probably got in the way.\n   */\n  bool map_filter_data_to_real_result(RecordTask* t, uint16_t value,\n                                      uint32_t* result);\n\n  /**\n   * Start numbering custom data values from here. This avoids overlapping\n   * values that might be returned from a PTRACE_EVENT_EXIT, so we can\n   * distinguish unexpected exits from real results of PTRACE_GETEVENTMSG.\n   */\n  enum { BASE_CUSTOM_DATA = 0x100 };\n\nprivate:\n  /**\n   * Seccomp filters can return 32-bit result values. We need to map all of\n   * them into a single 16 bit data field. Fortunately (so far) all the\n   * filters we've seen return constants, so there aren't too many distinct\n   * values we need to deal with. For each constant value that gets returned,\n   * we'll add it as the key in |result_map|, with the corresponding value\n   * being the 16-bit data value that our rewritten filter returns.\n   */\n  std::unordered_map<uint32_t, uint16_t> result_to_index;\n  std::vector<uint32_t> index_to_result;\n};\n\n} // namespace rr\n\n#endif // RR_SECCOMP_FILTER_REWRITER_H_\n"
  },
  {
    "path": "src/Session.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"Session.h\"\n\n#include <linux/limits.h>\n#include <linux/unistd.h>\n#include <syscall.h>\n#include <sys/wait.h>\n\n#include <algorithm>\n#include <limits>\n\n#include \"rr/rr.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"CPUs.h\"\n#include \"EmuFs.h\"\n#include \"Flags.h\"\n#include \"PerfCounters.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"Task.h\"\n#include \"ThreadGroup.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"util.h\"\n#include \"preload/preload_interface.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstruct Session::CloneCompletion {\n  struct AddressSpaceClone {\n    Task* clone_leader;\n    Task::CapturedState clone_leader_state;\n    vector<Task::CapturedState> member_states;\n    vector<pair<remote_ptr<void>, vector<uint8_t>>> captured_memory;\n  };\n  vector<AddressSpaceClone> address_spaces;\n  Task::ClonedFdTables cloned_fd_tables;\n};\n\nSession::Session()\n    : tracee_socket(make_shared<ScopedFd>()),\n      tracee_socket_receiver(make_shared<ScopedFd>()),\n      tracee_socket_fd_number(0),\n      next_task_serial_(1),\n      rrcall_base_(RR_CALL_BASE),\n      syscallbuf_fds_disabled_size_(SYSCALLBUF_FDS_DISABLED_SIZE),\n      syscallbuf_hdr_size_(sizeof(syscallbuf_hdr)),\n      syscall_seccomp_ordering_(PTRACE_SYSCALL_BEFORE_SECCOMP_UNKNOWN),\n      ticks_semantics_(PerfCounters::default_ticks_semantics()),\n      done_initial_exec_(false),\n      visible_execution_(true),\n      intel_pt_(false) {\n  LOG(debug) << \"Session \" << this << \" created\";\n}\n\nSession::~Session() {\n  kill_all_tasks();\n  LOG(debug) << \"Session \" << this << \" destroyed\";\n\n  for (auto tg : thread_group_map_) {\n    tg.second->forget_session();\n  }\n}\n\nSession::Session(const Session& other)\n    : statistics_(other.statistics_),\n      tracee_socket(other.tracee_socket),\n      tracee_socket_receiver(other.tracee_socket_receiver),\n      tracee_socket_fd_number(other.tracee_socket_fd_number),\n      next_task_serial_(other.next_task_serial_),\n      rrcall_base_(other.rrcall_base_),\n      syscallbuf_fds_disabled_size_(other.syscallbuf_fds_disabled_size_),\n      syscallbuf_hdr_size_(other.syscallbuf_hdr_size_),\n      syscall_seccomp_ordering_(other.syscall_seccomp_ordering_),\n      ticks_semantics_(other.ticks_semantics_),\n      done_initial_exec_(other.done_initial_exec_),\n      visible_execution_(other.visible_execution_),\n      intel_pt_(other.intel_pt_) {}\n\nvoid Session::on_create(ThreadGroup* tg) { thread_group_map_[tg->tguid()] = tg; }\nvoid Session::on_destroy(ThreadGroup* tg) {\n  thread_group_map_.erase(tg->tguid());\n}\n\nvoid Session::post_exec() {\n  /* We just saw a successful exec(), so from now on we know\n   * that the address space layout for the replay tasks will\n   * (should!) be the same as for the recorded tasks.  So we can\n   * start validating registers at events. */\n  assert_fully_initialized();\n  if (done_initial_exec_) {\n    return;\n  }\n  done_initial_exec_ = true;\n  DEBUG_ASSERT(tasks().size() == 1);\n  Task* t = tasks().begin()->second;\n  t->flush_inconsistent_state();\n  spawned_task_error_fd_.close();\n}\n\nAddressSpace::shr_ptr Session::create_vm(Task* t, const std::string& exe,\n                                         uint32_t exec_count) {\n  assert_fully_initialized();\n  AddressSpace::shr_ptr as(new AddressSpace(t, exe, exec_count));\n  as->insert_task(t);\n  vm_map[as->uid()] = as.get();\n  return as;\n}\n\nAddressSpace::shr_ptr Session::clone(Task* t, AddressSpace::shr_ptr vm) {\n  assert_fully_initialized();\n  // If vm already belongs to our session this is a fork, otherwise it's\n  // a session-clone\n  AddressSpace::shr_ptr as;\n  if (this == vm->session()) {\n    as = AddressSpace::shr_ptr(\n        new AddressSpace(this, *vm, t->rec_tid, t->tuid().serial(), 0));\n  } else {\n    as = AddressSpace::shr_ptr(new AddressSpace(this, *vm, vm->uid().tid(),\n                                                vm->uid().serial(),\n                                                vm->uid().exec_count()));\n  }\n  vm_map[as->uid()] = as.get();\n  return as;\n}\n\nThreadGroup::shr_ptr Session::create_initial_tg(Task* t) {\n  ThreadGroup::shr_ptr tg(\n      new ThreadGroup(this, nullptr, t->rec_tid, t->rec_tid,\n                      t->tuid().serial()));\n  tg->insert_task(t);\n  return tg;\n}\n\nThreadGroup::shr_ptr Session::clone(Task* t, ThreadGroup::shr_ptr tg) {\n  assert_fully_initialized();\n  // If tg already belongs to our session this is a fork to create a new\n  // taskgroup, otherwise it's a session-clone of an existing taskgroup\n  if (this == tg->session()) {\n    return ThreadGroup::shr_ptr(\n       new ThreadGroup(this, tg.get(), t->rec_tid,\n                       t->own_namespace_tid(), t->tuid().serial()));\n  }\n  ThreadGroup* parent =\n      tg->parent() ? find_thread_group(tg->parent()->tguid()) : nullptr;\n  return ThreadGroup::shr_ptr(\n      new ThreadGroup(this, parent, tg->tgid,\n                      t->own_namespace_tid(), tg->tguid().serial()));\n}\n\nTask* Session::new_task(pid_t tid, pid_t rec_tid, uint32_t serial,\n                        SupportedArch a, const std::string&) {\n  return new Task(*this, tid, rec_tid, serial, a);\n}\n\nvector<AddressSpace*> Session::vms() const {\n  vector<AddressSpace*> result;\n  for (auto& vm : vm_map) {\n    result.push_back(vm.second);\n  }\n  return result;\n}\n\nTask* Session::clone(Task* p, int flags, remote_ptr<void> stack,\n                     remote_ptr<void> tls, remote_ptr<int> cleartid_addr,\n                     pid_t new_tid, pid_t new_rec_tid) {\n  assert_fully_initialized();\n  Task* c = p->clone(Task::TRACEE_CLONE, flags, stack, tls, cleartid_addr,\n                     new_tid, new_rec_tid, next_task_serial());\n  on_create(c);\n  return c;\n}\n\nTask* Session::find_task(pid_t rec_tid) const {\n  finish_initializing();\n  auto it = tasks().find(rec_tid);\n  return tasks().end() != it ? it->second : nullptr;\n}\n\nTask* Session::find_task(const TaskUid& tuid) const {\n  Task* t = find_task(tuid.tid());\n  return t && t->tuid() == tuid ? t : nullptr;\n}\n\nThreadGroup* Session::find_thread_group(const ThreadGroupUid& tguid) const {\n  finish_initializing();\n  auto it = thread_group_map_.find(tguid);\n  if (thread_group_map_.end() == it) {\n    return nullptr;\n  }\n  return it->second;\n}\n\nThreadGroup* Session::find_thread_group(pid_t pid) const {\n  finish_initializing();\n  for (auto& tg : thread_group_map_) {\n    if (tg.first.tid() == pid) {\n      return tg.second;\n    }\n  }\n  return nullptr;\n}\n\nAddressSpace* Session::find_address_space(const AddressSpaceUid& vmuid) const {\n  finish_initializing();\n  auto it = vm_map.find(vmuid);\n  if (vm_map.end() == it) {\n    return nullptr;\n  }\n  return it->second;\n}\n\nvoid Session::kill_all_tasks() {\n  LOG(debug) << \"Killing all tasks ...\";\n  for (int pass = 0; pass <= 1; ++pass) {\n    /* We delete tasks in two passes. First, we kill\n     * every non-thread-group-leader, then we kill every group leader.\n     * Linux expects threads group leaders to survive until the last\n     * member of the thread group has exited, so we accommodate that.\n     */\n    for (auto& v : task_map) {\n      Task* t = v.second;\n      bool is_group_leader = t->tid == t->real_tgid();\n      if (pass == 0 ? is_group_leader : !is_group_leader) {\n        continue;\n      }\n      t->kill();\n    }\n  }\n  while (!task_map.empty()) {\n    Task* t = task_map.rbegin()->second;\n    delete t;\n  }\n  assert(task_map.empty());\n}\n\nvoid Session::on_destroy(AddressSpace* vm) {\n  DEBUG_ASSERT(vm->task_set().size() == 0);\n  DEBUG_ASSERT(vm_map.count(vm->uid()) == 1);\n  vm_map.erase(vm->uid());\n}\n\nvoid Session::on_destroy(Task* t) {\n  DEBUG_ASSERT(task_map.count(t->rec_tid) == 1);\n  task_map.erase(t->rec_tid);\n}\n\nvoid Session::on_create(Task* t) { task_map[t->rec_tid] = t; }\n\nScopedFd Session::create_spawn_task_error_pipe() {\n  int fds[2];\n  if (0 != pipe2(fds, O_CLOEXEC)) {\n    FATAL();\n  }\n  spawned_task_error_fd_ = ScopedFd(fds[0]);\n  return ScopedFd(fds[1]);\n}\n\nstring Session::read_spawned_task_error() const {\n  char buf[1024] = \"\";\n  ssize_t len = read(spawned_task_error_fd_, buf, sizeof(buf));\n  if (len <= 0) {\n    return string();\n  }\n  buf[len] = 0;\n  return string(buf, len);\n}\n\nBreakStatus Session::diagnose_debugger_trap(Task* t, RunCommand run_command) {\n  assert_fully_initialized();\n  BreakStatus break_status;\n  break_status.task_context = TaskContext(t);\n\n  int stop_sig = t->stop_sig();\n  if (!stop_sig) {\n    // This can happen if we were INCOMPLETE because we're close to\n    // the ticks_target.\n    return break_status;\n  }\n\n  if (SIGTRAP != stop_sig) {\n    BreakpointType pending_bp = t->vm()->get_breakpoint_type_at_addr(t->ip());\n    if (BKPT_USER == pending_bp) {\n      // A signal was raised /just/ before a trap\n      // instruction for a SW breakpoint.  This is\n      // observed when debuggers write trap\n      // instructions into no-exec memory, for\n      // example the stack.\n      //\n      // We report the breakpoint before any signal\n      // that might have been raised in order to let\n      // the debugger do something at the breakpoint\n      // insn; possibly clearing the breakpoint and\n      // changing the $ip.  Otherwise, we expect the\n      // debugger to clear the breakpoint and resume\n      // execution, which should raise the original\n      // signal again.\n      LOG(debug) << \"hit debugger breakpoint BEFORE ip \" << t->ip() << \" for \"\n                 << t->get_siginfo();\n      break_status.breakpoint_hit = true;\n    } else if (stop_sig && stop_sig != PerfCounters::TIME_SLICE_SIGNAL) {\n      break_status.signal =\n          unique_ptr<siginfo_t>(new siginfo_t(t->get_siginfo()));\n      LOG(debug) << \"Got signal \" << *break_status.signal << \" (expected sig \"\n                 << stop_sig << \")\";\n      break_status.signal->si_signo = stop_sig;\n    }\n  } else {\n    TrapReasons trap_reasons = t->compute_trap_reasons();\n\n    // Conceal any internal singlestepping\n    if (trap_reasons.singlestep && is_singlestep(run_command)) {\n      LOG(debug) << \"  finished debugger stepi\";\n      break_status.singlestep_complete = true;\n    }\n\n    if (trap_reasons.watchpoint) {\n      check_for_watchpoint_changes(t, break_status);\n    }\n\n    if (trap_reasons.breakpoint) {\n      BreakpointType retired_bp =\n          t->vm()->get_breakpoint_type_for_retired_insn(t->ip());\n      if (BKPT_USER == retired_bp) {\n        // SW breakpoint: $ip is just past the\n        // breakpoint instruction.  Move $ip back\n        // right before it.\n        t->move_ip_before_breakpoint();\n        break_status.breakpoint_hit = true;\n        LOG(debug) << \"hit debugger breakpoint at ip \" << t->ip();\n      }\n    }\n  }\n\n  return break_status;\n}\n\nvoid Session::check_for_watchpoint_changes(Task* t, BreakStatus& break_status) {\n  assert_fully_initialized();\n  break_status.watchpoints_hit = t->vm()->consume_watchpoint_changes();\n}\n\nvoid Session::assert_fully_initialized() const {\n  DEBUG_ASSERT(!clone_completion && \"Session not fully initialized\");\n}\n\nvoid Session::finish_initializing() const {\n  if (!clone_completion) {\n    return;\n  }\n\n  Session* self = const_cast<Session*>(this);\n  for (auto& asleader : clone_completion->address_spaces) {\n    {\n      AutoRemoteSyscalls remote(asleader.clone_leader);\n      for (const auto& m : asleader.clone_leader->vm()->maps()) {\n        // Creating this mapping was delayed in capture_state for performance\n        if (m.flags & AddressSpace::Mapping::IS_SYSCALLBUF) {\n          self->recreate_shared_mmap(remote, m);\n        }\n      }\n      for (auto& mem : asleader.captured_memory) {\n        asleader.clone_leader->write_bytes_helper(mem.first, mem.second.size(),\n                                                  mem.second.data());\n      }\n      for (auto& asmember : asleader.member_states) {\n        auto it = thread_group_map_.find(asmember.tguid);\n        ThreadGroup::shr_ptr tg(it == thread_group_map_.end() ? nullptr :\n          it->second->shared_from_this());\n        if (!tg) {\n          tg = std::make_shared<ThreadGroup>\n            (self, nullptr, asmember.tguid.tid(), asmember.tguid.tid(), asmember.tguid.serial());\n        }\n        Task* t_clone = Task::os_clone_into(\n            asmember, remote, clone_completion->cloned_fd_tables, tg);\n        self->on_create(t_clone);\n        t_clone->copy_state(asmember);\n      }\n    }\n    asleader.clone_leader->copy_state(asleader.clone_leader_state);\n  }\n\n  self->clone_completion = nullptr;\n}\n\nstatic void remap_shared_mmap(AutoRemoteSyscalls& remote, EmuFs& emu_fs,\n                              EmuFs& dest_emu_fs,\n                              const AddressSpace::Mapping& m_in_mem) {\n  AddressSpace::Mapping m = m_in_mem;\n\n  LOG(debug) << \"    remapping shared region at \" << m.map.start() << \"-\"\n             << m.map.end();\n  remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                            m.map.start(), m.map.size());\n\n  EmuFile::shr_ptr emu_file;\n  if (dest_emu_fs.has_file_for(m.recorded_map)) {\n    emu_file = dest_emu_fs.at(m.recorded_map);\n  } else {\n    emu_file = dest_emu_fs.clone_file(emu_fs.at(m.recorded_map));\n  }\n\n  // TODO: this duplicates some code in replay_syscall.cc, but\n  // it's somewhat nontrivial to factor that code out.\n  int remote_fd = remote.infallible_send_fd_if_alive(emu_file->fd());\n  if (remote_fd < 0) {\n    if (remote.task()->vm()->task_set().size() > remote.task()->thread_group()->task_set().size()) {\n      // XXX not sure how to handle the case where the tracee died after\n      // we unmapped the area\n      FATAL() << \"Unexpected task death leaving this address space in a bad state\";\n    }\n    return;\n  }\n  struct stat real_file = remote.task()->stat_fd(remote_fd);\n  string real_file_name = remote.task()->file_name_of_fd(remote_fd);\n  // XXX this condition is x86/x64-specific, I imagine.\n  // The remapped segment *must* be remapped at the same address,\n  // or else many things will go haywire.\n  auto ret = remote.infallible_mmap_syscall_if_alive(m.map.start(), m.map.size(), m.map.prot(),\n                                                     (m.map.flags() & ~MAP_ANONYMOUS) | MAP_FIXED,\n                                                     remote_fd,\n                                                     m.map.file_offset_bytes());\n  if (!ret) {\n    if (remote.task()->vm()->task_set().size() > remote.task()->thread_group()->task_set().size()) {\n      // XXX not sure how to handle the case where the tracee died after\n      // we unmapped the area\n      FATAL() << \"Unexpected task death leaving this address space in a bad state\";\n    }\n    return;\n  }\n\n  // We update the AddressSpace mapping too, since that tracks the real file\n  // name and we need to update that.\n  remote.task()->vm()->map(\n      remote.task(), m.map.start(), m.map.size(), m.map.prot(), m.map.flags(),\n      m.map.file_offset_bytes(), real_file_name, real_file.st_dev,\n      real_file.st_ino, nullptr, &m.recorded_map, emu_file);\n\n  remote.infallible_close_syscall_if_alive(remote_fd);\n}\n\n/*static*/ const char* Session::rr_mapping_prefix() { return \"/rr-shared-\"; }\n\nKernelMapping Session::create_shared_mmap(\n    AutoRemoteSyscalls& remote, size_t size, remote_ptr<void> required_child_addr,\n    const char* name, int tracee_prot, int tracee_flags,\n    MonitoredSharedMemory::shr_ptr monitored) {\n  Task* t = remote.task();\n  static int nonce = 0;\n  // Create the segment we'll share with the tracee.\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"%s%s%s-%d-%d\", tmp_dir(),\n           rr_mapping_prefix(), name, t->real_tgid(), nonce++);\n\n  ScopedFd shmem_fd(path, O_CREAT | O_EXCL | O_RDWR);\n  ASSERT(t, shmem_fd.is_open());\n  /* Remove the fs name so that we don't have to worry about\n   * cleaning up this segment in error conditions. */\n  unlink(path);\n\n  void* map_addr = mmap(nullptr, size, PROT_READ | PROT_WRITE,\n                        MAP_SHARED, shmem_fd, 0);\n  if (map_addr == MAP_FAILED) {\n    FATAL() << \"Failed to mmap shmem region\";\n  }\n  resize_shmem_segment(shmem_fd, size);\n\n  remote_ptr<void> child_map_addr = required_child_addr;\n  if (child_map_addr.is_null()) {\n    if (t->session().is_recording() &&\n        static_cast<RecordTask*>(t)->enable_chaos_memory_allocations()) {\n      child_map_addr = t->vm()->chaos_mode_find_free_memory(static_cast<RecordTask*>(t),\n          size, nullptr);\n    } else {\n      child_map_addr = t->vm()->find_free_memory(t, size, RR_PAGE_ADDR,\n          AddressSpace::FindFreeMemoryPolicy::USE_LAST_FREE_HINT);\n      if (!child_map_addr) {\n        FATAL() << \"Can't find free memory for shared mmap\";\n      }\n    }\n  }\n\n  struct stat st;\n  ASSERT(t, 0 == ::fstat(shmem_fd, &st));\n  int flags = MAP_SHARED;\n  if (!required_child_addr.is_null()) {\n    flags |= MAP_FIXED;\n  }\n\n  int child_shmem_fd = remote.infallible_send_fd_if_alive(shmem_fd);\n  if (child_shmem_fd < 0) {\n    return KernelMapping();\n  }\n  LOG(debug) << \"created shmem segment \" << path;\n\n  // Map the segment in ours and the tracee's address spaces.\n  remote_ptr<void> addr = remote.infallible_mmap_syscall_if_alive(\n      child_map_addr, size, tracee_prot, flags | MAP_FIXED, child_shmem_fd, 0);\n  if (!addr) {\n    // tracee unexpectedly died.\n    // We leak the fd; cleaning it up is probably impossible/unnecessary.\n    return KernelMapping();\n  }\n\n  // Note the mapping after we successfully created it in the child.\n  // If the child mapping fails for some reason (e.g. SIGKILL) we still\n  // want our cache to be correct (and not contain the mapping).\n  KernelMapping km = t->vm()->map(\n      t, child_map_addr, size, tracee_prot, flags | tracee_flags, 0,\n      path, st.st_dev, st.st_ino, nullptr, nullptr, nullptr, map_addr,\n      std::move(monitored));\n\n  remote.infallible_close_syscall_if_alive(child_shmem_fd);\n  return km;\n}\n\nstatic char* extract_name(char* name_buffer, size_t buffer_size) {\n  // Recover the name that was originally chosen by finding the part of the\n  // name between rr_mapping_prefix and the -%d-%d at the end.\n  char* path_start = strstr(name_buffer, Session::rr_mapping_prefix());\n  DEBUG_ASSERT(path_start &&\n               \"Passed something to create_shared_mmap that\"\n               \" wasn't a mapping shared between rr and the tracee?\");\n  size_t prefix_len = path_start - name_buffer;\n  buffer_size -= prefix_len;\n  name_buffer += prefix_len;\n\n  char* name_end = name_buffer + strnlen(name_buffer, buffer_size);\n  char* name_start = name_buffer + strlen(Session::rr_mapping_prefix());\n  int hyphens_seen = 0;\n  while (name_end > name_start) {\n    --name_end;\n    if (*name_end == '-') {\n      ++hyphens_seen;\n    } else if (*name_end == '/') {\n      DEBUG_ASSERT(false &&\n                   \"Passed something to create_shared_mmap that\"\n                   \" wasn't a mapping shared between rr and the tracee?\");\n    }\n    if (hyphens_seen == 2) {\n      break;\n    }\n  }\n  DEBUG_ASSERT(hyphens_seen == 2);\n  *name_end = '\\0';\n  return name_start;\n}\n\nconst AddressSpace::Mapping Session::recreate_shared_mmap(\n    AutoRemoteSyscalls& remote, const AddressSpace::Mapping& m,\n    PreserveContents preserve, MonitoredSharedMemory::shr_ptr monitored) {\n  char name[PATH_MAX];\n  strncpy(name, m.map.fsname().c_str(), sizeof(name) - 1);\n  name[sizeof(name) - 1] = 0;\n  uint32_t flags = m.flags;\n  size_t size = m.map.size();\n  void* preserved_data = preserve == PRESERVE_CONTENTS ? m.local_addr : nullptr;\n  void* remote_task_local_mapping = nullptr;\n\n  {\n    // Note that Mapping `m` may correspond to a Mapping from a different Task\n    // than the `maybe_detach_mapping`. See replay_syscall.cc prepare_clone()\n    // for an example.\n    auto remote_task_mapping = remote.task()->vm()->mapping_of(m.map.start());\n\n    // Sanity check\n    ASSERT(remote.task(), size == remote_task_mapping.map.size());\n    ASSERT(remote.task(), m.map.start() == remote_task_mapping.map.start());\n\n    remote_task_local_mapping =\n        remote.task()->vm()->detach_local_mapping(m.map.start());\n  }\n\n  remote_ptr<void> new_addr =\n      create_shared_mmap(remote, m.map.size(), m.map.start(),\n                         extract_name(name, sizeof(name)), m.map.prot(), 0,\n                         std::move(monitored))\n          .start();\n  AddressSpace::Mapping new_map;\n  if (new_addr) {\n    // m may be invalid now\n    remote.task()->vm()->mapping_flags_of(new_addr) = flags;\n    new_map = remote.task()->vm()->mapping_of(new_addr);\n    if (preserved_data) {\n      memcpy(new_map.local_addr, preserved_data, size);\n    }\n  }\n  if (remote_task_local_mapping) {\n    munmap(remote_task_local_mapping, size);\n  }\n  return new_map;\n}\n\nAddressSpace::Mapping Session::steal_mapping(\n    AutoRemoteSyscalls& remote, const AddressSpace::Mapping& m,\n    MonitoredSharedMemory::shr_ptr monitored) {\n  // We will include the name of the full path of the original mapping in the\n  // name of the shared mapping, replacing slashes by dashes.\n  char name[PATH_MAX - 40];\n  strncpy(name, m.map.fsname().c_str(), sizeof(name)-1);\n  name[sizeof(name) - 1] = '\\0';\n  for (char* ptr = name; *ptr != '\\0'; ++ptr) {\n    if (*ptr == '/') {\n      *ptr = '-';\n    }\n  }\n\n  // Now create the new mapping in its place\n  remote_ptr<void> start = m.map.start();\n  size_t sz = m.map.size();\n  const AddressSpace::Mapping& new_m = remote.task()->vm()->mapping_of(\n      create_shared_mmap(remote, sz, start, name, m.map.prot(),\n                         m.map.flags() & (MAP_GROWSDOWN | MAP_STACK),\n                         std::move(monitored))\n          .start());\n  return new_m;\n}\n\n// Replace a MAP_PRIVATE segment by one that is shared between rr and the\n// tracee.\nvoid Session::make_private_shared(AutoRemoteSyscalls& remote,\n                                  const AddressSpace::Mapping m) {\n  if (!(m.map.flags() & MAP_PRIVATE)) {\n    return;\n  }\n  // Find a place to map the current segment to temporarily\n  remote_ptr<void> start = m.map.start();\n  size_t sz = m.map.size();\n  remote_ptr<void> free_mem = remote.task()->vm()->find_free_memory(remote.task(), sz);\n  remote.infallible_syscall(syscall_number_for_mremap(remote.arch()), start, sz,\n                            sz, MREMAP_MAYMOVE | MREMAP_FIXED, free_mem);\n  remote.task()->vm()->remap(remote.task(), start, sz, free_mem, sz,\n                             MREMAP_MAYMOVE | MREMAP_FIXED);\n\n  // AutoRemoteSyscalls may have gotten unlucky and picked the old stack\n  // segment as it's scratch space, reevaluate that choice\n  AutoRemoteSyscalls remote2(remote.task());\n\n  AddressSpace::Mapping new_m = steal_mapping(remote2, m);\n\n  if (!new_m.local_addr) {\n    return;\n  }\n  // And copy over the contents. Since we can't just call memcpy in the\n  // inferior, just copy directly from the remote private into the local\n  // reference of the shared mapping. We use the fallible read method to\n  // handle the case where the mapping is larger than the backing file, which\n  // would otherwise cause a short read.\n  remote2.task()->read_bytes_fallible(free_mem, sz, new_m.local_addr);\n\n  // Finally unmap the original segment\n  remote2.infallible_syscall(syscall_number_for_munmap(remote.arch()), free_mem,\n                             sz);\n  remote.task()->vm()->unmap(remote.task(), free_mem, sz);\n}\n\nstatic vector<uint8_t> capture_syscallbuf(const AddressSpace::Mapping& m,\n                                          Task* clone_leader) {\n  remote_ptr<uint8_t> start = m.map.start().cast<uint8_t>();\n  auto syscallbuf_hdr = start.cast<struct syscallbuf_hdr>();\n  size_t data_size;\n  if (clone_leader->read_mem(REMOTE_PTR_FIELD(syscallbuf_hdr, locked))) {\n    // There may be an incomplete syscall record after num_rec_bytes that\n    // we need to capture here. We don't know how big that record is,\n    // so just record the entire buffer. This should not be common.\n    data_size = m.map.size();\n  } else {\n    data_size = clone_leader->read_mem(REMOTE_PTR_FIELD(syscallbuf_hdr, num_rec_bytes)) +\n        clone_leader->session().syscallbuf_hdr_size();\n  }\n  return clone_leader->read_mem(start, data_size);\n}\n\nstatic FdTable::shr_ptr& get_or_clone_fd_table(\n    Task::ClonedFdTables& existing_clones, Task* task_to_clone) {\n  auto original_fd_table = task_to_clone->fd_table();\n  FdTable::shr_ptr& existing_clone =\n      existing_clones[uintptr_t(original_fd_table.get())];\n  if (!existing_clone) {\n    existing_clone = original_fd_table->clone();\n  }\n  return existing_clone;\n}\n\nvoid Session::copy_state_to(Session& dest, EmuFs& emu_fs, EmuFs& dest_emu_fs) {\n  assert_fully_initialized();\n  DEBUG_ASSERT(!dest.clone_completion);\n\n  auto completion = unique_ptr<CloneCompletion>(new CloneCompletion());\n  auto& cloned_fd_tables = completion->cloned_fd_tables;\n\n  for (auto vm : vm_map) {\n    // Pick an arbitrary task to be group leader. The actual group leader\n    // might have died already.\n    Task* group_leader = *vm.second->task_set().begin();\n    LOG(debug) << \"  forking tg \" << group_leader->tgid()\n               << \" (real: \" << group_leader->real_tgid() << \")\";\n\n    completion->address_spaces.push_back(CloneCompletion::AddressSpaceClone());\n    auto& group = completion->address_spaces.back();\n\n    group.clone_leader = group_leader->os_fork_into(\n        &dest, get_or_clone_fd_table(cloned_fd_tables, group_leader));\n    dest.on_create(group.clone_leader);\n    LOG(debug) << \"  forked new group leader \" << group.clone_leader->tid;\n\n    {\n      AutoRemoteSyscalls remote(group.clone_leader);\n      vector<AddressSpace::Mapping> shared_maps_to_clone;\n      for (const auto& m : group.clone_leader->vm()->maps()) {\n        // Special case the syscallbuf as a performance optimization. The amount\n        // of data we need to capture is usually significantly smaller than the\n        // size of the mapping, so allocating the whole mapping here would be\n        // wasteful.\n        if (m.flags & AddressSpace::Mapping::IS_SYSCALLBUF) {\n          group.captured_memory.push_back(make_pair(\n              m.map.start(), capture_syscallbuf(m, group.clone_leader)));\n        } else if (m.local_addr != nullptr) {\n          ASSERT(group.clone_leader,\n                 m.map.start() == AddressSpace::preload_thread_locals_start());\n        } else if ((m.recorded_map.flags() & MAP_SHARED) &&\n                   emu_fs.has_file_for(m.recorded_map)) {\n          shared_maps_to_clone.push_back(m);\n        }\n      }\n      // Do this in a separate loop to avoid iteration invalidation issues\n      for (const auto& m : shared_maps_to_clone) {\n        remap_shared_mmap(remote, emu_fs, dest_emu_fs, m);\n      }\n\n      for (auto t : vm.second->task_set()) {\n        if (group_leader == t) {\n          continue;\n        }\n        LOG(debug) << \"    cloning \" << t->rec_tid;\n\n        get_or_clone_fd_table(cloned_fd_tables, t);\n        group.member_states.push_back(t->capture_state());\n      }\n    }\n\n    group.clone_leader_state = group_leader->capture_state();\n  }\n  dest.clone_completion = std::move(completion);\n\n  DEBUG_ASSERT(dest.vms().size() > 0);\n}\n\nbool Session::has_cpuid_faulting() {\n  return !Flags::get().disable_cpuid_faulting && cpuid_faulting_works();\n}\n\nBindCPU Session::cpu_binding() const {\n  int binding = const_cast<Session*>(this)->trace_stream()->bound_to_cpu();\n  if (binding < 0) {\n    return BindCPU(BindCPU::UNBOUND);\n  }\n  return BindCPU(binding);\n}\n\nvoid Session::do_bind_cpu() {\n  if (intel_pt_) {\n    PerfCounters::start_pt_copy_thread();\n  }\n\n  // Ensure initial affinity is initialized.\n  const CPUs& cpus = CPUs::get();\n  BindCPU binding = this->cpu_binding();\n  if (binding.mode == BindCPU::SPECIFIED_CORE) {\n    // Set CPU affinity now, after we've created any helper threads\n    // (so they aren't affected), but before we create any\n    // tracees (so they are all affected).\n    // Note that we're binding rr itself to the same CPU as the\n    // tracees, since this seems to help performance.\n    if (!cpus.set_affinity_to_cpu(binding.specified_core)) {\n      if (has_cpuid_faulting() && !is_recording()) {\n        // We can replay on any CPU.\n        int cpu_index = choose_cpu(BindCPU(BindCPU::ANY), cpu_lock);\n        if (!cpus.set_affinity_to_cpu(cpu_index)) {\n          FATAL() << \"Can't bind to requested CPU \" << cpu_index\n                  << \" even after we re-selected it\";\n        }\n        LOG(warn) << \"Bound to CPU \" << cpu_index\n                  << \"instead of selected \" << trace_stream()->bound_to_cpu()\n                  << \"because the latter is not available;\\n\"\n                  << \"Hoping tracee doesn't use LSL instruction!\";\n        trace_stream()->set_bound_cpu(cpu_index);\n      } else {\n        FATAL() << \"Can't bind to requested CPU \" << binding.specified_core\n                << \", and CPUID faulting not available\";\n      }\n    } else if (!is_recording()) {\n      // Make sure to mark this CPU as in use in the cpu_lock.\n      (void)choose_cpu(binding, cpu_lock);\n    }\n  }\n}\n\nbool Session::mark_stdio() const {\n  return visible_execution_ && Flags::get().mark_stdio;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/Session.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_SESSION_H_\n#define RR_SESSION_H_\n\n#include <cassert>\n#include <map>\n#include <memory>\n#include <set>\n#include <string>\n#include <vector>\n\n#include \"AddressSpace.h\"\n#include \"CPUs.h\"\n#include \"MonitoredSharedMemory.h\"\n#include \"Task.h\"\n#include \"TaskishUid.h\"\n#include \"TraceStream.h\"\n#include \"preload/preload_interface.h\"\n\nnamespace rr {\n\nclass AddressSpace;\nclass DiversionSession;\nclass EmuFs;\nclass RecordSession;\nclass ReplaySession;\nclass ReplayTask;\nclass Task;\nclass ThreadGroup;\nclass AutoRemoteSyscalls;\n\n// The following types are used by step() APIs in Session subclasses.\n\n/**\n * Stores a Task and information about it separately so decisions can\n * still be made from a Task's context even if it dies.\n */\nstruct TaskContext {\n  TaskContext()\n      : task(nullptr),\n        session(nullptr),\n        thread_group(nullptr) {}\n  explicit TaskContext(Task* task)\n      : task(task),\n        session(task ? &task->session() : nullptr),\n        thread_group(task ? task->thread_group() : nullptr) {}\n  TaskContext(Session* session, std::shared_ptr<ThreadGroup> thread_group)\n      : task(nullptr),\n        session(session),\n        thread_group(thread_group) {}\n\n  // A pointer to a task. This may be |nullptr|. When non-NULL, this\n  // is not necessarily the same as session->current_task() (for\n  // example, when replay switches to a new task after\n  // ReplaySession::replay_step()).\n  Task* task;\n  // The session to which |task| belongs/belonged.\n  Session* session;\n  // The thread group to which |task| belongs/belonged.\n  std::shared_ptr<ThreadGroup> thread_group;\n};\n\n/**\n * In general, multiple break reasons can apply simultaneously.\n */\nstruct BreakStatus {\n  BreakStatus()\n      : task_context(TaskContext()),\n        breakpoint_hit(false),\n        singlestep_complete(false),\n        approaching_ticks_target(false),\n        task_exit(false) {}\n  BreakStatus(const BreakStatus& other)\n      : task_context(other.task_context),\n        watchpoints_hit(other.watchpoints_hit),\n        signal(other.signal\n                   ? std::unique_ptr<siginfo_t>(new siginfo_t(*other.signal))\n                   : nullptr),\n        breakpoint_hit(other.breakpoint_hit),\n        singlestep_complete(other.singlestep_complete),\n        approaching_ticks_target(other.approaching_ticks_target),\n        task_exit(other.task_exit) {}\n  const BreakStatus& operator=(const BreakStatus& other) {\n    task_context = other.task_context;\n    watchpoints_hit = other.watchpoints_hit;\n    signal = other.signal\n                 ? std::unique_ptr<siginfo_t>(new siginfo_t(*other.signal))\n                 : nullptr;\n    breakpoint_hit = other.breakpoint_hit;\n    singlestep_complete = other.singlestep_complete;\n    approaching_ticks_target = other.approaching_ticks_target;\n    task_exit = other.task_exit;\n    return *this;\n  }\n\n  // The triggering TaskContext.\n  TaskContext task_context;\n  // List of watchpoints hit; any watchpoint hit causes a stop after the\n  // instruction that triggered the watchpoint has completed.\n  std::vector<WatchConfig> watchpoints_hit;\n  // When non-null, we stopped because a signal was delivered to |task|.\n  std::unique_ptr<siginfo_t> signal;\n  // True when we stopped because we hit a software breakpoint at |task|'s\n  // current ip().\n  bool breakpoint_hit;\n  // True when we stopped because a singlestep completed in |task|.\n  bool singlestep_complete;\n  // True when we stopped because we got too close to the specified ticks\n  // target.\n  bool approaching_ticks_target;\n  // True when we stopped because |task| is about to exit.\n  bool task_exit;\n\n  // True when we stopped because we hit a software or hardware breakpoint at\n  // |task|'s current ip().\n  bool hardware_or_software_breakpoint_hit() {\n    for (const auto& w : watchpoints_hit) {\n      // Hardware execution watchpoints behave like breakpoints: the CPU\n      // stops before the instruction is executed.\n      if (w.type == WATCH_EXEC) {\n        return true;\n      }\n    }\n    return breakpoint_hit;\n  }\n  // Returns just the data watchpoints hit.\n  std::vector<WatchConfig> data_watchpoints_hit() {\n    std::vector<WatchConfig> result;\n    for (const auto& w : watchpoints_hit) {\n      if (w.type != WATCH_EXEC) {\n        result.push_back(w);\n      }\n    }\n    return result;\n  }\n\n  bool any_break() const {\n    return !watchpoints_hit.empty() || signal || breakpoint_hit ||\n           singlestep_complete || approaching_ticks_target;\n  }\n\n  Task* task() const { return task_context.task; }\n};\nenum RunCommand {\n  // Continue until we hit a breakpoint or a new replay event\n  RUN_CONTINUE,\n  // Execute a single instruction (unless at a breakpoint or a replay event)\n  RUN_SINGLESTEP,\n  // Like RUN_SINGLESTEP, but a single-instruction loop is allowed (but not\n  // required) to execute multiple times if we don't reach a different\n  // instruction. Usable with ReplaySession::replay_step only.\n  RUN_SINGLESTEP_FAST_FORWARD\n};\n\ninline bool is_singlestep(RunCommand command) {\n  return command == RUN_SINGLESTEP || command == RUN_SINGLESTEP_FAST_FORWARD;\n}\n\n/**\n * Sessions track the global state of a set of tracees corresponding\n * to an rr recorder or replayer.  During recording, the tracked\n * tracees will all write to the same TraceWriter, and during\n * replay, the tracees that will be tracked will all be created based\n * on the same TraceReader.\n *\n * Multiple sessions can coexist in the same process.  This\n * is required when using replay checkpoints, for example.\n */\nclass Session {\n  friend class ReplaySession;\n\npublic:\n  // AddressSpaces and ThreadGroups are indexed by their first task's TaskUid\n  // (effectively), so that if the first task dies and its tid is recycled,\n  // we don't get confused. TaskMap is indexed by tid since there can never be\n  // two Tasks with the same tid at the same time.\n  typedef std::map<AddressSpaceUid, AddressSpace*> AddressSpaceMap;\n  typedef std::map<pid_t, Task*> TaskMap;\n  typedef std::map<ThreadGroupUid, ThreadGroup*> ThreadGroupMap;\n\n  /**\n   * Call |post_exec()| immediately after a tracee has successfully\n   * |execve()|'d.  After that, |done_initial_exec()| returns true.\n   * This is called while we're still in the execve syscall so it's not safe\n   * to perform remote syscalls in this method.\n   *\n   * Tracee state can't be validated before the first exec,\n   * because the address space inside the rr process for |rr\n   * replay| will be different than it was for |rr record|.\n   * After the first exec, we're running tracee code, and\n   * everything must be the same.\n   */\n  void post_exec();\n\n  /**\n   * Returns true after the tracee has done the initial exec in Task::spawn.\n   * Before then, tracee state can be inconsistent; from the exec exit-event\n   * onwards, the tracee state much be consistent.\n   */\n  bool done_initial_exec() const { return done_initial_exec_; }\n\n  /**\n   * Create and return a new address space that's constructed\n   * from |t|'s actual OS address space. When spawning, |exe| is the empty\n   * string; it will be replaced during the first execve(), when we first\n   * start running real tracee code.\n   */\n  std::shared_ptr<AddressSpace> create_vm(\n      Task* t, const std::string& exe = std::string(), uint32_t exec_count = 0);\n  /**\n   * Return a copy of |vm| with the same mappings.  If any\n   * mapping is changed, only the |clone()|d copy is updated,\n   * not its origin (i.e. copy-on-write semantics).\n   */\n  std::shared_ptr<AddressSpace> clone(Task* t,\n                                      std::shared_ptr<AddressSpace> vm);\n  /**\n   * Create the initial thread group.\n   */\n  std::shared_ptr<ThreadGroup> create_initial_tg(Task* t);\n  /**\n   * Return a copy of |tg| with the same mappings.\n   */\n  std::shared_ptr<ThreadGroup> clone(Task* t, std::shared_ptr<ThreadGroup> tg);\n\n  /** See Task::clone(). */\n  Task* clone(Task* p, int flags, remote_ptr<void> stack, remote_ptr<void> tls,\n              remote_ptr<int> cleartid_addr, pid_t new_tid,\n              pid_t new_rec_tid = -1);\n\n  uint32_t next_task_serial() { return next_task_serial_++; }\n\n  /**\n   * Return the task created with |rec_tid|, or nullptr if no such\n   * task exists.\n   */\n  Task* find_task(pid_t rec_tid) const;\n\n  Task* find_task(const TaskUid& tuid) const;\n\n  /**\n   * Return the thread group whose unique ID is |tguid|, or nullptr if no such\n   * thread group exists.\n   */\n  ThreadGroup* find_thread_group(const ThreadGroupUid& tguid) const;\n\n  /**\n   * Find the thread group for a specific pid\n   */\n  ThreadGroup* find_thread_group(pid_t pid) const;\n\n  /**\n   * Return the AddressSpace whose unique ID is |vmuid|, or nullptr if no such\n   * address space exists.\n   */\n  AddressSpace* find_address_space(const AddressSpaceUid& vmuid) const;\n\n  /**\n   * |tasks().size()| will be zero and all the OS tasks will be\n   * gone when this returns, or this won't return.\n   */\n  void kill_all_tasks();\n\n  /**\n   * Call these functions from the objects' destructors in order\n   * to notify this session that the objects are dying.\n   */\n  void on_destroy(AddressSpace* vm);\n  void on_destroy(Task* t);\n  void on_create(ThreadGroup* tg);\n  void on_destroy(ThreadGroup* tg);\n\n  /** Return the set of Tasks being traced in this session. */\n  const TaskMap& tasks() const {\n    finish_initializing();\n    return task_map;\n  }\n\n  /**\n   * Return the set of AddressSpaces being tracked in this session.\n   */\n  std::vector<AddressSpace*> vms() const;\n\n  virtual RecordSession* as_record() { return nullptr; }\n  virtual ReplaySession* as_replay() { return nullptr; }\n  virtual DiversionSession* as_diversion() { return nullptr; }\n\n  bool is_recording() { return as_record() != nullptr; }\n  bool is_replaying() { return as_replay() != nullptr; }\n  bool is_diversion() { return as_diversion() != nullptr; }\n\n  // Indicate if execution should be \"visible\", i.e. it's the main\n  // session of a recording or a replay whose output could be echoed.\n  void set_visible_execution(bool visible) { visible_execution_ = visible; }\n\n  virtual bool need_performance_counters() const { return true; }\n\n  struct Statistics {\n    Statistics()\n        : bytes_written(0), ticks_processed(0), syscalls_performed(0) {}\n    uint64_t bytes_written;\n    Ticks ticks_processed;\n    uint32_t syscalls_performed;\n  };\n  void accumulate_bytes_written(uint64_t bytes_written) {\n    statistics_.bytes_written += bytes_written;\n  }\n  void accumulate_syscall_performed() { statistics_.syscalls_performed += 1; }\n  void accumulate_ticks_processed(Ticks ticks) {\n    statistics_.ticks_processed += ticks;\n  }\n  Statistics statistics() { return statistics_; }\n\n  virtual Task* new_task(pid_t tid, pid_t rec_tid, uint32_t serial,\n                         SupportedArch a, const std::string& name);\n\n  std::string read_spawned_task_error() const;\n\n  /* Returns an empty mapping if the tracee died.\n   * If map_address is non-null then we must use that address in the tracee,\n   * otherwise we select the address.\n   */\n  static KernelMapping create_shared_mmap(\n      AutoRemoteSyscalls& remote, size_t size, remote_ptr<void> required_child_addr,\n      const char* name, int tracee_prot = PROT_READ | PROT_WRITE,\n      int tracee_flags = 0,\n      MonitoredSharedMemory::shr_ptr monitored = nullptr);\n\n  static void make_private_shared(AutoRemoteSyscalls& remote,\n                                  const AddressSpace::Mapping m);\n  enum PreserveContents {\n    PRESERVE_CONTENTS,\n    DISCARD_CONTENTS,\n  };\n  // Recreate an mmap region that is shared between rr and the tracee. The\n  // caller is responsible for recreating the data in the new mmap, if `preserve` is\n  // DISCARD_CONTENTS.\n  // OK to call this while 'm' references one of the mappings in remote's\n  // AddressSpace.\n  // Returns an empty Mapping if the tracee died unexpectedly.\n  static const AddressSpace::Mapping recreate_shared_mmap(\n      AutoRemoteSyscalls& remote, const AddressSpace::Mapping& m,\n      PreserveContents preserve = DISCARD_CONTENTS,\n      MonitoredSharedMemory::shr_ptr monitored = nullptr);\n\n  /* Takes a mapping and replaces it by one that is shared between rr and\n     the tracee. The caller is responsible for filling the contents of the\n      new mapping.\n      Returns an empty mapping if the tracee unexpectedly died.\n   */\n  static AddressSpace::Mapping steal_mapping(\n      AutoRemoteSyscalls& remote, const AddressSpace::Mapping& m,\n      MonitoredSharedMemory::shr_ptr monitored = nullptr);\n\n  enum PtraceSyscallBeforeSeccomp {\n    PTRACE_SYSCALL_BEFORE_SECCOMP,\n    SECCOMP_BEFORE_PTRACE_SYSCALL,\n    PTRACE_SYSCALL_BEFORE_SECCOMP_UNKNOWN,\n  };\n  PtraceSyscallBeforeSeccomp syscall_seccomp_ordering() {\n    return syscall_seccomp_ordering_;\n  }\n\n  static bool has_cpuid_faulting();\n  static const char* rr_mapping_prefix();\n\n  ScopedFd& tracee_socket_fd() { return *tracee_socket; }\n  // Before using this, it must be drained. See AutoRemoteSyscalls.\n  ScopedFd& tracee_socket_receiver_fd() { return *tracee_socket_receiver; }\n  int tracee_fd_number() const { return tracee_socket_fd_number; }\n\n  virtual TraceStream* trace_stream() { return nullptr; }\n  TicksSemantics ticks_semantics() const { return ticks_semantics_; }\n\n  // Must be `UNBOUND` or `SPECIFIED_CORE`.\n  virtual BindCPU cpu_binding() const;\n\n  int syscall_number_for_rrcall_init_preload() const {\n    return SYS_rrcall_init_preload - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_init_buffers() const {\n    return SYS_rrcall_init_buffers - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_notify_syscall_hook_exit() const {\n    return SYS_rrcall_notify_syscall_hook_exit - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_notify_control_msg() const {\n    return SYS_rrcall_notify_control_msg - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_reload_auxv() const {\n    return SYS_rrcall_reload_auxv - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_mprotect_record() const {\n    return SYS_rrcall_mprotect_record - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_notify_stap_semaphore_added() const {\n    return SYS_rrcall_notify_stap_semaphore_added - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_notify_stap_semaphore_removed() const {\n    return SYS_rrcall_notify_stap_semaphore_removed - RR_CALL_BASE + rrcall_base_;\n  }\n  int syscall_number_for_rrcall_rdtsc() const {\n    return SYS_rrcall_rdtsc - RR_CALL_BASE + rrcall_base_;\n  }\n  uint32_t syscallbuf_fds_disabled_size() const {\n    return syscallbuf_fds_disabled_size_;\n  }\n  uint32_t syscallbuf_hdr_size() const {\n    return syscallbuf_hdr_size_;\n  }\n\n  /* Bind the current process to the a CPU as specified in the session options\n     or trace */\n  void do_bind_cpu();\n\n  const ThreadGroupMap& thread_group_map() const { return thread_group_map_; }\n\n  virtual int tracee_output_fd(int dflt) {\n    return dflt;\n  }\n\n  void set_intel_pt_enabled(bool intel_pt) { intel_pt_ = intel_pt; }\n  /* When this is true, we collect Intel PT traces during recording\n     or replay. */\n  bool intel_pt_enabled() const { return intel_pt_; }\n\n  virtual bool mark_stdio() const;\n\nprotected:\n  Session();\n  virtual ~Session();\n\n  ScopedFd create_spawn_task_error_pipe();\n\n  Session(const Session& other);\n  Session& operator=(const Session&) = delete;\n\n  virtual void on_create(Task* t);\n\n  BreakStatus diagnose_debugger_trap(Task* t, RunCommand run_command);\n  void check_for_watchpoint_changes(Task* t, BreakStatus& break_status);\n\n  void copy_state_to(Session& dest, EmuFs& emu_fs, EmuFs& dest_emu_fs);\n\n  // XXX Move CloneCompletion/CaptureState etc to ReplayTask/ReplaySession\n  struct CloneCompletion;\n  // Call this before doing anything that requires access to the full set\n  // of tasks (i.e., almost anything!). Not really const!\n  void finish_initializing() const;\n  void assert_fully_initialized() const;\n\n  AddressSpaceMap vm_map;\n  TaskMap task_map;\n  ThreadGroupMap thread_group_map_;\n\n  ScopedFd cpu_lock;\n\n  // If non-null, data required to finish initializing the tasks of this\n  // session.\n  std::unique_ptr<CloneCompletion> clone_completion;\n\n  Statistics statistics_;\n\n  std::shared_ptr<ScopedFd> tracee_socket;\n  std::shared_ptr<ScopedFd> tracee_socket_receiver;\n  int tracee_socket_fd_number;\n  uint32_t next_task_serial_;\n  ScopedFd spawned_task_error_fd_;\n\n  int rrcall_base_;\n  uint32_t syscallbuf_fds_disabled_size_;\n  uint32_t syscallbuf_hdr_size_;\n  PtraceSyscallBeforeSeccomp syscall_seccomp_ordering_;\n\n  TicksSemantics ticks_semantics_;\n\n  /**\n   * True if we've done an exec so tracees are now in a state that will be\n   * consistent across record and replay.\n   */\n  bool done_initial_exec_;\n\n  /**\n   * True while the execution of this session is visible to users.\n   */\n  bool visible_execution_;\n\n  /**\n   * True while we're collecting Intel PT data.\n   */\n  bool intel_pt_;\n};\n\n} // namespace rr\n\n#endif // RR_SESSION_H_\n"
  },
  {
    "path": "src/SourcesCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <dirent.h>\n#include <spawn.h>\n#include <unistd.h>\n\n#include <algorithm>\n#include <set>\n#include <tuple>\n#include <unordered_map>\n#include <unordered_set>\n#include <vector>\n#include <map>\n\n#include \"Command.h\"\n#include \"ElfReader.h\"\n#include \"Flags.h\"\n#include \"ReplaySession.h\"\n#include \"StringVectorToCharArray.h\"\n#include \"TraceStream.h\"\n#include \"core.h\"\n#include \"cpp_supplement.h\"\n#include \"log.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nconst char* DEBUGLINK = \"debuglink\";\nconst char* DEBUGALTLINK = \"debugaltlink\";\nconst char* DWP = \"dwp\";\n\n/// Prints JSON containing\n/// \"relevant_binaries\": an array of strings, trace-relative binary file names (or build-ids, for explicit-sources).\n///   These are ELF files in the trace that our collected data is relevant to.\n/// \"loaded_elf_binaries\": an array of strings of absolute paths.\n///   These are the paths to all the loaded ELF objects mapped at any point in the trace, including both shared libraries and executables.\n/// \"external_debug_info\": an array of objects, {\"path\":<path>, \"build_id\":<build-id>, \"type\":<type>}\n///   These are ELF files in the filesystem that contain separate debuginfo. \"build-id\" is the\n///   build-id of the file from whence it originated, as a string. \"type\" is the type of\n///   external file, one of \"debuglink\", \"debugaltlink\", \"dwp\". Note that for \"debugaltlink\", it is possible\n///   to have the same file appearing multiple times with different build-ids, when it's shared by\n///   multiple ELF binaries.\n/// \"dwo\": an array of objects, {\"name\":<name>, \"trace_file\":<name>, \"build_id\":<value>, \"comp_dir\":<path>, \"id\":<value>}\n///   These are the references to DWO files found in the trace binaries. \"name\" is the value of\n/// DW_AT_GNU_dwo_name. \"trace_file\" is the trace-relative binary file name. \"build_id\" is the\n/// binary's ELF build-id. \"comp_dir\" is the value of DW_AT_comp_dir for the compilation unit\n/// containing the DWO reference. \"id\" is the value of DW_AT_GNU_dwo_id (64 bit number).\n/// \"symlinks\": an array of objects, {\"from\":<path>, \"to\":<path>}.\n///   These symlinks that exist in the filesystem that are relevant to the source file paths.\n/// \"files\": a map from VCS directory name to array of source files relative to that directory\n///   An empty VCS directory name means files not under any VCS.\n/// \"comp_dir_substitutions\": a map from trace-relative binary file names (or build-ids, for explicit-sources) to\n/// the compilation-dir-override.\nclass SourcesCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  SourcesCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static SourcesCommand singleton;\n};\n\nSourcesCommand SourcesCommand::singleton(\n    \"sources\",\n    \" rr sources [<trace_dir>]\\n\"\n    \"  --substitute=LIBRARY=PATH  When searching for the source to LIBRARY,\\n\"\n    \"                             substitute PATH in place of the path stored\\n\"\n    \"                             in the library's DW_AT_comp_dir property\\n\"\n    \"                             for all compilation units.\\n\"\n    \"                             LIBRARY is the basename of the original file name,\\n\"\n    \"                             e.g. libc-2.32.so\\n\"\n    \"  --gdb-script=SCRIPT        Runs the provided gdb script in a (very basic)\\n\"\n    \"                             emulator, and gives it a chance to change paths\\n\"\n    \"                             for symbol loading/etc\\n\");\n\nclass ExplicitSourcesCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  ExplicitSourcesCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static ExplicitSourcesCommand singleton;\n};\n\nExplicitSourcesCommand ExplicitSourcesCommand::singleton(\n    \"explicit-sources\",\n    \" rr explicit-sources [<file>...]\\n\"\n    \"  Like `rr sources` but instead of scanning the binary files used in a\\n\"\n    \"  trace, scans an explicit list of files.\\n\"\n    \"  --substitute=LIBRARY=PATH  When searching for the source to LIBRARY,\\n\"\n    \"                             substitute PATH in place of the path stored\\n\"\n    \"                             in the library's DW_AT_comp_dir property\\n\"\n    \"                             for all compilation units.\\n\"\n    \"                             LIBRARY is the basename of the original file name,\\n\"\n    \"                             e.g. libc-2.32.so\\n\");\n\nstruct SourcesFlags {\n  map<string, string> comp_dir_substitutions;\n  string gdb_script;\n};\n\nstatic void dir_name(string& s) {\n  size_t p = s.rfind('/');\n  if (p == string::npos || (p == 0 && s.size() == 1)) {\n    s.clear();\n  } else if (p > 0) {\n    s.resize(p);\n  } else {\n    s.resize(1);\n  }\n}\n\nstatic bool is_absolute(const string& s) {\n  return s[0] == '/';\n}\n\nstatic void prepend_path(const char* prefix, string& s) {\n  size_t len = strlen(prefix);\n  if (!len) {\n    return;\n  }\n  if (prefix[len - 1] == '/') {\n    s = string(prefix) + s;\n  } else {\n    s = string(prefix) + '/' + s;\n  }\n}\n\nstruct DirExistsCache {\n  unordered_map<string, bool> cache;\n  bool dir_exists(const string& dir) {\n    auto it = cache.find(dir);\n    if (it != cache.end()) {\n      return it->second;\n    }\n    bool exists = access(dir.c_str(), F_OK) == 0;\n    cache.insert(make_pair(dir, exists));\n    return exists;\n  }\n};\n\nstruct DebugDirs {\n  vector<string> debug_file_directories;\n  vector<string> source_directories;\n};\n\n/// Manages integration with rr-gdb-script-host.py to allow a gdb script to\n/// control which directories we search. If input_pipe_fd is open we have a\n/// python child process. If input_pipe_fd is closed then everything here\n/// becomes a no-op.\nclass DebugDirManager {\npublic:\n  DebugDirManager(const string& program, const string& gdb_script);\n  ~DebugDirManager();\n\n  DebugDirs initial_directories() {\n    if (!input_pipe_fd.is_open()) {\n      // Try known alternatives.\n      if (char* nix_debug_info_dirs = getenv(\"NIX_DEBUG_INFO_DIRS\")) {\n        // NIX_DEBUG_INFO_DIRS is a colon separated list of paths to search for debug info.\n        DebugDirs result;\n\n        // Make a copy that we can run strtok on.\n        nix_debug_info_dirs = strdup(nix_debug_info_dirs);\n        char* token = strtok(nix_debug_info_dirs, \":\");\n        while (token != nullptr) {\n          string s(token);\n          s = real_path(s);\n          result.debug_file_directories.push_back(s);\n          LOG(debug) << \"NIX_DEBUG_INFO_DIRS added debug dir '\" << s << \"'\";\n          token = strtok(nullptr, \":\");\n        }\n        free(nix_debug_info_dirs);\n        return result;\n      }\n    }\n\n    return read_result();\n  }\n  DebugDirs process_one_binary(const string& binary_path);\n\nprivate:\n  DebugDirManager(const DebugDirManager&) = delete;\n  DebugDirManager& operator=(const DebugDirManager&) = delete;\n\n  DebugDirs read_result();\n\n  ScopedFd input_pipe_fd;\n  FILE* output_file;\n  pid_t pid;\n};\n\nDebugDirManager::~DebugDirManager() {\n  if (!input_pipe_fd.is_open()) {\n    return;\n  }\n\n  input_pipe_fd.close();\n  fclose(output_file);\n\n  int status;\n  if (waitpid(pid, &status, 0) == -1) {\n    FATAL() << \"Failed to wait on gdb script host\";\n  }\n}\n\nDebugDirManager::DebugDirManager(const string& program, const string& gdb_script)\n  : pid(-1)\n{\n  if (gdb_script.empty()) {\n    return;\n  }\n\n  int stdin_pipe_fds[2];\n  if (pipe(stdin_pipe_fds) == -1) {\n    FATAL();\n  }\n  int stdout_pipe_fds[2];\n  if (pipe(stdout_pipe_fds) == -1) {\n    FATAL();\n  }\n\n  posix_spawn_file_actions_t file_actions;\n  int ret = posix_spawn_file_actions_init(&file_actions);\n  if (ret != 0) {\n    FATAL() << \"posix_spawn_file_actions_init failed with \" << ret;\n  }\n\n  // Close unused write end in the child.\n  ret = posix_spawn_file_actions_addclose(&file_actions, stdin_pipe_fds[1]);\n  if (ret != 0) {\n    FATAL() << \"posix_spawn_file_actions_addclose failed with \" << ret;\n  }\n\n  // Close unused read end in the child.\n  ret = posix_spawn_file_actions_addclose(&file_actions, stdout_pipe_fds[0]);\n  if (ret != 0) {\n    FATAL() << \"posix_spawn_file_actions_addclose failed with \" << ret;\n  }\n\n  // Replace child's stdin with the read end.\n  ret = posix_spawn_file_actions_adddup2(&file_actions, stdin_pipe_fds[0], 0);\n  if (ret != 0) {\n    FATAL() << \"posix_spawn_file_actions_adddup2 failed with \" << ret;\n  }\n\n  // Replace child's stdout with the write end.\n  ret = posix_spawn_file_actions_adddup2(&file_actions, stdout_pipe_fds[1], 1);\n  if (ret != 0) {\n    FATAL() << \"posix_spawn_file_actions_adddup2 failed with \" << ret;\n  }\n\n  string gdb_script_host_path = resource_path() + \"bin/rr-gdb-script-host.py\";\n  pid_t pid;\n  vector<string> gdb_script_host_argv_vec = { gdb_script_host_path, gdb_script, program };\n  StringVectorToCharArray gdb_script_host_argv(gdb_script_host_argv_vec);\n  ret = posix_spawn(&pid, gdb_script_host_path.c_str(), &file_actions, nullptr,\n                    gdb_script_host_argv.get(), environ);\n  if (ret != 0) {\n    FATAL() << \"posix_spawn failed with \" << ret;\n  }\n\n  // Ignore the return values during cleanup.\n  posix_spawn_file_actions_destroy(&file_actions);\n\n  close(stdin_pipe_fds[0]);\n  close(stdout_pipe_fds[1]);\n\n  this->pid = pid;\n  this->input_pipe_fd = ScopedFd(stdin_pipe_fds[1]);\n  this->output_file = fdopen(stdout_pipe_fds[0], \"r\");\n  if (!this->output_file) {\n    FATAL() << \"Failed to fdopen(stdout_pipe_fds[0])\";\n  }\n}\n\nDebugDirs DebugDirManager::process_one_binary(const string& binary_path) {\n  if (!input_pipe_fd.is_open()) {\n    return DebugDirs();\n  }\n\n  auto len = binary_path.length();\n  size_t written = write(input_pipe_fd, binary_path.c_str(), len);\n  if (written != len) {\n    FATAL() << \"Failed to write filename\";\n  }\n  written = write(input_pipe_fd, \"\\n\", 1);\n  if (written != 1) {\n    FATAL() << \"Failed to write trailing newline\";\n  }\n\n  return read_result();\n}\n\nDebugDirs DebugDirManager::read_result() {\n  char buf[4096];\n  DebugDirs result;\n  size_t index;\n  const char delimiter[2] = \":\";\n\n  if (!input_pipe_fd.is_open()) {\n    return result;\n  }\n\n  if (!fgets(buf, sizeof(buf) - 1, output_file)) {\n    FATAL() << \"Failed to read gdb script output\";\n  }\n  index = strcspn(buf, \"\\n\");\n  buf[index] = 0;\n\n  char* token = strtok(buf, delimiter);\n  while (token != nullptr) {\n    string s(token);\n    s = real_path(s);\n    result.debug_file_directories.push_back(s);\n    LOG(debug) << \"gdb script added debug dir '\" << s << \"'\";\n    token = strtok(nullptr, delimiter);\n  }\n\n  if (!fgets(buf, sizeof(buf) - 1, output_file)) {\n    FATAL() << \"Failed to read gdb script output\";\n  }\n  index = strcspn(buf, \"\\n\");\n  buf[index] = 0;\n\n  token = strtok(buf, delimiter);\n  while (token != nullptr) {\n    char* buf = realpath(token, nullptr);\n    if (buf) {\n      auto s = string(buf);\n      result.source_directories.push_back(s);\n      LOG(debug) << \"gdb script added source dir '\" << s << \"'\";\n      free(buf);\n    } else {\n      LOG(debug) << \"realpath(\" << token << \") = \" << strerror(errno);\n    }\n    token = strtok(nullptr, delimiter);\n  }\n\n  return result;\n}\n\n// Resolve a file name relative to a compilation directory and relative directory.\n// file_name cannot be null, but the others can be.\n// Takes into account the original file name as follows:\n// -- if comp_dir, rel_dir or file_name are absolute, or original_file_name is NULL,\n// then ignore original_file_name.\n// The result is just the result of combining comp_dir/rel_dir/file_name.\n// -- otherwise they're all relative to some build directory. We hypothesize\n// the build directory is some ancestor directory of original_file_name.\n// We try making comp_dir/rel_dir/file_name relative to each ancestor directory\n// of original_file_name, and if we find a file there, we return that name.\n// original_file_name must be absolute if not NULL.\n//\n// If non-empty, `comp_dir_substitution` should replace `original_comp_dir`\n// in `rel_dir` if `original_comp_dir` is a prefix of `rel_dir`.\n// Always returns an absolute file name.\n// Returns true if we got a result, otherwise false.\nstatic bool resolve_file_name(const char* original_file_name,\n                              const char* comp_dir,\n                              const char* original_comp_dir,\n                              const string& comp_dir_substitution,\n                              const char* rel_dir,\n                              const char* file_name,\n                              DirExistsCache& dir_exists_cache,\n                              string& path) {\n  path = file_name;\n  if (is_absolute(path)) {\n    return true;\n  }\n  if (rel_dir) {\n    if (rel_dir[0] == '/' && !comp_dir_substitution.empty() && original_comp_dir &&\n        strncmp(rel_dir, original_comp_dir, strlen(original_comp_dir)) == 0) {\n      string rel = comp_dir_substitution + (rel_dir + strlen(original_comp_dir));\n      prepend_path(rel.c_str(), path);\n    } else {\n      prepend_path(rel_dir, path);\n    }\n    if (is_absolute(path)) {\n      return true;\n    }\n  }\n  if (comp_dir) {\n    prepend_path(comp_dir, path);\n    if (is_absolute(path)) {\n      return true;\n    }\n  }\n  if (!original_file_name) {\n    if (is_absolute(path)) {\n      return true;\n    }\n    LOG(warn) << \"Path \" << path << \" is relative and we can't make it absolute\";\n    return false;\n  }\n  string original(original_file_name);\n  while (true) {\n    dir_name(original);\n    if (original.empty()) {\n      LOG(warn) << \"Path \" << path << \" is relative and we can't make it absolute\";\n      return false;\n    }\n    string candidate = original + \"/\" + path;\n    if (dir_exists_cache.dir_exists(candidate)) {\n      path = candidate;\n      return true;\n    }\n  }\n}\n\nstruct DwoInfo {\n  string name;\n  string trace_file;\n  string build_id;\n  // Could be an empty string\n  string comp_dir;\n  string full_path;\n  uint64_t id;\n};\n\nstruct OutputCompDirSubstitution {\n  string trace_relative_name;\n  string substitution;\n};\n\nstatic bool process_compilation_units(ElfFileReader& reader,\n                                      ElfFileReader* sup_reader,\n                                      const string& trace_relative_name,\n                                      const string& original_file_name,\n                                      const string& comp_dir_substitution,\n                                      vector<OutputCompDirSubstitution>& comp_dir_substitutions,\n                                      const string* debug_file_directory,\n                                      const string* debug_src_directory,\n                                      set<string>* file_names, vector<DwoInfo>* dwos,\n                                      DirExistsCache& dir_exists_cache) {\n  string build_id = reader.read_buildid();\n  DwarfSpan debug_info = reader.dwarf_section(\".debug_info\");\n  if (debug_info.empty()) {\n    debug_info = reader.dwarf_section(\".zdebug_info\", true);\n  }\n  DwarfSpan debug_abbrev = reader.dwarf_section(\".debug_abbrev\");\n  if (debug_abbrev.empty()) {\n    debug_abbrev = reader.dwarf_section(\".zdebug_abbrev\", true);\n  }\n  DwarfSpan debug_str = reader.dwarf_section(\".debug_str\");\n  if (debug_str.empty()) {\n    debug_str = reader.dwarf_section(\".zdebug_str\", true);\n  }\n  DwarfSpan debug_str_sup = sup_reader ? sup_reader->dwarf_section(\".debug_str\") : DwarfSpan();\n  DwarfSpan debug_str_offsets = reader.dwarf_section(\".debug_str_offsets\");\n  DwarfSpan debug_line = reader.dwarf_section(\".debug_line\");\n  if (debug_line.empty()) {\n    debug_line = reader.dwarf_section(\".zdebug_line\", true);\n  }\n  DwarfSpan debug_line_str = reader.dwarf_section(\".debug_line_str\");\n  if (debug_info.empty() || debug_abbrev.empty() ||\n      (debug_str.empty() && debug_str_sup.empty()) ||\n      debug_line.empty())  {\n    return false;\n  }\n\n  DebugStrSpans debug_strs = {\n    debug_str,\n    debug_str_sup,\n    debug_str_offsets,\n    debug_line_str,\n  };\n\n  DwarfAbbrevs abbrevs(debug_abbrev);\n  do {\n    bool ok = true;\n    DwarfCompilationUnit cu = DwarfCompilationUnit::next(&debug_info, abbrevs, &ok);\n    if (!ok) {\n      break;\n    }\n    int64_t str_offsets_base = cu.die().section_ptr_attr(DW_AT_str_offsets_base, &ok);\n    if (!ok) {\n      continue;\n    }\n    if (str_offsets_base > 0) {\n      cu.set_str_offsets_base(str_offsets_base);\n    } else {\n      cu.set_str_offsets_base(0);\n    }\n    const char* original_comp_dir = cu.die().string_attr(cu, DW_AT_comp_dir, debug_strs, &ok);\n    string comp_dir;\n    if (!comp_dir_substitution.empty()) {\n      comp_dir = comp_dir_substitution;\n    } else {\n      if (!ok) {\n        continue;\n      }\n      if (original_comp_dir) {\n        comp_dir = original_comp_dir;\n      }\n      if (debug_src_directory && !is_absolute(comp_dir)) {\n        prepend_path(debug_src_directory->c_str(), comp_dir);\n        if (std::find_if(comp_dir_substitutions.begin(), comp_dir_substitutions.end(), [trace_relative_name](OutputCompDirSubstitution& s) {\n          return s.trace_relative_name == trace_relative_name;\n        }) == comp_dir_substitutions.end()) {\n          comp_dir_substitutions.push_back({ trace_relative_name, comp_dir });\n        }\n      } else if (debug_file_directory) {\n        prepend_path(debug_file_directory->c_str(), comp_dir);\n      }\n    }\n    const char* dwo_name = cu.die().string_attr(cu, DW_AT_GNU_dwo_name, debug_strs, &ok);\n    if (!ok || !dwo_name) {\n      dwo_name = cu.die().string_attr(cu, DW_AT_dwo_name, debug_strs, &ok);\n      if (!ok) {\n        continue;\n      }\n    }\n    if (dwo_name) {\n      bool has_dwo_id = false;\n      uint64_t dwo_id = cu.dwo_id();\n      if (dwo_id != 0) {\n        has_dwo_id = true;\n      }\n      if (!has_dwo_id) {\n        dwo_id = cu.die().unsigned_attr(DW_AT_GNU_dwo_id, &has_dwo_id, &ok);\n        if (!ok) {\n          LOG(warn) << \"Have DWO name \" << dwo_name << \" but can't get DWO id\";\n          continue;\n        }\n      }\n      if (has_dwo_id) {\n        string full_name;\n        LOG(debug) << \"Have DWO name \" << dwo_name << \" id \" << HEX(dwo_id);\n        if (resolve_file_name(original_file_name.c_str(), comp_dir.c_str(), original_comp_dir, comp_dir_substitution, nullptr, dwo_name, dir_exists_cache, full_name)) {\n          string c = comp_dir;\n          dwos->push_back({ dwo_name, trace_relative_name, build_id, std::move(c), full_name, dwo_id });\n        } else {\n          FATAL() << \"DWO missing due to relative path \" << full_name;\n        }\n      } else {\n        LOG(warn) << \"DW_AT_GNU_dwo_name but not DW_AT_GNU_dwo_id\";\n      }\n    }\n    const char* source_file_name = cu.die().string_attr(cu, DW_AT_name, debug_strs, &ok);\n    if (!ok) {\n      continue;\n    }\n    if (source_file_name) {\n      string full_name;\n      if (resolve_file_name(original_file_name.c_str(), comp_dir.c_str(), original_comp_dir, comp_dir_substitution, nullptr, source_file_name, dir_exists_cache, full_name)) {\n        file_names->insert(full_name);\n      }\n    }\n    intptr_t stmt_list = cu.die().section_ptr_attr(DW_AT_stmt_list, &ok);\n    if (stmt_list < 0 || !ok) {\n      continue;\n    }\n    DwarfLineNumberTable lines(cu, debug_line.subspan(stmt_list), debug_strs, &ok);\n    if (!ok) {\n      continue;\n    }\n    for (auto& f : lines.file_names()) {\n      if (!f.file_name) {\n        // Already resolved above.\n        continue;\n      }\n      const char* dir = lines.directories()[f.directory_index];\n      string full_name;\n      if (resolve_file_name(original_file_name.c_str(), comp_dir.c_str(), original_comp_dir, comp_dir_substitution, dir, f.file_name, dir_exists_cache, full_name)) {\n        file_names->insert(full_name);\n      }\n    }\n  } while (!debug_info.empty());\n\n  return true;\n}\n\nstruct ExternalDebugInfo {\n  string path;\n  string build_id;\n  string type;\n  bool operator<(const ExternalDebugInfo& other) const {\n    if (path < other.path) {\n      return true;\n    }\n    if (path > other.path) {\n      return false;\n    }\n    if (build_id < other.build_id) {\n      return true;\n    }\n    if (build_id > other.build_id) {\n      return false;\n    }\n    return type < other.type;\n  }\n};\n\nstatic unique_ptr<ElfFileReader>\nfind_auxiliary_file(const string& original_file_name,\n                    const string& aux_file_name,\n                    string& full_file_name,\n                    const vector<string>& dirs) {\n  if (aux_file_name.empty()) {\n    return nullptr;\n  }\n  ScopedFd fd;\n  if (aux_file_name.c_str()[0] == '/') {\n    full_file_name = aux_file_name;\n    fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n    if (!fd.is_open()) {\n      LOG(warn) << \"Can't find external debuginfo file \" << full_file_name;\n      return nullptr;\n    }\n  } else {\n    // Skip first trying the current directory. That's unlikely to be correct.\n\n    // Try in the same directory as the original file.\n    string original_file_dir = original_file_name;\n    dir_name(original_file_dir);\n    full_file_name = original_file_dir + \"/\" + aux_file_name;\n    normalize_file_name(full_file_name);\n    fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n    if (fd.is_open()) {\n      // Debian/Ubuntu built /lib/x86_64-linux-gnu/ld-2.31.so with a\n      // .gnu_debuglink of \"ld-2.31.so\", expecting it to be found at\n      // /usr/lib/debug/lib/x86_64-linux-gnu/ld-2.31.so. So we need to make\n      // sure we aren't using the binary file as its own debuginfo.\n      if (real_path(original_file_name) != real_path(full_file_name)) {\n        goto found;\n      }\n    }\n    LOG(info) << \"Can't find external debuginfo file \" << full_file_name;\n\n    // Next try in a subdirectory called .debug\n    full_file_name = original_file_dir + \"/.debug/\" + aux_file_name;\n    normalize_file_name(full_file_name);\n    fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n    if (fd.is_open()) {\n      goto found;\n    }\n    LOG(info) << \"Can't find external debuginfo file \" << full_file_name;\n\n    // Then try in /usr/lib/debug\n    full_file_name = \"/usr/lib/debug/\" + aux_file_name;\n    normalize_file_name(full_file_name);\n    fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n    if (fd.is_open()) {\n      goto found;\n    }\n    LOG(info) << \"Can't find external debuginfo file \" << full_file_name;\n\n    // Try in an appropriate subdirectory of /usr/lib/debug\n    full_file_name = \"/usr/lib/debug\" + original_file_dir + \"/\" + aux_file_name;\n    normalize_file_name(full_file_name);\n    fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n    if (fd.is_open()) {\n      goto found;\n    }\n    LOG(info) << \"Can't find external debuginfo file \" << full_file_name;\n\n    // Try in an appropriate subdirectory of the provided debug dirs\n    for (auto& d : dirs) {\n      full_file_name = d + original_file_dir + \"/\" + aux_file_name;\n      normalize_file_name(full_file_name);\n      fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n      if (fd.is_open()) {\n        goto found;\n      }\n      LOG(info) << \"Can't find external debuginfo file \" << full_file_name;\n    }\n\n    // On Ubuntu 20.04 there's both a /lib/x86_64-linux-gnu/libc-2.31.so and a\n    // /usr/lib/x86_64-linux-gnu/libc-2.31.so. They are hardlinked to the same inode,\n    // and glibc debuginfo is present in the location corresponding to\n    // /lib/x86_64-linux-gnu/libc-2.31.so. But the kernel returns the /usr prefixed\n    // path from /proc/<pid>/fd/<fd>. Hack around that here.\n    if (original_file_dir.find(\"/usr/\") == 0) {\n      full_file_name = \"/usr/lib/debug\" + original_file_dir.substr(sizeof(\"/usr\") - 1) + \"/\" + aux_file_name;\n      normalize_file_name(full_file_name);\n      fd = ScopedFd(full_file_name.c_str(), O_RDONLY);\n      if (fd.is_open()) {\n        goto found;\n      }\n      LOG(info) << \"Can't find external debuginfo file \" << full_file_name;\n    }\n\n    // If none of those worked, give up.\n    LOG(warn) << \"Exhausted auxiliary debuginfo search locations for \" << aux_file_name;\n    return nullptr;\n  }\n\nfound:\n  LOG(info) << \"Examining external \" << full_file_name;\n  auto reader = make_unique<ElfFileReader>(fd);\n  if (!reader->ok()) {\n    LOG(warn) << \"Not an ELF file!\";\n    return nullptr;\n  }\n  return reader;\n}\n\nstatic unique_ptr<ElfFileReader>\nfind_auxiliary_file_by_buildid(ElfFileReader& trace_file_reader,\n                               string& full_file_name,\n                               const vector<string>& dirs) {\n  string build_id = trace_file_reader.read_buildid();\n  if (build_id.empty()) {\n    LOG(warn) << \"Main ELF binary has no build ID!\";\n    return nullptr;\n  }\n  if (build_id.size() < 3) {\n    LOG(warn) << \"Build ID is too short!\";\n    return nullptr;\n  }\n\n  string filename = build_id.substr(0, 2) + \"/\" + build_id.substr(2) + \".debug\";\n  string path = \"/usr/lib/debug/.build-id/\" + filename;\n  ScopedFd fd(path.c_str(), O_RDONLY);\n  if (!fd.is_open()) {\n    LOG(info) << \"Can't find external debuginfo file \" << path;\n    for (auto &d : dirs) {\n      path = d + \"/.build-id/\" + filename;\n      fd = ScopedFd(path.c_str(), O_RDONLY);\n      if (fd.is_open()) {\n        break;\n      }\n      LOG(info) << \"Can't find external debuginfo file \" << path;\n    }\n  }\n\n  if (!fd.is_open()) {\n    return nullptr;\n  }\n\n  LOG(info) << \"Examining external by buildid \" << path;\n  auto reader = make_unique<ElfFileReader>(fd);\n  if (!reader->ok()) {\n    LOG(warn) << \"Not an ELF file!\";\n    return nullptr;\n  }\n  full_file_name = path;\n  return reader;\n}\n\n// Traverse the compilation units of an auxiliary file to collect their source files\nstatic bool process_auxiliary_file(ElfFileReader& trace_file_reader,\n                                   ElfFileReader& aux_file_reader,\n                                   ElfFileReader* alt_file_reader,\n                                   const string& trace_relative_name,\n                                   const string& original_file_name,\n                                   set<string>* file_names,\n                                   const string& full_aux_file_name,\n                                   const char* file_type,\n                                   map<string, string> comp_dir_substitutions,\n                                   vector<OutputCompDirSubstitution>& output_comp_dir_substitutions,\n                                   const string* chosen_debug_dir,\n                                   const string* chosen_src_dir,\n                                   vector<DwoInfo>* dwos,\n                                   set<ExternalDebugInfo>* external_debug_info,\n                                   bool already_used_file,\n                                   DirExistsCache& dir_exists_cache) {\n  string build_id = trace_file_reader.read_buildid();\n  if (build_id.empty()) {\n    LOG(warn) << \"Main ELF binary has no build ID!\";\n    return false;\n  }\n\n  bool did_work;\n  string original_name = original_file_name;\n  base_name(original_name);\n  auto it = comp_dir_substitutions.find(original_name);\n  if (it != comp_dir_substitutions.end()) {\n    LOG(debug) << \"\\tFound comp_dir substitution \" << it->second;\n    did_work = process_compilation_units(aux_file_reader, alt_file_reader,\n                                         trace_relative_name, original_file_name,\n                                         it->second, output_comp_dir_substitutions,\n                                         chosen_debug_dir, chosen_src_dir,\n                                         file_names, dwos, dir_exists_cache);\n  } else {\n    LOG(debug) << \"\\tNo comp_dir substitution found\";\n    did_work = process_compilation_units(aux_file_reader, alt_file_reader,\n                                         trace_relative_name, original_file_name,\n                                         {}, output_comp_dir_substitutions,\n                                         chosen_debug_dir, chosen_src_dir,\n                                         file_names, dwos, dir_exists_cache);\n  }\n\n  if (!did_work) {\n    LOG(warn) << \"No debuginfo!\";\n    /* If we've already used this file we need to insert it into the external_debug_info\n     * set even if it does not have any CUs of its own.\n     */\n    if (!already_used_file) {\n      return false;\n    }\n  }\n  external_debug_info->insert({ full_aux_file_name, build_id, string(file_type) });\n  return did_work;\n}\n\nstatic bool try_debuglink_file(ElfFileReader& trace_file_reader,\n                               const string& trace_relative_name,\n                               const string& original_file_name,\n                               set<string>* file_names, const string& aux_file_name,\n                               map<string, string>& comp_dir_substitutions,\n                               vector<OutputCompDirSubstitution>& output_comp_dir_substitutions,\n                               unique_ptr<DebugDirManager>& debug_dirs,\n                               DebugDirs& dd,\n                               vector<DwoInfo>* dwos,\n                               set<ExternalDebugInfo>* external_debug_info,\n                               DirExistsCache& dir_exists_cache) {\n  string full_file_name;\n  auto reader = find_auxiliary_file(original_file_name, aux_file_name,\n                                    full_file_name, dd.debug_file_directories);\n  if (!reader) {\n    reader = find_auxiliary_file_by_buildid(trace_file_reader, full_file_name, dd.debug_file_directories);\n    if (!reader) {\n      dd.debug_file_directories.clear();\n      dd.source_directories.clear();\n      return false;\n    }\n  }\n\n  if (debug_dirs) {\n    dd = debug_dirs->process_one_binary(full_file_name);\n  }\n\n  /* A debuglink file can have its own debugaltlink */\n  string full_altfile_name;\n  Debugaltlink debugaltlink = reader->read_debugaltlink();\n  auto altlink_reader = find_auxiliary_file(original_file_name, debugaltlink.file_name,\n                                            full_altfile_name, dd.debug_file_directories);\n\n  // Notify a gdb script about the main binary before processing CUs.\n  if (debug_dirs) {\n    dd = debug_dirs->process_one_binary(original_file_name);\n  }\n\n  vector<string*> debug_file_directories;\n  debug_file_directories.reserve(dd.debug_file_directories.size() + 1);\n  for (auto& dfd : dd.debug_file_directories) {\n    debug_file_directories.push_back(&dfd);\n  }\n  debug_file_directories.push_back(nullptr);\n\n  for (auto chosen_debug_dir : debug_file_directories) {\n    const string* chosen_src_dir = nullptr;\n    if (!dd.source_directories.empty()) {\n      chosen_src_dir = &dd.source_directories.back();\n    }\n\n    bool has_source_files = process_auxiliary_file(trace_file_reader, *reader, altlink_reader.get(),\n                                                   trace_relative_name, original_file_name,\n                                                   file_names, full_file_name, DEBUGLINK,\n                                                   comp_dir_substitutions, output_comp_dir_substitutions,\n                                                   chosen_debug_dir, chosen_src_dir,\n                                                   dwos, external_debug_info, false, dir_exists_cache);\n\n    if (altlink_reader) {\n      has_source_files |= process_auxiliary_file(trace_file_reader, *altlink_reader, nullptr,\n                                                 trace_relative_name, original_file_name,\n                                                 file_names, full_altfile_name, DEBUGALTLINK,\n                                                 comp_dir_substitutions, output_comp_dir_substitutions,\n                                                 chosen_debug_dir, chosen_src_dir,\n                                                 dwos, external_debug_info, has_source_files, dir_exists_cache);\n    }\n    if (has_source_files) {\n      return true;\n    }\n  }\n  return false;\n}\n\nstruct Symlink {\n  string from;\n  string to;\n};\n\nstatic bool has_subdir(string& base, const char* suffix) {\n  base += suffix;\n  int ret = access(base.c_str(), F_OK);\n  base.resize(base.size() - strlen(suffix));\n  return !ret;\n}\n\nstatic void assert_absolute(const string& path) {\n  if (!is_absolute(path)) {\n    FATAL() << \"Path \" << path << \" not absolute\";\n  }\n}\n\nstatic void check_vcs_root(string& path, set<string>* vcs_dirs) {\n  assert_absolute(path);\n  if (has_subdir(path, \"/.git\") || has_subdir(path, \"/.hg\")) {\n    vcs_dirs->insert(path + \"/\");\n  }\n}\n\n// Returns an empty string if the path does not exist or\n// is not accessible.\n// `path` need not be normalized, i.e. may contain .. or .\n// components. It mus be absolute.\n// The result string, if non-empty, will be absolute,\n// normalized, and contain no symlink components.\n// The keys in resolved_dirs are absolute file paths\n// that may contain symlink components and need not be\n// normalized.\n// The values in resolved_dirs are always absolute, normalized,\n// contain no symlink components, and are directories.\nstatic string resolve_symlinks(const string& path,\n                               bool is_file,\n                               unordered_map<string, string>* resolved_dirs,\n                               vector<Symlink>* symlinks,\n                               set<string>* vcs_dirs) {\n  assert_absolute(path);\n  // Absolute, not normalized. We don't keep this normalized because\n  // we want resolved_dirs to work well.\n  // This is always a prefix of `path`.\n  string base = path;\n  // Absolute, normalized, no symlink components.\n  string resolved_base;\n  string rest;\n  while (true) {\n    size_t p = base.rfind('/');\n    if (p == 0 || p == string::npos) {\n      base = \"\";\n      rest = path;\n      break;\n    }\n    base.resize(p - 1);\n    auto it = resolved_dirs->find(base);\n    if (it != resolved_dirs->end()) {\n      resolved_base = it->second;\n      rest = path.substr(p);\n      break;\n    }\n  }\n  // Now iterate through the components of \"rest\".\n  // p points to some '/'-starting component in `rest`.\n  size_t p = 0;\n  while (true) {\n    size_t next = rest.find('/', p + 1);\n    bool base_is_file = false;\n    size_t end;\n    if (next == string::npos) {\n      base.append(rest, p, rest.size() - p);\n      resolved_base.append(rest, p, rest.size() - p);\n      base_is_file = is_file;\n      end = rest.size();\n    } else {\n      base.append(rest, p, next - p);\n      resolved_base.append(rest, p, next - p);\n      end = next;\n    }\n\n    if ((end == p + 2 && memcmp(rest.c_str() + p, \"/.\", 2) == 0) ||\n        (end == p + 3 && memcmp(rest.c_str() + p, \"/..\", 3) == 0)) {\n      normalize_file_name(resolved_base);\n    }\n\n    p = next;\n\n    // Now make resolved_base actually resolved.\n    // First see if our new resolved_base is cached.\n    auto it = resolved_dirs->find(resolved_base);\n    if (it != resolved_dirs->end()) {\n      resolved_base = it->second;\n      if (next == string::npos) {\n        return resolved_base;\n      }\n      resolved_dirs->insert(make_pair(base, resolved_base));\n      continue;\n    }\n\n    char buf[PATH_MAX + 1];\n    ssize_t ret = readlink(resolved_base.c_str(), buf, sizeof(buf));\n    if (ret >= 0) {\n      buf[ret] = 0;\n      string target;\n      if (buf[0] != '/') {\n        target = base;\n        dir_name(target);\n        if (target.size() > 1) {\n          target.push_back('/');\n        }\n      }\n      target += buf;\n      // We can't normalize `target` because `buf` may itself contain\n      // unresolved symlinks, which make normalization non-semantics-preserving.\n      string resolved = resolve_symlinks(target, base_is_file, resolved_dirs, symlinks, vcs_dirs);\n      symlinks->push_back({ resolved_base, resolved });\n      if (!base_is_file) {\n        check_vcs_root(resolved, vcs_dirs);\n        // Cache the result of the readlink operation\n        resolved_dirs->insert(make_pair(std::move(resolved_base), resolved));\n        // And cache based on the original `base`.\n        resolved_dirs->insert(make_pair(base, resolved));\n      }\n      resolved_base = resolved;\n      if (next == string::npos) {\n        return resolved_base;\n      }\n    } else {\n      if (errno == ENOENT || errno == EACCES || errno == ENOTDIR) {\n        // Path is invalid\n        resolved_base.clear();\n        return resolved_base;\n      }\n      if (errno != EINVAL) {\n        FATAL() << \"Failed to readlink \" << base;\n      }\n      if (!base_is_file) {\n        check_vcs_root(resolved_base, vcs_dirs);\n        // Cache the result of the readlink operation\n        resolved_dirs->insert(make_pair(resolved_base, resolved_base));\n        // And cache based on the original `base`.\n        resolved_dirs->insert(make_pair(base, resolved_base));\n      }\n      if (next == string::npos) {\n        return resolved_base;\n      }\n    }\n  }\n}\n\n/// Adds to vcs_dirs any directory paths under any\n/// of our resolved directories.\n/// file_names must be absolute.\nstatic void build_symlink_map(const set<string>& file_names,\n                              set<string>* resolved_file_names,\n                              vector<Symlink>* symlinks,\n                              set<string>* vcs_dirs) {\n  // <dir> -> <path> --- <dir> resolves to <path> using the\n  // current value of `symlinks` (and <path> contains no symlinks).\n  // If <path> is the empty string then that means the same as <dir>.\n  unordered_map<string, string> resolved_dirs;\n  for (auto& file_name : file_names) {\n    string resolved = resolve_symlinks(file_name, true, &resolved_dirs, symlinks, vcs_dirs);\n    if (resolved.empty()) {\n      LOG(info) << \"File \" << file_name << \" not found, skipping\";\n    } else {\n      LOG(debug) << \"File \" << file_name << \" resolved to \" << resolved;\n      resolved_file_names->insert(resolved);\n    }\n  }\n}\n\nstatic bool starts_with(const string& s, const string& prefix) {\n  return strncmp(s.c_str(), prefix.c_str(), prefix.size()) == 0;\n}\n\ntemplate<class iterable>\nstatic int sources(const iterable& binary_file_names,\n                   map<string, string>& comp_dir_substitutions,\n                   unique_ptr<DebugDirManager>& debug_dirs,\n                   bool is_explicit) {\n  vector<string> relevant_binary_names;\n  set<string> original_loaded_elf_names;\n  // Must be absolute.\n  set<string> file_names;\n  set<ExternalDebugInfo> external_debug_info;\n  vector<DwoInfo> dwos;\n  vector<OutputCompDirSubstitution> output_comp_dir_substitutions;\n  DirExistsCache dir_exists_cache;\n  DebugDirs dd;\n  if (debug_dirs) {\n    dd = debug_dirs->initial_directories();\n  }\n\n  for (auto& pair : binary_file_names) {\n    string trace_relative_name = pair.first;\n    string original_name = pair.second;\n    const char* file_name = is_explicit ? original_name.c_str() : trace_relative_name.c_str();\n    ScopedFd fd(file_name, O_RDONLY);\n    if (!fd.is_open()) {\n      FATAL() << \"Can't open \" << file_name;\n    }\n    LOG(info) << \"Examining \" << file_name;\n    ElfFileReader reader(fd);\n    if (!reader.ok()) {\n      LOG(info) << \"Probably not an ELF file, skipping\";\n      continue;\n    }\n\n    if (!is_explicit) {\n      base_name(trace_relative_name);\n    }\n    original_loaded_elf_names.insert(original_name);\n    base_name(original_name);\n    Debugaltlink debugaltlink = reader.read_debugaltlink();\n\n    string full_altfile_name;\n    auto altlink_reader = find_auxiliary_file(pair.second, debugaltlink.file_name,\n                                              full_altfile_name, dd.debug_file_directories);\n\n    bool has_source_files;\n    auto dwo_count = dwos.size();\n    LOG(debug) << \"Looking for comp_dir substitutions for \" << original_name;\n    auto it = comp_dir_substitutions.find(original_name);\n    if (it != comp_dir_substitutions.end()) {\n      LOG(debug) << \"\\tFound comp_dir substitution \" << it->second;\n      output_comp_dir_substitutions.push_back({ trace_relative_name, it->second });\n      has_source_files = process_compilation_units(reader, altlink_reader.get(),\n                                                   trace_relative_name, pair.second,\n                                                   it->second, output_comp_dir_substitutions,\n                                                   nullptr, nullptr, &file_names, &dwos,\n                                                   dir_exists_cache);\n    } else {\n      LOG(debug) << \"\\tNo comp_dir substitution found\";\n      has_source_files = process_compilation_units(reader, altlink_reader.get(),\n                                                   trace_relative_name, pair.second,\n                                                   {}, output_comp_dir_substitutions,\n                                                   nullptr, nullptr, &file_names, &dwos,\n                                                   dir_exists_cache);\n    }\n    /* If the original binary had source files, force the inclusion of any debugaltlink\n     * file, even if it does not itself have compilation units (it may have relevant strings)\n     */\n    const bool original_had_source_files = has_source_files;\n\n    Debuglink debuglink = reader.read_debuglink();\n    has_source_files |= try_debuglink_file(reader, trace_relative_name, pair.second,\n                                           &file_names, debuglink.file_name,\n                                           comp_dir_substitutions, output_comp_dir_substitutions, debug_dirs, dd, &dwos,\n                                           &external_debug_info, dir_exists_cache);\n\n    if (dd.debug_file_directories.empty() && debug_dirs) {\n      dd = debug_dirs->process_one_binary(pair.first);\n    }\n\n    if (altlink_reader) {\n      has_source_files |= process_auxiliary_file(reader, *altlink_reader, nullptr,\n                                                 trace_relative_name, pair.second,\n                                                 &file_names, full_altfile_name,\n                                                 DEBUGALTLINK, comp_dir_substitutions, output_comp_dir_substitutions,\n                                                 nullptr, nullptr, &dwos, &external_debug_info,\n                                                 original_had_source_files, dir_exists_cache);\n    }\n\n    if (dwos.size() > dwo_count) {\n      /* If there are any dwos, check for a dwp. */\n      string dwp_candidate = pair.second + \".dwp\";\n      struct stat statbuf;\n      int ret = stat(dwp_candidate.c_str(), &statbuf);\n      if (ret == 0 && S_ISREG(statbuf.st_mode)) {\n        string build_id = reader.read_buildid();\n        if (!build_id.empty()) {\n          external_debug_info.insert({ dwp_candidate, build_id, string(DWP) });\n        } else {\n          LOG(warn) << \"Main ELF binary has no build ID!\";\n        }\n      }\n    }\n\n    if (has_source_files) {\n      relevant_binary_names.push_back(std::move(trace_relative_name));\n    } else {\n      LOG(info) << \"No debuginfo found\";\n    }\n  }\n\n  set<string> resolved_file_names;\n  vector<Symlink> symlinks;\n  set<string> vcs_dirs;\n  build_symlink_map(file_names, &resolved_file_names, &symlinks, &vcs_dirs);\n  file_names.clear();\n\n  map<string, vector<const string*>> vcs_files;\n  const string empty_string;\n  vector<const string*> vcs_stack;\n  vector<const string*> vcs_dirs_vector;\n  auto vcs_dir_iterator = vcs_dirs.begin();\n  bool pushed_empty_string = false;\n  for (auto& f : resolved_file_names) {\n    while (!vcs_stack.empty() && !starts_with(f, *vcs_stack.back())) {\n      vcs_stack.pop_back();\n    }\n    while (vcs_dir_iterator != vcs_dirs.end()) {\n      if (starts_with(f, *vcs_dir_iterator)) {\n        vcs_stack.push_back(&*vcs_dir_iterator);\n        vcs_dirs_vector.push_back(&*vcs_dir_iterator);\n        ++vcs_dir_iterator;\n        continue;\n      }\n      if (*vcs_dir_iterator < f) {\n        // Skip this VCS dir because all of its files must have been\n        // skipped (not found).\n        ++vcs_dir_iterator;\n        continue;\n      }\n      break;\n    }\n    if (vcs_stack.empty()) {\n      if (!pushed_empty_string) {\n        pushed_empty_string = true;\n        vcs_dirs_vector.push_back(&empty_string);\n      }\n      vcs_files[empty_string].push_back(&f);\n    } else {\n      vcs_files[*vcs_stack.back()].push_back(&f);\n    }\n  }\n\n  printf(\"{\\n\");\n  printf(\"  \\\"relevant_binaries\\\":[\\n\");\n  for (size_t i = 0; i < relevant_binary_names.size(); ++i) {\n    printf(\"    \\\"%s\\\"%s\\n\", json_escape(relevant_binary_names[i]).c_str(),\n           i == relevant_binary_names.size() - 1 ? \"\" : \",\");\n  }\n  printf(\"  ],\\n\");\n\n  printf(\"  \\\"loaded_elf_binaries\\\": [\\n\");\n  for (auto it = original_loaded_elf_names.begin(); it != original_loaded_elf_names.end(); ++it) {\n    printf(\"    \\\"%s\\\"%s\\n\",\n      json_escape(*it).c_str(),\n      std::next(it) == original_loaded_elf_names.end() ? \"\" : \",\");\n  }\n  printf(\"  ],\\n\");\n\n  printf(\"  \\\"comp_dir_substitutions\\\":{\\n\");\n  for (size_t i = 0; i < output_comp_dir_substitutions.size(); ++i) {\n    auto& sub = output_comp_dir_substitutions[i];\n    printf(\"    \\\"%s\\\": \\\"%s\\\"%s\\n\", json_escape(sub.trace_relative_name).c_str(),\n           json_escape(sub.substitution).c_str(),\n           i == output_comp_dir_substitutions.size() - 1 ? \"\" : \",\");\n  }\n  printf(\"  },\\n\");\n  printf(\"  \\\"external_debug_info\\\":[\\n\");\n  size_t index = 0;\n  for (auto& ext : external_debug_info) {\n    printf(\"    { \\\"path\\\":\\\"%s\\\", \\\"build_id\\\":\\\"%s\\\", \\\"type\\\":\\\"%s\\\" }%s\\n\",\n           json_escape(ext.path).c_str(),\n           json_escape(ext.build_id).c_str(),\n           json_escape(ext.type).c_str(),\n           index == external_debug_info.size() - 1 ? \"\" : \",\");\n    ++index;\n  }\n  printf(\"  ],\\n\");\n  printf(\"  \\\"dwos\\\":[\\n\");\n  index = 0;\n  for (auto& d : dwos) {\n    printf(\"    { \\\"name\\\":\\\"%s\\\", \\\"full_path\\\":\\\"%s\\\", \\\"build_id\\\":\\\"%s\\\", \\\"trace_file\\\":\\\"%s\\\", \",\n           json_escape(d.name).c_str(),\n           json_escape(d.full_path).c_str(),\n           json_escape(d.build_id).c_str(),\n           json_escape(d.trace_file).c_str());\n    if (!d.comp_dir.empty()) {\n      printf(\"\\\"comp_dir\\\":\\\"%s\\\", \", json_escape(d.comp_dir).c_str());\n    }\n    printf(\"\\\"id\\\":%llu }%s\\n\",\n           (unsigned long long)d.id,\n           index == dwos.size() - 1 ? \"\" : \",\");\n    ++index;\n  }\n  printf(\"  ],\\n\");\n  printf(\"  \\\"symlinks\\\":[\\n\");\n  for (size_t i = 0; i < symlinks.size(); ++i) {\n    auto& link = symlinks[i];\n    printf(\"    { \\\"from\\\":\\\"%s\\\", \\\"to\\\":\\\"%s\\\" }%s\\n\",\n           json_escape(link.from).c_str(),\n           json_escape(link.to).c_str(),\n           i == symlinks.size() - 1 ? \"\" : \",\");\n  }\n  printf(\"  ],\\n\");\n  printf(\"  \\\"files\\\":{\\n\");\n  for (size_t i = 0; i < vcs_dirs_vector.size(); ++i) {\n    auto& dir = *vcs_dirs_vector[i];\n    string path = json_escape(dir);\n    if (path.size() > 1) {\n      // Pop final '/'\n      path.pop_back();\n    }\n    printf(\"    \\\"%s\\\": [\\n\", path.c_str());\n    auto& files = vcs_files[dir];\n    for (size_t j = 0; j < files.size(); ++j) {\n      printf(\"      \\\"%s\\\"%s\\n\", json_escape(*files[j], dir.size()).c_str(),\n             j == files.size() - 1 ? \"\" : \",\");\n    }\n    printf(\"    ]%s\\n\", i == vcs_dirs_vector.size() - 1 ? \"\" : \",\");\n  }\n  printf(\"  }\\n\");\n  printf(\"}\\n\");\n\n  return 0;\n}\n\nstatic bool parse_sources_option(vector<string>& args, SourcesFlags& flags) {\n  if (parse_global_option(args)) {\n    return true;\n  }\n\n  static const OptionSpec options[] = {\n    { 0, \"substitute\", HAS_PARAMETER },\n    { 1, \"gdb-script\", HAS_PARAMETER }\n  };\n\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  switch (opt.short_name) {\n    case 0: {\n      auto pos = opt.value.find_first_of('=');\n      if (pos != string::npos) {\n        auto k = opt.value.substr(0, pos);\n        auto v = opt.value.substr(pos+1);\n        flags.comp_dir_substitutions.insert(std::pair<string, string>(k, v));\n      }\n      break;\n    }\n    case 1: {\n      flags.gdb_script = opt.value;\n      break;\n    }\n  }\n\n  return true;\n}\n\nint SourcesCommand::run(vector<string>& args) {\n  // Various \"cannot replay safely...\" warnings cannot affect us since\n  // we only replay to the first execve.\n  Flags::get_for_init().suppress_environment_warnings = true;\n\n  SourcesFlags flags;\n  while (parse_sources_option(args, flags)) {\n  }\n\n  // (Trace file name, original file name) pairs\n  string trace_dir;\n  if (!parse_optional_trace_dir(args, &trace_dir)) {\n    print_help(stderr);\n    return 1;\n  }\n\n  TraceReader trace(trace_dir);\n  DIR* files = opendir(trace.dir().c_str());\n  if (!files) {\n    FATAL() << \"Can't open trace dir\";\n  }\n  closedir(files);\n\n  map<string, string> binary_file_names;\n  while (true) {\n    TraceReader::MappedData data;\n    bool found;\n    KernelMapping km = trace.read_mapped_region(\n        &data, &found, TraceReader::VALIDATE, TraceReader::ANY_TIME);\n    if (!found) {\n      break;\n    }\n    if (data.source == TraceReader::SOURCE_FILE) {\n      binary_file_names.insert(make_pair(std::move(data.file_name), km.fsname()));\n    }\n  }\n\n  string program;\n  {\n    ReplaySession::Flags flags;\n    flags.redirect_stdio = false;\n    flags.share_private_mappings = false;\n    flags.replay_stops_at_first_execve = true;\n    flags.cpu_unbound = true;\n\n    ReplaySession::shr_ptr replay_session = ReplaySession::create(trace_dir, flags);\n    while (true) {\n      auto result = replay_session->replay_step(RUN_CONTINUE);\n      if (replay_session->done_initial_exec()) {\n        program = replay_session->vms()[0]->exe_image();\n        break;\n      }\n\n      if (result.status == REPLAY_EXITED) {\n        break;\n      }\n    }\n  }\n\n  std::vector<std::pair<string, string>> binary_file_names_ordered;\n  auto i = binary_file_names.find(program);\n  if (i != binary_file_names.end()) {\n    binary_file_names_ordered.push_back(*i);\n    binary_file_names.erase(program);\n  }\n  std::copy(binary_file_names.begin(), binary_file_names.end(), std::back_inserter(binary_file_names_ordered));\n  auto debug_dirs = make_unique<DebugDirManager>(program, flags.gdb_script);\n  return sources(binary_file_names_ordered, flags.comp_dir_substitutions, debug_dirs, false);\n}\n\nint ExplicitSourcesCommand::run(vector<string>& args) {\n  // Various \"cannot replay safely...\" warnings cannot affect us since\n  // we only replay to the first execve.\n  Flags::get_for_init().suppress_environment_warnings = true;\n\n  SourcesFlags flags;\n  while (parse_sources_option(args, flags)) {\n  }\n\n  // (Trace file name, original file name) pairs\n  map<string, string> binary_file_names;\n  for (auto arg : args) {\n    struct stat statbuf;\n    int ret = stat(arg.c_str(), &statbuf);\n    if (ret < 0) {\n      FATAL() << \"Failed to stat `\" << arg << \"`\";\n    }\n    if (!S_ISREG(statbuf.st_mode)) {\n      continue;\n    }\n\n    ScopedFd fd = ScopedFd(arg.c_str(), O_RDONLY, 0);\n    if (!fd.is_open()) {\n      LOG(error) << \"Failed to open `\" << arg << \"`\";\n      return 1;\n    }\n\n    ElfFileReader reader(fd);\n    auto buildid = reader.read_buildid();\n    if (buildid.empty()) {\n      LOG(warn) << \"No build-id for `\" << arg << \"`\";\n      continue;\n    }\n    binary_file_names.insert(make_pair(std::move(buildid), arg));\n  }\n\n  unique_ptr<DebugDirManager> debug_dirs;\n  return sources(binary_file_names, flags.comp_dir_substitutions, debug_dirs, true);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/StdioMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"StdioMonitor.h\"\n\n#include \"Flags.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"Session.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nnamespace rr {\n\nSwitchable StdioMonitor::will_write(Task* t) {\n  if (t->session().mark_stdio()) {\n    char buf[256];\n    snprintf(buf, sizeof(buf) - 1, \"[rr %d %\" PRId64 \"]\", t->tgid(), t->trace_time());\n    write_all(original_fd, buf, strlen(buf));\n  }\n\n  return PREVENT_SWITCH;\n}\n\nvoid StdioMonitor::did_write(Task* t, const std::vector<Range>& ranges,\n                             LazyOffset&) {\n  ReplaySession* replay_session = t->session().as_replay();\n  if (!replay_session || !replay_session->echo_stdio()) {\n    return;\n  }\n  for (auto& r : ranges) {\n    auto bytes = t->read_mem(r.data.cast<uint8_t>(), r.length);\n    write_all(original_fd, bytes.data(), bytes.size());\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/StdioMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_STDIO_MONITOR_H_\n#define RR_STDIO_MONITOR_H_\n\n#include \"FileMonitor.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor to track writes to rr's stdout/stderr fds.\n * StdioMonitor prevents syscallbuf from buffering output to those fds. It\n * adds the optional stdio markers. During replay, it echoes stdio writes.\n */\nclass StdioMonitor : public FileMonitor {\npublic:\n  /**\n   * Create a StdioMonitor that monitors writes to rr's original_fd\n   * (STDOUT_FILENO or STDERR_FILENO).\n   * Note that it's possible for a tracee to have a StdioMonitor associated\n   * with a different fd, thanks to dup() etc.\n   */\n  StdioMonitor(int original_fd) : original_fd(original_fd) {}\n\n  virtual Type type() override { return Stdio; }\n\n  /**\n   * Make writes to stdout/stderr blocking, to avoid nondeterminism in the\n   * order in which the kernel actually performs such writes.\n   * This theoretically introduces the possibility of deadlock between rr's\n   * tracee and some external program reading rr's output\n   * via a pipe ... but that seems unlikely to bite in practice.\n   *\n   * Also, if stdio-marking is enabled, prepend the stdio write with\n   * \"[rr <pid> <global-time>]\".  This allows users to more easily correlate\n   * stdio with trace event numbers.\n   */\n  virtual Switchable will_write(Task* t) override;\n\n  /**\n   * During replay, echo writes to stdout/stderr.\n   */\n  virtual void did_write(Task* t, const std::vector<Range>& ranges,\n                         LazyOffset&) override;\n\nprivate:\n  int original_fd;\n};\n\n} // namespace rr\n\n#endif /* RR_STDIO_MONITOR_H_ */\n"
  },
  {
    "path": "src/StringVectorToCharArray.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_STRING_VECTOR_TO_CHAR_ARRAY_H_\n#define RR_STRING_VECTOR_TO_CHAR_ARRAY_H_\n\n#include <string>\n#include <vector>\n\nnamespace rr {\n\n/**\n * Converts a vector of strings to a POSIX-style array of char*s terminated\n * by a nullptr.\n */\nclass StringVectorToCharArray {\npublic:\n  StringVectorToCharArray(const std::vector<std::string>& vs) {\n    for (auto& v : vs) {\n      array.push_back(const_cast<char*>(v.c_str()));\n    }\n    array.push_back(nullptr);\n  }\n  char** get() { return array.data(); }\n\nprivate:\n  std::vector<char*> array;\n};\n\n} // namespace rr\n\n#endif\n"
  },
  {
    "path": "src/SysCpuMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <sstream>\n\n#include \"SysCpuMonitor.h\"\n#include \"RecordTask.h\"\n#include \"RecordSession.h\"\n#include \"Scheduler.h\"\n\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nSysCpuMonitor::SysCpuMonitor(Task*, const string&) {\n}\n\nstatic string make_cpu_online_data(RecordTask* t) {\n  const cpu_set_t cpus = t->session().scheduler().pretend_affinity_mask();\n  int real_ncpus = sysconf(_SC_NPROCESSORS_CONF);\n  bool last_was_set = false;\n  std::stringstream result;\n  bool first = true;\n  for (int i = 0; i < real_ncpus; ++i) {\n    bool this_is_set = CPU_ISSET(i, &cpus);\n    if (this_is_set) {\n      if (!last_was_set) {\n        if (!first) {\n          result << \",\";\n        }\n        first = false;\n        result << i;\n      }\n      if (!CPU_ISSET(i+1, &cpus)) {\n        if (last_was_set) {\n          result << \"-\" << i;\n        }\n      }\n    }\n    last_was_set = this_is_set;\n  }\n  result << \"\\n\";\n  return result.str();\n}\n\nbool SysCpuMonitor::emulate_read(\n  RecordTask* t, const vector<Range>& ranges,\n  LazyOffset& lazy_offset, uint64_t* result) {\n  string data = make_cpu_online_data(t);\n  int64_t offset = lazy_offset.retrieve(false);\n  *result = t->write_ranges(ranges, (uint8_t*)data.data() + offset,\n    offset > (ssize_t)data.size() ? 0 : data.size() - offset);\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/SysCpuMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_SYS_CPU_MONITOR_H_\n#define RR_SYS_CPU_MONITOR_H_\n\n#include \"FileMonitor.h\"\n#include \"TaskishUid.h\"\n\nnamespace rr {\n\n/**\n * A FileMonitor to intercept /sys/devices/system/cpu/online (and potentially\n * other files in that directory in the future) in order to pretend to the\n * tracee that it only has the CPUs that rr is willing to give it\n */\nclass SysCpuMonitor : public FileMonitor {\npublic:\n  SysCpuMonitor(Task* t, const std::string& pathname);\n\n  virtual Type type() override { return SysCpu; }\n\n  bool emulate_read(RecordTask* t, const std::vector<Range>& ranges,\n                    LazyOffset&, uint64_t* result) override;\n};\n\n} // namespace rr\n\n#endif /* RR_SYS_CPU_MONITOR_H_ */\n"
  },
  {
    "path": "src/TargetDescription.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"TargetDescription.h\"\n\n#include <sstream>\n\n#include \"GdbServerConnection.h\"\n#include \"kernel_abi.h\"\n\nnamespace rr {\n\nclass FeatureStream {\npublic:\n  string result() { return stream.str(); }\n\n  template <typename Any>\n  friend FeatureStream& operator<<(FeatureStream& stream, Any any);\n\nprivate:\n  stringstream stream;\n  const char* arch_prefix;\n};\n\ntemplate <typename Any>\nFeatureStream& operator<<(FeatureStream& stream, Any any) {\n  stream.stream << any;\n  return stream;\n}\n\ntemplate <>\nFeatureStream& operator<<(FeatureStream& stream, rr::SupportedArch arch) {\n  stream << \"<architecture>\";\n  switch (arch) {\n    case rr::x86:\n      stream << \"i386\";\n      stream.arch_prefix = \"32bit-\";\n      break;\n    case rr::x86_64:\n      stream << \"i386:x86-64\";\n      stream.arch_prefix = \"64bit-\";\n      break;\n    case rr::aarch64:\n      stream << \"aarch64\";\n      stream.arch_prefix = \"aarch64-\";\n      break;\n  }\n  stream << \"</architecture>\\n\";\n  return stream;\n}\n\ntemplate <>\nFeatureStream& operator<<(FeatureStream& stream, TargetFeature feature) {\n  DEBUG_ASSERT(stream.arch_prefix != nullptr &&\n               \"No architecture has been provided to description\");\n  stream << R\"(  <xi:include href=\")\" << stream.arch_prefix;\n  switch (feature) {\n    case TargetFeature::Core:\n      stream << \"core.xml\";\n      break;\n    case TargetFeature::Linux:\n      stream << \"linux.xml\";\n      break;\n    case TargetFeature::SSE:\n      stream << \"sse.xml\";\n      break;\n    case TargetFeature::AVX:\n      stream << \"avx.xml\";\n      break;\n    case TargetFeature::AVX512:\n      stream << \"avx512.xml\";\n      break;\n    case TargetFeature::PKeys:\n      stream << \"pkeys.xml\";\n      break;\n    case TargetFeature::Segment:\n      stream << \"seg.xml\";\n      break;\n    case TargetFeature::FPU:\n      stream << \"fpu.xml\";\n      break;\n  }\n  stream << R\"(\"/>)\" << '\\n';\n  return stream;\n}\n\nTargetDescription::TargetDescription(rr::SupportedArch arch,\n                                     uint32_t cpu_features)\n    : arch(arch), target_features() {\n\n  // default-assumed registers per arch\n  switch (arch) {\n    case rr::x86:\n      target_features.push_back(TargetFeature::Core);\n      target_features.push_back(TargetFeature::SSE);\n      target_features.push_back(TargetFeature::Linux);\n      break;\n    case rr::x86_64:\n      target_features.push_back(TargetFeature::Core);\n      target_features.push_back(TargetFeature::SSE);\n      target_features.push_back(TargetFeature::Linux);\n      target_features.push_back(TargetFeature::Segment);\n      break;\n    case rr::aarch64:\n      target_features.push_back(TargetFeature::Core);\n      target_features.push_back(TargetFeature::FPU);\n      break;\n  }\n\n  if (cpu_features & rr::GdbServerConnection::CPU_AVX) {\n    DEBUG_ASSERT((arch == rr::x86 || arch == rr::x86_64) && \"unexpected arch\");\n    target_features.push_back(TargetFeature::AVX);\n  }\n\n  if (cpu_features & rr::GdbServerConnection::CPU_AVX512) {\n    DEBUG_ASSERT((arch == rr::x86 || arch == rr::x86_64) && \"unexpected arch\");\n    target_features.push_back(TargetFeature::AVX512);\n  }\n\n  if (cpu_features & rr::GdbServerConnection::CPU_PKU) {\n    DEBUG_ASSERT((arch == rr::x86 || arch == rr::x86_64) && \"unexpected arch\");\n    target_features.push_back(TargetFeature::PKeys);\n  }\n}\n\nstatic const char header[] = R\"(<?xml version=\"1.0\"?>\n<!DOCTYPE target SYSTEM \"gdb-target.dtd\">\n<target>\n)\";\n\nstring TargetDescription::to_xml() const {\n  FeatureStream fs;\n  fs << header << arch << \"<osabi>GNU/Linux</osabi>\\n\";\n  for (const auto feature : target_features) {\n    fs << feature;\n  }\n  fs << \"</target>\";\n\n  return fs.result();\n}\n} // namespace rr"
  },
  {
    "path": "src/TargetDescription.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TARGET_DESCRIPTION_H_\n#define RR_TARGET_DESCRIPTION_H_\n\n#include <cstdint>\n\n#include \"kernel_abi.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nenum class TargetFeature : uint32_t {\n  Core = 0,\n  SSE,\n  Linux,\n  Segment,\n  AVX,\n  AVX512,\n  PKeys,\n  FPU,\n};\n\nclass TargetDescription {\npublic:\n  explicit TargetDescription(rr::SupportedArch arch, uint32_t cpu_features);\n  string to_xml() const;\n\nprivate:\n  SupportedArch arch;\n  vector<TargetFeature> target_features;\n};\n} // namespace rr\n\n#endif /* RR_TARGET_DESCRIPTION_H_ */"
  },
  {
    "path": "src/Task.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <errno.h>\n#include <limits.h>\n#include <linux/capability.h>\n#include <linux/elf.h>\n#include <linux/ipc.h>\n#include <linux/net.h>\n#include <linux/perf_event.h>\n#include <linux/unistd.h>\n#include <math.h>\n#include <stdarg.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/personality.h>\n#include <sys/prctl.h>\n#include <sys/resource.h>\n#include <sys/socket.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/un.h>\n#include <sys/user.h>\n#include <sys/wait.h>\n#include <syscall.h>\n\n#include <limits>\n#include <set>\n#include <sstream>\n\n#include <rr/rr.h>\n\n#include \"Task.h\"\n\n#include \"preload/preload_interface.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"CPUIDBugDetector.h\"\n#include \"Flags.h\"\n#include \"MagicSaveDataMonitor.h\"\n#include \"PidFdMonitor.h\"\n#include \"PreserveFileMonitor.h\"\n#include \"ProcMemMonitor.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"ScopedFd.h\"\n#include \"StdioMonitor.h\"\n#include \"StringVectorToCharArray.h\"\n#include \"TraceeAttentionSet.h\"\n#include \"WaitManager.h\"\n#include \"cpp_supplement.h\"\n#include \"fast_forward.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"record_signal.h\"\n#include \"seccomp-bpf.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic const unsigned int NUM_X86_DEBUG_REGS = 8;\nstatic const unsigned int NUM_X86_WATCHPOINTS = 4;\n\nTask::Task(Session& session, pid_t _tid, pid_t _rec_tid, uint32_t serial,\n           SupportedArch a)\n    : scratch_ptr(),\n      scratch_size(),\n      // This will be initialized when the syscall buffer is.\n      desched_fd_child(-1),\n      // This will be initialized when the syscall buffer is.\n      cloned_file_data_fd_child(-1),\n      hpc(_tid, session.cpu_binding(), session.ticks_semantics(),\n          session.need_performance_counters() ? PerfCounters::ENABLE\n            : PerfCounters::DISABLE,\n          session.intel_pt_enabled() ? PerfCounters::PT_ENABLE\n            : PerfCounters::PT_DISABLE),\n      tid(_tid),\n      rec_tid(_rec_tid > 0 ? _rec_tid : _tid),\n      own_namespace_rec_tid(_rec_tid > 0 ? _rec_tid: _tid),\n      syscallbuf_size(0),\n      ticks_at_last_syscall_entry(0),\n      ip_at_last_syscall_entry(nullptr),\n      last_syscall_entry_recorded(false),\n      serial(serial),\n      ticks(0),\n      registers(a),\n      how_last_execution_resumed(RESUME_CONT),\n      last_resume_orig_cx(0),\n      did_set_breakpoint_after_cpuid(false),\n      is_stopped_(false),\n      in_unexpected_exit(false),\n      in_injectable_signal_stop_(false),\n      seccomp_bpf_enabled(false),\n      registers_dirty(false),\n      orig_syscallno_dirty(false),\n      extra_registers(a),\n      extra_registers_known(false),\n      session_(&session),\n      top_of_stack(),\n      seen_ptrace_exit_event_(false),\n      handled_ptrace_exit_event_(false),\n      expecting_ptrace_interrupt_stop(0),\n      was_reaped_(false),\n      forgotten(false) {\n  memset(&thread_locals, 0, sizeof(thread_locals));\n}\n\nReplayTask* Task::as_replay() {\n  if (session().is_replaying() || session().is_diversion()) {\n    return static_cast<ReplayTask*>(this);\n  }\n  return nullptr;\n}\n\nvoid Task::detach() {\n  LOG(debug) << \"detaching from Task \" << tid << \" (rec:\" << rec_tid << \")\";\n\n  fallible_ptrace(PTRACE_DETACH, nullptr, nullptr);\n\n  // Not really, but there's also no reason to actually try to reap it,\n  // since we detached.\n  was_reaped_ = true;\n}\n\nvoid Task::reenable_cpuid_tsc() {\n  AutoRemoteSyscalls remote(this);\n  if (is_x86ish(arch())) {\n    if (session().has_cpuid_faulting()) {\n      remote.infallible_syscall(syscall_number_for_arch_prctl(arch()),\n                            ARCH_SET_CPUID, 1);\n    }\n    remote.infallible_syscall(syscall_number_for_prctl(arch()),\n                          PR_SET_TSC, PR_TSC_ENABLE);\n  }\n  if (arch() == aarch64) {\n    // Not infallible because the prctl is only available in 6.12+.\n    // We already warned about this in post_exec_syscall().\n    remote.syscall(syscall_number_for_prctl(arch()),\n                   PR_SET_TSC, PR_TSC_ENABLE);\n  }\n}\n\nvoid Task::wait_exit() {\n  LOG(debug) << \"Waiting for exit of \" << tid;\n  /* We want to wait for the child to exit, but we don't actually\n   * want to reap the task when it's dead. We could use WEXITED | WNOWAIT,\n   * but that would hang if `t` is a thread-group-leader of a thread group\n   * that has other still-running threads. Instead, we wait for WSTOPPED, but\n   * we know that there is no possibility for the task to stop between now and\n   * its exit, at which point the system call will return with -ECHILD.\n   * There is one exception: If there was a simultaneous exec from another\n   * thread, and this is the group leader, then this task may lose its pid\n   * as soon as it enters the zombie state, causing `tid` to refer to the\n   * newly-execed thread and us getting a PTRACE_EVENT_EXEC instead. To account\n   * for this we add `| WNOWAIT` (via consume=false) to prevent dequeuing the\n   * event and simply take it as an indication that the task has execed.\n   */\n  WaitOptions options(tid);\n  options.consume = false;\n  do {\n    WaitResult result = WaitManager::wait_stop(options);\n    if (result.code == WAIT_OK) {\n      if (result.status.ptrace_event() == PTRACE_EVENT_EXIT) {\n        // It's possible that we're only now catching up to the real process exit.\n        // (E.g. when a RecordTask for a detached proxy is destroyed because the\n        // detached task exited.)\n        // In that case, just ask the process to actually exit.\n        // Consume this status now, otherwise proceed_to_exit() will call\n        // back here and we won't fetch the new status.\n        options.consume = true;\n        result = WaitManager::wait_stop(options);\n        ASSERT(this, result.status.ptrace_event() == PTRACE_EVENT_EXIT);\n        return proceed_to_exit();\n      }\n      ASSERT(this, result.status.ptrace_event() == PTRACE_EVENT_EXEC)\n        << \"Expected PTRACE_EVENT_EXEC, got \" << result.status;\n      // The kernel will do the reaping for us in this case\n      was_reaped_ = true;\n    } else if (result.code == WAIT_NO_STATUS) {\n      // Wait was EINTR'd most likely - retry.\n      continue;\n    } else {\n      ASSERT(this, result.code == WAIT_NO_CHILD);\n    }\n  } while (false);\n}\n\nvoid Task::proceed_to_exit(bool wait) {\n  LOG(debug) << \"Advancing tid \" << tid << \" to exit; wait=\" << wait;\n  int ret = fallible_ptrace(PTRACE_CONT, nullptr, nullptr);\n  ASSERT(this, ret == 0 || (ret == -1 && errno == ESRCH))\n    << \"Got ret=\" << ret << \" errno=\" << errno;\n  if (wait) {\n    wait_exit();\n  }\n}\n\nWaitStatus Task::kill() {\n  if (was_reaped()) {\n    return this->status();\n  }\n  /* This call is racy. There is basically three situations:\n  * 1. By the time the kernel gets around to delivering this signal,\n  *    we were already in a PTRACE_EVENT_EXIT stop (e.g. due to an earlier\n  *    fatal signal or group exit from a sibling task that the kernel\n  *    didn't report to us yet), that we didn't observe yet (if we had, we\n  *    would have removed the task from the task map already). In this case,\n  *    this signal will advance from the PTRACE_EVENT_EXIT and put the child\n  *    into hidden-zombie state, which the waitpid below will reap.\n  * 2. The task was in a coredump wait. This situation essentially works the\n  *    same as 1, but the final exit status will be some other fatal signal.\n  * 3. Anything else basically. The signal will take priority and put us\n  *    into the PTRACE_EVENT_EXIT stop, which the subsequent waitpid will\n  *    then observe.\n  */\n  LOG(debug) << \"Sending SIGKILL to \" << tid;\n  int ret = syscall(SYS_tgkill, real_tgid(), tid, SIGKILL);\n  ASSERT(this, ret == 0);\n  WaitResult result;\n  bool is_exit_event;\n  do {\n    result = WaitManager::wait_stop_or_exit(WaitOptions(tid));\n    ASSERT(this, result.code == WAIT_OK);\n    LOG(debug) << \" -> \" << result.status;\n    is_exit_event = result.status.ptrace_event() == PTRACE_EVENT_EXIT;\n    // Loop until we get a suitable event; there could be a cached stop\n    // notification.\n  } while (!(is_exit_event || result.status.type() == WaitStatus::FATAL_SIGNAL ||\n             result.status.type() == WaitStatus::EXIT));\n  did_kill();\n  WaitStatus status = result.status;\n  if (is_exit_event) {\n    /* If this is the exit event, we can detach here and the task will\n      * continue to zombie state for its parent to reap. If we're not in\n      * the exit event, we already reaped it from the ptrace perspective,\n      * which implicitly detached.\n      */\n    unsigned long long_status;\n    if (ptrace_if_stopped(PTRACE_GETEVENTMSG, nullptr, &long_status)) {\n      status = WaitStatus(long_status);\n    } else {\n      // The task has been killed due to SIGKILL or equivalent.\n      status = WaitStatus::for_fatal_sig(SIGKILL);\n    }\n    int ret = fallible_ptrace(PTRACE_DETACH, nullptr, nullptr);\n    DEBUG_ASSERT(ret == 0 || (ret == -1 && errno == ESRCH));\n    if (ret == -1) {\n      /* It's possible for the above ptrace to fail with ESRCH. How?\n      * It's the other side of the race described above. If an external\n      * process issues an additional SIGKILL, we will advance from the\n      * ptrace exit event and we might still be processing the exit, just\n      * as the detach request comes in. To address this, we waitpid again,\n      * which will reap/detach us from ptrace and frees the real parent to\n      * do its reaping. */\n      result = WaitManager::wait_exit(WaitOptions(tid));\n      ASSERT(this, result.code == WAIT_OK);\n      LOG(debug) << \" --> \" << result.status;\n      ASSERT(this, result.status.fatal_sig() == SIGKILL);\n      status = result.status;\n    }\n  } else {\n    was_reaped_ = true;\n  }\n  return status;\n}\n\nTask::~Task() {\n  if (!forgotten) {\n    ASSERT(this, handled_ptrace_exit_event_);\n    ASSERT(this, syscallbuf_child.is_null());\n\n    if (!session().is_recording() && !was_reaped()) {\n      // Reap the zombie.\n      WaitResult result = WaitManager::wait_exit(WaitOptions(tid));\n      ASSERT(this, result.code == WAIT_OK || result.code == WAIT_NO_CHILD);\n    }\n\n    LOG(debug) << \"  dead\";\n  }\n\n  session().on_destroy(this);\n  tg->erase_task(this);\n  as->erase_task(this);\n  fds->erase_task(this);\n}\n\nvoid Task::forget() {\n  forgotten = true;\n}\n\nvoid Task::finish_emulated_syscall() {\n  // XXX verify that this can't be interrupted by a breakpoint trap\n  Registers r = regs();\n\n  // Passing RESUME_NO_TICKS here is not only a small performance optimization,\n  // but also avoids counting an event if the instruction immediately following\n  // a syscall instruction is a conditional branch.\n  bool ok = resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS);\n  ASSERT(this, ok) << \"Tracee exited unexpectedly\";\n\n  set_regs(r);\n  wait_status = WaitStatus();\n}\n\nstring Task::name() const {\n  char buf[1024];\n  sprintf(buf, \"/proc/%d/comm\", tid);\n  ScopedFd comm(buf, O_RDONLY);\n  if (!comm.is_open()) {\n    return \"???\";\n  }\n  ssize_t bytes = read(comm, buf, sizeof(buf) - 1);\n  ASSERT(this, bytes >= 0);\n  if (bytes > 0 && buf[bytes - 1] == '\\n') {\n    --bytes;\n  }\n  return string(buf, bytes);\n}\n\nvoid Task::set_name(AutoRemoteSyscalls& remote, const std::string& name) {\n  ASSERT(this, this == remote.task());\n  char prname[17];\n  strncpy(prname, name.c_str(), sizeof(prname));\n  prname[16] = 0;\n  AutoRestoreMem remote_prname(remote, (const uint8_t*)prname, 16);\n  LOG(debug) << \"    setting name to \" << prname;\n  remote.infallible_syscall(syscall_number_for_prctl(remote.arch()), PR_SET_NAME,\n                            remote_prname.get().as_int());\n}\n\nvoid Task::dump(FILE* out) const {\n  out = out ? out : stderr;\n  stringstream ss;\n  ss << wait_status;\n  fprintf(out, \"  %s(tid:%d rec_tid:%d status:0x%s)<%p>\\n\", name().c_str(),\n          tid, rec_tid, ss.str().c_str(), this);\n  if (session().is_recording()) {\n    // TODO pending events are currently only meaningful\n    // during recording.  We should change that\n    // eventually, to have more informative output.\n    log_pending_events();\n  }\n}\n\nstd::string Task::proc_fd_path(int fd) {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/fd/%d\", tid, fd);\n  return path;\n}\n\nstd::string Task::proc_pagemap_path() {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/pagemap\", tid);\n  return path;\n}\n\nstd::string Task::proc_stat_path() {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/stat\", tid);\n  return path;\n}\n\nstd::string Task::proc_exe_path() {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/exe\", tid);\n  return path;\n}\n\nstd::string Task::exe_path() {\n  char proc_exe[PATH_MAX];\n  snprintf(proc_exe, sizeof(proc_exe), \"/proc/%d/exe\", tid);\n  char exe[PATH_MAX];\n  ssize_t ret = readlink(proc_exe, exe, sizeof(exe) - 1);\n  ASSERT(this, ret >= 0);\n  exe[ret] = 0;\n  return exe;\n}\n\nstruct stat Task::stat_fd(int fd) {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/fd/%d\", tid, fd);\n  struct stat result;\n  auto ret = ::stat(path, &result);\n  ASSERT(this, ret == 0);\n  return result;\n}\n\nstruct stat Task::lstat_fd(int fd) {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/fd/%d\", tid, fd);\n  struct stat result;\n  auto ret = ::lstat(path, &result);\n  ASSERT(this, ret == 0);\n  return result;\n}\n\nScopedFd Task::open_fd(int fd, int flags) {\n  char path[PATH_MAX];\n  snprintf(path, sizeof(path) - 1, \"/proc/%d/fd/%d\", tid, fd);\n  return ScopedFd(path, flags);\n}\n\nstring Task::file_name_of_fd(int fd) {\n  char path[PATH_MAX];\n  char procfd[40];\n  snprintf(procfd, sizeof(procfd) - 1, \"/proc/%d/fd/%d\", tid, fd);\n  ssize_t nbytes = readlink(procfd, path, sizeof(path) - 1);\n  if (nbytes < 0) {\n    path[0] = 0;\n  } else {\n    path[nbytes] = 0;\n  }\n  return path;\n}\n\npid_t Task::get_ptrace_eventmsg_pid() {\n  unsigned long msg = 0;\n  if (!ptrace_if_stopped(PTRACE_GETEVENTMSG, nullptr, &msg)) {\n    return -1;\n  }\n  return msg;\n}\n\nconst siginfo_t& Task::get_siginfo() {\n  DEBUG_ASSERT(stop_sig());\n  return pending_siginfo;\n}\n\n/**\n * Must be idempotent.\n */\nvoid Task::destroy_buffers(Task *as_task, Task *fd_task) {\n  auto saved_syscallbuf_child = syscallbuf_child;\n  // Clear syscallbuf_child now so nothing tries to use it while tearing\n  // down buffers.\n  syscallbuf_child = nullptr;\n  if (as_task != nullptr) {\n    AutoRemoteSyscalls remote(as_task);\n    as_task->unmap_buffers_for(remote, this, saved_syscallbuf_child);\n    if (as_task == fd_task) {\n      as_task->close_buffers_for(remote, this, true);\n    }\n    goto done;\n  }\n  if (fd_task != nullptr) {\n    AutoRemoteSyscalls remote(fd_task);\n    fd_task->close_buffers_for(remote, this, true);\n  }\ndone:\n  scratch_ptr = nullptr;\n  desched_fd_child = -1;\n  cloned_file_data_fd_child = -1;\n}\n\nvoid Task::unmap_buffers_for(\n    AutoRemoteSyscalls& remote, Task* other,\n    remote_ptr<struct syscallbuf_hdr> saved_syscallbuf_child) {\n  if (other->scratch_ptr) {\n    if (remote.infallible_munmap_syscall_if_alive(\n          other->scratch_ptr, other->scratch_size)) {\n      vm()->unmap(this, other->scratch_ptr, other->scratch_size);\n    }\n  }\n  if (!saved_syscallbuf_child.is_null()) {\n    if (remote.infallible_munmap_syscall_if_alive(\n          saved_syscallbuf_child, other->syscallbuf_size)) {\n      vm()->unmap(this, saved_syscallbuf_child, other->syscallbuf_size);\n    }\n  }\n}\n\nvoid Task::did_kill()\n{\n  /* We may or may not have seen this event (see the note on race conditions\n   * in Session.cc), but let's pretend that we did to make this task look like\n   * other that we didn't kill ourselves\n   */\n  seen_ptrace_exit_event_ = true;\n  handled_ptrace_exit_event_ = true;\n  syscallbuf_child = nullptr;\n  /* No need to unmap/close things in the child here - the kernel did that for\n   * us when the child died. */\n  scratch_ptr = nullptr;\n  desched_fd_child = -1;\n  cloned_file_data_fd_child = -1;\n}\n\n/**\n * Must be idempotent.\n */\nvoid Task::close_buffers_for(AutoRemoteSyscalls& remote, Task* other, bool really_close) {\n  if (other->desched_fd_child >= 0) {\n    if (session().is_recording() && really_close) {\n      remote.infallible_close_syscall_if_alive(other->desched_fd_child);\n    }\n    fds->did_close(other->desched_fd_child);\n  }\n  if (other->cloned_file_data_fd_child >= 0) {\n    if (really_close) {\n      remote.infallible_close_syscall_if_alive(other->cloned_file_data_fd_child);\n    }\n    fds->did_close(other->cloned_file_data_fd_child);\n  }\n}\n\nvoid Task::emulate_jump(remote_code_ptr ip) {\n  Registers r = regs();\n  r.set_ip(ip);\n  set_regs(r);\n  ticks += PerfCounters::ticks_for_unconditional_indirect_branch(this);\n}\n\nbool Task::is_desched_event_syscall() {\n  return is_ioctl_syscall(regs().original_syscallno(), arch()) &&\n         desched_fd_child != -1 &&\n         desched_fd_child == (int)regs().arg1_signed();\n}\n\nbool Task::is_ptrace_seccomp_event() const {\n  int event = ptrace_event();\n  return (PTRACE_EVENT_SECCOMP_OBSOLETE == event ||\n          PTRACE_EVENT_SECCOMP == event);\n}\n\ntemplate <typename Arch>\nstatic vector<uint8_t> ptrace_get_regs_set(Task* t, const Registers& regs,\n                                           size_t min_size) {\n  auto iov = t->read_mem(remote_ptr<typename Arch::iovec>(regs.arg4()));\n  ASSERT(t, iov.iov_len >= min_size)\n      << \"Should have been caught during prepare_ptrace\";\n  return t->read_mem(iov.iov_base.rptr().template cast<uint8_t>(), iov.iov_len);\n}\n\nstatic void process_shmdt(Task* t, remote_ptr<void> addr) {\n  size_t size = t->vm()->get_shm_size(addr);\n  t->vm()->remove_shm_size(addr);\n  t->vm()->unmap(t, addr, size);\n}\n\ntemplate <typename Arch>\nstatic void ptrace_syscall_exit_legacy_arch(Task* t, Task* tracee, const Registers& regs)\n{\n  switch ((int)regs.orig_arg1_signed()) {\n    case Arch::PTRACE_SETREGS: {\n      auto data = t->read_mem(\n          remote_ptr<typename Arch::user_regs_struct>(regs.arg4()));\n      Registers r = tracee->regs();\n      r.set_from_ptrace_for_arch(Arch::arch(), &data, sizeof(data));\n      tracee->set_regs(r);\n      break;\n    }\n    case Arch::PTRACE_SETFPREGS: {\n      auto data = t->read_mem(\n          remote_ptr<typename Arch::user_fpregs_struct>(regs.arg4()));\n      if (auto r_ptr = tracee->extra_regs_fallible()) {\n        ExtraRegisters r = *r_ptr;\n        r.set_user_fpregs_struct(t, Arch::arch(), &data, sizeof(data));\n        tracee->set_extra_regs(r);\n      }\n      break;\n    }\n    case Arch::PTRACE_SETFPXREGS: {\n      auto data =\n          t->read_mem(remote_ptr<X86Arch::user_fpxregs_struct>(regs.arg4()));\n      if (auto r_ptr = tracee->extra_regs_fallible()) {\n        ExtraRegisters r = *r_ptr;\n        r.set_user_fpxregs_struct(t, data);\n        tracee->set_extra_regs(r);\n      }\n      break;\n    }\n    case Arch::PTRACE_POKEUSR: {\n      size_t addr = regs.arg3();\n      typename Arch::unsigned_word data = regs.arg4();\n      if (addr < sizeof(typename Arch::user_regs_struct)) {\n        Registers r = tracee->regs();\n        r.write_register_by_user_offset(addr, data);\n        tracee->set_regs(r);\n      } else if (addr >= offsetof(typename Arch::user, u_debugreg[0]) &&\n                  addr < offsetof(typename Arch::user, u_debugreg[8])) {\n        size_t regno =\n            (addr - offsetof(typename Arch::user, u_debugreg[0])) /\n            sizeof(data);\n        tracee->set_x86_debug_reg(regno, data);\n      }\n      break;\n    }\n    default:\n      break;\n  }\n}\n\ntemplate <>\nvoid ptrace_syscall_exit_legacy_arch<ARM64Arch>(Task*, Task*, const Registers&)\n{\n  // Nothing to do - unimplemented on this architecture\n  return;\n}\n\ntemplate <typename Arch>\nvoid Task::on_syscall_exit_arch(int syscallno, const Registers& regs) {\n  session().accumulate_syscall_performed();\n\n  if (regs.original_syscallno() == SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO) {\n    return;\n  }\n\n  if (syscallno == session_->syscall_number_for_rrcall_mprotect_record()) {\n    // When we record an rr replay of a tracee which does a syscallbuf'ed\n    // `mprotect`, neither the replay nor its recording see the mprotect\n    // syscall, since it's untraced during both recording and replay. rr\n    // replay is notified of the syscall via the `mprotect_records`\n    // mechanism; if it's being recorded, it forwards that notification to\n    // the recorder by calling this syscall.\n    pid_t tid = regs.orig_arg1();\n    remote_ptr<void> addr = regs.arg2();\n    size_t num_bytes = regs.arg3();\n    int prot = regs.arg4_signed();\n    Task* t = session().find_task(tid);\n    ASSERT(this, t);\n    return t->vm()->protect(t, addr, num_bytes, prot);\n  }\n\n  // mprotect can change the protection status of some mapped regions before\n  // failing.\n  // SYS_rrcall_mprotect_record always fails with ENOSYS, though we want to\n  // note its usage here.\n  if (regs.syscall_failed() && !is_mprotect_syscall(syscallno, regs.arch())\n      && !is_pkey_mprotect_syscall(syscallno, regs.arch())\n      && !is_prctl_syscall(syscallno, regs.arch())) {\n    return;\n  }\n\n  switch (syscallno) {\n    case Arch::brk:\n    case Arch::mmap:\n    case Arch::mmap2:\n    case Arch::mremap: {\n      LOG(debug) << \"(brk/mmap/mmap2/mremap will receive / has received direct \"\n                    \"processing)\";\n      return;\n    }\n\n    case Arch::pkey_mprotect:\n    case Arch::mprotect: {\n      remote_ptr<void> addr = regs.orig_arg1();\n      size_t num_bytes = regs.arg2();\n      int prot = regs.arg3_signed();\n      return vm()->protect(this, addr, num_bytes, prot);\n    }\n    case Arch::munmap: {\n      remote_ptr<void> addr = regs.orig_arg1();\n      size_t num_bytes = regs.arg2();\n      return vm()->unmap(this, addr, num_bytes);\n    }\n    case Arch::shmdt:\n      return process_shmdt(this, regs.orig_arg1());\n    case Arch::madvise: {\n      remote_ptr<void> addr = regs.orig_arg1();\n      size_t num_bytes = regs.arg2();\n      int advice = regs.arg3();\n      return vm()->advise(this, addr, num_bytes, advice);\n    }\n    case Arch::ipc: {\n      switch ((int)regs.orig_arg1_signed()) {\n        case SHMDT:\n          return process_shmdt(this, regs.arg5());\n        default:\n          break;\n      }\n      break;\n    }\n\n    case Arch::set_thread_area:\n      set_thread_area(regs.orig_arg1());\n      return;\n\n    case Arch::prctl:\n      switch ((int)regs.orig_arg1_signed()) {\n        case PR_SET_SECCOMP:\n          if (regs.syscall_failed()) {\n            return;\n          }\n          if (regs.arg2() == SECCOMP_MODE_FILTER && session().is_recording()) {\n            seccomp_bpf_enabled = true;\n          }\n          break;\n        case PR_SET_NAME:\n          if (regs.syscall_failed()) {\n            return;\n          }\n          did_prctl_set_prname(regs.arg2());\n          break;\n        case PR_SET_VMA: {\n          switch ((unsigned long)regs.arg2()) {\n            case PR_SET_VMA_ANON_NAME: {\n              if (regs.syscall_failed() &&\n                  regs.syscall_result_signed() != -ENOMEM &&\n                  regs.syscall_result_signed() != -EBADF) {\n                return;\n              }\n              remote_ptr<void> start = regs.arg3();\n              size_t size = regs.arg4();\n              remote_ptr<char> name_ptr = regs.arg5();\n              if (!name_ptr.is_null()) {\n                string name = read_c_str(name_ptr);\n                vm()->set_anon_name(this, MemoryRange(start, size), &name);\n              } else {\n                vm()->set_anon_name(this, MemoryRange(start, size), nullptr);\n              }\n              break;\n            }\n            default:\n              break;\n          }\n          break;\n        }\n      }\n      return;\n\n    case Arch::dup:\n    case Arch::dup2:\n    case Arch::dup3:\n      fd_table()->did_dup(regs.orig_arg1(), regs.syscall_result());\n      return;\n    case Arch::fcntl64:\n    case Arch::fcntl:\n      if (regs.arg2() == Arch::DUPFD || regs.arg2() == Arch::DUPFD_CLOEXEC) {\n        fd_table()->did_dup(regs.orig_arg1(), regs.syscall_result());\n      }\n      return;\n    case Arch::close:\n      fd_table()->did_close(regs.orig_arg1());\n      return;\n\n    case Arch::unshare:\n      if (regs.orig_arg1() & CLONE_FILES) {\n        fds->erase_task(this);\n        fds = fds->clone();\n        fds->insert_task(this);\n        vm()->fd_tables_changed();\n      }\n      return;\n\n    case Arch::pwrite64:\n    case Arch::write: {\n      int fd = (int)regs.orig_arg1_signed();\n      vector<FileMonitor::Range> ranges;\n      ssize_t amount = regs.syscall_result_signed();\n      if (amount > 0) {\n        ranges.push_back(FileMonitor::Range(regs.arg2(), amount));\n      }\n      FileMonitor::LazyOffset offset(this, regs, syscallno);\n      fd_table()->did_write(this, fd, ranges, offset);\n      return;\n    }\n\n    case Arch::pwritev:\n    case Arch::writev: {\n      int fd = (int)regs.orig_arg1_signed();\n      vector<FileMonitor::Range> ranges;\n      auto iovecs =\n          read_mem(remote_ptr<typename Arch::iovec>(regs.arg2()), regs.arg3());\n      ssize_t written = regs.syscall_result_signed();\n      ASSERT(this, written >= 0);\n      for (auto& v : iovecs) {\n        ssize_t amount = min<ssize_t>(written, v.iov_len);\n        if (amount > 0) {\n          ranges.push_back(FileMonitor::Range(v.iov_base, amount));\n          written -= amount;\n        }\n      }\n      FileMonitor::LazyOffset offset(this, regs, syscallno);\n      fd_table()->did_write(this, fd, ranges, offset);\n      return;\n    }\n\n    case Arch::ptrace: {\n      pid_t pid = (pid_t)regs.arg2_signed();\n      Task* tracee = session().find_task(pid);\n      switch ((int)regs.orig_arg1_signed()) {\n        case PTRACE_SETREGSET: {\n          switch ((int)regs.arg3()) {\n            case NT_PRSTATUS: {\n              auto set = ptrace_get_regs_set<Arch>(\n                  this, regs, user_regs_struct_size(tracee->arch()));\n              Registers r = tracee->regs();\n              r.set_from_ptrace_for_arch(tracee->arch(), set.data(), set.size());\n              tracee->set_regs(r);\n              break;\n            }\n            case NT_PRFPREG: {\n              auto set = ptrace_get_regs_set<Arch>(\n                  this, regs, user_fpregs_struct_size(tracee->arch()));\n              if (auto r_ptr = tracee->extra_regs_fallible()) {\n                ExtraRegisters r = *r_ptr;\n                r.set_user_fpregs_struct(this, tracee->arch(), set.data(),\n                                         set.size());\n                tracee->set_extra_regs(r);\n              }\n              break;\n            }\n            case NT_ARM_SYSTEM_CALL: {\n              auto set = ptrace_get_regs_set<Arch>(\n                  this, regs, sizeof(int));\n              ASSERT(this, set.size() >= sizeof(int));\n              int new_syscallno = *(int*)set.data();\n              Registers r = tracee->regs();\n              r.set_original_syscallno(new_syscallno);\n              tracee->set_regs(r);\n              break;\n            }\n            case NT_ARM_HW_WATCH:\n            case NT_ARM_HW_BREAK: {\n              auto set = ptrace_get_regs_set<Arch>(\n                  this, regs, offsetof(ARM64Arch::user_hwdebug_state, dbg_regs[0]));\n              ASSERT(this, set.size() >= sizeof(int));\n              tracee->set_aarch64_debug_regs((int)regs.arg3(),\n                (ARM64Arch::user_hwdebug_state*)set.data(),\n                (set.size() - offsetof(ARM64Arch::user_hwdebug_state, dbg_regs[0]))/\n                  2*sizeof(ARM64Arch::hw_bp));\n              break;\n            }\n            case NT_X86_XSTATE: {\n              if (auto extra_regs = tracee->extra_regs_fallible()) {\n                switch (extra_regs->format()) {\n                  case ExtraRegisters::XSAVE: {\n                    XSaveLayout layout;\n                    ReplaySession* replay = session().as_replay();\n                    if (replay) {\n                      layout = xsave_layout_from_trace(\n                          replay->trace_reader().cpuid_records());\n                    } else {\n                      layout = xsave_native_layout();\n                    }\n                    auto set = ptrace_get_regs_set<Arch>(this, regs, layout.full_size);\n                    ExtraRegisters r;\n                    bool ok =\n                        r.set_to_raw_data(tracee->arch(), ExtraRegisters::XSAVE,\n                                          set.data(), set.size(), layout);\n                    ASSERT(this, ok) << \"Invalid XSAVE data\";\n                    tracee->set_extra_regs(r);\n                    break;\n                  }\n                  default:\n                    ASSERT(this, false) << \"Unknown ExtraRegisters format; \"\n                                           \"Should have been caught during \"\n                                           \"prepare_ptrace\";\n                }\n              }\n              break;\n            }\n            default:\n              ASSERT(this, false) << \"Unknown regset type; Should have been \"\n                                     \"caught during prepare_ptrace\";\n              break;\n          }\n          break;\n        }\n        case Arch::PTRACE_ARCH_PRCTL: {\n          if (tracee->arch() != x86_64) {\n            break;\n          }\n          int code = (int)regs.arg4();\n          switch (code) {\n            case ARCH_GET_FS:\n            case ARCH_GET_GS:\n              break;\n            case ARCH_SET_FS:\n            case ARCH_SET_GS: {\n              Registers r = tracee->regs();\n              if (regs.arg3() == 0) {\n                // Work around a kernel bug in pre-4.7 kernels, where setting\n                // the gs/fs base to 0 via PTRACE_REGSET did not work correctly.\n                // If this fails the tracee is on the exit path and it\n                // doesn't matter what its fs/gs base is.\n                tracee->ptrace_if_stopped(Arch::PTRACE_ARCH_PRCTL, regs.arg3(),\n                                        (void*)(uintptr_t)regs.arg4());\n              }\n              if (code == ARCH_SET_FS) {\n                r.set_fs_base(regs.arg3());\n              } else {\n                r.set_gs_base(regs.arg3());\n              }\n              tracee->set_regs(r);\n              break;\n            }\n            default:\n              ASSERT(tracee, 0) << \"Should have detected this earlier\";\n          }\n          break;\n        }\n        case Arch::PTRACE_SETREGS:\n        case Arch::PTRACE_SETFPREGS:\n        case Arch::PTRACE_SETFPXREGS:\n        case Arch::PTRACE_POKEUSR: {\n          ptrace_syscall_exit_legacy_arch<Arch>(this, tracee, regs);\n        }\n      }\n      return;\n    }\n    case Arch::pidfd_open: {\n      int fd = regs.syscall_result();\n      pid_t pid = (pid_t)regs.orig_arg1();\n      TaskUid tuid;\n      if (Task* t = session().find_task(pid)) {\n        tuid = t->tuid();\n      }\n      fd_table()->add_monitor(this, fd, new PidFdMonitor(tuid));\n      return;\n    }\n    case Arch::pidfd_getfd: {\n      int pidfd = regs.orig_arg1();\n      int fd = regs.arg2();\n      if (PidFdMonitor* monitor = PidFdMonitor::get(fd_table().get(), pidfd)) {\n        // NB: This can return NULL if the pidfd is for a process outside of\n        // the rr trace.\n        if (auto source = monitor->fd_table(session())) {\n          fd_table()->did_dup(source.get(), fd, regs.syscall_result());\n        }\n      } else {\n        LOG(warn) << \"pidfd_getfd succeeded but we lost track of the pidfd \" << pidfd;\n      }\n      return;\n    }\n  }\n}\n\nvoid Task::on_syscall_exit(int syscallno, SupportedArch arch,\n                           const Registers& regs) {\n  with_converted_registers<void>(regs, arch, [&](const Registers& regs) {\n    RR_ARCH_FUNCTION(on_syscall_exit_arch, arch, syscallno, regs);\n  });\n}\n\nvoid Task::move_ip_before_breakpoint() {\n  // TODO: assert that this is at a breakpoint trap.\n  Registers r = regs();\n  r.set_ip(r.ip().undo_executed_bkpt(arch()));\n  set_regs(r);\n}\n\nbool Task::enter_syscall(SupportedArch syscall_arch, bool allow_exit) {\n  bool need_ptrace_syscall_event = !seccomp_bpf_enabled ||\n                                   session().syscall_seccomp_ordering() ==\n                                       Session::SECCOMP_BEFORE_PTRACE_SYSCALL;\n  bool need_seccomp_event = seccomp_bpf_enabled;\n  while (need_ptrace_syscall_event || need_seccomp_event) {\n    if (!resume_execution(need_ptrace_syscall_event ? RESUME_SYSCALL : RESUME_CONT,\n                          RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n      return false;\n    }\n    if (is_ptrace_seccomp_event()) {\n      ASSERT(this, need_seccomp_event);\n      need_seccomp_event = false;\n      continue;\n    }\n    if (allow_exit && ptrace_event() == PTRACE_EVENT_EXIT) {\n      return false;\n    }\n    ASSERT(this, !ptrace_event());\n    if (session().is_recording() && wait_status.group_stop()) {\n      static_cast<RecordTask*>(this)->stash_group_stop();\n      continue;\n    }\n    if (!stop_sig()) {\n      ASSERT(this, need_ptrace_syscall_event);\n      need_ptrace_syscall_event = false;\n      continue;\n    }\n    if (ReplaySession::is_ignored_signal(stop_sig()) &&\n        session().is_replaying()) {\n      continue;\n    }\n    ASSERT(this, session().is_recording() && !is_deterministic_signal(this))\n        << \" got unexpected signal \" << signal_name(stop_sig());\n    if (stop_sig() == session().as_record()->syscallbuf_desched_sig()) {\n      continue;\n    }\n    static_cast<RecordTask*>(this)->stash_sig();\n  }\n  apply_syscall_entry_regs();\n  canonicalize_regs(syscall_arch);\n  return true;\n}\n\nbool Task::exit_syscall(SupportedArch syscall_arch) {\n  // If PTRACE_SYSCALL_BEFORE_SECCOMP, we are inconsistent about\n  // whether we process the syscall on the syscall entry trap or\n  // on the seccomp trap. Detect if we are on the former and\n  // just bring us forward to the seccomp trap.\n  bool will_see_seccomp = seccomp_bpf_enabled &&\n                          (session().syscall_seccomp_ordering() ==\n                           Session::PTRACE_SYSCALL_BEFORE_SECCOMP) &&\n                          !is_ptrace_seccomp_event();\n  while (true) {\n    if (!resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n      return false;\n    }\n    if (will_see_seccomp && is_ptrace_seccomp_event()) {\n      will_see_seccomp = false;\n      continue;\n    }\n    if (ptrace_event() == PTRACE_EVENT_EXIT) {\n      return false;\n    }\n    ASSERT(this, !ptrace_event());\n    if (!stop_sig()) {\n      canonicalize_regs(syscall_arch);\n      break;\n    }\n    if (ReplaySession::is_ignored_signal(stop_sig()) &&\n        session().is_replaying()) {\n      continue;\n    }\n    ASSERT(this, session().is_recording());\n    static_cast<RecordTask*>(this)->stash_sig();\n  }\n  return true;\n}\n\nbool Task::exit_syscall_and_prepare_restart(SupportedArch syscall_arch) {\n  Registers r = regs();\n  int syscallno = r.original_syscallno();\n  LOG(debug) << \"exit_syscall_and_prepare_restart from syscall \"\n             << rr::syscall_name(syscallno, syscall_arch);\n  r.set_original_syscallno(syscall_number_for_gettid(syscall_arch));\n  set_regs(r);\n  // This exits the hijacked SYS_gettid.  Now the tracee is\n  // ready to do our bidding.\n  if (!exit_syscall(syscall_arch)) {\n    // The tracee unexpectedly exited. To get this to replay correctly, we need to\n    // make it look like we really entered the syscall. Then\n    // handle_ptrace_exit_event will record something appropriate.\n    r.set_syscallno(syscallno);\n    r.emulate_syscall_entry();\n    set_regs(r);\n    return false;\n  }\n  LOG(debug) << \"exit_syscall_and_prepare_restart done\";\n\n  // Restore these regs to what they would have been just before\n  // the tracee trapped at the syscall.\n  r.set_original_syscallno(-1);\n  r.set_syscallno(syscallno);\n  r.set_ip(r.ip() - syscall_instruction_length(syscall_arch));\n  set_regs(r);\n  return true;\n}\n\n#if defined(__i386__) || defined(__x86_64__)\n#define AR_L (1 << 21)\nstatic bool is_long_mode_segment(uint32_t segment) {\n  uint32_t ar = 0;\n  asm(\"lar %[segment], %[ar]\" : [ar] \"=r\"(ar) : [segment] \"r\"(segment));\n  return ar & AR_L;\n}\n#endif\n\nvoid Task::post_exec(const string& exe_file) {\n  // If the address space of this process which just exec'd is shared with another process\n  // (via vfork(2) or CLONE_VM perhaps), we will be leaving behind the syscallbuf mappings\n  // for this pid in the shared address space. Make a note of this, so that the next time\n  // we run a task in tihs address space, we unmap these buffers. (n.b. we can't clean up\n  // those buffers *before* the exec completes, because it might fail in which case we\n  // souldn't have cleaned them up.)\n  if (scratch_ptr) {\n    as->regions_pending_unmap.push_back(MemoryRange(scratch_ptr, scratch_size));\n  }\n  if (!syscallbuf_child.is_null()) {\n    as->regions_pending_unmap.push_back(MemoryRange(syscallbuf_child, syscallbuf_size));\n  }\n\n  session().post_exec();\n\n  as->erase_task(this);\n  fds->erase_task(this);\n\n  extra_registers = ExtraRegisters(registers.arch());\n  extra_registers_known = false;\n  ExtraRegisters e = *extra_regs_fallible();\n  e.reset();\n  set_extra_regs(e);\n\n  syscallbuf_child = nullptr;\n  syscallbuf_size = 0;\n  scratch_ptr = nullptr;\n  cloned_file_data_fd_child = -1;\n  desched_fd_child = -1;\n  preload_globals = nullptr;\n  rseq_state = nullptr;\n  thread_group()->execed = true;\n\n  thread_areas_.clear();\n  memset(&thread_locals, 0, sizeof(thread_locals));\n\n  as = session().create_vm(this, exe_file, as->uid().exec_count() + 1);\n  // It's barely-documented, but Linux unshares the fd table on exec\n  fds = fds->clone();\n  fds->insert_task(this);\n}\n\nstatic string prname_from_exe_image(const string& e) {\n  size_t last_slash = e.rfind('/');\n  return e.substr(last_slash == e.npos ? 0 : last_slash + 1);\n}\n\nvoid Task::post_exec_syscall(const std::string& original_exe_file) {\n  canonicalize_regs(arch());\n  as->post_exec_syscall(this);\n\n  AutoRemoteSyscalls remote(this);\n  set_name(remote, prname_from_exe_image(original_exe_file));\n  if (session().has_cpuid_faulting()) {\n    remote.infallible_syscall(syscall_number_for_arch_prctl(arch()),\n                              ARCH_SET_CPUID, 0);\n  }\n  if (arch() == aarch64) {\n    if (remote.syscall(syscall_number_for_prctl(remote.task()->arch()),\n                       PR_SET_TSC, PR_TSC_SIGSEGV, 0, 0) != 0) {\n      LOG(warn) << \"Missing kernel support for PR_SET_TSC; architected timer \"\n                   \"accesses will not be replayed deterministically. It is \"\n                   \"recommended to upgrade to kernel version 6.12\";\n    }\n  }\n}\n\nbool Task::execed() const { return tg->execed; }\n\nvoid Task::unmap_dead_syscallbufs_if_required() {\n  if (!as->regions_pending_unmap.empty()) {\n    LOG(warn) << \"Using \" << tid << \" to unmap syscallbuf regions for \"\n              << \"previously exec'd processes\";\n    AutoRemoteSyscalls remote(this);\n    std::vector<MemoryRange> regions_pending_unmap;\n    std::swap(regions_pending_unmap, as->regions_pending_unmap);\n    for (auto region : regions_pending_unmap) {\n      if (remote.infallible_munmap_syscall_if_alive(region.start(), region.size())) {\n        vm()->unmap(this, region.start(), region.size());\n      }\n    }\n  }\n}\n\nvoid Task::flush_inconsistent_state() { ticks = 0; }\n\nstring Task::read_c_str(remote_ptr<char> child_addr, bool *ok) {\n  remote_ptr<void> p = child_addr;\n  string str;\n  while (true) {\n    // We're only guaranteed that [child_addr,\n    // end_of_page) is mapped.\n    remote_ptr<void> end_of_page = ceil_page_size(p + 1);\n    ssize_t nbytes = end_of_page - p;\n    std::unique_ptr<char[]> buf(new char[nbytes]);\n\n    read_bytes_helper(p, nbytes, buf.get(), ok);\n    if (ok && !*ok) {\n      return \"\";\n    }\n    for (int i = 0; i < nbytes; ++i) {\n      if ('\\0' == buf[i]) {\n        return str;\n      }\n      str += buf[i];\n    }\n    p = end_of_page;\n  }\n}\n\nconst Registers& Task::regs() const {\n  // If we're in an unexpected exit then the tracee may\n  // not be stopped but we know its registers won't change again,\n  // so it's safe to ask for them here.\n  ASSERT(this, stopped_or_unexpected_exit());\n  return registers;\n}\n\nconst ExtraRegisters* Task::extra_regs_fallible() {\n  if (!extra_registers_known) {\n#if defined(__i386__) || defined(__x86_64__)\n    if (xsave_area_size() > 512) {\n      LOG(debug) << \"  (refreshing extra-register cache using XSAVE)\";\n\n      extra_registers.format_ = ExtraRegisters::XSAVE;\n      extra_registers.data_.resize(xsave_area_size());\n      struct iovec vec = { extra_registers.data_.data(),\n                           extra_registers.data_.size() };\n      if (fallible_ptrace(PTRACE_GETREGSET, NT_X86_XSTATE, &vec)) {\n        return nullptr;\n      }\n      extra_registers.data_.resize(vec.iov_len);\n      // The kernel may return less than the full XSTATE\n      extra_registers.validate(this);\n    } else {\n#if defined(__i386__)\n      LOG(debug) << \"  (refreshing extra-register cache using FPXREGS)\";\n\n      extra_registers.format_ = ExtraRegisters::XSAVE;\n      extra_registers.data_.resize(sizeof(user_fpxregs_struct));\n      if (fallible_ptrace(X86Arch::PTRACE_GETFPXREGS, nullptr, extra_registers.data_.data())) {\n        return nullptr;\n      }\n#elif defined(__x86_64__)\n      // x86-64 that doesn't support XSAVE; apparently Xeon E5620 (Westmere)\n      // is in this class.\n      LOG(debug) << \"  (refreshing extra-register cache using FPREGS)\";\n\n      extra_registers.format_ = ExtraRegisters::XSAVE;\n      extra_registers.data_.resize(sizeof(user_fpregs_struct));\n      if (fallible_ptrace(PTRACE_GETFPREGS, nullptr, extra_registers.data_.data())) {\n        return nullptr;\n      }\n#endif\n    }\n#elif defined(__aarch64__)\n    LOG(debug) << \"  (refreshing extra-register cache using FPR)\";\n\n    extra_registers.format_ = ExtraRegisters::NT_FPR;\n    extra_registers.data_.resize(sizeof(ARM64Arch::user_fpregs_struct));\n    struct iovec vec = { extra_registers.data_.data(),\n                          extra_registers.data_.size() };\n    if (fallible_ptrace(PTRACE_GETREGSET, NT_PRFPREG, &vec)) {\n      return nullptr;\n    }\n    extra_registers.data_.resize(vec.iov_len);\n#else\n#error need to define new extra_regs support\n#endif\n    extra_registers_known = true;\n  }\n  return &extra_registers;\n}\n\n#if defined(__i386__) || defined(__x86_64__)\nstatic ssize_t dr_user_word_offset(size_t i) {\n  DEBUG_ASSERT(i < NUM_X86_DEBUG_REGS);\n  return offsetof(struct user, u_debugreg[0]) + sizeof(void*) * i;\n}\n\nuintptr_t Task::get_debug_reg(size_t regno) {\n  errno = 0;\n  long result =\n      fallible_ptrace(PTRACE_PEEKUSER, dr_user_word_offset(regno), nullptr);\n  if (errno == ESRCH) {\n    return 0;\n  }\n  return result;\n}\n\nbool Task::set_x86_debug_reg(size_t regno, uintptr_t value) {\n  errno = 0;\n  fallible_ptrace(PTRACE_POKEUSER, dr_user_word_offset(regno), (void*)value);\n  return errno == ESRCH || errno == 0;\n}\n\nuintptr_t Task::x86_debug_status() {\n  return fallible_ptrace(PTRACE_PEEKUSER, dr_user_word_offset(6), nullptr);\n}\n#else\n#define FATAL_X86_ONLY() FATAL() << \"Reached x86-only code path on non-x86 architecture\";\nuintptr_t Task::get_debug_reg(size_t) {\n  FATAL_X86_ONLY();\n  return 0;\n}\n\nbool Task::set_x86_debug_reg(size_t, uintptr_t) {\n  FATAL_X86_ONLY();\n  return false;\n}\n\nuintptr_t Task::x86_debug_status() {\n  FATAL_X86_ONLY();\n  return 0;\n}\n#endif\n\n#if defined(__aarch64__)\nbool Task::set_aarch64_debug_regs(int which, ARM64Arch::user_hwdebug_state *regs, size_t nregs) {\n  errno = 0;\n  struct iovec iov { .iov_base = regs, .iov_len = sizeof(*regs) - (16-nregs)*sizeof(ARM64Arch::hw_bp) };\n  ASSERT(this, which == NT_ARM_HW_BREAK || which == NT_ARM_HW_WATCH);\n  fallible_ptrace(PTRACE_SETREGSET, which, (void*)&iov);\n  return errno == 0;\n}\nbool Task::get_aarch64_debug_regs(int which, ARM64Arch::user_hwdebug_state *regs) {\n  errno = 0;\n  struct iovec iov { .iov_base = regs, .iov_len = sizeof(*regs) };\n  ASSERT(this, which == NT_ARM_HW_BREAK || which == NT_ARM_HW_WATCH);\n  fallible_ptrace(PTRACE_GETREGSET, which, (void*)&iov);\n  return errno == 0;\n}\nstd::vector<uint8_t> Task::pac_keys(bool *ok)\n{\n  std::vector<uint8_t> pac_data(\n      sizeof(ARM64Arch::user_pac_address_keys) +\n      sizeof(ARM64Arch::user_pac_generic_keys));\n  struct iovec vec = { pac_data.data(), sizeof(ARM64Arch::user_pac_address_keys) };\n  if (fallible_ptrace(PTRACE_GETREGSET, NT_ARM_PACA_KEYS, &vec)) {\n    if (ok) {\n      *ok = false;\n    }\n    return std::vector<uint8_t>{};\n  }\n  vec = { pac_data.data() + sizeof(ARM64Arch::user_pac_address_keys),\n          sizeof(ARM64Arch::user_pac_generic_keys) };\n  if (fallible_ptrace(PTRACE_GETREGSET, NT_ARM_PACG_KEYS, &vec)) {\n    if (ok) {\n      *ok = false;\n    }\n    return std::vector<uint8_t>{};\n  }\n  return pac_data;\n}\nbool Task::set_pac_keys(const std::vector<uint8_t> &pac_data)\n{\n  if (pac_data.empty()) {\n    return true;\n  }\n  struct iovec vec = { (void*)pac_data.data(), sizeof(ARM64Arch::user_pac_address_keys) };\n  if (fallible_ptrace(PTRACE_SETREGSET, NT_ARM_PACA_KEYS, &vec)) {\n    return false;\n  }\n  vec = { (void*)(pac_data.data() + sizeof(ARM64Arch::user_pac_address_keys)),\n          sizeof(ARM64Arch::user_pac_generic_keys) };\n  return !fallible_ptrace(PTRACE_SETREGSET, NT_ARM_PACG_KEYS, &vec);\n}\n#else\nstd::vector<uint8_t> Task::pac_keys(bool *)\n{\n  return std::vector<uint8_t>{};\n}\nbool Task::set_pac_keys(const std::vector<uint8_t> &)\n{\n  return true;\n}\nbool Task::set_aarch64_debug_regs(int, ARM64Arch::user_hwdebug_state *, size_t) {\n  FATAL() << \"Reached aarch64 code path on non-aarch64 system\";\n  return false;\n}\nbool Task::get_aarch64_debug_regs(int, ARM64Arch::user_hwdebug_state *regs) {\n  // Following memset just to silence a warning about dbg_info may be used uninitialized.\n  memset(regs, 0, sizeof(*regs));\n  FATAL() << \"Reached aarch64 code path on non-aarch64 system\";\n  return false;\n}\n#endif\n\nvoid Task::set_x86_debug_status(uintptr_t status) {\n  if (arch() == x86 || arch() == x86_64) {\n    set_x86_debug_reg(6, status);\n  }\n}\n\nstatic bool is_singlestep_resume(ResumeRequest request) {\n  return request == RESUME_SINGLESTEP || request == RESUME_SYSEMU_SINGLESTEP;\n}\n\nTrapReasons Task::compute_trap_reasons() {\n  ASSERT(this, stop_sig() == SIGTRAP);\n\n  TrapReasons reasons;\n\n  const siginfo_t& si = get_siginfo();\n  if (arch() == x86 || arch() == x86_64) {\n    uintptr_t status = x86_debug_status();\n    reasons.singlestep = (status & DS_SINGLESTEP) != 0;\n    if (!reasons.singlestep && is_singlestep_resume(how_last_execution_resumed)) {\n      if (is_at_syscall_instruction(this, address_of_last_execution_resume) &&\n          ip() ==\n              address_of_last_execution_resume +\n                  syscall_instruction_length(arch())) {\n        // During replay we execute syscall instructions in certain cases, e.g.\n        // mprotect with syscallbuf. The kernel does not set DS_SINGLESTEP when we\n        // step over those instructions so we need to detect that here.\n        reasons.singlestep = true;\n      } else {\n        SpecialInst si =\n          special_instruction_at(this, address_of_last_execution_resume);\n        if (si.opcode == SpecialInstOpcode::X86_CPUID &&\n            ip() == address_of_last_execution_resume +\n                        special_instruction_len(SpecialInstOpcode::X86_CPUID)) {\n          // Likewise we emulate CPUID instructions and must forcibly detect that\n          // here.\n          reasons.singlestep = true;\n          // This also takes care of the did_set_breakpoint_after_cpuid workaround case\n        } else if (si.opcode == SpecialInstOpcode::X86_INT3 &&\n            ip() == address_of_last_execution_resume +\n                        special_instruction_len(SpecialInstOpcode::X86_INT3)) {\n          // INT3 instructions should also be turned into a singlestep here.\n          reasons.singlestep = true;\n        }\n      }\n    }\n\n    // In VMWare Player 6.0.4 build-2249910, 32-bit Ubuntu x86 guest,\n    // single-stepping does not trigger watchpoints :-(. So we have to\n    // check watchpoints here. fast_forward also hides watchpoint changes.\n    // Write-watchpoints will detect that their value has changed and trigger.\n    // XXX Read/exec watchpoints can't be detected this way so they're still\n    // broken in the above configuration :-(.\n    if ((DS_WATCHPOINT_ANY | DS_SINGLESTEP) & status) {\n      as->notify_watchpoint_fired(status, nullptr,\n          is_singlestep_resume(how_last_execution_resumed)\n              ? address_of_last_execution_resume : nullptr);\n    }\n    reasons.watchpoint =\n        as->has_any_watchpoint_changes() || (DS_WATCHPOINT_ANY & status);\n  } else if (arch() == aarch64) {\n    reasons.watchpoint = false;\n    reasons.singlestep = si.si_code == TRAP_TRACE;\n    reasons.watchpoint = si.si_code == TRAP_HWBKPT;\n    if (reasons.watchpoint) {\n      as->notify_watchpoint_fired(0, remote_ptr<void>((uintptr_t)si.si_addr),\n          is_singlestep_resume(how_last_execution_resumed)\n              ? address_of_last_execution_resume : nullptr);\n    }\n  }\n\n  // If we triggered a breakpoint, this would be the address of the breakpoint\n  remote_code_ptr ip_at_breakpoint = ip().undo_executed_bkpt(arch());\n  // Don't trust siginfo to report execution of a breakpoint if singlestep or\n  // watchpoint triggered.\n  if (reasons.singlestep) {\n    reasons.breakpoint =\n        as->is_breakpoint_instruction(this, address_of_last_execution_resume);\n    if (reasons.breakpoint) {\n      ASSERT(this, address_of_last_execution_resume == ip_at_breakpoint);\n    }\n  } else if (reasons.watchpoint) {\n    // We didn't singlestep, so watchpoint state is completely accurate.\n    // The only way the last instruction could have triggered a watchpoint\n    // and be a breakpoint instruction is if an EXEC watchpoint fired\n    // at the breakpoint address.\n    reasons.breakpoint = as->has_exec_watchpoint_fired(ip_at_breakpoint) &&\n                         as->is_breakpoint_instruction(this, ip_at_breakpoint);\n  } else {\n    ASSERT(this, SIGTRAP == si.si_signo) << \" expected SIGTRAP, got \" << si;\n    reasons.breakpoint = is_kernel_trap(si.si_code);\n    if (reasons.breakpoint) {\n      ASSERT(this, as->is_breakpoint_instruction(this, ip_at_breakpoint))\n          << \" expected breakpoint at \" << ip_at_breakpoint << \", got siginfo \"\n          << si;\n    }\n    // If we got a SIGTRAP via a FASYNC signal it must be our bpf-enabled\n    // hardware breakpoint.\n    reasons.breakpoint |= si.si_code == SI_SIGIO;\n  }\n  return reasons;\n}\n\nstatic void* preload_thread_locals_local_addr(AddressSpace& as) {\n  if (!as.has_mapping(AddressSpace::preload_thread_locals_start())) {\n    return nullptr;\n  }\n  // There might have been a mapping there, but not the one we expect (i.e.\n  // the one shared with us for thread locals). In that case we behave as\n  // if the mapping didn't exist at all.\n  auto& mapping = as.mapping_of(AddressSpace::preload_thread_locals_start());\n  if (mapping.flags & AddressSpace::Mapping::IS_THREAD_LOCALS) {\n    DEBUG_ASSERT(mapping.local_addr);\n    return mapping.local_addr;\n  }\n  return nullptr;\n}\n\ntemplate <typename Arch> static void setup_preload_thread_locals_arch(Task* t) {\n  void* local_addr = preload_thread_locals_local_addr(*t->vm());\n  if (local_addr) {\n    auto locals = reinterpret_cast<preload_thread_locals<Arch>*>(local_addr);\n    static_assert(sizeof(*locals) <= PRELOAD_THREAD_LOCALS_SIZE,\n                  \"bad PRELOAD_THREAD_LOCALS_SIZE\");\n    locals->syscallbuf_stub_alt_stack = t->syscallbuf_alt_stack();\n  }\n}\n\nvoid Task::setup_preload_thread_locals() {\n  activate_preload_thread_locals();\n  RR_ARCH_FUNCTION(setup_preload_thread_locals_arch, arch(), this);\n}\n\nconst Task::ThreadLocals& Task::fetch_preload_thread_locals() {\n  if (tuid() == as->thread_locals_tuid()) {\n    void* local_addr = preload_thread_locals_local_addr(*as);\n    if (local_addr) {\n      memcpy(thread_locals, local_addr, PRELOAD_THREAD_LOCALS_SIZE);\n      return thread_locals;\n    }\n    // The mapping might have been removed by crazy application code.\n    // That's OK, assuming the preload library was removed too.\n    memset(&thread_locals, 0, sizeof(thread_locals));\n  }\n  return thread_locals;\n}\n\nvoid Task::activate_preload_thread_locals() {\n  // Switch thread-locals to the new task.\n  if (tuid() != as->thread_locals_tuid()) {\n    void* local_addr = preload_thread_locals_local_addr(*as);\n    if (local_addr) {\n      Task* t = session().find_task(as->thread_locals_tuid());\n      if (t) {\n        t->fetch_preload_thread_locals();\n      }\n      memcpy(local_addr, thread_locals, PRELOAD_THREAD_LOCALS_SIZE);\n      as->set_thread_locals_tuid(tuid());\n    }\n  }\n}\n\n#if defined(__x86_64__) || defined(__i386__)\nstatic bool cpu_has_KNL_string_singlestep_bug() {\n  static bool has_quirk =\n      ((cpuid(CPUID_GETFEATURES, 0).eax & 0xF0FF0) == 0x50670);\n  return has_quirk;\n}\n#else\nstatic bool cpu_has_KNL_string_singlestep_bug() {\n  return false;\n}\n#endif\n\n/*\n * The value of rcx above which the CPU doesn't properly handle singlestep for\n * string instructions. Right now, since only once CPU has this quirk, this\n * value is hardcoded, but could depend on the CPU architecture in the future.\n */\nstatic int single_step_coalesce_cutoff() { return 16; }\n\nvoid Task::work_around_KNL_string_singlestep_bug() {\n  /* The extra cx >= cutoff check is just an optimization, to avoid the\n     moderately expensive load from ip() if we can */\n  if (!cpu_has_KNL_string_singlestep_bug()) {\n    return;\n  }\n  uintptr_t cx = regs().cx();\n  uintptr_t cutoff = single_step_coalesce_cutoff();\n  if (cx > cutoff && at_x86_string_instruction(this)) {\n    /* KNL has a quirk where single-stepping a string instruction can step up\n      to 64 iterations. Work around this by fudging registers to force the\n      processor to execute one iteration and one iteration only. */\n    LOG(debug) << \"Working around KNL single-step hardware bug (cx=\" << cx\n              << \")\";\n    if (cx > cutoff) {\n      last_resume_orig_cx = cx;\n      Registers r = regs();\n      /* An arbitrary value < cutoff would work fine here, except 1, since\n        the last iteration of the loop behaves differently */\n      r.set_cx(cutoff);\n      set_regs(r);\n    }\n  }\n}\n\nbool Task::resume_execution(ResumeRequest how, WaitRequest wait_how,\n                            TicksRequest tick_period, int sig) {\n  ASSERT(this, is_stopped_);\n\n  // Ensure our HW debug registers are up to date before we execute any code.\n  // If this fails because the task died, the code below will detect it.\n  set_debug_regs(vm()->get_hw_watchpoints());\n\n  will_resume_execution(how, wait_how, tick_period, sig);\n\n  LOG(debug) << \"resuming execution of \" << tid << \" with \"\n             << ptrace_req_name<NativeArch>(how)\n             << (sig ? string(\", signal \") + signal_name(sig) : string())\n             << \" tick_period \" << tick_period << \" wait \" << wait_how;\n  set_x86_debug_status(0);\n\n  if (is_singlestep_resume(how)) {\n    work_around_KNL_string_singlestep_bug();\n    if (is_x86ish(arch())) {\n      singlestepping_instruction = special_instruction_at(this, ip());\n      if (singlestepping_instruction.opcode == SpecialInstOpcode::X86_CPUID) {\n        // In KVM virtual machines (and maybe others), singlestepping over CPUID\n        // executes the following instruction as well. Work around that.\n        did_set_breakpoint_after_cpuid =\n          vm()->add_breakpoint(ip() + special_instruction_len(singlestepping_instruction.opcode), BKPT_INTERNAL);\n      }\n    } else if (arch() == aarch64 && is_singlestep_resume(how_last_execution_resumed)) {\n      // On aarch64, if the last execution was any sort of single step, then\n      // resuming again with PTRACE_(SYSEMU_)SINGLESTEP will cause a debug fault\n      // immediately before executing the next instruction in userspace\n      // (essentially completing the singlestep that got \"interrupted\" by\n      // trapping into the kernel). To prevent this, we must re-arm the\n      // PSTATE.SS bit. (If the last resume was not a single step,\n      // the kernel will apply this modification).\n      if (!registers.aarch64_singlestep_flag()) {\n        registers.set_aarch64_singlestep_flag();\n        registers_dirty = true;\n      }\n    }\n  }\n\n  address_of_last_execution_resume = ip();\n  how_last_execution_resumed = how;\n\n  bool flushed_ok = flush_regs();\n\n  // Start perf counters now. Stop them later if we don't\n  // actually resume the task. We can't defer starting the perf\n  // counters later than this, because we want to minimize the time\n  // between the wait_stop_or_exit below and the PTRACE_CONT.\n  if (tick_period != RESUME_NO_TICKS) {\n    if (tick_period == RESUME_UNLIMITED_TICKS) {\n      hpc.start(this, 0);\n    } else {\n      ASSERT(this, tick_period >= 0 && tick_period <= MAX_TICKS_REQUEST);\n      hpc.start(this, max<Ticks>(1, tick_period));\n    }\n    activate_preload_thread_locals();\n  }\n\n  if (session().is_recording() && !seen_ptrace_exit_event()) {\n    /* There's a nasty race where a stopped task gets woken up by a SIGKILL\n     * and advances to the PTRACE_EXIT_EVENT ptrace-stop just before we\n     * send a PTRACE_CONT. Our PTRACE_CONT will cause it to continue and exit,\n     * which means we don't get a chance to clean up robust futexes etc.\n     * Avoid that by doing a waitpid() here to see if it has exited.\n     * This doesn't fully close the race since in theory we could be preempted\n     * between the waitpid and the ptrace_if_stopped, giving another task\n     * a chance to SIGKILL our tracee and advance it to the PTRACE_EXIT_EVENT,\n     * or just letting the tracee be scheduled to process its pending SIGKILL.\n     */\n    WaitOptions options(tid);\n    options.block_seconds = 0.0;\n    WaitResult result = WaitManager::wait_stop_or_exit(options);\n    ASSERT(this, result.code == WAIT_OK || result.code == WAIT_NO_STATUS);\n    if (result.code == WAIT_OK) {\n      // In some (but not all) cases where the child was killed with SIGKILL,\n      // we don't get PTRACE_EVENT_EXIT before it just exits, because a SIGKILL\n      // arrived when the child was already in the PTRACE_EVENT_EXIT stop.\n      // The status could be any exit or fatal-signal status, since this status\n      // can reflect what caused the thread to exit before the SIGKILL arrived\n      // and forced it out of the PTRACE_EVENT_EXIT stop.\n      ASSERT(this,\n             result.status.ptrace_event() == PTRACE_EVENT_EXIT ||\n                 result.status.reaped())\n          << \"got \" << result.status;\n      LOG(debug) << \"Task \" << tid << \" exited unexpectedly with status \"\n          << result.status;\n      Ticks executed_ticks = hpc.stop(this);\n      ASSERT(this, !executed_ticks)\n          << \"Didn't actually resume the task, so there should be no ticks\";\n      if (did_waitpid(result.status)) {\n        // We reached a new stop (or actually reaped the task).\n        // Consider this \"resume execution\" to be done.\n        ASSERT(this, is_stopped_ || was_reaped_);\n        return wait_how != RESUME_WAIT_NO_EXIT;\n      }\n      ASSERT(this, result.status.ptrace_event() == PTRACE_EVENT_EXIT)\n        << \"did_waitpid should always succeed for reaped() statuses\";\n      // The tracee must have been kicked out of PTRACE_EVENT_EXIT\n      // by a SIGKILL (only possible on older kernels).\n      // If we were supposed to wait, we've failed.\n      // We can't wait now because on old kernels tasks can block\n      // indefinitely even after PTRACE_EVENT_EXIT (e.g. due to coredumping).\n      // We don't know what state it's in exactly, but registers haven't changed\n      // since nothing has really happened since the last stop.\n      set_stopped(false);\n      in_injectable_signal_stop_ = false;\n      ASSERT(this, in_unexpected_exit);\n      return RESUME_NONBLOCKING == wait_how;\n    }\n  }\n\n  // If the flush failed and we reached here, then the tracee must have\n  // been unexpectedly killed but not yet at a PTRACE_EVENT_EXIT that we\n  // could detect above. In that case we don't need to resume it, it is\n  // already resumed.\n  if (flushed_ok) {\n    ptrace_if_stopped(how, nullptr, (void*)(uintptr_t)sig);\n  } else {\n    Ticks executed_ticks = hpc.stop(this);\n    ASSERT(this, !executed_ticks)\n        << \"Didn't actually resume the task, so there should be no ticks\";\n  }\n  // If ptrace_if_stopped failed, it means we're running along the\n  // exit path due to a SIGKILL or equivalent, so just like if it\n  // succeeded, we will eventually receive a wait notification.\n  set_stopped(false);\n  in_injectable_signal_stop_ = false;\n  extra_registers_known = false;\n  if (RESUME_NONBLOCKING != wait_how) {\n    if (!wait()) {\n      ASSERT(this, in_unexpected_exit);\n      return false;\n    }\n    if (wait_how == RESUME_WAIT_NO_EXIT) {\n      return ptrace_event() != PTRACE_EVENT_EXIT && !was_reaped();\n    }\n  }\n  return true;\n}\n\nvoid Task::set_regs(const Registers& regs) {\n  // Only allow registers to be set while our copy is the source of truth.\n  ASSERT(this, stopped_or_unexpected_exit());\n  if (registers.original_syscallno() != regs.original_syscallno()) {\n    orig_syscallno_dirty = true;\n  }\n  bool changed = registers != regs;\n  if (changed) {\n    registers_dirty = true;\n    registers = regs;\n  }\n}\n\nbool Task::flush_regs() {\n  if (registers_dirty) {\n    LOG(debug) << \"Flushing registers for tid \" << tid << \" \" << registers;\n    auto ptrace_regs = registers.get_ptrace_iovec();\n#if defined(__i386__) || defined(__x86_64__)\n    if (ptrace_if_stopped(PTRACE_SETREGSET, NT_PRSTATUS, &ptrace_regs)) {\n      /* If that failed, the task was killed and it should not matter what\n         we tried to set. But we will remember that our registers are dirty. */\n      registers_dirty = false;\n      orig_syscallno_dirty = false;\n    }\n#elif defined(__aarch64__)\n    if (ptrace_if_stopped(PTRACE_SETREGSET, NT_PRSTATUS, &ptrace_regs)) {\n      /* If that failed, the task was killed and it should not matter what\n         we tried to set. But we will remember that our registers are dirty. */\n      registers_dirty = false;\n    }\n#else\n    #error \"Unknown architecture\"\n#endif\n  }\n#if defined(__i386__) || defined(__x86_64__)\n  else {\n    ASSERT(this, !orig_syscallno_dirty);\n  }\n#elif defined(__aarch64__)\n  if (orig_syscallno_dirty) {\n    uintptr_t syscall = registers.original_syscallno();\n    struct iovec vec = { &syscall,\n                          sizeof(syscall) };\n    LOG(debug) << \"Changing syscall to \" << syscall;\n    if (ptrace_if_stopped(PTRACE_SETREGSET, NT_ARM_SYSTEM_CALL, &vec)) {\n      /* If that failed, the task was killed and it should not matter what\n         we tried to set. But we will remember that our registers are dirty. */\n      orig_syscallno_dirty = false;\n    }\n  }\n#endif\n  return !registers_dirty;\n}\n\nvoid Task::set_extra_regs(const ExtraRegisters& regs) {\n  ASSERT(this, !regs.empty()) << \"Trying to set empty ExtraRegisters\";\n  ASSERT(this, regs.arch() == arch())\n      << \"Trying to set wrong arch ExtraRegisters\";\n  extra_registers = regs;\n\n  switch (extra_registers.format()) {\n    case ExtraRegisters::XSAVE: {\n      if (xsave_area_size() > 512) {\n        struct iovec vec = { extra_registers.data_.data(),\n                             extra_registers.data_.size() };\n        if (ptrace_if_stopped(PTRACE_SETREGSET, NT_X86_XSTATE, &vec)) {\n          /* If that failed, the task was killed and it should not matter what\n             we tried to set. But we will remember that our registers are dirty. */\n          extra_registers_known = true;\n        }\n      } else {\n#if defined(__i386__)\n        ASSERT(this,\n               extra_registers.data_.size() == sizeof(user_fpxregs_struct));\n        if (ptrace_if_stopped(X86Arch::PTRACE_SETFPXREGS, nullptr,\n                              extra_registers.data_.data())) {\n          /* If that failed, the task was killed and it should not matter what\n             we tried to set. But we will remember that our registers are dirty. */\n          extra_registers_known = true;\n        }\n#elif defined(__x86_64__)\n        ASSERT(this,\n               extra_registers.data_.size() == sizeof(user_fpregs_struct));\n        if (ptrace_if_stopped(PTRACE_SETFPREGS, nullptr,\n                              extra_registers.data_.data())) {\n          /* If that failed, the task was killed and it should not matter what\n             we tried to set. But we will remember that our registers are dirty. */\n          extra_registers_known = true;\n        }\n#endif\n      }\n      break;\n    }\n    case ExtraRegisters::NT_FPR: {\n      struct iovec vec = { extra_registers.data_.data(),\n                            extra_registers.data_.size() };\n      if (ptrace_if_stopped(PTRACE_SETREGSET, NT_PRFPREG, &vec)) {\n        /* If that failed, the task was killed and it should not matter what\n           we tried to set. But we will remember that our registers are dirty. */\n        extra_registers_known = true;\n      }\n      break;\n    }\n    default:\n      ASSERT(this, false) << \"Unexpected ExtraRegisters format\";\n  }\n}\n\nenum WatchBytesX86 {\n  BYTES_1 = 0x00,\n  BYTES_2 = 0x01,\n  BYTES_4 = 0x03,\n  BYTES_8 = 0x02\n};\nstatic WatchBytesX86 num_bytes_to_dr_len(size_t num_bytes) {\n  switch (num_bytes) {\n    case 1:\n      return BYTES_1;\n    case 2:\n      return BYTES_2;\n    case 4:\n      return BYTES_4;\n    case 8:\n      return BYTES_8;\n    default:\n      FATAL() << \"Unsupported breakpoint size \" << num_bytes;\n      return WatchBytesX86(-1); // not reached\n  }\n}\n\nstruct DebugControl {\n  uintptr_t dr0_local : 1;\n  uintptr_t dr0_global : 1;\n  uintptr_t dr1_local : 1;\n  uintptr_t dr1_global : 1;\n  uintptr_t dr2_local : 1;\n  uintptr_t dr2_global : 1;\n  uintptr_t dr3_local : 1;\n  uintptr_t dr3_global : 1;\n\n  uintptr_t ignored : 8;\n\n  WatchType dr0_type : 2;\n  WatchBytesX86 dr0_len : 2;\n  WatchType dr1_type : 2;\n  WatchBytesX86 dr1_len : 2;\n  WatchType dr2_type : 2;\n  WatchBytesX86 dr2_len : 2;\n  WatchType dr3_type : 2;\n  WatchBytesX86 dr3_len : 2;\n\n  void enable(size_t index, WatchBytesX86 size, WatchType type) {\n    switch (index) {\n#define CASE(_i)                                                  \\\n      case _i:                                                    \\\n        dr##_i##_local = 1;                                       \\\n        dr##_i##_global = 0;                                      \\\n        dr##_i##_type = type;                                     \\\n        dr##_i##_len = size;                                      \\\n        break\n      CASE(0);\n      CASE(1);\n      CASE(2);\n      CASE(3);\n#undef CASE\n      default:\n        FATAL() << \"Invalid index\";\n    }\n  }\n};\n\nstatic_assert(sizeof(DebugControl) == sizeof(uintptr_t),\n              \"Can't pack DebugControl\");\n\nunion PackedDebugControl {\n  uintptr_t packed;\n  DebugControl ctl;\n};\n\nstatic bool set_x86_debug_regs(Task *t, const Task::HardwareWatchpoints& regs) {\n  // Reset the debug status since we're about to change the set\n  // of programmed watchpoints.\n  t->set_x86_debug_reg(6, 0);\n\n  if (regs.size() > NUM_X86_WATCHPOINTS) {\n    t->set_x86_debug_reg(7, 0);\n    return false;\n  }\n\n  // Work around kernel bug https://bugzilla.kernel.org/show_bug.cgi?id=200965.\n  // For every watchpoint we're going to use, enable it with size 1.\n  // This will let us set the address freely without potentially triggering\n  // the kernel bug which will reject an unaligned address if the watchpoint\n  // is disabled but was non-size-1.\n  PackedDebugControl dr7;\n  dr7.packed = 0;\n  for (size_t i = 0; i < regs.size(); ++i) {\n    dr7.ctl.enable(i, BYTES_1, WATCH_EXEC);\n  }\n  t->set_x86_debug_reg(7, dr7.packed);\n  if (regs.empty()) {\n    // Don't do another redundant poke to DR7.\n    return true;\n  }\n\n  size_t index = 0;\n  for (auto reg : regs) {\n    if (!t->set_x86_debug_reg(index, reg.addr.as_int())) {\n      t->set_x86_debug_reg(7, 0);\n      return false;\n    }\n    dr7.ctl.enable(index, num_bytes_to_dr_len(reg.num_bytes), reg.type);\n    ++index;\n  }\n  return t->set_x86_debug_reg(7, dr7.packed);\n}\n\ntemplate <typename Arch>\nstatic bool set_debug_regs_arch(Task* t,\n                                const Task::HardwareWatchpoints& regs);\ntemplate <> bool set_debug_regs_arch<X86Arch>(Task* t,\n                                              const Task::HardwareWatchpoints& regs) {\n  return set_x86_debug_regs(t, regs);\n}\ntemplate <> bool set_debug_regs_arch<X64Arch>(Task* t,\n                                              const Task::HardwareWatchpoints& regs) {\n  return set_x86_debug_regs(t, regs);\n}\n\nstatic void query_max_bp_wp(Task* t, ssize_t* max_bp, ssize_t* max_wp) {\n  ARM64Arch::user_hwdebug_state bps;\n  ARM64Arch::user_hwdebug_state wps;\n  bool ok = t->get_aarch64_debug_regs(NT_ARM_HW_BREAK, &bps) &&\n            t->get_aarch64_debug_regs(NT_ARM_HW_WATCH, &wps);\n  ASSERT(t, ok);\n  *max_bp = bps.dbg_info & 0xff;\n  *max_wp = wps.dbg_info & 0xff;\n}\n\ntemplate <> bool set_debug_regs_arch<ARM64Arch>(Task* t,\n                                                const Task::HardwareWatchpoints& regs) {\n  ARM64Arch::user_hwdebug_state bps;\n  ARM64Arch::user_hwdebug_state wps;\n  memset(&bps, 0, sizeof(bps));\n  memset(&wps, 0, sizeof(wps));\n\n  static ssize_t max_bp = -1;\n  static ssize_t max_wp = -1;\n  if (max_bp == -1) {\n    query_max_bp_wp(t, &max_bp, &max_wp);\n  }\n\n  // Having at least one of each is architecturally guaranteed\n  ASSERT(t, max_bp >= 1 && max_wp >= 1);\n\n  ssize_t cur_bp = 0;\n  ssize_t cur_wp = 0;\n  for (auto reg : regs) {\n    // GDB always splits these into nicely aligned platform chunks for us,\n    // but let's be general and support unaligned registers also.\n    size_t len = reg.num_bytes;\n    remote_ptr<uint8_t> addr = reg.addr.cast<uint8_t>();\n    while (len > 0) {\n      ARM64Arch::hw_bp* bp = nullptr;\n      if (reg.type == WATCH_EXEC) {\n        if (cur_bp == max_bp) {\n          return false;\n        }\n        bp = &bps.dbg_regs[cur_bp++];\n      } else {\n        if (cur_wp == max_wp) {\n          return false;\n        }\n        bp = &wps.dbg_regs[cur_wp++];\n      }\n      ARM64Arch::hw_breakpoint_ctrl ctrl;\n      memset(&ctrl, 0, sizeof(ctrl));\n      switch (reg.type) {\n        case WATCH_EXEC:\n          ctrl.type = ARM_WATCH_EXEC;\n          break;\n        case WATCH_WRITE:\n          ctrl.type = ARM_WATCH_WRITE;\n          break;\n        case WATCH_READWRITE:\n          ctrl.type = ARM_WATCH_READWRITE;\n          break;\n      }\n      ctrl.enabled = 1;\n      ctrl.priv = ARM_PRIV_EL0;\n      uintptr_t off = (uintptr_t)addr.as_int() % 8;\n      size_t cur_bp_len = std::min(8-off, len);\n      // This is a byte mask of which particular byte in the 8byte word at `addr`\n      // to watch.\n      uintptr_t mask = ((((uintptr_t)1) << cur_bp_len) - 1) << off;\n      ASSERT(t, (mask & ~0xff) == 0);\n      ctrl.length = mask;\n      bp->addr = addr.as_int() - off;\n      bp->ctrl = ctrl;\n      len -= cur_bp_len;\n      addr += cur_bp_len;\n    }\n  }\n\n  // max_bp rather than cur_bp to make sure to clear out any unused slots\n  return t->set_aarch64_debug_regs(NT_ARM_HW_BREAK, &bps, max_bp) &&\n         t->set_aarch64_debug_regs(NT_ARM_HW_WATCH, &wps, max_wp);\n}\n\nstatic bool set_debug_regs_internal(Task* t, const Task::HardwareWatchpoints& regs) {\n  RR_ARCH_FUNCTION(set_debug_regs_arch, t->arch(), t, regs);\n}\n\nbool Task::set_debug_regs(const HardwareWatchpoints& regs) {\n  if (regs == current_hardware_watchpoints) {\n    return true;\n  }\n  bool ret = set_debug_regs_internal(this, regs);\n  if (ret) {\n    current_hardware_watchpoints = regs;\n  } else {\n    current_hardware_watchpoints.clear();\n  }\n  return ret;\n}\n\nstatic void set_thread_area(std::vector<X86Arch::user_desc>& thread_areas_,\n                            X86Arch::user_desc desc) {\n  for (auto& t : thread_areas_) {\n    if (t.entry_number == desc.entry_number) {\n      t = desc;\n      return;\n    }\n  }\n  thread_areas_.push_back(desc);\n}\n\nvoid Task::set_thread_area(remote_ptr<X86Arch::user_desc> tls) {\n  // We rely on the fact that user_desc is word-size-independent.\n  DEBUG_ASSERT(arch() == x86 || arch() == x86_64);\n  auto desc = read_mem(tls);\n  rr::set_thread_area(thread_areas_, desc);\n}\n\nint Task::emulate_set_thread_area(int idx, X86Arch::user_desc desc) {\n  DEBUG_ASSERT(arch() == x86 || arch() == x86_64);\n  errno = 0;\n  fallible_ptrace(NativeArch::PTRACE_SET_THREAD_AREA, idx, &desc);\n  if (errno != 0) {\n    return errno;\n  }\n  desc.entry_number = idx;\n  rr::set_thread_area(thread_areas_, desc);\n  return 0;\n}\n\nint Task::emulate_get_thread_area(int idx, X86Arch::user_desc& desc) {\n  DEBUG_ASSERT(arch() == x86 || arch() == x86_64);\n  LOG(debug) << \"Emulating PTRACE_GET_THREAD_AREA\";\n  errno = 0;\n  fallible_ptrace(NativeArch::PTRACE_GET_THREAD_AREA, idx, &desc);\n  return errno;\n}\n\npid_t Task::tgid() const { return tg->tgid; }\n\npid_t Task::real_tgid() const {\n  // Unless we're recording, each task is in its own thread group\n  return session().is_recording() ? tgid() : tid;\n}\n\nconst string& Task::trace_dir() const {\n  const TraceStream* trace = trace_stream();\n  ASSERT(this, trace) << \"Trace directory not available\";\n  return trace->dir();\n}\n\nFrameTime Task::trace_time() const {\n  const TraceStream* trace = trace_stream();\n  return trace ? trace->time() : 0;\n}\n\nstatic bool is_signal_triggered_by_ptrace_interrupt(int group_stop_sig) {\n  switch (group_stop_sig) {\n    case SIGTRAP:\n    // We sometimes see SIGSTOP at interrupts, though the\n    // docs don't mention that.\n    case SIGSTOP:\n      return true;\n    default:\n      return false;\n  }\n}\n\n// This function doesn't really need to do anything. The signal will cause\n// waitpid to return EINTR and that's all we need.\nstatic void handle_alarm_signal(__attribute__((unused)) int sig) {}\n\nbool Task::do_ptrace_interrupt() {\n  errno = 0;\n  fallible_ptrace(PTRACE_INTERRUPT, nullptr, nullptr);\n  if (errno) {\n    ASSERT(this, errno == ESRCH) << \"Unexpected PTRACE_INTERRUPT error \" << errno;\n    return false;\n  }\n  expecting_ptrace_interrupt_stop = 2;\n  return true;\n}\n\nbool Task::account_for_potential_ptrace_interrupt_stop(WaitStatus status) {\n  if (expecting_ptrace_interrupt_stop > 0) {\n    --expecting_ptrace_interrupt_stop;\n    if (is_signal_triggered_by_ptrace_interrupt(status.group_stop())) {\n      expecting_ptrace_interrupt_stop = 0;\n      return true;\n    }\n  }\n  return false;\n}\n\nbool Task::wait(double interrupt_after_elapsed) {\n  LOG(debug) << \"going into blocking wait for \" << tid << \" ...\";\n  ASSERT(this, session().is_recording() || interrupt_after_elapsed == -1);\n\n  bool sent_wait_interrupt = false;\n  WaitResult result;\n  while (true) {\n    if (interrupt_after_elapsed == 0 && !sent_wait_interrupt) {\n      // If this fails, the tracee must be a zombie or altogether gone,\n      // in which case we should detect that status change later.\n      do_ptrace_interrupt();\n      if (session().is_recording()) {\n        // Force this timeslice to end\n        session().as_record()->scheduler().expire_timeslice();\n      }\n      sent_wait_interrupt = true;\n    }\n\n    WaitOptions options(tid);\n    if (interrupt_after_elapsed > 0) {\n      options.block_seconds = interrupt_after_elapsed;\n      interrupt_after_elapsed = 0;\n    }\n    result = WaitManager::wait_stop(options);\n\n    if (result.code == WAIT_OK) {\n      break;\n    }\n    if (result.code == WAIT_NO_CHILD) {\n      /* The process died without us getting a PTRACE_EXIT_EVENT notification.\n       * This is possible if the process receives a SIGKILL while in the exit\n       * event stop, but before we were able to read the event notification.\n       */\n      in_unexpected_exit = true;\n      return false;\n    }\n    ASSERT(this, result.code == WAIT_NO_STATUS);\n  }\n\n  if (sent_wait_interrupt) {\n    LOG(warn) << \"Forced to PTRACE_INTERRUPT tracee\";\n    if (!is_signal_triggered_by_ptrace_interrupt(result.status.group_stop())) {\n      LOG(warn) << \"  PTRACE_INTERRUPT raced with another event \" << result.status;\n    }\n  }\n  return did_waitpid(result.status);\n}\n\nvoid Task::canonicalize_regs(SupportedArch syscall_arch) {\n  ASSERT(this, stopped_or_unexpected_exit());\n\n  if (registers.arch() == x86_64) {\n    if (syscall_arch == x86) {\n      // The int $0x80 compatibility handling clears r8-r11\n      // (see arch/x86/entry/entry_64_compat.S). The sysenter compatibility\n      // handling also clears r12-r15. However, to actually make such a syscall,\n      // the user process would have to switch itself into compatibility mode,\n      // which, though possible, does not appear to actually be done by any\n      // real application (contrary to int $0x80, which is accessible from 64bit\n      // mode as well).\n      registers_dirty |= registers.set_r8(0x0);\n      registers_dirty |= registers.set_r9(0x0);\n      registers_dirty |= registers.set_r10(0x0);\n      registers_dirty |= registers.set_r11(0x0);\n    } else {\n      // x86-64 'syscall' instruction copies RFLAGS to R11 on syscall entry.\n      // If we single-stepped into the syscall instruction, the TF flag will be\n      // set in R11. We don't want the value in R11 to depend on whether we\n      // were single-stepping during record or replay, possibly causing\n      // divergence.\n      // This doesn't matter when exiting a sigreturn syscall, since it\n      // restores the original flags.\n      // For untraced syscalls, the untraced-syscall entry point code (see\n      // write_rr_page) does this itself.\n      // We tried just clearing %r11, but that caused hangs in\n      // Ubuntu/Debian kernels.\n      // Making this match the flags makes this operation idempotent, which is\n      // helpful.\n      registers_dirty |= registers.set_r11(0x246);\n      // x86-64 'syscall' instruction copies return address to RCX on syscall\n      // entry. rr-related kernel activity normally sets RCX to -1 at some point\n      // during syscall execution, but apparently in some (unknown) situations\n      // probably involving untraced syscalls, that doesn't happen. To avoid\n      // potential issues, forcibly replace RCX with -1 always.\n      // This doesn't matter (and we should not do this) when exiting a\n      // sigreturn syscall, since it will restore the original RCX and we don't\n      // want to clobber that.\n      // For untraced syscalls, the untraced-syscall entry point code (see\n      // write_rr_page) does this itself.\n      registers_dirty |= registers.set_cx((intptr_t)-1);\n    }\n    // On kernel 3.13.0-68-generic #111-Ubuntu SMP we have observed a failed\n    // execve() clearing all flags during recording. During replay we emulate\n    // the exec so this wouldn't happen. Just reset all flags so everything's\n    // consistent.\n    // 0x246 is ZF+PF+IF+reserved, the result clearing a register using\n    // \"xor reg, reg\".\n    registers_dirty |= registers.set_flags(0x246);\n  } else if (registers.arch() == x86) {\n    // The x86 SYSENTER handling in Linux modifies EBP and EFLAGS on entry.\n    // EBP is the potential sixth syscall parameter, stored on the user stack.\n    // The EFLAGS changes are described here:\n    // http://linux-kernel.2935.n7.nabble.com/ia32-sysenter-target-does-not-preserve-EFLAGS-td1074164.html\n    // In a VMWare guest, the modifications to EFLAGS appear to be\n    // nondeterministic. Cover that up by setting EFLAGS to reasonable values\n    // now.\n    registers_dirty |= registers.set_flags(0x246);\n  }\n}\n\nbool Task::read_aarch64_tls_register(uintptr_t *result) {\n  struct iovec vec = { result, sizeof(*result) };\n  return ptrace_if_stopped(PTRACE_GETREGSET, NT_ARM_TLS, &vec);\n}\n\nvoid Task::set_aarch64_tls_register(uintptr_t val) {\n  struct iovec vec = { &val, sizeof(val) };\n  ptrace_if_stopped(PTRACE_SETREGSET, NT_ARM_TLS, &vec);\n  /* If that failed, the task was killed and it should not matter what\n     we tried to set. */\n}\n\nstatic FrameTime simulate_error_at_event() {\n  const char* s = getenv(\"RR_SIMULATE_ERROR_AT_EVENT\");\n  if (s) {\n    return atoi(s);\n  }\n  return INT64_MAX;\n}\n\nstatic bool simulate_transient_error(Task* t) {\n  static bool simulated_error = false;\n  static FrameTime simulate_error_at_event_ = simulate_error_at_event();\n\n  if (simulated_error || !t->session().is_replaying() ||\n      t->as_replay()->session().trace_stream()->time() < simulate_error_at_event_) {\n    return false;\n  }\n  simulated_error = true;\n  return true;\n}\n\nstatic bool ignore_signal_for_detached_proxy(int sig) {\n  switch (sig) {\n    case SIGSTOP:\n    case SIGCONT:\n    case SIGTTIN:\n    case SIGTTOU:\n      return true;\n    default:\n      return false;\n  }\n}\n\nbool Task::did_waitpid(WaitStatus status) {\n  if (is_detached_proxy() &&\n      ignore_signal_for_detached_proxy(status.stop_sig())) {\n    LOG(debug) << \"Task \" << tid << \" is a detached proxy, ignoring status \" << status;\n    return true;\n  }\n\n  LOG(debug) << \"  Task \" << tid << \" changed status to \" << status;\n\n  intptr_t original_syscallno = registers.original_syscallno();\n  LOG(debug) << \"  (refreshing register cache)\";\n  Ticks more_ticks = 0;\n  // Some (all?) SIGTRAP stops are *not* usable for signal injection.\n  bool in_injectable_signal_stop =\n    status.stop_sig() > 0 && status.stop_sig() != SIGTRAP;\n\n  if (status.reaped()) {\n    was_reaped_ = true;\n    if (handled_ptrace_exit_event_) {\n      LOG(debug) << \"Reaped task late \" << tid;\n      // We did not reap this task when it exited, likely because it was a\n      // thread group leader blocked on the exit of the other members of\n      // its thread group. This has now reaped the task, so all we need to do\n      // here is get out quickly and the higher-level function should go ahead\n      // and delete us.\n      wait_status = status;\n      return true;\n    }\n    LOG(debug) << \"Unexpected process reap for \" << tid;\n    /* Mark buffers as having been destroyed. We missed our chance\n     * to destroy them normally in handle_ptrace_exit_event.\n     * XXX: We could try to find some tasks here to unmap our buffers, but it\n     *      seems hardly worth it.\n     */\n    destroy_buffers(nullptr, nullptr);\n  } else {\n    bool was_stopped = is_stopped_;\n    // Mark as stopped now. If we fail one of the ticks assertions below,\n    // the test-monitor (or user) might want to attach the emergency debugger,\n    // which needs to know that the tracee is stopped.\n    set_stopped(true);\n\n    // After PTRACE_INTERRUPT, any next two stops may be a group stop caused by\n    // that PTRACE_INTERRUPT (or neither may be). This is because PTRACE_INTERRUPT\n    // generally lets other stops win (and thus doesn't inject it's own stop), but\n    // if the other stop was already done processing, even we didn't see it yet,\n    // the stop will still be queued, so we could see the other stop and then the\n    // PTRACE_INTERRUPT group stop.\n    // When we issue PTRACE_INTERRUPT, we this set this counter to 2, and here\n    // we decrement it on every stop such that while this counter is positive,\n    // any group-stop could be one induced by PTRACE_INTERRUPT\n    if (account_for_potential_ptrace_interrupt_stop(status)) {\n      // Assume this was PTRACE_INTERRUPT and thus treat this as\n      // TIME_SLICE_SIGNAL instead.\n      status = WaitStatus::for_stop_sig(PerfCounters::TIME_SLICE_SIGNAL);\n      memset(&pending_siginfo, 0, sizeof(pending_siginfo));\n      pending_siginfo.si_signo = PerfCounters::TIME_SLICE_SIGNAL;\n      pending_siginfo.si_fd = hpc.ticks_interrupt_fd();\n      pending_siginfo.si_code = POLL_IN;\n      // Don't try to inject signals into ptrace-interrupt stops\n      in_injectable_signal_stop = false;\n    } else if (status.stop_sig()) {\n      if (!ptrace_if_stopped(PTRACE_GETSIGINFO, nullptr, &pending_siginfo)) {\n        LOG(debug) << \"Unexpected process death getting siginfo for \" << tid;\n        // Let's pretend this stop never happened.\n        set_stopped(false);\n        in_unexpected_exit = true;\n        return false;\n      }\n    }\n\n    // A SIGKILL or equivalent can cause a task to exit without us having run it, in\n    // which case we might have pending register changes for it that are now\n    // irrelevant. In that case we just throw away our register changes and use\n    // whatever the kernel now has.\n    if (status.ptrace_event() != PTRACE_EVENT_EXIT) {\n      ASSERT(this, !registers_dirty) << \"Registers shouldn't already be dirty (status is \" << status << \")\";\n    }\n    // If the task was stopped, we don't need to read the registers.\n    // In fact if we didn't start the thread, we may not have flushed dirty\n    // registers but still received a PTRACE_EVENT_EXIT, in which case the\n    // task's register values are not what they should be.\n    if (!was_stopped && !registers_dirty) {\n      LOG(debug) << \"Requesting registers from tracee \" << tid;\n      NativeArch::user_regs_struct ptrace_regs;\n      PerfCounters::Error error_state;\n      PerfCounters::Error* detect_transient_error = nullptr;\n      ReplaySession* replay_session = session().as_replay();\n      if (replay_session && !replay_session->flags().transient_errors_fatal) {\n        detect_transient_error = &error_state;\n      }\n\n#if defined(__i386__) || defined(__x86_64__)\n      if (ptrace_if_stopped(PTRACE_GETREGS, nullptr, &ptrace_regs)) {\n        registers.set_from_ptrace(ptrace_regs);\n        // Check the architecture of the task by looking at the\n        // cs segment register and checking if that segment is a long mode segment\n        // (Linux always uses GDT entries for this, which are globally the same).\n        SupportedArch a = is_long_mode_segment(registers.cs()) ? x86_64 : x86;\n\n        if (a == x86_64 && NativeArch::arch() == x86) {\n          FATAL() << \"Sorry, tracee \" << tid << \" is executing in x86-64 mode\"\n                  << \" and that's not supported with a 32-bit rr.\";\n        }\n\n        if (a != registers.arch()) {\n          registers.set_arch(a);\n          registers.set_from_ptrace(ptrace_regs);\n        }\n\n        // Only adjust tick count if we were able to read registers.\n        // For example if the task is already reaped we don't have new\n        // register values and we don't want to read a ticks value\n        // that mismatches our registers.\n        more_ticks = hpc.stop(this, detect_transient_error);\n      }\n#elif defined(__aarch64__)\n      struct iovec vec = { &ptrace_regs,\n                          sizeof(ptrace_regs) };\n      if (ptrace_if_stopped(PTRACE_GETREGSET, NT_PRSTATUS, &vec)) {\n        registers.set_from_ptrace(ptrace_regs);\n        more_ticks = hpc.stop(this, detect_transient_error);\n      }\n#else\n#error detect architecture here\n#endif\n      else {\n        LOG(debug) << \"Unexpected process death for \" << tid;\n        // Let's pretend this stop never happened.\n        // Note that pending_siginfo may have been overwritten above,\n        // but in that case we're going to ignore this signal-stop\n        // so it doesn't matter.\n        set_stopped(false);\n        in_unexpected_exit = true;\n        return false;\n      }\n      if (simulate_transient_error(this)) {\n        error_state = PerfCounters::Error::Transient;\n      }\n      if (detect_transient_error &&\n        *detect_transient_error == PerfCounters::Error::Transient) {\n        session().as_replay()->notify_detected_transient_error();\n      }\n    }\n  }\n\n  wait_status = status;\n  /* Record this now that we're going to stay in the stopped state */\n  in_injectable_signal_stop_ = in_injectable_signal_stop;\n  session().accumulate_ticks_processed(more_ticks);\n  ticks += more_ticks;\n\n  if (was_reaped_) {\n    ASSERT(this, !handled_ptrace_exit_event_);\n  } else if (status.ptrace_event() == PTRACE_EVENT_EXIT) {\n    ASSERT(this, !handled_ptrace_exit_event_);\n    seen_ptrace_exit_event_ = true;\n  } else {\n    if (arch() == x86 || arch() == x86_64) {\n      // Clear the single step flag in case we got here by taking a signal\n      // after asking for a single step. We want to avoid taking that single\n      // step after the signal resumes, so the singlestep flag needs to be\n      // cleared. On aarch64, the kernel does this for us.\n      if (registers.x86_singlestep_flag()) {\n        registers.clear_x86_singlestep_flag();\n        registers_dirty = true;\n      }\n\n      if (last_resume_orig_cx != 0) {\n        uintptr_t new_cx = registers.cx();\n        /* Un-fudge registers, if we fudged them to work around the KNL hardware\n          quirk */\n        unsigned cutoff = single_step_coalesce_cutoff();\n        ASSERT(this, new_cx == cutoff - 1 || new_cx == cutoff);\n        registers.set_cx(last_resume_orig_cx - cutoff + new_cx);\n        registers_dirty = true;\n      }\n      last_resume_orig_cx = 0;\n    }\n\n    if (did_set_breakpoint_after_cpuid) {\n      remote_code_ptr bkpt_addr =\n        address_of_last_execution_resume + special_instruction_len(singlestepping_instruction.opcode);\n      if (ip().undo_executed_bkpt(arch()) == bkpt_addr) {\n        Registers r = regs();\n        r.set_ip(bkpt_addr);\n        set_regs(r);\n      }\n      vm()->remove_breakpoint(bkpt_addr, BKPT_INTERNAL);\n      did_set_breakpoint_after_cpuid = false;\n    }\n    if ((singlestepping_instruction.opcode == SpecialInstOpcode::X86_PUSHF ||\n         singlestepping_instruction.opcode == SpecialInstOpcode::X86_PUSHF16) &&\n        ip() == address_of_last_execution_resume +\n          special_instruction_len(singlestepping_instruction.opcode)) {\n      // We singlestepped through a pushf. Clear TF bit on stack.\n      auto sp = regs().sp().cast<uint16_t>();\n      // If this address is invalid then we should have segfaulted instead of\n      // retiring the instruction!\n      uint16_t val = read_mem(sp);\n      write_mem(sp, (uint16_t)(val & ~X86_TF_FLAG));\n    }\n    singlestepping_instruction.opcode = SpecialInstOpcode::NONE;\n\n    // We might have singlestepped at the resumption address and just exited\n    // the kernel without executing the breakpoint at that address.\n    // The kernel usually (always?) singlesteps an extra instruction when\n    // we do this with PTRACE_SYSEMU_SINGLESTEP, but rr's ptrace emulation\n    // doesn't and it's kind of a kernel bug.\n    if (as->get_breakpoint_type_at_addr(address_of_last_execution_resume) !=\n            BKPT_NONE &&\n        stop_sig() == SIGTRAP && !ptrace_event() &&\n        ip().undo_executed_bkpt(arch()) == address_of_last_execution_resume) {\n      ASSERT(this, more_ticks == 0);\n      // When we resume execution and immediately hit a breakpoint, the original\n      // syscall number can be reset to -1. Undo that, so that the register\n      // state matches the state we'd be in if we hadn't resumed. ReplayTimeline\n      // depends on resume-at-a-breakpoint being a noop.\n      registers.set_original_syscallno(original_syscallno);\n      registers_dirty = true;\n    }\n\n    // If we're in the rr page,  we may have just returned from an untraced\n    // syscall there and while in the rr page registers need to be consistent\n    // between record and replay. During replay most untraced syscalls are\n    // replaced with \"xor eax,eax\" (right after a \"movq -1, %rcx\") so\n    // rcx is always -1, but during recording it sometimes isn't after we've\n    // done a real syscall.\n    if (is_in_rr_page()) {\n      // N.B.: Cross architecture syscalls don't go through the rr page, so we\n      // know what the architecture is.\n      canonicalize_regs(arch());\n    }\n  }\n\n  did_wait();\n  return true;\n}\n\ntemplate <typename Arch>\nstatic void set_tls_from_clone_arch(Task* t, remote_ptr<void> tls) {\n  if (Arch::clone_tls_type == Arch::UserDescPointer) {\n    t->set_thread_area(tls.cast<X86Arch::user_desc>());\n  }\n}\n\nstatic void set_tls_from_clone(Task* t, remote_ptr<void> tls) {\n  RR_ARCH_FUNCTION(set_tls_from_clone_arch, t->arch(), t, tls);\n}\n\ntemplate <typename Arch>\nstatic void setup_preload_thread_locals_from_clone_arch(Task* t, Task* origin) {\n  void* local_addr = preload_thread_locals_local_addr(*t->vm());\n  if (local_addr) {\n    t->activate_preload_thread_locals();\n    auto locals = reinterpret_cast<preload_thread_locals<Arch>*>(local_addr);\n    auto origin_locals = reinterpret_cast<const preload_thread_locals<Arch>*>(\n        origin->fetch_preload_thread_locals());\n    locals->alt_stack_nesting_level = origin_locals->alt_stack_nesting_level;\n    // vfork() will restore the flags on the way out since its on the same\n    // stack.\n    locals->saved_flags = origin_locals->saved_flags;\n    // clone() syscalls set the child stack pointer, so the child is no\n    // longer in the syscallbuf code even if the parent was.\n    if (PRELOAD_THREAD_LOCAL_SCRATCH2_SIZE >= 8 * 2) {\n      // On aarch64, we use this to save and restore some register values across clone\n      memcpy(locals->stub_scratch_2, origin_locals->stub_scratch_2, 8 * 2);\n    }\n  }\n}\n\nvoid Task::setup_preload_thread_locals_from_clone(Task* origin) {\n  RR_ARCH_FUNCTION(setup_preload_thread_locals_from_clone_arch, this->arch(), this, origin);\n}\n\nTask* Task::clone(CloneReason reason, int flags, remote_ptr<void> stack,\n                  remote_ptr<void> tls, remote_ptr<int>, pid_t new_tid,\n                  pid_t new_rec_tid, uint32_t new_serial,\n                  Session* other_session,\n                  FdTable::shr_ptr new_fds,\n                  ThreadGroup::shr_ptr new_tg) {\n  Session* new_task_session = &session();\n  if (other_session) {\n    ASSERT(this, reason != TRACEE_CLONE);\n    new_task_session = other_session;\n  } else {\n    ASSERT(this, reason == TRACEE_CLONE);\n  }\n  string n;\n  if (!session().is_recording()) {\n    n = name();\n  }\n  Task* t =\n      new_task_session->new_task(new_tid, new_rec_tid, new_serial, arch(), n);\n\n  if (CLONE_SHARE_VM & flags) {\n    t->as = as;\n    if (!stack.is_null()) {\n      remote_ptr<void> last_stack_byte = stack - 1;\n      if (t->as->has_mapping(last_stack_byte)) {\n        auto mapping = t->as->mapping_of(last_stack_byte);\n        if (!mapping.recorded_map.is_heap()) {\n          const KernelMapping& m = mapping.map;\n          LOG(debug) << \"mapping stack for \" << new_tid << \" at \" << m;\n          t->as->map(t, m.start(), m.size(), m.prot(), m.flags(),\n                     m.file_offset_bytes(), \"[stack]\", m.device(), m.inode());\n        }\n      }\n    }\n    // rseq state is not cloned into new threads\n  } else {\n    t->as = new_task_session->clone(t, as);\n    if (rseq_state) {\n      // rseq state is cloned into non-thread children\n      t->rseq_state = make_unique<RseqState>(*rseq_state);\n    }\n  }\n\n  t->syscallbuf_size = syscallbuf_size;\n  t->preload_globals = preload_globals;\n  t->seccomp_bpf_enabled = seccomp_bpf_enabled;\n\n  // FdTable is either shared or copied, so the contents of\n  // syscallbuf_fds_disabled_child are still valid.\n  if (CLONE_SHARE_FILES & flags) {\n    ASSERT(this, !new_fds);\n    t->fds = fds;\n  } else if (new_fds) {\n    t->fds = new_fds;\n  } else {\n    t->fds = fds->clone();\n  }\n  t->fds->insert_task(t);\n\n  t->top_of_stack = stack;\n\n  // wait() before trying to do anything that might need to\n  // use ptrace to access memory\n  bool ok = t->wait();\n  ASSERT(t, ok) << \"Task \" << t->tid << \" killed unexpectedly; not sure how to handle this\";\n\n  t->post_wait_clone(this, flags);\n  if (CLONE_SHARE_THREAD_GROUP & flags) {\n    ASSERT(this, !new_tg);\n    t->tg = tg;\n  } else {\n    if (new_tg) {\n      t->tg = new_tg;\n    } else {\n      t->tg = new_task_session->clone(t, tg);\n    }\n  }\n  t->tg->insert_task(t);\n\n  t->open_mem_fd_if_needed();\n  t->thread_areas_ = thread_areas_;\n  if (CLONE_SET_TLS & flags) {\n    set_tls_from_clone(t, tls);\n  }\n\n  t->as->insert_task(t);\n\n  if (reason == TRACEE_CLONE) {\n    if (!(CLONE_SHARE_VM & flags)) {\n      // Unmap syscallbuf and scratch for tasks running the original address\n      // space.\n      AutoRemoteSyscalls remote(t);\n      for (Task* tt : as->task_set()) {\n        // Leak the scratch buffer for the task we cloned from. We need to do\n        // this because we may be using part of it for the syscallbuf stack\n        // and unmapping it now would cause a crash in the new task.\n        if (tt != this) {\n          t->unmap_buffers_for(remote, tt, tt->syscallbuf_child);\n        }\n      }\n      as->did_fork_into(t);\n    }\n\n    // `t` doesn't have a syscallbuf and `t->desched_fd_child`/\n    // `t->cloned_file_data_fd_child` are both -1.\n    if (session().is_replaying()) {\n      // `t` is not really sharing our fd table, in fact our real fd table\n      // is only used by this task, so it only contains our syscallbuf fds (if any),\n      // not the fds for any other task. So, only really-close the fds for 'this'.\n      // We still need to update t's `fds` table to indicate that those fds were\n      // closed during recording, though, otherwise we may get FileMonitor\n      // collisions.\n      AutoRemoteSyscalls remote(t);\n      for (Task* tt : fds->task_set()) {\n        t->close_buffers_for(remote, tt, tt == this);\n      }\n    } else if (CLONE_SHARE_FILES & flags) {\n      // `t` is sharing our fd table, so it should not close anything.\n    } else {\n      // Close syscallbuf fds for all tasks using the original fd table.\n      AutoRemoteSyscalls remote(t);\n      for (Task* tt : fds->task_set()) {\n        t->close_buffers_for(remote, tt, true);\n      }\n    }\n  }\n\n  t->post_vm_clone(reason, flags, this);\n\n  // Copy debug register values. We assume the kernel will either copy debug\n  // registers into the new task, or the debug registers will be unset\n  // in the new task. If we have no HW watchpoints then debug registers\n  // will definitely be unset in the new task so there is nothing to do.\n  if (!current_hardware_watchpoints.empty()) {\n    // Copy debug register settings into the new task so we're in a known state.\n    bool ret = set_debug_regs_internal(t, current_hardware_watchpoints);\n    if (!ret) {\n      LOG(warn) << \"Failed to initialize new task's debug registers; \"\n                << \"this should always work since we were able to set them in the old task, \"\n                << \"but the new task might have been killed\";\n    }\n    t->current_hardware_watchpoints = current_hardware_watchpoints;\n  }\n\n  return t;\n}\n\nbool Task::post_vm_clone(CloneReason reason, int flags, Task* origin) {\n  bool created_preload_thread_locals_mapping = false;\n  if (!(CLONE_SHARE_VM & flags)) {\n    created_preload_thread_locals_mapping = this->as->post_vm_clone(this);\n  }\n  this->as->fd_tables_changed();\n\n  if (reason == TRACEE_CLONE) {\n    setup_preload_thread_locals_from_clone(origin);\n  }\n\n  return created_preload_thread_locals_mapping;\n}\n\nTask* Task::os_fork_into(Session* session, FdTable::shr_ptr new_fds) {\n  AutoRemoteSyscalls remote(this, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);\n  Task* child =\n      os_clone(Task::SESSION_CLONE_LEADER, session, remote, rec_tid, serial,\n               // Most likely, we'll be setting up a\n               // CLEARTID futex.  That's not done\n               // here, but rather later in\n               // |copy_state()|.\n               //\n               // We also don't use any of the SETTID\n               // flags because that earlier work will\n               // be copied by fork()ing the address\n               // space.\n               SIGCHLD,\n               std::move(new_fds));\n  // When we forked ourselves, the child inherited the setup we\n  // did to make the clone() call.  So we have to \"finish\" the\n  // remote calls (i.e. undo fudged state) in the child too,\n  // even though we never made any syscalls there.\n  remote.restore_state_to(child);\n  return child;\n}\n\nTask* Task::os_clone_into(const CapturedState& state,\n                          AutoRemoteSyscalls& remote,\n                          const ClonedFdTables& cloned_fd_tables,\n                          ThreadGroup::shr_ptr new_tg) {\n  auto fdtable_entry = cloned_fd_tables.find(state.fdtable_identity);\n  DEBUG_ASSERT(fdtable_entry != cloned_fd_tables.end() &&\n               \"All captured fd tables should be in cloned_fd_tables\");\n  return os_clone(Task::SESSION_CLONE_NONLEADER, &remote.task()->session(),\n                  remote, state.rec_tid, state.serial,\n                  // We don't actually /need/ to specify the\n                  // SIGHAND/SYSVMEM flags because those things\n                  // are emulated in the tracee.  But we use the\n                  // same flags as glibc to be on the safe side\n                  // wrt kernel bugs.\n                  //\n                  // We don't pass CLONE_SETTLS here *only*\n                  // because we'll do it later in\n                  // |copy_state()|.\n                  //\n                  // See |os_fork_into()| above for discussion\n                  // of the CTID flags.\n                  (CLONE_VM | CLONE_FS | CLONE_SIGHAND |\n                   CLONE_SYSVSEM),\n                  fdtable_entry->second,\n                  std::move(new_tg),\n                  state.top_of_stack);\n}\n\ntemplate <typename Arch>\nstatic void copy_tls_arch(const Task::CapturedState& state,\n                          AutoRemoteSyscalls& remote) {\n  if (Arch::clone_tls_type == Arch::UserDescPointer) {\n    for (const auto& t : state.thread_areas) {\n      AutoRestoreMem remote_tls(remote, (const uint8_t*)&t, sizeof(t));\n      LOG(debug) << \"    setting tls \" << remote_tls.get();\n      remote.infallible_syscall(\n          syscall_number_for_set_thread_area(remote.arch()),\n          remote_tls.get().as_int());\n    }\n  } else if (Arch::arch() == aarch64) {\n    remote.task()->set_aarch64_tls_register(state.tls_register);\n  }\n}\n\nstatic void copy_tls(const Task::CapturedState& state,\n                     AutoRemoteSyscalls& remote) {\n  RR_ARCH_FUNCTION(copy_tls_arch, remote.arch(), state, remote);\n}\n\nstatic int64_t fdinfo_field(Task* t, int fd, const char* field, bool must_exist) {\n  char buf[1024];\n  sprintf(buf, \"/proc/%d/fdinfo/%d\", t->tid, fd);\n  ScopedFd info(buf, O_RDONLY);\n  if (must_exist) {\n    ASSERT(t, info.is_open()) << \"Can't open \" << buf;\n  } else if (!info.is_open()) {\n    return -1;\n  }\n  ssize_t bytes = read(info, buf, sizeof(buf) - 1);\n  ASSERT(t, bytes > 0);\n  buf[bytes] = 0;\n\n  char* p = buf;\n  size_t field_len = strlen(field);\n  while (*p) {\n    if (strncmp(p, field, field_len) == 0) {\n      char* end;\n      long long int r = strtoll(p + field_len, &end, 10);\n      ASSERT(t, *end == 0 || *end == '\\n');\n      return r;\n    }\n    while (*p) {\n      if (*p == '\\n') {\n        ++p;\n        break;\n      }\n      ++p;\n    }\n  }\n  return -1;\n}\n\nint64_t Task::fd_offset(int fd) {\n  return fdinfo_field(this, fd, \"pos:\", true);\n}\n\npid_t Task::pid_of_pidfd(int fd) {\n  return fdinfo_field(this, fd, \"Pid:\", false);\n}\n\nTask::CapturedState Task::capture_state() {\n  CapturedState state;\n  state.rec_tid = rec_tid;\n  state.own_namespace_rec_tid = own_namespace_rec_tid;\n  state.fdtable_identity = uintptr_t(fds.get());\n  state.serial = serial;\n  state.tguid = thread_group()->tguid();\n  state.regs = regs();\n  state.extra_regs = *extra_regs_fallible();\n  state.prname = name();\n  if (arch() == aarch64) {\n    bool ok = read_aarch64_tls_register(&state.tls_register);\n    ASSERT(this, ok) << \"Tracee died; this shouldn't happen in replay\";\n  }\n  if (rseq_state) {\n    state.rseq_state = make_unique<RseqState>(*rseq_state);\n  }\n\n  state.thread_areas = thread_areas_;\n  state.desched_fd_child = desched_fd_child;\n  state.cloned_file_data_fd_child = cloned_file_data_fd_child;\n  state.cloned_file_data_fname = cloned_file_data_fname;\n  state.cloned_file_data_offset =\n      cloned_file_data_fd_child >= 0\n          ? fd_offset(cloned_file_data_fd_child)\n          : 0;\n  memcpy(&state.thread_locals, fetch_preload_thread_locals(),\n         PRELOAD_THREAD_LOCALS_SIZE);\n  state.syscallbuf_child = syscallbuf_child;\n  state.syscallbuf_size = syscallbuf_size;\n  state.preload_globals = preload_globals;\n  state.scratch_ptr = scratch_ptr;\n  state.scratch_size = scratch_size;\n  state.wait_status = wait_status;\n  state.ticks = ticks;\n  state.top_of_stack = top_of_stack;\n  return state;\n}\n\nvoid Task::copy_state(const CapturedState& state) {\n  set_regs(state.regs);\n  set_extra_regs(state.extra_regs);\n  {\n    AutoRemoteSyscalls remote(this);\n    set_name(remote, state.prname);\n    copy_tls(state, remote);\n    thread_areas_ = state.thread_areas;\n    syscallbuf_size = state.syscallbuf_size;\n\n    ASSERT(this, !syscallbuf_child)\n        << \"Syscallbuf should not already be initialized in clone\";\n    if (!state.syscallbuf_child.is_null()) {\n      // All these fields are preserved by the fork.\n      desched_fd_child = state.desched_fd_child;\n      cloned_file_data_fd_child = state.cloned_file_data_fd_child;\n      cloned_file_data_fname = state.cloned_file_data_fname;\n      if (cloned_file_data_fd_child >= 0) {\n        ScopedFd fd(cloned_file_data_fname.c_str(), session().as_record() ?\n          O_RDWR : O_RDONLY);\n        remote.infallible_send_fd_dup(fd, cloned_file_data_fd_child, O_CLOEXEC);\n        remote.infallible_lseek_syscall(\n            cloned_file_data_fd_child, state.cloned_file_data_offset, SEEK_SET);\n      }\n      syscallbuf_child = state.syscallbuf_child;\n    }\n  }\n  preload_globals = state.preload_globals;\n  ASSERT(this, as->thread_locals_tuid() != tuid());\n  memcpy(&thread_locals, &state.thread_locals, PRELOAD_THREAD_LOCALS_SIZE);\n  // The scratch buffer (for now) is merely a private mapping in\n  // the remote task.  The CoW copy made by fork()'ing the\n  // address space has the semantics we want.  It's not used in\n  // replay anyway.\n  scratch_ptr = state.scratch_ptr;\n  scratch_size = state.scratch_size;\n\n  // Whatever |from|'s last wait status was is what ours would\n  // have been.\n  wait_status = state.wait_status;\n\n  ticks = state.ticks;\n  own_namespace_rec_tid = state.own_namespace_rec_tid;\n  if (state.rseq_state) {\n    rseq_state = make_unique<RseqState>(*state.rseq_state);\n  }\n}\n\nsize_t Task::syscallbuf_data_size() {\n  return read_mem(REMOTE_PTR_FIELD(syscallbuf_child, num_rec_bytes)) +\n         session().syscallbuf_hdr_size();\n}\n\nremote_ptr<const struct syscallbuf_record> Task::next_syscallbuf_record() {\n  return (syscallbuf_child.cast<uint8_t>() + syscallbuf_data_size())\n      .cast<const struct syscallbuf_record>();\n}\n\nlong Task::stored_record_size(\n    remote_ptr<const struct syscallbuf_record> record) {\n  return ::stored_record_size(read_mem(REMOTE_PTR_FIELD(record, size)));\n}\n\nlong Task::fallible_ptrace(int request, remote_ptr<void> addr, void* data) {\n  return ptrace(_ptrace_request(request), tid, addr, data);\n}\n\nbool Task::open_mem_fd() {\n  // Use ptrace to read/write during open_mem_fd\n  as->set_mem_fd(ScopedFd());\n\n  if (!is_stopped_) {\n    LOG(warn) << \"Can't retrieve mem fd for \" << tid <<\n      \"; process not stopped, racing with exec?\";\n    return false;\n  }\n\n  /**\n   * We're expecting that either we or the child can read the mem fd.\n   * It's possible for both to not be the case (us on certain kernel\n   * configurations, the child after it did a setuid).\n   */\n  char pid_path[PATH_MAX];\n  sprintf(pid_path, \"/proc/%d\", tid);\n  ScopedFd dir_fd(pid_path, O_PATH);\n  if (dir_fd < 0) {\n    LOG(info) << \"Can't retrieve mem fd for \" << tid << \"; process no longer exists??\";\n    return false;\n  }\n\n  ScopedFd fd = ScopedFd::openat(dir_fd, \"mem\", O_RDWR | O_CLOEXEC);\n  if (!fd.is_open() && !is_exiting()) {\n    LOG(debug) << \"Falling back to the remote fd dance\";\n    AutoRemoteSyscalls remote(this);\n    int remote_mem_dir_fd = remote.send_fd(dir_fd);\n    if (remote_mem_dir_fd < 0) {\n      LOG(info) << \"Can't retrieve mem fd for \" << tid << \"; process is exiting?\";\n      return false;\n    }\n\n    char mem[] = \"mem\";\n    // If the remote dies, any of these can fail. That's ok, we'll just\n    // find that the fd wasn't successfully opened.\n    AutoRestoreMem remote_path(remote, mem, sizeof(mem));\n    int remote_mem_fd = remote.syscall(syscall_number_for_openat(arch()),\n                        remote_mem_dir_fd, remote_path.get(), O_RDWR);\n    if (remote_mem_fd < 0) {\n      LOG(info) << \"Can't retrieve mem fd for \" << tid\n        << \"; couldn't open /proc/...mem; errno=\" << errno_name(-remote_mem_fd);\n      return false;\n    }\n    fd = remote.retrieve_fd(remote_mem_fd);\n    remote.infallible_close_syscall_if_alive(remote_mem_fd);\n    remote.infallible_close_syscall_if_alive(remote_mem_dir_fd);\n  }\n\n  if (!fd.is_open()) {\n    LOG(info) << \"Can't retrieve mem fd for \" << tid << \"; process no longer exists?\";\n    return false;\n  }\n  as->set_mem_fd(std::move(fd));\n  return true;\n}\n\nvoid Task::open_mem_fd_if_needed() {\n  if (!as->mem_fd().is_open()) {\n    open_mem_fd();\n  }\n}\n\nScopedFd& Task::pagemap_fd() {\n  if (!as->pagemap_fd().is_open()) {\n    ScopedFd fd(proc_pagemap_path().c_str(), O_RDONLY | O_CLOEXEC);\n    if (fd.is_open()) {\n      as->set_pagemap_fd(std::move(fd));\n    } else {\n      LOG(info) << \"Can't retrieve pagemap fd for \" << tid;\n    }\n  }\n  return as->pagemap_fd();\n}\n\nKernelMapping Task::init_syscall_buffer(AutoRemoteSyscalls& remote,\n                                        remote_ptr<void> map_hint) {\n  char name[50];\n  sprintf(name, \"syscallbuf.%d\", rec_tid);\n  KernelMapping km =\n      Session::create_shared_mmap(remote, syscallbuf_size, map_hint, name);\n  if (!km.size()) {\n    return km;\n  }\n  remote.task()->vm()->mapping_flags_of(km.start()) |=\n      AddressSpace::Mapping::IS_SYSCALLBUF;\n\n  ASSERT(this, !syscallbuf_child)\n      << \"Should not already have syscallbuf initialized!\";\n\n  syscallbuf_child = km.start().cast<struct syscallbuf_hdr>();\n  return km;\n}\n\nvoid Task::set_syscallbuf_locked(bool locked) {\n  if (!syscallbuf_child) {\n    return;\n  }\n  remote_ptr<uint8_t> remote_addr = REMOTE_PTR_FIELD(syscallbuf_child, locked);\n  uint8_t locked_before = read_mem(remote_addr);\n  uint8_t new_locked = locked ? (locked_before | SYSCALLBUF_LOCKED_TRACER)\n                              : (locked_before & ~SYSCALLBUF_LOCKED_TRACER);\n  if (new_locked != locked_before) {\n    write_mem(remote_addr, new_locked);\n  }\n}\n\nvoid Task::reset_syscallbuf() {\n  if (!syscallbuf_child) {\n    return;\n  }\n\n  ASSERT(this,\n         !is_in_untraced_syscall() ||\n             0 == (SYSCALLBUF_LOCKED_TRACEE &\n                   read_mem(REMOTE_PTR_FIELD(syscallbuf_child, locked))));\n\n  // Memset is easiest to do by using the local mapping which should always\n  // exist for the syscallbuf\n  uint32_t num_rec =\n      read_mem(REMOTE_PTR_FIELD(syscallbuf_child, num_rec_bytes));\n  uint8_t* ptr = as->local_mapping(\n        syscallbuf_child.cast<void>() + session().syscallbuf_hdr_size(), num_rec);\n  DEBUG_ASSERT(ptr != nullptr);\n  memset(ptr, 0, num_rec);\n  write_mem(REMOTE_PTR_FIELD(syscallbuf_child, num_rec_bytes), (uint32_t)0);\n  write_mem(REMOTE_PTR_FIELD(syscallbuf_child, mprotect_record_count),\n            (uint32_t)0);\n  write_mem(REMOTE_PTR_FIELD(syscallbuf_child, mprotect_record_count_completed),\n            (uint32_t)0);\n  write_mem(REMOTE_PTR_FIELD(syscallbuf_child, blocked_sigs_generation),\n            (uint32_t)0);\n}\n\nssize_t Task::read_bytes_ptrace(remote_ptr<void> addr, ssize_t buf_size,\n                                void* buf) {\n  ssize_t nread = 0;\n  // ptrace operates on the word size of the host, so we really do want\n  // to use sizes of host types here.\n  uintptr_t word_size = sizeof(long);\n  errno = 0;\n  // Only read aligned words. This ensures we can always read the last\n  // byte before an unmapped region.\n  while (nread < buf_size) {\n    uintptr_t start = addr.as_int() + nread;\n    uintptr_t start_word = start & ~(word_size - 1);\n    uintptr_t end_word = start_word + word_size;\n    uintptr_t length = std::min(end_word - start, uintptr_t(buf_size - nread));\n\n    long v = fallible_ptrace(PTRACE_PEEKDATA, start_word, nullptr);\n    if (errno) {\n      break;\n    }\n    memcpy(static_cast<uint8_t*>(buf) + nread,\n           reinterpret_cast<uint8_t*>(&v) + (start - start_word), length);\n    nread += length;\n  }\n\n  return nread;\n}\n\nssize_t Task::write_bytes_ptrace(remote_ptr<void> addr, ssize_t buf_size,\n                                 const void* buf) {\n  ssize_t nwritten = 0;\n  // ptrace operates on the word size of the host, so we really do want\n  // to use sizes of host types here.\n  uintptr_t word_size = sizeof(long);\n  errno = 0;\n  // Only write aligned words. This ensures we can always write the last\n  // byte before an unmapped region.\n  while (nwritten < buf_size) {\n    uintptr_t start = addr.as_int() + nwritten;\n    uintptr_t start_word = start & ~(word_size - 1);\n    uintptr_t end_word = start_word + word_size;\n    uintptr_t length =\n        std::min(end_word - start, uintptr_t(buf_size - nwritten));\n\n    long v;\n    if (length < word_size) {\n      v = fallible_ptrace(PTRACE_PEEKDATA, start_word, nullptr);\n      if (errno) {\n        break;\n      }\n    }\n    memcpy(reinterpret_cast<uint8_t*>(&v) + (start - start_word),\n           static_cast<const uint8_t*>(buf) + nwritten, length);\n    fallible_ptrace(PTRACE_POKEDATA, start_word, reinterpret_cast<void*>(v));\n    nwritten += length;\n  }\n\n  return nwritten;\n}\n\nssize_t Task::read_bytes_fallible(remote_ptr<void> addr, ssize_t buf_size,\n                                  void* buf) {\n  ASSERT_ACTIONS(this, buf_size >= 0, << \"Invalid buf_size \" << buf_size);\n  if (0 == buf_size) {\n    return 0;\n  }\n\n  if (uint8_t* local_addr = as->local_mapping(addr, buf_size)) {\n    memcpy(buf, local_addr, buf_size);\n    return buf_size;\n  }\n\n  if (!as->mem_fd().is_open()) {\n    return read_bytes_ptrace(addr, buf_size, static_cast<uint8_t*>(buf));\n  }\n\n  ssize_t all_read = 0;\n  while (all_read < buf_size) {\n    errno = 0;\n    ssize_t nread = pread64(as->mem_fd(), static_cast<uint8_t*>(buf) + all_read,\n                            buf_size - all_read, addr.as_int() + all_read);\n    // We open the mem_fd just after being notified of\n    // exec(), when the Task is created.  Trying to read from that\n    // fd seems to return 0 with errno 0.  Reopening the mem fd\n    // allows the pwrite to succeed.  It seems that the first mem\n    // fd we open, very early in exec, refers to the address space\n    // before the exec and the second mem fd refers to the address\n    // space after exec.\n    if (0 == nread && 0 == all_read && 0 == errno) {\n      if (!open_mem_fd()) {\n        return 0;\n      }\n      continue;\n    }\n    if (nread <= 0) {\n      if (all_read > 0) {\n        // We did successfully read some data, so return success and ignore\n        // any error.\n        errno = 0;\n        return all_read;\n      }\n      return nread;\n    }\n    // We read some data. We should try again in case we get short reads.\n    all_read += nread;\n  }\n  return all_read;\n}\n\nvoid Task::read_bytes_helper(remote_ptr<void> addr, ssize_t buf_size, void* buf,\n                             bool* ok) {\n  // pread64 etc can't handle addresses that appear to be negative ...\n  // like [vsyscall].\n  ssize_t nread = read_bytes_fallible(addr, buf_size, buf);\n  if (nread != buf_size) {\n    if (ok) {\n      *ok = false;\n    } else {\n      ASSERT(this, false) << \"Should have read \" << buf_size << \" bytes from \"\n                          << addr << \", but only read \" << nread;\n    }\n  }\n}\n\n/**\n * This function was initially created to work around\n * https://bugzilla.kernel.org/show_bug.cgi?id=99101.\n * On some kernels pwrite() to /proc/.../mem fails when writing to a region\n * that's PROT_NONE. Actually this was fixed in kernel 4.8 but we still\n * support 4.7 for now and there's no point in bumping the version\n * requirement just to avoid this, especially because...\n * Writing through MAP_SHARED readonly mappings fails (even if the\n * file was opened read-write originally), so we handle that here too. This\n * seems to be an issue for all kernel versions up to the present day.\n */\nstatic ssize_t safe_pwrite64(Task* t, const void* buf, ssize_t buf_size,\n                             remote_ptr<void> addr) {\n  vector<KernelMapping> mappings_to_fix;\n  for (const auto& m :\n       t->vm()->maps_containing_or_after(floor_page_size(addr))) {\n    if (m.map.start() >= ceil_page_size(addr + buf_size)) {\n      break;\n    }\n    if (m.map.prot() & PROT_WRITE) {\n      continue;\n    }\n    if (!(m.map.prot() & PROT_READ) || (m.map.flags() & MAP_SHARED)) {\n      // Limit the mapping change to the region we're actually going to write to.\n      // Kernel 6.15 reports ENOMEM trying mprotect PROT_WRITE colossal\n      // MAP_PRIVATE mappings. For some reason MAP_SHARED is OK...\n      auto start = floor_page_size(addr);\n      auto end = ceil_page_size(addr + buf_size);\n      mappings_to_fix.push_back(m.map.subrange(start, end));\n    }\n  }\n\n  if (mappings_to_fix.empty()) {\n    return pwrite_all_fallible(t->vm()->mem_fd(), buf, buf_size, addr.as_int());\n  }\n\n  AutoRemoteSyscalls remote(t);\n  int mprotect_syscallno = syscall_number_for_mprotect(t->arch());\n  bool failed_access = false;\n  for (auto& m : mappings_to_fix) {\n    int ret = remote.syscall(mprotect_syscallno, m.start(), m.size(), m.prot() | PROT_WRITE);\n    if (ret == -EACCES) {\n      // We could be trying to write to a read-only shared file. In that case we should\n      // report the error without dying.\n      failed_access = true;\n    } else if (remote.check_syscall_result(ret, mprotect_syscallno)) {\n      errno = ESRCH;\n      // No point continuing to go around the loop\n      return -1;\n    }\n  }\n  ssize_t nwritten;\n  if (failed_access) {\n    nwritten = -1;\n  } else {\n    nwritten = pwrite_all_fallible(t->vm()->mem_fd(), buf, buf_size, addr.as_int());\n  }\n  for (auto& m : mappings_to_fix) {\n    int ret = remote.infallible_syscall_if_alive(mprotect_syscallno, m.start(),\n                                                 m.size(), m.prot());\n    if (ret == -ESRCH) {\n      errno = ESRCH;\n      // No point continuing to go around the loop\n      return nwritten;\n    }\n  }\n  if (failed_access) {\n    errno = EACCES;\n  }\n  return nwritten;\n}\n\nssize_t Task::write_bytes_helper(remote_ptr<void> addr, ssize_t buf_size,\n                              const void* buf, bool* ok, uint32_t flags) {\n  ssize_t nwritten = write_bytes_helper_no_notifications(addr, buf_size, buf, ok, flags);\n  if (nwritten > 0) {\n    vm()->notify_written(addr, nwritten, flags);\n  }\n  return nwritten;\n}\n\nssize_t Task::write_bytes_helper_no_notifications(remote_ptr<void> addr, ssize_t buf_size,\n                                                  const void* buf, bool* ok, uint32_t flags) {\n  ASSERT(this, buf_size >= 0) << \"Invalid buf_size \" << buf_size;\n  if (0 == buf_size) {\n    return 0;\n  }\n\n  if (uint8_t* local_addr = as->local_mapping(addr, buf_size)) {\n    memcpy(local_addr, buf, buf_size);\n    return buf_size;\n  }\n\n  if (!as->mem_fd().is_open()) {\n    ssize_t nwritten =\n        write_bytes_ptrace(addr, buf_size, static_cast<const uint8_t*>(buf));\n    if (ok && nwritten < buf_size) {\n      *ok = false;\n    }\n    return nwritten;\n  }\n\n  errno = 0;\n  ssize_t nwritten = safe_pwrite64(this, buf, buf_size, addr.as_int());\n  // See comment in read_bytes_helper().\n  if (0 == nwritten && 0 == errno) {\n    open_mem_fd();\n    return write_bytes_helper_no_notifications(addr, buf_size, buf, ok, flags);\n  }\n  if (errno == EPERM) {\n    FATAL() << \"Can't write to /proc/\" << tid << \"/mem\\n\"\n            << \"Maybe you need to disable grsecurity MPROTECT with:\\n\"\n            << \"  setfattr -n user.pax.flags -v 'emr' <executable>\";\n  }\n  if (ok) {\n    if (nwritten < buf_size) {\n      *ok = false;\n    }\n  } else {\n    ASSERT(this, nwritten == buf_size)\n        << \"Should have written \" << buf_size << \" bytes to \" << addr\n        << \", but only wrote \" << nwritten;\n  }\n  return nwritten;\n}\n\nuint64_t Task::write_ranges(const vector<FileMonitor::Range>& ranges,\n                            void* data, size_t size) {\n  uint8_t* p = static_cast<uint8_t*>(data);\n  size_t s = size;\n  size_t result = 0;\n  for (auto& r : ranges) {\n    size_t bytes = min(s, r.length);\n    write_bytes_helper(r.data, bytes, p);\n    s -= bytes;\n    result += bytes;\n    if (s == 0) {\n      break;\n    }\n  }\n  return result;\n}\n\nvoid Task::write_zeroes(unique_ptr<AutoRemoteSyscalls>* remote, remote_ptr<void> addr, size_t size) {\n  if (!size) {\n    return;\n  }\n\n  remote_ptr<void> initial_addr = addr;\n  size_t initial_size = size;\n  vector<uint8_t> zeroes;\n  while (size > 0) {\n    size_t bytes;\n    remote_ptr<void> start_page = ceil_page_size(addr);\n    if (addr < start_page) {\n      bytes = min<size_t>(start_page - addr, size);\n    } else {\n      // we're page-aligned. Try using an madvise call to quickly zero large\n      // areas. Process one VMA at a time.\n      const KernelMapping& m = vm()->mapping_of(start_page).map;\n      remote_ptr<void> end_page = min(floor_page_size(start_page + size), m.end());\n      if (start_page + 65536 <= end_page) {\n        if (!*remote) {\n          *remote = make_unique<AutoRemoteSyscalls>(this);\n        }\n        int advice = (m.flags() & MAP_ANONYMOUS) ? MADV_DONTNEED : MADV_REMOVE;\n        int ret = (*remote)->syscall(syscall_number_for_madvise(arch()),\n            start_page, end_page - start_page, advice);\n        if (ret == 0) {\n          addr = end_page;\n          size -= end_page - start_page;\n          continue;\n        }\n      }\n      bytes = min<size_t>(4*1024*1024, size);\n    }\n    zeroes.resize(bytes);\n    memset(zeroes.data(), 0, bytes);\n    ssize_t written = write_bytes_helper_no_notifications(addr, bytes, zeroes.data(), nullptr, 0);\n    ASSERT(this, written == (ssize_t)bytes);\n    addr += bytes;\n    size -= bytes;\n  }\n  vm()->notify_written(initial_addr, initial_size, 0);\n}\n\nvoid Task::will_schedule() {\n  if (rseq_state) {\n    // Relying on rseq_t being the same across architectures.\n    int cpu = session().trace_stream()->bound_to_cpu();\n    uint32_t cpu_id = cpu >= 0 ? cpu : 0;\n    auto addr = REMOTE_PTR_FIELD(rseq_state->ptr.cast<typename NativeArch::rseq_t>(), cpu_id_start);\n    bool ok = true;\n    write_mem(addr, cpu_id, &ok);\n    addr = REMOTE_PTR_FIELD(rseq_state->ptr.cast<typename NativeArch::rseq_t>(), cpu_id);\n    write_mem(addr, cpu_id, &ok);\n  }\n}\n\nconst TraceStream* Task::trace_stream() const {\n  if (session().as_record()) {\n    return &session().as_record()->trace_writer();\n  }\n  if (session().as_replay()) {\n    return &session().as_replay()->trace_reader();\n  }\n  return nullptr;\n}\n\nbool Task::ptrace_if_stopped(int request, remote_ptr<void> addr, void* data) {\n  ASSERT(this, is_stopped_);\n\n  errno = 0;\n  fallible_ptrace(request, addr, data);\n  if (errno == ESRCH) {\n    LOG(debug) << \"ptrace_if_stopped tid \" << tid << \" was not stopped\";\n    return false;\n  }\n  ASSERT(this, !errno) << \"ptrace(\" << ptrace_req_name<NativeArch>(request) << \", \" << tid\n                       << \", addr=\" << addr << \", data=\" << data\n                       << \") failed with errno \" << errno;\n  return true;\n}\n\nSupportedArch Task::detect_syscall_arch() {\n  SupportedArch syscall_arch;\n  bool ok = get_syscall_instruction_arch(\n      this, regs().ip().decrement_by_syscall_insn_length(arch()),\n      &syscall_arch);\n  ASSERT(this, ok);\n  return syscall_arch;\n}\n\nbool Task::clone_syscall_is_complete(pid_t* new_pid,\n                                     SupportedArch syscall_arch) {\n  int event = ptrace_event();\n  if (PTRACE_EVENT_CLONE == event || PTRACE_EVENT_FORK == event ||\n      PTRACE_EVENT_VFORK == event) {\n    *new_pid = get_ptrace_eventmsg_pid();\n    ASSERT(this, *new_pid >= 0)\n      << \"Task was killed just after clone/fork/vfork and before we could get the new pid; giving up\";\n    return true;\n  }\n  ASSERT(this, !event) << \"Unexpected ptrace event \"\n                       << ptrace_event_name(event);\n\n  // EAGAIN can happen here due to fork failing under load. The caller must\n  // handle this.\n  // XXX ENOSYS shouldn't happen here.\n  intptr_t result = regs().syscall_result_signed();\n  ASSERT(this,\n         regs().syscall_may_restart() || -ENOSYS == result ||\n             -EAGAIN == result || -ENOMEM == result)\n      << \"Unexpected task status \" << status() << \" (\"\n      << syscall_name(regs().original_syscallno(), syscall_arch)\n      << \" syscall errno: \" << errno_name(-result) << \")\";\n  return false;\n}\n\ntemplate <typename Arch> static void do_preload_init_arch(Task* t) {\n  auto params = t->read_mem(\n      remote_ptr<rrcall_init_preload_params<Arch>>(t->regs().orig_arg1()));\n\n  for (Task* tt : t->vm()->task_set()) {\n    tt->preload_globals = params.globals.rptr();\n  }\n\n  ReplaySession *replay = t->session().as_replay();\n  if (replay && replay->has_trace_quirk(TraceReader::UsesGlobalsInReplay)) {\n    t->write_mem(REMOTE_PTR_FIELD(t->preload_globals, reserved_legacy_in_replay), (unsigned char)1);\n  }\n}\n\nstatic void do_preload_init(Task* t) {\n  RR_ARCH_FUNCTION(do_preload_init_arch, t->arch(), t);\n}\n\nvoid Task::at_preload_init() {\n  as->at_preload_init(this);\n  do_preload_init(this);\n\n  fd_table()->init_syscallbuf_fds_disabled(this);\n}\n\ntemplate <typename Arch>\nstatic long perform_remote_clone_arch(\n    AutoRemoteSyscalls& remote, unsigned base_flags, remote_ptr<void> stack,\n    remote_ptr<int> ptid, remote_ptr<void> tls, remote_ptr<int> ctid) {\n  switch (Arch::clone_parameter_ordering) {\n    case Arch::FlagsStackParentTLSChild:\n      return remote.syscall(Arch::clone, base_flags, stack, ptid.as_int(),\n                            tls.as_int(), ctid.as_int());\n    case Arch::FlagsStackParentChildTLS:\n      return remote.syscall(Arch::clone, base_flags, stack, ptid.as_int(),\n                            ctid.as_int(), tls.as_int());\n  }\n}\n\nstatic long perform_remote_clone(AutoRemoteSyscalls& remote,\n                                 unsigned base_flags, remote_ptr<void> stack,\n                                 remote_ptr<int> ptid, remote_ptr<void> tls,\n                                 remote_ptr<int> ctid) {\n  RR_ARCH_FUNCTION(perform_remote_clone_arch, remote.arch(), remote, base_flags,\n                   stack, ptid, tls, ctid);\n}\n\n/*static*/ Task* Task::os_clone(CloneReason reason, Session* session,\n                                AutoRemoteSyscalls& remote, pid_t rec_child_tid,\n                                uint32_t new_serial, unsigned base_flags,\n                                FdTable::shr_ptr new_fds,\n                                ThreadGroup::shr_ptr new_tg,\n                                remote_ptr<void> stack, remote_ptr<int> ptid,\n                                remote_ptr<void> tls, remote_ptr<int> ctid) {\n  long ret;\n  do {\n    ret = perform_remote_clone(remote, base_flags, stack, ptid, tls, ctid);\n  } while (ret == -EAGAIN);\n  ASSERT(remote.task(), ret >= 0)\n      << \"remote clone failed with errno \" << errno_name(-ret);\n\n  Task* child = remote.task()->clone(\n      reason, clone_flags_to_task_flags(base_flags), stack, tls, ctid,\n      remote.new_tid(), rec_child_tid, new_serial, session, std::move(new_fds),\n      std::move(new_tg));\n  return child;\n}\n\nstatic void setup_fd_table(Task* t, FdTable& fds, int tracee_socket_fd_number) {\n  fds.add_monitor(t, STDOUT_FILENO, new StdioMonitor(t->session().tracee_output_fd(STDOUT_FILENO)));\n  fds.add_monitor(t, STDERR_FILENO, new StdioMonitor(t->session().tracee_output_fd(STDERR_FILENO)));\n  fds.add_monitor(t, RR_MAGIC_SAVE_DATA_FD, new MagicSaveDataMonitor());\n  fds.add_monitor(t, tracee_socket_fd_number, new PreserveFileMonitor());\n}\n\nstatic void spawned_child_fatal_error(const ScopedFd& err_fd,\n                                      const char* format, ...) {\n  va_list args;\n  va_start(args, format);\n  char* buf;\n  if (vasprintf(&buf, format, args) < 0) {\n    exit(1);\n  }\n\n  char* buf2;\n  if (asprintf(&buf2, \"%s (%s)\", buf, errno_name(errno).c_str()) < 0) {\n    exit(1);\n  }\n  write_all(err_fd, buf2, strlen(buf2));\n  _exit(1);\n}\n\nstatic void disable_tsc(const ScopedFd& err_fd) {\n  /* Trap to the rr process if a 'rdtsc' instruction is issued.\n   * That allows rr to record the tsc and replay it\n   * deterministically. */\n  if (0 > prctl(PR_SET_TSC, PR_TSC_SIGSEGV, 0, 0, 0)) {\n    spawned_child_fatal_error(err_fd, \"error setting up prctl\");\n  }\n}\n\ntemplate <typename Arch> void set_up_process_arch(const ScopedFd&);\ntemplate <> void set_up_process_arch<X86Arch>(const ScopedFd& err_fd) { disable_tsc(err_fd); }\ntemplate <> void set_up_process_arch<X64Arch>(const ScopedFd& err_fd) { disable_tsc(err_fd); }\ntemplate <> void set_up_process_arch<ARM64Arch>(const ScopedFd&) {}\n\nvoid set_up_process_arch(SupportedArch arch, const ScopedFd& err_fd) {\n  RR_ARCH_FUNCTION(set_up_process_arch, arch, err_fd);\n}\n\n/**\n * Prepare this process and its ancestors for recording/replay by\n * preventing direct access to sources of nondeterminism, and ensuring\n * that rr bugs don't adversely affect the underlying system.\n */\nstatic void set_up_process(Session& session, const ScopedFd& err_fd,\n                           const ScopedFd& sock_fd, int sock_fd_number) {\n  /* TODO tracees can probably undo some of the setup below\n   * ... */\n\n  // Restore signal mask\n  sigset_t sigmask;\n  TraceeAttentionSet::get_original_sigmask(&sigmask);\n  sigprocmask(SIG_SETMASK, &sigmask, nullptr);\n\n  // When creating a detach-teleport child, this task inherits signal\n  // handling set up by RecordCommand. So reset non-RT signal handlers\n  // to defaults now.\n  for (int sig = 1; sig <= 31; ++sig) {\n    signal(sig, SIG_DFL);\n  }\n\n  struct NativeArch::cap_header header = {.version =\n                                              _LINUX_CAPABILITY_VERSION_3,\n                                          .pid = 0 };\n  struct NativeArch::cap_data caps[2];\n  if (syscall(NativeArch::capget, &header, &caps) != 0) {\n    spawned_child_fatal_error(err_fd, \"Failed to read capabilities\");\n  }\n  uint32_t perfmon_mask = 1 << (CAP_PERFMON - 32);\n  if (caps[1].permitted & perfmon_mask) {\n    // Try to pass CAP_PERFMON into our tracees.\n    caps[1].inheritable |= perfmon_mask;\n    // Ignore any failures here. Capabilities are super complex and I'm not\n    // sure this can be trusted to succeed.\n    if (syscall(NativeArch::capset, &header, &caps) == 0) {\n      // Install CAP_PERFMON as an ambient capabilities.\n      // This prctl was only added in 4.3. Ignore failures.\n      prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_PERFMON, 0, 0);\n    }\n  }\n\n  /* CLOEXEC so that the original fd here will be closed by the exec that's\n   * about to happen.\n   */\n  int fd = open(\"/dev/null\", O_WRONLY | O_CLOEXEC);\n  if (0 > fd) {\n    spawned_child_fatal_error(err_fd, \"error opening /dev/null\");\n  }\n  if (RR_MAGIC_SAVE_DATA_FD != dup2(fd, RR_MAGIC_SAVE_DATA_FD)) {\n    spawned_child_fatal_error(err_fd, \"error duping to RR_MAGIC_SAVE_DATA_FD\");\n  }\n\n  if (sock_fd_number != dup2(sock_fd, sock_fd_number)) {\n    spawned_child_fatal_error(err_fd,\n                              \"error duping to RR_RESERVED_SOCKET_FD\");\n  }\n\n  if (session.is_replaying()) {\n    // This task and all its descendants should silently reap any terminating\n    // children.\n    if (SIG_ERR == signal(SIGCHLD, SIG_IGN)) {\n      spawned_child_fatal_error(err_fd, \"error doing signal()\");\n    }\n\n    // If the rr process dies, prevent runaway tracee processes\n    // from dragging down the underlying system.\n    //\n    // TODO: this isn't inherited across fork().\n    if (0 > prctl(PR_SET_PDEATHSIG, SIGKILL)) {\n      spawned_child_fatal_error(err_fd, \"Couldn't set parent-death signal\");\n    }\n\n    // Put the replaying processes into their own session. This will stop\n    // signals being sent to these processes by the terminal --- in particular\n    // SIGTSTP/SIGINT/SIGWINCH.\n    setsid();\n    // Preserve increased resource limits, in case the tracee\n    // increased its limits and we need high limits to apply during replay.\n  } else {\n    restore_initial_resource_limits();\n  }\n\n  /* Do any architecture specific setup, such as disabling non-deterministic\n     instructions */\n  set_up_process_arch(NativeArch::arch(), err_fd);\n\n  /* If we're in setuid_sudo mode, we have CAP_SYS_ADMIN, so we don't need to\n     set NO_NEW_PRIVS here in order to install the seccomp filter later. In,\n     emulate any potentially privileged, operations, so we might as well set\n     no_new_privs */\n  if (!session.is_recording() || !has_effective_caps(1 << CAP_SYS_ADMIN)) {\n    if (0 > prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {\n      spawned_child_fatal_error(\n          err_fd,\n          \"prctl(NO_NEW_PRIVS) failed, SECCOMP_FILTER is not available: your \"\n          \"kernel is too old. Use `record -n` to disable the filter.\");\n    }\n  }\n}\n\nstatic SeccompFilter<struct sock_filter> create_seccomp_filter() {\n  SeccompFilter<struct sock_filter> f;\n  for (auto& e : AddressSpace::rr_page_syscalls()) {\n    if (e.traced == AddressSpace::UNTRACED) {\n      auto ip = AddressSpace::rr_page_syscall_exit_point(e.traced, e.privileged,\n                                                         e.enabled,\n                                                         NativeArch::arch());\n      f.allow_syscalls_from_callsite(ip);\n    }\n  }\n  f.trace();\n  return f;\n}\n\n/**\n * This is called (and must be called) in the tracee after rr has taken\n * ptrace control. Otherwise, once we've installed the seccomp filter,\n * things go wrong because we have no ptracer and the seccomp filter demands\n * one.\n */\nstatic void set_up_seccomp_filter(const struct sock_fprog& prog, const ScopedFd& err_fd) {\n  /* Note: the filter is installed only for record. This call\n   * will be emulated (not passed to the kernel) in the replay. */\n  if (0 > prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (uintptr_t)&prog, 0, 0)) {\n    spawned_child_fatal_error(\n        err_fd, \"prctl(SECCOMP) failed, SECCOMP_FILTER is not available: your \"\n                \"kernel is too old.\");\n  }\n  /* anything that happens from this point on gets filtered! */\n}\n\nstatic void run_initial_child(Session& session, const ScopedFd& error_fd,\n                              const ScopedFd& sock_fd, int sock_fd_number,\n                              const char* exe_path_cstr,\n                              char* const argv_array[],\n                              char* const envp_array[],\n                              const struct sock_fprog& seccomp_prog) {\n  pid_t pid = getpid();\n\n  set_up_process(session, error_fd, sock_fd, sock_fd_number);\n  // The preceding code must run before sending SIGSTOP here,\n  // since after SIGSTOP replay emulates almost all syscalls, but\n  // we need the above syscalls to run \"for real\".\n\n  // Signal to tracer that we're configured.\n  ::kill(pid, SIGSTOP);\n\n  // This code must run after rr has taken ptrace control.\n  set_up_seccomp_filter(seccomp_prog, error_fd);\n\n  // We do a small amount of dummy work here to retire\n  // some branches in order to ensure that the ticks value is\n  // non-zero.  The tracer can then check the ticks value\n  // at the first ptrace-trap to see if it seems to be\n  // working.\n  int start = random() % 5;\n  int num_its = start + 5;\n  int sum = 0;\n  for (int i = start; i < num_its; ++i) {\n    sum += i;\n  }\n  syscall(SYS_write, -1, &sum, sizeof(sum));\n\n  CPUIDBugDetector::run_detection_code();\n\n  execve(exe_path_cstr, argv_array, envp_array);\n\n  switch (errno) {\n    case ENOENT:\n      spawned_child_fatal_error(\n          error_fd, \"execve failed: '%s' (or interpreter) not found\",\n          exe_path_cstr);\n      break;\n    default:\n      spawned_child_fatal_error(error_fd, \"execve of '%s' failed\",\n                                exe_path_cstr);\n      break;\n  }\n  // Never returns!\n}\n\nlong Task::ptrace_seize(pid_t tid, Session& session) {\n  intptr_t options = PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK |\n                     PTRACE_O_TRACECLONE;\n  if (!Flags::get().disable_ptrace_exit_events) {\n    options |= PTRACE_O_TRACEEXIT;\n  }\n  if (session.is_recording()) {\n    options |= PTRACE_O_TRACEVFORK | PTRACE_O_TRACESECCOMP | PTRACE_O_TRACEEXEC;\n  }\n\n  long ret =\n      ptrace((_ptrace_request)PTRACE_SEIZE, tid, nullptr, (void*)(options | PTRACE_O_EXITKILL));\n  if (ret < 0 && errno == EINVAL) {\n    // PTRACE_O_EXITKILL was added in kernel 3.8, and we only need\n    // it for more robust cleanup, so tolerate not having it.\n    ret = ptrace((_ptrace_request)PTRACE_SEIZE, tid, nullptr, (void*)options);\n  }\n  return ret;\n}\n\n/*static*/ Task* Task::spawn(Session& session, ScopedFd& error_fd,\n                             ScopedFd* sock_fd_out,\n                             ScopedFd* sock_fd_receiver_out,\n                             int* tracee_socket_fd_number_out,\n                             const std::string& exe_path,\n                             const std::vector<std::string>& argv,\n                             const std::vector<std::string>& envp,\n                             pid_t rec_tid) {\n  DEBUG_ASSERT(session.tasks().size() == 0);\n\n  int sockets[2];\n  long ret = socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, sockets);\n  if (ret < 0) {\n    FATAL() << \"socketpair failed\";\n  }\n  *sock_fd_out = ScopedFd(sockets[0]);\n  *sock_fd_receiver_out = ScopedFd(sockets[1]);\n\n  // Find a usable FD number to dup to in the child. RR_RESERVED_SOCKET_FD\n  // might already be used by an outer rr.\n  int fd_number = RR_RESERVED_SOCKET_FD;\n  // We assume no other thread is mucking with this part of the fd address space.\n  while (true) {\n    ret = fcntl(fd_number, F_GETFD);\n    if (ret < 0) {\n      if (errno != EBADF) {\n        FATAL() << \"Error checking fd\";\n      }\n      break;\n    }\n    ++fd_number;\n  }\n  *tracee_socket_fd_number_out = fd_number;\n\n  pid_t tid;\n  // After fork() in a multithreaded program, the child can safely call only\n  // async-signal-safe functions, and malloc is not one of them (breaks e.g.\n  // with tcmalloc).\n  // Doing the allocations before the fork duplicates the allocations, but\n  // prevents errors.\n  StringVectorToCharArray argv_array(argv);\n  StringVectorToCharArray envp_array(envp);\n  SeccompFilter<struct sock_filter> filter = create_seccomp_filter();\n  struct sock_fprog prog = {(unsigned short)filter.filters.size(),\n                            filter.filters.data()};\n  do {\n    tid = fork();\n    // fork() can fail with EAGAIN due to temporary load issues. In such\n    // cases, retry the fork().\n  } while (0 > tid && errno == EAGAIN);\n\n  if (0 == tid) {\n    run_initial_child(session, error_fd, *sock_fd_receiver_out, fd_number, exe_path.c_str(),\n                      argv_array.get(), envp_array.get(), prog);\n    // run_initial_child never returns\n  }\n\n  if (0 > tid) {\n    FATAL() << \"Failed to fork\";\n  }\n\n  // Make sure the child has the only reference to this side of the pipe.\n  error_fd.close();\n\n  // Sync with the child process.\n  // We minimize the code we run between fork()ing and PTRACE_SEIZE, because\n  // any abnormal exit of the rr process will leave the child paused and\n  // parented by the init process, i.e. effectively leaked. After PTRACE_SEIZE\n  // with PTRACE_O_EXITKILL, the tracee will die if rr dies.\n  if (getenv(\"RR_TEST_DELAY_SEIZE\")) {\n    sleep(1);\n  }\n  ret = ptrace_seize(tid, session);\n  // See early_error.c for the testing of these paths, which may need to be\n  // updated if these change.\n  if (ret) {\n    // Note that although the tracee may have died due to some fatal error,\n    // we haven't reaped its exit code so there's no danger of killing\n    // (or PTRACE_SEIZEing) the wrong process.\n    int tmp_errno = errno;\n    ::kill(tid, SIGKILL);\n    errno = tmp_errno;\n\n    string hint;\n    if (errno == EPERM) {\n      hint = \"; child probably died before reaching SIGSTOP\\n\"\n             \"Child's message: \" +\n             session.read_spawned_task_error();\n    }\n    FATAL() << \"PTRACE_SEIZE failed for tid \" << tid << hint;\n  }\n\n  Task* t = session.new_task(tid, rec_tid, session.next_task_serial(),\n                             NativeArch::arch(), \"rr\");\n  auto tg = session.create_initial_tg(t);\n  t->tg.swap(tg);\n  auto as = session.create_vm(t);\n  t->as.swap(as);\n  t->fds = FdTable::create(t);\n  setup_fd_table(t, *t->fds, fd_number);\n\n  // Install signal handler here, so that when creating the first RecordTask\n  // it sees the exact same signal state in the parent as will be in the child.\n  struct sigaction sa;\n  sa.sa_handler = handle_alarm_signal;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = 0; // No SA_RESTART, so waitpid() will be interrupted\n  sigaction(SIGALRM, &sa, nullptr);\n\n  if (!t->wait()) {\n    FATAL() << \"Tracee died before reaching SIGSTOP\";\n  }\n  if (t->ptrace_event() == PTRACE_EVENT_EXIT) {\n    t->proceed_to_exit();\n    FATAL() << \"Tracee died before reaching SIGSTOP\\n\"\n               \"Child's message: \"\n            << session.read_spawned_task_error();\n  }\n  // SIGSTOP can be reported as a signal-stop or group-stop depending on\n  // whether PTRACE_SEIZE happened before or after it was delivered.\n  if (SIGSTOP != t->status().stop_sig() &&\n      SIGSTOP != t->status().group_stop()) {\n    WaitStatus failed_status = t->status();\n    t->kill();\n    FATAL() << \"Unexpected stop \" << failed_status\n            << \"\\nChild's message: \"\n            << session.read_spawned_task_error();\n  }\n\n  t->clear_wait_status();\n  t->open_mem_fd();\n  return t;\n}\n\nvoid* Task::preload_thread_locals() {\n  return preload_thread_locals_local_addr(*as);\n}\n\nstatic bool file_was_deleted(string s) {\n  static const char deleted[] = \" (deleted)\";\n  ssize_t find_deleted = s.size() - (sizeof(deleted) - 1);\n  return s.find(deleted) == size_t(find_deleted);\n}\n\nstatic void create_mapping(Task *t, AutoRemoteSyscalls &remote, const KernelMapping &km) {\n  string real_file_name;\n  dev_t device = KernelMapping::NO_DEVICE;\n  ino_t inode = KernelMapping::NO_INODE;\n  if (km.is_real_device() && !file_was_deleted(km.fsname())) {\n    struct stat real_file;\n    string real_file_name;\n    remote.finish_direct_mmap(km.start(), km.size(), km.prot(), km.flags(),\n      km.fsname(), O_RDONLY, km.file_offset_bytes(),\n      real_file, real_file_name);\n  } else {\n    auto ret = remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),\n                                                       km.flags() | MAP_FIXED | MAP_ANONYMOUS, -1,\n                                                       0);\n    ASSERT(t, ret || t->vm()->task_set().size() == t->thread_group()->task_set().size())\n      << \"Not handling shared address spaces where one threadgroup unexpectedly dies\";\n  }\n  t->vm()->map(t, km.start(), km.size(), km.prot(), km.flags(), km.file_offset_bytes(),\n               real_file_name, device, inode, nullptr, &km);\n}\n\nstatic void apply_mm_map(AutoRemoteSyscalls& remote, const NativeArch::prctl_mm_map& map)\n{\n  unsigned int expected_size = 0;\n  int result = prctl(PR_SET_MM, PR_SET_MM_MAP_SIZE, &expected_size, 0, 0);\n  if (result != 0) {\n    FATAL() << \"Failed to get expected MM_MAP_SIZE. Error was \" << errno_name(-result);\n  }\n\n  const void* pmap = NULL;\n  int pmap_size = 0;\n\n  /* Expected size matches native prctl_mm_map */\n  if (expected_size == sizeof(map)) {\n    pmap = &map;\n    pmap_size = sizeof(map);\n  }\n\n#if defined(__i386__)\n  /* A 64-bit kernel expects a \"64-bit sized\" prctl_mm_map\n     even from a 32-bit process. */\n  X64Arch::prctl_mm_map map64;\n  if (expected_size == sizeof(map64)) {\n    LOG(warn) << \"Kernel expects different sized MM_MAP. Using 64-bit prctl_mm_map.\";\n    memcpy(&map64, &map, sizeof(map));\n    map64.auxv.val = map.auxv.val;\n    map64.auxv_size = map.auxv_size;\n    map64.exe_fd = map.exe_fd;\n\n    pmap = &map64;\n    pmap_size = sizeof(map64);\n  }\n#endif\n\n  /* Are we prepared for the requested structure size? */\n  if (pmap == NULL || pmap_size == 0) {\n    FATAL() << \"Kernel expects MM_MAP of size \" << expected_size;\n  }\n\n  AutoRestoreMem remote_mm_map(remote, (const uint8_t*)pmap, pmap_size);\n  result = remote.syscall(syscall_number_for_prctl(remote.task()->arch()), PR_SET_MM,\n                          PR_SET_MM_MAP, remote_mm_map.get().as_int(),\n                          pmap_size);\n  if (result == -EINVAL &&\n      (map.start_brk <= map.end_data || map.brk <= map.end_data)) {\n    CLEAN_FATAL() << \"The linux kernel prohibits duplication of this task's memory map,\" <<\n                \" because the brk segment is located below the data segment. Sorry.\";\n  }\n  else if (result != 0) {\n    FATAL() << \"Failed to set target task memory map. Error was \" << errno_name(-result);\n  }\n}\n\nstatic void copy_mem_mapping(Task* from, Task* to, const KernelMapping& km) {\n  vector<char> buf;\n  buf.resize(km.size());\n  ssize_t bytes = from->read_bytes_fallible(km.start(), km.size(), buf.data());\n  // There can be mappings of files where the mapping starts beyond the end-of-file\n  // so no bytes will be read.\n  if (bytes > 0) {\n    // We may have a short read here if there are beyond-end-of-mapped-file pages\n    // in the mapping.\n    bool ok = true;\n    to->write_bytes_helper(km.start(), bytes, buf.data(), &ok);\n    ASSERT(to, ok);\n  }\n}\n\n// https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/fs/proc/task_mmu.c?h=v6.3#n1352\n#define PM_PRESENT (1ULL << 63)\n#define PM_SWAP    (1ULL << 62)\n\nstatic bool copy_mem_mapping_just_used(Task* from, Task* to, const KernelMapping& km)\n{\n  ScopedFd& fd = from->pagemap_fd();\n  if (!fd.is_open()) {\n    LOG(debug) << \"Failed to open \" << from->proc_pagemap_path();\n    return false;\n  }\n\n  size_t pagesize = page_size();\n  uint64_t pages_present = 0; // Just for logging\n\n  const int max_buf_size = 65536;\n  vector<uint64_t> buf;\n\n  for (uintptr_t page_offset = 0; page_offset < km.size() / pagesize; page_offset += max_buf_size) {\n    auto page_read_offset = (km.start().as_int() / pagesize + page_offset);\n    size_t page_read_count = min<size_t>(max_buf_size, km.size() / pagesize - page_offset);\n    buf.resize(page_read_count);\n    size_t bytes_read = pread(fd, buf.data(), page_read_count * sizeof(uint64_t), page_read_offset * sizeof(uint64_t));\n    ASSERT(from, bytes_read == page_read_count * sizeof(uint64_t));\n\n    // A chunk was read from pagemap above, now iterate through it to detect\n    // if memory is physically present (bit 63, PM_PRESENT) or in swap (bit 62, PM_SWAP) in Task \"from\".\n    // If yes, just transfer those pages to the new Task \"to\".\n    // Also try to find consecutive pages to copy them in one operation.\n    // The file /proc/PID/pagemap consists of 64-bit values, each describing\n    // the state of one page. See https://www.kernel.org/doc/Documentation/vm/pagemap.txt\n\n    for (size_t page = 0; page < page_read_count; ++page) {\n      if (buf[page] & (PM_PRESENT | PM_SWAP)) {\n        auto start = km.start() + (page_offset + page) * pagesize;\n        if (start >= km.end()) {\n          break;\n        }\n        ++pages_present;\n\n        // Check for consecutive used pages\n        while (page + 1 < page_read_count &&\n               buf[page + 1] & (PM_PRESENT | PM_SWAP))\n        {\n          ++page;\n          ++pages_present;\n        }\n\n        auto end = km.start() + (page_offset + page + 1) * pagesize;\n        LOG(debug) << km << \" copying start: 0x\" << hex << start << \" end: 0x\" << end\n                   << dec << \" pages: \" << (end - start) / pagesize;\n        auto pages = km.subrange(start, end);\n        copy_mem_mapping(from, to, pages);\n      }\n    }\n  }\n  LOG(debug) << km << \" pages_present: \" << pages_present << \" pages_total: \" << km.size() / pagesize;\n  return true;\n}\n\nstatic void mremap_move(AutoRemoteSyscalls& remote, remote_ptr<void> src,\n    remote_ptr<void> dest, size_t size, const char* message) {\n  if (!size) {\n    return;\n  }\n  long ret = remote.syscall(syscall_number_for_mremap(remote.arch()),\n                            src, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, dest);\n  ASSERT(remote.task(), remote_ptr<void>(ret) == dest)\n    << \"Failed to move from \" << src << \" to \" << dest << \" \"\n    << HEX(size) << \" bytes, ret=\" << ret << \", \" << message;\n  remote.task()->vm()->remap(remote.task(), src, size, dest, size,\n                             MREMAP_MAYMOVE | MREMAP_FIXED);\n}\n\nstruct VMappings {\n  KernelMapping vdso;\n  KernelMapping vvar;\n  KernelMapping vvar_vclock;\n};\n\n/* Remap VDSO and VVAR to the addresses is used in the target process,\n   before they get unmapped.\n   Otherwise the kernel seems to put the address of the original\n   VDSO __kernel_rt_sigreturn function as return address on the stack.\n   This might not affect x86_64 because there __restore_rt\n   located in libpthread.so.0 is used.\n*/\nstatic void move_vdso_and_vvar_mappings(AutoRemoteSyscalls& remote,\n                                        const VMappings& new_) {\n  VMappings current;\n  Task* t = remote.task();\n  for (const auto& m : t->vm()->maps()) {\n    if (m.map.is_vdso()) {\n      current.vdso = m.map;\n    } else if (m.map.is_vvar()) {\n      current.vvar = m.map;\n    } else if (m.map.is_vvar_vclock()) {\n      current.vvar_vclock = m.map;\n    }\n  }\n\n  ASSERT(t, current.vdso.size() == new_.vdso.size())\n    << \"VDSO size mismatch\";\n  ASSERT(t, current.vvar.size() == new_.vvar.size() || !new_.vvar.size())\n    << \"VVAR size mismatch\";\n  ASSERT(t, current.vvar_vclock.size() == new_.vvar_vclock.size() || !new_.vvar_vclock.size())\n    << \"VVAR VCLOCK size mismatch\";\n\n  // Handle case where old and new addresses overlap by finding a free range early in the\n  // address space we can use as a temporary buffer. VDSOs are always at fairly high\n  // addresses so this shouldn't introduce any new overlap issues.\n  // We move VDSO and VVAR to their temp addresses first, then move both of them to their\n  // final address, to avoid situations where current's VDSO overlaps target's VVAR or\n  // vice versa.\n  size_t temp_size = new_.vdso.size() + new_.vvar.size() + new_.vvar_vclock.size();\n  remote_ptr<void> vdso_temp_address = t->vm()->find_free_memory(t,\n        temp_size,\n        remote_ptr<void>(65536), AddressSpace::FindFreeMemoryPolicy::STRICT_SEARCH);\n  remote_ptr<void> vvar_temp_address = vdso_temp_address + new_.vdso.size();\n  remote_ptr<void> vvar_vclock_temp_address = vvar_temp_address + new_.vvar.size();\n  MemoryRange temp_range(vdso_temp_address, temp_size);\n  ASSERT(t, !temp_range.intersects(new_.vdso))\n    << \"Free memory found overlaps new VDSO address\";\n  ASSERT(t, !temp_range.intersects(new_.vvar))\n    << \"Free memory found overlaps new VVAR address\";\n  ASSERT(t, !temp_range.intersects(new_.vvar_vclock))\n    << \"Free memory found overlaps new VVAR VCLOCK address\";\n\n  mremap_move(remote, current.vdso.start(), vdso_temp_address, new_.vdso.size(),\n              \"current.vdso.start() -> vdso_temp_address\");\n  if (new_.vvar.size()) {\n    mremap_move(remote, current.vvar.start(), vvar_temp_address, current.vvar.size(),\n                \"current.vvar.start() -> vvar_temp_address\");\n  } else {\n    bool ok = remote.infallible_munmap_syscall_if_alive(current.vvar.start(),\n        current.vvar.size());\n    ASSERT(t, ok) << \"Duped task got killed?\";\n    t->vm()->unmap(t, current.vvar.start(), current.vvar.size());\n  }\n  if (new_.vvar_vclock.size()) {\n    mremap_move(remote, current.vvar_vclock.start(), vvar_vclock_temp_address,\n        current.vvar_vclock.size(),\n        \"current.vvar_vclock.start() -> vvar_vclock_temp_address\");\n  } else if (new_.vvar_vclock.start()) {\n    bool ok = remote.infallible_munmap_syscall_if_alive(current.vvar_vclock.start(),\n        current.vvar_vclock.size());\n    ASSERT(t, ok) << \"Duped task got killed?\";\n    t->vm()->unmap(t, current.vvar_vclock.start(), current.vvar_vclock.size());\n  }\n  mremap_move(remote, vdso_temp_address, new_.vdso.start(), new_.vdso.size(),\n              \"vdso_temp_address -> new_.vdso.start()\");\n  mremap_move(remote, vvar_temp_address, new_.vvar.start(), new_.vvar.size(),\n              \"vvar_temp_address -> new_.vvar.start()\");\n  if (new_.vvar_vclock.start()) {\n    mremap_move(remote, vvar_vclock_temp_address, new_.vvar_vclock.start(), new_.vvar_vclock.size(),\n                \"vvar_vclock_temp_address -> new_.vvar_vclock.start()\");\n  }\n}\n\nconst int all_rlimits[] = {\n  (int)RLIMIT_AS, (int)RLIMIT_CORE, (int)RLIMIT_CPU, (int)RLIMIT_DATA,\n  (int)RLIMIT_FSIZE, (int)RLIMIT_LOCKS, (int)RLIMIT_MEMLOCK,\n  (int)RLIMIT_MSGQUEUE, (int)RLIMIT_NICE, (int)RLIMIT_NOFILE, (int)RLIMIT_NPROC,\n  (int)RLIMIT_RSS, (int)RLIMIT_RTTIME, (int)RLIMIT_SIGPENDING, (int)RLIMIT_STACK\n};\n\nvoid Task::dup_from(Task *other) {\n  std::vector<KernelMapping> mappings;\n  KernelMapping stack_mapping;\n  bool found_stack = false;\n  VMappings vmaps;\n\n  for (auto map : other->vm()->maps()) {\n    auto km = map.map;\n    if (map.flags != AddressSpace::Mapping::FLAG_NONE) {\n      if (map.flags & (AddressSpace::Mapping::IS_THREAD_LOCALS |\n                       AddressSpace::Mapping::IS_RR_PAGE)) {\n        // While under rr control this task already has an rr page and\n        // a thread locals shared segment, don't mess with them.\n        continue;\n      }\n      // For rr private mappings, just make an anonymous segment of the same size\n      km = KernelMapping(km.start(), km.end(), string(), KernelMapping::NO_DEVICE,\n                           KernelMapping::NO_INODE, km.prot(),\n                           (km.flags() & ~MAP_SHARED) | MAP_PRIVATE, 0);\n    }\n    if (km.is_stack() && !found_stack) {\n      stack_mapping = km;\n      found_stack = true;\n    } else {\n      if (km.is_vdso()) {\n        vmaps.vdso = km;\n      } else if (km.is_vvar()) {\n        vmaps.vvar = km;\n      } else if (km.is_vvar_vclock()) {\n        vmaps.vvar_vclock = km;\n      } else if (!km.is_vsyscall()) {\n        mappings.push_back(km);\n      }\n    }\n  }\n  ASSERT(this, found_stack);\n  // Copy address space\n  LOG(debug) << \"Mapping rr page for \" << tid;\n  {\n    AutoRemoteSyscalls remote(this);\n    this->vm()->map_rr_page(remote);\n  }\n  {\n    AutoRemoteSyscalls remote(this, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);\n    move_vdso_and_vvar_mappings(remote, vmaps);\n    LOG(debug) << \"Unmapping memory for \" << tid;\n    // TODO: Only do this if the rr page isn't already mapped\n    AddressSpace::UnmapOptions options;\n    options.exclude_vdso_vvar = true;\n    this->vm()->unmap_all_but_rr_mappings(remote, options);\n    LOG(debug) << \"Creating stack mapping \" << stack_mapping << \" for \" << tid;\n    create_mapping(this, remote, stack_mapping);\n    LOG(debug) << \"Copying stack into \" << tid;\n    copy_mem_mapping(other, this, stack_mapping);\n  }\n  {\n    AutoRemoteSyscalls remote_this(this);\n    for (auto &km : mappings) {\n      LOG(debug) << \"Creating mapping \" << km << \" for \" << tid;\n      create_mapping(this, remote_this, km);\n      LOG(debug) << \"Copying mapping into \" << tid;\n      if (!(km.flags() & MAP_SHARED)) {\n        // Make the effort just for bigger mappings, copy smaller as a whole.\n        if ((km.flags() & MAP_ANONYMOUS) &&\n            km.size() >= 0x400000/*4MB*/)\n        {\n          LOG(debug) << \"Using copy_mem_mapping_just_used\";\n          if (copy_mem_mapping_just_used(other, this, km)) {\n            continue;\n          }\n          LOG(debug) << \"Fallback to copy_mem_mapping\";\n        }\n        copy_mem_mapping(other, this, km);\n      }\n    }\n    AutoRemoteSyscalls remote_other(other);\n    std::vector<int> all_fds = read_all_proc_fds(other->tid);\n    for (int fd : all_fds) {\n      if (fd == session().tracee_fd_number()) {\n        continue;\n      }\n      // If this is a /proc/self/mem fd, rewrite it for the new task\n      FileMonitor *fd_monitor = other->fd_table()->get_monitor(fd);\n      ScopedFd here;\n      if (fd_monitor && fd_monitor->type() == FileMonitor::ProcMem &&\n          ((ProcMemMonitor *)fd_monitor)->target_is_vm(other->vm().get())) {\n        here = ScopedFd(::dup(this->vm()->mem_fd().get()));\n      } else {\n        here = remote_other.retrieve_fd(fd);\n      }\n      int remote_fd_flags = remote_other.infallible_syscall(\n        syscall_number_for_fcntl(this->arch()), fd, F_GETFD);\n      int remote_fd = remote_this.infallible_send_fd_if_alive(here);\n      if (remote_fd >= 0) {\n        if (remote_fd != fd) {\n          remote_this.infallible_syscall(syscall_number_for_dup3(this->arch()), remote_fd, fd, 0);\n          remote_this.infallible_close_syscall_if_alive(remote_fd);\n        }\n        remote_other.infallible_syscall(\n          syscall_number_for_fcntl(this->arch()),\n          fd, F_SETFD, remote_fd_flags);\n      }\n    }\n    string path = \".\";\n    AutoRestoreMem child_path(remote_other, path.c_str());\n    {\n      long child_fd =\n        remote_other.syscall(syscall_number_for_openat(other->arch()), AT_FDCWD,\n                       child_path.get(), O_RDONLY);\n      ASSERT(other, child_fd != -1);\n      ScopedFd fd = remote_other.retrieve_fd(child_fd);\n      remote_other.infallible_close_syscall_if_alive(child_fd);\n      child_fd = remote_this.infallible_send_fd_if_alive(fd);\n      if (child_fd >= 0) {\n        remote_this.syscall(syscall_number_for_fchdir(this->arch()), child_fd);\n        remote_this.infallible_close_syscall_if_alive(child_fd);\n      }\n    }\n\n    // Copy rlimits\n    struct rlimit64 limit;\n    for (size_t i = 0; i < (sizeof(all_rlimits)/sizeof(all_rlimits[0])); ++i) {\n      int err = syscall(SYS_prlimit64, (uintptr_t)other->tid,\n        (uintptr_t)all_rlimits[i], (uintptr_t)NULL, (uintptr_t)&limit);\n      ASSERT(other, err == 0);\n      err = syscall(SYS_prlimit64, (uintptr_t)this->tid,\n        (uintptr_t)all_rlimits[i], (uintptr_t)&limit, (uintptr_t)NULL);\n      ASSERT(this, err == 0);\n    }\n\n    NativeArch::prctl_mm_map map;\n    memset(&map, 0, sizeof(map));\n\n    other->vm()->read_mm_map(other, &map);\n    apply_mm_map(remote_this, map);\n  }\n  copy_state(other->capture_state());\n  activate_preload_thread_locals();\n}\n\n/**\n * Proceeds until the next system call, which is being executed.\n * Returns false if did_waitpid failed because the task got SIGKILL\n * or equivalent.\n */\nstatic bool __ptrace_cont(Task* t, ResumeRequest resume_how,\n                          SupportedArch syscall_arch, int expect_syscallno,\n                          int expect_syscallno2 = -1, pid_t new_tid = -1) {\n  t->resume_execution(resume_how, RESUME_NONBLOCKING, RESUME_NO_TICKS);\n  while (true) {\n    // Do our own waiting instead of calling Task::wait() so we can detect and\n    // handle tid changes due to off-main-thread execve.\n    WaitOptions options(t->tid);\n    if (new_tid >= 0) {\n      options.unblock_on_other_tasks = true;\n    }\n    WaitResult result = WaitManager::wait_stop(options);\n    if (new_tid >= 0 && result.code == WAIT_NO_CHILD) {\n      // tid change happened before our wait call. Try another wait .\n      options.tid = new_tid;\n      options.unblock_on_other_tasks = false;\n      result = WaitManager::wait_stop(options);\n    }\n    ASSERT(t, result.code == WAIT_OK);\n    if (new_tid >= 0) {\n      t->hpc.set_tid(new_tid);\n      t->tid = new_tid;\n    }\n    if (!t->did_waitpid(result.status)) {\n      return false;\n    }\n\n    if (ReplaySession::is_ignored_signal(t->status().stop_sig())) {\n      t->resume_execution(resume_how, RESUME_NONBLOCKING, RESUME_NO_TICKS);\n    } else {\n      break;\n    }\n  }\n\n  ASSERT(t, !t->stop_sig())\n      << \"Expected no pending signal, but got \" << t->stop_sig();\n\n  /* check if we are synchronized with the trace -- should never fail */\n  int current_syscall = t->regs().original_syscallno();\n  ASSERT(t,\n         current_syscall == expect_syscallno ||\n             current_syscall == expect_syscallno2)\n      << \"Should be at \" << syscall_name(expect_syscallno, syscall_arch)\n      << \", but instead at \" << syscall_name(current_syscall, syscall_arch);\n  return true;\n}\n\nvoid Task::did_handle_ptrace_exit_event() {\n  ASSERT(this, !handled_ptrace_exit_event_);\n  handled_ptrace_exit_event_ = true;\n}\n\ntemplate <typename Arch>\nstatic void setup_exec_args_arch(Task* t, const std::string& filename,\n    remote_ptr<void> remote_mem, Registers& regs) {\n  auto argv = remote_mem.cast<typename Arch::size_t>();\n  auto argv0 = argv + 1;\n  auto zero_word = argv0 + 1;\n  remote_ptr<void> filename_addr = zero_word + 1;\n  typename Arch::size_t words[] = {\n    static_cast<typename Arch::size_t>(argv0.as_int()),\n    static_cast<typename Arch::size_t>(zero_word.as_int()),\n    0\n  };\n  t->write_mem(argv, words, 3);\n  t->write_bytes_helper(filename_addr, filename.size() + 1, filename.c_str());\n  regs.set_arg1(filename_addr);\n  regs.set_arg2(argv);\n  regs.set_arg3(zero_word);\n}\n\nstatic void setup_exec_args(Task* t, const std::string& filename,\n    remote_ptr<void> remote_mem, Registers& regs) {\n  RR_ARCH_FUNCTION(setup_exec_args_arch, t->arch(), t, filename, remote_mem, regs);\n}\n\nvoid Task::os_exec(SupportedArch exec_arch, std::string filename)\n{\n  // Setup memory and registers for the execve call. We may not have to save\n  // the old values since they're going to be wiped out by execve. We can\n  // determine this by checking if this address space has any tasks with a\n  // different tgid.\n  Task* memory_task = this;\n  for (auto task : vm()->task_set()) {\n    if (task->tgid() != tgid()) {\n      memory_task = task;\n      break;\n    }\n  }\n\n  // Old data if required\n  std::vector<uint8_t> saved_data;\n\n  // Set up everything\n  Registers regs = this->regs();\n  regs.set_ip(vm()->traced_syscall_ip());\n  remote_ptr<void> remote_mem = floor_page_size(regs.sp());\n\n  // Determine how much memory we'll need (upper bound)\n  size_t total_size = filename.size() + 1 + 2*sizeof(size_t);\n  if (memory_task != this) {\n    saved_data = read_mem(remote_mem.cast<uint8_t>(), total_size);\n  }\n\n  setup_exec_args(this, filename, remote_mem, regs);\n  /* The original_syscallno is execve in the old architecture. The kernel does\n   * not update the original_syscallno when the architecture changes across\n   * an exec.\n   * We're using the dedicated traced-syscall IP so its arch is t's arch.\n   */\n  int expect_syscallno = syscall_number_for_execve(arch());\n  regs.set_syscallno(expect_syscallno);\n  regs.set_original_syscallno(expect_syscallno);\n  set_regs(regs);\n\n  LOG(debug) << \"Beginning execve\" << this->regs();\n  enter_syscall(exec_arch);\n  ASSERT(this, !stop_sig()) << \"exec failed on entry\";\n  /* Complete the syscall. The tid of the task will be the thread-group-leader\n   * tid, no matter what tid it was before.\n   */\n  pid_t tgid = real_tgid();\n  bool ok = __ptrace_cont(this, RESUME_SYSCALL, arch(), expect_syscallno,\n                          syscall_number_for_execve(exec_arch),\n                          tgid == tid ? -1 : tgid);\n  ASSERT(this, ok) << \"Task \" << tid << \" got killed while trying to exec\";\n  LOG(debug) << this->status() << \" \" << this->regs();\n  if (this->regs().syscall_result()) {\n    errno = -this->regs().syscall_result();\n    if (access(filename.c_str(), 0) == -1 && errno == ENOENT &&\n        exec_arch == x86) {\n      FATAL() << \"Cannot find \" << filename\n              << \" to replay this 32-bit process; you probably built rr with \"\n                 \"disable32bit\";\n    }\n    errno = -this->regs().syscall_result();\n    ASSERT(this, false) << \"Exec of \" << filename << \" failed\";\n  }\n\n  // Restore any memory if required. We need to do this through memory_task,\n  // since the new task is now on the new address space. Do it now because\n  // later we may try to unmap this task's syscallbuf.\n  if (memory_task != this) {\n    memory_task->write_mem(remote_mem.cast<uint8_t>(), saved_data.data(),\n                           saved_data.size());\n  }\n}\n\nvoid Task::apply_syscall_entry_regs()\n{\n  if (arch() == aarch64) {\n    registers.set_original_syscallno(registers.syscallno());\n    registers.set_orig_arg1(registers.arg1());\n    // Don't update registers_dirty here, because these registers are not part\n    // of the ptrace state tracked by that flag.\n    ticks_at_last_syscall_entry = tick_count();\n    ip_at_last_syscall_entry = registers.ip();\n    last_syscall_entry_recorded = false;\n  }\n}\n\nvoid Task::tgkill(int sig) {\n  LOG(debug) << \"Sending \" << sig << \" to tid \" << tid;\n  ASSERT(this, 0 == syscall(SYS_tgkill, real_tgid(), tid, sig));\n}\n\nbool Task::move_to_signal_stop()\n{\n  LOG(debug) << \"    maybe not in signal-stop (status \" << status()\n             << \"); doing tgkill(SYSCALLBUF_DESCHED_SIGNAL)\";\n  // Always send SYSCALLBUF_DESCHED_SIGNAL because other signals (except\n  // TIME_SLICE_SIGNAL) will be blocked by\n  // RecordTask::will_resume_execution().\n  // During record make sure to use the syscallbuf desched sig.\n  // During replay, it doesn't really matter, since we don't apply\n  // the signal mask to the replay task.\n  int sig = SYSCALLBUF_DEFAULT_DESCHED_SIGNAL;\n  if (session().is_recording()) {\n    sig = session().as_record()->syscallbuf_desched_sig();\n  }\n  // Note that this signal cannot be blocked by tracees.\n  this->tgkill(sig);\n  /* Now singlestep the task until we're in a signal-stop for the signal\n   * we've just sent. We must absorb and forget that signal here since we\n   * don't want it delivered to the task for real.\n   */\n  auto old_ip = ip();\n  if (arch() == aarch64 && session().is_recording() && status().is_syscall() &&\n      static_cast<RecordTask*>(this)->at_may_restart_syscall()) {\n    // On aarch64, single step of an aborted syscall\n    // will cause us to move to before the syscall instruction\n    old_ip = old_ip.decrement_by_syscall_insn_length(arch());\n  }\n  do {\n    if (!resume_execution(RESUME_SINGLESTEP, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n      return false;\n    }\n    ASSERT(this, old_ip == ip())\n        << \"Singlestep actually advanced when we \"\n        << \"just expected a signal; was at \" << old_ip << \" now at \"\n        << ip() << \" with status \" << status();\n    // Ignore any pending TIME_SLICE_SIGNALs and continue until we get our\n    // SYSCALLBUF_DESCHED_SIGNAL.\n  } while (stop_sig() == PerfCounters::TIME_SLICE_SIGNAL);\n  return true;\n}\n\nbool Task::should_apply_rseq_abort(EventType event_type, remote_code_ptr* new_ip,\n                                   bool* invalid_rseq_cs) {\n  /* Syscallbuf flushes don't trigger rseq aborts ---\n     whatever triggered the syscallbuf flush might.\n     No need to do this if the process is exiting. */\n  if (!rseq_state || event_type == EV_SYSCALLBUF_FLUSH || is_exiting()) {\n    return false;\n  }\n  // We're relying on the fact that rseq_t is the same across architectures.\n  // These reads might fail if the task is dead and gone.\n  bool ok = true;\n  auto rseq = read_mem(rseq_state->ptr.cast<typename NativeArch::rseq_t>(), &ok);\n  if (!ok || !rseq.rseq_cs) {\n    return false;\n  }\n  auto rseq_cs = read_mem(remote_ptr<typename NativeArch::rseq_cs>(rseq.rseq_cs), &ok);\n  if (!ok || rseq_cs.version ||\n      rseq_cs.start_ip + rseq_cs.post_commit_offset < rseq_cs.start_ip ||\n      rseq_cs.abort_ip - rseq_cs.start_ip < rseq_cs.post_commit_offset) {\n    *invalid_rseq_cs = true;\n    return false;\n  }\n  if (ip().register_value() - rseq_cs.start_ip >= rseq_cs.post_commit_offset) {\n    return false;\n  }\n  uint32_t flag;\n  switch (event_type) {\n    case EV_SCHED:\n      flag = 1 << RR_RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT;\n      break;\n    case EV_SIGNAL:\n      flag = 1 << RR_RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT;\n      break;\n    default:\n      /* A system call inside the rseq region should SIGSEGV but we don't emulate that yet */\n      ASSERT(this, false) << \"Unsupported event type\";\n      return false;\n  }\n  if ((rseq.flags | rseq_cs.flags) & flag) {\n    return false;\n  }\n  uint32_t sig = read_mem(remote_ptr<uint32_t>(rseq_cs.abort_ip - 4), &ok);\n  if (!ok || sig != rseq_state->abort_prefix_signature) {\n    *invalid_rseq_cs = true;\n    return false;\n  }\n  *new_ip = remote_code_ptr(rseq_cs.abort_ip);\n  return true;\n}\n\n}\n"
  },
  {
    "path": "src/Task.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TASK_H_\n#define RR_TASK_H_\n\n#include <memory>\n#include <vector>\n#include <unordered_map>\n\n#include \"preload/preload_interface.h\"\n\n#include \"AddressSpace.h\"\n#include \"Event.h\"\n#include \"ExtraRegisters.h\"\n#include \"FdTable.h\"\n#include \"PerfCounters.h\"\n#include \"Registers.h\"\n#include \"TaskishUid.h\"\n#include \"ThreadGroup.h\"\n#include \"TraceStream.h\"\n#include \"WaitStatus.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_supplement.h\"\n#include \"remote_code_ptr.h\"\n#include \"util.h\"\n\nstruct syscallbuf_hdr;\nstruct syscallbuf_record;\n\nnamespace rr {\n\nclass AutoRemoteSyscalls;\nclass RecordSession;\nclass ReplaySession;\nclass ScopedFd;\nclass Session;\nclass ThreadGroup;\n\nenum CloneFlags {\n  /**\n   * The child gets a semantic copy of all parent resources (and\n   * becomes a new thread group).  This is the semantics of the\n   * fork() syscall.\n   */\n  CLONE_SHARE_NOTHING = 0,\n  /**\n   * Child will share the table of signal dispositions with its\n   * parent.\n   */\n  CLONE_SHARE_SIGHANDLERS = 1 << 0,\n  /** Child will join its parent's thread group. */\n  CLONE_SHARE_THREAD_GROUP = 1 << 1,\n  /** Child will share its parent's address space. */\n  CLONE_SHARE_VM = 1 << 2,\n  /** Child will share its parent's file descriptor table. */\n  CLONE_SHARE_FILES = 1 << 3,\n  /** Kernel will clear and notify tid futex on task exit. */\n  CLONE_CLEARTID = 1 << 4,\n  // Set the thread area to what's specified by the |tls| arg.\n  CLONE_SET_TLS = 1 << 5,\n};\n\n/**\n * Enumeration of ways to resume execution.  See the ptrace manual for\n * details of the semantics of these.\n *\n * We define a new datatype because the PTRACE_SYSEMU* requests aren't\n * part of the official ptrace API, and we want to use a strong type\n * for these resume requests to ensure callers don't confuse their\n * arguments.\n */\nenum ResumeRequest {\n  RESUME_CONT = PTRACE_CONT,\n  RESUME_SINGLESTEP = PTRACE_SINGLESTEP,\n  RESUME_SYSCALL = PTRACE_SYSCALL,\n  RESUME_SYSEMU = NativeArch::PTRACE_SYSEMU,\n  RESUME_SYSEMU_SINGLESTEP = NativeArch::PTRACE_SYSEMU_SINGLESTEP,\n};\nenum WaitRequest {\n  // Don't wait after resuming.\n  RESUME_NONBLOCKING,\n  // After resuming, blocking-waitpid() until tracee status\n  // changes.\n  RESUME_WAIT,\n  // Like RESUME_WAIT, but we're not expecting a PTRACE_EVENT_EXIT\n  // or reap, so return false also in that case.\n  RESUME_WAIT_NO_EXIT\n};\nenum TicksRequest {\n  // We don't expect to see any ticks (though we seem to on the odd buggy\n  // system...). Using this is a small performance optimization because we don't\n  // have to stop and restart the performance counters. This may also avoid\n  // bugs on some systems that report performance counter advances while\n  // in the kernel...\n  RESUME_NO_TICKS = -2,\n  RESUME_UNLIMITED_TICKS = -1,\n  // Positive values are a request for an interrupt\n  // after that number of ticks\n  // Don't request more than this!\n  MAX_TICKS_REQUEST = 2000000000,\n};\n\n/** Reasons why a SIGTRAP might have been delivered. Multiple reasons can\n * apply. Also, none can apply, e.g. if someone sent us a SIGTRAP via kill().\n */\nstruct TrapReasons {\n  /* Singlestep completed (RESUME_SINGLESTEP, RESUME_SYSEMU_SINGLESTEP). */\n  bool singlestep;\n  /* Hardware watchpoint fired. This includes cases where the actual values\n   * did not change (i.e. AddressSpace::has_any_watchpoint_changes may return\n   * false even though this is set). */\n  bool watchpoint;\n  /* Breakpoint instruction was executed. */\n  bool breakpoint;\n};\n\nstruct RseqState {\n  remote_ptr<void> ptr;\n  uint32_t abort_prefix_signature;\n  RseqState(remote_ptr<void> ptr, uint32_t abort_prefix_signature)\n    : ptr(ptr), abort_prefix_signature(abort_prefix_signature) {}\n};\n\n/**\n * A \"task\" is a task in the linux usage: the unit of scheduling.  (OS\n * people sometimes call this a \"thread control block\".)  Multiple\n * tasks may share the same address space and file descriptors, in\n * which case they're commonly called \"threads\".  Or two tasks may\n * have their own address spaces and file descriptors, in which case\n * they're called \"processes\".  Both look the same to rr (on linux),\n * so no distinction is made here.\n */\nclass Task {\n  friend class Session;\n  friend class RecordSession;\n  friend class ReplaySession;\n\npublic:\n  typedef std::vector<WatchConfig> HardwareWatchpoints;\n\n  ReplayTask* as_replay();\n\n  /**\n   * Ptrace-detach the task.\n   */\n  void detach();\n\n  /*\n   * Re-enable the CPUID instruction in this task (if it was previously\n   * disabled to support CPUID emulation) as well as the use of rdtsc.\n   */\n  void reenable_cpuid_tsc();\n\n  /**\n   * Wait for the task to exit, but do not reap/detach yet.\n   */\n  void wait_exit();\n\n  /**\n   * Advance the task to its exit state if it's not already there.\n   * If `wait` is false, then during recording Scheduler::start() must be\n   * called.\n   */\n  void proceed_to_exit(bool wait = true);\n\n  /**\n   * Kill this task and wait for it to exit.\n   * N.B.: If may_reap() is false, this may hang.\n   * Returns the WaitStatus of the task at exit (usually SIGKILL, but may not\n   * be if we raced with another exit reason).\n   */\n  WaitStatus kill();\n\n  /**\n   * This must be in an emulated syscall, entered through\n   * |cont_sysemu()| or |cont_sysemu_singlestep()|, but that's\n   * not checked.  If so, step over the system call instruction\n   * to \"exit\" the emulated syscall.\n   */\n  void finish_emulated_syscall();\n\n  size_t syscallbuf_data_size();\n\n  /**\n   * Dump attributes of this process, including pending events,\n   * to |out|, which defaults to LOG_FILE.\n   */\n  void dump(FILE* out = nullptr) const;\n\n  /**\n   * Called after the first exec in a session, when the session first\n   * enters a consistent state. Prior to that, the task state\n   * can vary based on how rr set up the child process. We have to flush\n   * out any state that might have been affected by that.\n   */\n  void flush_inconsistent_state();\n\n  /**\n   * Return total number of ticks ever executed by this task.\n   * Updates tick count from the current performance counter values if\n   * necessary.\n   */\n  Ticks tick_count() const { return ticks; }\n\n  /**\n   * Return the path of this fd as /proc/<pid>/fd/<fd>\n   */\n  std::string proc_fd_path(int fd);\n\n  /**\n   * Return the path of /proc/<pid>/pagemap\n   */\n  std::string proc_pagemap_path();\n\n  /**\n   * Return the path of /proc/<pid>/stat\n   */\n  std::string proc_stat_path();\n\n  /**\n   * Return the path of /proc/<pid>/exe\n   */\n  std::string proc_exe_path();\n\n  /**\n   * Return the path of the executable (i.e. what\n   * /proc/<pid>/exe points to).\n   */\n  std::string exe_path();\n\n  /**\n   * Stat |fd| in the context of this task's fd table.\n   */\n  struct stat stat_fd(int fd);\n  /**\n   * Lstat |fd| in the context of this task's fd table.\n   */\n  struct stat lstat_fd(int fd);\n  /**\n   * Open |fd| in the context of this task's fd table.\n   */\n  ScopedFd open_fd(int fd, int flags);\n  /**\n   * Get the name of the file referenced by |fd| in the context of this\n   * task's fd table.\n   */\n  std::string file_name_of_fd(int fd);\n  /**\n   * Get current offset of |fd|\n   */\n  int64_t fd_offset(int fd);\n  /**\n   * Get pid of pidfd |fd|\n   */\n  pid_t pid_of_pidfd(int fd);\n\n  /**\n   * Records the wait status of this task as |status|, e.g. if\n   * |wait()/try_wait()| has returned it. Call this whenever a waitpid\n   * returned activity for this task.\n   * If this returns false, the task was kicked out of a ptrace-stop\n   * by SIGKILL or equivalent before we could read registers etc:\n   * -- We will treat this stop as if it never happened; the caller must\n   * act as if there was no stop.\n   * -- is_stopped will be false\n   * -- in_unexpected_exit will be true\n   * If this returns true, is_stopped will be true.\n   * If `status.reaped()` (i.e. fatal signal or normal exit), this always\n   * returns true.\n   */\n  bool did_waitpid(WaitStatus status);\n\n  /**\n   * Syscalls have side effects on registers (e.g. setting the flags register).\n   * Perform those side effects on |registers| to make it look like a syscall\n   * happened.\n   */\n  void canonicalize_regs(SupportedArch syscall_arch);\n\n  /**\n   * Return the ptrace message pid associated with the current ptrace\n   * event, f.e. the new child's pid at PTRACE_EVENT_CLONE.\n   * Returns -1 if the ptrace returns ESRCH, i.e. the task is not in a\n   * ptrace-stop.\n   */\n  pid_t get_ptrace_eventmsg_pid();\n\n  /**\n   * Return the siginfo at the signal-stop of this.\n   * Not meaningful unless this is actually at a signal stop.\n   */\n  const siginfo_t& get_siginfo();\n\n  /**\n   * Destroy in the tracee task the scratch buffer and syscallbuf (if\n   * syscallbuf_child is non-null).\n   * Both the as_task and the fd_task must be able to execute remote syscalls\n   * and share the address space, resp. the file descriptor table with the\n   * current task. If either of these is null, the corresponding resource is\n   * not destroyed remote (e.g. if there are no other tasks left in the same\n   * address space or file descriptor table).\n   */\n  void destroy_buffers(Task *as_task, Task *fd_task);\n  void destroy_buffers() { destroy_buffers(this, this); }\n\n  void did_kill();\n\n  void unmap_buffers_for(\n      AutoRemoteSyscalls& remote, Task* t,\n      remote_ptr<struct syscallbuf_hdr> saved_syscallbuf_child);\n  /* Close fds related to `t`'s syscallbuf, in this task's fd table.\n     If `really_close` is true, actually close the kernel fds through `remote`,\n     otherwise only update our FdTable. */\n  void close_buffers_for(AutoRemoteSyscalls& remote, Task* t, bool really_close);\n\n  remote_ptr<const struct syscallbuf_record> next_syscallbuf_record();\n  long stored_record_size(remote_ptr<const struct syscallbuf_record> record);\n\n  /** Return the current $ip of this. */\n  remote_code_ptr ip() { return regs().ip(); }\n\n  /**\n   * Emulate a jump to a new IP, updating the ticks counter as appropriate.\n   */\n  void emulate_jump(remote_code_ptr);\n  void count_direct_jump()\n  {\n    ticks += PerfCounters::ticks_for_unconditional_direct_branch(this);\n  }\n\n  /**\n   * Return true if this is at an arm-desched-event or\n   * disarm-desched-event syscall.\n   */\n  bool is_desched_event_syscall();\n\n  /**\n   * Return true when this task is in a traced syscall made by the\n   * syscallbuf code. Callers may assume |is_in_syscallbuf()|\n   * is implied by this. Note that once we've entered the traced syscall,\n   * ip() is immediately after the syscall instruction.\n   */\n  bool is_in_traced_syscall() {\n    return ip() ==\n               as->traced_syscall_ip().increment_by_syscall_insn_length(\n                   arch()) ||\n           ip() ==\n               as->privileged_traced_syscall_ip()\n                   .increment_by_syscall_insn_length(arch());\n  }\n  bool is_at_traced_syscall_entry() {\n    return ip() == as->traced_syscall_ip() ||\n           ip() == as->privileged_traced_syscall_ip();\n  }\n\n  /**\n   * Return true when this task is in an untraced syscall, i.e. one\n   * initiated by a function in the syscallbuf. Callers may\n   * assume |is_in_syscallbuf()| is implied by this. Note that once we've\n   * entered the traced syscall, ip() is immediately after the syscall\n   * instruction.\n   */\n  bool is_in_untraced_syscall() {\n    const AddressSpace::SyscallType *t;\n    if (arch() == aarch64 && stop_sig() > 0) {\n      // On aarch64 we can't distinguish untraced syscall entry and exit\n      // when a signal happened\n      t = AddressSpace::rr_page_syscall_from_entry_point(arch(), ip());\n    } else {\n      t = AddressSpace::rr_page_syscall_from_exit_point(arch(), ip());\n    }\n    return t && t->traced == AddressSpace::UNTRACED;\n  }\n\n  bool is_in_rr_page() {\n    auto p = ip().to_data_ptr<void>();\n    return AddressSpace::rr_page_start() <= p &&\n           p < AddressSpace::rr_page_end();\n  }\n\n  /**\n   * Return true if |ptrace_event()| is the trace event\n   * generated by the syscallbuf seccomp-bpf when a traced\n   * syscall is entered.\n   */\n  bool is_ptrace_seccomp_event() const;\n\n  /** Dump all pending events to the RecordTask INFO log. */\n  virtual void log_pending_events() const {}\n\n  /**\n   * Call this hook just before exiting a syscall.  Often Task\n   * attributes need to be updated based on the finishing syscall.\n   * Use 'regs' instead of this->regs() because some registers may not be\n   * set properly in the task yet.\n   */\n  virtual void on_syscall_exit(int syscallno, SupportedArch arch,\n                               const Registers& regs);\n\n  /**\n   * Hook called by `resume_execution`.\n   */\n  virtual void will_resume_execution(ResumeRequest, WaitRequest, TicksRequest,\n                                     int /*sig*/) {}\n  /**\n   * Hook called by `did_waitpid`.\n   */\n  virtual void did_wait() {}\n  /**\n   * Return the pid of the task in its own pid namespace.\n   * Only RecordTasks actually change pid namespaces, but\n   * this value is stored and present during replay too.\n   */\n  pid_t own_namespace_tid() { return own_namespace_rec_tid; }\n\n  /**\n   * Assuming ip() is just past a breakpoint instruction, adjust\n   * ip() backwards to point at that breakpoint insn.\n   */\n  void move_ip_before_breakpoint();\n\n  /**\n   * Assuming we've just entered a syscall, exit that syscall and reset\n   * state to reenter the syscall just as it was called the first time.\n   * Returns false if we see the process exit instead.\n   */\n  bool exit_syscall_and_prepare_restart(SupportedArch syscall_arch);\n\n  /**\n   * We're currently in user-space with registers set up to perform a system\n   * call. Continue into the kernel and stop where we can modify the syscall\n   * state.\n   * Return `true` if the syscall entry succeeded.\n   * Return `false` if the tracee exited unexpectedly.\n   */\n  bool enter_syscall(SupportedArch syscall_arch, bool allow_exit = false);\n\n  /**\n   * We have observed entry to a syscall (either by PTRACE_EVENT_SECCOMP or\n   * a syscall, depending on the value of Session::syscall_seccomp_ordering()).\n   * Continue into the kernel to perform the syscall and stop at the\n   * PTRACE_SYSCALL syscall-exit trap. Returns false if we see the process exit\n   * before that; we may or may not be stopped in that case.\n   */\n  bool exit_syscall(SupportedArch syscall_arch);\n\n  /**\n   * Return the \"task name\"; i.e. what |prctl(PR_GET_NAME)| or\n   * /proc/tid/comm say that the task's name is.\n   *\n   * During recording we don't monitor changes to this, we just let\n   * the kernel update it directly. This lets us syscall-buffer PR_SET_NAME.\n   * During replay we monitor changes to this and cache the name in ReplayTask,\n   * hence these methods are virtual. During replay the task's actual name\n   * is \"rr:\" followed by the original name.\n   */\n  virtual std::string name() const;\n\n  virtual void set_name(AutoRemoteSyscalls& remote, const std::string& name);\n\n  /**\n   * Called for every PR_SET_NAME during replay but not always during recording\n   * (it is not called for syscall-buffered PR_SET_NAME).\n   */\n  virtual void did_prctl_set_prname(remote_ptr<void>) {}\n\n  /**\n   * Call this method when this task has just performed an |execve()|\n   * (so we're in the new address space), but before the system call has\n   * returned.\n   * `exe_file` is the name of the executable file in the trace, if there is one,\n   * otherwise the original exe file name --- a best-effort filename we can\n   * pass to gdb for it to read the exe.\n   */\n  void post_exec(const std::string& exe_file);\n\n  /**\n   * Call this method when this task has exited a successful execve() syscall.\n   * At this point it is safe to make remote syscalls.\n   * `original_exe_file` is the original file exe file name.\n   */\n  void post_exec_syscall(const std::string& original_exe_file);\n\n  /**\n   * Return true if this task has execed.\n   */\n  bool execed() const;\n\n  /**\n   * Return true if this task is dead and just waiting to be reaped.\n   */\n  virtual bool already_exited() const { return false; }\n\n  virtual bool is_detached_proxy() const { return false; }\n\n  /**\n   * Read |N| bytes from |child_addr| into |buf|, or don't\n   * return.\n   */\n  template <size_t N>\n  void read_bytes(remote_ptr<void> child_addr, uint8_t (&buf)[N]) {\n    return read_bytes_helper(child_addr, N, buf);\n  }\n\n  /** Return the current regs of this. */\n  const Registers& regs() const;\n\n  /** Return the extra registers of this, or null if the task died. */\n  const ExtraRegisters* extra_regs_fallible();\n\n  /** Return the current arch of this. This can change due to exec(). */\n  SupportedArch arch() const {\n    // Use 'registers' directly instead of calling regs(), since this can\n    // be called while the task is not stopped.\n    return registers.arch();\n  }\n\n  /**\n   * Return the debug status (DR6 on x86). The debug status is always cleared\n   * in resume_execution() before we resume, so it always only reflects the\n   * events since the last resume. Must not be called on non-x86 architectures.\n   */\n  uintptr_t x86_debug_status();\n\n  /**\n   * Set the debug status (DR6 on x86). Noop on non-x86 architectures.\n   */\n  void set_x86_debug_status(uintptr_t status);\n\n  /**\n   * Read the (architecture-specific) pointer authentication keys of the current task\n   */\n  std::vector<uint8_t> pac_keys(bool *ok = nullptr);\n\n  /**\n   * Set the (architecture-specific) pointer authentication keys for the current task\n   */\n  bool set_pac_keys(const std::vector<uint8_t> &data);\n\n  /**\n   * Determine why a SIGTRAP occurred. On x86, uses x86_debug_status() but doesn't\n   * consume it.\n   */\n  TrapReasons compute_trap_reasons();\n\n  /**\n   * Called on syscall entry to save any registers that we need to keep, but\n   * cannot get from the kernel (r.g. orig_x0 on aarch64).\n   */\n  void apply_syscall_entry_regs();\n\n  /**\n   * Read |val| from |child_addr|.\n   * If the data can't all be read, then if |ok| is non-null\n   * sets *ok to false, otherwise asserts.\n   */\n  template <typename T>\n  T read_mem(remote_ptr<T> child_addr, bool* ok = nullptr) {\n    typename std::remove_cv<T>::type val;\n    read_bytes_helper(child_addr, sizeof(val), &val, ok);\n    return val;\n  }\n\n  /**\n   * Read |count| values from |child_addr|.\n   */\n  template <typename T>\n  std::vector<T> read_mem(remote_ptr<T> child_addr, size_t count,\n                          bool* ok = nullptr) {\n    std::vector<T> v;\n    v.resize(count);\n    read_bytes_helper(child_addr, sizeof(T) * count, v.data(), ok);\n    return v;\n  }\n\n  /**\n   * Read and return the C string located at |child_addr| in\n   * this address space. If the data can't all be read (because the c string to\n   * be read is invalid), then if |ok| is non-null, sets *ok to\n   * false, otherwise asserts.\n   */\n  std::string read_c_str(remote_ptr<char> child_addr, bool *ok = nullptr);\n\n  /**\n   * Resume execution |how|, delivering |sig| if nonzero.\n   * After resuming, |wait_how|. In replay, reset hpcs and\n   * request a tick period of tick_period. The default value\n   * of tick_period is 0, which means effectively infinite.\n   * If interrupt_after_elapsed is nonzero, we interrupt the task\n   * after that many seconds have elapsed.\n   *\n   * All tracee execution goes through here.\n   *\n   * If `wait_how` == RESUME_WAIT and we don't complete a\n   * did_waitpid() (e.g. because the tracee was SIGKILLed or\n   * equivalent), this returns false.\n   */\n  bool resume_execution(ResumeRequest how, WaitRequest wait_how,\n                        TicksRequest tick_period, int sig = 0);\n\n  /** Return the session this is part of. */\n  Session& session() const { return *session_; }\n\n  /** Set the tracee's registers to |regs|. Lazy. */\n  void set_regs(const Registers& regs);\n\n  /** Ensure registers are flushed back to the underlying task.\n   *  Returns false if that failed due to the tracee being in\n   *  an unexpected state. */\n  bool flush_regs();\n\n  /** Set the tracee's extra registers to |regs|. */\n  void set_extra_regs(const ExtraRegisters& regs);\n\n  /** Adjust IP for rseq abort if necessary and return true if an abort is required.\n   * Sets *rseq_cs_invalid if it was invalid */\n  bool should_apply_rseq_abort(EventType event_type, remote_code_ptr* new_ip,\n                               bool* invalid_rseq_cs);\n\n  /**\n   * Read the aarch64 TLS register via ptrace. Returns true on success, false\n   * on failure. On success `result` is set to the tracee's TLS register.\n   * This can only fail when ptrace_if_stopped fails, i.e. the tracee\n   * is on the exit path due to a SIGKILL or equivalent.\n   */\n  bool read_aarch64_tls_register(uintptr_t *result);\n  void set_aarch64_tls_register(uintptr_t val);\n\n  /**\n   * Program the debug registers to the vector of watchpoint\n   * configurations in |reg| (also updating the debug control\n   * register appropriately).  Return true if all registers were\n   * successfully programmed, false otherwise.  Any time false\n   * is returned, the caller is guaranteed that no watchpoint\n   * has been enabled; either all of |regs| is enabled and true\n   * is returned, or none are and false is returned.\n   */\n  bool set_debug_regs(const HardwareWatchpoints& watchpoints);\n\n  bool set_aarch64_debug_regs(int which, ARM64Arch::user_hwdebug_state *regs, size_t nregs);\n  bool get_aarch64_debug_regs(int which, ARM64Arch::user_hwdebug_state *regs);\n\n  uintptr_t get_debug_reg(size_t regno);\n  bool set_x86_debug_reg(size_t regno, uintptr_t value);\n\n  /** Update the thread area to |addr|. */\n  void set_thread_area(remote_ptr<X86Arch::user_desc> tls);\n\n  /** Set the thread area at index `idx` to desc and reflect this\n    * into the OS task. Returns 0 on success, errno otherwise.\n    */\n  int emulate_set_thread_area(int idx, X86Arch::user_desc desc);\n\n  /** Get the thread area from the remote process.\n    * Returns 0 on success, errno otherwise.\n    */\n  int emulate_get_thread_area(int idx, X86Arch::user_desc& desc);\n\n  const std::vector<X86Arch::user_desc>& thread_areas() {\n    DEBUG_ASSERT(arch() == x86 || arch() == x86_64);\n    return thread_areas_;\n  }\n\n  void set_status(WaitStatus status) { wait_status = status; }\n\n  /**\n   * Return true when the task stopped for a ptrace-stop and we\n   * haven't resumed it yet.\n   */\n  bool is_stopped() const { return is_stopped_; }\n\n  /**\n   * Setter for `is_stopped_` to update `Scheduler::ntasks_stopped`.\n   */\n  virtual void set_stopped(bool stopped) { is_stopped_ = stopped; }\n\n  bool in_injectable_signal_stop() const { return in_injectable_signal_stop_; }\n\n  /**\n   * Return the status of this as of the last successful wait()/try_wait() call.\n   */\n  WaitStatus status() const { return wait_status; }\n\n  /**\n   * Return the ptrace event as of the last call to |wait()/try_wait()|.\n   */\n  int ptrace_event() const { return wait_status.ptrace_event(); }\n\n  /**\n   * Return the signal that's pending for this as of the last\n   * call to |wait()/try_wait()|.  The signal 0 means \"no signal\".\n   */\n  int stop_sig() const { return wait_status.stop_sig(); }\n\n  void clear_wait_status() { wait_status = WaitStatus(); }\n\n  /** Return the thread group this belongs to. */\n  std::shared_ptr<ThreadGroup> thread_group() const { return tg; }\n\n  /** Return the id of this task's recorded thread group. */\n  pid_t tgid() const;\n  /** Return id of real OS thread group. */\n  pid_t real_tgid() const;\n\n  TaskUid tuid() const { return TaskUid(rec_tid, serial); }\n\n  /** Return the dir of the trace we're using. */\n  const std::string& trace_dir() const;\n\n  /**\n   * Get the current \"time\" measured as ticks on recording trace\n   * events.  |task_time()| returns that \"time\" wrt this task\n   * only.\n   */\n  FrameTime trace_time() const;\n\n  /**\n   * Call this to reset syscallbuf_hdr->num_rec_bytes and zero out the data\n   * recorded in the syscall buffer. This makes for more deterministic behavior\n   * especially during replay, where during checkpointing we only save and\n   * restore the recorded data area.\n   */\n  void reset_syscallbuf();\n\n  /**\n   * Return the virtual memory mapping (address space) of this\n   * task.\n   */\n  AddressSpace::shr_ptr vm() { return as; }\n\n  FdTable::shr_ptr fd_table() { return fds; }\n\n  /**\n   * Block until the status of this changes. wait() expects the wait to end\n   * with the process in a stopped() state. If interrupt_after_elapsed >= 0,\n   * interrupt the task after that many seconds have elapsed. If\n   * interrupt_after_elapsed == 0.0, the interrupt will happen immediately.\n   * Returns false if the wait failed because we reached a stop but we got\n   * SIGKILLed (or equivalent) out of it, in which case it is not safe to wait\n   * because that might block indefinitely waiting for us to acknowledge the\n   * PTRACE_EVENT_EXIT of other tasks. In this case in_unexpected_exit will\n   * be true and is_stopped will be false.\n   * This can't reap the task.\n   */\n  bool wait(double interrupt_after_elapsed = -1);\n\n  /**\n   * Currently we don't allow recording across uid changes, so we can\n   * just return rr's uid.\n   */\n  uid_t getuid() { return ::getuid(); }\n\n  /**\n   * Write |N| bytes from |buf| to |child_addr|, or don't return.\n   */\n  template <size_t N>\n  void write_bytes(remote_ptr<void> child_addr, const uint8_t (&buf)[N]) {\n    write_bytes_helper(child_addr, N, buf);\n  }\n\n  enum WriteFlags {\n    IS_BREAKPOINT_RELATED = 0x1,\n  };\n  /**\n   * Write |val| to |child_addr|.\n   */\n  template <typename T>\n  void write_mem(remote_ptr<T> child_addr, const T& val, bool* ok = nullptr,\n                 uint32_t flags = 0) {\n    DEBUG_ASSERT(type_has_no_holes<T>());\n    write_bytes_helper(child_addr, sizeof(val), static_cast<const void*>(&val),\n                       ok, flags);\n  }\n  /**\n   * This is not the helper you're looking for.  See above: you\n   * probably accidentally wrote |write_mem(addr, &foo)| when\n   * you meant |write_mem(addr, foo)|.\n   */\n  template <typename T>\n  void write_mem(remote_ptr<T> child_addr, const T* val) = delete;\n\n  template <typename T>\n  void write_mem(remote_ptr<T> child_addr, const T* val, int count,\n                 bool* ok = nullptr) {\n    DEBUG_ASSERT(type_has_no_holes<T>());\n    write_bytes_helper(child_addr, sizeof(*val) * count,\n                       static_cast<const void*>(val), ok);\n  }\n\n  uint64_t write_ranges(const std::vector<FileMonitor::Range>& ranges,\n                        void* data, size_t size);\n\n  /**\n   * Writes zeroes to the given memory range.\n   * For efficiency tries using MADV_REMOVE via `remote`. Caches\n   * an AutoRemoteSyscalls in `*remote`.\n   */\n  void write_zeroes(std::unique_ptr<AutoRemoteSyscalls>* remote, remote_ptr<void> addr, size_t size);\n\n  /**\n   * Don't use these helpers directly; use the safer and more\n   * convenient variants above.\n   *\n   * Read/write the number of bytes that the template wrapper\n   * inferred.\n   */\n  ssize_t read_bytes_fallible(remote_ptr<void> addr, ssize_t buf_size,\n                              void* buf);\n  /**\n   * If the data can't all be read, then if |ok| is non-null, sets *ok to\n   * false, otherwise asserts.\n   */\n  void read_bytes_helper(remote_ptr<void> addr, ssize_t buf_size, void* buf,\n                         bool* ok = nullptr);\n  /**\n   * |flags| is bits from WriteFlags.\n   */\n  ssize_t write_bytes_helper(remote_ptr<void> addr, ssize_t buf_size,\n                          const void* buf, bool* ok = nullptr,\n                          uint32_t flags = 0);\n  /**\n   * |flags| is bits from WriteFlags.\n   * Returns number of bytes written.\n   */\n  ssize_t write_bytes_helper_no_notifications(remote_ptr<void> addr, ssize_t buf_size,\n                                              const void* buf, bool* ok = nullptr,\n                                              uint32_t flags = 0);\n\n  /**\n   * This task has been selected to run next.\n   */\n  void will_schedule();\n\n  SupportedArch detect_syscall_arch();\n\n  /**\n   * Call this when performing a clone syscall in this task. Returns\n   * true if the call completed, false if it was interrupted and\n   * needs to be resumed. When the call returns true, the task is\n   * stopped at a PTRACE_EVENT_CLONE or PTRACE_EVENT_FORK.\n   */\n  bool clone_syscall_is_complete(pid_t* new_pid, SupportedArch syscall_arch);\n\n  /**\n   * Called when SYS_rrcall_init_preload has happened.\n   */\n  virtual void at_preload_init();\n\n  /**\n   * Open /proc/[tid]/mem fd for our AddressSpace, closing the old one\n   * first. If necessary we force the tracee to open the file\n   * itself and smuggle the fd back to us.\n   * Returns false if the process no longer exists.\n   */\n  bool open_mem_fd();\n\n  /**\n   * Calls open_mem_fd if this task's AddressSpace doesn't already have one.\n   */\n  void open_mem_fd_if_needed();\n\n  /**\n   * Open /proc/[tid]/pagemap fd for our AddressSpace.\n   */\n  ScopedFd& pagemap_fd();\n\n  /**\n   * Perform a PTRACE_INTERRUPT and set up the counter for potential spurious stops\n   * to be detected in `account_for_potential_ptrace_interrupt_stop`.\n   * Returns true if it succeeded, false if we got ESRCH (i.e. the tracee has\n   * disappeared or is not being ptraced; PTRACE_INTERRUPT doesn't require the\n   * tracee to be stopped).\n   */\n  bool do_ptrace_interrupt();\n\n  /**\n   * Sometimes we use PTRACE_INTERRUPT to kick the tracee out of various\n   * undesirable states. Unfortunately, that can (but need not) result in later\n   * undesired GROUP-STOP-SIGTRAP stops which report the PTRACE_INTERRUPT.\n   * This function may be called when examining stops to account for any\n   * such spurious stops.\n   *\n   * Should be called at exactly once for every ptrace stop.\n   *\n   * Returns true if the stop is caused by a PTRACE_INTERRUPT we know about,\n   * false otherwise.\n   */\n  bool account_for_potential_ptrace_interrupt_stop(WaitStatus status);\n\n  /* Imagine that task A passes buffer |b| to the read()\n   * syscall.  Imagine that, after A is switched out for task B,\n   * task B then writes to |b|.  Then B is switched out for A.\n   * Since rr doesn't schedule the kernel code, the result is\n   * nondeterministic.  To avoid that class of replay\n   * divergence, we \"redirect\" (in)outparams passed to may-block\n   * syscalls, to \"scratch memory\".  The kernel writes to\n   * scratch deterministically, and when A (in the example\n   * above) exits its read() syscall, rr copies the scratch data\n   * back to the original buffers, serializing A and B in the\n   * example above.\n   *\n   * Syscalls can \"nest\" due to signal handlers.  If a syscall A\n   * is interrupted by a signal, and the sighandler calls B,\n   * then we can have scratch buffers set up for args of both A\n   * and B.  In linux, B won't actually re-enter A; A is exited\n   * with a \"will-restart\" error code and its args are saved for\n   * when (or if) it's restarted after the signal.  But that\n   * doesn't really matter wrt scratch space.  (TODO: in the\n   * future, we may be able to use that fact to simplify\n   * things.)\n   *\n   * Because of nesting, at first blush it seems we should push\n   * scratch allocations onto a stack and pop them as syscalls\n   * (or restarts thereof) complete.  But under a critical\n   * assumption, we can actually skip that.  The critical\n   * assumption is that the kernel writes its (in)outparams\n   * atomically wrt signal interruptions, and only writes them\n   * on successful exit.  Each syscall will complete in stack\n   * order, and it's invariant that the syscall processors must\n   * only write back to user buffers *only* the data that was\n   * written by the kernel.  So as long as the atomicity\n   * assumption holds, the completion of syscalls higher in the\n   * event stack may overwrite scratch space, but the completion\n   * of each syscall will overwrite those overwrites again, and\n   * that over-overwritten data is exactly and only what we'll\n   * write back to the tracee.\n   *\n   * |scratch_ptr| points at the mapped address in the child,\n   * and |size| is the total available space. */\n  remote_ptr<void> scratch_ptr;\n  /* The full size of the scratch buffer.\n   * The last page of the scratch buffer is used as an alternate stack\n   * for the syscallbuf code. So the usable size is less than this.\n   */\n  ssize_t scratch_size;\n\n  /* The child's desched counter event fd number */\n  int desched_fd_child;\n  /* The child's cloned_file_data_fd */\n  int cloned_file_data_fd_child;\n  /* The filename opened by the child's cloned_file_data_fd */\n  std::string cloned_file_data_fname;\n  // Current rseq state if registered\n  std::unique_ptr<RseqState> rseq_state;\n\n  PerfCounters hpc;\n\n  /* This is always the \"real\" tid of the tracee. For a detached proxy,\n   * it's the proxy tid. */\n  pid_t tid;\n  /* This is always the recorded tid of the tracee.  During\n   * recording, it's synonymous with |tid|, and during replay\n   * it's the tid that was recorded. For a detached proxy,\n   * this is the tid of the detachd process. */\n  pid_t rec_tid;\n  /* This is the recorded tid of the tracee *in its own pid namespace*. */\n  pid_t own_namespace_rec_tid;\n\n  size_t syscallbuf_size;\n  /* Points at the tracee's mapping of the buffer. */\n  remote_ptr<struct syscallbuf_hdr> syscallbuf_child;\n\n  remote_ptr<struct preload_globals> preload_globals;\n  typedef uint8_t ThreadLocals[PRELOAD_THREAD_LOCALS_SIZE];\n  ThreadLocals thread_locals;\n\n  size_t usable_scratch_size() {\n    return std::max<ssize_t>(0, scratch_size - page_size());\n  }\n  remote_ptr<void> syscallbuf_alt_stack() {\n    return scratch_ptr.is_null() ? remote_ptr<void>()\n                                 : scratch_ptr + scratch_size;\n  }\n  void setup_preload_thread_locals();\n  void setup_preload_thread_locals_from_clone(Task* origin);\n  // If `fetch_full` is false, avoid fetching the full stub_scratch_2 on aarch64\n  // and only fetch the first two pointers from it.\n  const ThreadLocals& fetch_preload_thread_locals();\n  void activate_preload_thread_locals();\n\n  struct CapturedState {\n    Ticks ticks;\n    Registers regs;\n    ExtraRegisters extra_regs;\n    std::string prname;\n    uintptr_t fdtable_identity;\n    remote_ptr<struct syscallbuf_hdr> syscallbuf_child;\n    size_t syscallbuf_size;\n    size_t num_syscallbuf_bytes;\n    remote_ptr<struct preload_globals> preload_globals;\n    remote_ptr<void> scratch_ptr;\n    ssize_t scratch_size;\n    remote_ptr<void> top_of_stack;\n    std::unique_ptr<RseqState> rseq_state;\n    uint64_t cloned_file_data_offset;\n    ThreadLocals thread_locals;\n    pid_t rec_tid;\n    pid_t own_namespace_rec_tid;\n    uint32_t serial;\n    ThreadGroupUid tguid;\n    int desched_fd_child;\n    int cloned_file_data_fd_child;\n    std::string cloned_file_data_fname;\n    WaitStatus wait_status;\n    // TLS state (architecture specific)\n    // On x86_64 the tls register is part of the general register state (%fs)\n    // On x86 thread_areas is used\n    // on aarch64, tls_register is used\n    uintptr_t tls_register;\n    std::vector<X86Arch::user_desc> thread_areas;\n  };\n\n  /**\n   * Lock or unlock the syscallbuf to prevent the preload library from using it.\n   * Only has an effect if the syscallbuf has been initialized.\n   */\n  void set_syscallbuf_locked(bool locked);\n\n  // Disable syscall buffering during diversions\n  void set_in_diversion(bool in_diversion) {\n    if (preload_globals) {\n      write_mem(REMOTE_PTR_FIELD(preload_globals, in_diversion),\n                (unsigned char)in_diversion);\n    }\n    set_syscallbuf_locked(in_diversion);\n  }\n\n  /**\n   * Executes a ptrace() call that expects the task to be in a ptrace-stop.\n   * Errors other than ESRCH are treated as fatal (those are rr bugs).\n   * Only call this when `Task::is_stopped_`.\n   * Even when `is_stopped_` is true, this can return false because the kernel\n   * could have pushed the task out of the ptrace-stop due to SIGKILL or\n   * equivalent (such as `zap_pid_ns_processes`).\n   *\n   * So when this returns false, one of the following is true:\n   * * The tracee is executing towards its PTRACE_EVENT_EXIT stop. This\n   * happens concurrently with rr so it may enter that stop at any time.\n   * But it can also be indefinitely delayed before reaching the exit stop,\n   * e.g. waiting in`zap_pid_ns_processes`.\n   * * In older kernels (before 9a95f78eab70deeb5a4c879c19b841a6af5b66e7)\n   * it is possible for a tracee stopped in PTRACE_EVENT_EXIT to be kicked\n   * out of that stop by another SIGKILL. In that case it is executing towards\n   * or has actually reached the zombie state. In old kernels it can be\n   * blocked indefinitely from reaching the zombie state due to coredumping.\n   *\n   * In either of these cases, the tracee has been killed via SIGKILL or equivalent\n   * and will not execute user code or system calls again. We can assume\n   * its registers won't change again. It won't handle any more signals.\n   */\n  bool ptrace_if_stopped(int request, remote_ptr<void> addr, void* data);\n\n  /**\n   * Make the ptrace |request| with |addr| and |data|, return\n   * the ptrace return value. Just a very thin wrapper around the syscall.\n   */\n  long fallible_ptrace(int request, remote_ptr<void> addr, void* data);\n\n  bool is_exiting() const {\n    return seen_ptrace_exit_event_ || was_reaped_ || in_unexpected_exit;\n  }\n\n  bool seen_ptrace_exit_event() const {\n    return seen_ptrace_exit_event_;\n  }\n\n  void did_handle_ptrace_exit_event();\n\n  remote_code_ptr last_execution_resume() const {\n    return address_of_last_execution_resume;\n  }\n\n  bool was_reaped() const {\n    return was_reaped_;\n  }\n  bool handled_ptrace_exit_event() const {\n    return handled_ptrace_exit_event_;\n  }\n  bool stopped_or_unexpected_exit() const {\n    return is_stopped_ || was_reaped_ || in_unexpected_exit;\n  }\n\n  void os_exec(SupportedArch arch, std::string filename);\n  void os_exec_stub(SupportedArch arch) {\n      os_exec(arch, find_exec_stub(arch));\n  }\n\n  /**\n   * Try to make the current task look exactly like some `other` task\n   * by copying that task's address space and other relevant properties,\n   * but without using the os's clone system call.\n   */\n  void dup_from(Task *task);\n\n  virtual ~Task();\n\n  /**\n   * Fork and exec the initial task. If something goes wrong later\n   * (i.e. an exec does not occur before an exit), an error may be\n   * readable from the other end of the pipe whose write end is error_fd.\n   */\n  static Task* spawn(Session& session, ScopedFd& error_fd,\n                     ScopedFd* sock_fd_out,\n                     ScopedFd* sock_fd_receiver_out,\n                     int* tracee_socket_fd_number_out,\n                     const std::string& exe_path,\n                     const std::vector<std::string>& argv,\n                     const std::vector<std::string>& envp, pid_t rec_tid = -1);\n\n  /**\n   * Do PTRACE_SEIZE on this tid with the correct ptrace options.\n   */\n  static long ptrace_seize(pid_t tid, Session& session);\n\n  /**\n   * Do a tgkill to send a specific signal to this task.\n   */\n  void tgkill(int sig);\n\n  /**\n   * Try to move this task to a signal stop by signaling it with the\n   * syscallbuf desched signal (which is guaranteed not to be blocked).\n   * Returns false if the task exited unexpectedly.\n   */\n  bool move_to_signal_stop();\n\n  // A map from original table to (potentially detached) clone, to preserve\n  // FdTable sharing relationships during a session fork.\n  using ClonedFdTables = std::unordered_map<uintptr_t, FdTable::shr_ptr>;\n\n  /**\n   * Just forget that this Task exists. Another rr process will manage it.\n   */\n  void forget();\n\n  // Used on aarch64 to detect whether we've recorded x0 and x8 on syscall entry\n  Ticks ticks_at_last_syscall_entry;\n  remote_code_ptr ip_at_last_syscall_entry;\n  // Whether the syscall entry corresponding to `{ticks,ip}_at_last_syscall_entry`\n  // has been recorded in the trace\n  // (used to avoid double recording on unexpected exit)\n  bool last_syscall_entry_recorded;\n\n  /*\n   * Called before the scheduler resumes a task to check if the task's address\n   * space has any leftover syscallbufs from dead processes which shared the\n   * address space\n   */\n  void unmap_dead_syscallbufs_if_required();\n\nprotected:\n  Task(Session& session, pid_t tid, pid_t rec_tid, uint32_t serial,\n       SupportedArch a);\n\n  enum CloneReason {\n    // Cloning a task in the same session due to tracee fork()/vfork()/clone()\n    TRACEE_CLONE,\n    // Cloning a task into a new session as the leader for a checkpoint\n    SESSION_CLONE_LEADER,\n    // Cloning a task into the same session to recreate threads while\n    // restoring a checkpoint\n    SESSION_CLONE_NONLEADER,\n  };\n  /**\n   * Return a new Task cloned from |p|.  |flags| are a set of\n   * CloneFlags (see above) that determine which resources are\n   * shared or copied to the new child.  |new_tid| is the tid\n   * assigned to the new task by the kernel.  |new_rec_tid| is\n   * only relevant to replay, and is the pid that was assigned\n   * to the task during recording.\n   */\n  virtual Task* clone(CloneReason reason, int flags, remote_ptr<void> stack,\n                      remote_ptr<void> tls, remote_ptr<int> cleartid_addr,\n                      pid_t new_tid, pid_t new_rec_tid, uint32_t new_serial,\n                      Session* other_session = nullptr,\n                      FdTable::shr_ptr new_fds = nullptr,\n                      ThreadGroup::shr_ptr new_tg = nullptr);\n\n  /**\n   * Internal method called after the first wait() during a clone().\n   */\n  virtual void post_wait_clone(Task*, int) {}\n\n  /**\n   * Internal method called after the clone to fix up the new address space.\n   */\n  virtual bool post_vm_clone(CloneReason reason, int flags, Task* origin);\n\n  template <typename Arch>\n  void on_syscall_exit_arch(int syscallno, const Registers& regs);\n\n  /** Helper function for init_buffers. */\n  template <typename Arch> void init_buffers_arch(remote_ptr<void> map_hint);\n\n  /**\n   * Grab state from this task into a structure that we can use to\n   * initialize a new task via os_clone_into/os_fork_into and copy_state.\n   */\n  CapturedState capture_state();\n\n  /**\n   * Make this task look like an identical copy of the task whose state\n   * was captured by capture_task_state(), in\n   * every way relevant to replay.  This task should have been\n   * created by calling os_clone_into() or os_fork_into(),\n   * and if it wasn't results are undefined.\n   *\n   * Some task state must be copied into this by injecting and\n   * running syscalls in this task.  Other state is metadata\n   * that can simply be copied over in local memory.\n   */\n  void copy_state(const CapturedState& state);\n\n  /**\n   * Read tracee memory using PTRACE_PEEKDATA calls. Slow, only use\n   * as fallback. Returns number of bytes actually read.\n   */\n  ssize_t read_bytes_ptrace(remote_ptr<void> addr, ssize_t buf_size, void* buf);\n\n  /**\n   * Write tracee memory using PTRACE_POKEDATA calls. Slow, only use\n   * as fallback. Returns number of bytes actually written.\n   */\n  ssize_t write_bytes_ptrace(remote_ptr<void> addr, ssize_t buf_size,\n                             const void* buf);\n\n  /**\n   * Try writing 'buf' to 'addr' by replacing pages in the tracee\n   * address-space using a temporary file. This may work around PaX issues.\n   */\n  bool try_replace_pages(remote_ptr<void> addr, ssize_t buf_size,\n                         const void* buf);\n\n  /**\n   * Map the syscallbuffer for this, shared with this process.\n   * |map_hint| is the address where the syscallbuf is expected\n   * to be mapped --- and this is asserted --- or nullptr if\n   * there are no expectations.\n   * Initializes syscallbuf_child.\n   */\n  KernelMapping init_syscall_buffer(AutoRemoteSyscalls& remote,\n                                    remote_ptr<void> map_hint);\n\n  /**\n   * Make the OS-level calls to create a new fork or clone that\n   * will eventually be a copy of this task and return that Task\n   * metadata.  These methods are used in concert with\n   * |Task::copy_state()| to create task copies during\n   * checkpointing.\n   *\n   * For |os_fork_into()|, |session| will be tracking the\n   * returned fork child.\n   *\n   * For |os_clone_into()|, |task_leader| is the \"main thread\"\n   * in the process into which the copy of this task will be\n   * created.  |task_leader| will perform the actual OS calls to\n   * create the new child.\n   */\n  Task* os_fork_into(Session* session, FdTable::shr_ptr new_fds);\n  static Task* os_clone_into(const CapturedState& state,\n                             AutoRemoteSyscalls& remote,\n                             const ClonedFdTables& cloned_fd_tables,\n                             ThreadGroup::shr_ptr new_tg);\n\n  /**\n   * Return the TraceStream that we're using, if in recording or replay.\n   * Returns null if we're not in record or replay.\n   */\n  const TraceStream* trace_stream() const;\n\n  /**\n   * Make the OS-level calls to clone |parent| into |session|\n   * and return the resulting Task metadata for that new\n   * process.  This is as opposed to |Task::clone()|, which only\n   * attaches Task metadata to an /existing/ process.\n   *\n   * The new clone will be tracked in |session|.  The other\n   * arguments are as for |Task::clone()| above.\n   */\n  static Task* os_clone(CloneReason reason, Session* session,\n                        AutoRemoteSyscalls& remote, pid_t rec_child_tid,\n                        uint32_t new_serial, unsigned base_flags,\n                        FdTable::shr_ptr new_fds = nullptr,\n                        ThreadGroup::shr_ptr new_tg = nullptr,\n                        remote_ptr<void> stack = nullptr,\n                        remote_ptr<int> ptid = nullptr,\n                        remote_ptr<void> tls = nullptr,\n                        remote_ptr<int> ctid = nullptr);\n\n  void work_around_KNL_string_singlestep_bug();\n\n  void* preload_thread_locals();\n\n  uint32_t serial;\n  // The address space of this task.\n  AddressSpace::shr_ptr as;\n  // The file descriptor table of this task.\n  FdTable::shr_ptr fds;\n  // Count of all ticks seen by this task since tracees became\n  // consistent and the task last wait()ed.\n  Ticks ticks;\n  // Copy of the child registers.\n  // When is_stopped_ or in_unexpected_exit, these are the source of\n  // truth. Otherwise the child is running and the registers could be\n  // changed by the kernel or user-space execution, and the values here\n  // are meaningless.\n  // See also registers_dirty.\n  Registers registers;\n  // Where we last resumed execution\n  remote_code_ptr address_of_last_execution_resume;\n  // Current hardware watchpoint state as programmed into debug registers\n  HardwareWatchpoints current_hardware_watchpoints;\n  ResumeRequest how_last_execution_resumed;\n  // In certain circumstances, due to hardware bugs, we need to fudge the\n  // cx register. If so, we record the original value here. See comments in\n  // Task.cc\n  uint64_t last_resume_orig_cx;\n  // The instruction type we're singlestepping through.\n  SpecialInst singlestepping_instruction;\n  // True if we set a breakpoint after a singlestepped CPUID instruction.\n  // We need this in addition to `singlestepping_instruction` because that\n  // might be CPUID but we failed to set the breakpoint.\n  bool did_set_breakpoint_after_cpuid;\n  // True when we know via waitpid() that the task was stopped in\n  // a ptrace-stop and we haven't resumed it.\n  // It is possible that the task has been pushed out of the ptrace-stop\n  // without our knowledge, due to a SIGKILL or equivalent such as\n  // zap_pid_ns_processes.\n  bool is_stopped_;\n  // True when we've been kicked out of a ptrace-stop via SIGKILL or\n  // equivalent.\n  bool in_unexpected_exit;\n  // True when the task is stopped in a signal-stop where we can\n  // inject our own signal. Usually equal to wait_status.stop_sig() > 0,\n  // but can be different if an AutoRemoteSyscalls changed our state and\n  // then restored wait_status.\n  bool in_injectable_signal_stop_;\n  /* True when the seccomp filter has been enabled via prctl(). This happens\n   * in the first system call issued by the initial tracee (after it returns\n   * from kill(SIGSTOP) to synchronize with the tracer). */\n  bool seccomp_bpf_enabled;\n  // True when 'registers' has changes that haven't been flushed back to the\n  // task yet.\n  bool registers_dirty;\n  // True when changes to the original syscallno in 'registers' have not been\n  // flushed back to the task yet. Some architectures (e.g. AArch64) require a\n  // separate ptrace call for this.\n  bool orig_syscallno_dirty;\n  // When |extra_registers_known|, we have saved our extra registers.\n  ExtraRegisters extra_registers;\n  bool extra_registers_known;\n  // The session we're part of.\n  Session* session_;\n  // The thread group this belongs to.\n  std::shared_ptr<ThreadGroup> tg;\n  // Entries set by |set_thread_area()| or the |tls| argument to |clone()|\n  // (when that's a user_desc). May be more than one due to different\n  // entry_numbers.\n  // x86(_64) only.\n  std::vector<X86Arch::user_desc> thread_areas_;\n  // The |stack| argument passed to |clone()|, which for\n  // \"threads\" is the top of the user-allocated stack.\n  remote_ptr<void> top_of_stack;\n  // The most recent status of this task as returned by\n  // waitpid().\n  WaitStatus wait_status;\n  // The most recent siginfo (captured when wait_status shows pending_sig())\n  siginfo_t pending_siginfo;\n  // True when a PTRACE_EXIT_EVENT has been observed in the wait_status\n  // for this task.\n  bool seen_ptrace_exit_event_;\n  // True when a PTRACE_EXIT_EVENT has been handled for this task.\n  // By handled we mean either RecordSession's handle_ptrace_exit_event was\n  // run (or the replay equivalent) or we recognized that the task is already\n  // dead and we cleaned up our books so we don't try to destroy our buffers\n  // or anything like that in an already deceased task.\n  // We might defer handling the exit (e.g. if there's an ongoing execve).\n  // If this is true, `seen_ptrace_exit_event` must be true.\n  bool handled_ptrace_exit_event_;\n\n  // A counter for the number of stops for which the stop may have been caused\n  // by PTRACE_INTERRUPT. See description in do_waitpid\n  int expecting_ptrace_interrupt_stop;\n\n  bool was_reaped_;\n  // Let this Task object be destroyed with no consequences.\n  bool forgotten;\n\n  Task(Task&) = delete;\n  Task operator=(Task&) = delete;\n};\n\n} // namespace rr\n\n#endif /* RR_TASK_H_ */\n"
  },
  {
    "path": "src/TaskishUid.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TASKISH_UID_H_\n#define RR_TASKISH_UID_H_\n\n#include <inttypes.h>\n#include <unistd.h>\n\nnamespace rr {\n\nclass AddressSpace;\nclass Task;\nclass ThreadGroup;\n\n/**\n * An ID that's unique within a Session (but consistent across\n * multiple ReplaySessions for the same trace), used by Tasks, ThreadGroups\n * and AddressSpaces.\n * This is needed because tids can be recycled during a long-running session.\n */\ntemplate <class T> class TaskishUid {\npublic:\n  TaskishUid() : tid_(0), serial_(0) {}\n  TaskishUid(pid_t tid, uint32_t serial) : tid_(tid), serial_(serial) {}\n  TaskishUid(const TaskishUid<T>& other) = default;\n  TaskishUid& operator=(const TaskishUid<T>& other) = default;\n  bool operator==(const TaskishUid<T>& other) const {\n    return tid_ == other.tid_ && serial_ == other.serial_;\n  }\n  bool operator!=(const TaskishUid<T>& other) const {\n    return !(*this == other);\n  }\n  bool operator<(const TaskishUid<T>& other) const {\n    if (tid_ < other.tid_) {\n      return true;\n    }\n    if (tid_ > other.tid_) {\n      return false;\n    }\n    return serial_ < other.serial_;\n  }\n  pid_t tid() const { return tid_; }\n  uint32_t serial() const { return serial_; }\n\nprivate:\n  pid_t tid_;\n  uint32_t serial_;\n};\n\ntypedef TaskishUid<Task> TaskUid;\ntypedef TaskishUid<ThreadGroup> ThreadGroupUid;\n\nclass AddressSpaceUid : public TaskishUid<AddressSpace> {\npublic:\n  AddressSpaceUid() : exec_count_(0) {}\n  AddressSpaceUid(pid_t tid, uint32_t serial, uint32_t exec_count)\n      : TaskishUid<AddressSpace>(tid, serial), exec_count_(exec_count) {}\n  AddressSpaceUid(const AddressSpaceUid& other) = default;\n  AddressSpaceUid& operator=(const AddressSpaceUid& other) = default;\n  bool operator==(const AddressSpaceUid& other) const {\n    return TaskishUid<AddressSpace>::operator==(other) &&\n           exec_count_ == other.exec_count_;\n  }\n  bool operator<(const AddressSpaceUid& other) const {\n    if (TaskishUid<AddressSpace>::operator<(other)) {\n      return true;\n    }\n    if (other.TaskishUid<AddressSpace>::operator<(*this)) {\n      return false;\n    }\n    return exec_count_ < other.exec_count_;\n  }\n  uint32_t exec_count() const { return exec_count_; }\n\nprivate:\n  uint32_t exec_count_;\n};\n\n} // namespace rr\n\nnamespace std {\n  template <typename T> struct hash<rr::TaskishUid<T>> {\n    std::size_t operator()(const rr::TaskishUid<T>& k) const {\n      return k.serial();\n    }\n  };\n}\n\n#endif // RR_TASKISH_UID_H_\n"
  },
  {
    "path": "src/ThreadDb.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ThreadDb.h\"\n#include \"GdbServer.h\"\n#include \"Task.h\"\n#include \"ThreadGroup.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nextern \"C\" {\n// The proc_service/thread_db library has a very weird API.  It\n// requires the user of the library to provide certain functions which\n// it links to (rather than, say, having the library user supply a\n// struct of function pointers).  We have to ensure that these\n// functions have C linkage, so that libthread_db can find them.\n#include \"proc_service.h\"\n}\n\n#include <dlfcn.h>\n#include <linux/elf.h>\n\n#define LIBRARY_NAME \"libthread_db.so.1\"\n\n// Needed for the logging API.\nusing namespace rr;\n\nps_err_e ps_pglobal_lookup(struct ps_prochandle* h, const char*,\n                           const char* symbol, psaddr_t* sym_addr) {\n  rr::remote_ptr<void> addr;\n  if (!h->db->query_symbol(symbol, &addr)) {\n    LOG(debug) << \"ps_pglobal_lookup \" << symbol << \" failed\";\n    return PS_NOSYM;\n  }\n  *sym_addr = reinterpret_cast<psaddr_t>(addr.as_int());\n  LOG(debug) << \"ps_pglobal_lookup \" << symbol << \" OK\";\n  return PS_OK;\n}\n\nps_err_e ps_pdread(struct ps_prochandle* h, psaddr_t addr, void* buffer,\n                   size_t len) {\n  if (!h->thread_group) {\n    FATAL() << \"unexpected ps_pdread call with uninitialized thread_group\";\n  }\n  bool ok = true;\n  uintptr_t uaddr = reinterpret_cast<uintptr_t>(addr);\n  // We need any task associated with the thread group.  Here we assume\n  // that all the tasks in the thread group share VM, which is enforced\n  // by clone(2).\n  rr::Task* task = h->thread_group->first_running_task();\n  if (!task) {\n    return PS_ERR;\n  }\n  task->read_bytes_helper(uaddr, len, buffer, &ok);\n  LOG(debug) << \"ps_pdread \" << ok;\n  return ok ? PS_OK : PS_ERR;\n}\n\nps_err_e ps_pdwrite(struct ps_prochandle*, psaddr_t, const void*, size_t) {\n  FATAL() << \"ps_pdwrite not implemented\";\n  return PS_ERR;\n}\n\nps_err_e ps_lgetregs(struct ps_prochandle* h, lwpid_t rec_tid,\n                     prgregset_t result) {\n  if (!h->thread_group) {\n    FATAL() << \"unexpected ps_lgetregs call with uninitialized thread_group\";\n  }\n  rr::Task* task = h->thread_group->session()->find_task(rec_tid);\n  DEBUG_ASSERT(task != nullptr);\n\n  NativeArch::user_regs_struct regs = task->regs().get_ptrace();\n  memcpy(result, static_cast<void*>(&regs), sizeof(regs));\n  LOG(debug) << \"ps_lgetregs OK\";\n  return PS_OK;\n}\n\nps_err_e ps_lsetregs(struct ps_prochandle*, lwpid_t, const prgregset_t) {\n  FATAL() << \"ps_lsetregs not implemented\";\n  return PS_ERR;\n}\n\nps_err_e ps_lgetfpregs(struct ps_prochandle*, lwpid_t, prfpregset_t*) {\n  FATAL() << \"ps_lgetfpregs not implemented\";\n  return PS_ERR;\n}\n\nps_err_e ps_lsetfpregs(struct ps_prochandle*, lwpid_t, const prfpregset_t*) {\n  FATAL() << \"ps_lsetfpregs not implemented\";\n  return PS_ERR;\n}\n\npid_t ps_getpid(struct ps_prochandle* h) {\n  LOG(debug) << \"ps_getpid \" << h->tgid;\n  return h->tgid;\n}\n\nstatic const int _REG_FS = 25;\nstatic const int _REG_GS = 26;\n\nps_err_e ps_get_thread_area(const struct ps_prochandle* h, lwpid_t rec_tid,\n                            int val, psaddr_t* base) {\n  if (!h->thread_group) {\n    FATAL()\n        << \"unexpected ps_get_thread_area call with uninitialized thread_group\";\n  }\n  rr::Task* task = h->thread_group->session()->find_task(rec_tid);\n  DEBUG_ASSERT(task != nullptr);\n\n  if (task->arch() == rr::x86) {\n    unsigned int uval = static_cast<unsigned int>(val);\n    for (auto& area : task->thread_areas()) {\n      if (area.entry_number == uval) {\n        uintptr_t result = static_cast<uintptr_t>(area.base_addr);\n        *base = reinterpret_cast<psaddr_t>(result);\n        return PS_OK;\n      }\n    }\n    LOG(debug) << \"ps_get_thread_area 32 failed\";\n    return PS_ERR;\n  } else if (task->arch() == rr::x86_64) {\n    uintptr_t result;\n    switch (val) {\n      case _REG_FS:\n        result = task->regs().fs_base();\n        break;\n      case _REG_GS:\n        result = task->regs().gs_base();\n        break;\n      default:\n        LOG(debug) << \"ps_get_thread_area PS_BADADDR\";\n        return PS_BADADDR;\n    }\n\n    *base = reinterpret_cast<psaddr_t>(result);\n    return PS_OK;\n  } else if (task->arch() == aarch64) {\n    uintptr_t result;\n    if (!task->read_aarch64_tls_register(&result)) {\n      LOG(error) << \"Task was dead\";\n      return PS_ERR;\n    }\n    *base = reinterpret_cast<psaddr_t>(result - val);\n    return PS_OK;\n  } else {\n    LOG(error) << \"Unknown architecture in ThreadDb\";\n    return PS_ERR;\n  }\n}\n\nrr::ThreadDb::ThreadDb(pid_t tgid)\n    : internal_handle(nullptr),\n      thread_db_library(nullptr),\n      td_ta_delete_fn(nullptr),\n      td_thr_tls_get_addr_fn(nullptr),\n      td_ta_map_lwp2thr_fn(nullptr) {\n  prochandle.thread_group = nullptr;\n  prochandle.db = this;\n  prochandle.tgid = tgid;\n}\n\nrr::ThreadDb::~ThreadDb() {\n  if (internal_handle) {\n    td_ta_delete_fn(internal_handle);\n  }\n  if (thread_db_library) {\n    dlclose(thread_db_library);\n  }\n}\n\nconst std::set<std::string> rr::ThreadDb::get_symbols_and_clear_map(\n    ThreadGroup* thread_group) {\n  // If we think the symbol locations might have changed, then we\n  // probably need to recreate the handle.\n  if (internal_handle) {\n    td_ta_delete_fn(internal_handle);\n    internal_handle = nullptr;\n  }\n\n  prochandle.thread_group = thread_group;\n  symbols.clear();\n  load_library();\n  prochandle.thread_group = nullptr;\n  return symbol_names;\n}\n\nvoid rr::ThreadDb::register_symbol(const std::string& name,\n                                   remote_ptr<void> address) {\n  LOG(debug) << \"register_symbol \" << name;\n  symbols[name] = address;\n}\n\nbool rr::ThreadDb::query_symbol(const char* name, remote_ptr<void>* address) {\n  auto it = symbols.find(name);\n  if (it == symbols.end()) {\n    return false;\n  }\n  *address = it->second;\n  return true;\n}\n\nbool rr::ThreadDb::get_tls_address(ThreadGroup* thread_group, pid_t rec_tid,\n                                   size_t offset, remote_ptr<void> load_module,\n                                   remote_ptr<void>* result) {\n  prochandle.thread_group = thread_group;\n  if (!initialize()) {\n    prochandle.thread_group = nullptr;\n    return false;\n  }\n\n  td_thrhandle_t th;\n  if (td_ta_map_lwp2thr_fn(internal_handle, rec_tid, &th) != TD_OK) {\n    prochandle.thread_group = nullptr;\n    return false;\n  }\n\n  psaddr_t load_module_addr = reinterpret_cast<psaddr_t>(load_module.as_int());\n  psaddr_t addr;\n  if (td_thr_tls_get_addr_fn(&th, load_module_addr, offset, &addr) != TD_OK) {\n    prochandle.thread_group = nullptr;\n    return false;\n  }\n  prochandle.thread_group = nullptr;\n  *result = remote_ptr<void>(reinterpret_cast<uintptr_t>(addr));\n  return true;\n}\n\nbool rr::ThreadDb::initialize() {\n  if (internal_handle) {\n    return true;\n  }\n\n  if (!load_library()) {\n    return false;\n  }\n\n  if (!td_ta_new_fn || td_ta_new_fn(&prochandle, &internal_handle) != TD_OK) {\n    LOG(debug) << \"initialize td_ta_new_fn failed\";\n    return false;\n  }\n\n  LOG(debug) << \"initialize OK\";\n  return true;\n}\n\nbool rr::ThreadDb::load_library() {\n  if (thread_db_library) {\n    LOG(debug) << \"load_library already loaded: \" << loaded;\n    return loaded;\n  }\n\n  thread_db_library = dlopen(LIBRARY_NAME, RTLD_NOW);\n  if (!thread_db_library) {\n    LOG(debug) << \"load_library dlopen failed\";\n    return false;\n  }\n\n  decltype(td_symbol_list)* td_symbol_list_fn;\n\n#define FIND_FUNCTION(Name)                                                    \\\n  do {                                                                         \\\n    Name##_fn = (decltype(Name)*)(dlsym(thread_db_library, #Name));            \\\n    if (!Name##_fn) {                                                          \\\n      LOG(debug) << \"load_library failed to find \" << #Name;                   \\\n      return false;                                                            \\\n    }                                                                          \\\n  } while (0)\n\n  FIND_FUNCTION(td_thr_tls_get_addr);\n  FIND_FUNCTION(td_ta_delete);\n  FIND_FUNCTION(td_symbol_list);\n  FIND_FUNCTION(td_ta_new);\n  FIND_FUNCTION(td_ta_map_lwp2thr);\n\n#undef FIND_FUNCTION\n\n  for (const char** syms = td_symbol_list_fn(); *syms; ++syms) {\n    symbol_names.insert(*syms);\n  }\n\n  // Good to go.\n  loaded = true;\n  LOG(debug) << \"load_library OK\";\n  return true;\n}\n"
  },
  {
    "path": "src/ThreadDb.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_THREADDB_H_\n#define RR_THREADDB_H_\n\n#include \"remote_ptr.h\"\n#include <map>\n#include <set>\n#include <string>\n\nextern \"C\" {\n#include <thread_db.h>\n}\n\nnamespace rr {\nclass ThreadGroup;\nclass ThreadDb;\n}\n\n// This is declared as incomplete by the libthread_db API and is\n// expected to be defined by the API user.  We define it to hold just\n// pointers back to the thread group and to the ThreadDb object.\nstruct ps_prochandle {\n  rr::ThreadGroup* thread_group;\n  rr::ThreadDb* db;\n  pid_t tgid;\n};\n\nnamespace rr {\n\n/**\n * This provides an interface to libthread_db.so to help with TLS\n * lookup. In principle there could be one instance per process, but we only\n * support one instance for the GdbServer's target process.\n *\n * The overall approach is that a libthread_db.so is loaded into rr\n * when this class is initialized (see |load_library|).  This provides\n * the GdbServer with a list of symbols whose addresses might be\n * needed in order to resolve TLS accesses.\n *\n * Then, when the address of a TLS variable is requested by the\n * debugger, GdbServer calls |get_tls_address|.  This uses the\n * libthread_db \"new\" function (\"td_ta_new\"); if this succeeds then\n * ThreadDb proceeds to use other APIs to find the desired address.\n *\n * ThreadDb works on a callback model, using symbols provided by the\n * hosting application.  These are all defined in ThreadDb.cc.\n */\nclass ThreadDb {\npublic:\n  explicit ThreadDb(pid_t tgid);\n  ~ThreadDb();\n\n  /**\n   * Return a set of the names of all the symbols that might be needed\n   * by libthread_db.  Also clears the current mapping of symbol names\n   * to addresses.\n   */\n  const std::set<std::string> get_symbols_and_clear_map(\n      ThreadGroup* thread_group);\n\n  /**\n   * Note that the symbol |name| has the given address.\n   */\n  void register_symbol(const std::string& name, remote_ptr<void> address);\n\n  /**\n   * Look up the symbol |name|.  If found, set |*address| and return\n   * true.  If not found, return false.\n   */\n  bool query_symbol(const char* name, remote_ptr<void>* address);\n\n  /**\n   * Look up a TLS address for thread |rec_tid|.  |offset| and\n   * |load_module| are as specified in the qGetTLSAddr packet.  If the\n   * address is found, set |*result| and return true.  Otherwise,\n   * return false.\n   */\n  bool get_tls_address(ThreadGroup* thread_group, pid_t rec_tid, size_t offset,\n                       remote_ptr<void> load_module, remote_ptr<void>* result);\n\nprivate:\n  bool load_library();\n  bool initialize();\n\n  ThreadDb(ThreadDb&) = delete;\n  ThreadDb operator=(ThreadDb&) = delete;\n\n  // True if libthread_db has been successfully initialized, if all\n  // the functions exist, and if the list of needed symbol names has\n  // been computed.\n  bool loaded;\n\n  // The external handle for this thread, for libthread_db.\n  struct ps_prochandle prochandle;\n  // The internal handle for this thread, from libthread_db.\n  td_thragent_t* internal_handle;\n  // Handle on the libthread_db library itself.\n  void* thread_db_library;\n\n  // Functions from libthread_db.\n  decltype(td_ta_delete)* td_ta_delete_fn;\n  decltype(td_thr_tls_get_addr)* td_thr_tls_get_addr_fn;\n  decltype(td_ta_map_lwp2thr)* td_ta_map_lwp2thr_fn;\n  decltype(td_ta_new)* td_ta_new_fn;\n\n  // Set of all symbol names.\n  std::set<std::string> symbol_names;\n\n  // Map from symbol names to addresses.\n  std::map<std::string, remote_ptr<void>> symbols;\n};\n\n} // namespace rr\n\n#endif // RR_THREADDB_H_\n"
  },
  {
    "path": "src/ThreadGroup.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ThreadGroup.h\"\n\n#include \"RecordTask.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n#include \"log.h\"\n\nnamespace rr {\n\nThreadGroup::ThreadGroup(Session* session, ThreadGroup* parent,\n                         pid_t tgid, pid_t tgid_own_namespace,\n                         uint32_t serial)\n    : tgid(tgid),\n      tgid_own_namespace(tgid_own_namespace),\n      dumpable(true),\n      execed(false),\n      received_sigframe_SIGSEGV(false),\n      session_(session),\n      parent_(parent),\n      first_run_event_(0),\n      serial(serial) {\n  LOG(debug) << \"creating new thread group \" << tgid;\n  if (parent) {\n    parent->children_.insert(this);\n  }\n  session->on_create(this);\n}\n\nThreadGroup::shr_ptr ThreadGroup::shared_from_this() {\n  return (*tasks.begin())->thread_group();\n}\n\nThreadGroup::~ThreadGroup() {\n  if (session_) {\n    session_->on_destroy(this);\n  }\n  if (parent_) {\n    parent_->children_.erase(this);\n  }\n  for (ThreadGroup* tg : children()) {\n    tg->parent_ = nullptr;\n    // We don't fix the parenting during replay. Currently\n    // nothing depends on parenting during replay.\n    if (session_ && session_->is_recording()) {\n      auto it = tg->task_set().begin();\n      if (it != tg->task_set().end()) {\n        const RecordTask* rt = static_cast<const RecordTask*>(*it);\n        pid_t ppid = rt->get_parent_pid();\n        tg->parent_ = session_->find_thread_group(ppid);\n        if (tg->parent_) {\n          tg->parent_->children_.insert(tg);\n        }\n      }\n    }\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/ThreadGroup.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TASKGROUP_H_\n#define RR_TASKGROUP_H_\n\n#include <sched.h>\n#include <stdint.h>\n\n#include <memory>\n#include <set>\n\n#include \"HasTaskSet.h\"\n#include \"TaskishUid.h\"\n#include \"WaitStatus.h\"\n#include \"TraceFrame.h\"\n\nnamespace rr {\n\nclass Session;\n\n/**\n * Tracks a group of tasks with an associated ID, set from the\n * original \"thread group leader\", the child of |fork()| which became\n * the ancestor of all other threads in the group.  Each constituent\n * task must own a reference to this. `ThreadGroup` represents the state\n * of the thread grouping during record. During replay, we put each task\n * into its own thread group.\n */\nclass ThreadGroup final : public HasTaskSet {\npublic:\n  ThreadGroup(Session* session, ThreadGroup* parent,\n              pid_t tgid, pid_t thid_own_namespace,\n              uint32_t serial);\n  ~ThreadGroup();\n\n  typedef std::shared_ptr<ThreadGroup> shr_ptr;\n\n  /* The id of this thread group (== pid of the thread group leader)\n   * (during record) */\n  const pid_t tgid;\n  const pid_t tgid_own_namespace;\n\n  WaitStatus exit_status;\n\n  Session* session() const { return session_; }\n  void forget_session() { session_ = nullptr; }\n\n  ThreadGroup* parent() { return parent_; }\n  const std::set<ThreadGroup*>& children() { return children_; }\n\n  ThreadGroupUid tguid() const { return ThreadGroupUid(tgid, serial); }\n\n  FrameTime first_run_event() { return first_run_event_; }\n  void set_first_run_event(FrameTime time) { first_run_event_ = time; }\n\n  shr_ptr shared_from_this();\n\n  // We don't allow tasks to make themselves undumpable. If they try,\n  // record that here and lie about it if necessary.\n  bool dumpable;\n\n  // Whether this thread group has execed\n  bool execed;\n\n  // True when a task in the task-group received a SIGSEGV because we\n  // couldn't push a signal handler frame. Only used during recording.\n  bool received_sigframe_SIGSEGV;\n\nprivate:\n  ThreadGroup(const ThreadGroup&) = delete;\n  ThreadGroup operator=(const ThreadGroup&) = delete;\n\n  Session* session_;\n  /** Parent ThreadGroup, or nullptr if it's not a tracee (rr or init). */\n  ThreadGroup* parent_;\n\n  std::set<ThreadGroup*> children_;\n\n  FrameTime first_run_event_;\n\n  uint32_t serial;\n};\n\n} // namespace rr\n\n#endif /* RR_TASKGROUP_H_ */\n"
  },
  {
    "path": "src/Ticks.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TICKS_H_\n#define RR_TICKS_H_\n\n#include <stdint.h>\n\nnamespace rr {\n\ntypedef int64_t Ticks;\n\n} // namespace rr\n\n#endif /* RR_TICKS_H_ */\n"
  },
  {
    "path": "src/TraceField.cc",
    "content": "#include <string>\n\n#include \"ReplayTask.h\"\n#include \"TraceField.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nnamespace {\n\nvoid print_hex(uint8_t* value, size_t size, FILE* out) {\n  bool any_printed = false;\n  for (ssize_t i = size - 1; i >= 0; --i) {\n    if (value[i] || any_printed || i == 0) {\n      fprintf(out, any_printed ? \"%02x\" : \"%x\", value[i]);\n      any_printed = true;\n    }\n  }\n}\n\nvoid print_value(const char* name, void* value, size_t size,\n                 bool hex, bool raw, FILE* out) {\n  if (raw) {\n    fwrite(value, size, 1, out);\n  } else if (hex) {\n    fprintf(out, \"%s:0x\", name);\n    print_hex(static_cast<uint8_t*>(value), size, out);\n  } else {\n    uint64_t v = 0;\n    DEBUG_ASSERT(size <= 8);\n    memcpy(&v, value, size);\n    fprintf(out, \"%s:%lld\", name, (long long)v);\n  }\n}\n\n#ifdef __x86_64__\nuint8_t user_regs_fields[16] = {\n  offsetof(user_regs_struct, rax), offsetof(user_regs_struct, rcx),\n  offsetof(user_regs_struct, rdx), offsetof(user_regs_struct, rbx),\n  offsetof(user_regs_struct, rsp), offsetof(user_regs_struct, rbp),\n  offsetof(user_regs_struct, rsi), offsetof(user_regs_struct, rdi),\n  offsetof(user_regs_struct, r8),  offsetof(user_regs_struct, r9),\n  offsetof(user_regs_struct, r10), offsetof(user_regs_struct, r11),\n  offsetof(user_regs_struct, r12), offsetof(user_regs_struct, r13),\n  offsetof(user_regs_struct, r14), offsetof(user_regs_struct, r15),\n};\n#elif __i386__\nuint8_t user_regs_fields[16] = {\n  offsetof(user_regs_struct, eax), offsetof(user_regs_struct, ecx),\n  offsetof(user_regs_struct, edx), offsetof(user_regs_struct, ebx),\n  offsetof(user_regs_struct, esp), offsetof(user_regs_struct, ebp),\n  offsetof(user_regs_struct, esi), offsetof(user_regs_struct, edi),\n};\n#elif defined(__aarch64__)\n#define user_regs_struct NativeArch::user_regs_struct\nuint16_t user_regs_fields[34] = {\n  offsetof(user_regs_struct, x[0]), offsetof(user_regs_struct, x[1]),\n  offsetof(user_regs_struct, x[2]), offsetof(user_regs_struct, x[3]),\n  offsetof(user_regs_struct, x[4]), offsetof(user_regs_struct, x[5]),\n  offsetof(user_regs_struct, x[6]), offsetof(user_regs_struct, x[7]),\n  offsetof(user_regs_struct, x[8]), offsetof(user_regs_struct, x[9]),\n  offsetof(user_regs_struct, x[10]), offsetof(user_regs_struct, x[11]),\n  offsetof(user_regs_struct, x[12]), offsetof(user_regs_struct, x[13]),\n  offsetof(user_regs_struct, x[14]), offsetof(user_regs_struct, x[15]),\n  offsetof(user_regs_struct, x[16]), offsetof(user_regs_struct, x[17]),\n  offsetof(user_regs_struct, x[18]), offsetof(user_regs_struct, x[19]),\n  offsetof(user_regs_struct, x[20]), offsetof(user_regs_struct, x[21]),\n  offsetof(user_regs_struct, x[22]), offsetof(user_regs_struct, x[23]),\n  offsetof(user_regs_struct, x[24]), offsetof(user_regs_struct, x[25]),\n  offsetof(user_regs_struct, x[26]), offsetof(user_regs_struct, x[27]),\n  offsetof(user_regs_struct, x[28]), offsetof(user_regs_struct, x[29]),\n  offsetof(user_regs_struct, x[30]),\n  offsetof(user_regs_struct, sp),\n  offsetof(user_regs_struct, pc),\n  offsetof(user_regs_struct, pstate)\n};\n#undef user_regs_struct\n#else\n#error Unsupported architecture\n#endif\n\nconst char gp_reg_names[16][4] = { \"rax\", \"rcx\", \"rdx\", \"rbx\",\n                                   \"rsp\", \"rbp\", \"rsi\", \"rdi\",\n                                   \"r8\",  \"r9\",  \"r10\", \"r11\",\n                                   \"r12\", \"r13\", \"r14\", \"r15\" };\nconst char gp_reg_names_32[8][4] = { \"eax\", \"ecx\", \"edx\", \"ebx\",\n                                     \"esp\", \"ebp\", \"esi\", \"edi\" };\n\nconst char seg_reg_names[6][3] = { \"es\", \"cs\", \"ss\", \"ds\", \"fs\", \"gs\" };\n\nuint64_t seg_reg(const Registers& regs, uint8_t index) {\n  switch (index) {\n    case 0:\n      return regs.es();\n    case 1:\n      return regs.cs();\n    case 2:\n      return regs.ss();\n    case 3:\n      return regs.ds();\n    case 4:\n      return regs.fs();\n    case 5:\n      return regs.gs();\n    default:\n      FATAL() << \"Unknown seg reg\";\n      return 0;\n  }\n}\n\nint find_gp_reg(const string& reg) {\n  for (int i = 0; i < 16; ++i) {\n    if (reg == gp_reg_names[i] || (i < 8 && reg == gp_reg_names_32[i])) {\n      return i;\n    }\n  }\n  return -1;\n}\n\nint find_seg_reg(const string& reg) {\n  for (int i = 0; i < 6; ++i) {\n    if (reg == seg_reg_names[i]) {\n      return i;\n    }\n  }\n  return -1;\n}\n\n} // anonymous namespace\n\nvoid print_trace_fields(ReplayTask* t, FrameTime event, uint64_t instruction_count,\n                        bool raw, const vector<TraceField>& fields, FILE* out) {\n  if (fields.empty()) {\n    return;\n  }\n  union {\n    NativeArch::user_regs_struct gp_regs;\n    uintptr_t regs_values[sizeof(NativeArch::user_regs_struct) / sizeof(uintptr_t)];\n  };\n  bool got_gp_regs = false;\n  bool first = true;\n\n  for (auto& field : fields) {\n    if (first) {\n      first = false;\n    } else if (!raw) {\n      fputc(' ', out);\n    }\n    switch (field.kind) {\n      case TRACE_EVENT_NUMBER: {\n        uint64_t value = event;\n        print_value(\"event\", &value, sizeof(value), false, raw, out);\n        break;\n      }\n      case TRACE_INSTRUCTION_COUNT:\n        print_value(\"icount\", &instruction_count, sizeof(instruction_count),\n                    false, raw, out);\n        break;\n      case TRACE_IP: {\n        uint64_t value = t->regs().ip().register_value();\n        print_value(t->arch() == x86 ? \"eip\" : \"rip\", &value, sizeof(value),\n                    true, raw, out);\n        break;\n      }\n      case TRACE_FSBASE: {\n        uint64_t value = t->regs().fs_base();\n        print_value(\"fsbase\", &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_GSBASE: {\n        uint64_t value = t->regs().gs_base();\n        print_value(\"gsbase\", &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_FLAGS: {\n        uint64_t value = t->regs().flags();\n        print_value(t->arch() == x86 ? \"eflags\" : \"rflags\", &value,\n                    sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_ORIG_AX: {\n        uint64_t value = t->regs().original_syscallno();\n        print_value(t->arch() == x86 ? \"orig_eax\" : \"orig_rax\", &value,\n                    sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_SEG_REG: {\n        uint64_t value = seg_reg(t->regs(), field.reg_num);\n        print_value(seg_reg_names[field.reg_num], &value, sizeof(value), true,\n                    raw, out);\n        break;\n      }\n      case TRACE_XINUSE: {\n        bool defined;\n        uint64_t value = t->extra_regs().read_xinuse(&defined);\n        print_value(\"xinuse\", &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_GP_REG: {\n        if (!got_gp_regs) {\n          gp_regs = t->regs().get_ptrace();\n          got_gp_regs = true;\n        }\n        uint64_t value = field.reg_num < array_length(user_regs_fields)\n                             ? regs_values[user_regs_fields[field.reg_num] / 8]\n                             : 0;\n        if (field.reg_num == 0 && t->arch() == x86) {\n          // EAX->RAX is sign-extended, so undo that.\n          value = (uint32_t)value;\n        }\n        const char* name = (t->arch() == x86 && field.reg_num < 8)\n                               ? gp_reg_names_32[field.reg_num]\n                               : gp_reg_names[field.reg_num];\n        print_value(name, &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_XMM_REG: {\n        uint8_t value[16];\n        bool defined;\n        switch (t->arch()) {\n          case x86:\n            if (field.reg_num < 8) {\n              t->extra_regs().read_register(\n                  value, GdbServerRegister(DREG_XMM0 + field.reg_num), &defined);\n            } else {\n              memset(value, 0, sizeof(value));\n            }\n            break;\n          case x86_64:\n            if (field.reg_num < 16) {\n              t->extra_regs().read_register(\n                  value, GdbServerRegister(DREG_64_XMM0 + field.reg_num), &defined);\n            } else {\n              memset(value, 0, sizeof(value));\n            }\n            break;\n          default:\n            FATAL() << \"Unexpected architecture\";\n        }\n        char buf[8];\n        sprintf(buf, \"xmm%d\", field.reg_num);\n        print_value(buf, value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_YMM_REG: {\n        uint8_t value[32];\n        bool defined;\n        switch (t->arch()) {\n          case x86:\n            if (field.reg_num < 8) {\n              t->extra_regs().read_register(\n                  value, GdbServerRegister(DREG_XMM0 + field.reg_num), &defined);\n              t->extra_regs().read_register(\n                  value + 16, GdbServerRegister(DREG_YMM0H + field.reg_num),\n                  &defined);\n            } else {\n              memset(value, 0, sizeof(value));\n            }\n            break;\n          case x86_64:\n            if (field.reg_num < 16) {\n              t->extra_regs().read_register(\n                  value, GdbServerRegister(DREG_64_XMM0 + field.reg_num), &defined);\n              t->extra_regs().read_register(\n                  value + 16, GdbServerRegister(DREG_64_YMM0H + field.reg_num),\n                  &defined);\n            } else {\n              memset(value, 0, sizeof(value));\n            }\n            break;\n          default:\n            FATAL() << \"Unexpected architecture\";\n        }\n        char buf[8];\n        sprintf(buf, \"ymm%d\", field.reg_num);\n        print_value(buf, value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_FIP: {\n        bool defined;\n        uint64_t value = t->extra_regs().read_fip(&defined);\n        print_value(\"fip\", &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_FOP: {\n        bool defined;\n        uint16_t value = t->extra_regs().read_fop(&defined);\n        print_value(\"fop\", &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_MXCSR: {\n        bool defined;\n        uint32_t value = t->extra_regs().read_mxcsr(&defined);\n        print_value(\"mxcsr\", &value, sizeof(value), true, raw, out);\n        break;\n      }\n      case TRACE_TID:\n        print_value(\"tid\", &t->rec_tid, sizeof(t->rec_tid), false, raw, out);\n        break;\n      case TRACE_TICKS: {\n        Ticks ticks = t->tick_count();\n        print_value(\"ticks\", &ticks, sizeof(ticks), false, raw, out);\n        break;\n      }\n    }\n  }\n\n  fputc('\\n', out);\n}\n\nbool parse_trace_fields(const string& value, vector<TraceField>* out) {\n  string s = value;\n  if (s.size() == 0) {\n    fprintf(stderr, \"Empty register list not allowed\\n\");\n    return false;\n  }\n  do {\n    size_t comma = s.find(',');\n    string reg;\n    if (comma == s.npos) {\n      reg = s;\n      s = \"\";\n    } else {\n      reg = s.substr(0, comma);\n      s = s.substr(comma + 1);\n    }\n    if (reg == \"event\") {\n      out->push_back({ TRACE_EVENT_NUMBER, 0 });\n    } else if (reg == \"icount\") {\n      out->push_back({ TRACE_INSTRUCTION_COUNT, 0 });\n    } else if (reg == \"ip\" || reg == \"rip\") {\n      out->push_back({ TRACE_IP, 0 });\n    } else if (reg == \"fsbase\") {\n      out->push_back({ TRACE_FSBASE, 0 });\n    } else if (reg == \"gsbase\") {\n      out->push_back({ TRACE_GSBASE, 0 });\n    } else if (reg == \"flags\" || reg == \"rflags\") {\n      out->push_back({ TRACE_FLAGS, 0 });\n    } else if (reg == \"orig_rax\" || reg == \"orig_eax\") {\n      out->push_back({ TRACE_ORIG_AX, 0 });\n    } else if (reg == \"gp_x16\") {\n      for (uint8_t i = 0; i < 16; ++i) {\n        out->push_back({ TRACE_GP_REG, i });\n      }\n    } else if (reg == \"xmm_x16\") {\n      for (uint8_t i = 0; i < 16; ++i) {\n        out->push_back({ TRACE_XMM_REG, i });\n      }\n    } else if (reg == \"ymm_x16\") {\n      for (uint8_t i = 0; i < 16; ++i) {\n        out->push_back({ TRACE_YMM_REG, i });\n      }\n    } else if (find_gp_reg(reg) >= 0) {\n      out->push_back({ TRACE_GP_REG, (uint8_t)find_gp_reg(reg) });\n    } else if (find_seg_reg(reg) >= 0) {\n      out->push_back({ TRACE_SEG_REG, (uint8_t)find_seg_reg(reg) });\n    } else if (reg == \"xinuse\") {\n      out->push_back({ TRACE_XINUSE, 0 });\n    } else if (reg == \"fip\") {\n      out->push_back({ TRACE_FIP, 0 });\n    } else if (reg == \"fop\") {\n      out->push_back({ TRACE_FOP, 0 });\n    } else if (reg == \"mxcsr\") {\n      out->push_back({ TRACE_MXCSR, 0});\n    } else if (reg == \"tid\") {\n      out->push_back({ TRACE_TID, 0 });\n    } else if (reg == \"ticks\") {\n      out->push_back({ TRACE_TICKS, 0 });\n    } else {\n      fprintf(stderr, \"Unknown register '%s'\\n\", reg.c_str());\n      return false;\n    }\n  } while (s.size() > 0);\n  return true;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/TraceField.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TRACE_FIELD_H_\n#define RR_TRACE_FIELD_H_\n\n#include <string>\n#include <vector>\n\n#include \"core.h\"\n\nnamespace rr {\n\nenum TraceFieldKind {\n  TRACE_EVENT_NUMBER,      // outputs 64-bit value\n  TRACE_INSTRUCTION_COUNT, // outputs 64-bit value\n  TRACE_IP,                // outputs 64-bit value\n  TRACE_FSBASE,            // outputs 64-bit value\n  TRACE_GSBASE,            // outputs 64-bit value\n  TRACE_FLAGS,             // outputs 64-bit value\n  TRACE_ORIG_AX,           // outputs 64-bit value\n  TRACE_SEG_REG,           // outputs 64-bit value\n  TRACE_XINUSE,            // outputs 64-bit value\n  TRACE_GP_REG,            // outputs 64-bit value\n  TRACE_XMM_REG,           // outputs 128-bit value\n  TRACE_YMM_REG,           // outputs 256-bit value\n  TRACE_FIP,               // outputs 64-bit value\n  TRACE_FOP,               // outputs 16-bit value\n  TRACE_TID,               // outputs 32-bit value\n  TRACE_MXCSR,             // outputs 32-bit value\n  TRACE_TICKS,             // outputs 64-bit value\n};\nstruct TraceField {\n  TraceFieldKind kind;\n  uint8_t reg_num;\n};\n\nvoid print_trace_fields(ReplayTask* t, FrameTime event, uint64_t instruction_count,\n                        bool raw, const std::vector<TraceField>& fields, FILE* out);\n\nbool parse_trace_fields(const std::string& value, std::vector<TraceField>* out);\n\n} // namespace rr\n\n#endif /* RR_TRACE_FIELD_H_ */\n"
  },
  {
    "path": "src/TraceFrame.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"TraceFrame.h\"\n\n#include <inttypes.h>\n\n#include \"core.h\"\n#include \"util.h\"\n\nnamespace rr {\n\nTraceFrame::TraceFrame(FrameTime global_time, pid_t tid, const Event& event,\n                       Ticks tick_count, double monotonic_time)\n    : global_time(global_time),\n      tid_(tid),\n      ev(event),\n      ticks_(tick_count),\n      monotonic_time_(monotonic_time ? monotonic_time : monotonic_now_sec()) {}\n\nvoid TraceFrame::dump(FILE* out) const {\n  out = out ? out : stdout;\n\n  fprintf(out, \"{\\n  real_time:%f global_time:%llu, event:`%s' \",\n          monotonic_time(), (long long)time(), event().str().c_str());\n  if (event().is_syscall_event()) {\n    fprintf(out, \"(state:%s) \", state_name(event().Syscall().state));\n  }\n  fprintf(out, \"tid:%d, ticks:%\" PRId64 \"\\n\", tid(), ticks());\n  if (!event().record_regs()) {\n    return;\n  }\n\n  regs().print_register_file_compact(out);\n  if (recorded_extra_regs.format() != ExtraRegisters::NONE) {\n    fputc(' ', out);\n    recorded_extra_regs.print_register_file_compact(out);\n  }\n  fprintf(out, \"\\n\");\n}\n\nvoid TraceFrame::dump_raw(FILE* out) const {\n  out = out ? out : stdout;\n\n  fprintf(out, \" %lld %d %d %\" PRId64, (long long)time(), tid(), event().type(),\n          ticks());\n  if (!event().record_regs()) {\n    fprintf(out, \"\\n\");\n    return;\n  }\n\n  regs().print_register_file_for_trace_raw(out);\n  fprintf(out, \"\\n\");\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/TraceFrame.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TRACE_FRAME_H_\n#define RR_TRACE_FRAME_H_\n\n#include <stdint.h>\n#include <stdio.h>\n#include <unistd.h>\n\n#include \"Event.h\"\n#include \"ExtraRegisters.h\"\n#include \"PerfCounters.h\"\n#include \"Registers.h\"\n#include \"Ticks.h\"\n\nnamespace rr {\n\nclass TraceReader;\nclass TraceWriter;\n\ntypedef int64_t FrameTime;\n\n/**\n * A trace_frame is one \"trace event\" from a complete trace.  During\n * recording, a trace_frame is recorded upon each significant event,\n * for example a context-switch or syscall.  During replay, a\n * trace_frame represents a \"next state\" that needs to be transitioned\n * into, and the information recorded in the frame dictates the nature\n * of the transition.\n */\nclass TraceFrame {\npublic:\n  TraceFrame(FrameTime global_time, pid_t tid, const Event& event,\n             Ticks tick_count, double monotonic_time = 0);\n  TraceFrame() : global_time(0), tid_(0), ticks_(0), monotonic_time_(0) {}\n\n  FrameTime time() const { return global_time; }\n  pid_t tid() const { return tid_; }\n  const Event& event() const { return ev; }\n  Ticks ticks() const { return ticks_; }\n  double monotonic_time() const { return monotonic_time_; }\n\n  const Registers& regs() const { return recorded_regs; }\n  const ExtraRegisters& extra_regs() const { return recorded_extra_regs; }\n\n  /**\n   * Log a human-readable representation of this to |out|\n   * (defaulting to stdout), including a newline character.\n   * A human-friendly format is used. Does not emit a trailing '}'\n   * (so the caller can add more fields to the record).\n   */\n  void dump(FILE* out = nullptr) const;\n  /**\n   * Log a human-readable representation of this to |out|\n   * (defaulting to stdout), including a newline character.  An\n   * easily machine-parseable format is dumped.\n   */\n  void dump_raw(FILE* out = nullptr) const;\n\nprivate:\n  friend class TraceReader;\n  friend class TraceWriter;\n\n  FrameTime global_time;\n  pid_t tid_;\n  Event ev;\n  Ticks ticks_;\n  double monotonic_time_;\n\n  Registers recorded_regs;\n\n  // Only used when has_exec_info, but variable length (and usually not\n  // present) so we don't want to stuff it into exec_info\n  ExtraRegisters recorded_extra_regs;\n};\n\n} // namespace rr\n\n#endif /* RR_TRACE_FRAME_H_ */\n"
  },
  {
    "path": "src/TraceInfoCommand.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"DumpCommand.h\"\n\n#include <inttypes.h>\n\n#include <limits>\n#include <unordered_map>\n\n#include \"preload/preload_interface.h\"\n\n#include \"AddressSpace.h\"\n#include \"Command.h\"\n#include \"Flags.h\"\n#include \"RecordSession.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"TraceStream.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"main.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass TraceInfoCommand : public Command {\npublic:\n  virtual int run(vector<string>& args) override;\n\nprotected:\n  TraceInfoCommand(const char* name, const char* help) : Command(name, help) {}\n\n  static TraceInfoCommand singleton;\n};\n\nTraceInfoCommand TraceInfoCommand::singleton(\n    \"traceinfo\",\n    \" rr traceinfo [<trace_dir>]\\n\"\n    \"  Dump trace header in JSON format.\\n\");\n\nstatic int dump_trace_info(const string& trace_dir, FILE* out) {\n  int ret = 0;\n  TraceReader trace(trace_dir);\n\n  fputs(\"{\\n\", out);\n\n  const uint8_t* bytes = trace.uuid().bytes;\n  fputs(\"  \\\"uuid\\\":[\", out);\n  for (size_t i = 0; i < sizeof(trace.uuid().bytes); ++i) {\n    if (i > 0) {\n      fputc(',', out);\n    }\n    fprintf(out, \"%d\", bytes[i]);\n  }\n  fputs(\"],\\n\", out);\n\n  fprintf(out, \"  \\\"xcr0\\\":%llu,\\n\", (unsigned long long)trace.xcr0());\n\n  fprintf(out, \"  \\\"bindToCpu\\\":%d,\\n\", trace.bound_to_cpu());\n\n  fprintf(out, \"  \\\"cpuidFaulting\\\":%s,\\n\", trace.uses_cpuid_faulting() ? \"true\" : \"false\");\n\n  fprintf(out, \"  \\\"requiredForwardCompatibilityVersion\\\":%d,\\n\", trace.required_forward_compatibility_version());\n\n  const char* semantics;\n  switch (trace.ticks_semantics()) {\n    case TICKS_RETIRED_CONDITIONAL_BRANCHES: semantics = \"rcb\"; break;\n    case TICKS_TAKEN_BRANCHES: semantics = \"branches\"; break;\n    default: semantics = \"?\"; break;\n  }\n  fprintf(out, \"  \\\"ticksSemantics\\\":\\\"%s\\\",\\n\", semantics);\n\n  fputs(\"  \\\"cpuidRecords\\\":[\", out);\n  auto& records = trace.cpuid_records();\n  for (size_t i = 0; i < records.size(); ++i) {\n    if (i > 0) {\n      fputc(',', out);\n    }\n    auto& r = records[i];\n    fprintf(out, \"\\n    [%u,%u,%u,%u,%u,%u]\", r.eax_in, r.ecx_in,\n           r.out.eax, r.out.ebx, r.out.ecx, r.out.edx);\n  }\n  fputs(\"\\n  ],\\n\", out);\n\n  bool chaos_mode_known;\n  bool chaos_mode = trace.chaos_mode(&chaos_mode_known);\n  if (chaos_mode_known) {\n    fprintf(out, \"  \\\"chaosMode\\\":%s,\\n\", chaos_mode ? \"true\" : \"false\");\n    if (chaos_mode) {\n      MemoryRange exclusion_range = trace.exclusion_range();\n      fprintf(out, \"  \\\"exclusionRange\\\": { \\\"start\\\": %llu, \\\"end\\\": %llu },\\n\",\n             (unsigned long long)exclusion_range.start().as_int(),\n             (unsigned long long)exclusion_range.end().as_int());\n    }\n  }\n\n  uint8_t max_virtual_address_size = trace.max_virtual_address_size();\n  if (max_virtual_address_size > 0) {\n    fprintf(out, \"  \\\"maxVirtualAddressSize\\\":%d,\\n\", max_virtual_address_size);\n  }\n\n  bool cpu_improperly_configured_known;\n  bool cpu_improperly_configured = trace.cpu_improperly_configured(&cpu_improperly_configured_known);\n  if (cpu_improperly_configured_known) {\n    fprintf(out, \"  \\\"cpuImproperlyConfigured\\\":%s,\\n\", cpu_improperly_configured ? \"true\" : \"false\");\n  }\n\n  if (!trace.uname().sysname.empty()) {\n    const auto& uname = trace.uname();\n    fputs(\"  \\\"uname\\\":{\", out);\n    fprintf(out, \"\\n    \\\"sysname\\\":\\\"%s\\\",\", json_escape(uname.sysname).c_str());\n    fprintf(out, \"\\n    \\\"nodename\\\":\\\"%s\\\",\", json_escape(uname.nodename).c_str());\n    fprintf(out, \"\\n    \\\"release\\\":\\\"%s\\\",\", json_escape(uname.release).c_str());\n    fprintf(out, \"\\n    \\\"version\\\":\\\"%s\\\",\", json_escape(uname.version).c_str());\n    fprintf(out, \"\\n    \\\"machine\\\":\\\"%s\\\",\", json_escape(uname.machine).c_str());\n    fprintf(out, \"\\n    \\\"domainname\\\":\\\"%s\\\"\", json_escape(uname.domainname).c_str());\n    fputs(\"\\n  },\\n\", out);\n  }\n\n  ReplaySession::Flags flags;\n  flags.redirect_stdio = false;\n  flags.share_private_mappings = false;\n  flags.replay_stops_at_first_execve = true;\n  flags.cpu_unbound = true;\n  ReplaySession::shr_ptr replay_session = ReplaySession::create(trace_dir, flags);\n\n  while (true) {\n    auto result = replay_session->replay_step(RUN_CONTINUE);\n    if (replay_session->done_initial_exec()) {\n      fputs(\"  \\\"environ\\\":[\", out);\n      auto environ = read_env(replay_session->current_task());\n      for (size_t i = 0; i < environ.size(); ++i) {\n        if (i > 0) {\n          fputc(',', out);\n        }\n        fprintf(out, \"\\n    \\\"%s\\\"\", json_escape(environ[i]).c_str());\n      }\n      fputs(\"\\n  ],\\n\", out);\n\n      fprintf(out, \"  \\\"program\\\": \\\"%s\\\"\\n\", json_escape(replay_session->vms()[0]->exe_image()).c_str());\n\n      break;\n    }\n    if (result.status == REPLAY_EXITED) {\n      fputs(\"Replay finished before initial exec!\\n\", stderr);\n      ret = 1;\n      break;\n    }\n  }\n\n  fputs(\"}\\n\", out);\n  return ret;\n}\n\nint TraceInfoCommand::run(vector<string>& args) {\n  // Various \"cannot replay safely...\" warnings cannot affect us since\n  // we only replay to the first execve.\n  Flags::get_for_init().suppress_environment_warnings = true;\n\n  while (parse_global_option(args)) {\n  }\n\n  string trace_dir;\n  if (!parse_optional_trace_dir(args, &trace_dir)) {\n    print_help(stderr);\n    return 1;\n  }\n\n  return dump_trace_info(trace_dir, stdout);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/TraceStream.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef _GNU_SOURCE\n// For utsname::domainname\n#define _GNU_SOURCE 1\n#endif\n\n#include \"TraceStream.h\"\n\n#include <capnp/message.h>\n#include <capnp/serialize-packed.h>\n#include <inttypes.h>\n#include <limits.h>\n#include <sched.h>\n#include <sys/file.h>\n#include <sys/utsname.h>\n#include <sys/wait.h>\n#include <sysexits.h>\n#include <dirent.h>\n\n#include <algorithm>\n#include <fstream>\n#include <sstream>\n#include <string>\n\n#include \"AddressSpace.h\"\n#include \"AutoRemoteSyscalls.h\"\n#include \"Event.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"TaskishUid.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"preload/preload_interface.h\"\n#include \"rr_trace.capnp.h\"\n#include \"util.h\"\n\n#include \"rr/rr.h\"\n\nusing namespace std;\nusing namespace capnp;\n\nnamespace rr {\n\n//\n// This represents the format and layout of recorded traces.  This\n// version number doesn't track the rr version number, because changes\n// to the trace format will be rare.\n//\n// We don't plan to ever change this again. Instead, we use CapnpProto\n// to define the trace format in an extensible way (see rr_trace.capnp).\n//\n#define TRACE_VERSION 85\n\nstruct SubstreamData {\n  const char* name;\n  size_t block_size;\n  int threads;\n};\n\nstatic SubstreamData substreams[TraceStream::SUBSTREAM_COUNT] = {\n  { \"events\", 1024 * 1024, 1 },\n  { \"data\", 1024 * 1024, 0 },\n  { \"mmaps\", 64 * 1024, 1 },\n  { \"tasks\", 64 * 1024, 1 },\n};\n\nstatic const SubstreamData& substream(TraceStream::Substream s) {\n  if (!substreams[TraceStream::RAW_DATA].threads) {\n    int cpus = sysconf(_SC_NPROCESSORS_ONLN);\n    if (cpus < 1) {\n      FATAL() << \"sysconf failed\";\n    }\n    substreams[TraceStream::RAW_DATA].threads = min(8, cpus);\n  }\n  return substreams[s];\n}\n\nstatic TraceStream::Substream operator++(TraceStream::Substream& s) {\n  s = (TraceStream::Substream)(s + 1);\n  return s;\n}\n\nstatic bool dir_exists(const string& dir) {\n  struct stat dummy;\n  return !dir.empty() && stat(dir.c_str(), &dummy) == 0;\n}\n\nstatic string default_rr_trace_dir() {\n  static string cached_dir;\n\n  if (!cached_dir.empty()) {\n    return cached_dir;\n  }\n\n  string dot_dir;\n  const char* home = getenv(\"HOME\");\n  if (home) {\n    dot_dir = string(home) + \"/.rr\";\n  }\n  string xdg_dir;\n  const char* xdg_data_home = getenv(\"XDG_DATA_HOME\");\n  if (xdg_data_home) {\n    xdg_dir = string(xdg_data_home) + \"/rr\";\n  } else if (home) {\n    xdg_dir = string(home) + \"/.local/share/rr\";\n  }\n\n  // If XDG dir does not exist but ~/.rr does, prefer ~/.rr for backwards\n  // compatibility.\n  if (dir_exists(xdg_dir)) {\n    cached_dir = xdg_dir;\n  } else if (dir_exists(dot_dir)) {\n    cached_dir = dot_dir;\n  } else if (!xdg_dir.empty()) {\n    cached_dir = xdg_dir;\n  } else {\n    cached_dir = \"/tmp/rr\";\n  }\n\n  return cached_dir;\n}\n\nstring trace_save_dir() {\n  const char* output_dir = getenv(\"_RR_TRACE_DIR\");\n  return output_dir ? output_dir : default_rr_trace_dir();\n}\n\nstring latest_trace_symlink() {\n  return trace_save_dir() + \"/latest-trace\";\n}\n\nstring resolve_trace_name(const string& trace_name)\n{\n  if (trace_name.empty()) {\n    return latest_trace_symlink();\n  }\n\n  // Single-component paths are looked up first in the current directory, next\n  // in the default trace dir.\n\n  if (trace_name.find('/') == string::npos) {\n    if (dir_exists(trace_name)) {\n      return trace_name;\n    }\n\n    string resolved_trace_name = trace_save_dir() + \"/\" + trace_name;\n    if (dir_exists(resolved_trace_name)) {\n      return resolved_trace_name;\n    }\n  }\n\n  return trace_name;\n}\n\nclass CompressedWriterOutputStream : public kj::OutputStream {\npublic:\n  CompressedWriterOutputStream(CompressedWriter& writer) : writer(writer) {}\n  virtual ~CompressedWriterOutputStream() {}\n\n  virtual void write(const void* buffer, size_t size) {\n    writer.write(buffer, size);\n  }\n\nprivate:\n  CompressedWriter& writer;\n};\n\nstruct IOException {};\n\nclass CompressedReaderInputStream : public kj::BufferedInputStream {\npublic:\n  CompressedReaderInputStream(CompressedReader& reader) : reader(reader) {}\n  virtual ~CompressedReaderInputStream() {}\n\n  virtual size_t tryRead(void* buffer, size_t, size_t maxBytes) {\n    if (!reader.read(buffer, maxBytes)) {\n      throw IOException();\n    }\n    return maxBytes;\n  }\n  virtual void skip(size_t bytes) {\n    reader.skip(bytes);\n  }\n  virtual kj::ArrayPtr<const capnp::byte> tryGetReadBuffer() {\n    const uint8_t* p;\n    size_t size;\n    if (!reader.get_buffer(&p, &size)) {\n      throw IOException();\n    }\n    return kj::ArrayPtr<const capnp::byte>(p, size);\n  }\n\nprivate:\n  CompressedReader& reader;\n};\n\nTraceStream::TraceStream(const string& trace_dir, FrameTime initial_time)\n    : trace_dir(real_path(trace_dir)),\n      bind_to_cpu(-1),\n      global_time(initial_time)\n   {}\n\nstring TraceStream::file_data_clone_file_name(const TaskUid& tuid) {\n  stringstream ss;\n  ss << trace_dir << \"/cloned_data_\" << tuid.tid() << \"_\" << tuid.serial();\n  return ss.str();\n}\n\nstring TraceStream::path(Substream s) {\n  return trace_dir + \"/\" + substream(s).name;\n}\n\nsize_t TraceStream::mmaps_block_size() { return substreams[MMAPS].block_size; }\n\nbool TraceWriter::good() const {\n  for (auto& w : writers) {\n    if (!w->good()) {\n      return false;\n    }\n  }\n  return true;\n}\n\nbool TraceReader::good() const {\n  for (auto& r : readers) {\n    if (!r->good()) {\n      return false;\n    }\n  }\n  return true;\n}\n\nstatic kj::ArrayPtr<const capnp::byte> str_to_data(const string& str) {\n  return kj::ArrayPtr<const capnp::byte>(\n      reinterpret_cast<const capnp::byte*>(str.data()), str.size());\n}\n\nstatic string data_to_str(const kj::ArrayPtr<const capnp::byte>& data) {\n  if (!data.begin()) {\n    return string();\n  }\n  if (memchr(data.begin(), 0, data.size())) {\n    FATAL() << \"Invalid string: contains null character\";\n  }\n  return string(reinterpret_cast<const char*>(data.begin()), data.size());\n}\n\nstatic trace::Arch to_trace_arch(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      return trace::Arch::X86;\n    case x86_64:\n      return trace::Arch::X8664;\n    case aarch64:\n      return trace::Arch::AARCH64;\n    default:\n      FATAL() << \"Unknown arch\";\n      return trace::Arch::X86;\n  }\n}\n\nstatic trace::CpuTriState to_tristate(bool value) {\n  return value ? trace::CpuTriState::KNOWN_TRUE : trace::CpuTriState::KNOWN_FALSE;\n}\n\nstatic SupportedArch from_trace_arch(trace::Arch arch) {\n  switch (arch) {\n    case trace::Arch::X86:\n      return x86;\n    case trace::Arch::X8664:\n      return x86_64;\n    case trace::Arch::AARCH64:\n      return aarch64;\n    default:\n      FATAL() << \"Unknown arch\";\n      return x86;\n  }\n}\n\nstatic trace::SignalDisposition to_trace_disposition(\n    SignalResolvedDisposition disposition) {\n  switch (disposition) {\n    case DISPOSITION_FATAL:\n      return trace::SignalDisposition::FATAL;\n    case DISPOSITION_IGNORED:\n      return trace::SignalDisposition::IGNORED;\n    case DISPOSITION_USER_HANDLER:\n      return trace::SignalDisposition::USER_HANDLER;\n    default:\n      FATAL() << \"Unknown disposition\";\n      return trace::SignalDisposition::FATAL;\n  }\n}\n\nstatic SignalResolvedDisposition from_trace_disposition(\n    trace::SignalDisposition disposition) {\n  switch (disposition) {\n    case trace::SignalDisposition::FATAL:\n      return DISPOSITION_FATAL;\n    case trace::SignalDisposition::IGNORED:\n      return DISPOSITION_IGNORED;\n    case trace::SignalDisposition::USER_HANDLER:\n      return DISPOSITION_USER_HANDLER;\n    default:\n      FATAL() << \"Unknown disposition\";\n      return DISPOSITION_FATAL;\n  }\n}\n\nstatic trace::SyscallState to_trace_syscall_state(SyscallState state) {\n  switch (state) {\n    case ENTERING_SYSCALL_PTRACE:\n      return trace::SyscallState::ENTERING_PTRACE;\n    case ENTERING_SYSCALL:\n      return trace::SyscallState::ENTERING;\n    case EXITING_SYSCALL:\n      return trace::SyscallState::EXITING;\n    default:\n      FATAL() << \"Unknown syscall state\";\n      return trace::SyscallState::ENTERING;\n  }\n}\n\nstatic SyscallState from_trace_syscall_state(trace::SyscallState state) {\n  switch (state) {\n    case trace::SyscallState::ENTERING_PTRACE:\n      return ENTERING_SYSCALL_PTRACE;\n    case trace::SyscallState::ENTERING:\n      return ENTERING_SYSCALL;\n    case trace::SyscallState::EXITING:\n      return EXITING_SYSCALL;\n    default:\n      FATAL() << \"Unknown syscall state\";\n      return ENTERING_SYSCALL;\n  }\n}\n\nstatic void to_trace_signal(trace::Signal::Builder signal, const Event& ev) {\n  const SignalEvent& sig_ev = ev.Signal();\n  signal.setSiginfoArch(to_trace_arch(NativeArch::arch()));\n  signal.setSiginfo(\n      Data::Reader(reinterpret_cast<const uint8_t*>(&sig_ev.siginfo),\n                   sizeof(sig_ev.siginfo)));\n  signal.setDeterministic(sig_ev.deterministic == DETERMINISTIC_SIG);\n  signal.setDisposition(to_trace_disposition(sig_ev.disposition));\n}\n\nstatic Event from_trace_signal(EventType type, trace::Signal::Reader signal) {\n  union {\n    NativeArch::siginfo_t native_siginfo;\n    siginfo_t system_siginfo;\n  } si;\n  auto siginfo = signal.getSiginfo();\n  si.native_siginfo = convert_to_native_siginfo(from_trace_arch(signal.getSiginfoArch()),\n      siginfo.begin(), siginfo.size());\n  return Event(type,\n               SignalEvent(si.system_siginfo,\n                           signal.getDeterministic() ? DETERMINISTIC_SIG\n                                                     : NONDETERMINISTIC_SIG,\n                           from_trace_disposition(signal.getDisposition())));\n}\n\nstatic trace::TicksSemantics to_trace_ticks_semantics(TicksSemantics semantics) {\n  switch (semantics) {\n    case TICKS_RETIRED_CONDITIONAL_BRANCHES:\n      return trace::TicksSemantics::RETIRED_CONDITIONAL_BRANCHES;\n    case TICKS_TAKEN_BRANCHES:\n      return trace::TicksSemantics::TAKEN_BRANCHES;\n    default:\n      FATAL() << \"Unknown ticks semantics\";\n      return trace::TicksSemantics::RETIRED_CONDITIONAL_BRANCHES;\n  }\n}\n\nstatic TicksSemantics from_trace_ticks_semantics(trace::TicksSemantics semantics) {\n  switch (semantics) {\n    case trace::TicksSemantics::RETIRED_CONDITIONAL_BRANCHES:\n      return TICKS_RETIRED_CONDITIONAL_BRANCHES;\n    case trace::TicksSemantics::TAKEN_BRANCHES:\n      return TICKS_TAKEN_BRANCHES;\n    default:\n      FATAL() << \"Unknown ticks semantics\";\n      return TICKS_RETIRED_CONDITIONAL_BRANCHES;\n  }\n}\n\nstatic pid_t i32_to_tid(int tid) {\n  if (tid <= 0) {\n    FATAL() << \"Invalid tid\";\n  }\n  return tid;\n}\n\nstatic int check_fd(int fd) {\n  if (fd < 0) {\n    FATAL() << \"Invalid fd\";\n  }\n  return fd;\n}\n\n// 8-byte words\nstatic const size_t reasonable_frame_message_words = 64;\n\nvoid TraceWriter::write_frame(RecordTask* t, const Event& ev,\n                              const Registers* registers,\n                              const ExtraRegisters* extra_registers) {\n  // Use an on-stack first segment that should be adequate for most cases. A\n  // simple syscall event takes 320 bytes currently. The default Capnproto\n  // implementation does a calloc(8192) for the first segment.\n  word buf[reasonable_frame_message_words] = {};\n  MallocMessageBuilder frame_msg(buf);\n  trace::Frame::Builder frame = frame_msg.initRoot<trace::Frame>();\n\n  frame.setTid(t->tid);\n  frame.setTicks(t->tick_count());\n  frame.setMonotonicSec(monotonic_now_sec());\n  frame.setInSyscallbufSyscallHook(0);\n  auto mem_writes = frame.initMemWrites(raw_recs.size());\n  for (size_t i = 0; i < raw_recs.size(); ++i) {\n    auto w = mem_writes[i];\n    auto& r = raw_recs[i];\n    w.setTid(r.rec_tid);\n    w.setAddr(r.addr.as_int());\n    w.setSize(r.size);\n    w.setSizeIsConservative(r.size_validation == MemWriteSizeValidation::CONSERVATIVE);\n    auto holes = w.initHoles(r.holes.size());\n    for (size_t j = 0; j < r.holes.size(); ++j) {\n      holes[j].setOffset(r.holes[j].offset);\n      holes[j].setSize(r.holes[j].size);\n    }\n  }\n  raw_recs.clear();\n  frame.setArch(to_trace_arch(t->arch()));\n  if (registers) {\n    // Avoid dynamic allocation and copy\n    auto raw_regs = registers->get_regs_for_trace();\n    frame.initRegisters().setRaw(Data::Reader(raw_regs.data, raw_regs.size));\n  }\n  if (extra_registers) {\n    frame.initExtraRegisters().setRaw(Data::Reader(\n        extra_registers->data_bytes(), extra_registers->data_size()));\n  }\n\n  auto event = frame.initEvent();\n  switch (ev.type()) {\n    case EV_INSTRUCTION_TRAP:\n      event.setInstructionTrap(Void());\n      break;\n    case EV_PATCH_SYSCALL:\n      if (ev.PatchSyscall().patch_trapping_instruction) {\n        event.setPatchTrappingInstruction(Void());\n      } else if (ev.PatchSyscall().patch_vsyscall) {\n        event.setPatchVsyscall(Void());\n      } else if (ev.PatchSyscall().patch_after_syscall) {\n        event.setPatchAfterSyscall(Void());\n      } else {\n        event.setPatchSyscall(Void());\n      }\n      break;\n    case EV_SYSCALLBUF_ABORT_COMMIT:\n      event.setSyscallbufAbortCommit(Void());\n      break;\n    case EV_SYSCALLBUF_RESET:\n      event.setSyscallbufReset(Void());\n      break;\n    case EV_SCHED:\n      frame.setInSyscallbufSyscallHook(ev.Sched().in_syscallbuf_syscall_hook.register_value());\n      event.setSched(Void());\n      break;\n    case EV_GROW_MAP:\n      event.setGrowMap(Void());\n      break;\n    case EV_SIGNAL:\n      to_trace_signal(event.initSignal(), ev);\n      break;\n    case EV_SIGNAL_DELIVERY:\n      to_trace_signal(event.initSignalDelivery(), ev);\n      break;\n    case EV_SIGNAL_HANDLER:\n      to_trace_signal(event.initSignalHandler(), ev);\n      break;\n    case EV_EXIT:\n      event.setExit(Void());\n      break;\n    case EV_SYSCALLBUF_FLUSH: {\n      const SyscallbufFlushEvent& e = ev.SyscallbufFlush();\n      event.initSyscallbufFlush().setMprotectRecords(Data::Reader(\n          reinterpret_cast<const uint8_t*>(e.mprotect_records.data()),\n          e.mprotect_records.size() * sizeof(mprotect_record)));\n      break;\n    }\n    case EV_SYSCALL: {\n      const SyscallEvent& e = ev.Syscall();\n      auto syscall = event.initSyscall();\n      syscall.setArch(to_trace_arch(e.arch()));\n      syscall.setNumber(e.is_restart\n                            ? syscall_number_for_restart_syscall(t->arch())\n                            : e.number);\n      syscall.setState(to_trace_syscall_state(e.state));\n      syscall.setFailedDuringPreparation(e.failed_during_preparation);\n      auto data = syscall.initExtra();\n      if (e.write_offset >= 0) {\n        data.setWriteOffset(e.write_offset);\n      }\n      if (!e.exec_fds_to_close.empty()) {\n        data.setExecFdsToClose(kj::ArrayPtr<const int>(\n            e.exec_fds_to_close.data(), e.exec_fds_to_close.size()));\n      }\n      if (!e.opened.empty()) {\n        auto open = data.initOpenedFds(e.opened.size());\n        for (size_t i = 0; i < e.opened.size(); ++i) {\n          auto o = open[i];\n          auto opened = e.opened[i];\n          o.setFd(opened.fd);\n          o.setPath(str_to_data(opened.path));\n          o.setDevice(opened.device);\n          o.setInode(opened.inode);\n        }\n      }\n      if (e.socket_addrs) {\n        auto addrs = data.initSocketAddrs();\n        auto localAddr = (*e.socket_addrs.get())[0];\n        auto remoteAddr = (*e.socket_addrs.get())[1];\n        addrs.setLocalAddr(Data::Reader(reinterpret_cast<uint8_t*>(&localAddr), sizeof(localAddr)));\n        addrs.setRemoteAddr(Data::Reader(reinterpret_cast<uint8_t*>(&remoteAddr), sizeof(remoteAddr)));\n      }\n      if (!e.madvise_ranges.empty()) {\n        auto ranges = data.initMadviseRanges(e.madvise_ranges.size());\n        for (size_t i = 0; i < e.madvise_ranges.size(); ++i) {\n          auto r = ranges[i];\n          auto mr = e.madvise_ranges[i];\n          r.setStart(mr.start().as_int());\n          r.setEnd(mr.end().as_int());\n        }\n      }\n      break;\n    }\n    default:\n      FATAL() << \"Event type not recordable\";\n      break;\n  }\n\n  try {\n    auto& events = writer(EVENTS);\n    CompressedWriterOutputStream stream(events);\n    writePackedMessage(stream, frame_msg);\n  } catch (...) {\n    FATAL() << \"Unable to write events\";\n  }\n\n  tick_time();\n}\n\nTraceFrame TraceReader::read_frame(FrameTime skip_before) {\n  auto& events = reader(EVENTS);\n  word buf[reasonable_frame_message_words];\n  CompressedReaderInputStream stream(events);\n  PackedMessageReader frame_msg(stream, ReaderOptions(), buf);\n  tick_time();\n  TraceFrame ret;\n  ret.global_time = time();\n\n  trace::Frame::Reader frame = frame_msg.getRoot<trace::Frame>();\n\n  auto mem_writes = frame.getMemWrites();\n  raw_recs.resize(mem_writes.size());\n  for (size_t i = 0; i < raw_recs.size(); ++i) {\n    // Build list in reverse order so we can efficiently pull records from it\n    auto w = mem_writes[raw_recs.size() - 1 - i];\n    auto holes = w.getHoles();\n    vector<WriteHole> h;\n    h.resize(holes.size());\n    for (size_t j = 0; j < h.size(); ++j) {\n      const auto& hole = holes[j];\n      h[j] = { hole.getOffset(), hole.getSize() };\n    }\n    raw_recs[i] = { w.getAddr(), (size_t)w.getSize(), i32_to_tid(w.getTid()), h,\n                    w.getSizeIsConservative() ? MemWriteSizeValidation::CONSERVATIVE : MemWriteSizeValidation::EXACT };\n  }\n\n  if (ret.global_time < skip_before) {\n    return ret;\n  }\n\n  ret.tid_ = i32_to_tid(frame.getTid());\n  ret.ticks_ = frame.getTicks();\n  if (ret.ticks_ < 0) {\n    FATAL() << \"Invalid ticks value\";\n  }\n  monotonic_time_ = ret.monotonic_time_ = frame.getMonotonicSec();\n\n  SupportedArch arch = from_trace_arch(frame.getArch());\n  ret.recorded_regs.set_arch(arch);\n  auto reg_data = frame.getRegisters().getRaw();\n  if (reg_data.size()) {\n    ret.recorded_regs.set_from_trace(arch, reg_data.begin(),\n                                     reg_data.size());\n  }\n  auto extra_reg_data = frame.getExtraRegisters().getRaw();\n  if (extra_reg_data.size()) {\n    ExtraRegisters::Format fmt;\n    switch (arch) {\n      default:\n        FATAL() << \"Unknown architecture\";\n        RR_FALLTHROUGH;\n      case x86:\n      case x86_64:\n        fmt = ExtraRegisters::XSAVE;\n        break;\n      case aarch64:\n        fmt = ExtraRegisters::NT_FPR;\n        break;\n    }\n    bool ok = ret.recorded_extra_regs.set_to_raw_data(\n        arch, fmt, extra_reg_data.begin(),\n        extra_reg_data.size(), xsave_layout_from_trace(cpuid_records()));\n    if (!ok) {\n      FATAL() << \"Invalid extended register data in trace\";\n    }\n  } else {\n    ret.recorded_extra_regs = ExtraRegisters(arch);\n  }\n\n  auto event = frame.getEvent();\n  switch (event.which()) {\n    case trace::Frame::Event::INSTRUCTION_TRAP:\n      ret.ev = Event::instruction_trap();\n      break;\n    case trace::Frame::Event::PATCH_SYSCALL:\n      ret.ev = Event::patch_syscall();\n      break;\n    case trace::Frame::Event::PATCH_TRAPPING_INSTRUCTION:\n      ret.ev = Event::patch_syscall();\n      ret.ev.PatchSyscall().patch_trapping_instruction = true;\n      break;\n    case trace::Frame::Event::PATCH_VSYSCALL:\n      ret.ev = Event::patch_syscall();\n      ret.ev.PatchSyscall().patch_vsyscall = true;\n      break;\n    case trace::Frame::Event::PATCH_AFTER_SYSCALL:\n      ret.ev = Event::patch_syscall();\n      ret.ev.PatchSyscall().patch_after_syscall = true;\n      break;\n    case trace::Frame::Event::SYSCALLBUF_ABORT_COMMIT:\n      ret.ev = Event::syscallbuf_abort_commit();\n      break;\n    case trace::Frame::Event::SYSCALLBUF_RESET:\n      ret.ev = Event::syscallbuf_reset();\n      break;\n    case trace::Frame::Event::SCHED:\n      ret.ev = Event::sched();\n      ret.ev.Sched().in_syscallbuf_syscall_hook = frame.getInSyscallbufSyscallHook();\n      break;\n    case trace::Frame::Event::GROW_MAP:\n      ret.ev = Event::grow_map();\n      break;\n    case trace::Frame::Event::SIGNAL:\n      ret.ev = from_trace_signal(EV_SIGNAL, event.getSignal());\n      break;\n    case trace::Frame::Event::SIGNAL_DELIVERY:\n      ret.ev = from_trace_signal(EV_SIGNAL_DELIVERY, event.getSignalDelivery());\n      break;\n    case trace::Frame::Event::SIGNAL_HANDLER:\n      ret.ev = from_trace_signal(EV_SIGNAL_HANDLER, event.getSignalHandler());\n      break;\n    case trace::Frame::Event::EXIT:\n      ret.ev = Event::exit();\n      break;\n    case trace::Frame::Event::SYSCALLBUF_FLUSH: {\n      ret.ev = Event(SyscallbufFlushEvent());\n      auto mprotect_records = event.getSyscallbufFlush().getMprotectRecords();\n      auto& records = ret.ev.SyscallbufFlush().mprotect_records;\n      records.resize(mprotect_records.size() / sizeof(mprotect_record));\n      if (records.data()) {\n        memcpy(records.data(), mprotect_records.begin(),\n               records.size() * sizeof(mprotect_record));\n      }\n      break;\n    }\n    case trace::Frame::Event::SYSCALL: {\n      auto syscall = event.getSyscall();\n      ret.ev = Event(SyscallEvent(syscall.getNumber(),\n                                  from_trace_arch(syscall.getArch())));\n      auto& syscall_ev = ret.ev.Syscall();\n      syscall_ev.state = from_trace_syscall_state(syscall.getState());\n      syscall_ev.failed_during_preparation =\n          syscall.getFailedDuringPreparation();\n      auto data = syscall.getExtra();\n      switch (data.which()) {\n        case trace::Frame::Event::Syscall::Extra::NONE:\n          break;\n        case trace::Frame::Event::Syscall::Extra::WRITE_OFFSET:\n          syscall_ev.write_offset = data.getWriteOffset();\n          if (syscall_ev.write_offset < 0) {\n            FATAL() << \"Write offset out of range\";\n          }\n          break;\n        case trace::Frame::Event::Syscall::Extra::EXEC_FDS_TO_CLOSE: {\n          auto exec_fds = data.getExecFdsToClose();\n          syscall_ev.exec_fds_to_close.resize(exec_fds.size());\n          for (size_t i = 0; i < exec_fds.size(); ++i) {\n            syscall_ev.exec_fds_to_close[i] = check_fd(exec_fds[i]);\n          }\n          break;\n        }\n        case trace::Frame::Event::Syscall::Extra::OPENED_FDS: {\n          auto open = data.getOpenedFds();\n          syscall_ev.opened.resize(open.size());\n          for (size_t i = 0; i < open.size(); ++i) {\n            auto& opened = syscall_ev.opened[i];\n            const auto& o = open[i];\n            opened.fd = check_fd(o.getFd());\n            opened.path = data_to_str(o.getPath());\n            opened.device = o.getDevice();\n            opened.inode = o.getInode();\n          }\n          break;\n        }\n        case trace::Frame::Event::Syscall::Extra::SOCKET_ADDRS: {\n          auto addrs = data.getSocketAddrs();\n          syscall_ev.socket_addrs = make_shared<std::array<typename NativeArch::sockaddr_storage, 2>>();\n          Data::Reader local = addrs.getLocalAddr();\n          if (local.size() != sizeof(NativeArch::sockaddr_storage)) {\n            FATAL() << \"Invalid sockaddr length\";\n          }\n          memcpy(&(*syscall_ev.socket_addrs.get())[0], local.begin(), sizeof(NativeArch::sockaddr_storage));\n          Data::Reader remote = addrs.getRemoteAddr();\n          if (remote.size() != sizeof(NativeArch::sockaddr_storage)) {\n            FATAL() << \"Invalid sockaddr length\";\n          }\n          memcpy(&(*syscall_ev.socket_addrs.get())[1], remote.begin(), sizeof(NativeArch::sockaddr_storage));\n          break;\n        }\n        case trace::Frame::Event::Syscall::Extra::MADVISE_RANGES: {\n          auto mrs = data.getMadviseRanges();\n          syscall_ev.madvise_ranges.resize(mrs.size());\n          for (size_t i = 0; i < mrs.size(); ++i) {\n            const auto& mr = mrs[i];\n            syscall_ev.madvise_ranges[i] =\n                MemoryRange(remote_ptr<void>(mr.getStart()), remote_ptr<void>(mr.getEnd()));\n          }\n          break;\n        }\n        default:\n          FATAL() << \"Unknown syscall type\";\n          break;\n      }\n      break;\n    }\n    default:\n      FATAL() << \"Event type not supported\";\n      break;\n  }\n\n  return ret;\n}\n\nvoid TraceWriter::write_task_event(const TraceTaskEvent& event) {\n  MallocMessageBuilder task_msg;\n  trace::TaskEvent::Builder task = task_msg.initRoot<trace::TaskEvent>();\n  task.setFrameTime(global_time);\n  task.setTid(event.tid());\n\n  switch (event.type()) {\n    case TraceTaskEvent::CLONE: {\n      auto clone = task.initClone();\n      clone.setParentTid(event.parent_tid());\n      clone.setOwnNsTid(event.own_ns_tid());\n      clone.setFlags(event.clone_flags());\n      break;\n    }\n    case TraceTaskEvent::EXEC: {\n      auto exec = task.initExec();\n      exec.setFileName(str_to_data(event.file_name()));\n      const auto& event_cmd_line = event.cmd_line();\n      auto cmd_line = exec.initCmdLine(event_cmd_line.size());\n      for (size_t i = 0; i < event_cmd_line.size(); ++i) {\n        cmd_line.set(i, str_to_data(event_cmd_line[i]));\n      }\n      exec.setExeBase(event.exe_base().as_int());\n      exec.setInterpBase(event.interp_base().as_int());\n      exec.setInterpName(str_to_data(event.interp_name()));;\n      auto pac_data = exec.initPacData();\n      std::vector<uint8_t> pac_data_vec = event.pac_data();\n      pac_data.setRaw(Data::Reader(pac_data_vec.data(), pac_data_vec.size()));\n      break;\n    }\n    case TraceTaskEvent::EXIT:\n      task.initExit().setExitStatus(event.exit_status().get());\n      break;\n    case TraceTaskEvent::DETACH:\n      task.initDetach();\n      break;\n    case TraceTaskEvent::NONE:\n      DEBUG_ASSERT(0 && \"Writing NONE TraceTaskEvent\");\n      break;\n  }\n\n  try {\n    auto& tasks = writer(TASKS);\n    CompressedWriterOutputStream stream(tasks);\n    writePackedMessage(stream, task_msg);\n  } catch (...) {\n    FATAL() << \"Unable to write tasks\";\n  }\n}\n\nTraceTaskEvent TraceReader::read_task_event(FrameTime* time) {\n  TraceTaskEvent r;\n  auto& tasks = reader(TASKS);\n  if (tasks.at_end()) {\n    return r;\n  }\n\n  CompressedReaderInputStream stream(tasks);\n  PackedMessageReader task_msg(stream);\n  trace::TaskEvent::Reader task = task_msg.getRoot<trace::TaskEvent>();\n  r.tid_ = i32_to_tid(task.getTid());\n  if (time) {\n    *time = task.getFrameTime();\n  }\n  switch (task.which()) {\n    case trace::TaskEvent::Which::CLONE: {\n      r.type_ = TraceTaskEvent::CLONE;\n      auto clone = task.getClone();\n      r.parent_tid_ = i32_to_tid(clone.getParentTid());\n      // The record task could have died before we were able to compute this,\n      // which we handle fine (since we'll see the exit event right away),\n      // but we can't use i32_to_tid, which will assert if the tid is invalid.\n      r.own_ns_tid_ = (pid_t)clone.getOwnNsTid();\n      r.clone_flags_ = clone.getFlags();\n      LOG(debug) << \"Reading event for \" << task.getFrameTime()\n                 << \": parent=\" << r.parent_tid_ << \" tid=\" << r.tid_;\n      break;\n    }\n    case trace::TaskEvent::Which::EXEC: {\n      r.type_ = TraceTaskEvent::EXEC;\n      auto exec = task.getExec();\n      r.file_name_ = data_to_str(exec.getFileName());\n      auto cmd_line = exec.getCmdLine();\n      r.cmd_line_.resize(cmd_line.size());\n      for (size_t i = 0; i < cmd_line.size(); ++i) {\n        r.cmd_line_[i] = data_to_str(cmd_line[i]);\n      }\n      r.exe_base_ = exec.getExeBase();\n      r.interp_base_ = exec.getInterpBase();\n      r.interp_name_ = data_to_str(exec.getInterpName());\n      auto pac_data = exec.getPacData().getRaw();\n      r.pac_data_ = std::vector<uint8_t>(pac_data.begin(), pac_data.end());\n      break;\n    }\n    case trace::TaskEvent::Which::EXIT:\n      r.type_ = TraceTaskEvent::EXIT;\n      r.exit_status_ = WaitStatus(task.getExit().getExitStatus());\n      break;\n    case trace::TaskEvent::Which::DETACH:\n      r.type_ = TraceTaskEvent::DETACH;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Unknown TraceEvent type\");\n      break;\n  }\n  return r;\n}\n\nstatic string base_file_name(const string& file_name) {\n  size_t last_slash = file_name.rfind('/');\n  return (last_slash != file_name.npos) ? file_name.substr(last_slash + 1)\n                                        : file_name;\n}\n\nbool TraceWriter::try_hardlink_file(const string& real_file_name,\n                                    const string& access_file_name,\n                                    std::string* new_name) {\n  char count_str[20];\n  sprintf(count_str, \"%d\", mmap_count);\n\n  string path =\n      string(\"mmap_hardlink_\") + count_str + \"_\" + base_file_name(real_file_name);\n  int ret = linkat(AT_FDCWD, access_file_name.c_str(), AT_FDCWD, (dir() + \"/\" + path).c_str(), AT_SYMLINK_FOLLOW);\n  if (ret < 0) {\n    return false;\n  }\n  *new_name = path;\n  return true;\n}\n\nbool TraceWriter::try_clone_file(RecordTask* t,\n    const string& real_file_name, const string& access_file_name,\n    string* new_name) {\n  if (!t->session().use_file_cloning()) {\n    return false;\n  }\n\n  char count_str[20];\n  sprintf(count_str, \"%d\", mmap_count);\n\n  string path =\n      string(\"mmap_clone_\") + count_str + \"_\" + base_file_name(real_file_name);\n\n  ScopedFd src(access_file_name.c_str(), O_RDONLY);\n  if (!src.is_open()) {\n    return false;\n  }\n  string dest_path = dir() + \"/\" + path;\n  ScopedFd dest(dest_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0700);\n  if (!dest.is_open()) {\n    return false;\n  }\n\n  int ret = ioctl(dest, BTRFS_IOC_CLONE, src.get());\n  if (ret < 0) {\n    // maybe not on the same filesystem, or filesystem doesn't support clone?\n    unlink(dest_path.c_str());\n    return false;\n  }\n\n  *new_name = path;\n  return true;\n}\n\nbool TraceWriter::copy_file(const std::string& real_file_name,\n                            const std::string& access_file_name,\n                            std::string* new_name) {\n  char count_str[20];\n  sprintf(count_str, \"%d\", mmap_count);\n\n  string path =\n      string(\"mmap_copy_\") + count_str + \"_\" + base_file_name(real_file_name);\n\n  ScopedFd src(access_file_name.c_str(), O_RDONLY);\n  if (!src.is_open()) {\n    LOG(debug) << \"Can't open \" << access_file_name;\n    return false;\n  }\n  string dest_path = dir() + \"/\" + path;\n  ScopedFd dest(dest_path.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0700);\n  if (!dest.is_open()) {\n    return false;\n  }\n\n  *new_name = path;\n\n  return rr::copy_file(dest, src);\n}\n\nstatic bool starts_with(const string& s, const string& with) {\n  return s.find(with) == 0;\n}\n\nTraceWriter::RecordInTrace TraceWriter::write_mapped_region(\n    RecordTask* t, const KernelMapping& km,\n    const struct stat& stat, const std::string &file_name,\n    const vector<TraceRemoteFd>& extra_fds, MappingOrigin origin,\n    bool skip_monitoring_mapped_fd) {\n  MallocMessageBuilder map_msg;\n  trace::MMap::Builder map = map_msg.initRoot<trace::MMap>();\n  map.setFrameTime(global_time);\n  map.setStart(km.start().as_int());\n  map.setEnd(km.end().as_int());\n  map.setFsname(str_to_data(km.fsname()));\n  map.setDevice(km.device());\n  map.setInode(km.inode());\n  map.setProt(km.prot());\n  map.setFlags(km.flags());\n  map.setFileOffsetBytes(km.file_offset_bytes());\n  map.setStatMode(stat.st_mode);\n  map.setStatUid(stat.st_uid);\n  map.setStatGid(stat.st_gid);\n  map.setStatSize(stat.st_size);\n  map.setStatMTime(stat.st_mtime);\n  auto fds = map.initExtraFds(extra_fds.size());\n  for (size_t i = 0; i < extra_fds.size(); ++i) {\n    auto e = fds[i];\n    auto& r = extra_fds[i];\n    e.setTid(r.tid);\n    e.setFd(r.fd);\n  }\n  map.setSkipMonitoringMappedFd(skip_monitoring_mapped_fd);\n  auto src = map.getSource();\n  string backing_file_name;\n\n  auto copy_file_or_trace = [&](string file_name) {\n    // Make executable files accessible to debuggers by copying the whole\n    // thing into the trace directory. We don't get to compress the data and\n    // the entire file is copied, not just the used region, which is why we\n    // don't do this for all files.\n    // Don't bother trying to copy [vdso].\n    // Don't try to copy files that use shared mappings. We do not want to\n    // create a shared mapping of a file stored in the trace. This means\n    // debuggers can't find the file, but the Linux loader doesn't create\n    // shared mappings so situations where a shared-mapped executable contains\n    // usable debug info should be very rare at best...\n    // copy files when the mapping is PROT_EXEC, unless the file is too big\n    // sometimes km.size() does not equal the file size from fstat().\n    string backing_file_name;\n    if ((km.prot() & PROT_EXEC) &&\n        !(km.flags() & MAP_SHARED) &&\n        stat.st_size <= 1024 * 1024 * 1024 &&\n        copy_file(km.fsname(), file_name, &backing_file_name)) {\n      src.initFile().setBackingFileName(str_to_data(backing_file_name));\n    } else {\n      src.setTrace();\n    }\n  };\n\n  if (origin == REMAP_MAPPING || origin == PATCH_MAPPING ||\n      origin == RR_BUFFER_MAPPING) {\n    src.setZero();\n  } else if (starts_with(km.fsname(), \"/SYSV\")) {\n    src.setTrace();\n  } else if (origin == SYSCALL_MAPPING &&\n             (km.inode() == 0 || km.fsname_strip_deleted() == \"/dev/zero\")) {\n    src.setZero();\n  } else if (!starts_with(km.fsname(), \"/\")) {\n    src.setTrace();\n  } else {\n    auto assumed_immutable =\n        files_assumed_immutable.find(make_pair(stat.st_dev, stat.st_ino));\n\n    if (assumed_immutable != files_assumed_immutable.end()) {\n      src.initFile().setBackingFileName(str_to_data(assumed_immutable->second));\n    } else if ((km.flags() & MAP_PRIVATE) &&\n               try_clone_file(t, km.fsname(), file_name, &backing_file_name)) {\n      src.initFile().setBackingFileName(str_to_data(backing_file_name));\n    } else if (should_copy_mmap_region(km, file_name, stat)) {\n      copy_file_or_trace(file_name);\n    } else {\n      // should_copy_mmap_region's heuristics determined it was OK to just map\n      // the file here even if it's MAP_SHARED. So try cloning again to avoid\n      // the possibility of the file changing between recording and replay.\n      if (try_clone_file(t, km.fsname(), file_name, &backing_file_name)) {\n        src.initFile().setBackingFileName(str_to_data(backing_file_name));\n      } else {\n        // Try hardlinking file into the trace directory. This will avoid\n        // replay failures if the original file is deleted or replaced (but not\n        // if it is overwritten in-place). If try_hardlink_file fails it\n        // just returns the original file name.\n        // A relative backing_file_name is relative to the trace directory.\n        if (!try_hardlink_file(km.fsname(), file_name, &backing_file_name)) {\n          // Don't ever use `file_name` for the `backing_file_name` because it\n          // contains the pid of a recorded process and will not work!\n          backing_file_name = km.fsname();\n          // If the backing_file_name refers to a different file (e.g.\n          // because we have a file in our mount namespace that matches the\n          // fsname in the Task's mount namespace), then copy the file even\n          // if the heuristics above thought we could get away with leaving it\n          // in place. Otherwise, we're essentially guaranteed to have a broken\n          // recording.\n          struct stat backing_stat;\n          int err = ::stat(backing_file_name.c_str(), &backing_stat);\n          if (err != 0 || backing_stat.st_dev != km.device() ||\n              backing_stat.st_ino != km.inode()) {\n            copy_file_or_trace(file_name);\n          } else {\n            files_assumed_immutable.insert(\n                make_pair(make_pair(stat.st_dev, stat.st_ino), backing_file_name));\n            src.initFile().setBackingFileName(str_to_data(backing_file_name));\n          }\n        } else {\n          files_assumed_immutable.insert(\n            make_pair(make_pair(stat.st_dev, stat.st_ino), backing_file_name));\n          src.initFile().setBackingFileName(str_to_data(backing_file_name));\n        }\n      }\n    }\n  }\n\n  try {\n    auto& mmaps = writer(MMAPS);\n    CompressedWriterOutputStream stream(mmaps);\n    writePackedMessage(stream, map_msg);\n  } catch (...) {\n    FATAL() << \"Unable to write mmaps\";\n  }\n\n  ++mmap_count;\n  return src.isTrace() ? RECORD_IN_TRACE : DONT_RECORD_IN_TRACE;\n}\n\nvoid TraceWriter::write_mapped_region_to_alternative_stream(\n    CompressedWriter& mmaps, const MappedData& data, const KernelMapping& km,\n    const vector<TraceRemoteFd>& extra_fds, bool skip_monitoring_mapped_fd) {\n  MallocMessageBuilder map_msg;\n  trace::MMap::Builder map = map_msg.initRoot<trace::MMap>();\n\n  map.setFrameTime(data.time);\n  map.setStart(km.start().as_int());\n  map.setEnd(km.end().as_int());\n  map.setFsname(str_to_data(km.fsname()));\n  map.setDevice(km.device());\n  map.setInode(km.inode());\n  map.setProt(km.prot());\n  map.setFlags(km.flags());\n  map.setFileOffsetBytes(km.file_offset_bytes());\n  map.setStatSize(data.file_size_bytes);\n  auto fds = map.initExtraFds(extra_fds.size());\n  for (size_t i = 0; i < extra_fds.size(); ++i) {\n    auto e = fds[i];\n    auto& r = extra_fds[i];\n    e.setTid(r.tid);\n    e.setFd(r.fd);\n  }\n  map.setSkipMonitoringMappedFd(skip_monitoring_mapped_fd);\n  auto src = map.getSource();\n  switch (data.source) {\n    case TraceReader::SOURCE_ZERO:\n      src.setZero();\n      break;\n    case TraceReader::SOURCE_TRACE:\n      src.setTrace();\n      break;\n    case TraceReader::SOURCE_FILE:\n      src.initFile().setBackingFileName(str_to_data(data.file_name));\n      break;\n    default:\n      FATAL() << \"Unknown source type\";\n      break;\n  }\n\n  try {\n    CompressedWriterOutputStream stream(mmaps);\n    writePackedMessage(stream, map_msg);\n  } catch (...) {\n    FATAL() << \"Unable to write mmaps\";\n  }\n}\n\nKernelMapping TraceReader::read_mapped_region(MappedData* data, bool* found,\n                                              ValidateSourceFile validate,\n                                              TimeConstraint time_constraint,\n                                              vector<TraceRemoteFd>* extra_fds,\n                                              bool* skip_monitoring_mapped_fd) {\n  if (found) {\n    *found = false;\n  }\n\n  auto& mmaps = reader(MMAPS);\n  if (mmaps.at_end()) {\n    return KernelMapping();\n  }\n\n  if (time_constraint == CURRENT_TIME_ONLY) {\n    mmaps.save_state();\n  }\n  CompressedReaderInputStream stream(mmaps);\n  PackedMessageReader map_msg(stream);\n  trace::MMap::Reader map = map_msg.getRoot<trace::MMap>();\n  if (time_constraint == CURRENT_TIME_ONLY) {\n    if (map.getFrameTime() != global_time) {\n      mmaps.restore_state();\n      return KernelMapping();\n    }\n    mmaps.discard_state();\n  }\n\n  if (data) {\n    data->time = map.getFrameTime();\n    if (data->time <= 0) {\n      FATAL() << \"Invalid frameTime\";\n    }\n    data->data_offset_bytes = 0;\n    data->file_size_bytes = map.getStatSize();\n    if (extra_fds) {\n      const auto& fds = map.getExtraFds();\n      for (size_t i = 0; i < fds.size(); ++i) {\n        const auto& f = fds[i];\n        extra_fds->push_back({ f.getTid(), f.getFd() });\n      }\n    }\n    if (skip_monitoring_mapped_fd) {\n      *skip_monitoring_mapped_fd = map.getSkipMonitoringMappedFd();\n    }\n    auto src = map.getSource();\n    switch (src.which()) {\n      case trace::MMap::Source::Which::ZERO:\n        data->source = SOURCE_ZERO;\n        break;\n      case trace::MMap::Source::Which::TRACE:\n        data->source = SOURCE_TRACE;\n        break;\n      case trace::MMap::Source::Which::FILE: {\n        data->source = SOURCE_FILE;\n        string backing_file_name =\n            data_to_str(src.getFile().getBackingFileName());\n        bool is_clone = starts_with(backing_file_name, \"mmap_clone_\");\n        bool is_copy = starts_with(backing_file_name, \"mmap_copy_\");\n        if (backing_file_name[0] != '/') {\n          backing_file_name = dir() + \"/\" + backing_file_name;\n        }\n        uint32_t uid = map.getStatUid();\n        uint32_t gid = map.getStatGid();\n        uint32_t mode = map.getStatMode();\n        int64_t mtime = map.getStatMTime();\n        int64_t size = map.getStatSize();\n        if (size < 0) {\n          FATAL() << \"Invalid statSize\";\n        }\n        bool has_stat_buf = mode != 0 || uid != 0 || gid != 0 || mtime != 0;\n        if (!is_clone && !is_copy && validate == VALIDATE && has_stat_buf) {\n          struct stat backing_stat;\n          if (stat(backing_file_name.c_str(), &backing_stat)) {\n            FATAL() << \"Failed to stat \" << backing_file_name\n                    << \": replay is impossible\";\n          }\n          if (backing_stat.st_ino != map.getInode() ||\n              backing_stat.st_mode != mode || backing_stat.st_uid != uid ||\n              backing_stat.st_gid != gid || backing_stat.st_size != size ||\n              backing_stat.st_mtime != mtime) {\n            LOG(error) << \"Metadata of \" << data_to_str(map.getFsname())\n                       << \" changed: replay divergence likely, but continuing \"\n                          \"anyway. inode: \"\n                       << backing_stat.st_ino << \"/\" << map.getInode()\n                       << \"; mode: \" << backing_stat.st_mode << \"/\" << mode\n                       << \"; uid: \" << backing_stat.st_uid << \"/\" << uid\n                       << \"; gid: \" << backing_stat.st_gid << \"/\" << gid\n                       << \"; size: \" << backing_stat.st_size << \"/\" << size\n                       << \"; mtime: \" << backing_stat.st_mtime << \"/\" << mtime;\n          }\n        }\n        data->file_name = backing_file_name;\n        int64_t file_offset_bytes = map.getFileOffsetBytes();\n        if (file_offset_bytes < 0) {\n          FATAL() << \"Invalid fileOffsetBytes\";\n        }\n        data->data_offset_bytes = file_offset_bytes;\n        break;\n      }\n      default:\n        FATAL() << \"Unknown mapping source\";\n        break;\n    }\n  }\n  if (found) {\n    *found = true;\n  }\n  return KernelMapping(map.getStart(), map.getEnd(),\n                       data_to_str(map.getFsname()), map.getDevice(),\n                       map.getInode(), map.getProt(), map.getFlags(),\n                       map.getFileOffsetBytes());\n}\n\nvoid TraceWriter::write_raw_header(pid_t rec_tid, size_t total_len,\n                                   remote_ptr<void> addr,\n                                   const std::vector<WriteHole>& holes,\n                                   MemWriteSizeValidation size_validation) {\n  raw_recs.push_back({ addr, total_len, rec_tid, holes, size_validation });\n}\n\nvoid TraceWriter::write_raw_data(const void* d, size_t len) {\n  auto& data = writer(RAW_DATA);\n  data.write(d, len);\n}\n\nbool TraceReader::read_raw_data_for_frame(RawData& d) {\n  if (raw_recs.empty()) {\n    return false;\n  }\n  auto& rec = raw_recs[raw_recs.size() - 1];\n  d.rec_tid = rec.rec_tid;\n  d.addr = rec.addr;\n  d.size_validation = rec.size_validation;\n\n  d.data.resize(rec.size);\n  auto hole_iter = rec.holes.begin();\n  uintptr_t offset = 0;\n  while (offset < d.data.size()) {\n    uintptr_t end = rec.size;\n    if (hole_iter != rec.holes.end()) {\n      if (offset == hole_iter->offset) {\n        memset(d.data.data() + offset, 0, hole_iter->size);\n        offset += hole_iter->size;\n        ++hole_iter;\n        continue;\n      }\n      end = hole_iter->offset;\n    }\n    reader(RAW_DATA).read((char*)d.data.data() + offset, end - offset);\n    offset = end;\n  }\n\n  raw_recs.pop_back();\n  return true;\n}\n\nbool TraceReader::read_raw_data_for_frame_with_holes(RawDataWithHoles& d) {\n  if (raw_recs.empty()) {\n    return false;\n  }\n  auto& rec = raw_recs[raw_recs.size() - 1];\n  d.rec_tid = rec.rec_tid;\n  d.addr = rec.addr;\n  d.holes = std::move(rec.holes);\n  size_t data_size = rec.size;\n  d.size_validation = rec.size_validation;\n  for (auto& h : d.holes) {\n    data_size -= h.size;\n  }\n  d.data.resize(data_size);\n  reader(RAW_DATA).read((char*)d.data.data(), data_size);\n\n  raw_recs.pop_back();\n  return true;\n}\n\nbool TraceReader::read_raw_data_metadata_for_frame(RawDataMetadata& d) {\n  if (raw_recs.empty()) {\n    return false;\n  }\n  d = raw_recs[raw_recs.size() - 1];\n  size_t data_size = d.size;\n  for (auto& h : d.holes) {\n    data_size -= h.size;\n  }\n  reader(RAW_DATA).skip(data_size);\n  raw_recs.pop_back();\n  return true;\n}\n\nstatic string make_trace_dir(const string& exe_path, const string& output_trace_dir) {\n  if (!output_trace_dir.empty()) {\n    // save trace dir in given output trace dir with option -o\n    int ret = mkdir(output_trace_dir.c_str(), S_IRWXU | S_IRWXG);\n    if (ret == 0) {\n      return output_trace_dir;\n    }\n    if (EEXIST == errno) {\n      CLEAN_FATAL() << \"Trace directory `\" << output_trace_dir << \"' already exists.\";\n    } else if (EACCES == errno) {\n      CLEAN_FATAL() << \"Permission denied to create trace directory `\" << output_trace_dir << \"'\";\n    } else {\n      FATAL() << \"Unable to create trace directory `\" << output_trace_dir << \"'\";\n    }\n  } else {\n    // save trace dir set in _RR_TRACE_DIR or in the default trace dir\n    ensure_dir(trace_save_dir(), \"trace directory\", S_IRWXU);\n\n    // Find a unique trace directory name.\n    int nonce = 0;\n    int ret;\n    string dir;\n    do {\n      stringstream ss;\n      ss << trace_save_dir() << \"/\" << basename(exe_path.c_str()) << \"-\"\n         << nonce++;\n      dir = ss.str();\n      ret = mkdir(dir.c_str(), S_IRWXU | S_IRWXG);\n    } while (ret && EEXIST == errno);\n\n    if (ret) {\n      FATAL() << \"Unable to create trace directory `\" << dir << \"'\";\n    }\n\n    return dir;\n  }\n\n  return \"\"; // not reached\n}\n\n#define STR_HELPER(x) #x\n#define STR(x) STR_HELPER(x)\n\nTraceWriter::TraceWriter(const std::string& file_name,\n                         const string& output_trace_dir,\n                         TicksSemantics ticks_semantics_)\n    : TraceStream(make_trace_dir(file_name, output_trace_dir),\n                  // Somewhat arbitrarily start the\n                  // global time from 1.\n                  1),\n      ticks_semantics_(ticks_semantics_),\n      mmap_count(0),\n      max_virtual_address_size(0),\n      has_cpuid_faulting_(false),\n      xsave_fip_fdp_quirk_(false),\n      fdp_exception_only_quirk_(false),\n      clear_fip_fdp_(false),\n      supports_file_data_cloning_(false),\n      chaos_mode(false)\n{\n  this->ticks_semantics_ = ticks_semantics_;\n\n  for (Substream s = SUBSTREAM_FIRST; s < SUBSTREAM_COUNT; ++s) {\n    writers[s] = unique_ptr<CompressedWriter>(new CompressedWriter(\n        path(s), substream(s).block_size, substream(s).threads));\n  }\n\n  string ver_path = incomplete_version_path();\n  version_fd = ScopedFd(ver_path.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0600);\n  if (!version_fd.is_open()) {\n    FATAL() << \"Unable to create \" << ver_path;\n  }\n  // Take an exclusive lock and hold it until we rename the file at\n  // the end of recording and then close our file descriptor.\n  if (flock(version_fd, LOCK_EX | LOCK_NB) != 0) {\n    FATAL() << \"Unable to lock \" << ver_path;\n  }\n  static const char buf[] = STR(TRACE_VERSION) \"\\n\";\n  size_t buf_len = sizeof(buf) - 1;\n  if (write(version_fd, buf, buf_len) != (ssize_t)buf_len) {\n    FATAL() << \"Unable to write \" << ver_path;\n  }\n\n  // Test if file data cloning is supported\n  string version_clone_path = trace_dir + \"/tmp_clone\";\n  ScopedFd version_clone_fd(version_clone_path.c_str(), O_WRONLY | O_CREAT,\n                            0600);\n  if (!version_clone_fd.is_open()) {\n    FATAL() << \"Unable to create \" << version_clone_path;\n  }\n  btrfs_ioctl_clone_range_args clone_args;\n  clone_args.src_fd = version_fd;\n  clone_args.src_offset = 0;\n  clone_args.src_length = buf_len;\n  clone_args.dest_offset = 0;\n  if (ioctl(version_clone_fd, BTRFS_IOC_CLONE_RANGE, &clone_args) == 0) {\n    supports_file_data_cloning_ = true;\n  }\n  unlink(version_clone_path.c_str());\n\n  if (!probably_not_interactive(STDOUT_FILENO)) {\n    printf(\"rr: Saving execution to trace directory `%s'.\\n\",\n           trace_dir.c_str());\n  }\n}\n\nvoid TraceWriter::setup_cpuid_records(bool has_cpuid_faulting,\n                                      const DisableCPUIDFeatures& disable_cpuid_features) {\n  has_cpuid_faulting_ = has_cpuid_faulting;\n  // We are now bound to the selected CPU (if any), so collect CPUID records\n  // (which depend on the bound CPU number).\n  cpuid_records = all_cpuid_records();\n  // Modify the recorded cpuid data only if cpuid faulting is available. If it\n  // is not available, the tracee will see unmodified data and should also see\n  // that in handle_unrecorded_cpuid_fault (which is sourced from this data).\n  if (has_cpuid_faulting) {\n    for (auto& r : cpuid_records) {\n      disable_cpuid_features.amend_cpuid_data(r.eax_in, r.ecx_in, &r.out);\n    }\n  }\n}\n\nvoid TraceWriter::close(CloseStatus status, const TraceUuid* uuid) {\n  for (auto& w : writers) {\n    w->close();\n  }\n\n  MallocMessageBuilder header_msg;\n  trace::Header::Builder header = header_msg.initRoot<trace::Header>();\n  header.setBindToCpu(this->bind_to_cpu);\n  header.setTicksSemantics(\n    to_trace_ticks_semantics(PerfCounters::default_ticks_semantics()));\n  header.setSyscallbufProtocolVersion(SYSCALLBUF_PROTOCOL_VERSION);\n  header.setRequiredForwardCompatibilityVersion(FORWARD_COMPATIBILITY_VERSION);\n  header.setPreloadThreadLocalsRecorded(true);\n  header.setRrcallBase(syscall_number_for_rrcall_init_preload(x86_64));\n  header.setSyscallbufFdsDisabledSize(SYSCALLBUF_FDS_DISABLED_SIZE);\n  header.setSyscallbufHdrSize(sizeof(syscallbuf_hdr));\n\n  header.setNativeArch(to_trace_arch(NativeArch::arch()));\n  if (NativeArch::is_x86ish())\n  {\n    auto x86data = header.initX86();\n    x86data.setHasCpuidFaulting(has_cpuid_faulting_);\n    x86data.setCpuidRecords(\n        Data::Reader(reinterpret_cast<const uint8_t*>(cpuid_records.data()),\n                    cpuid_records.size() * sizeof(CPUIDRecord)));\n    x86data.setXcr0(xcr0());\n    x86data.setXsaveFipFdpQuirk(to_tristate(xsave_fip_fdp_quirk_));\n    x86data.setFdpExceptionOnlyQuirk(to_tristate(fdp_exception_only_quirk_));\n    x86data.setClearFipFdp(clear_fip_fdp_);\n  }\n\n  {\n    auto quirks = header.initQuirks();\n    quirks.setExplicitProcMem(false);\n    quirks.setSpecialLibrrpage(false);\n    quirks.setPkeyAllocRecordedExtraRegs(true);\n    quirks.setBufferedSyscallForcedTick(true);\n    quirks.setUsesGlobalsInReplay(false);\n  }\n  // Add a random UUID to the trace metadata. This lets tools identify a trace\n  // easily.\n  if (!uuid) {\n    uint8_t uuid[sizeof(TraceUuid::bytes)];\n    good_random(uuid, sizeof(uuid));\n    header.setUuid(Data::Reader(uuid, sizeof(uuid)));\n  } else {\n    header.setUuid(Data::Reader(uuid->bytes, sizeof(TraceUuid::bytes)));\n  }\n  header.setOk(status == CLOSE_OK);\n  header.setChaosMode(chaos_mode ? trace::ChaosMode::KNOWN_TRUE : trace::ChaosMode::KNOWN_FALSE);\n  MemoryRange exclusion_range = AddressSpace::get_global_exclusion_range(nullptr);\n  header.setExclusionRangeStart(exclusion_range.start().as_int());\n  header.setExclusionRangeEnd(exclusion_range.end().as_int());\n  header.setRuntimePageSize(page_size());\n  header.setPreloadLibraryPageSize(PRELOAD_LIBRARY_PAGE_SIZE);\n  header.setMaxVirtualAddressSize(max_virtual_address_size);\n  header.setCpuImproperlyConfigured(to_tristate(PerfCounters::improperly_configured()));\n\n  {\n    struct utsname uname_buf;\n    int ret = uname(&uname_buf);\n    if (ret) {\n      FATAL() << \"uname failed\";\n    }\n    auto uname_msg = header.initUname();\n    uname_msg.setSysname(str_to_data(uname_buf.sysname));\n    uname_msg.setNodename(str_to_data(uname_buf.nodename));\n    uname_msg.setRelease(str_to_data(uname_buf.release));\n    uname_msg.setVersion(str_to_data(uname_buf.version));\n    uname_msg.setMachine(str_to_data(uname_buf.machine));\n    uname_msg.setDomainname(str_to_data(uname_buf.domainname));\n  }\n\n  try {\n    writePackedMessageToFd(version_fd, header_msg);\n  } catch (...) {\n    FATAL() << \"Unable to write \" << incomplete_version_path();\n  }\n\n  string incomplete_path = incomplete_version_path();\n  string path = version_path();\n  if (rename(incomplete_path.c_str(), path.c_str()) < 0) {\n    FATAL() << \"Unable to create version file \" << path;\n  }\n  version_fd.close();\n}\n\nvoid TraceWriter::make_latest_trace() {\n  string link_name = latest_trace_symlink();\n  // Try to update the symlink to |this|.  We only try attempt\n  // to set the symlink once.  If the link is re-created after\n  // we |unlink()| it, then another rr process is racing with us\n  // and it \"won\".  The link is then valid and points at some\n  // very-recent trace, so that's good enough.\n  unlink(link_name.c_str());\n  // Link only the trace name, not the full path, so moving a directory full\n  // of traces around doesn't break the latest-trace link.\n  const char* trace_name = trace_dir.c_str();\n  const char* last = strrchr(trace_name, '/');\n  if (last) {\n    trace_name = last + 1;\n  }\n  int ret = symlink(trace_name, link_name.c_str());\n  if (ret < 0 && errno != EEXIST) {\n    FATAL() << \"Failed to update symlink `\" << link_name << \"' to `\"\n            << trace_dir << \"'.\";\n  }\n}\n\nTraceFrame TraceReader::peek_frame() {\n  auto& events = reader(EVENTS);\n  events.save_state();\n  auto saved_time = global_time;\n  auto saved_raw_recs = raw_recs;\n  TraceFrame frame;\n  if (!at_end()) {\n    frame = read_frame();\n  }\n  events.restore_state();\n  global_time = saved_time;\n  raw_recs = saved_raw_recs;\n  return frame;\n}\n\nvoid TraceReader::rewind() {\n  for (Substream s = SUBSTREAM_FIRST; s < SUBSTREAM_COUNT; ++s) {\n    reader(s).rewind();\n  }\n  global_time = 0;\n  DEBUG_ASSERT(good());\n}\n\nTraceReader::TraceReader(const string& dir)\n    : TraceStream(resolve_trace_name(dir), 1) {\n  for (Substream s = SUBSTREAM_FIRST; s < SUBSTREAM_COUNT; ++s) {\n    readers[s] = unique_ptr<CompressedReader>(new CompressedReader(path(s)));\n  }\n\n  string path = version_path();\n  ScopedFd version_fd(path.c_str(), O_RDONLY);\n  if (!version_fd.is_open()) {\n    if (errno == ENOENT) {\n      string incomplete_path = incomplete_version_path();\n      if (access(incomplete_path.c_str(), F_OK) == 0) {\n        fprintf(\n            stderr,\n            \"\\n\"\n            \"rr: Trace file `%s' found.\\n\"\n            \"rr recording terminated abnormally and the trace is incomplete.\\n\"\n            \"\\n\",\n            incomplete_path.c_str());\n      } else {\n        fprintf(stderr,\n                \"\\n\"\n                \"rr: Trace file `%s' not found. There is no trace there.\\n\"\n                \"\\n\",\n                path.c_str());\n      }\n    } else {\n      fprintf(stderr, \"\\n\"\n                      \"rr: Trace file `%s' not readable.\\n\"\n                      \"\\n\",\n              path.c_str());\n    }\n    exit(EX_DATAERR);\n  }\n  string version_str;\n  while (true) {\n    char ch;\n    ssize_t ret = read(version_fd, &ch, 1);\n    if (ret <= 0) {\n      FATAL() << \"Can't read version file \" << path;\n    }\n    if (ch == '\\n') {\n      break;\n    }\n    version_str += ch;\n  }\n  char* end_ptr;\n  long int version = strtol(version_str.c_str(), &end_ptr, 10);\n  if (*end_ptr != 0) {\n    FATAL() << \"Invalid version: \" << version_str;\n  }\n  if (TRACE_VERSION != version) {\n    fprintf(stderr, \"\\n\"\n                    \"rr: error: Recorded trace `%s' has an incompatible \"\n                    \"version %ld; expected\\n\"\n                    \"           %d.  Did you record `%s' with an older version \"\n                    \"of rr?  If so,\\n\"\n                    \"           you'll need to replay `%s' with that older \"\n                    \"version.  Otherwise,\\n\"\n                    \"           your trace is likely corrupted.\\n\"\n                    \"\\n\",\n            path.c_str(), version, TRACE_VERSION, path.c_str(), path.c_str());\n    exit(EX_DATAERR);\n  }\n\n  PackedFdMessageReader header_msg(version_fd);\n\n  trace::Header::Reader header = header_msg.getRoot<trace::Header>();\n  uint16_t syscallbuf_protocol_version = header.getSyscallbufProtocolVersion();\n  if (syscallbuf_protocol_version > SYSCALLBUF_PROTOCOL_VERSION) {\n    fprintf(stderr, \"\\n\"\n                    \"rr: error: Recorded trace `%s' has an incompatible \"\n                    \"syscallbuf protocol version %d; expected\\n\"\n                    \"           %d.  Did you record `%s' with an older version \"\n                    \"of rr?  If so,\\n\"\n                    \"           you'll need to replay `%s' with that older \"\n                    \"version.  Otherwise,\\n\"\n                    \"           your trace is likely corrupted.\\n\"\n                    \"\\n\",\n            path.c_str(), syscallbuf_protocol_version, SYSCALLBUF_PROTOCOL_VERSION, path.c_str(), path.c_str());\n    exit(EX_DATAERR);\n  }\n  bind_to_cpu = header.getBindToCpu();\n  preload_thread_locals_recorded_ = header.getPreloadThreadLocalsRecorded();\n  ticks_semantics_ = from_trace_ticks_semantics(header.getTicksSemantics());\n  rrcall_base_ = header.getRrcallBase();\n  max_virtual_address_size_ = header.getMaxVirtualAddressSize();\n  syscallbuf_fds_disabled_size_ = header.getSyscallbufFdsDisabledSize();\n  syscallbuf_hdr_size_ = header.getSyscallbufHdrSize();\n  required_forward_compatibility_version_ = header.getRequiredForwardCompatibilityVersion();\n  quirks_ = 0;\n  {\n    auto quirks = header.getQuirks();\n    if (quirks.getExplicitProcMem()) {\n      quirks_ |= ExplicitProcMem;\n    }\n    if (quirks.getSpecialLibrrpage()) {\n      quirks_ |= SpecialLibRRpage;\n    }\n    if (quirks.getPkeyAllocRecordedExtraRegs()) {\n      quirks_ |= PkeyAllocRecordedExtraRegs;\n    }\n    if (quirks.getBufferedSyscallForcedTick()) {\n      quirks_ |= BufferedSyscallForcedTick;\n    }\n    if (quirks.getUsesGlobalsInReplay()) {\n      quirks_ |= UsesGlobalsInReplay;\n    }\n  }\n  Data::Reader uuid = header.getUuid();\n  uuid_ = unique_ptr<TraceUuid>(new TraceUuid());\n  if (uuid.size() != sizeof(uuid_->bytes)) {\n    FATAL() << \"Invalid UUID length\";\n  }\n  memcpy(uuid_->bytes, uuid.begin(), sizeof(uuid_->bytes));\n\n  arch_ = from_trace_arch(header.getNativeArch());\n  if (is_x86ish(arch_)) {\n    auto x86data = header.getX86();\n    trace_uses_cpuid_faulting = x86data.getHasCpuidFaulting();\n    Data::Reader cpuid_records_bytes = x86data.getCpuidRecords();\n    size_t len = cpuid_records_bytes.size() / sizeof(CPUIDRecord);\n    if (cpuid_records_bytes.size() != len * sizeof(CPUIDRecord)) {\n      FATAL() << \"Invalid CPUID records length\";\n    }\n    cpuid_records_.resize(len);\n    memcpy(cpuid_records_.data(), cpuid_records_bytes.begin(),\n          len * sizeof(CPUIDRecord));\n    xcr0_ = x86data.getXcr0();\n    clear_fip_fdp_ = x86data.getClearFipFdp();\n  }\n\n  switch (header.getChaosMode()) {\n    case trace::ChaosMode::UNKNOWN:\n      chaos_mode_known_ = false;\n      chaos_mode_ = false;\n      break;\n    case trace::ChaosMode::KNOWN_TRUE:\n      chaos_mode_known_ = true;\n      chaos_mode_ = true;\n      break;\n    case trace::ChaosMode::KNOWN_FALSE:\n      chaos_mode_known_ = true;\n      chaos_mode_ = false;\n      break;\n  }\n  exclusion_range_ = MemoryRange(remote_ptr<void>(header.getExclusionRangeStart()),\n                                 remote_ptr<void>(header.getExclusionRangeEnd()));\n\n  switch (header.getCpuImproperlyConfigured()) {\n    case trace::CpuTriState::UNKNOWN:\n      cpu_improperly_configured_known_ = false;\n      cpu_improperly_configured_ = false;\n      break;\n    case trace::CpuTriState::KNOWN_TRUE:\n      cpu_improperly_configured_known_ = true;\n      cpu_improperly_configured_ = true;\n      break;\n    case trace::CpuTriState::KNOWN_FALSE:\n      cpu_improperly_configured_known_ = true;\n      cpu_improperly_configured_ = false;\n      break;\n  }\n\n  const auto& uname = header.getUname();\n  uname_.sysname = data_to_str(uname.getSysname());\n  uname_.nodename = data_to_str(uname.getNodename());\n  uname_.release = data_to_str(uname.getRelease());\n  uname_.version = data_to_str(uname.getVersion());\n  uname_.machine = data_to_str(uname.getMachine());\n  uname_.domainname = data_to_str(uname.getDomainname());\n\n  // Set the global time at 0, so that when we tick it for the first\n  // event, it matches the initial global time at recording, 1.\n  global_time = 0;\n}\n\n/**\n * Create a copy of this stream that has exactly the same\n * state as 'other', but for which mutations of this\n * clone won't affect the state of 'other' (and vice versa).\n */\nTraceReader::TraceReader(const TraceReader& other)\n    : TraceStream(other.dir(), other.time()) {\n  for (Substream s = SUBSTREAM_FIRST; s < SUBSTREAM_COUNT; ++s) {\n    readers[s] =\n        unique_ptr<CompressedReader>(new CompressedReader(other.reader(s)));\n  }\n\n  bind_to_cpu = other.bind_to_cpu;\n  trace_uses_cpuid_faulting = other.trace_uses_cpuid_faulting;\n  cpuid_records_ = other.cpuid_records_;\n  raw_recs = other.raw_recs;\n  xcr0_ = other.xcr0_;\n  preload_thread_locals_recorded_ = other.preload_thread_locals_recorded_;\n  rrcall_base_ = other.rrcall_base_;\n  max_virtual_address_size_ = other.max_virtual_address_size_;\n  arch_ = other.arch_;\n  chaos_mode_ = other.chaos_mode_;\n  chaos_mode_known_ = other.chaos_mode_known_;\n  exclusion_range_ = other.exclusion_range_;\n  uname_ = other.uname_;\n  quirks_ = other.quirks_;\n  clear_fip_fdp_ = other.clear_fip_fdp_;\n  required_forward_compatibility_version_ = other.required_forward_compatibility_version_;\n}\n\nTraceReader::~TraceReader() {}\n\nuint64_t TraceReader::uncompressed_bytes() const {\n  uint64_t total = 0;\n  for (Substream s = SUBSTREAM_FIRST; s < SUBSTREAM_COUNT; ++s) {\n    total += reader(s).uncompressed_bytes();\n  }\n  return total;\n}\n\nuint64_t TraceReader::compressed_bytes() const {\n  uint64_t total = 0;\n  for (Substream s = SUBSTREAM_FIRST; s < SUBSTREAM_COUNT; ++s) {\n    total += reader(s).compressed_bytes();\n  }\n  return total;\n}\n\nuint64_t TraceReader::xcr0() const {\n  if (xcr0_) {\n    return xcr0_;\n  }\n  // All valid XCR0 values have bit 0 (x87) == 1. So this is the default\n  // value for traces that didn't store XCR0. Assume that the OS enabled\n  // all CPU-supported XCR0 bits.\n  const CPUIDRecord* record =\n    find_cpuid_record(cpuid_records_, CPUID_GETXSAVE, 0);\n  if (!record) {\n    // No XSAVE support at all on the recording CPU??? Assume just\n    // x87/SSE enabled.\n    return 3;\n  }\n  return (uint64_t(record->out.edx) << 32) | record->out.eax;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/TraceStream.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TRACE_STREAM_H_\n#define RR_TRACE_STREAM_H_\n\n#include <unistd.h>\n\n#include <algorithm>\n#include <map>\n#include <memory>\n#include <set>\n#include <string>\n#include <vector>\n\n#include \"CompressedReader.h\"\n#include \"CompressedWriter.h\"\n#include \"Event.h\"\n#include \"MemoryRange.h\"\n#include \"TaskishUid.h\"\n#include \"TraceFrame.h\"\n#include \"TraceTaskEvent.h\"\n#include \"remote_ptr.h\"\n\nnamespace rr {\n\n/**\n * Bump this when rr changes mean that traces produced by new rr can't be replayed by old rr.\n */\nconst int FORWARD_COMPATIBILITY_VERSION = 3;\n\nstruct CPUIDRecord;\nstruct DisableCPUIDFeatures;\nclass KernelMapping;\nclass RecordTask;\nstruct TraceUuid;\n\nstruct WriteHole {\n  uint64_t offset;\n  uint64_t size;\n};\n\nenum class MemWriteSizeValidation {\n  /* A data record where we _know_ that this data was all written, and it\n   * _must_ be replicated in the replayed process in its entirety */\n  EXACT,\n  /* We recorded a range of memory that's a conservative over-estimate of\n    * what was actually written, and it might not replay cleanly in its\n    * entirety in a replayed process */\n  CONSERVATIVE,\n};\n\n/**\n * TraceStream stores all the data common to both recording and\n * replay.  TraceWriter deals with recording-specific logic, and\n * TraceReader handles replay-specific details.\n *\n * These classes are all in the same .h/.cc file to keep trace reading and\n * writing code together for easier coordination.\n */\nclass TraceStream {\nprotected:\n  typedef std::string string;\n\npublic:\n  struct RawDataMetadata {\n    remote_ptr<void> addr;\n    size_t size;\n    pid_t rec_tid;\n    std::vector<WriteHole> holes;\n    MemWriteSizeValidation size_validation;\n  };\n\n  /**\n   * Update |substreams| and TRACE_VERSION when you update this list.\n   */\n  enum Substream {\n    SUBSTREAM_FIRST,\n    // Substream that stores events (trace frames).\n    EVENTS = SUBSTREAM_FIRST,\n    RAW_DATA,\n    // Substream that stores metadata about files mmap'd during\n    // recording.\n    MMAPS,\n    // Substream that stores task creation and exec events\n    TASKS,\n    SUBSTREAM_COUNT\n  };\n\n  /** Return the directory storing this trace's files. */\n  const string& dir() const { return trace_dir; }\n\n  /** Returns -1 if the CPU isn't/wasn't bound. */\n  int bound_to_cpu() const { return bind_to_cpu; }\n  void set_bound_cpu(int bound) { bind_to_cpu = bound; }\n\n  /**\n   * Return the current \"global time\" (event count) for this\n   * trace.\n   */\n  FrameTime time() const { return global_time; }\n\n  std::string file_data_clone_file_name(const TaskUid& tuid);\n\n  static size_t mmaps_block_size();\n\n  /**\n   * For REMAP_MAPPING maps, the memory contents are preserved so we don't\n   * need a source. We use SOURCE_ZERO for that case and it's ignored.\n   */\n  enum MappedDataSource { SOURCE_TRACE, SOURCE_FILE, SOURCE_ZERO };\n  /**\n   * Where to obtain data for the mapped region.\n   */\n  struct MappedData {\n    FrameTime time;\n    MappedDataSource source;\n    /** Name of file to map the data from. */\n    string file_name;\n    /** Data offset within |file_name|. */\n    size_t data_offset_bytes;\n    /** Original size of mapped file. */\n    size_t file_size_bytes;\n  };\n\nprotected:\n  TraceStream(const string& trace_dir, FrameTime initial_time);\n\n  /**\n   * Return the path of the file for the given substream.\n   */\n  string path(Substream s);\n\n  /**\n   * Return the path of \"version\" file, into which the current\n   * trace format version of rr is stored upon creation of the\n   * trace.\n   */\n  string version_path() const { return trace_dir + \"/version\"; }\n  /**\n   * While the trace is being built, the version file is stored under this name.\n   * When the trace is closed we rename it to the correct name. This lets us\n   * detect incomplete traces.\n   */\n  string incomplete_version_path() const { return trace_dir + \"/incomplete\"; }\n\n  /**\n   * Increment the global time and return the incremented value.\n   */\n  void tick_time() { ++global_time; }\n\n  // Directory into which we're saving the trace files.\n  string trace_dir;\n  // CPU core# that the tracees are bound to\n  int32_t bind_to_cpu;\n\n  // Arbitrary notion of trace time, ticked on the recording of\n  // each event (trace frame).\n  FrameTime global_time;\n};\n\nstruct TraceRemoteFd {\n  pid_t tid;\n  int fd;\n};\n\n/**\n * Trace writing takes the trace directory through a defined set of states.\n * These states can be usefully observed by external programs.\n *\n * -- Initially the trace directory does not exist.\n * -- The trace directory is created. It is empty.\n * -- A file `incomplete` is created in the trace directory. It is empty.\n * -- rr takes an exclusive flock() lock on `incomplete`.\n * -- rr writes data to `incomplete` so it is no longer empty. (At this\n * point the data is undefined.) rr may write to the file at any\n * time during recording.\n * -- At the end of trace recording, rr renames `incomplete` to `version`.\n * At this point the trace is complete and ready to replay.\n * -- rr releases its flock() lock on `version`.\n *\n * Thus:\n * -- If the trace directory contains the file `version` the trace is valid\n * and ready for replay.\n * -- If the trace directory contains the file `incomplete`, and there is an\n * exclusive flock() lock on that file, rr is still recording (or something\n * is messing with us).\n * -- If the trace directory contains the file `incomplete`, that file\n * does not have an exclusive `flock()` lock on it, and the file is non-empty,\n * rr must have died before the recording was complete.\n * -- If the trace directory contains the file `incomplete`, that file\n * does not have an exclusive `flock()` lock on it, and the file is empty,\n * rr has just started recording (or perhaps died during startup).\n * -- If the trace directory does not contain the file `incomplete`,\n * rr has just started recording (or perhaps died during startup) (or perhaps\n * that isn't a trace directory at all).\n */\nclass TraceWriter : public TraceStream {\npublic:\n  bool supports_file_data_cloning() { return supports_file_data_cloning_; }\n\n  /**\n   * Write trace frame to the trace.\n   *\n   * Recording a trace frame has the side effect of ticking\n   * the global time.\n   */\n  void write_frame(RecordTask* t, const Event& ev, const Registers* registers,\n                   const ExtraRegisters* extra_registers);\n\n  enum RecordInTrace { DONT_RECORD_IN_TRACE, RECORD_IN_TRACE };\n  enum MappingOrigin {\n    SYSCALL_MAPPING,\n    // Just memory moved from one place to another, so no recording needed.\n    REMAP_MAPPING,\n    EXEC_MAPPING,\n    PATCH_MAPPING,\n    RR_BUFFER_MAPPING\n  };\n  /**\n   * Write mapped-region record to the trace.\n   * If this returns RECORD_IN_TRACE, then the data for the map should be\n   * recorded in the trace raw-data.\n   */\n  RecordInTrace write_mapped_region(RecordTask* t, const KernelMapping& map,\n                                    const struct stat& stat,\n                                    const std::string &file_name,\n                                    const std::vector<TraceRemoteFd>& extra_fds,\n                                    MappingOrigin origin = SYSCALL_MAPPING,\n                                    bool skip_monitoring_mapped_fd = false);\n\n  static void write_mapped_region_to_alternative_stream(\n      CompressedWriter& mmaps, const MappedData& data, const KernelMapping& km,\n      const std::vector<TraceRemoteFd>& extra_fds, bool skip_monitoring_mapped_fd);\n\n  /**\n   * Write a raw-data record to the trace.\n   * 'addr' is the address in the tracee where the data came from/will be\n   * restored to.\n   */\n  void write_raw(pid_t tid, const void* data, size_t len, remote_ptr<void> addr,\n                 MemWriteSizeValidation size_validation = MemWriteSizeValidation::EXACT) {\n    write_raw_data(data, len);\n    write_raw_header(tid, len, addr, std::vector<WriteHole>(), size_validation);\n  }\n  void write_raw_data(const void* data, size_t len);\n  void write_raw_header(pid_t tid, size_t total_len, remote_ptr<void> addr,\n                        const std::vector<WriteHole>& holes,\n                        MemWriteSizeValidation size_validation = MemWriteSizeValidation::EXACT);\n\n  /**\n   * Write a task event (clone or exec record) to the trace.\n   */\n  void write_task_event(const TraceTaskEvent& event);\n\n  /**\n   * Return true iff all trace files are \"good\".\n   */\n  bool good() const;\n\n  /**\n   * Create a trace where the traces are bound to cpu |bind_to_cpu|. This\n   * data is recorded in the trace. If |bind_to_cpu| is -1 then the tracees\n   * were not bound.\n   * The trace name is determined by |file_name| and _RR_TRACE_DIR (if set)\n   * or by setting -o=<OUTPUT_TRACE_DIR>.\n   */\n  TraceWriter(const std::string& file_name,\n              const string& output_trace_dir, TicksSemantics ticks_semantics);\n\n  /**\n   * Called after the calling thread is actually bound to |bind_to_cpu|.\n   */\n  void setup_cpuid_records(bool has_cpuid_faulting,\n                           const DisableCPUIDFeatures& disable_cpuid_features);\n\n  void set_xsave_fip_fdp_quirk(bool value) { xsave_fip_fdp_quirk_ = value; }\n  void set_fdp_exception_only_quirk(bool value) { fdp_exception_only_quirk_ = value; }\n  void set_clear_fip_fdp(bool value) { clear_fip_fdp_ = value; }\n  bool clear_fip_fdp() const { return clear_fip_fdp_; }\n  void set_chaos_mode(bool value) { chaos_mode = value; }\n  void note_virtual_address_size(uint8_t value) {\n    DEBUG_ASSERT(value < 64);\n    max_virtual_address_size = std::max(max_virtual_address_size, value);\n  }\n\n  enum CloseStatus {\n    /**\n     * Trace completed normally and can be replayed.\n     */\n    CLOSE_OK,\n    /**\n     * Trace completed abnormally due to rr error.\n     */\n    CLOSE_ERROR\n  };\n  /** Call close() on all the relevant trace files.\n   *  Normally this will be called by the destructor. It's helpful to\n   *  call this before a crash that won't call the destructor, to ensure\n   *  buffered data is flushed.\n   */\n  void close(CloseStatus status, const TraceUuid* uuid);\n\n  /**\n   * We got far enough into recording that we should set this as the latest\n   * trace.\n   */\n  void make_latest_trace();\n\n  TicksSemantics ticks_semantics() const { return ticks_semantics_; }\n\nprivate:\n  bool try_hardlink_file(const std::string& real_file_name,\n                         const std::string& access_file_name, std::string* new_name);\n  bool try_clone_file(RecordTask* t, const std::string& real_file_name,\n                      const std::string& access_file_name,\n                      std::string* new_name);\n  bool copy_file(const std::string& real_file_name,\n                 const std::string& access_file_name, std::string* new_name);\n\n  CompressedWriter& writer(Substream s) { return *writers[s]; }\n  const CompressedWriter& writer(Substream s) const { return *writers[s]; }\n\n  std::unique_ptr<CompressedWriter> writers[SUBSTREAM_COUNT];\n  /**\n   * Files that have already been mapped without being copied to the trace,\n   * i.e. that we have already assumed to be immutable.\n   * We store the file name under which we assumed it to be immutable, since\n   * a file may be accessed through multiple names, only some of which\n   * are immutable.\n   */\n  std::map<std::pair<dev_t, ino_t>, std::string> files_assumed_immutable;\n  std::vector<RawDataMetadata> raw_recs;\n  std::vector<CPUIDRecord> cpuid_records;\n  TicksSemantics ticks_semantics_;\n  // Keep the 'incomplete' (later renamed to 'version') file open until we\n  // rename it, so our flock() lock stays held on it.\n  ScopedFd version_fd;\n  uint32_t mmap_count;\n  uint8_t max_virtual_address_size;\n  bool has_cpuid_faulting_;\n  bool xsave_fip_fdp_quirk_;\n  bool fdp_exception_only_quirk_;\n  bool clear_fip_fdp_;\n  bool supports_file_data_cloning_;\n  bool chaos_mode;\n};\n\nstruct TraceUtsName {\n  std::string sysname;\n  std::string nodename;\n  std::string release;\n  std::string version;\n  std::string machine;\n  std::string domainname;\n};\n\nclass TraceReader : public TraceStream {\npublic:\n  /**\n   * A parcel of recorded tracee data.  |data| contains the data read\n   * from |addr| in the tracee. `data` contains zeroes for holes.\n   */\n  struct RawData {\n    std::vector<uint8_t> data;\n    remote_ptr<void> addr;\n    pid_t rec_tid;\n    MemWriteSizeValidation size_validation;\n  };\n\n  /**\n   * Like RawData, but returns positions of holes. `data` excludes holes.\n   */\n  struct RawDataWithHoles {\n    std::vector<uint8_t> data;\n    remote_ptr<void> addr;\n    pid_t rec_tid;\n    std::vector<WriteHole> holes;\n    MemWriteSizeValidation size_validation;\n  };\n\n  /**\n   * Read relevant data from the trace.\n   *\n   * NB: reading a trace frame has the side effect of ticking\n   * the global time to match the time recorded in the trace\n   * frame.\n   *\n   * For all frames before `skip_before` we only fill in the `global_time`\n   * field. (Raw data and maps are still accessible.)\n   */\n  TraceFrame read_frame(FrameTime skip_before = 0);\n\n  /**\n   * Read the next mapped region descriptor and return it.\n   * Also returns where to get the mapped data in |*data|, if it's non-null.\n   * If |found| is non-null, set |*found| to indicate whether a descriptor\n   * was found for the current event.\n   */\n  enum ValidateSourceFile { VALIDATE, DONT_VALIDATE };\n  enum TimeConstraint { CURRENT_TIME_ONLY, ANY_TIME };\n  KernelMapping read_mapped_region(\n      MappedData* data = nullptr, bool* found = nullptr,\n      ValidateSourceFile validate = VALIDATE,\n      TimeConstraint time_constraint = CURRENT_TIME_ONLY,\n      std::vector<TraceRemoteFd>* extra_fds = nullptr,\n      bool* skip_monitoring_mapped_fd = nullptr);\n\n  /**\n   * Read a task event (clone or exec record) from the trace.\n   * Returns a record of type NONE at the end of the trace.\n   * Sets |*time| (if non-null) to the global time of the event.\n   */\n  TraceTaskEvent read_task_event(FrameTime* time = nullptr);\n\n  /**\n   * Reads the next raw data record for last-read frame. If there are no more\n   * raw data records for this frame, return false.\n   * Holes are filled with zeroes in the output buffer.\n   */\n  bool read_raw_data_for_frame(RawData& d);\n\n  /**\n   * Reads the next raw data record for last-read frame. If there are no more\n   * raw data records for this frame, return false.\n   * Returns hole metadata so you can do something smarter with it than\n   * explicitly filling with zeroes.\n   */\n  bool read_raw_data_for_frame_with_holes(RawDataWithHoles& d);\n\n  /**\n   * Like read_raw_data_for_frame, but doesn't actually read the data bytes.\n   * The array is resized but the data is not filled in.\n   */\n  bool read_raw_data_metadata_for_frame(RawDataMetadata& d);\n\n  /**\n   * Return true iff all trace files are \"good\".\n   * for more details.\n   */\n  bool good() const;\n\n  /**\n   * Return true if we're at the end of the trace file.\n   */\n  bool at_end() const { return reader(EVENTS).at_end(); }\n\n  /**\n   * Return the next trace frame, without mutating any stream\n   * state.\n   */\n  TraceFrame peek_frame();\n\n  /**\n   * Restore the state of this to what it was just after\n   * |open()|.\n   */\n  void rewind();\n\n  uint64_t uncompressed_bytes() const;\n  uint64_t compressed_bytes() const;\n\n  /**\n   * Open the trace in 'dir'. When 'dir' is the empty string, open the\n   * latest trace.\n   */\n  TraceReader(const string& dir);\n\n  /**\n   * Create a copy of this stream that has exactly the same\n   * state as 'other', but for which mutations of this\n   * clone won't affect the state of 'other' (and vice versa).\n   */\n  TraceReader(const TraceReader& other);\n\n  ~TraceReader();\n\n  const std::vector<CPUIDRecord>& cpuid_records() const {\n    return cpuid_records_;\n  }\n  bool uses_cpuid_faulting() const { return trace_uses_cpuid_faulting; }\n  uint64_t xcr0() const;\n  bool clear_fip_fdp() const { return clear_fip_fdp_; }\n  // Prior to issue 2370, we did not emit mapping into the trace for the\n  // preload_thread_locals mapping if it was created by a clone(2) without\n  // CLONE_VM. This is true if that has been fixed.\n  bool preload_thread_locals_recorded() const { return preload_thread_locals_recorded_; }\n  const TraceUuid& uuid() const { return *uuid_; }\n\n  TicksSemantics ticks_semantics() const { return ticks_semantics_; }\n\n  double recording_time() const { return monotonic_time_; }\n\n  // The base syscall number for rr syscalls in this trace\n  int rrcall_base() const { return rrcall_base_; }\n  uint32_t syscallbuf_fds_disabled_size() const { return syscallbuf_fds_disabled_size_; }\n  uint32_t syscallbuf_hdr_size() const { return syscallbuf_hdr_size_; }\n\n  SupportedArch arch() const { return arch_; }\n\n  bool chaos_mode(bool* known) const {\n    *known = chaos_mode_known_;\n    return chaos_mode_;\n  }\n  MemoryRange exclusion_range() const {\n    return exclusion_range_;\n  }\n  uint8_t max_virtual_address_size() const {\n    return max_virtual_address_size_;\n  }\n  bool cpu_improperly_configured(bool* known) const {\n    *known = cpu_improperly_configured_known_;\n    return cpu_improperly_configured_;\n  }\n\n  enum TraceQuirks {\n    // Whether the /proc/<pid>/mem calls were explicitly recorded in this trace\n    ExplicitProcMem = 0x1,\n    // Whether this trace requires the special librrpage replay behavior\n    // added in 3aaf792 and later removed.\n    SpecialLibRRpage = 0x2,\n    // Whether this trace recorded extra regs for pkey_alloc(2).\n    PkeyAllocRecordedExtraRegs = 0x4,\n    // Whether this trace forced a tick after buffered syscalls.\n    BufferedSyscallForcedTick = 0x8,\n    // Whether this trace requires globals.is_replay to be toggled.\n    UsesGlobalsInReplay = 0x10,\n  };\n\n  int quirks() const { return quirks_; }\n\n  int required_forward_compatibility_version() const { return required_forward_compatibility_version_; }\n\n  const TraceUtsName& uname() const { return uname_; }\n\nprivate:\n  CompressedReader& reader(Substream s) { return *readers[s]; }\n  const CompressedReader& reader(Substream s) const { return *readers[s]; }\n\n  uint64_t xcr0_;\n  std::unique_ptr<CompressedReader> readers[SUBSTREAM_COUNT];\n  std::vector<CPUIDRecord> cpuid_records_;\n  std::vector<RawDataMetadata> raw_recs;\n  TicksSemantics ticks_semantics_;\n  double monotonic_time_;\n  std::unique_ptr<TraceUuid> uuid_;\n  MemoryRange exclusion_range_;\n  TraceUtsName uname_;\n  bool trace_uses_cpuid_faulting;\n  bool preload_thread_locals_recorded_;\n  bool clear_fip_fdp_;\n  bool chaos_mode_known_;\n  bool chaos_mode_;\n  int rrcall_base_;\n  uint8_t max_virtual_address_size_;\n  bool cpu_improperly_configured_known_;\n  bool cpu_improperly_configured_;\n  uint32_t syscallbuf_fds_disabled_size_;\n  uint32_t syscallbuf_hdr_size_;\n  int required_forward_compatibility_version_;\n  SupportedArch arch_;\n  int quirks_;\n};\n\nstd::string trace_save_dir();\nstd::string resolve_trace_name(const std::string& trace_name);\nstd::string latest_trace_symlink();\n\n} // namespace rr\n\n#endif /* RR_TRACE_STREAM_H_ */\n"
  },
  {
    "path": "src/TraceTaskEvent.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TRACE_TASK_EVENT_H_\n#define RR_TRACE_TASK_EVENT_H_\n\n#include <string>\n#include <vector>\n\n#include \"Event.h\"\n#include \"ExtraRegisters.h\"\n#include \"PerfCounters.h\"\n#include \"TraceFrame.h\"\n#include \"WaitStatus.h\"\n#include \"core.h\"\n\nnamespace rr {\n\nclass TraceReader;\nclass TraceWriter;\n\nclass TraceTaskEvent {\npublic:\n  enum Type {\n    NONE,\n    CLONE, // created by clone(2), fork(2), vfork(2) syscalls\n    EXEC,\n    EXIT,\n    DETACH\n  };\n\n  TraceTaskEvent(Type type = NONE, pid_t tid = 0) : type_(type), tid_(tid) {}\n\n  static TraceTaskEvent for_clone(pid_t tid, pid_t parent_tid, pid_t own_ns_tid,\n                                  int clone_flags) {\n    TraceTaskEvent result(CLONE, tid);\n    result.parent_tid_ = parent_tid;\n    result.own_ns_tid_ = own_ns_tid;\n    result.clone_flags_ = clone_flags;\n    return result;\n  }\n  static TraceTaskEvent for_exec(pid_t tid, const std::string& file_name,\n                                 const std::vector<std::string> cmd_line) {\n    TraceTaskEvent result(EXEC, tid);\n    result.file_name_ = file_name;\n    result.cmd_line_ = cmd_line;\n    result.exe_base_ = nullptr;\n    return result;\n  }\n  static TraceTaskEvent for_exit(pid_t tid, WaitStatus exit_status) {\n    TraceTaskEvent result(EXIT, tid);\n    result.exit_status_ = exit_status;\n    return result;\n  }\n  static TraceTaskEvent for_detach(pid_t tid) {\n    TraceTaskEvent result(DETACH, tid);\n    return result;\n  }\n\n  Type type() const { return type_; }\n  pid_t tid() const { return tid_; }\n  pid_t parent_tid() const {\n    DEBUG_ASSERT(type() == CLONE);\n    return parent_tid_;\n  }\n  pid_t own_ns_tid() const {\n    DEBUG_ASSERT(type() == CLONE);\n    return own_ns_tid_;\n  }\n  int clone_flags() const {\n    DEBUG_ASSERT(type() == CLONE);\n    return clone_flags_;\n  }\n  // Ignores `dirfd` for execveat\n  const std::string& file_name() const {\n    DEBUG_ASSERT(type() == EXEC);\n    return file_name_;\n  }\n  const std::vector<std::string>& cmd_line() const {\n    DEBUG_ASSERT(type() == EXEC);\n    return cmd_line_;\n  }\n  // May be zero when not present in older trace versions\n  remote_ptr<void> exe_base() const {\n    DEBUG_ASSERT(type() == EXEC);\n    return exe_base_;\n  }\n  void set_exe_base(remote_ptr<void> ptr) {\n    DEBUG_ASSERT(type() == EXEC);\n    exe_base_ = ptr;\n  }\n  // May be zero at any time.\n  remote_ptr<void> interp_base() const {\n    DEBUG_ASSERT(type() == EXEC);\n    return interp_base_;\n  }\n  void set_interp_base(remote_ptr<void> ptr) {\n    DEBUG_ASSERT(type() == EXEC);\n    interp_base_ = ptr;\n  }\n  const std::string& interp_name() const {\n    DEBUG_ASSERT(type() == EXEC);\n    return interp_name_;\n  }\n  void set_interp_name(std::string name) {\n    DEBUG_ASSERT(type() == EXEC);\n    interp_name_ = name;\n  }\n  std::vector<uint8_t> pac_data() const {\n    DEBUG_ASSERT(type() == EXEC);\n    return pac_data_;\n  }\n  void set_pac_data(std::vector<uint8_t> data) {\n    DEBUG_ASSERT(type() == EXEC);\n    pac_data_ = data;\n  }\n  WaitStatus exit_status() const {\n    DEBUG_ASSERT(type() == EXIT);\n    return exit_status_;\n  }\n\nprivate:\n  friend class TraceReader;\n  friend class TraceWriter;\n\n  Type type_;\n  pid_t tid_;\n  pid_t parent_tid_;                  // CLONE only\n  pid_t own_ns_tid_;                  // CLONE only\n  int clone_flags_;                   // CLONE only\n  std::string file_name_;             // EXEC only\n  std::vector<std::string> cmd_line_; // EXEC only\n  remote_ptr<void> exe_base_;         // EXEC only\n  remote_ptr<void> interp_base_;      // EXEC only\n  std::string interp_name_;           // EXEC only\n  std::vector<uint8_t> pac_data_;     // EXEC only\n  WaitStatus exit_status_;            // EXIT only\n};\n\n} // namespace rr\n\n#endif /* RR_TRACE_TASK_EVENT_H_ */\n"
  },
  {
    "path": "src/TraceeAttentionSet.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"TraceeAttentionSet.h\"\n\n#include <pthread.h>\n#include <signal.h>\n#include <sys/signalfd.h>\n#include <unistd.h>\n\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic pthread_mutex_t attention_set_lock = PTHREAD_MUTEX_INITIALIZER;\nstatic unordered_set<pid_t>* attention_set;\nstatic sigset_t original_mask;\n\nstatic void* tracee_attention_set_thread(__attribute__((unused)) void* p) {\n  sigset_t set;\n  sigemptyset(&set);\n  sigaddset(&set, SIGCHLD);\n  int fd = signalfd(-1, &set, SFD_CLOEXEC);\n  if (fd < 0) {\n    FATAL() << \"Can't open signalfd\";\n  }\n\n  while (true) {\n    struct signalfd_siginfo si;\n    ssize_t ret = ::read(fd, &si, sizeof(si));\n    if (ret < (ssize_t)sizeof(si)) {\n      FATAL() << \"Failed to read correct number of bytes: \" << ret;\n    }\n\n    pthread_mutex_lock(&attention_set_lock);\n    attention_set->insert(si.ssi_pid);\n    pthread_mutex_unlock(&attention_set_lock);\n  }\n}\n\nvoid TraceeAttentionSet::initialize() {\n  if (attention_set) {\n    return;\n  }\n  attention_set = new unordered_set<pid_t>();\n  // Block all signals so when we create our child thread,\n  // it has all signals blocked. This also initializes original_mask.\n  sigset_t set;\n  sigfillset(&set);\n  sigprocmask(SIG_BLOCK, &set, &original_mask);\n\n  pthread_t thread;\n  pthread_create(&thread, nullptr, tracee_attention_set_thread, nullptr);\n  pthread_setname_np(thread, \"TraceeAttention\");\n\n  // Restore original sigmask but block SIGCHLD in this thread\n  // (and all future spawned threads) so that our attention thread\n  // gets all the SIGCHLD notifications via signalfd.\n  set = original_mask;\n  sigaddset(&set, SIGCHLD);\n  sigprocmask(SIG_SETMASK, &set, nullptr);\n}\n\nunordered_set<pid_t> TraceeAttentionSet::read() {\n  unordered_set<pid_t> result;\n  pthread_mutex_lock(&attention_set_lock);\n  if (!attention_set) {\n    FATAL() << \"TraceeAttentionSet not initialized\";\n  }\n  result = std::move(*attention_set);\n  pthread_mutex_unlock(&attention_set_lock);\n  return result;\n}\n\nvoid TraceeAttentionSet::get_original_sigmask(sigset_t* out) {\n  if (attention_set) {\n    *out = original_mask;\n  } else {\n    sigprocmask(SIG_BLOCK, nullptr, out);\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/TraceeAttentionSet.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_TRACEE_ATTENTION_SET_H_\n#define RR_TRACEE_ATTENTION_SET_H_\n\n#include <signal.h>\n#include <sys/wait.h>\n\n#include <unordered_set>\n\nnamespace rr {\n\n// This class creates a thread that continuously observes SIGCHLD signals\n// and adds their pids to an \"attention set\". This attention set can be\n// read from any thread (which clears the set).\n// In general multiple SIGCHLD signals can arrive between observations,\n// in which case all but the first one will effectively dropped, so this\n// is not a reliable record of which pids SICHLD has been triggered for.\n// These values are only usable as hints.\nclass TraceeAttentionSet {\npublic:\n  // Call this early, before any other threads have been spawned.\n  static void initialize();\n\n  static std::unordered_set<pid_t> read();\n\n  // Return original sigmask (before initialize() was called, if it was)\n  static void get_original_sigmask(sigset_t* out);\n};\n\n}\n\n#endif // RR_TRACEE_ATTENTION_SET_H_\n"
  },
  {
    "path": "src/VirtualPerfCounterMonitor.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"VirtualPerfCounterMonitor.h\"\n\n#include <linux/perf_event.h>\n#include <stdlib.h>\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstd::map<TaskUid, VirtualPerfCounterMonitor*>\n    VirtualPerfCounterMonitor::tasks_with_interrupts =\n        std::map<TaskUid, VirtualPerfCounterMonitor*>();\n\nbool VirtualPerfCounterMonitor::should_virtualize(\n    const struct perf_event_attr& attr) {\n  return PerfCounters::is_rr_ticks_attr(attr);\n}\n\nVirtualPerfCounterMonitor::VirtualPerfCounterMonitor(\n    Task* t, Task* target, const struct perf_event_attr& attr)\n    : initial_ticks(target->tick_count()),\n      target_tuid_(target->tuid()),\n      owner_tid(0),\n      flags(0),\n      sig(0),\n      enabled(false) {\n  ASSERT(t, should_virtualize(attr));\n  if (t->session().is_recording()) {\n    maybe_enable_interrupt(t, attr.sample_period);\n  }\n}\n\nVirtualPerfCounterMonitor::~VirtualPerfCounterMonitor() { disable_interrupt(); }\n\nbool VirtualPerfCounterMonitor::emulate_ioctl(RecordTask* t, uint64_t* result) {\n  switch ((int)t->regs().arg2()) {\n    case PERF_EVENT_IOC_ENABLE:\n      *result = 0;\n      enabled = true;\n      break;\n    case PERF_EVENT_IOC_DISABLE:\n      *result = 0;\n      enabled = false;\n      break;\n    case PERF_EVENT_IOC_RESET: {\n      *result = 0;\n      RecordTask* target = t->session().find_task(target_tuid());\n      initial_ticks = target->tick_count();\n      break;\n    }\n    case PERF_EVENT_IOC_PERIOD: {\n      *result = 0;\n      maybe_enable_interrupt(\n          t, t->read_mem(remote_ptr<uint64_t>(t->regs().arg3())));\n      break;\n    }\n    default:\n      ASSERT(t, false) << \"Unsupported perf event ioctl \"\n                       << HEX((int)t->regs().arg2());\n      break;\n  }\n  return true;\n}\n\nbool VirtualPerfCounterMonitor::emulate_fcntl(RecordTask* t, uint64_t* result) {\n  *result = -(int64_t)EINVAL;\n  switch ((int)t->regs().arg2()) {\n    case F_SETOWN_EX: {\n      auto owner = t->read_mem(remote_ptr<struct f_owner_ex>(t->regs().arg3()));\n      ASSERT(t, owner.type == F_OWNER_TID)\n          << \"Unsupported perf event F_SETOWN_EX type \" << owner.type;\n      ASSERT(t, owner.pid == target_tuid().tid())\n          << \"Perf event F_SETOWN_EX is only supported to the target tid\";\n      owner_tid = owner.pid;\n      *result = 0;\n      break;\n    }\n    case F_SETFL:\n      ASSERT(t, !(t->regs().arg3() & ~O_ASYNC))\n          << \"Unsupported perf event flags \" << HEX((int)t->regs().arg3());\n      flags = (int)t->regs().arg3();\n      *result = 0;\n      break;\n    case F_SETSIG:\n      sig = (int)t->regs().arg3();\n      *result = 0;\n      break;\n    default:\n      ASSERT(t, false) << \"Unsupported perf event fnctl \"\n                       << HEX((int)t->regs().arg2());\n      break;\n  }\n  return true;\n}\n\nbool VirtualPerfCounterMonitor::emulate_read(RecordTask* t,\n                                             const vector<Range>& ranges,\n                                             LazyOffset&, uint64_t* result) {\n  RecordTask* target = t->session().find_task(target_tuid());\n  if (target) {\n    int64_t val;\n    val = target->tick_count() - initial_ticks;\n    *result = t->write_ranges(ranges, &val, sizeof(val));\n  } else {\n    *result = 0;\n  }\n  return true;\n}\n\nvoid VirtualPerfCounterMonitor::maybe_enable_interrupt(Task* t,\n                                                       uint64_t after) {\n  Task* target = t->session().find_task(target_tuid());\n  if (after == 0 || after > 0xffffffff) {\n    return;\n  }\n\n  auto previous =\n      tasks_with_interrupts.insert(std::make_pair(target_tuid(), this));\n  ASSERT(t, previous.second || previous.first->second == this)\n      << \"Multiple virtualized performance counters with interrupts\\n\\tFirst \"\n         \"at \"\n      << previous.first->second << \"\\tSecond at \" << this;\n\n  target_ticks_ = target->tick_count() + after;\n}\n\nvoid VirtualPerfCounterMonitor::disable_interrupt() const {\n  auto found = tasks_with_interrupts.find(target_tuid());\n  if (found == tasks_with_interrupts.end()) {\n    return;\n  }\n\n  if (found->second == this) {\n    tasks_with_interrupts.erase(found);\n  }\n}\n\nvoid VirtualPerfCounterMonitor::synthesize_signal(RecordTask* t) const {\n  // Use NativeArch here because different versions of system headers\n  // have inconsistent field naming.\n  union {\n    NativeArch::siginfo_t native_api;\n    siginfo_t linux_api;\n  } si;\n  memset(&si, 0, sizeof(si));\n  si.native_api.si_signo = sig;\n  si.native_api.si_errno = VIRTUAL_PERF_COUNTER_SIGNAL_SI_ERRNO;\n  LOG(debug) << \"Synthesizing vpmc signal \" << si.linux_api;\n  t->stash_synthetic_sig(si.linux_api, NONDETERMINISTIC_SIG);\n  disable_interrupt();\n}\n\n/* static */\nVirtualPerfCounterMonitor*\nVirtualPerfCounterMonitor::interrupting_virtual_pmc_for_task(Task* t) {\n  auto found = tasks_with_interrupts.find(t->tuid());\n  if (found == tasks_with_interrupts.end()) {\n    return nullptr;\n  }\n\n  return found->second;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/VirtualPerfCounterMonitor.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_VIRTUAL_PERF_COUNTER_MONITOR_H_\n#define RR_VIRTUAL_PERF_COUNTER_MONITOR_H_\n\n#include \"FileMonitor.h\"\n#include \"TaskishUid.h\"\n\nstruct perf_event_attr;\n\nnamespace rr {\n\n/**\n * A FileMonitor to virtualize the performance counter that rr uses to count\n * ticks. Note that this doesn't support interrupts yet so recording rr replays\n * that involve async signals will not work!\n */\nclass VirtualPerfCounterMonitor : public FileMonitor {\npublic:\n  static bool should_virtualize(const struct perf_event_attr& attr);\n\n  VirtualPerfCounterMonitor(Task* t, Task* target,\n                            const struct perf_event_attr& attr);\n  virtual ~VirtualPerfCounterMonitor();\n\n  virtual Type type() override { return VirtualPerfCounter; }\n\n  virtual bool emulate_ioctl(RecordTask* t, uint64_t* result) override;\n  virtual bool emulate_fcntl(RecordTask* t, uint64_t* result) override;\n  virtual bool emulate_read(RecordTask* t, const std::vector<Range>& ranges,\n                            LazyOffset& offset, uint64_t* result) override;\n\n  Ticks target_ticks() const { return target_ticks_; }\n  TaskUid target_tuid() const { return target_tuid_; }\n\n  void synthesize_signal(RecordTask* t) const;\n\n  enum { VIRTUAL_PERF_COUNTER_SIGNAL_SI_ERRNO = -1337 };\n\n  static bool is_virtual_perf_counter_signal(siginfo_t* t) {\n    return t->si_errno == VIRTUAL_PERF_COUNTER_SIGNAL_SI_ERRNO;\n  }\n\n  static VirtualPerfCounterMonitor* interrupting_virtual_pmc_for_task(Task* t);\n\nprivate:\n  void maybe_enable_interrupt(Task* t, uint64_t after);\n  void disable_interrupt() const;\n\n  Ticks initial_ticks;\n  Ticks target_ticks_;\n  TaskUid target_tuid_;\n  pid_t owner_tid;\n  int flags;\n  int sig;\n  bool enabled;\n\n  static std::map<TaskUid, VirtualPerfCounterMonitor*> tasks_with_interrupts;\n};\n\n} // namespace rr\n\n#endif /* RR_VIRTUAL_PERF_COUNTER_MONITOR_H_ */\n"
  },
  {
    "path": "src/WaitManager.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"WaitManager.h\"\n\n#include <errno.h>\n#include <unistd.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n\n#include <map>\n\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nclass WaitState {\npublic:\n  WaitResult wait(const WaitOptions& options, int type);\n  void poll_stops();\nprotected:\n  // Poll child(ren) for a wait status. If tid == -1 we wait for any child, otherwise\n  // we wait for the specific child 'tid' (which may be more efficient, the kernel\n  // has a fast path when the child is specified).\n  // If we got a status, returns the pid_t of the task we got a status for and\n  // stores the status in `status`. If there's no error, there are children, but\n  // none of them are reporting a status, returns 0. Otherwise returns -1 and errno\n  // has been set by waitid.\n  // It is possible for tid to be > 0 and for this to return a different pid, in one case:\n  // when the task changes its tid due to execve handling.\n  // If consume is false we don't consume the event in the kernel.\n  pid_t do_wait(pid_t tid, bool consume, int type, double block_seconds, WaitStatus& status);\n  bool check_status(pid_t tid, bool consume, WaitResult& result);\n\n  map<pid_t, vector<WaitStatus>> stop_statuses;\n};\n\npid_t WaitState::do_wait(pid_t tid, bool consume, int type, double block_seconds, WaitStatus& status) {\n  int options = type | __WALL;\n  if (!consume) {\n    options |= WNOWAIT;\n  }\n  siginfo_t siginfo;\n  memset(&siginfo, 0, sizeof(siginfo));\n  if (block_seconds <= 0.0) {\n    options |= WNOHANG;\n  } else if (block_seconds < static_cast<double>(WAIT_BLOCK_MAX)) {\n    struct itimerval timer = { { 0, 0 }, to_timeval(block_seconds) };\n    if (setitimer(ITIMER_REAL, &timer, nullptr) < 0) {\n      FATAL() << \"Failed to set itimer\";\n    }\n    LOG(debug) << \"  Arming timer for polling\";\n    // XXX what if the timer fires before we get into waitid???\n  }\n  int ret = waitid(tid >= 0 ? P_PID : P_ALL, tid, &siginfo, options);\n  if (ret && errno == EINVAL) {\n    CLEAN_FATAL() << \"waitid(options=\" << options\n      << \") returned EINVAL; rr requires Linux kernel 4.7 or greater\";\n  }\n  if (!(block_seconds <= 0.0) && block_seconds < static_cast<double>(WAIT_BLOCK_MAX)) {\n    int err = errno;\n    struct itimerval timer = { { 0, 0 }, { 0, 0 } };\n    if (setitimer(ITIMER_REAL, &timer, nullptr) < 0) {\n      FATAL() << \"Failed to set itimer\";\n    }\n    LOG(debug) << \"  Disarming timer for polling\";\n    errno = err;\n  }\n  if (!ret) {\n    if (!siginfo.si_pid) {\n      return 0;\n    }\n    status = WaitStatus(siginfo);\n    return siginfo.si_pid;\n  }\n  return -1;\n}\n\nbool WaitState::check_status(pid_t tid, bool consume, WaitResult& result) {\n  map<pid_t, vector<WaitStatus>>::iterator it;\n  if (tid < 0) {\n    it = stop_statuses.begin();\n  } else {\n    it = stop_statuses.find(tid); \n  }\n  if (it != stop_statuses.end()) {\n    result.code = WAIT_OK;\n    result.tid = it->first;\n    result.status = it->second[0];\n    if (consume) {\n      it->second.erase(it->second.begin());\n      if (it->second.empty()) {\n        stop_statuses.erase(it);\n      }\n    }\n    return true;\n  }\n  return false;\n}\n\nWaitResult WaitState::wait(const WaitOptions& options, int type) {\n  WaitResult result;\n  if ((type & WSTOPPED) && check_status(options.tid, options.consume, result)) {\n    return result;\n  }\n  if (!options.can_perform_syscall) {\n    result.code = WAIT_NO_STATUS;\n    return result;\n  }\n\n  pid_t ret = do_wait(options.unblock_on_other_tasks ? -1 : options.tid,\n                      options.consume, type, options.block_seconds,\n                      result.status);\n  if (ret == 0) {\n    result.code = WAIT_NO_STATUS;\n    return result;\n  }\n  if (ret < 0) {\n    if (errno == EINTR) {\n      result.code = WAIT_NO_STATUS;\n      return result;        \n    }\n    if (errno == ECHILD) {\n      result.code = WAIT_NO_CHILD;\n      return result;\n    }\n    FATAL() << \"Unexpected error waiting for \" << options.tid;\n  }\n  // We got a status for some task.\n\n  if (options.unblock_on_other_tasks && options.tid >= 0 &&\n      ret != options.tid) {\n    // We got a status for a non-requested task. Stash it and return.\n    if (result.status.reaped()) {\n      FATAL() << \"Expected a stop!\";\n    }\n    if (options.consume) {\n      // We told the kernel to consume it, so we need to store it here\n      // so we can still return it when required.\n      stop_statuses[ret].push_back(result.status);\n    }\n    result.code = WAIT_NO_STATUS;\n    return result;\n  }\n\n  if (!result.status.reaped() && !(type & WSTOPPED)) {\n    // We got a stop, but we weren't expecting a stop. This happens\n    // because when ptrace is enabled, waitid(WEXITED) still returns\n    // stops as well as exits :-(.\n    if (options.consume) {\n      // We told the kernel to consume it, so we need to store it here\n      // so we can still return it when required.\n      stop_statuses[ret].push_back(result.status);\n    }\n    result.code = WAIT_NO_STATUS;\n    return result;\n  }\n\n  // We got a status that we should return.\n  result.code = WAIT_OK;\n  result.tid = ret;\n  return result;\n}\n\nvoid WaitState::poll_stops() {\n  while (true) {\n    WaitStatus status;\n    pid_t ret = do_wait(-1, true, WSTOPPED, 0, status);\n    if (ret == 0) {\n      return;\n    }\n    if (ret < 0) {\n      if (errno == EINTR || errno == ECHILD) {\n        return;\n      }\n      FATAL() << \"Unexpected error polling for stops\";\n    }\n    // We got a status for some task. Stash it.\n    if (status.reaped()) {\n      FATAL() << \"Expected a stop!\";\n    }\n    stop_statuses[ret].push_back(status);\n  }\n}\n\nstatic WaitState& wait_state() {\n  static WaitState static_state;\n  return static_state;\n}\n\nWaitResult WaitManager::wait_stop(const WaitOptions& options) {\n  return wait_state().wait(options, WSTOPPED);\n}\n\nWaitResult WaitManager::wait_exit(const WaitOptions& options) {\n  if (options.unblock_on_other_tasks || !options.can_perform_syscall) {\n    FATAL() << \"We can't stash exit statuses\";\n  }\n  if (!options.consume && (options.block_seconds > 0 || options.tid < 0)) {\n    // We can't support this; a ptraced child that receives a signal will trigger\n    // a ptrace stop that will be reported even by waitid(WEXITED). If we don't\n    // consume the ptrace stop then we won't be able to wait for the exit.\n    if (options.block_seconds > 0) {\n      FATAL() << \"Blocking non-consuming exit waits not supported\";\n    }\n    FATAL() << \"Non-consuming wait-for-any-process-exit not supported\";\n  }\n  return wait_state().wait(options, WEXITED);\n}\n\nWaitResult WaitManager::wait_stop_or_exit(const WaitOptions& options) {\n  if (options.unblock_on_other_tasks || !options.can_perform_syscall) {\n    FATAL() << \"We can't stash exit statuses\";\n  }\n  return wait_state().wait(options, WSTOPPED | WEXITED);\n}\n\nvoid WaitManager::poll_stops() {\n  wait_state().poll_stops();\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/WaitManager.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_WAIT_MANAGER_H_\n#define RR_WAIT_MANAGER_H_\n\n#include <unordered_map>\n\n#include \"WaitStatus.h\"\n\nnamespace rr {\n\nenum {\n  // Ten years.\n  WAIT_BLOCK_MAX = 315360000\n};\n\n// The problem with waiting for arbitrary tasks is that we'll reap them and that exposes us\n// to pid reuse issues. So we really need to wait for non-exit only and handle exits specially,\n// when we're ready and we can ensure those tasks aren't touched again.\n\nstruct WaitOptions {\n  // Default options: wait for any task, block indefinitely.\n  WaitOptions() :\n      tid(-1),\n      block_seconds(WAIT_BLOCK_MAX),\n      unblock_on_other_tasks(false),\n      consume(true),\n      can_perform_syscall(true) {}\n  // Default options, but wait for a specific task and don't stop\n  // waiting if other tasks return a status.\n  explicit WaitOptions(pid_t tid) :\n      tid(tid),\n      block_seconds(WAIT_BLOCK_MAX),\n      unblock_on_other_tasks(false),\n      consume(true),\n      can_perform_syscall(true) {}\n  // -1 to accept the status of any tid, otherwise returns only the\n  // status of 'tid'.\n  pid_t tid;\n  // Number of seconds we should block waiting for a result.\n  double block_seconds;\n  // True if we should stop blocking and return WAIT_NO_STATUS if,\n  // while blocking, we observe a task other than the requested task(s)\n  // return a status.\n  bool unblock_on_other_tasks;\n  // True if we should consume the wait status. Otherwise we leave it\n  // pending, either in the WaitManager (if it already was in the WaitManager)\n  // or in the kernel itself. Exit status are never stashed in the WaitManager.\n  bool consume;\n  // True if we should allow syscalls, false if we should only return cached\n  // status. If this is false, consume/block_seconds/unblock_on_other_tasks are ignored.\n  bool can_perform_syscall;\n};\n\nenum WaitResultCode {\n  // Got a valid WaitStatus\n  WAIT_OK,\n  // No matching task exists\n  WAIT_NO_CHILD,\n  // There is at least one matching child task but it hasn't reported a wait status.\n  WAIT_NO_STATUS,\n};\nstruct WaitResult {\n  WaitResultCode code;\n  // The tid for which we got a wait status, or -1 if we didn't get one.\n  // If options.tid > 0 and the `options.tid` task changes its tid during the wait call,\n  // e.g. due to execve tid changes, this may not match options.tid.\n  pid_t tid;\n  WaitStatus status;\n};\n\n// All waits must go through methods on this class.\nclass WaitManager {\npublic:\n  // Wait for a WSTOPPED notification.\n  static WaitResult wait_stop(const WaitOptions& options);\n  // Wait for a WEXITED exit notification.\n  // unblock_on_other_tasks must be false. perform_syscall must be true\n  // (we only cache stops).\n  // If `consume` is false then tid must be >= 0 and\n  // blocking must be 0: WEXITED returns stops as well for ptracees, so if there\n  // is a stop and we don't consume it we won't be able to see an exit notification\n  // on that task or a different task.\n  static WaitResult wait_exit(const WaitOptions& options);\n  // Wait for a WSTOPPED or WEXITED notification.\n  // unblock_on_other_tasks must be false. perform_syscall must be true\n  // (we only cache stops).\n  static WaitResult wait_stop_or_exit(const WaitOptions& options);\n\n  // Gather stop notifications from all tasks without blocking.\n  static void poll_stops();\n};\n\n}\n\n#endif // RR_WAIT_MANAGER_H_\n"
  },
  {
    "path": "src/WaitStatus.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"WaitStatus.h\"\n\n#include <sys/types.h>\n#include <sys/wait.h>\n\n#include \"RecordTask.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nWaitStatus::WaitStatus(const siginfo_t &info) : status(0)\n{\n  if (info.si_code == CLD_EXITED) {\n    status = (info.si_status & 0x7f) << 8;\n    return;\n  }\n\n  if (info.si_code == CLD_KILLED || info.si_code == CLD_DUMPED) {\n    status = (info.si_status & 0x7f);\n    if (info.si_code == CLD_DUMPED) {\n      status |= 0x80;\n    }\n    return;\n  }\n\n  DEBUG_ASSERT(info.si_code == CLD_STOPPED || info.si_code == CLD_TRAPPED);\n  status = info.si_status << 8 | 0x7f;\n}\n\nWaitStatus::Type WaitStatus::type() const {\n  if (exit_code() >= 0) {\n    return EXIT;\n  }\n  if (fatal_sig() > 0) {\n    return FATAL_SIGNAL;\n  }\n  if (stop_sig() > 0) {\n    return SIGNAL_STOP;\n  }\n  if (group_stop() > 0) {\n    return GROUP_STOP;\n  }\n  if (is_syscall()) {\n    return SYSCALL_STOP;\n  }\n  if (ptrace_event() > 0) {\n    return PTRACE_EVENT;\n  }\n  FATAL() << \"Status \" << HEX(status) << \" not understood\";\n  return EXIT;\n}\n\nint WaitStatus::exit_code() const {\n  return WIFEXITED(status) ? WEXITSTATUS(status) : -1;\n}\n\nint WaitStatus::fatal_sig() const {\n  return WIFSIGNALED(status) ? WTERMSIG(status) : 0;\n}\n\nbool WaitStatus::stopped() const {\n  // N.B.: infop distinguishes between ptrace and child stops,\n  // but regular waitpid does not.\n  // (info.si_code == CLD_TRAPPED || info.si_code == CLD_TRAPPED)\n  return WIFSTOPPED(status);\n}\n\nint WaitStatus::ptrace_event_code() const {\n  return (status >> 16) & 0xff;\n}\n\nint WaitStatus::stop_sig_code() const {\n  return WSTOPSIG(status);\n}\n\nint WaitStatus::stop_sig() const {\n  if (!stopped() || ptrace_event_code()) {\n    return 0;\n  }\n  int sig = stop_sig_code();\n  if (sig == (SIGTRAP | 0x80)) {\n    return 0;\n  }\n  sig &= ~0x80;\n  return sig ? sig : SIGSTOP;\n}\n\nint WaitStatus::group_stop() const {\n  if (!stopped() || ptrace_event_code() != PTRACE_EVENT_STOP) {\n    return 0;\n  }\n  int sig = stop_sig_code();\n  sig &= ~0x80;\n  return sig ? sig : SIGSTOP;\n}\n\nbool WaitStatus::is_syscall() const {\n  if (!stopped() || ptrace_event_code()) {\n    return 0;\n  }\n  return stop_sig_code() == (SIGTRAP | 0x80);\n}\n\nint WaitStatus::ptrace_event() const {\n  if (!stopped())\n    return 0;\n  int event = ptrace_event_code();\n  return event == PTRACE_EVENT_STOP ? 0 : event;\n}\n\nint WaitStatus::ptrace_signal() const {\n  return stopped() ? (stop_sig_code() & 0x7f) : 0;\n}\n\nWaitStatus WaitStatus::for_exit_code(int code) {\n  DEBUG_ASSERT(code >= 0 && code < 0x100);\n  return WaitStatus(code << 8);\n}\n\nWaitStatus WaitStatus::for_fatal_sig(int sig) {\n  DEBUG_ASSERT(sig >= 1 && sig < 0x80);\n  return WaitStatus(sig);\n}\n\nWaitStatus WaitStatus::for_stop_sig(int sig) {\n  DEBUG_ASSERT(sig >= 1 && sig < 0x80);\n  return WaitStatus((sig << 8) | 0x7f);\n}\n\nWaitStatus WaitStatus::for_group_sig(int sig, RecordTask* t) {\n  DEBUG_ASSERT(sig >= 1 && sig < 0x80);\n  int code = (sig << 8) | 0x7f;\n  if (t->emulated_ptrace_seized) {\n    code |= PTRACE_EVENT_STOP << 16;\n  }\n  return WaitStatus(code);\n}\n\nWaitStatus WaitStatus::for_syscall(RecordTask* t) {\n  int code = (SIGTRAP << 8) | 0x7f;\n  if (t->emulated_ptrace_options & PTRACE_O_TRACESYSGOOD) {\n    code |= 0x80 << 8;\n  }\n  return WaitStatus(code);\n}\n\nWaitStatus WaitStatus::for_ptrace_event(int ptrace_event) {\n  DEBUG_ASSERT(ptrace_event >= 1 && ptrace_event < 0x100);\n  return WaitStatus((ptrace_event << 16) | (SIGTRAP << 8) | 0x7f);\n}\n\ntemplate <typename Arch>\nvoid WaitStatus::fill_siginfo(typename Arch::siginfo_t *si, bool ptracer, unsigned ptrace_options)\n{\n  if (exit_code() >= 0) {\n    si->si_code = CLD_EXITED;\n    si->_sifields._sigchld.si_status_ = exit_code();\n    return;\n  }\n\n  if (fatal_sig()) {\n    // `waitpid`'s status can't distinguish between CLD_KILLED and CLD_DUMPED.\n    // Always use CLD_KILLED for now.\n    si->si_code = is_coredumping_signal(fatal_sig()) ? CLD_DUMPED : CLD_KILLED;\n    si->_sifields._sigchld.si_status_ = fatal_sig();\n    return;\n  }\n\n  if (!ptracer) {\n    DEBUG_ASSERT(!ptrace_event());\n    si->si_code = CLD_STOPPED;\n    si->_sifields._sigchld.si_status_ = stop_sig();\n    return;\n  }\n\n  si->si_code = CLD_TRAPPED;\n  if (is_syscall()) {\n    if (ptrace_options & PTRACE_O_TRACESYSGOOD) {\n      si->_sifields._sigchld.si_status_ = 0x80 | SIGTRAP;\n    } else {\n      si->_sifields._sigchld.si_status_ = SIGTRAP;\n    }\n    return;\n  }\n\n  si->_sifields._sigchld.si_status_ = status >> 8;\n}\n\ntemplate void WaitStatus::fill_siginfo<X86Arch>(X86Arch::siginfo_t*, bool, unsigned);\ntemplate void WaitStatus::fill_siginfo<X64Arch>(X64Arch::siginfo_t*, bool, unsigned);\ntemplate void WaitStatus::fill_siginfo<ARM64Arch>(ARM64Arch::siginfo_t*, bool, unsigned);\n\nostream& operator<<(ostream& stream, WaitStatus status) {\n  stream << HEX(status.get());\n  switch (status.type()) {\n    case WaitStatus::EXIT:\n      stream << \" (EXIT-\" << status.exit_code() << \")\";\n      break;\n    case WaitStatus::FATAL_SIGNAL:\n      stream << \" (FATAL-\" << signal_name(status.fatal_sig()) << \")\";\n      break;\n    case WaitStatus::SIGNAL_STOP:\n      stream << \" (STOP-\" << signal_name(status.stop_sig()) << \")\";\n      break;\n    case WaitStatus::GROUP_STOP:\n      stream << \" (GROUP-STOP-\" << signal_name(status.group_stop()) << \")\";\n      break;\n    case WaitStatus::SYSCALL_STOP:\n      stream << \" (SYSCALL)\";\n      break;\n    case WaitStatus::PTRACE_EVENT:\n      stream << \" (\" << ptrace_event_name(status.ptrace_event()) << \")\";\n      break;\n  }\n  return stream;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/WaitStatus.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_WAIT_STATUS_H_\n#define RR_WAIT_STATUS_H_\n\n#include <signal.h>\n\n#include <memory>\n#include <vector>\n\n#include \"core.h\"\n\nnamespace rr {\n\nclass RecordTask;\n\nclass WaitStatus {\npublic:\n  explicit WaitStatus(int status = 0) : status(status) {}\n  explicit WaitStatus(const siginfo_t &info);\n\n  enum Type {\n    // Task exited normally.\n    EXIT,\n    // Task exited due to fatal signal.\n    FATAL_SIGNAL,\n    // Task is in a signal-delivery-stop.\n    SIGNAL_STOP,\n    // Task is in a group-stop. (See ptrace man page.)\n    // You must use PTRACE_SEIZE to generate PTRACE_EVENT_STOPs, or these\n    // will be treated as STOP_SIGNAL.\n    GROUP_STOP,\n    // Task is in a syscall-stop triggered by PTRACE_SYSCALL\n    // and PTRACE_O_TRACESYSGOOD.\n    SYSCALL_STOP,\n    // Task is in a PTRACE_EVENT stop, except for PTRACE_EVENT_STOP\n    // which is treated as GROUP_STOP.\n    PTRACE_EVENT\n  };\n\n  Type type() const;\n\n  // Exit code if type() == EXIT, otherwise -1.\n  int exit_code() const;\n  // Fatal signal if type() == FATAL_SIGNAL, otherwise zero.\n  int fatal_sig() const;\n  // Stop signal if type() == STOP_SIGNAL, otherwise zero. A zero signal\n  // (rare but observed via PTRACE_INTERRUPT) is converted to SIGSTOP.\n  int stop_sig() const;\n  // Stop signal if type() == GROUP_STOP, otherwise zero. A zero signal\n  // (rare but observed via PTRACE_INTERRUPT) is converted to SIGSTOP.\n  int group_stop() const;\n  bool is_syscall() const;\n  // ptrace event if type() == PTRACE_EVENT, otherwise zero.\n  int ptrace_event() const;\n\n  // For exit_code() and fatal_sig(), returns 0. For all other types\n  // returns the signal involved.\n  int ptrace_signal() const;\n  // True if this status means we reaped the exit status.\n  bool reaped() const { return exit_code() != -1 || fatal_sig() != 0; }\n\n  int get() const { return status; }\n\n  static WaitStatus for_exit_code(int code);\n  static WaitStatus for_fatal_sig(int sig);\n  static WaitStatus for_stop_sig(int sig);\n  static WaitStatus for_group_sig(int sig, RecordTask* t);\n  static WaitStatus for_syscall(RecordTask* t);\n  static WaitStatus for_ptrace_event(int ptrace_event);\n\n  // Fill in the si_status/si_code field of the siginfo_t struct to correspond\n  // this wait status.\n  template <typename Arch>\n  void fill_siginfo(typename Arch::siginfo_t *info, bool ptracer = true,\n                    unsigned ptrace_options = 0);\n\nprivate:\n  bool stopped() const;\n  int ptrace_event_code() const;\n  int stop_sig_code() const;\n  int status;\n};\n\nstd::ostream& operator<<(std::ostream& stream, WaitStatus status);\n\n} // namespace rr\n\n#endif /* RR_WAIT_STATUS_H_ */\n"
  },
  {
    "path": "src/assembly_templates.py",
    "content": "from io import StringIO\nimport sys\n\nclass RawBytes(object):\n    \"\"\"A sequence of literal bytes to appear in an assembly language template.\"\"\"\n    def __init__(self, *bytes):\n        self.bytes = bytes\n\n    def __len__(self):\n        return len(self.bytes)\n\nclass Field(object):\n    \"\"\"A variable field of bytes.\"\"\"\n    def __init__(self, name, byte_length):\n        self.name = name\n        self.byte_length = byte_length\n\n    def __len__(self):\n        return self.byte_length\n\n    def c_type(self):\n        types = { 8: 'uint64_t', 4: 'uint32_t', 2: 'uint16_t', 1: 'uint8_t' }\n        return types[self.byte_length]\n\nclass ShiftField(object):\n    \"\"\"A field embedded at some bit shift offset in another object.\"\"\"\n    def __init__(self, parent, shift, name, byte_length):\n        self.parent = parent\n        self.shift = shift\n        self.name = name\n        self.byte_length = byte_length\n\n    def __len__(self):\n        return len(self.parent)\n\n    def c_type(self):\n        types = { 8: 'uint64_t', 4: 'uint32_t', 2: 'uint16_t', 1: 'uint8_t' }\n        return types[self.byte_length]\n\n    def patch_c_type(self):\n        types = { 8: 'uint64_t', 4: 'uint32_t', 2: 'uint16_t', 1: 'uint8_t' }\n        return types[len(self.parent)]\n\nclass AssemblyTemplate(object):\n    \"\"\"A sequence of RawBytes and Field objects, which can be used to verify\n    that a given sequence of assembly instructions matches the RawBytes while\n    pulling out the Field values for inspection.  Or for creating custom\n    assembly stubs, filling out Fields with runtime-determined values.\"\"\"\n    def __init__(self, *chunks):\n        # Merge consecutive RawBytes elements together for efficiency of\n        # matching and for simplicity of template expansion.\n        merged_chunks = []\n        current_raw_bytes = []\n        for c in chunks:\n            if isinstance(c, Field) or isinstance(c, ShiftField):\n                # Push any raw bytes before this.\n                if current_raw_bytes:\n                    merged_chunks.append(RawBytes(*current_raw_bytes))\n                    current_raw_bytes = []\n                merged_chunks.append(c)\n            else:\n                current_raw_bytes.extend(c.bytes)\n        # Merge in trailing raw bytes.\n        if current_raw_bytes:\n            merged_chunks.append(RawBytes(*current_raw_bytes))\n        self.chunks = merged_chunks\n\n    def fields(self):\n        return [c for c in self.chunks if (isinstance(c, Field) or isinstance(c, ShiftField))]\n\n    def bytes(self):\n        bytes = []\n        for c in self.chunks:\n            if isinstance(c, Field):\n                bytes.extend([0] * len(c))\n            elif isinstance(c, ShiftField):\n                bytes.extend(c.parent.bytes)\n            else:\n                bytes.extend(c.bytes)\n        return bytes\n\ntemplates = {\n    'X86SysenterVsyscallSyscallHook': AssemblyTemplate(\n        RawBytes(0xe9),         # jmp $syscall_hook_trampoline\n        Field('syscall_hook_trampoline', 4),\n    ),\n    'X86SyscallStubExtendedJump': AssemblyTemplate(\n        # This code must match the stubs in syscall_hook.S.\n        RawBytes(0x89, 0x25, 0x08, 0x10, 0x00, 0x70), # movl %esp,(stub_scratch_1)\n        RawBytes(0xBC, 0x12, 0x10, 0x00, 0x70),                   # mov $saved_flags+2,%esp\n        RawBytes(0x66, 0x9c),                                     # pushfw\n        RawBytes(0x8b, 0x25, 0x08, 0x10, 0x00, 0x70),             # movq (stub_scratch_1),%esp\n        RawBytes(0xFF, 0x05, 0x0c, 0x10, 0x00, 0x70), # incl (alt_stack_nesting_level)\n        RawBytes(0x83, 0x3c, 0x25, 0x0c, 0x10, 0x00, 0x70, 0x01), # cmpl 1,(alt_stack_nesting_level)\n        RawBytes(0x75, 0x06),                                     # jne dont_switch\n        RawBytes(0x8b, 0x25, 0x00, 0x10, 0x00, 0x70), # movl (syscallbuf_stub_alt_stack),%esp\n        # dont_switch:\n        RawBytes(0xff, 0x35, 0x08, 0x10, 0x00, 0x70), # pushl (stub_scratch_1)\n        RawBytes(0x68),                               # pushl $return_addr\n        Field('return_addr', 4),\n        RawBytes(0xe9),                               # jmp $trampoline_relative_addr\n        Field('trampoline_relative_addr', 4)\n    ),\n    'X86TrapInstructionStubExtendedJump': AssemblyTemplate(\n        # This code must match the stubs in syscall_hook.S.\n        RawBytes(0x89, 0x25, 0x08, 0x10, 0x00, 0x70), # movl %esp,(stub_scratch_1)\n        RawBytes(0xBC, 0x12, 0x10, 0x00, 0x70),                   # mov $saved_flags+2,%esp\n        RawBytes(0x66, 0x9c),                                     # pushfw\n        RawBytes(0x8b, 0x25, 0x08, 0x10, 0x00, 0x70),             # movq (stub_scratch_1),%esp\n        RawBytes(0xFF, 0x05, 0x0c, 0x10, 0x00, 0x70), # incl (alt_stack_nesting_level)\n        RawBytes(0x83, 0x3c, 0x25, 0x0c, 0x10, 0x00, 0x70, 0x01), # cmpl 1,(alt_stack_nesting_level)\n        RawBytes(0x75, 0x06),                                     # jne dont_switch\n        RawBytes(0x8b, 0x25, 0x00, 0x10, 0x00, 0x70), # movl (syscallbuf_stub_alt_stack),%esp\n        # dont_switch:\n        RawBytes(0xff, 0x35, 0x08, 0x10, 0x00, 0x70), # pushl (stub_scratch_1)\n        RawBytes(0x68),                               # pushl $return_addr\n        Field('return_addr', 4),\n        RawBytes(0xb8),                               # movl $fake_syscall_no,%eax\n        Field('fake_syscall_no', 4),\n        RawBytes(0xe9),                               # jmp $trampoline_relative_addr\n        Field('trampoline_relative_addr', 4)\n    ),\n    'X86SyscallStubRestore': AssemblyTemplate(\n        RawBytes(0xe9),                               # jmp $trampoline_relative_addr\n        Field('trampoline_relative_addr', 4)\n    ),\n    'X64CallMonkeypatch': AssemblyTemplate(\n        RawBytes(0xe8),         # call $relative_addr\n        Field('relative_addr', 4),\n    ),\n    'X64JumpMonkeypatch': AssemblyTemplate(\n        RawBytes(0xe9),         # jmp $relative_addr\n        Field('relative_addr', 4),\n    ),\n    'X64AbsoluteIndirectCallMonkeypatch': AssemblyTemplate(\n        RawBytes(0xff, 0x14, 0x25),     # call [absolute_addr]\n        Field('absolute_addr', 4),\n    ),\n    'X64SyscallStubExtendedJump': AssemblyTemplate(\n        # This code must match the stubs in syscall_hook.S.\n        RawBytes(0x48, 0x89, 0x24, 0x25, 0x10, 0x10, 0x00, 0x70), # movq %rsp,(stub_scratch_1)\n        RawBytes(0xBC, 0x1e, 0x10, 0x00, 0x70),                   # mov $saved_flags+2,%esp\n        RawBytes(0x66, 0x9c),                                     # pushfw\n        RawBytes(0x48, 0x8b, 0x24, 0x25, 0x10, 0x10, 0x00, 0x70), # movq (stub_scratch_1),%rsp\n        RawBytes(0xFF, 0x04, 0x25, 0x18, 0x10, 0x00, 0x70),       # incl (alt_stack_nesting_level)\n        RawBytes(0x83, 0x3c, 0x25, 0x18, 0x10, 0x00, 0x70, 0x01), # cmpl 1,(alt_stack_nesting_level)\n        RawBytes(0x75, 0x0a),                                     # jne dont_switch\n        RawBytes(0x48, 0x8b, 0x24, 0x25, 0x00, 0x10, 0x00, 0x70), # movq (syscallbuf_stub_alt_stack),%rsp\n        RawBytes(0xeb, 0x07),                                     # jmp after_adjust\n        # dont_switch:\n        RawBytes(0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00), # subq $256, %rsp\n        # after adjust\n        RawBytes(0xff, 0x34, 0x25, 0x10, 0x10, 0x00, 0x70), # pushq (stub_scratch_1)\n        RawBytes(0x50),                                     # pushq rax (just to make space for the next 2 instructions)\n        RawBytes(0xc7, 0x04, 0x24),                         # movl $return_addr_lo,(%rsp)\n        Field('return_addr_lo', 4),\n        RawBytes(0xc7, 0x44, 0x24, 0x04),                   # movl $return_addr_hi,(%rsp+4)\n        Field('return_addr_hi', 4),\n        RawBytes(0xff, 0x25, 0x00, 0x00, 0x00, 0x00),       # jmp *0(%rip)\n        Field('jump_target', 8),\n    ),\n    'X64TrapInstructionStubExtendedJump': AssemblyTemplate(\n        # This code must match the stubs in syscall_hook.S.\n        RawBytes(0x48, 0x89, 0x24, 0x25, 0x10, 0x10, 0x00, 0x70), # movq %rsp,(stub_scratch_1)\n        RawBytes(0xBC, 0x1e, 0x10, 0x00, 0x70),                   # mov $saved_flags+2,%esp\n        RawBytes(0x66, 0x9c),                                     # pushfw\n        RawBytes(0x48, 0x8b, 0x24, 0x25, 0x10, 0x10, 0x00, 0x70), # movq (stub_scratch_1),%rsp\n        RawBytes(0xFF, 0x04, 0x25, 0x18, 0x10, 0x00, 0x70),       # incl (alt_stack_nesting_level)\n        RawBytes(0x83, 0x3c, 0x25, 0x18, 0x10, 0x00, 0x70, 0x01), # cmpl 1,(alt_stack_nesting_level)\n        RawBytes(0x75, 0x0a),                                     # jne dont_switch\n        RawBytes(0x48, 0x8b, 0x24, 0x25, 0x00, 0x10, 0x00, 0x70), # movq (syscallbuf_stub_alt_stack),%rsp\n        RawBytes(0xeb, 0x07),                                     # jmp after_adjust\n        # dont_switch:\n        RawBytes(0x48, 0x81, 0xec, 0x00, 0x01, 0x00, 0x00), # subq $256, %rsp\n        # after adjust\n        RawBytes(0xff, 0x34, 0x25, 0x10, 0x10, 0x00, 0x70), # pushq (stub_scratch_1)\n        RawBytes(0x50),                                     # pushq rax (just to make space for the next 2 instructions)\n        RawBytes(0xc7, 0x04, 0x24),                         # movl $return_addr_lo,(%rsp)\n        Field('return_addr_lo', 4),\n        RawBytes(0xc7, 0x44, 0x24, 0x04),                   # movl $return_addr_hi,(%rsp+4)\n        Field('return_addr_hi', 4),\n        RawBytes(0xb8),                                     # movl $fake_syscall_no,%eax\n        Field('fake_syscall_no', 4),\n        RawBytes(0xff, 0x25, 0x00, 0x00, 0x00, 0x00),       # jmp *0(%rip)\n        Field('jump_target', 8),\n    ),\n    'X64SyscallStubRestore': AssemblyTemplate(\n        RawBytes(0xff, 0x25, 0x00, 0x00, 0x00, 0x00),       # jmp *0(%rip)\n        Field('return_addr', 8),\n    ),\n    'X64DLRuntimeResolve': AssemblyTemplate(\n        RawBytes(0x53),                   # push %rbx\n        RawBytes(0x48, 0x89, 0xe3),       # mov %rsp,%rbx\n        RawBytes(0x48, 0x83, 0xe4, 0xf0), # and $0xfffffffffffffff0,%rsp\n    ),\n    'X64DLRuntimeResolve2': AssemblyTemplate(\n        RawBytes(0x53),                   # push %rbx\n        RawBytes(0x48, 0x89, 0xe3),       # mov %rsp,%rbx\n        RawBytes(0x48, 0x83, 0xe4, 0xc0), # and $0xffffffffffffffc0,%rsp\n    ),\n    'X64EndBr': AssemblyTemplate(\n        RawBytes(0xf3, 0x0f, 0x1e, 0xfa)\n    ),\n    'X86EndBr': AssemblyTemplate(\n        RawBytes(0xf3, 0x0f, 0x1e, 0xfb)\n    ),\n    'X64VSyscallEntry': AssemblyTemplate(\n        RawBytes(0x48, 0xc7, 0xc0), # movq $[addr], %rax\n        Field('addr', 4),\n        RawBytes(0xff, 0xd0) # callq *%rax\n    ),\n    'X64VSyscallReplacement': AssemblyTemplate(\n        RawBytes(0x48, 0xc7, 0xc0), # movq $[syscallno], %rax\n        Field('syscallno', 4),\n        RawBytes(0x0f, 0x05) # syscall\n    ),\n}\n\ndef byte_array_name(name):\n    return '%s_bytes' % name\n\ndef generate_match_method(byte_array, template):\n    s = StringIO()\n    fields = template.fields()\n    field_types = [f.c_type() for f in fields]\n    field_names = [f.name for f in fields]\n    args = ', ' + ', '.join(\"%s* %s\" % (t, n) for t, n in zip(field_types, field_names)) \\\n           if fields else ''\n\n    s.write('  static bool match(const uint8_t* buffer %s) {\\n' % (args,))\n    offset = 0\n    for chunk in template.chunks:\n        if isinstance(chunk, Field):\n            field_name = chunk.name\n            s.write('    memcpy(%s, &buffer[%d], sizeof(*%s));\\n'\n                    % (field_name, offset, field_name))\n        elif isinstance(chunk, ShiftField):\n            s.write('    (void)%s;' % chunk.name)\n            s.write('    assert(0 && \"Matching not implemented for ShiftField\");')\n        else:\n            s.write('    if (memcmp(&buffer[%d], &%s[%d], %d) != 0) { return false; }\\n'\n                    % (offset, byte_array, offset, len(chunk)))\n        offset += len(chunk)\n    s.write('    return true;\\n')\n    s.write('  }')\n    return s.getvalue()\n\ndef generate_substitute_chunk(s, chunk, byte_array, offset):\n    if isinstance(chunk, Field):\n        field_name = chunk.name\n        s.write('    memcpy(&buffer[%d], &%s, sizeof(%s));\\n'\n                % (offset, field_name, field_name))\n    elif isinstance(chunk, ShiftField):\n        generate_substitute_chunk(s, chunk.parent, byte_array, offset);\n        typ = chunk.patch_c_type()\n        field_name = chunk.name\n        s.write('    *((%s*)&buffer[%d]) |= (((%s)%s)<<%d);\\n'\n                % (typ, offset, typ, field_name, chunk.shift))\n    else:\n        s.write('    memcpy(&buffer[%d], &%s[%d], %d);\\n'\n                % (offset, byte_array, offset, len(chunk)))\n    offset += len(chunk)\n    return offset\n\ndef generate_substitute_method(byte_array, template):\n    s = StringIO()\n    fields = template.fields()\n    field_types = [f.c_type() for f in fields]\n    field_names = [f.name for f in fields]\n    args = ', ' + ', '.join(\"%s %s\" % (t, n) for t, n in zip(field_types, field_names)) \\\n           if fields else ''\n\n    s.write('  static void substitute(uint8_t* buffer %s) {\\n' % (args,))\n    offset = 0\n    for chunk in template.chunks:\n        offset = generate_substitute_chunk(s, chunk, byte_array, offset)\n    s.write('  }')\n    return s.getvalue()\n\ndef generate_field_end_methods(byte_array, template):\n    s = StringIO()\n    offset = 0\n    for chunk in template.chunks:\n        offset += len(chunk)\n        if isinstance(chunk, Field):\n            s.write('  static const size_t %s_end = %d;\\n' % (chunk.name, offset))\n    return s.getvalue()\n\ndef generate_size_member(byte_array):\n    s = StringIO()\n    s.write('  static const size_t size = sizeof(%s);' % byte_array)\n    return s.getvalue()\n\ndef generate(f):\n    # Raw bytes.\n    for name, template in templates.items():\n        bytes = template.bytes()\n        f.write('static const uint8_t %s[] = { %s };\\n'\n                % (byte_array_name(name), ', '.join(['0x%x' % b for b in bytes])))\n    f.write('\\n')\n\n    # Objects representing assembly templates.\n    for name, template in templates.items():\n        byte_array = byte_array_name(name)\n        f.write(\"\"\"class %(class_name)s {\npublic:\n%(match_method)s\n\n%(substitute_method)s\n\n%(field_end_methods)s\n%(size_member)s\n};\n\"\"\" % { 'class_name': name,\n        'match_method': generate_match_method(byte_array, template),\n        'substitute_method': generate_substitute_method(byte_array, template),\n        'field_end_methods': generate_field_end_methods(byte_array, template),\n        'size_member': generate_size_member(byte_array), })\n        f.write('\\n\\n')\n"
  },
  {
    "path": "src/audit/rtld-audit.c",
    "content": "#include \"stap-note-iter.h\"\n#include \"rtld-audit.h\"\n#include <stdio.h>\n#include <stdlib.h>\n#include <assert.h>\n#include <string.h>\n#define RR_IMPLEMENT_AUDIT\n#include \"../preload/preload_interface.h\"\n\n/* Some notes about audit libraries:\n *\n * Due to some libpthread bugs[0][1] (and probably others in other libraries)\n * not everything is safe to call from here. In particular, anything that calls\n * _dlerror_run or __dlerror (i.e., most/all of the public dlfcn functions)\n * will cause a TLS slot to be allocated more than once. Make sure nothing\n * calls pthread_key_create() outside of the main link namespace.\n *\n * Since gdb lacks support for multiple link namespaces[2], no debugging\n * information is available for audit libraries in gdb sessions by default. To\n * avoid debugging unannotated disassembly, we have to inform gdb about the\n * other libraries:\n *  - Run rr-record with '-v LD_DEBUG=files'. This will present output in the form\n *      <pid>:      file=libfoo.so [<link map id>];  needed by bar [<link map id>]\n *      <pid>:      file=libfoo.so [<link map id>];  generating link map\n *      <pid>:        dynamic: 0xxxxxxxxxxxxxxxxx  base: 0xxxxxxxxxxxxxxxxx  size:  0xxxxxxxxxxxxxxxxx\n *      <pid>:        entry:   0xxxxxxxxxxxxxxxxx  phdr: 0xxxxxxxxxxxxxxxxx  phnum:                 XX\n *    We're interested in entries with link map ID 1, assuming librraudit is\n *    first in the audit library list.\n *  - Load the library into gdb:\n *      (rr) add-symbol-file /path/to/libfoo.so -o <base address>\n *    Where <base address> is the value labelled 'base' above.\n *\n * [0]: https://sourceware.org/bugzilla/show_bug.cgi?id=24773#c1\n * [1]: https://sourceware.org/bugzilla/show_bug.cgi?id=24776\n * [2]: https://sourceware.org/bugzilla/show_bug.cgi?id=15971\n */\n\ntypedef struct {\n  uintptr_t start, end;\n} SemaphoreAddrRange;\n\nextern __attribute__((visibility(\"hidden\")))\nlong _raw_syscall(int syscallno, long a0, long a1, long a2,\n                  long a3, long a4, long a5,\n                  void* syscall_instruction,\n                  long stack_param_1, long stack_param_2);\n\nbool rr_audit_debug;\n\nunsigned la_version(unsigned version) {\n  rr_audit_debug = !!getenv(\"RR_AUDIT_DEBUG\");\n  return version;\n}\n\nstatic void semaphore_addr_range_init(SemaphoreAddrRange* range) {\n  range->start = 0;\n  range->end = 0;\n}\n\nstatic void semaphore_addr_range_init_single(SemaphoreAddrRange* range,\n                                             uintptr_t addr) {\n  range->start = addr;\n  range->end = addr + sizeof(uint16_t);\n}\n\nstatic bool semaphore_addr_range_is_valid(const SemaphoreAddrRange* range) {\n  return range->end > range->start;\n}\n\nstatic bool semaphore_addr_range_contains(const SemaphoreAddrRange* range,\n                                          uintptr_t addr) {\n  return addr >= range->start && addr < range->end;\n}\n\nstatic bool semaphore_addr_range_contiguous(const SemaphoreAddrRange* range,\n                                            uintptr_t addr) {\n  return addr + sizeof(uint16_t) == range->start || addr == range->end;\n}\n\nstatic void semaphore_addr_range_expand(SemaphoreAddrRange* range,\n                                        uintptr_t addr) {\n  if (addr < range->start) {\n    range->start = addr;\n  }\n  if (addr + sizeof(uint16_t) > range->end) {\n    range->end = addr + sizeof(uint16_t);\n  }\n}\n\nstatic void semaphore_addr_range_submit(const SemaphoreAddrRange* range,\n                                        int syscallno) {\n  if (rr_audit_debug) {\n    fprintf(stderr,\n            \"Submitting STap semaphore range: \"\n              \"0x%\" PRIxELFADDR \"-0x%\" PRIxELFADDR \"\\n\",\n            range->start, range->end);\n  }\n  _raw_syscall(syscallno,\n               range->start, range->end,\n               0, 0, 0, 0,\n               RR_PAGE_SYSCALL_TRACED,\n               0, 0);\n}\n\nstatic void semaphore_addr_range_handle_add(SemaphoreAddrRange* range,\n                                            ElfW(Addr) address,\n                                            int submit_syscallno) {\n  if (semaphore_addr_range_contiguous(range, address)) {\n    semaphore_addr_range_expand(range, address);\n  } else {\n    if (semaphore_addr_range_is_valid(range)) {\n      semaphore_addr_range_submit(range, submit_syscallno);\n    }\n    semaphore_addr_range_init_single(range, address);\n  }\n}\n\nunsigned la_objopen(struct link_map* map,\n                    Lmid_t lmid,\n                    uintptr_t* cookie __attribute__((unused))) {\n  StapNoteIter iter;\n  ElfStapNote note;\n  SemaphoreAddrRange range;\n\n  if (lmid != LM_ID_BASE) {\n    return 0;\n  }\n\n  if (rr_audit_debug) {\n    fprintf(stderr,\n            \"Processing STap semaphores for loaded object: %s\\n\",\n            map->l_name);\n  }\n\n  semaphore_addr_range_init(&range);\n  stap_note_iter_init(&iter, map);\n  while (stap_note_iter_next(&iter, &note)) {\n    if (note.semaphore_address &&\n        !semaphore_addr_range_contains(&range, note.semaphore_address)) {\n      uint16_t* semaphore = (void*) note.semaphore_address;\n      if (rr_audit_debug) {\n        fprintf(stderr,\n                \"Incrementing STap semaphore for %s:%s at \"\n                  \"0x%\" PRIxELFADDR \" (was: %u)\\n\",\n                note.provider_name, note.probe_name,\n                note.semaphore_address,\n                *semaphore);\n      }\n      (*semaphore)++;\n      semaphore_addr_range_handle_add(&range,\n                                      note.semaphore_address,\n                                      SYS_rrcall_notify_stap_semaphore_added);\n    }\n  }\n  stap_note_iter_release(&iter);\n\n  if (semaphore_addr_range_is_valid(&range)) {\n    semaphore_addr_range_submit(&range, SYS_rrcall_notify_stap_semaphore_added);\n  }\n\n  return 0;\n}\n\nunsigned la_objclose(uintptr_t* cookie) {\n  StapNoteIter iter;\n  ElfStapNote note;\n  SemaphoreAddrRange range;\n\n  /* The default value of cookie is the address of the link_map structure.\n   * Since we don't modify the value in la_objopen, this should still be its\n   * value. */\n  const struct link_map* map = (void*) *cookie;\n\n  /* ld.so never has its cookie value initialised, so map will be NULL.\n   * However, none of its probes have associated semaphores so we can just\n   * ignore it. */\n  if (!map) {\n    return 0;\n  }\n\n  if (rr_audit_debug) {\n    fprintf(stderr,\n            \"Processing STap semaphores for closing object: %s\\n\",\n            map->l_name);\n  }\n\n  semaphore_addr_range_init(&range);\n  stap_note_iter_init(&iter, map);\n  while (stap_note_iter_next(&iter, &note)) {\n    if (note.semaphore_address &&\n        !semaphore_addr_range_contains(&range, note.semaphore_address)) {\n      uint16_t* semaphore = (void*) note.semaphore_address;\n      if (rr_audit_debug) {\n        fprintf(stderr,\n                \"Decrementing STap semaphore for %s:%s at \"\n                  \"0x%\" PRIxELFADDR \" (was: %u)\\n\",\n                note.provider_name, note.probe_name,\n                note.semaphore_address,\n                *semaphore);\n      }\n      assert(*semaphore != 0);\n      (*semaphore)--;\n      semaphore_addr_range_handle_add(&range,\n                                      note.semaphore_address,\n                                      SYS_rrcall_notify_stap_semaphore_removed);\n    }\n  }\n  stap_note_iter_release(&iter);\n\n  if (semaphore_addr_range_is_valid(&range)) {\n    semaphore_addr_range_submit(&range,\n                                SYS_rrcall_notify_stap_semaphore_removed);\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/audit/rtld-audit.h",
    "content": "#ifndef __RR_RTLD_AUDIT_H__\n#define __RR_RTLD_AUDIT_H__\n\n#include <stdbool.h>\n#include <inttypes.h>\n#include <elf.h>\n\n#define PRIxELFADDR _PRIxELFADDR(PRIx, __ELF_NATIVE_CLASS)\n#define _PRIxELFADDR(f, w) _PRIxELFADDR_1(f, w)\n#define _PRIxELFADDR_1(f, w) f##w\n\nextern bool rr_audit_debug;\n\n#endif\n"
  },
  {
    "path": "src/audit/stap-note-iter.c",
    "content": "#include \"stap-note-iter.h\"\n#include \"rtld-audit.h\"\n#include <stdio.h>\n#include <errno.h>\n#include <string.h>\n#include <assert.h>\n#include <fcntl.h>\n#include <sys/mman.h>\n#include <unistd.h>\n\n/* For more information about what's going on in here, see\n * https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation */\n\n#define ALIGN_UP(x, p2) \\\n  (((x) & ((p2) - 1)) == 0 ? (x) : ((x) + (p2)) & ~((p2) - 1))\n\nstatic void* stap_note_iter_map(StapNoteIter* self,\n                                size_t offset, size_t size) {\n  void* map;\n  size_t requested_offset = offset;\n  size_t slack;\n\n  if (self->fd == -1) {\n    const char* path = self->map->l_name;\n\n    if (*path == '\\0') {\n      path = \"/proc/self/exe\";\n    }\n\n    if ((self->fd = open(path, O_RDONLY)) == -1) {\n      if (rr_audit_debug) {\n        fprintf(stderr, \"Failed to open '%s': %s\\n\", path, strerror(errno));\n      }\n      return NULL;\n    }\n  }\n\n  offset &= ~(sysconf(_SC_PAGE_SIZE) - 1);\n  slack = requested_offset - offset;\n  size += slack;\n  map = mmap(NULL, size, PROT_READ, MAP_SHARED, self->fd, offset);\n  if (map == MAP_FAILED) {\n    if (rr_audit_debug) {\n      fprintf(stderr,\n              \"Failed to map 0x%\" PRIxELFADDR \"+0x%\" PRIxELFADDR\n                \" from '%s': %s\\n\",\n              offset, size,\n              self->map->l_name,\n              strerror(errno));\n    }\n    return NULL;\n  }\n\n  return (char*) map + slack;\n}\n\nstatic void stap_note_iter_unmap(StapNoteIter* self __attribute__((unused)),\n                                 void* data, size_t size) {\n  uintptr_t data_addr = (uintptr_t) data;\n  void* page = (void*) (data_addr & ~(sysconf(_SC_PAGE_SIZE) - 1));\n  size += (char*) data - (char*) page;\n  munmap(page, size);\n}\n\nvoid stap_note_iter_init(StapNoteIter* self, const struct link_map* map) {\n  const ElfW(Ehdr)* ehdr;\n  const ElfW(Shdr) *shstrtab_hdr, *shdr_iter;\n  const char* shstrtab;\n\n  memset(self, '\\0', sizeof(*self));\n  self->fd = -1;\n\n  self->map = map;\n\n  ehdr = stap_note_iter_map(self, 0, sizeof(*ehdr));\n  if (!ehdr) {\n    if (rr_audit_debug) {\n      fprintf(stderr, \"Mapping ELF header for '%s' failed\\n\", map->l_name);\n    }\n    return;\n  }\n\n  assert(ehdr->e_shentsize == sizeof(ElfW(Shdr)));\n\n  self->shdrs = stap_note_iter_map(self,\n                                   ehdr->e_shoff,\n                                   ehdr->e_shnum * sizeof(ElfW(Shdr)));\n  if (!self->shdrs) {\n    if (rr_audit_debug) {\n      fprintf(stderr, \"Mapping section headers for '%s' failed\\n\", map->l_name);\n    }\n    stap_note_iter_unmap(self, (void*) ehdr, sizeof(*ehdr));\n    return;\n  }\n\n  self->shdr_iter = self->shdrs;\n  self->shdr_end = self->shdrs + ehdr->e_shnum;\n\n  assert(ehdr->e_shstrndx < ehdr->e_shnum);\n  shstrtab_hdr = self->shdrs + ehdr->e_shstrndx;\n  stap_note_iter_unmap(self, (void*) ehdr, sizeof(*ehdr));\n\n  shstrtab = stap_note_iter_map(self,\n                                shstrtab_hdr->sh_offset,\n                                shstrtab_hdr->sh_size);\n  if (!shstrtab) {\n    if (rr_audit_debug) {\n      fprintf(stderr,\n              \"Mapping section string table for '%s' failed\\n\",\n              map->l_name);\n    }\n    return;\n  }\n\n  /* STap notes store the link-time memory address of the .stapsdt.base section\n   * within the note, allowing us to relocate addresses in the note by finding\n   * the difference between this value and the real run-time address of the\n   * section. */\n  for (shdr_iter = self->shdrs; shdr_iter < self->shdr_end; shdr_iter++) {\n    if (strcmp(shstrtab + shdr_iter->sh_name, \".stapsdt.base\") == 0) {\n      break;\n    }\n  }\n\n  if (shdr_iter < self->shdr_end) {\n    self->stapbase = self->map->l_addr + shdr_iter->sh_addr;\n  }\n\n  stap_note_iter_unmap(self, (void*) shstrtab, shstrtab_hdr->sh_size);\n}\n\nbool stap_note_iter_next(StapNoteIter* self, ElfStapNote* out_note) {\n  /* did the initialisation fail? */\n  if (!self->stapbase) {\n    return false;\n  }\n\n  if (!self->note_data) {\n    /* ran out of note data, mmap the next note section */\n    for (; self->shdr_iter < self->shdr_end; self->shdr_iter++) {\n      if (self->shdr_iter->sh_type == SHT_NOTE) {\n        break;\n      }\n    }\n\n    if (self->shdr_iter == self->shdr_end) {\n      return false;\n    }\n    assert(self->shdr_iter < self->shdr_end);\n    assert(self->shdr_iter->sh_type == SHT_NOTE);\n\n    self->note_data = stap_note_iter_map(self,\n                                         self->shdr_iter->sh_offset,\n                                         self->shdr_iter->sh_size);\n    if (!self->note_data) {\n      if (rr_audit_debug) {\n        fprintf(stderr, \"Mapping note data failed\\n\");\n      }\n      return false;\n    }\n  }\n\n  while (self->note_data_offset + sizeof(ElfW(Nhdr))\n          < self->shdr_iter->sh_size) {\n    const ElfW(Nhdr)* nhdr;\n    const char* name = NULL;\n    const void* desc = NULL;\n\n    nhdr = (void*) ((char*) self->note_data + self->note_data_offset);\n    self->note_data_offset += sizeof(*nhdr);\n\n    if (nhdr->n_namesz) {\n      name = (char*) self->note_data + self->note_data_offset;\n      self->note_data_offset += ALIGN_UP(nhdr->n_namesz, 4);\n    }\n\n    if (nhdr->n_descsz) {\n      desc = (char*) self->note_data + self->note_data_offset;\n      self->note_data_offset += ALIGN_UP(nhdr->n_descsz, 4);\n    }\n\n    if (!name || strcmp(name, \"stapsdt\") != 0 || nhdr->n_type != 3) {\n      continue;\n    }\n\n    out_note->probe_address = *(ElfW(Addr)*) desc;\n    desc = (char*) desc + sizeof (ElfW(Addr));\n    out_note->base_address = *(ElfW(Addr)*) desc;\n    desc = (char*) desc + sizeof (ElfW(Addr));\n    out_note->semaphore_address = *(ElfW(Addr)*) desc;\n    desc = (char*) desc + sizeof (ElfW(Addr));\n\n    /* relocate addresses */\n    out_note->probe_address += self->stapbase - out_note->base_address;\n    if (out_note->semaphore_address) {\n      out_note->semaphore_address += self->stapbase - out_note->base_address;\n    }\n\n    out_note->provider_name = desc;\n    desc = out_note->provider_name + strlen(out_note->provider_name) + 1;\n    out_note->probe_name = desc;\n    desc = out_note->probe_name + strlen(out_note->probe_name) + 1;\n    out_note->argument_format = desc;\n\n    return true;\n  }\n\n  /* We've exhausted the note data in the currently mapped section. Unmap it\n   * and try again with the next note section. */\n  stap_note_iter_unmap(self, self->note_data, self->shdr_iter->sh_size);\n  self->shdr_iter++;\n  self->note_data = NULL;\n  self->note_data_offset = 0;\n  return stap_note_iter_next(self, out_note);\n}\n\nvoid stap_note_iter_release(StapNoteIter* self) {\n  if (self->note_data) {\n    stap_note_iter_unmap(self, self->note_data, self->shdr_iter->sh_size);\n  }\n  if (self->shdrs) {\n    stap_note_iter_unmap(self,\n                         (void*) self->shdrs,\n                         (char*) self->shdr_end - (char*) self->shdrs);\n  }\n  if (self->fd != -1) {\n    close(self->fd);\n  }\n  memset(self, '\\0', sizeof(*self));\n  self->fd = -1;\n}\n"
  },
  {
    "path": "src/audit/stap-note-iter.h",
    "content": "#ifndef __RR_STAP_NOTE_ITER_H__\n#define __RR_STAP_NOTE_ITER_H__\n\n#define _GNU_SOURCE\n#include <stdbool.h>\n#include <link.h>\n\ntypedef struct {\n  ElfW(Addr) probe_address;\n  ElfW(Addr) base_address;\n  ElfW(Addr) semaphore_address;\n  const char* provider_name;\n  const char* probe_name;\n  const char* argument_format;\n} ElfStapNote;\n\ntypedef struct {\n  /*< private >*/\n  const struct link_map* map;\n  int fd;\n  uintptr_t stapbase;\n  const ElfW(Shdr) *shdrs, *shdr_iter, *shdr_end;\n  void* note_data;\n  size_t note_data_offset;\n} StapNoteIter;\n\nvoid stap_note_iter_init(StapNoteIter* iter, const struct link_map* map);\n\nbool stap_note_iter_next(StapNoteIter* iter, ElfStapNote* out_note);\n\nvoid stap_note_iter_release(StapNoteIter* iter);\n\n#endif\n"
  },
  {
    "path": "src/bpf/async_event_filter.c",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <linux/bpf.h>\n#include <linux/bpf_perf_event.h>\n#include <bpf/bpf_helpers.h>\n#include <stdint.h>\n\nconst uint32_t REGISTER_COUNT = sizeof(struct pt_regs)/sizeof(uint64_t);\n\nstruct {\n  __uint(type, BPF_MAP_TYPE_ARRAY);\n  __uint(max_entries, REGISTER_COUNT);\n  __uint(map_flags, BPF_F_MMAPABLE);\n  __type(key, uint32_t);\n  __type(value, uint64_t);\n} registers SEC(\".maps\");\n\nstruct {\n  __uint(type, BPF_MAP_TYPE_ARRAY);\n  __uint(max_entries, 1);\n  __uint(map_flags, BPF_F_MMAPABLE);\n  __type(key, uint32_t);\n  __type(value, uint64_t);\n} skips SEC(\".maps\");\n\nSEC(\"perf_event\")\nint match_registers(struct bpf_perf_event_data* event) {\n#define CHECK_REG(name)                                                        \\\n  do {                                                                         \\\n    const uint32_t i = offsetof(struct pt_regs, name) / sizeof(uint64_t);      \\\n    uint64_t* reg = bpf_map_lookup_elem(&registers, &i);                       \\\n    if (!reg) {                                                                \\\n      return 1;                                                                \\\n    }                                                                          \\\n    if (event->regs.name != *reg) {                                            \\\n      const uint32_t j = 0;                                                    \\\n      uint64_t* s = bpf_map_lookup_elem(&skips, &j);                           \\\n      if (s) {                                                                 \\\n        *s += 1;                                                               \\\n      }                                                                        \\\n      return 0;                                                                \\\n    }                                                                          \\\n  } while(0)\n\n  CHECK_REG(r15);\n  CHECK_REG(r14);\n  CHECK_REG(r13);\n  CHECK_REG(r12);\n  CHECK_REG(rbp);\n  CHECK_REG(rbx);\n  CHECK_REG(r11);\n  CHECK_REG(r10);\n  CHECK_REG(r9);\n  CHECK_REG(r8);\n  CHECK_REG(rax);\n  CHECK_REG(rcx);\n  CHECK_REG(rdx);\n  CHECK_REG(rsi);\n  CHECK_REG(rdi);\n  CHECK_REG(rsp);\n\n  return 1;\n}\n\nchar _license[] SEC(\"license\") = \"Dual MIT/GPL\";\n"
  },
  {
    "path": "src/chaos-test/chaos-test.sh",
    "content": "#!/bin/sh\n\n# Chaos tests take a long time to run, and by their very nature they're\n# nondeterministic and may fail intermittently, so they aren't part of 'make\n# check'. For realistic results, run the tests on a machine that's otherwise\n# idle.\n#\n# Usage: chaos-test.sh <path-to-rr-objdir>\n\ncd `dirname $0`\n\n./harness.py $1 40 40 core_count 3\n./harness.py $1 40 40 getaffinity_core_count 3\n./harness.py $1 200 200 futex_wakeup\n./harness.py $1 200 200 pipe_wakeup\n./harness.py $1 500 500 mmap_bits 7\n./harness.py $1 500 500 mmap_adjacent 10\n./harness.py $1 200 200 startup\n./harness.py $1 100 200 starvation_singlethreaded 200000 202000 2000 1000000\n./harness.py $1 100 200 starvation_singlethreaded 2000000 2400000 500000 5000000\n./harness.py $1 400 800 starvation_multithreaded 200000 202000 2000 1000000\n./harness.py $1 400 1600 starvation_multithreaded 2000000 2400000 500000 5000000\n"
  },
  {
    "path": "src/chaos-test/chaosutil.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_CHAOSUTIL_H\n#define RR_CHAOSUTIL_H\n\n#define _GNU_SOURCE 1\n#define _POSIX_C_SOURCE 2\n\n#include <errno.h>\n#include <pthread.h>\n#include <sched.h>\n#include <stdarg.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/user.h>\n#include <time.h>\n#include <unistd.h>\n\n/**\n * Print the printf-like arguments to stdout as atomic-ly as we can\n * manage.  Async-signal-safe.  Does not flush stdio buffers (doing so\n * isn't signal safe).\n */\n__attribute__((format(printf, 1, 2))) inline static int atomic_printf(\n    const char* fmt, ...) {\n  va_list args;\n  char buf[1024];\n  int len;\n\n  va_start(args, fmt);\n  len = vsnprintf(buf, sizeof(buf) - 1, fmt, args);\n  va_end(args);\n  return write(STDOUT_FILENO, buf, len);\n}\n\ninline static int check_cond(int cond) {\n  if (!cond) {\n    atomic_printf(\"FAILED: errno=%d (%s)\\n\", errno, strerror(errno));\n  }\n  return cond;\n}\n\n/**\n * Write |str| on its own line to stdout as atomic-ly as we can\n * manage.  Async-signal-safe.  Does not flush stdio buffers (doing so\n * isn't signal safe).\n */\ninline static int atomic_puts(const char* str) {\n  return atomic_printf(\"%s\\n\", str);\n}\n\n#define test_assert(cond)                                                      \\\n  do {                                                                         \\\n    if (!check_cond(cond))                                                     \\\n      abort();                                                                 \\\n  } while (0)\n\n__attribute__((format(printf, 1, 2))) inline static void caught_test_failure(\n    const char* fmt, ...) {\n  va_list args;\n  char buf[1024];\n  int len;\n\n  atomic_printf(\"EXIT-FAIL: \");\n  va_start(args, fmt);\n  len = vsnprintf(buf, sizeof(buf) - 2, fmt, args);\n  va_end(args);\n  buf[len] = '\\n';\n  if (len + 1 != write(STDOUT_FILENO, buf, len + 1)) {\n    abort();\n  }\n  exit(77);\n}\n\ninline static double now_double(void) {\n  struct timespec ts;\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  return ts.tv_sec + ts.tv_nsec / 1000000000.0;\n}\n\ninline static long get_page_size(void) { return sysconf(_SC_PAGE_SIZE); }\n\n#endif\n"
  },
  {
    "path": "src/chaos-test/core_count.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\n/* Given command-line parameter <c>,\n   test fails if sysconf() reports 'c' cores. */\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  int cores = atoi(argv[1]);\n  int sysconf_onln = sysconf(_SC_NPROCESSORS_ONLN);\n\n  if (sysconf_onln == cores) {\n    caught_test_failure(\"got core count: %d\", cores);\n  }\n\n  atomic_printf(\"Found %d cores online\\n\", sysconf_onln);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/futex_wakeup.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\nstatic int flag;\nstatic pthread_mutex_t mutex;\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  pthread_mutex_lock(&mutex);\n  pthread_mutex_unlock(&mutex);\n  flag = 1;\n  return NULL;\n}\n\nint main(void) {\n  int i;\n  pthread_t thread;\n  struct timespec ts = { 0, 10000000 };\n\n  pthread_mutex_init(&mutex, NULL);\n  pthread_mutex_lock(&mutex);\n  pthread_create(&thread, NULL, run_thread, NULL);\n  nanosleep(&ts, NULL);\n  pthread_mutex_unlock(&mutex);\n  if (flag > 0) {\n    caught_test_failure(\"flag set\");\n  }\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/getaffinity_core_count.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\n/* Given command-line parameter <c>,\n   test fails if sched_getaffinity() reports 'c' cores. */\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  int cores = atoi(argv[1]);\n  int i;\n\n  cpu_set_t cpus;\n  int count = 0;\n  sched_getaffinity(0, sizeof(cpus), &cpus);\n  for (i = 0; i < CPU_SETSIZE; ++i) {\n    if (CPU_ISSET(i, &cpus)) {\n      ++count;\n    }\n  }\n\n  if (count == cores) {\n    caught_test_failure(\"got core count: %d\", cores);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/harness.py",
    "content": "#!/usr/bin/env python3\n\nimport sys\nimport multiprocessing\nimport tempfile\nimport subprocess\nimport copy\nimport shutil\nimport os\nimport itertools\n\nobjdir = sys.argv[1]\nsanity_runs = eval(sys.argv[2])\nruns = eval(sys.argv[3])\nname = sys.argv[4]\nparams = sys.argv[5:]\n\nGOOD_FAIL = 77\n\n# Runs test, returns True if the test passed, False if it\n# expectedly fails. Exits with code 1 if test unexpectedly failed.\ndef run(rr_params):\n    d = tempfile.mkdtemp(prefix='rr-chaos-')\n    try:\n        env = copy.copy(os.environ)\n        env['_RR_TRACE_DIR'] = d\n        with open(d + \"/out\", 'w') as out:\n            p = subprocess.Popen([\"%s/bin/rr\"%objdir, \"record\"] + rr_params + [\"%s/bin/%s\"%(objdir, name)] + params, env=env,\n                stdout=out, stderr=out)\n            ret = p.wait()\n        if ret != 0 and ret != GOOD_FAIL:\n            print(\"Test %s failed unexpectedly; leaving behind trace in %s\"%(name, d))\n        out_array = []\n        with open(d + \"/out\", 'r') as out:\n            for line in out:\n                out_array.append(line.strip())\n        return [ret, out_array]\n    finally:\n        shutil.rmtree(d)\n\n# Use only half the cores. Otherwise tests will induce starvation\n# themselves; we want to measure starvation induced by rr.\npool = multiprocessing.Pool(max(1, round(multiprocessing.cpu_count()/2)))\n\ndef safe_exit(code):\n    pool.terminate()\n    pool.join()\n    print()\n    sys.exit(code)\n\nprint(\"Running %d iterations of %s/bin/%s %s without chaos mode\"%(sanity_runs, objdir, name, ' '.join(params)))\nsanity_failed = 0\nfor r in pool.imap_unordered(run, itertools.repeat([], sanity_runs)):\n    if r[0] == 0:\n        continue\n    if r[0] != GOOD_FAIL:\n        safe_exit(r[0])\n        break\n    sanity_failed = sanity_failed + 1\nif sanity_failed == sanity_runs:\n    print(\"PROBLEM: %d runs of %s all failed; not a good chaos mode test\"%(sanity_failed, name))\n    safe_exit(2)\nprint(\"Without chaos mode, %d runs of %s failed out of %d\"%(sanity_failed, name, sanity_runs))\n\nprint(\"Running %d iterations of %s/bin/%s %s in chaos mode\"%(runs, objdir, name, ' '.join(params)))\nfailed = 0\nfor r in pool.imap_unordered(run, itertools.repeat([\"--chaos\"], runs)):\n    if r[0] == 0:\n        continue\n    if r[0] != GOOD_FAIL:\n        safe_exit(r[0])\n        break\n    if failed == 0:\n        print(\"First test failure detected, output:\")\n        for line in r[1]:\n            print(line)\n    failed = failed + 1\nif failed == 0:\n    print(\"PROBLEM: With chaos mode, test %s did not fail in %d runs\"%(name, runs))\n    safe_exit(1)\n\nprint(\"With chaos mode, %d runs of %s failed out of %d\"%(failed, name, runs))\nif float(failed)/runs < 3*float(sanity_failed)/sanity_runs:\n    print(\"PROBLEM: Chaos mode didn't really help!\")\n    safe_exit(3)\n\nprint(\"SUCCESS\")\nsafe_exit(0)\n"
  },
  {
    "path": "src/chaos-test/mmap_adjacent.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\n/* Given command-line parameter <n>, mmaps n pages independently.\n   The test only fails if the first page is after the last page. */\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  int page_count = atoi(argv[1]);\n  char* p1 = mmap(NULL, get_page_size(), PROT_READ | PROT_WRITE,\n                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  char* p2;\n  int i;\n\n  for (i = 0; i < page_count - 2; ++i) {\n    char* p = mmap(NULL, get_page_size(), PROT_READ | PROT_WRITE,\n                   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n    test_assert(p != MAP_FAILED);\n  }\n\n  p2 = mmap(NULL, get_page_size(), PROT_READ | PROT_WRITE,\n            MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  if (p2 + get_page_size() == p1) {\n    caught_test_failure(\"maps are adjacent: %p %p\", p2, p1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/mmap_bits.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\n/* Given command-line parameter <b>, mmaps two pages independently;\n   test only fails if bits 16...16+b-1 of the two addresses match.\n   Probability of failure is therefore 2^(-b). */\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  int bits_match = atoi(argv[1]);\n  char* p1 = mmap(NULL, get_page_size(), PROT_READ | PROT_WRITE,\n                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  char* p2 = mmap(NULL, get_page_size(), PROT_READ | PROT_WRITE,\n                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  intptr_t delta = p2 - p1;\n  intptr_t mask = ((1 << bits_match) - 1) << 12;\n\n  test_assert(get_page_size() == (1 << 12));\n  test_assert(p1 != MAP_FAILED);\n  test_assert(p2 != MAP_FAILED);\n\n  if (!(delta & mask)) {\n    caught_test_failure(\"map bits match: %p %p\", p1, p2);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/pipe_wakeup.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\nstatic int flag;\nstatic int pipe_fds[2];\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  char ch;\n  int ret = read(pipe_fds[0], &ch, 1);\n  if (ret != 1) {\n    abort();\n  }\n  flag = 1;\n  return NULL;\n}\n\nint main(__attribute__((unused)) int argc,\n         __attribute__((unused)) const char** argv) {\n  int i;\n  int ret;\n  pthread_t thread;\n  struct timespec ts = { 0, 10000000 };\n\n  ret = pipe(pipe_fds);\n  if (ret != 0) {\n    abort();\n  }\n\n  pthread_create(&thread, NULL, run_thread, NULL);\n  nanosleep(&ts, NULL);\n  ret = write(pipe_fds[1], \"x\", 1);\n  if (ret != 1) {\n    abort();\n  }\n  if (flag > 0) {\n    caught_test_failure(\"flag set\");\n  }\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/startup.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\nstatic int flag;\nstatic pthread_mutex_t mutex;\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  struct timespec ts = { 1, 0 };\n  nanosleep(&ts, NULL);\n  pthread_mutex_lock(&mutex);\n  flag = 1;\n  pthread_mutex_unlock(&mutex);\n  return NULL;\n}\n\nint main(void) {\n  int i;\n  pthread_t thread;\n\n  pthread_mutex_init(&mutex, NULL);\n  pthread_create(&thread, NULL, run_thread, NULL);\n  pthread_mutex_lock(&mutex);\n  if (flag > 0) {\n    caught_test_failure(\"flag set\");\n  }\n  pthread_mutex_unlock(&mutex);\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/starvation_multithreaded.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\nstatic double samples[10000000];\nstatic size_t sample_count = 0;\n\n/* Given command-line parameters <S>, <T>, <D> and <L>:\n   Spin the CPU on one thread until L microseconds have elapsed, while\n   other threads frequently sleep.\n   The test fails if, at some point starting between S and T microseconds,\n   the spinning thread fails to be scheduled for D microseconds. */\n\nstatic double start, S, T, D, L;\n\nstatic void* spinning_thread(__attribute__((unused)) void* p) {\n  int k = 0;\n  double last = 0;\n\n  while (1) {\n    int i;\n    double t;\n    for (i = 0; i < 10000; ++i) {\n      k += i * i;\n    }\n    t = now_double();\n    samples[sample_count++] = t;\n    if (sample_count >= sizeof(samples) / sizeof(samples[0])) {\n      atomic_puts(\"OVERFLOW\");\n      exit(1);\n    }\n    if (t > L) {\n      break;\n    }\n    if (last >= S && last < T && t >= last + D) {\n      caught_test_failure(\"time wasn't checked between %f and %f\", last - start,\n                          t - start);\n    }\n    last = t;\n  }\n  return (void*)(intptr_t)k;\n}\n\nstatic void* aux_thread(__attribute__((unused)) void* p) {\n  /* Repeatedly sleep for a millisecond */\n  struct timespec ts = { 0, 1000000 };\n  while (1) {\n    nanosleep(&ts, NULL);\n  }\n  return NULL;\n}\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  int i;\n  pthread_t thread;\n\n  start = now_double();\n  S = atoi(argv[1]) / 1000000.0 + start;\n  T = atoi(argv[2]) / 1000000.0 + start;\n  D = atoi(argv[3]) / 1000000.0;\n  L = atoi(argv[4]) / 1000000.0 + start;\n\n  atomic_printf(\"Critical range is %f to %f\\n\", S, T);\n\n  pthread_create(&thread, NULL, spinning_thread, NULL);\n\n  for (i = 0; i < 4; ++i) {\n    pthread_t t;\n    pthread_create(&t, NULL, aux_thread, NULL);\n  }\n\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/chaos-test/starvation_singlethreaded.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"chaosutil.h\"\n\nstatic double samples[10000000];\nstatic size_t sample_count = 0;\n\n/* Given command-line parameters <S>, <T>, <D> and <L>:\n   Spins the CPU on a single thread until L microseconds have elapsed.\n   The test fails if, at some point starting between S and T microseconds,\n   we fail to be scheduled for D microseconds */\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  double start = now_double();\n  double S = atoi(argv[1]) / 1000000.0 + start;\n  double T = atoi(argv[2]) / 1000000.0 + start;\n  double D = atoi(argv[3]) / 1000000.0;\n  double L = atoi(argv[4]) / 1000000.0 + start;\n  int k = 0;\n  double last = 0;\n\n  atomic_printf(\"Critical range is %f to %f\\n\", S, T);\n\n  while (1) {\n    int i;\n    double t;\n    for (i = 0; i < 10000; ++i) {\n      k += i * i;\n    }\n    t = now_double();\n    samples[sample_count++] = t;\n    if (sample_count >= sizeof(samples) / sizeof(samples[0])) {\n      atomic_puts(\"OVERFLOW\");\n      exit(1);\n    }\n    if (t > L) {\n      break;\n    }\n    if (last >= S && last < T && t >= last + D) {\n      caught_test_failure(\"time wasn't checked between %f and %f\", last - start,\n                          t - start);\n    }\n    last = t;\n  }\n\n  atomic_printf(\"dummy = %d\\n\", k);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/core.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_CORE_H_\n#define RR_CORE_H_\n\n#include <assert.h>\n#include <string.h>\n\n#include <array>\n\n/* This file depends on nothing in rr and can be included anywhere */\n\n#ifndef __has_attribute\n#define __has_attribute(x) 0\n#endif\n#ifndef __has_cpp_attribute\n#define __has_cpp_attribute(x) 0\n#endif\n\n/* RR_FALLTHROUGH - Mark fallthrough cases in switch statements. */\n#if defined(__cplusplus) && __cplusplus > 201402L &&                           \\\n    __has_cpp_attribute(fallthrough)\n#define RR_FALLTHROUGH [[fallthrough]]\n#elif !__cplusplus\n/* Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious\n   error when __has_cpp_attribute is given a scoped attribute in C mode. */\n#define RR_FALLTHROUGH\n#elif __has_cpp_attribute(clang::fallthrough)\n#define RR_FALLTHROUGH [[clang::fallthrough]]\n#elif defined(__GNUC__) && __GNUC__ >= 7\n#define RR_FALLTHROUGH __attribute__((fallthrough))\n#else\n#define RR_FALLTHROUGH\n#endif\n\n#ifdef __cplusplus\n\nnamespace rr {\n\ntemplate <typename T, size_t N> constexpr size_t array_length(T (&)[N]) {\n  return N;\n}\n\ntemplate <typename T, size_t N>\nconstexpr size_t array_length(std::array<T, N>&) {\n  return N;\n}\n\ntemplate <typename T> T return_dummy_value() {\n  T v;\n  memset(&v, 1, sizeof(T));\n  return v;\n}\ntemplate <typename T> bool check_type_has_no_holes() {\n  T v;\n  memset(&v, 2, sizeof(T));\n  v = return_dummy_value<T>();\n  return memchr(&v, 2, sizeof(T)) == NULL;\n}\n/**\n * Returns true when type T has no holes. Preferably should not be defined\n * at all otherwise.\n * This is not 100% reliable since the check_type_has_no_holes may be\n * compiled to copy holes. However, it has detected at least two bugs.\n */\ntemplate <typename T> bool type_has_no_holes() {\n  static bool check = check_type_has_no_holes<T>();\n  return check;\n}\n}\n\n#endif\n\n#endif /* RR_CORE_H_ */\n"
  },
  {
    "path": "src/counters-test/README.md",
    "content": "# counters test\n\nThis does a quick check to determine whether hardware performance counter measurement and interrupts, and the kernel/hypervisor support for them, are working as expected. It's useful for testing PMU infrastructure without the full complexity of rr.\n\nIt copies some code from rr sources to make a standalone test for easier debugging and/or inclusion in CI tests for other projects. It's under the same MIT-style license as the rest of the rr code.\n\n## Basic test\n\nRun with\n```\ng++ counters.cc -o /tmp/counters && /tmp/counters\n```\n\n## Intensive interrupt testing\n\n`counters` takes optional command-line parameters:\n```\n/tmp/counters [number of interrupts to test] [interrupt period]\n```\nThe number of interrupts to test defaults to 1. The interrupt period defaults to 1000000.\n\nTo test interrupts thoroughly, try something like\n```\nfor i in `seq 1 1000`; do /tmp/counters 1000 10000 > /tmp/output$i & done\n```\nDon't run this on your laptop! This tests 1M interrupts with the machine under load. If there are failures you will see lines like\n```\n[425]   Aborted                 (core dumped) ~/obj/bin/counters 1000 10000 > /tmp/output$i\n```\n"
  },
  {
    "path": "src/counters-test/counters.cc",
    "content": "#include <dirent.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <linux/perf_event.h>\n#include <sched.h>\n#include <signal.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/syscall.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <algorithm>\n#include <fstream>\n#include <iostream>\n#include <limits>\n#include <regex>\n#include <vector>\n\n#define CHECK(condition) \\\n  do { \\\n    if (!(condition)) { \\\n      fprintf(stderr, \"CHECK '%s' failed at %s:%d (errno=%d)\\n\", #condition, __FILE__, __LINE__, errno); \\\n      abort(); \\\n    } \\\n  } while (0)\n\nstatic void die(const char* msg) {\n  fprintf(stderr, \"%s\\n\", msg);\n  abort();\n}\n\n/* ==== Copied from PerfCounters.cc ==== */\n\n/*\n * Find out the cpu model using the cpuid instruction.\n * Full list of CPUIDs at http://sandpile.org/x86/cpuid.htm\n * Another list at\n * http://software.intel.com/en-us/articles/intel-architecture-and-processor-identification-with-cpuid-model-and-family-numbers\n */\nenum CpuMicroarch {\n  UnknownCpu,\n  FirstIntel,\n  IntelMerom = FirstIntel,\n  IntelPenryn,\n  IntelNehalem,\n  IntelWestmere,\n  IntelSandyBridge,\n  IntelIvyBridge,\n  IntelHaswell,\n  IntelBroadwell,\n  IntelSkylake,\n  IntelSilvermont,\n  IntelGoldmont,\n  IntelTremont,\n  IntelKabylake,\n  IntelCometlake,\n  IntelIcelake,\n  IntelTigerlake,\n  IntelRocketlake,\n  IntelAlderlake,\n  IntelRaptorlake,\n  IntelSapphireRapid,\n  IntelEmeraldRapid,\n  IntelGraniteRapid,\n  IntelMeteorLake,\n  IntelArrowLake,\n  LastIntel = IntelArrowLake,\n  FirstAMD,\n  AMDF15 = FirstAMD,\n  AMDZen,\n  LastAMD = AMDZen,\n  FirstARM,\n  ARMNeoverseN1 = FirstARM,\n  ARMNeoverseE1,\n  ARMNeoverseV1,\n  ARMNeoverseN2,\n  ARMCortexA55,\n  ARMCortexA75,\n  ARMCortexA76,\n  ARMCortexA77,\n  ARMCortexA78,\n  ARMCortexX1,\n  AppleM1Icestorm,\n  AppleM1Firestorm,\n  AppleM2Blizzard,\n  AppleM2Avalanche,\n  LastARM = AppleM2Avalanche,\n};\n\n/*\n * Set if this CPU supports ticks counting retired conditional branches.\n */\n#define PMU_TICKS_RCB (1<<0)\n\n/*\n * Some CPUs turn off the whole PMU when there are no remaining events\n * scheduled (perhaps as a power consumption optimization). This can be a\n * very expensive operation, and is thus best avoided. For cpus, where this\n * is a problem, we keep a cycles counter (which corresponds to one of the\n * fixed function counters, so we don't use up a programmable PMC) that we\n * don't otherwise use, but keeps the PMU active, greatly increasing\n * performance.\n */\n#define PMU_BENEFITS_FROM_USELESS_COUNTER (1<<1)\n\n/*\n * Set if this CPU supports ticks counting all taken branches\n * (excluding interrupts, far branches, and rets).\n */\n#define PMU_TICKS_TAKEN_BRANCHES (1<<3)\n\nstruct PmuConfig {\n  CpuMicroarch uarch;\n  const char* name;\n  unsigned rcb_cntr_event;\n  unsigned minus_ticks_cntr_event;\n  unsigned llsc_cntr_event;\n  uint32_t skid_size;\n  uint32_t flags;\n  const char* pmu_name = nullptr; // ARM only\n  unsigned cycle_event = PERF_COUNT_HW_CPU_CYCLES;\n  int cycle_type = PERF_TYPE_HARDWARE;\n  int event_type = PERF_TYPE_RAW;\n};\n\n// XXX please only edit this if you really know what you're doing.\n// event = 0x5101c4:\n// - 51 = generic PMU\n// - 01 = umask for event BR_INST_RETIRED.CONDITIONAL\n// - c4 = eventsel for event BR_INST_RETIRED.CONDITIONAL\n// event = 0x5301cb:\n// - 51 = generic PMU\n// - 01 = umask for event HW_INTERRUPTS.RECEIVED\n// - cb = eventsel for event HW_INTERRUPTS.RECEIVED\n// See Intel 64 and IA32 Architectures Performance Monitoring Events.\n// See check_events from libpfm4.\nstatic const PmuConfig pmu_configs[] = {\n  { IntelGraniteRapid, \"Intel GraniteRapid\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelEmeraldRapid, \"Intel EmeraldRapid\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelSapphireRapid, \"Intel SapphireRapid\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelArrowLake, \"Intel Arrowlake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelMeteorLake, \"Intel Meteorlake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelRaptorlake, \"Intel Raptorlake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelAlderlake, \"Intel Alderlake\", 0x5111c4, 0, 0, 125, PMU_TICKS_RCB },\n  { IntelRocketlake, \"Intel Rocketlake\", 0x5111c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelTigerlake, \"Intel Tigerlake\", 0x5111c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelIcelake, \"Intel Icelake\", 0x5111c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelCometlake, \"Intel Cometlake\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelKabylake, \"Intel Kabylake\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelSilvermont, \"Intel Silvermont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelGoldmont, \"Intel Goldmont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelTremont, \"Intel Tremont\", 0x517ec4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelSkylake, \"Intel Skylake\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelBroadwell, \"Intel Broadwell\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelHaswell, \"Intel Haswell\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelIvyBridge, \"Intel Ivy Bridge\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelSandyBridge, \"Intel Sandy Bridge\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelNehalem, \"Intel Nehalem\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelWestmere, \"Intel Westmere\", 0x5101c4, 0, 0, 100, PMU_TICKS_RCB },\n  { IntelPenryn, \"Intel Penryn\", 0, 0, 0, 100, 0 },\n  { IntelMerom, \"Intel Merom\", 0, 0, 0, 100, 0 },\n  { AMDF15, \"AMD Family 15h\", 0xc4, 0xc6, 0, 250, PMU_TICKS_TAKEN_BRANCHES },\n  // 0xd1 == RETIRED_CONDITIONAL_BRANCH_INSTRUCTIONS - Number of retired conditional branch instructions\n  // 0x2c == INTERRUPT_TAKEN - Counts the number of interrupts taken\n  // Both counters are available on Zen, Zen+ and Zen2.\n  { AMDZen, \"AMD Zen\", 0x5100d1, 0, 0, 10000, PMU_TICKS_RCB },\n  // Performance cores from ARM from cortex-a76 on (including neoverse-n1 and later)\n  // have the following counters that are reliable enough for us.\n  // 0x21 == BR_RETIRED - Architecturally retired taken branches\n  // 0x6F == STREX_SPEC - Speculatively executed strex instructions\n  // 0x11 == CPU_CYCLES - Cycle\n  { ARMNeoverseN1, \"ARM Neoverse N1\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseV1, \"ARM Neoverse V1\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMNeoverseN2, \"ARM Neoverse N2\", 0x21, 0, 0x6F, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3_0\", 0x11, -1, -1 },\n  { ARMCortexA76, \"ARM Cortex A76\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { ARMCortexA77, \"ARM Cortex A77\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { ARMCortexA78, \"ARM Cortex A78\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  { ARMCortexX1, \"ARM Cortex X1\", 0x21, 0, 0x6F, 10000, PMU_TICKS_TAKEN_BRANCHES,\n    \"armv8_pmuv3\", 0x11, -1, -1 },\n  // cortex-a55, cortex-a75 and neoverse-e1 counts uarch ISB\n  // as retired branches so the BR_RETIRED counter is not reliable.\n  // There are some counters that are somewhat more reliable than\n  // the total branch count (0x21) including\n  // 0x0D (BR_IMMED_RETIRED) 0x0E (BR_RETURN_RETIRED)\n  // 0xCD (BR_INDIRECT_ADDR_PRED) 0x76 (PC_WRITE_SPEC)\n  // 0x78 (BR_IMMED_SPEC), 0xC9 (BR_COND_PRED)\n  // 0xCD (BR_INDIRECT_ADDR_PRED)\n  // but according to tests on the LITTLE core on a snapdragon 865\n  // none of them (including the sums) seems to be useful/reliable enough.\n  { ARMNeoverseE1, \"ARM Neoverse E1\", 0, 0, 0, 0, 0 },\n  { ARMCortexA55, \"ARM Cortex A55\", 0, 0, 0, 0, 0 },\n  { ARMCortexA75, \"ARM Cortex A75\", 0, 0, 0, 0, 0 },\n  { AppleM1Icestorm, \"Apple M1 Icestorm\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_icestorm_pmu\", 0x8c, -1, -1 },\n  { AppleM1Firestorm, \"Apple M1 Firestorm\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_firestorm_pmu\", 0x8c, -1, -1 },\n  { AppleM2Blizzard, \"Apple M2 Blizzard\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_blizzard_pmu\", 0x8c, -1, -1 },\n  { AppleM2Avalanche, \"Apple M2 Avalanche\", 0x90, 0, 0, 1000, PMU_TICKS_TAKEN_BRANCHES,\n    \"apple_avalanche_pmu\", 0x8c, -1, -1 },\n};\n\n/* ==== End copying from PerfCounters.cc ==== */\n\n/* ==== Copied from util.h ==== */\n\ntypedef struct {\n  uint32_t eax, ebx, ecx, edx;\n} CPUIDData;\n\ntypedef enum  {\n  CPUID_GETVENDORSTRING,\n  CPUID_GETFEATURES,\n  CPUID_GETTLB,\n  CPUID_GETSERIAL,\n  CPUID_GETCACHEPARAMS = 0x04,\n  CPUID_GETEXTENDEDFEATURES = 0x07,\n  CPUID_GETEXTENDEDTOPOLOGY = 0x0B,\n  CPUID_GETXSAVE = 0x0D,\n  CPUID_GETRDTMONITORING = 0x0F,\n  CPUID_GETRDTALLOCATION = 0x10,\n  CPUID_GETSGX = 0x12,\n  CPUID_GETPT = 0x14,\n  CPUID_GETSOC = 0x17,\n  CPUID_HYPERVISOR = 0x40000000,\n  CPUID_INTELEXTENDED = 0x80000000,\n  CPUID_INTELFEATURES,\n  CPUID_INTELBRANDSTRING,\n  CPUID_INTELBRANDSTRINGMORE,\n  CPUID_INTELBRANDSTRINGEND,\n  CPUID_AMD_CACHE_TOPOLOGY = 0x8000001D,\n  CPUID_AMD_PLATFORM_QOS = 0x80000020\n} cpuid_requests;\n\n/* ==== End copying from util.h ==== */\n\n#if defined(__i386__) || defined(__x86_64__)\n/* ==== Copied from util.cc ==== */\n\nCPUIDData cpuid(uint32_t code, uint32_t subrequest) {\n  CPUIDData result;\n  asm volatile(\"cpuid\"\n               : \"=a\"(result.eax), \"=b\"(result.ebx), \"=c\"(result.ecx),\n                 \"=d\"(result.edx)\n               : \"a\"(code), \"c\"(subrequest));\n  return result;\n}\n\n/* ==== End copying from util.cc === */\n\n/* ==== Copied from PerfCounters_x86.h ==== */\n\n/**\n * Return the detected, known microarchitecture of this CPU, or don't\n * return; i.e. never return UnknownCpu.\n */\nstatic CpuMicroarch compute_cpu_microarch(void) {\n  CPUIDData cpuid_vendor = cpuid(CPUID_GETVENDORSTRING, 0);\n  char vendor[12];\n  memcpy(&vendor[0], &cpuid_vendor.ebx, 4);\n  memcpy(&vendor[4], &cpuid_vendor.edx, 4);\n  memcpy(&vendor[8], &cpuid_vendor.ecx, 4);\n  if (strncmp(vendor, \"GenuineIntel\", sizeof(vendor)) &&\n      strncmp(vendor, \"AuthenticAMD\", sizeof(vendor))) {\n    die(\"Unknown CPU vendor\");\n  }\n\n  CPUIDData cpuid_data = cpuid(CPUID_GETFEATURES, 0);\n  unsigned int cpu_type = cpuid_data.eax & 0xF0FF0;\n  unsigned int ext_family = (cpuid_data.eax >> 20) & 0xff;\n  switch (cpu_type) {\n    case 0x006F0:\n    case 0x10660:\n      return IntelMerom;\n    case 0x10670:\n    case 0x106D0:\n      return IntelPenryn;\n    case 0x106A0:\n    case 0x106E0:\n    case 0x206E0:\n      return IntelNehalem;\n    case 0x20650:\n    case 0x206C0:\n    case 0x206F0:\n      return IntelWestmere;\n    case 0x206A0:\n    case 0x206D0:\n    case 0x306e0:\n      return IntelSandyBridge;\n    case 0x306A0:\n      return IntelIvyBridge;\n    case 0x306C0: /* Devil's Canyon */\n    case 0x306F0:\n    case 0x40650:\n    case 0x40660:\n      return IntelHaswell;\n    case 0x306D0:\n    case 0x40670:\n    case 0x406F0:\n    case 0x50660:\n      return IntelBroadwell;\n    case 0x406e0:\n    case 0x50650:\n    case 0x506e0:\n      return IntelSkylake;\n    case 0x30670:\n    case 0x406c0:\n    case 0x50670:\n      return IntelSilvermont;\n    case 0x506f0:\n    case 0x706a0:\n    case 0x506c0:\n      return IntelGoldmont;\n    case 0x706e0:\n    case 0x606a0:\n      return IntelIcelake;\n    case 0x806c0:\n    case 0x806d0:\n      return IntelTigerlake;\n    case 0x806e0:\n    case 0x906e0:\n      return IntelKabylake;\n    case 0xa0650:\n    case 0xa0660:\n      return IntelCometlake;\n    case 0xa0670:\n      return IntelRocketlake;\n    case 0x90670:\n    case 0x906a0:\n      return IntelAlderlake;\n    case 0xb0670:\n      return IntelRaptorlake;\n    case 0x806f0:\n      return IntelSapphireRapid;\n    case 0xc06f0:\n      return IntelEmeraldRapid;\n    case 0xa06d0:\n      return IntelGraniteRapid;\n    case 0xa06a0:\n      return IntelMeteorLake;\n    case 0xc0660:\n      return IntelArrowLake;\n    case 0xf20:\n    case 0x30f00:\n      return AMDF15;\n    case 0x00f10: // Naples, Whitehaven, Summit Ridge, Snowy Owl (Zen), Milan (Zen 3) (UNTESTED)\n    case 0x10f10: // Raven Ridge, Great Horned Owl (Zen) (UNTESTED)\n    case 0x10f80: // Banded Kestrel (Zen), Picasso (Zen+) (UNTESTED)\n    case 0x20f00: // Dali (Zen) (UNTESTED)\n    case 0x00f80: // Colfax, Pinnacle Ridge (Zen+) (UNTESTED)\n    case 0x30f10: // Rome, Castle Peak (Zen 2)\n    case 0x60f00: // Renoir (Zen 2) (UNTESTED)\n    case 0x70f10: // Matisse (Zen 2) (UNTESTED)\n    case 0x60f80: // Lucienne\n    case 0x90f00: // Van Gogh (Zen 2)\n      if (ext_family == 8 || ext_family == 0xa) {\n        return AMDZen;\n      } else if (ext_family == 3) {\n        return AMDF15;\n      }\n      break;\n    case 0x20f10: // Vermeer (Zen 3)\n    case 0x50f00: // Cezanne (Zen 3)\n    case 0x40f40: // Rembrandt (Zen 3+)\n    case 0x60f10: // Raphael (Zen 4)\n    case 0x70f40: // Phoenix (Zen 4)\n    case 0x70f50: // Hawk Point (Zen 4)\n      if (ext_family == 0xa) {\n        return AMDZen;\n      }\n    default:\n      break;\n  }\n\n  if (!strncmp(vendor, \"AuthenticAMD\", sizeof(vendor))) {\n    die(\"AMD CPU type unknown\");\n  } else {\n    die(\"Intel CPU type unknown\");\n  }\n  return UnknownCpu; // not reached\n}\n\nstatic std::vector<CpuMicroarch> compute_cpu_microarchs() {\n  return { compute_cpu_microarch() };\n}\n\n/* ==== End copying from PerfCounters_x86.h ==== */\n#endif\n\n#if defined(__aarch64__)\n/* ==== End copying from PerfCounters_aarch64.h ==== */\n\nstruct CPUID {\n  uint8_t implementer = 0;\n  uint8_t variant = 0;\n  uint16_t part = 0;\n  operator bool() const\n  {\n    return implementer || variant || part;\n  }\n  // bool operator==(const CPUID&) const = default; // c++20\n  bool operator==(const CPUID &other) const\n  {\n    return implementer == other.implementer &&\n      variant == other.variant && part == other.part;\n  }\n  bool operator!=(const CPUID &other) const\n  {\n    return !(*this == other);\n  }\n};\n\n/**\n * Return the detected, known microarchitecture of this CPU, or don't\n * return; i.e. never return UnknownCpu.\n */\nstatic CpuMicroarch compute_cpu_microarch(const CPUID &cpuid) {\n  switch (cpuid.implementer) {\n  case 0x41: // ARM\n    switch (cpuid.part) {\n    case 0xd05:\n      return ARMCortexA55;\n    case 0xd0a:\n      return ARMCortexA75;\n    case 0xd0b:\n      return ARMCortexA76;\n    case 0xd0c:\n      return ARMNeoverseN1;\n    case 0xd0d:\n      return ARMCortexA77;\n    case 0xd40:\n      return ARMNeoverseV1;\n    case 0xd41:\n    case 0xd4b: // ARM Cortex A78C\n      return ARMCortexA78;\n    case 0xd44:\n    case 0xd4c: // ARM Cortex X1C\n      return ARMCortexX1;\n    case 0xd49:\n      return ARMNeoverseN2;\n    case 0xd4a:\n      return ARMNeoverseE1;\n    }\n    break;\n  case 0x51: // Qualcomm\n    switch (cpuid.part) {\n    case 0x802:\n      return ARMCortexA75;\n    case 0x803:\n      return ARMCortexA55;\n    case 0x804:\n      return ARMCortexA76;\n    case 0x805:\n      return ARMCortexA55;\n    }\n    break;\n  case 0x61: // Apple\n    switch (cpuid.part) {\n    case 0x22:\n    case 0x24:\n    case 0x28:\n      return AppleM1Icestorm;\n    case 0x23:\n    case 0x25:\n    case 0x29:\n      return AppleM1Firestorm;\n    case 0x32:\n      return AppleM2Blizzard;\n    case 0x33:\n      return AppleM2Avalanche;\n    }\n    break;\n  }\n  die(\"Unknown aarch64 CPU type\");\n  return UnknownCpu; // not reached\n}\n\nstatic void set_cpuid(std::vector<CPUID> &cpuids, unsigned long cpuidx, CPUID cpuid)\n{\n  if (cpuids.size() <= cpuidx) {\n    cpuids.resize(cpuidx + 1);\n  }\n  if (cpuids[cpuidx]) {\n    die(\"Duplicated CPUID for core\");\n  }\n  cpuids[cpuidx] = cpuid;\n}\n\n/**\n * The new interface to get ID register values on AArch64\n * `/sys/devices/system/cpu/cpu([0-9]+)/regs/identification/midr_el1`\n * The register value is stored in hex.\n */\nstatic inline void get_cpuinfo_sysfs(std::vector<CPUID> &res)\n{\n  const std::string cpu_dir = \"/sys/devices/system/cpu/\";\n  const std::regex cpuname_regex(\"cpu([0-9]+)\");\n  auto dir = opendir(cpu_dir.c_str());\n  if (!dir) {\n    return;\n  }\n  while (auto entry = readdir(dir)) {\n    std::cmatch match;\n    if (entry->d_type != DT_DIR ||\n        !std::regex_match(entry->d_name, match, cpuname_regex)) {\n      continue;\n    }\n    auto cpuidx = std::stoul(match[1].str());\n    std::string name = cpu_dir + entry->d_name + \"/regs/identification/midr_el1\";\n    std::ifstream file(name);\n    if (!file) {\n      die(\"Failed to read midr register from kernel\");\n    }\n    uint64_t val = 0;\n    file >> std::hex >> val;\n    if (!file) {\n      die(\"Failed to read midr register from kernel\");\n    }\n    set_cpuid(res, cpuidx, {\n        uint8_t(val >> 24),\n        uint8_t((val >> 20) & 0xf),\n        uint16_t((val >> 4) & 0xfff)\n      });\n  }\n  closedir(dir);\n}\n\n/**\n * A line we care about in /proc/cpuinfo starts with a prefix followed by\n * `:` and some white space characters, then followed by the value we care about.\n * Return true if we've found the prefix. Set `flag` to `false`\n * if the value parsing failed.\n *\n * Use an external template since lambda's can't be templated in C++11\n */\ntemplate<typename T, typename F>\nstatic inline bool try_read_procfs_line(const std::string &line,\n                                        const char *prefix, T &out,\n                                        bool &flag, F &&reset)\n{\n  size_t prefix_len = strlen(prefix);\n  if (line.size() < prefix_len) {\n    return false;\n  }\n  if (memcmp(&line[0], prefix, prefix_len) != 0) {\n    return false;\n  }\n  if (flag) {\n    // We've seen this already,\n    // i.e. we didn't see a new line between the processor lines\n    reset();\n  }\n  const char *p = &line[prefix_len];\n  // Skip blank and `:`.\n  while (*p == '\\t' || *p == ' ' || *p == ':') {\n    p++;\n  }\n  char *str_end;\n  auto num = std::strtoull(p, &str_end, 0);\n  out = (T)num;\n  if (str_end == p) {\n    flag = false;\n  } else if (num > (unsigned long long)std::numeric_limits<T>::max()) {\n    flag = false;\n  } else {\n    flag = true;\n  }\n  return true;\n}\n\n/**\n * /proc/cpuinfo reader\n * The cpuinfo file contains blocks of text for each core.\n * The blocks are separated by empty lines and it should start with a\n * `processor : <num>` line followed by lines showing properties of the core.\n * The three property lines we are looking for starts with\n * `CPU implementer`, `CPU variant` and `CPU part`.\n */\nstatic inline void get_cpuinfo_procfs(std::vector<CPUID> &res)\n{\n  std::ifstream file(\"/proc/cpuinfo\");\n  CPUID cpuid = {0, 0, 0};\n  unsigned cpuidx = 0;\n  bool has_cpuidx = false;\n  bool has_impl = false;\n  bool has_part = false;\n  bool has_var = false;\n  auto reset = [&] () {\n    // Few (none) of the detection code care about the variant number\n    // so we'll accept it if we couldn't read it.\n    if (has_cpuidx && has_impl && has_part) {\n      set_cpuid(res, cpuidx, cpuid);\n    }\n    has_cpuidx = false;\n    has_impl = false;\n    has_part = false;\n    has_var = false;\n    cpuid = {0, 0, 0};\n  };\n  for (std::string line; std::getline(file, line);) {\n    // Empty lines means that we've finished processing of a block\n    if (line.empty()) {\n      reset();\n      continue;\n    }\n    // First find the processor line\n    if (try_read_procfs_line(line, \"processor\", cpuidx, has_cpuidx, reset)) {\n      continue;\n    }\n    // and ignore the line until we found the processor line.\n    if (!has_cpuidx) {\n      continue;\n    }\n\n    // Try parsing as one of the data lines.\n    // Short circuiting after the first hit.\n    try_read_procfs_line(line, \"CPU implementer\", cpuid.implementer, has_impl, reset) ||\n      try_read_procfs_line(line, \"CPU variant\", cpuid.variant, has_var, reset) ||\n      try_read_procfs_line(line, \"CPU part\", cpuid.part, has_part, reset);\n  }\n  reset();\n}\n\nstatic std::vector<CpuMicroarch> compute_cpu_microarchs() {\n  std::vector<CPUID> cpuids;\n  get_cpuinfo_sysfs(cpuids);\n  if (cpuids.empty()) {\n    fprintf(stderr, \"Unable to read CPU type from sysfs, trying procfs instead.\");\n    get_cpuinfo_procfs(cpuids);\n  }\n  if (cpuids.empty()) {\n    die(\"Failed to read midr register from kernel\");\n  }\n  for (auto &cpuid : cpuids) {\n    if (!cpuid) {\n      die(\"Unable to find CPU id for core\");\n    }\n  }\n  auto cpuid0 = cpuids[0];\n  bool single_uarch = true;\n  for (auto &cpuid : cpuids) {\n    if (cpuid != cpuid0) {\n      single_uarch = false;\n      break;\n    }\n  }\n  if (single_uarch) {\n    return { compute_cpu_microarch(cpuid0) };\n  }\n  std::vector<CpuMicroarch> uarchs;\n  for (auto &cpuid : cpuids) {\n    uarchs.push_back(compute_cpu_microarch(cpuid));\n  }\n  return uarchs;\n}\n\n/* ==== End copying from PerfCounters_aarch64.h ==== */\n#endif\n\nstatic int parent_to_child_fds[2];\nstatic int child_to_parent_fds[2];\nstatic char do_test_ticks_basic;\nstatic char do_test_ticks_syscalls;\n\n/* Tell the parent we're ready, then wait for the parent to signal us,\n   without executing any conditional branches */\nstatic void child_wait(void) {\n#if defined(__x86_64__)\n  /* write(child_to_parent_fds[1], buf, 1) */\n  /* Use hand-rolled syscalls to avoid conditional branches (e.g. setting errno) */\n  __asm__ __volatile__ (\"syscall\" : : \"a\"(__NR_write), \"D\"(child_to_parent_fds[1]), \"S\"(\"x\"), \"d\"(1) : \"rcx\", \"r11\", \"flags\");\n  char buf;\n  /* read(parent_to_child_fds[0], buf, 1) */\n  __asm__ __volatile__ (\"syscall\" : : \"a\"(__NR_read), \"D\"(parent_to_child_fds[0]), \"S\"(&buf), \"d\"(1) : \"rcx\", \"r11\", \"flags\");\n#elif defined(__i386__)\n  /* write(child_to_parent_fds[1], buf, 1) */\n  /* Use hand-rolled syscalls to avoid conditional branches (e.g. setting errno) */\n  __asm__ __volatile__ (\"int $0x80\" : : \"a\"(__NR_write), \"b\"(child_to_parent_fds[1]), \"c\"(\"x\"), \"d\"(1));\n  char buf;\n  /* read(parent_to_child_fds[0], buf, 1) */\n  __asm__ __volatile__ (\"int $0x80\" : : \"a\"(__NR_read), \"b\"(parent_to_child_fds[0]), \"c\"(&buf), \"d\"(1));\n#elif defined(__aarch64__)\n  /* write(child_to_parent_fds[1], buf, 1) */\n  register long x8 __asm__(\"x8\") = __NR_write;\n  register long x0 __asm__(\"x0\") = child_to_parent_fds[1];\n  register long x1 __asm__(\"x1\") = (long)\"x\";\n  register long x2 __asm__(\"x2\") = (long)1;\n  /* Use hand-rolled syscalls to avoid conditional branches (e.g. setting errno) */\n  __asm__ volatile(\"svc #0\\n\\t\"\n                   : \"+r\"(x0)\n                   : \"r\"(x1), \"r\"(x2), \"r\"(x8));\n  char buf;\n  x8 = __NR_read;\n  x0 = parent_to_child_fds[0];\n  x1 = (long)&buf;\n  x2 = (long)1;\n  /* read(parent_to_child_fds[0], buf, 1) */\n  __asm__ volatile(\"svc #0\\n\\t\"\n                   : \"+r\"(x0)\n                   : \"r\"(x1), \"r\"(x2), \"r\"(x8));\n#endif\n}\n\n#define NUM_ITERATIONS_BASIC 100000\n#define NUM_VOLATILE_UPDATES 1000\n#define NUM_ITERATIONS_SYSCALLS 100000\n\nstatic volatile long volatile_value;\n\nvoid test_ticks_basic(void) {\n  int i, j;\n  for (i = 0; i < NUM_ITERATIONS_BASIC; ++i) {\n    child_wait();\n    volatile_value = 0;\n    for (j = 0; j < NUM_VOLATILE_UPDATES; ++j) {\n      ++volatile_value;\n    }\n  }\n  child_wait();\n}\n\nvoid test_ticks_syscalls(void) {\n  int i, j;\n  char buf[1024];\n  for (i = 0; i < NUM_ITERATIONS_SYSCALLS; ++i) {\n    child_wait();\n    size_t buflen = i % sizeof(buf);\n    /* Use hand-rolled syscalls to avoid conditional branches (e.g. setting errno) */\n#if defined(__x86_64__)\n    __asm__ __volatile__ (\"syscall\" : : \"a\"(__NR_getrandom), \"D\"(buf), \"S\"(buflen), \"d\"(0) : \"rcx\", \"r11\", \"flags\");\n    __asm__ __volatile__ (\"syscall\" : : \"a\"(__NR_sched_yield) : \"rcx\", \"r11\", \"flags\");\n#elif defined(__i386__)\n    __asm__ __volatile__ (\"int $0x80\" : : \"a\"(__NR_getrandom), \"b\"(buf), \"c\"(buflen), \"d\"(0));\n    __asm__ __volatile__ (\"int $0x80\" : : \"a\"(__NR_sched_yield));\n#elif defined(__aarch64__)\n    register long x8 __asm__(\"x8\") = __NR_getrandom;\n    register long x0 __asm__(\"x0\") = (long)buf;\n    register long x1 __asm__(\"x1\") = buflen;\n    register long x2 __asm__(\"x2\") = 0;\n    __asm__ volatile(\"svc #0\\n\\t\"\n                     : \"+r\"(x0)\n                     : \"r\"(x1), \"r\"(x2), \"r\"(x8));\n    x8 = __NR_sched_yield;\n    __asm__ volatile(\"svc #0\\n\\t\"\n                     : \"+r\"(x0)\n                     : \"r\"(x8));\n#endif\n  }\n  child_wait();\n}\n\nvoid sighandler(int sig) {\n  child_wait();\n}\n\nvoid test_interrupts(void) {\n  /* wait for the parent to set the period */\n  child_wait();\n  /* Sync with the parent every time we get a signal */\n  signal(SIGIO, sighandler);\n  volatile_value = 0;\n  /* Loop forever. Eventually the parent will kill us. */\n  while (!volatile_value) {\n  }\n}\n\nstatic int do_child(void) {\n  if (do_test_ticks_basic) {\n    test_ticks_basic();\n  }\n  if (do_test_ticks_syscalls) {\n    test_ticks_syscalls();\n  }\n  test_interrupts();\n  return 0;\n}\n\ntypedef uint64_t Ticks;\n\nstatic void check_ticks(Ticks got, Ticks expected) {\n  if (got != expected) {\n    fprintf(stderr, \"Ticks mismatch; got %lld, expected %lld\\n\", (long long)got, (long long)expected);\n    abort();\n  }\n}\n\nstatic void reset_counter_period(int counter_fd, uint64_t period) {\n  CHECK(0 == ioctl(counter_fd, PERF_EVENT_IOC_DISABLE, 0));\n  CHECK(0 == ioctl(counter_fd, PERF_EVENT_IOC_RESET, 0));\n  CHECK(0 == ioctl(counter_fd, PERF_EVENT_IOC_PERIOD, &period));\n  CHECK(0 == ioctl(counter_fd, PERF_EVENT_IOC_ENABLE, 0));\n}\n\n/* Wait for child to pause, read counter value, reset the counter value,\n   resume the child, and report the read counter value */\nstatic Ticks reset_counting(pid_t child, int counter_fd, uint64_t period) {\n  char ch;\n  CHECK(1 == read(child_to_parent_fds[0], &ch, 1));\n  CHECK(ch == 'x');\n  Ticks ticks;\n  CHECK(sizeof(ticks) == read(counter_fd, &ticks, sizeof(ticks)));\n  reset_counter_period(counter_fd, period);\n  CHECK(1 == write(parent_to_child_fds[1], \"y\", 1));\n  return ticks;\n}\n\n#define MAX_PERIOD 0x1000000000000000LL\n\nint main(int argc, char** argv) {\n  int interrupt_tests = 1;\n  int interrupt_period = 1000000;\n\n  if (argc > 1) {\n    interrupt_tests = atoi(argv[1]);\n  }\n  if (argc > 2) {\n    interrupt_period = atoi(argv[2]);\n  }\n\n  // Assume CPU 0 for now.\n  CpuMicroarch uarch = compute_cpu_microarchs()[0];\n\n  const PmuConfig* pmu = NULL;\n  for (size_t i = 0; i < sizeof(pmu_configs)/sizeof(pmu_configs[0]); ++i) {\n    if (uarch == pmu_configs[i].uarch) {\n      pmu = &pmu_configs[i];\n      break;\n    }\n  }\n  CHECK(pmu);\n\n  do_test_ticks_basic = (pmu->flags & PMU_TICKS_RCB) != 0;\n  do_test_ticks_syscalls = (pmu->flags & PMU_TICKS_RCB) != 0;\n\n  CHECK(0 == pipe(parent_to_child_fds));\n  CHECK(0 == pipe(child_to_parent_fds));\n\n  pid_t child = fork();\n  if (!child) {\n    return do_child();\n  }\n  CHECK(child >= 0);\n\n  struct perf_event_attr perf_attr;\n  memset(&perf_attr, 0, sizeof(perf_attr));\n  perf_attr.type = PERF_TYPE_RAW;\n  perf_attr.size = sizeof(perf_attr);\n  perf_attr.config = pmu->rcb_cntr_event;\n  perf_attr.exclude_kernel = 1;\n  perf_attr.exclude_guest = 1;\n  perf_attr.pinned = 1;\n  perf_attr.sample_period = MAX_PERIOD;\n\n  int counter_fd = syscall(__NR_perf_event_open, &perf_attr, child, -1, -1, PERF_FLAG_FD_CLOEXEC);\n  CHECK(counter_fd >= 0);\n\n  if (do_test_ticks_basic) {\n    reset_counting(child, counter_fd, MAX_PERIOD);\n    for (int i = 0; i < NUM_ITERATIONS_BASIC; ++i) {\n      Ticks ticks = reset_counting(child, counter_fd, MAX_PERIOD);\n      /* NUM_VOLATILE_UPDATES conditional branches for the inner loop, plus one conditional branch\n         for the outer loop. */\n      int expect;\n      if (i == 0) {\n        if (ticks == NUM_VOLATILE_UPDATES + 1) {\n          expect = ticks;\n        } else {\n          expect = NUM_VOLATILE_UPDATES + 2;\n        }\n      } else {\n        expect = NUM_VOLATILE_UPDATES + 2;\n      }\n      check_ticks(ticks, expect);\n    }\n  }\n\n  if (do_test_ticks_syscalls) {\n    reset_counting(child, counter_fd, MAX_PERIOD);\n    for (int i = 0; i < NUM_ITERATIONS_SYSCALLS; ++i) {\n      Ticks ticks = reset_counting(child, counter_fd, MAX_PERIOD);\n      /* One conditional branch for the outer loop. */\n      check_ticks(ticks, 1);\n    }\n  }\n\n  /* program an interrupt */\n  CHECK(0 == fcntl(counter_fd, F_SETOWN, child));\n  CHECK(0 == fcntl(counter_fd, F_SETFL, O_ASYNC));\n\n  reset_counting(child, counter_fd, interrupt_period);\n  for (int i = 0; i < interrupt_tests; ++i) {\n    char ch;\n    CHECK(1 == read(child_to_parent_fds[0], &ch, 1));\n    CHECK(ch == 'x');\n    Ticks ticks;\n    CHECK(sizeof(ticks) == read(counter_fd, &ticks, sizeof(ticks)));\n    printf(\"Interrupted after %lld ticks, expected %lld ticks\\n\", (long long)ticks, (long long)interrupt_period);\n    CHECK(ticks >= interrupt_period);\n    if (ticks > interrupt_period + pmu->skid_size) {\n      fprintf(stderr, \"Skid %d exceeded :-(\\n\", pmu->skid_size);\n      fflush(stdout);\n      abort();\n    }\n    reset_counter_period(counter_fd, interrupt_period);\n    CHECK(1 == write(parent_to_child_fds[1], \"y\", 1));\n  }\n\n  kill(child, SIGKILL);\n  int status;\n  CHECK(child == waitpid(child, &status, 0));\n  CHECK(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n\n  puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/cpp_supplement.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_CPP_SUPPLEMENT_H_\n#define RR_CPP_SUPPLEMENT_H_\n\n#if __cplusplus == 201103L\n\n/**\n * Implementation of make_unique for C++11 (from https://herbsutter.com/gotw/_102/).\n */\ntemplate<typename T, typename ...Args>\nstd::unique_ptr<T> make_unique( Args&& ...args )\n{\n    return std::unique_ptr<T>( new T( std::forward<Args>(args)... ) );\n}\n\n#endif /* __cplusplus == 201103L */\n\n#endif\n"
  },
  {
    "path": "src/exec_stub.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\nvoid _start(void) {}\n"
  },
  {
    "path": "src/extra_version_string.h.in",
    "content": "#ifndef RR_EXTRA_VERSION_STRING_H_\n#define RR_EXTRA_VERSION_STRING_H_\n\n#define EXTRA_VERSION_STRING \"@EXTRA_VERSION_STRING@\"\n\n#endif\n"
  },
  {
    "path": "src/fast_forward.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"fast_forward.h\"\n\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstruct InstructionBuf {\n  SupportedArch arch;\n  uint8_t code_buf[32];\n  int code_buf_len;\n};\n\nstatic InstructionBuf read_instruction(Task* t, remote_code_ptr ip) {\n  InstructionBuf result;\n  result.arch = t->arch();\n  result.code_buf_len = (int)t->read_bytes_fallible(\n      ip.to_data_ptr<uint8_t>(), sizeof(result.code_buf), result.code_buf);\n  return result;\n}\n\nstruct DecodedInstruction {\n  int operand_size;\n  int address_size;\n  int length;\n  bool modifies_flags;\n  bool uses_si;\n  bool is_repne;\n};\n\n/**\n * This can be conservative: for weird prefix combinations that make valid\n * string instructions, but aren't ever used in practice, we can return false.\n */\nstatic bool decode_x86_string_instruction(const InstructionBuf& code,\n                                          DecodedInstruction* decoded) {\n  bool found_operand_prefix = false;\n  bool found_address_prefix = false;\n  bool found_REP_prefix = false;\n  bool found_REXW_prefix = false;\n\n  decoded->modifies_flags = false;\n  decoded->uses_si = false;\n  decoded->is_repne = false;\n\n  int i;\n  bool done = false;\n  for (i = 0; i < code.code_buf_len; ++i) {\n    switch (code.code_buf[i]) {\n      case 0x66:\n        found_operand_prefix = true;\n        break;\n      case 0x67:\n        found_address_prefix = true;\n        break;\n      case 0x48:\n        if (code.arch == x86_64) {\n          found_REXW_prefix = true;\n          break;\n        }\n        return false;\n      case 0xF2:\n        decoded->is_repne = true;\n        RR_FALLTHROUGH;\n      case 0xF3:\n        found_REP_prefix = true;\n        break;\n      case 0xA4: // MOVSB\n      case 0xA5: // MOVSW\n        decoded->uses_si = true;\n        done = true;\n        break;\n      case 0xAA: // STOSB\n      case 0xAB: // STOSW\n      case 0xAC: // LODSB\n      case 0xAD: // LODSW\n        done = true;\n        break;\n      case 0xA6: // CMPSB\n      case 0xA7: // CMPSW\n        decoded->modifies_flags = true;\n        decoded->uses_si = true;\n        done = true;\n        break;\n      case 0xAE: // SCASB\n      case 0xAF: // SCASW\n        decoded->modifies_flags = true;\n        done = true;\n        break;\n      default:\n        return false;\n    }\n    if (done) {\n      break;\n    }\n  }\n\n  if (!found_REP_prefix) {\n    return false;\n  }\n\n  decoded->length = i + 1;\n  if (code.code_buf[i] & 1) {\n    decoded->operand_size =\n        found_REXW_prefix ? 8 : (found_operand_prefix ? 2 : 4);\n  } else {\n    decoded->operand_size = 1;\n  }\n  decoded->address_size = found_address_prefix ? 4 : 8;\n  return true;\n}\n\nstatic bool mem_intersect(remote_ptr<void> a1, int s1, remote_ptr<void> a2,\n                          int s2) {\n  DEBUG_ASSERT(a1 + s1 > a1);\n  DEBUG_ASSERT(a2 + s2 > a2);\n  return max(a1, a2) < min(a1 + s1, a2 + s2);\n}\n\nstatic void bound_iterations_for_watchpoint(Task* t, remote_ptr<void> reg,\n                                            const DecodedInstruction& decoded,\n                                            const WatchConfig& watch,\n                                            uintptr_t* iterations) {\n  if (watch.num_bytes == 0) {\n    // Ignore zero-sized watch. It can't ever trigger.\n    return;\n  }\n\n  // Compute how many iterations it will take before we hit the watchpoint.\n  // 0 means the first iteration will hit the watchpoint.\n  int size = decoded.operand_size;\n  int direction = t->regs().df_flag() ? -1 : 1;\n\n  if (mem_intersect(reg, size, watch.addr, watch.num_bytes)) {\n    *iterations = 0;\n    return;\n  }\n\n  // Number of iterations we can perform without triggering the watchpoint\n  uintptr_t steps;\n  if (direction > 0) {\n    if (watch.addr < reg) {\n      // We're assuming wraparound can't happen!\n      return;\n    }\n    // We'll hit the first byte of the watchpoint moving forward.\n    steps = (watch.addr - reg) / size;\n  } else {\n    if (watch.addr > reg) {\n      // We're assuming wraparound can't happen!\n      return;\n    }\n    // We'll hit the last byte of the watchpoint moving backward.\n    steps = (reg - (watch.addr + watch.num_bytes)) / size + 1;\n  }\n\n  *iterations = min(*iterations, steps);\n}\n\nFastForwardStatus fast_forward_through_instruction(Task* t, ResumeRequest how,\n                                                   const vector<const Registers*>& states) {\n  DEBUG_ASSERT(how == RESUME_SINGLESTEP || how == RESUME_SYSEMU_SINGLESTEP);\n  FastForwardStatus result;\n\n  remote_code_ptr ip = t->ip();\n\n  bool ok = t->resume_execution(how, RESUME_WAIT_NO_EXIT, RESUME_UNLIMITED_TICKS);\n  ASSERT(t, ok) << \"Tracee was killed\";\n  if (t->stop_sig() != SIGTRAP) {\n    // we might have stepped into a system call...\n    return result;\n  }\n\n  if (t->ip() != ip) {\n    return result;\n  }\n  if (t->vm()->get_breakpoint_type_at_addr(ip) != BKPT_NONE) {\n    // breakpoint must have fired\n    return result;\n  }\n  if (t->compute_trap_reasons().watchpoint) { \n    // watchpoint fired\n    return result;\n  }\n  for (auto& state : states) {\n    if (state->matches(t->regs())) {\n      return result;\n    }\n  }\n  if (!is_x86ish(t->arch())) {\n    return result;\n  }\n\n  InstructionBuf instruction_buf = read_instruction(t, ip);\n  DecodedInstruction decoded;\n  if (!decode_x86_string_instruction(instruction_buf, &decoded)) {\n    return result;\n  }\n  if (decoded.address_size != 8) {\n    ASSERT(t, false) << \"Address-size prefix on string instructions unsupported\";\n  }\n\n  remote_code_ptr limit_ip = ip + decoded.length;\n\n  // At this point we can be sure the instruction didn't trigger a syscall,\n  // so we no longer care about the value of |how|.\n\n  Registers extra_state_to_avoid;\n  vector<const Registers*> states_copy;\n  auto using_states = &states;\n\n  while (true) {\n    // This string instruction should execute until CX reaches 0 and\n    // we move to the next instruction, or we hit one of the states in\n    // |states|, or the ZF flag changes so that the REP stops, or we hit\n    // a watchpoint. (We can't hit a breakpoint during the loop since we\n    // already verified there isn't one set here.)\n\n    // We'll compute an upper bound on the number of string instruction\n    // iterations to execute, and execute just that many iterations by\n    // modifying CX, setting a breakpoint after the string instruction to catch it\n    // ending.\n    // Keep in mind that it's possible that states in |states| might\n    // belong to multiple independent loops of this string instruction, with\n    // registers reset in between the loops.\n\n    uintptr_t cur_cx = t->regs().cx();\n    if (cur_cx == 0) {\n      // Fake singlestep status for trap diagnosis\n      t->set_x86_debug_status(DS_SINGLESTEP);\n      // This instruction will be skipped entirely.\n      return result;\n    }\n    // There is at least one more iteration to go.\n    result.incomplete_fast_forward = true;\n\n    // Don't execute the last iteration of the string instruction. That\n    // simplifies code below that tries to emulate the register effects\n    // of singlestepping to predict if the next singlestep would result in a\n    // mark_vector state.\n    uintptr_t iterations = cur_cx - 1;\n\n    // Bound |iterations| to ensure we stop before reaching any |states|.\n    for (auto& state : *using_states) {\n      if (state->ip() == ip) {\n        uintptr_t dest_cx = state->cx();\n        if (dest_cx == 0) {\n          // This state represents entering the string instruction with CX==0,\n          // so we can't reach this state in the current loop.\n          continue;\n        }\n        if (dest_cx >= cur_cx) {\n          // This can't be reached in the current loop.\n          continue;\n        }\n        iterations = min(iterations, cur_cx - dest_cx - 1);\n      } else if (state->ip() == limit_ip) {\n        uintptr_t dest_cx = state->cx();\n        if (dest_cx >= cur_cx) {\n          // This can't be reached in the current loop.\n          continue;\n        }\n        iterations = min(iterations, cur_cx - dest_cx - 1);\n      }\n    }\n\n    // To stop before the ZF changes and we exit the loop, we don't bound\n    // the iterations here. Instead we run the loop, observe the ZF change,\n    // and then rerun the loop with the loop-exit state added to the |states|\n    // list. See below.\n\n    // A code watchpoint would already be hit if we're going to hit it.\n    // Check for data watchpoints that we might hit when reading/writing\n    // memory.\n    // Make conservative assumptions about the watchpoint type. Applying\n    // unnecessary watchpoints here will only result in a few more singlesteps.\n    // We do have to ignore SI if the instruction doesn't use it; otherwise\n    // a watchpoint which happens to match SI will appear to be hit on every\n    // iteration of the string instruction, which would be devastating.\n    for (auto& watch : t->vm()->all_watchpoints()) {\n      if (decoded.uses_si) {\n        bound_iterations_for_watchpoint(t, t->regs().si(), decoded, watch,\n                                        &iterations);\n      }\n      bound_iterations_for_watchpoint(t, t->regs().di(), decoded, watch,\n                                      &iterations);\n    }\n\n    if (iterations == 0) {\n      // Fake singlestep status for trap diagnosis\n      t->set_x86_debug_status(DS_SINGLESTEP);\n      return result;\n    }\n\n    LOG(debug) << \"x86-string fast-forward: \" << iterations\n               << \" iterations required (ip==\" << t->ip() << \")\";\n\n    Registers r = t->regs();\n\n    Registers tmp = r;\n    tmp.set_cx(iterations);\n    t->set_regs(tmp);\n    bool ok = t->vm()->add_breakpoint(limit_ip, BKPT_INTERNAL);\n    ASSERT(t, ok) << \"Failed to add breakpoint\";\n    // Watchpoints can fire spuriously because configure_watch_registers\n    // can increase the size of the watched area to conserve watch registers.\n    // So, disable watchpoints temporarily.\n    t->vm()->save_watchpoints();\n    t->vm()->remove_all_watchpoints();\n    ok = t->resume_execution(RESUME_CONT, RESUME_WAIT_NO_EXIT, RESUME_UNLIMITED_TICKS);\n    ASSERT(t, ok) << \"Tracee was killed\";\n    t->vm()->restore_watchpoints();\n    t->vm()->remove_breakpoint(limit_ip, BKPT_INTERNAL);\n    result.did_fast_forward = true;\n    // We should have reached the breakpoint\n    ASSERT(t, t->stop_sig() == SIGTRAP);\n    ASSERT(t, t->ip().undo_executed_bkpt(t->arch()) == limit_ip);\n    uintptr_t iterations_performed = iterations - t->regs().cx();\n    tmp = t->regs();\n    // Undo our change to CX value\n    tmp.set_cx(tmp.cx() + cur_cx - iterations);\n    if (decoded.modifies_flags &&\n        (t->regs().cx() > 0 ||\n         (decoded.is_repne && t->regs().zf_flag()) ||\n         (!decoded.is_repne && !t->regs().zf_flag()))) {\n      // String instructions that modify flags don't have non-register side\n      // effects, so we can reset registers to effectively unwind the loop.\n      // Then we try rerunning the loop again, adding this state as one to\n      // avoid stepping into. We shouldn't need to do this more than once!\n      ASSERT(t, states_copy.empty());\n      tmp.set_ip(limit_ip);\n      extra_state_to_avoid = tmp;\n      states_copy = states;\n      states_copy.push_back(&extra_state_to_avoid);\n      using_states = &states_copy;\n      t->set_regs(r);\n      continue;\n    }\n    // instructions that don't modify flags should not terminate too early.\n    ASSERT(t, t->regs().cx() == 0);\n    ASSERT(t, iterations_performed == iterations);\n    // We always end with at least one iteration to go in the string instruction,\n    // so we must have the IP of the string instruction.\n    tmp.set_ip(r.ip());\n    t->set_regs(tmp);\n\n    LOG(debug) << \"x86-string fast-forward done; ip()==\" << t->ip();\n    // Fake singlestep status for trap diagnosis\n    t->set_x86_debug_status(DS_SINGLESTEP);\n    return result;\n  }\n}\n\nstatic bool is_ignorable_prefix(Task* t, uint8_t byte) {\n  if (byte >= 0x40 && byte <= 0x4f) {\n    // REX prefix\n    return t->arch() == x86_64;\n  }\n  switch (byte) {\n    case 0x26: // ES override\n    case 0x2E: // CS override\n    case 0x36: // SS override\n    case 0x3E: // DS override\n    case 0x64: // FS override\n    case 0x65: // GS override\n    case 0x66: // operand-size override\n    case 0x67: // address-size override\n    case 0xF0: // LOCK\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic bool is_rep_prefix(uint8_t byte) { return byte == 0xF2 || byte == 0xF3; }\n\nstatic bool is_string_instruction(uint8_t byte) {\n  switch (byte) {\n    case 0xA4: // MOVSB\n    case 0xA5: // MOVSW\n    case 0xA6: // CMPSB\n    case 0xA7: // CMPSW\n    case 0xAA: // STOSB\n    case 0xAB: // STOSW\n    case 0xAC: // LODSB\n    case 0xAD: // LODSW\n    case 0xAE: // SCASB\n    case 0xAF: // SCASW\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic int fallible_read_byte(Task* t, remote_ptr<uint8_t> ip) {\n  uint8_t byte;\n  if (t->read_bytes_fallible(ip, 1, &byte) == 0) {\n    return -1;\n  }\n  return byte;\n}\n\n#if defined(__i386__) || defined(__x86_64__)\nbool is_x86_string_instruction_at(Task* t, remote_code_ptr ip) {\n  bool found_rep = false;\n  remote_ptr<uint8_t> bare_ip = ip.to_data_ptr<uint8_t>();\n  while (true) {\n    int byte = fallible_read_byte(t, bare_ip);\n    if (byte < 0) {\n      return false;\n    } else if (is_rep_prefix(byte)) {\n      found_rep = true;\n    } else if (is_string_instruction(byte)) {\n      return found_rep;\n    } else if (!is_ignorable_prefix(t, byte)) {\n      return false;\n    }\n    ++bare_ip;\n  }\n}\n#endif\n\nstatic bool is_string_instruction_before(Task* t, remote_code_ptr ip) {\n  remote_ptr<uint8_t> bare_ip = ip.to_data_ptr<uint8_t>();\n  --bare_ip;\n  int byte = fallible_read_byte(t, bare_ip);\n  if (byte < 0 || !is_string_instruction(byte)) {\n    return false;\n  }\n  while (true) {\n    --bare_ip;\n    int byte = fallible_read_byte(t, bare_ip);\n    if (byte < 0) {\n      return false;\n    } else if (is_rep_prefix(byte)) {\n      return true;\n    } else if (!is_ignorable_prefix(t, byte)) {\n      return false;\n    }\n  }\n}\n\nbool maybe_at_or_after_x86_string_instruction(Task* t) {\n  if (!is_x86ish(t->arch())) {\n    return false;\n  }\n\n  return is_x86_string_instruction_at(t, t->ip()) ||\n         is_string_instruction_before(t, t->ip());\n}\n\nbool at_x86_string_instruction(Task* t) {\n  if (!is_x86ish(t->arch())) {\n    return false;\n  }\n\n  return is_x86_string_instruction_at(t, t->ip());\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/fast_forward.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_FAST_FORWARD_H_\n#define RR_FAST_FORWARD_H_\n\n#include <vector>\n\n#include \"Task.h\"\n\nnamespace rr {\n\nclass Registers;\n\nstruct FastForwardStatus {\n  FastForwardStatus() : did_fast_forward(false), incomplete_fast_forward(false) {}\n  FastForwardStatus(const FastForwardStatus& other) = default;\n  FastForwardStatus& operator=(const FastForwardStatus& other) = default;\n  FastForwardStatus& operator|=(const FastForwardStatus& other) {\n    did_fast_forward |= other.did_fast_forward;\n    incomplete_fast_forward |= other.incomplete_fast_forward;\n    return *this;\n  }\n  bool did_fast_forward;\n  bool incomplete_fast_forward;\n};\n\n/**\n * Perform one or more synchronous singlesteps of |t|. Usually just does\n * one singlestep, except when a singlestep leaves the IP unchanged (i.e. a\n * single instruction represents a loop, such as an x86 REP-prefixed string\n * instruction).\n *\n * |how| must be either RESUME_SINGLESTEP or RESUME_SYSEMU_SINGLESTEP.\n *\n * We always perform at least one singlestep. We stop after a singlestep if\n * one of the following is true, or will be true after one more singlestep:\n * -- Any breakpoint or watchpoint has been triggered\n * -- IP has advanced to the next instruction\n * -- One of the register states in |states| (a null-terminated list)\n * has been reached.\n *\n * Spurious returns after any singlestep are also allowed.\n *\n * This will not add more than one tick to t->tick_count().\n *\n * Returns true if we did a fast-forward, false if we just did one regular\n * singlestep.\n */\nFastForwardStatus fast_forward_through_instruction(\n    Task* t, ResumeRequest how, const std::vector<const Registers*>& states);\n\n/**\n * Return true if the instruction at t->ip(), or the instruction immediately\n * before t->ip(), could be a REP-prefixed string instruction. It's OK to\n * return true if it's not really a string instruction (though for performance\n * reasons, this should be rare).\n */\nbool maybe_at_or_after_x86_string_instruction(Task* t);\n\n/* Return true if the instruction at t->ip() is a string instruction */\nbool at_x86_string_instruction(Task* t);\n\n#if defined(__i386__) || defined(__x86_64__)\nbool is_x86_string_instruction_at(Task* t, remote_code_ptr ip);\n#else\ninline bool is_x86_string_instruction_at(Task*, remote_code_ptr) {\n  return false;\n}\n#endif\n\n} // namespace rr\n\n#endif // RR_FAST_FORWARD_H_\n"
  },
  {
    "path": "src/ftrace/ftrace_helper.c",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define _GNU_SOURCE\n\n#include <dirent.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <pthread.h>\n#include <signal.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/select.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/types.h>\n#include <sys/un.h>\n#include <sys/user.h>\n#include <unistd.h>\n\n#ifndef F_GETPIPE_SZ\n#define F_GETPIPE_SZ 1032\n#endif\n\n#ifdef NDEBUG\n#undef NDEBUG\n#endif\n#include <assert.h>\n\n/*\n * ftrace_helper is a small server providing an interface to ftrace. It needs\n * to run as root, and lets non-root applications connect to it to control\n * ftracing.\n *\n * 'ftrace_helper <path>' creates an AF_UNIX socket at <path> and makes it\n * world-writable. Only one connection is allowed to this socket, then the\n * socket name is removed.\n * 'ftrace_helper' without arguments spawns itself with 'sudo' and creates the\n * socket at $HOME/.local/share/rr/ftrace.\n *\n * Over this connection the client can establish a series of sessions. All\n * messages from the client are newline-terminated and acked with a single\n * 'K' character.\n * To start a session the client sends a CPU number which is the only CPU\n * which will be traced (all traced processes must be affinity-bound to this\n * CPU). Then the client sends a series of PIDs, one per line, ending in\n * a blank line; these PIDs are the ones that will be traced. ftrace_helper\n * starts tracing those processes with the function_graph tracer.\n * ftrace_helper then sends the client a single 'F' character with a file\n * descriptor attached using SCM_RIGHTS. This fd is for the trace_marker file.\n * The client sends the string \"end\" to stop the session.\n *\n * Trace output is dumped to /tmp/ftrace_helper_out, owned by root but\n * world-readable, in trace-cmd raw format. Producing raw output is a bit\n * fiddly but it reduces overhead and lets us use \"splice\" to move data from\n * the kernel to the output file. On my laptop, at least, this is necessary\n * because saving \"trace_pipe\" loses events due to ringbuffer overrun and\n * using \"trace_pipe_raw\" does not.\n *\n * To view the output install trace-cmd and run\n *   trace-cmd report /tmp/ftrace_helper_out|less\n */\n\ninline static int check_cond(int cond) {\n  if (!cond) {\n    fprintf(stderr, \"FAILED: errno=%d (%s)\\n\", errno, strerror(errno));\n  }\n  return cond;\n}\n\nstatic void drop_sig(__attribute__((unused)) int sig) {}\n\n#define check(cond) assert(\"FAILED: !\" && check_cond(cond))\n\nstatic int out_fd;\nstatic void* do_echo(void* arg) {\n  int fd = *(int*)arg;\n  int pipe_fds[2];\n  ssize_t size;\n  check(0 == pipe(pipe_fds));\n  size = fcntl(pipe_fds[1], F_GETPIPE_SZ);\n  check(size > 0);\n  while (1) {\n    ssize_t ret2;\n    ssize_t ret = splice(fd, NULL, pipe_fds[1], NULL, size, SPLICE_F_MOVE);\n    if (ret == -1 && (errno == EBADF || errno == EINTR)) {\n      break;\n    }\n    check(ret >= 0);\n    ret2 = splice(pipe_fds[0], NULL, out_fd, NULL, ret,\n                  SPLICE_F_MOVE | SPLICE_F_NONBLOCK);\n    if (ret2 == -1 && (errno == EBADF || errno == EINTR)) {\n      break;\n    }\n    check(ret2 == ret);\n  }\n  return NULL;\n}\n\nstatic void chdir_to_tracing(void) {\n  int ret = chdir(\"/sys/kernel/debug\");\n  if (ret < 0 && errno == ENOENT) {\n    fprintf(stderr, \"/sys/kernel/debug not found; debugfs not mounted?\\n\");\n    exit(1);\n  }\n  if (ret < 0 && errno == EACCES) {\n    fprintf(stderr, \"Cannot chdir to /sys/kernel/debug; run this as root\\n\");\n    exit(1);\n  }\n  check(ret == 0);\n\n  ret = chdir(\"tracing\");\n  if (ret < 0 && errno == ENOENT) {\n    fprintf(stderr,\n            \"/sys/kernel/debug/tracing not found; tracing not enabled?\\n\");\n    exit(1);\n  }\n  check(ret == 0);\n}\n\nstatic void copy_file_data(int final_fd, int in_fd) {\n  char buf[64 * 1024];\n  while (1) {\n    ssize_t ret = read(in_fd, buf, sizeof(buf));\n    check(ret >= 0);\n    if (!ret) {\n      break;\n    }\n    check(ret == write(final_fd, buf, ret));\n  }\n}\n\nstatic void copy_trace_file(int final_fd, const char* name, int size_len) {\n  char buf[1024];\n  int fd = open(name, O_RDONLY);\n  check(fd >= 0);\n  uint64_t len = 0;\n  while (1) {\n    ssize_t ret = read(fd, buf, sizeof(buf));\n    check(ret >= 0);\n    if (!ret) {\n      break;\n    }\n    len += ret;\n  }\n  check(0 == lseek(fd, 0, SEEK_SET));\n\n  /* XXX assumes little-endian */\n  check(size_len == write(final_fd, &len, size_len));\n  copy_file_data(final_fd, fd);\n  check(0 == close(fd));\n}\n\nstatic void copy_trace_file_with_name(int final_fd, const char* name,\n                                      int size_len) {\n  const char* bare_name = strrchr(name, '/');\n  if (bare_name) {\n    ++bare_name;\n  } else {\n    bare_name = name;\n  }\n  check((ssize_t)strlen(bare_name) + 1 ==\n        write(final_fd, bare_name, strlen(bare_name) + 1));\n  copy_trace_file(final_fd, name, size_len);\n}\n\nstatic int iterate_events(int final_fd, const char* dir, int write) {\n  int count = 0;\n  DIR* d = opendir(dir);\n  check(d != NULL);\n  while (1) {\n    char* buf;\n    struct dirent* e = readdir(d);\n    if (!e) {\n      break;\n    }\n    int ret = asprintf(&buf, \"%s/%s/format\", dir, e->d_name);\n    if (ret >= 0 && access(buf, F_OK) == 0) {\n      if (write) {\n        copy_trace_file(final_fd, buf, 8);\n      }\n      ++count;\n    }\n    free(buf);\n  }\n  check(0 == closedir(d));\n  return count;\n}\n\nstatic uint64_t file_offset(int fd) {\n  off_t offset = lseek(fd, 0, SEEK_CUR);\n  check(offset != (off_t)-1);\n  return offset;\n}\n\nsize_t page_size(void) {\n  static size_t size = 0;\n  if (!size) {\n    size = sysconf(_SC_PAGE_SIZE);\n  }\n  return size;\n}\n\nstatic uint64_t pad_output_to_page_size(int fd) {\n  char *buf = alloca(page_size());\n  uint64_t offset = file_offset(fd);\n  memset(buf, 0, page_size());\n  ssize_t pad = ((offset + page_size() - 1) & ~(page_size() - 1)) - offset;\n  check(pad == write(fd, buf, pad));\n  return offset + pad;\n}\n\nstatic void write_final_output(void) {\n  int final_fd;\n  static const char magic[] = { 23,          8,   68,  't', 'r', 'a', 'c',\n                                'i',         'n', 'g', '6', 0, /* file version\n                                                                  */\n                                0, /* little-endian */\n                                sizeof(long) };\n  const uint32_t psize = page_size();\n  uint32_t ftrace_count;\n  static const uint32_t zero = 0;\n  static const uint32_t cpus = 1;\n  static const char options[] = \"options  \";\n  static const uint16_t options_done = 0;\n  static const char fly_record[] = \"flyrecord\";\n  uint64_t cpu_data[2] = { 0, 0 };\n  uint64_t cpu_data_offset;\n\n  final_fd = open(\"/tmp/ftrace_helper_out\", O_WRONLY | O_TRUNC | O_CREAT, 0644);\n  check(final_fd >= 0);\n\n  check(sizeof(magic) == write(final_fd, magic, sizeof(magic)));\n  check(sizeof(psize) == write(final_fd, &psize, sizeof(psize)));\n\n  copy_trace_file_with_name(final_fd, \"events/header_page\", 8);\n  copy_trace_file_with_name(final_fd, \"events/header_event\", 8);\n  ftrace_count = iterate_events(final_fd, \"events/ftrace\", 0);\n  check(sizeof(ftrace_count) ==\n        write(final_fd, &ftrace_count, sizeof(ftrace_count)));\n  iterate_events(final_fd, \"events/ftrace\", 1);\n  /* Write no events (for now) */\n  check(sizeof(zero) == write(final_fd, &zero, sizeof(zero)));\n  copy_trace_file(final_fd, \"/proc/kallsyms\", 4);\n  copy_trace_file(final_fd, \"printk_formats\", 4);\n  copy_trace_file(final_fd, \"saved_cmdlines\", 8);\n  check(sizeof(cpus) == write(final_fd, &cpus, sizeof(cpus)));\n  check(sizeof(options) == write(final_fd, &options, sizeof(options)));\n  check(sizeof(options_done) ==\n        write(final_fd, &options_done, sizeof(options_done)));\n  check(sizeof(fly_record) == write(final_fd, fly_record, sizeof(fly_record)));\n  cpu_data_offset = file_offset(final_fd);\n  check(sizeof(cpu_data) == write(final_fd, cpu_data, sizeof(cpu_data)));\n  copy_trace_file(final_fd, \"trace_clock\", 8);\n  cpu_data[0] = pad_output_to_page_size(final_fd);\n  cpu_data[1] = file_offset(out_fd);\n  check(0 == lseek(out_fd, 0, SEEK_SET));\n  copy_file_data(final_fd, out_fd);\n  check(cpu_data_offset ==\n        (uint64_t)lseek(final_fd, cpu_data_offset, SEEK_SET));\n  check(sizeof(cpu_data) == write(final_fd, cpu_data, sizeof(cpu_data)));\n  check(0 == close(final_fd));\n}\n\nstatic int control_fd = -1;\nstatic char control_buf[1024];\nstatic size_t control_buf_len = 0;\n\nstatic void open_control_fd(const char* path) {\n  struct sockaddr_un addr;\n  int listen_fd = socket(AF_UNIX, SOCK_STREAM, 0);\n  check(listen_fd >= 0);\n\n  addr.sun_family = AF_UNIX;\n  if (strlen(path) + 1 > sizeof(addr.sun_path)) {\n    fprintf(stderr, \"Socket path %s too long\\n\", path);\n    exit(1);\n  }\n  strcpy(addr.sun_path, path);\n  unlink(path);\n  check(0 == bind(listen_fd, (struct sockaddr*)&addr, sizeof(addr)));\n  check(0 == chmod(path, 0666));\n  check(0 == listen(listen_fd, 1));\n  control_fd = accept(listen_fd, NULL, NULL);\n  check(control_fd >= 0);\n  check(0 == close(listen_fd));\n  check(0 == unlink(path));\n}\n\nstatic int trace_pipe_fd = -1;\nstatic pthread_t echo_thread;\n\nstatic void write_file(const char* file, const char* value) {\n  int fd = open(file, O_WRONLY | O_TRUNC);\n  ssize_t ret;\n  check(fd >= 0);\n  ret = write(fd, value, strlen(value));\n  check((ssize_t)strlen(value) == ret);\n  check(0 == close(fd));\n}\n\nstatic void stop_tracing(void) {\n  write_file(\"tracing_on\", \"0\");\n\n  if (trace_pipe_fd >= 0) {\n    check(0 == close(trace_pipe_fd));\n    trace_pipe_fd = -1;\n  }\n\n  if (echo_thread) {\n    /* The thread might already have exited */\n    pthread_kill(echo_thread, SIGUSR1);\n    check(0 == pthread_join(echo_thread, NULL));\n    memset(&echo_thread, 0, sizeof(echo_thread));\n  }\n\n  /* Do this last; we can't change current_tracer while those files are open */\n  write_file(\"current_tracer\", \"nop\");\n}\n\n#define MAX_LINE_SIZE 65536\nstatic void read_control_line(char out[MAX_LINE_SIZE]) {\n  size_t out_pos = 0;\n\n  while (1) {\n    size_t i;\n    if (!control_buf_len) {\n      int ret = read(control_fd, control_buf, sizeof(control_buf));\n      check(ret >= 0);\n      if (!ret) {\n        stop_tracing();\n        write_final_output();\n        exit(2);\n      }\n      control_buf_len = ret;\n    }\n    for (i = 0; i < control_buf_len; ++i) {\n      check(out_pos < MAX_LINE_SIZE);\n      if (control_buf[i] == '\\n') {\n        out[out_pos] = 0;\n        ++i;\n        memmove(control_buf, control_buf + i, control_buf_len - i);\n        control_buf_len -= i;\n        return;\n      }\n      out[out_pos] = control_buf[i];\n      ++out_pos;\n    }\n  }\n}\n\nstatic void ack_control_message(void) { check(1 == write(control_fd, \"K\", 1)); }\n\nstatic void send_marker_fd(void) {\n  char cmsgbuf[CMSG_SPACE(sizeof(int))];\n  struct msghdr msg;\n  struct iovec data;\n  struct cmsghdr* cmsg = (struct cmsghdr*)cmsgbuf;\n  int trace_marker_fd = open(\"trace_marker\", O_WRONLY);\n  check(trace_marker_fd >= 0);\n\n  data.iov_base = \"F\";\n  data.iov_len = 1;\n\n  memset(&msg, 0, sizeof(msg));\n  msg.msg_control = cmsgbuf;\n  msg.msg_controllen = sizeof(cmsgbuf);\n  msg.msg_iov = &data;\n  msg.msg_iovlen = 1;\n\n  cmsg->cmsg_len = CMSG_LEN(sizeof(int));\n  cmsg->cmsg_level = SOL_SOCKET;\n  cmsg->cmsg_type = SCM_RIGHTS;\n  memcpy(CMSG_DATA(cmsg), &trace_marker_fd, sizeof(int));\n\n  check(1 == sendmsg(control_fd, &msg, 0));\n  check(0 == close(trace_marker_fd));\n}\n\nstatic void process_control_session(void) {\n  char buf[MAX_LINE_SIZE];\n  char path[PATH_MAX];\n  int cpu;\n  int ftrace_pid_fd;\n  char buf_out[65536];\n  char* buf_out_ptr = buf_out;\n\n  read_control_line(buf);\n  cpu = atoi(buf);\n\n  while (1) {\n    read_control_line(buf);\n    if (buf[0] == 0) {\n      break;\n    }\n\n    if (buf_out_ptr + strlen(buf) >= buf_out + sizeof(buf_out)) {\n      break;\n    }\n    buf_out_ptr += sprintf(buf_out_ptr, \"%s\\n\", buf);\n  }\n\n  ftrace_pid_fd = open(\"set_ftrace_pid\", O_WRONLY | O_TRUNC);\n  check(ftrace_pid_fd >= 0);\n  check(buf_out_ptr - buf_out ==\n        write(ftrace_pid_fd, buf_out, buf_out_ptr - buf_out));\n  check(0 == close(ftrace_pid_fd));\n\n  write_file(\"current_tracer\", \"function_graph\");\n\n  send_marker_fd();\n\n  sprintf(path, \"per_cpu/cpu%d/trace_pipe_raw\", cpu);\n  trace_pipe_fd = open(path, O_RDONLY);\n  check(trace_pipe_fd >= 0);\n  check(0 == pthread_create(&echo_thread, NULL, do_echo, &trace_pipe_fd));\n\n  write_file(\"tracing_on\", \"1\");\n  ack_control_message();\n\n  read_control_line(buf);\n  check(!strcmp(buf, \"end\"));\n\n  ack_control_message();\n  stop_tracing();\n  write_final_output();\n}\n\nint main(int argc, const char** argv) {\n  if (argc == 1) {\n    char* control_path;\n    int ret =\n        asprintf(&control_path, \"%s/.local/share/rr/ftrace\", getenv(\"HOME\"));\n    if (ret >= 0) {\n      execlp(\"sudo\", \"sudo\", argv[1], control_path, NULL);\n    }\n    fprintf(stderr, \"Can't exec 'sudo'\\n\");\n    return 1;\n  }\n\n  signal(SIGUSR1, drop_sig);\n\n  chdir_to_tracing();\n  open_control_fd(argv[1]);\n\n  unlink(\"/tmp/ftrace_helper_out\");\n  out_fd = open(\"/tmp/ftrace_helper_tmp\", O_RDWR | O_TRUNC | O_CREAT, 0644);\n  check(out_fd >= 0);\n  check(0 == unlink(\"/tmp/ftrace_helper_tmp\"));\n\n  while (1) {\n    process_control_session();\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/ftrace.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"ftrace.h\"\n\n#include <limits.h>\n#include <sys/socket.h>\n#include <sys/types.h>\n#include <sys/uio.h>\n#include <sys/un.h>\n\n#include <sstream>\n\n#include \"ScopedFd.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n#include \"core.h\"\n#include \"log.h\"\n\nusing namespace std;\n\nnamespace rr {\nnamespace ftrace {\n\nstatic ScopedFd control_fd;\n// This needs to be a pointer since we may need to check it during logging that\n// happens in life-before-main.\nstatic ScopedFd* marker_fd = nullptr;\nstatic bool tracing = false;\n\nstatic void open_socket() {\n  string s = string(getenv(\"HOME\")) + \"/.local/share/rr/ftrace\";\n  control_fd = ScopedFd(socket(AF_UNIX, SOCK_STREAM, 0));\n  if (control_fd < 0) {\n    FATAL() << \"Cannot create socket\";\n  }\n  DEBUG_ASSERT(control_fd >= 0);\n  struct sockaddr_un addr;\n  addr.sun_family = AF_UNIX;\n  if (s.size() + 1 > sizeof(addr.sun_path)) {\n    FATAL() << \"Pathname '\" << s << \"' too long\";\n  }\n  strcpy(addr.sun_path, s.c_str());\n  int ret = connect(control_fd, (struct sockaddr*)&addr, sizeof(addr));\n  if (ret < 0 && (errno == ENOENT || errno == ECONNREFUSED)) {\n    FATAL() << \"ftrace-helper not running. Run ftrace-helper first.\";\n  }\n  if (ret < 0) {\n    FATAL() << \"Can't connect to socket \" << s;\n  }\n}\n\nstatic void write_control_message(const string& s) {\n  ssize_t ret = ::write(control_fd, s.c_str(), s.size());\n  if (ret != (ssize_t)s.size()) {\n    FATAL() << \"Can't write line to socket \" << s;\n  }\n}\n\nstatic void wait_for_reply() {\n  char ch;\n  if (read(control_fd, &ch, 1) != 1) {\n    FATAL() << \"Can't read reply from socket\";\n  }\n}\n\nstatic void receive_marker_fd() {\n  char received_data;\n  struct iovec msgdata;\n  msgdata.iov_base = &received_data;\n  msgdata.iov_len = 1;\n\n  char cmsgbuf[CMSG_SPACE(sizeof(int))];\n  struct msghdr msg;\n  memset(&msg, 0, sizeof(msg));\n  msg.msg_control = cmsgbuf;\n  msg.msg_controllen = sizeof(cmsgbuf);\n  msg.msg_iov = &msgdata;\n  msg.msg_iovlen = 1;\n\n  if (0 > recvmsg(control_fd, &msg, 0)) {\n    FATAL() << \"Failed to receive fd\";\n  }\n  DEBUG_ASSERT(received_data == 'F');\n\n  struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);\n  DEBUG_ASSERT(cmsg && cmsg->cmsg_level == SOL_SOCKET &&\n               cmsg->cmsg_type == SCM_RIGHTS);\n  marker_fd = new ScopedFd(*(int*)CMSG_DATA(cmsg));\n  DEBUG_ASSERT(marker_fd->is_open());\n}\n\nvoid start_function_graph(const Session& session, const TraceStream& trace) {\n  if (tracing) {\n    return;\n  }\n\n  if (!control_fd.is_open()) {\n    open_socket();\n  }\n\n  stringstream ss;\n  ss << trace.bound_to_cpu() << \"\\n\";\n\n  ss << getpid() << \"\\n\";\n  for (auto& it : session.tasks()) {\n    ss << it.second->tid << \"\\n\";\n  }\n  ss << \"\\n\";\n\n  write_control_message(ss.str());\n\n  receive_marker_fd();\n\n  wait_for_reply();\n  tracing = true;\n}\n\nvoid write(const string& str) {\n  if (!marker_fd) {\n    return;\n  }\n  size_t last_start = 0;\n  for (size_t i = 0; i < str.size(); ++i) {\n    if (str[i] == '\\n') {\n      if (i > last_start) {\n        string s = str.substr(last_start, i + 1 - last_start);\n        ssize_t ret = ::write(*marker_fd, s.c_str(), s.size());\n        if (ret != (ssize_t)s.size()) {\n          FATAL() << \"Can't write line to socket \" << s;\n        }\n      }\n      last_start = i + 1;\n    }\n  }\n}\n\nvoid stop() {\n  if (tracing) {\n    marker_fd->close();\n    delete marker_fd;\n    marker_fd = nullptr;\n    write_control_message(\"end\\n\");\n    wait_for_reply();\n    tracing = false;\n  }\n}\n}\n}\n"
  },
  {
    "path": "src/ftrace.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_FTRACE_H_\n#define RR_FTRACE_H_\n\n#include <unistd.h>\n\n#include <string>\n\n#include \"TraceStream.h\"\n\nnamespace rr {\n\nclass Session;\n\n/*\n * API for starting/stopping the Linux ftrace API. This uses the support\n * process 'ftrace_helper'. It's only for debugging rr.\n */\n\nnamespace ftrace {\n\n/**\n * Start kernel function-graph tracing. The processes of 'session', plus\n * rr itself, are traced. bin/ftrace_helper must have been started manually\n * before this gets called.\n */\nvoid start_function_graph(const Session& session, const TraceStream& trace);\n\n/**\n * Write a marker to the ftrace file. 'str' should be newline-terminated.\n */\nvoid write(const std::string& str);\n\n/**\n * Stop tracing.\n */\nvoid stop();\n}\n\n} // namespace rr\n\n#endif /* RR_FTRACE_H_ */\n"
  },
  {
    "path": "src/generate_syscalls.py",
    "content": "#!/usr/bin/env python3\n\nimport assembly_templates\nfrom io import StringIO\nimport os\nimport string\nimport sys\nimport syscalls\n\ndef arch_syscall_number(arch, syscall):\n    s = getattr(syscall[1], arch)\n    if s == None:\n        s = -1\n    return s\n\ndef write_syscall_enum(f, arch):\n    f.write(\"enum Syscalls {\\n\")\n    undefined_syscall = -1\n    for name, obj in sorted(syscalls.all(), key=lambda x: arch_syscall_number(arch, x)):\n        syscall_number = getattr(obj, arch)\n        if syscall_number is not None:\n            enum_number = syscall_number\n        else:\n            enum_number = undefined_syscall\n            undefined_syscall -= 1\n        f.write(\"  %s = %d,\\n\" % (name, enum_number))\n    f.write(\"  SYSCALL_COUNT,\\n\")\n    f.write(\"};\\n\")\n    f.write(\"\\n\")\n\ndef write_syscall_enum_for_tests(f, arch):\n    f.write(\"enum Syscalls {\\n\")\n    undefined_syscall = -1\n    for name, obj in sorted(syscalls.all(), key=lambda x: arch_syscall_number(arch, x)):\n        syscall_number = getattr(obj, arch)\n        if syscall_number is not None:\n            enum_number = syscall_number\n        else:\n            enum_number = undefined_syscall\n            undefined_syscall -= 1\n        f.write(\"  RR_%s = %d,\\n\" % (name, enum_number))\n    f.write(\"};\\n\")\n    f.write(\"\\n\")\n\ndef write_syscallname_arch(f):\n    f.write(\"template <typename Arch> static std::string syscallname_arch(int syscall);\\n\")\n    f.write(\"\\n\");\n    for specializer, arch in [(\"X86Arch\", \"x86\"), (\"X64Arch\", \"x64\"), (\"ARM64Arch\", \"generic\")]:\n        f.write(\"template <> std::string syscallname_arch<%s>(int syscall) {\\n\" % specializer)\n        f.write(\"  switch (syscall) {\\n\");\n        def write_case(name):\n            f.write(\"    case %(specializer)s::%(syscall)s: return \\\"%(syscall)s\\\";\\n\"\n                    % { 'specializer': specializer, 'syscall': name })\n        for name, _ in syscalls.for_arch(arch):\n            write_case(name)\n        f.write(\"    default: {\")\n        f.write(\"      char buf[100];\")\n        f.write(\"      sprintf(buf, \\\"<unknown-syscall-%d>\\\", syscall);\")\n        f.write(\"      return buf;\\n\")\n        f.write(\"    }\\n\")\n        f.write(\"  }\\n\")\n        f.write(\"}\\n\")\n        f.write(\"\\n\")\n\ndef write_syscall_record_cases(f):\n    def write_recorder_for_arg(syscall, arg):\n        arg_descriptor = getattr(syscall, 'arg' + str(arg), None)\n        if isinstance(arg_descriptor, str):\n            f.write(\"    syscall_state.reg_parameter<%s>(%d);\\n\"\n                    % (arg_descriptor, arg))\n    for name, obj in syscalls.all():\n        # Irregular syscalls will be handled by hand-written code elsewhere.\n        if isinstance(obj, syscalls.RegularSyscall):\n            f.write(\"  case Arch::%s:\\n\" % name)\n            for arg in range(1,6):\n                write_recorder_for_arg(obj, arg)\n            f.write(\"    return PREVENT_SWITCH;\\n\")\n\nhas_syscall = string.Template(\"\"\"inline bool\nhas_${syscall}_syscall(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      return X86Arch::${syscall} >= 0;\n    case x86_64:\n      return X64Arch::${syscall} >= 0;\n    case aarch64:\n      return ARM64Arch::${syscall} >= 0;\n    default:\n      DEBUG_ASSERT(0 && \"unsupported architecture\");\n      return false;\n  }\n}\n\"\"\")\n\nis_syscall = string.Template(\"\"\"inline bool\nis_${syscall}_syscall(int syscallno, SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      return syscallno >= 0 && syscallno == X86Arch::${syscall};\n    case x86_64:\n      return syscallno >= 0 && syscallno == X64Arch::${syscall};\n    case aarch64:\n      return syscallno >= 0 && syscallno == ARM64Arch::${syscall};\n    default:\n      DEBUG_ASSERT(0 && \"unsupported architecture\");\n      return false;\n  }\n}\n\"\"\")\n\nsyscall_number = string.Template(\"\"\"inline int\nsyscall_number_for_${syscall}(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      DEBUG_ASSERT(X86Arch::${syscall} >= 0);\n      return X86Arch::${syscall};\n    case x86_64:\n      DEBUG_ASSERT(X64Arch::${syscall} >= 0);\n      return X64Arch::${syscall};\n    case aarch64:\n      DEBUG_ASSERT(ARM64Arch::${syscall} >= 0);\n      return ARM64Arch::${syscall};\n    default:\n      DEBUG_ASSERT(0 && \"unsupported architecture\");\n      return -1;\n  }\n}\n\"\"\")\n\ndef write_syscall_helper_functions(f):\n    def write_helpers(syscall):\n        subs = { 'syscall': syscall }\n        f.write(has_syscall.safe_substitute(subs))\n        f.write(is_syscall.safe_substitute(subs))\n        f.write(syscall_number.safe_substitute(subs))\n\n    for name, obj in syscalls.all():\n        write_helpers(name)\n\ndef write_check_syscall_numbers(f):\n    for name, obj in syscalls.all():\n        # XXX hard-coded to x86 currently\n        if not obj.x86:\n            continue\n        f.write(\"\"\"static_assert(X86Arch::%s == SYS_%s, \"Incorrect syscall number for %s\");\\n\"\"\"\n                % (name, name, name))\n\ngenerators_for = {\n    'AssemblyTemplates': lambda f: assembly_templates.generate(f),\n    'CheckSyscallNumbers': write_check_syscall_numbers,\n    'SyscallEnumsX86': lambda f: write_syscall_enum(f, 'x86'),\n    'SyscallEnumsX64': lambda f: write_syscall_enum(f, 'x64'),\n    'SyscallEnumsGeneric': lambda f: write_syscall_enum(f, 'generic'),\n    'SyscallEnumsForTestsX86': lambda f: write_syscall_enum_for_tests(f, 'x86'),\n    'SyscallEnumsForTestsX64': lambda f: write_syscall_enum_for_tests(f, 'x64'),\n    'SyscallEnumsForTestsGeneric': lambda f: write_syscall_enum_for_tests(f, 'generic'),\n    'SyscallnameArch': write_syscallname_arch,\n    'SyscallRecordCase': write_syscall_record_cases,\n    'SyscallHelperFunctions': write_syscall_helper_functions,\n}\n\ndef main(argv):\n    filename = argv[0]\n    base, extension = os.path.splitext(os.path.basename(filename))\n\n    if os.access(filename, os.F_OK):\n        with open(filename, 'r') as f:\n            before = f.read()\n    else:\n        before = \"\"\n\n    stream = StringIO()\n    generators_for[base](stream)\n    after = stream.getvalue()\n    stream.close()\n\n    if before != after:\n        with open(filename, 'w') as f:\n            f.write(after)\n\nif __name__ == '__main__':\n    main(sys.argv[1:])\n"
  },
  {
    "path": "src/git_revision.h.in",
    "content": "#ifndef RR_GIT_REVISION_H_\n#define RR_GIT_REVISION_H_\n\n#define GIT_REVISION \"@GIT_REVISION@\"\n\n#endif\n"
  },
  {
    "path": "src/kernel_abi.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n// Include remote_ptr.h first since it (indirectly) requires a definition of\n// ERANGE, which other headers below #undef :-(\n#include \"remote_ptr.h\"\n\n// Get all the kernel definitions so we can verify our alternative versions.\n#include <arpa/inet.h>\n#include <dirent.h>\n#include <elf.h>\n#include <fcntl.h>\n#include <linux/audit.h>\n#include <linux/capability.h>\n#include <linux/cdrom.h>\n#include <linux/ethtool.h>\n#include <linux/fb.h>\n#include <linux/fiemap.h>\n#include <linux/filter.h>\n#include <linux/futex.h>\n#include <linux/if_bonding.h>\n#include <linux/ipc.h>\n#include <linux/mqueue.h>\n#include <linux/msg.h>\n#include <linux/net.h>\n#include <linux/netfilter/x_tables.h>\n#include <linux/seccomp.h>\n#include <linux/sem.h>\n#include <linux/serial.h>\n#include <linux/shm.h>\n#include <linux/sockios.h>\n#include <linux/sysctl.h>\n#include <linux/usbdevice_fs.h>\n#include <linux/videodev2.h>\n#include <linux/vt.h>\n#include <linux/wireless.h>\n#include <mtd/mtd-user.h>\n#include <poll.h>\n#include <sched.h>\n#include <scsi/sg.h>\n#include <signal.h>\n#include <sound/asound.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <sys/epoll.h>\n#include <sys/ioctl.h>\n#include <sys/prctl.h>\n#include <sys/quota.h>\n#include <sys/resource.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/sysinfo.h>\n#include <sys/time.h>\n#include <sys/times.h>\n#include <sys/timex.h>\n#include <sys/un.h>\n#include <sys/user.h>\n#include <sys/utsname.h>\n#include <sys/vfs.h>\n#include <termios.h>\n\n// x86_only\n#if defined(__i386__) || defined(__x86_64__)\n#include <asm/prctl.h>\n#include <asm/ldt.h>\n#endif\n\n// Used to verify definitions in kernel_abi.h\nnamespace rr {\n#define RR_VERIFY_TYPE_ARCH(arch_, system_type_, rr_type_)                     \\\n  static_assert(Verifier<arch_, system_type_, rr_type_>::same_size,            \\\n                \"type \" #system_type_ \" not correctly defined\");\n\n// For instances where the system type and the rr type are named differently.\n#define RR_VERIFY_TYPE_EXPLICIT(system_type_, rr_type_)                        \\\n  RR_VERIFY_TYPE_ARCH(arch_, system_type_, rr_type_)\n\n// For instances where the system type and the rr type are named identically.\n#define RR_VERIFY_TYPE(type_) RR_VERIFY_TYPE_EXPLICIT(::type_, type_)\n\n#if defined(__i386__) || defined(__x86_64__)\n#define RR_VERIFY_TYPE_X86(type_) RR_VERIFY_TYPE(type_)\n#define RR_VERIFY_TYPE_X86_ARCH(arch_, system_type_, rr_type_) RR_VERIFY_TYPE_ARCH(arch_, system_type_, rr_type_)\n#endif\n}\n\n#include \"kernel_abi.h\"\n\n#include <stdlib.h>\n\n#include \"AddressSpace.h\"\n#include \"Session.h\"\n#include \"Task.h\"\n\n#include \"preload/preload_interface.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n#define CHECK_ELF(cond)                                                        \\\n  static_assert(cond, \"ELF constant defined incorrectly\" #cond)\n\nCHECK_ELF(ELFCLASSNONE == ELFCLASS::CLASSNONE);\nCHECK_ELF(ELFCLASS32 == ELFCLASS::CLASS32);\nCHECK_ELF(ELFCLASS64 == ELFCLASS::CLASS64);\n\nCHECK_ELF(EM_386 == EM::I386);\nCHECK_ELF(EM_X86_64 == EM::X86_64);\n\nCHECK_ELF(ELFDATA2LSB == ELFENDIAN::DATA2LSB);\n\nint to_audit_arch(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      return AUDIT_ARCH_I386;\n    case x86_64:\n      return AUDIT_ARCH_X86_64;\n#ifdef AUDIT_ARCH_AARCH64\n    case aarch64:\n      return AUDIT_ARCH_AARCH64;\n#endif\n    default:\n      FATAL() << \"Unknown architecture\";\n      return 0;\n  }\n}\n\nstatic const uint8_t int80_insn[] = { 0xcd, 0x80 };\nstatic const uint8_t sysenter_insn[] = { 0x0f, 0x34 };\nstatic const uint8_t syscall_insn[] = { 0x0f, 0x05 };\nstatic const uint8_t svc0_insn[] = { 0x1, 0x0, 0x0, 0xd4 };\n\nbool get_syscall_instruction_arch(Task* t, remote_code_ptr ptr,\n                                  SupportedArch* arch,\n                                  bool* ok) {\n  if (ok) {\n    *ok = true;\n  }\n\n  // Lots of syscalls occur in the rr page and we know what it contains without\n  // looking at it.\n  // (Without this optimization we spend a few % of all CPU time in this\n  // function in a syscall-dominated trace.)\n  if (t->vm()->has_rr_page()) {\n    const AddressSpace::SyscallType* type =\n        AddressSpace::rr_page_syscall_from_entry_point(t->arch(), ptr);\n    if (type && (type->enabled == AddressSpace::RECORDING_AND_REPLAY ||\n                 type->enabled == (t->session().is_recording()\n                                       ? AddressSpace::RECORDING_ONLY\n                                       : AddressSpace::REPLAY_ONLY))) {\n      // rr-page syscalls are always the task's arch\n      *arch = t->arch();\n      return true;\n    }\n  }\n\n  if (!t->session().done_initial_exec()) {\n    // We're in rr, and all our syscalls are native.\n    *arch = NativeArch::arch();\n    return true;\n  }\n\n  if (!t->vm()->has_mapping(ptr.to_data_ptr<void>())) {\n    return false;\n  }\n\n  vector<uint8_t> code;\n  code.resize(syscall_instruction_length(t->arch()));\n  ssize_t bytes = t->read_bytes_fallible(ptr.to_data_ptr<void>(), code.size(), code.data());\n  if (bytes != (ssize_t)code.size()) {\n    if (ok) {\n      *ok = false;\n    }\n    return false;\n  }\n  switch (t->arch()) {\n    // Compatibility mode switch can happen in user space (but even without\n    // such tricks, int80, which uses the 32bit syscall table, can be invoked\n    // from 64bit processes).\n    case x86:\n    case x86_64:\n      if (memcmp(code.data(), int80_insn, sizeof(int80_insn)) == 0 ||\n          memcmp(code.data(), sysenter_insn, sizeof(sysenter_insn)) == 0) {\n        *arch = x86;\n      } else if (memcmp(code.data(), syscall_insn, sizeof(syscall_insn)) == 0) {\n        *arch = x86_64;\n      } else {\n        return false;\n      }\n      return true;\n    case aarch64:\n      *arch = aarch64;\n      return memcmp(code.data(), svc0_insn, sizeof(svc0_insn)) == 0;\n    default:\n      return false;\n  }\n}\n\nbool is_at_syscall_instruction(Task* t, remote_code_ptr ptr, bool* ok) {\n  SupportedArch arch;\n  return get_syscall_instruction_arch(t, ptr, &arch, ok);\n}\n\nvector<uint8_t> syscall_instruction(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      return vector<uint8_t>(int80_insn, int80_insn + sizeof(int80_insn));\n    case x86_64:\n      return vector<uint8_t>(syscall_insn, syscall_insn + sizeof(syscall_insn));\n    case aarch64:\n      return vector<uint8_t>(svc0_insn, svc0_insn + sizeof(svc0_insn));\n    default:\n      DEBUG_ASSERT(0 && \"Need to define syscall instruction\");\n      return vector<uint8_t>();\n  }\n}\n\nstatic ssize_t instruction_length(SupportedArch arch) {\n  switch (arch) {\n    case aarch64:\n      return 4;\n    default:\n      // x86 and x86_64 must be handled in the caller.\n      // Add new architectures here if all instructions have the same length,\n      // otherwise add them in the appropriate caller.\n      DEBUG_ASSERT(0 && \"Need to define instruction length\");\n      return 0;\n  }\n}\n\nssize_t syscall_instruction_length(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n    case x86_64:\n      return 2;\n    default:\n      return instruction_length(arch);\n  }\n}\n\nssize_t bkpt_instruction_length(SupportedArch arch) {\n  ssize_t val = 0;\n  switch (arch) {\n    case x86_64:\n    case x86:\n      val = 1;\n      break;\n    default:\n      val = instruction_length(arch);\n  }\n  DEBUG_ASSERT(val <= MAX_BKPT_INSTRUCTION_LENGTH);\n  return val;\n}\n\nssize_t movrm_instruction_length(SupportedArch arch) {\n  switch (arch) {\n    case x86:\n      return 2;\n    case x86_64:\n      return 3;\n    default:\n      return instruction_length(arch);\n  }\n}\n\nssize_t vsyscall_entry_length(SupportedArch arch) {\n  switch (arch) {\n    case x86_64:\n      return 9;\n    default:\n      DEBUG_ASSERT(0 && \"Vsyscall is only used on x86_64\");\n      return 0;\n  }\n}\n\ntemplate <typename Arch>\nstatic void assign_sigval(typename Arch::sigval_t& to,\n                          const NativeArch::sigval_t& from) {\n  // si_ptr/si_int are a union and we don't know which part is valid.\n  // The only case where it matters is when we're mapping 64->32, in which\n  // case we can just assign the ptr first (which is bigger) and then the\n  // int (to be endian-independent).\n  to.sival_ptr = from.sival_ptr.rptr();\n  to.sival_int = from.sival_int;\n}\n\ntemplate <typename Arch>\nstatic void set_arch_siginfo_arch(const siginfo_t& src, void* dest,\n                                  size_t dest_size) {\n  // Copying this structure field-by-field instead of just memcpy'ing\n  // siginfo into si serves two purposes: performs 64->32 conversion if\n  // necessary, and ensures garbage in any holes in siginfo isn't copied to the\n  // tracee.\n  auto si = static_cast<typename Arch::siginfo_t*>(dest);\n  DEBUG_ASSERT(dest_size == sizeof(*si));\n\n  union {\n    NativeArch::siginfo_t native_api;\n    siginfo_t linux_api;\n  } u;\n  u.linux_api = src;\n  auto& siginfo = u.native_api;\n\n  si->si_signo = siginfo.si_signo;\n  si->si_errno = siginfo.si_errno;\n  si->si_code = siginfo.si_code;\n  switch (siginfo.si_code) {\n    case SI_USER:\n    case SI_TKILL:\n      si->_sifields._kill.si_pid_ = siginfo._sifields._kill.si_pid_;\n      si->_sifields._kill.si_uid_ = siginfo._sifields._kill.si_uid_;\n      break;\n    case SI_QUEUE:\n    case SI_MESGQ:\n      si->_sifields._rt.si_pid_ = siginfo._sifields._rt.si_pid_;\n      si->_sifields._rt.si_uid_ = siginfo._sifields._rt.si_uid_;\n      assign_sigval<Arch>(si->_sifields._rt.si_sigval_,\n                          siginfo._sifields._rt.si_sigval_);\n      break;\n    case SI_TIMER:\n      si->_sifields._timer.si_overrun_ = siginfo._sifields._timer.si_overrun_;\n      si->_sifields._timer.si_tid_ = siginfo._sifields._timer.si_tid_;\n      assign_sigval<Arch>(si->_sifields._timer.si_sigval_,\n                          siginfo._sifields._timer.si_sigval_);\n      break;\n    default:\n      switch (siginfo.si_signo) {\n        case SIGCHLD:\n          si->_sifields._sigchld.si_pid_ = siginfo._sifields._sigchld.si_pid_;\n          si->_sifields._sigchld.si_uid_ = siginfo._sifields._sigchld.si_uid_;\n          si->_sifields._sigchld.si_status_ =\n              siginfo._sifields._sigchld.si_status_;\n          si->_sifields._sigchld.si_utime_ =\n              siginfo._sifields._sigchld.si_utime_;\n          si->_sifields._sigchld.si_stime_ =\n              siginfo._sifields._sigchld.si_stime_;\n          break;\n        case SIGILL:\n        case SIGBUS:\n        case SIGFPE:\n        case SIGSEGV:\n        case SIGTRAP:\n          si->_sifields._sigfault.si_addr_ =\n              siginfo._sifields._sigfault.si_addr_.rptr();\n          si->_sifields._sigfault.si_addr_lsb_ =\n              siginfo._sifields._sigfault.si_addr_lsb_;\n          break;\n        case SIGIO:\n          si->_sifields._sigpoll.si_band_ = siginfo._sifields._sigpoll.si_band_;\n          si->_sifields._sigpoll.si_fd_ = siginfo._sifields._sigpoll.si_fd_;\n          break;\n        case SIGSYS:\n          si->_sifields._sigsys._call_addr =\n              siginfo._sifields._sigsys._call_addr.rptr();\n          si->_sifields._sigsys._syscall = siginfo._sifields._sigsys._syscall;\n          si->_sifields._sigsys._arch = siginfo._sifields._sigsys._arch;\n          break;\n      }\n  }\n}\n\nvoid set_arch_siginfo(const siginfo_t& siginfo, SupportedArch a, void* dest,\n                      size_t dest_size) {\n  RR_ARCH_FUNCTION(set_arch_siginfo_arch, a, siginfo, dest, dest_size);\n}\n\ntemplate <typename Arch> static size_t sigaction_sigset_size_arch() {\n  return sizeof(typename Arch::kernel_sigset_t);\n}\n\nsize_t sigaction_sigset_size(SupportedArch arch) {\n  RR_ARCH_FUNCTION(sigaction_sigset_size_arch, arch);\n}\n\ntemplate <typename Arch> static size_t user_regs_struct_size_arch() {\n  return sizeof(typename Arch::user_regs_struct);\n}\n\nsize_t user_regs_struct_size(SupportedArch arch) {\n  RR_ARCH_FUNCTION(user_regs_struct_size_arch, arch)\n}\n\ntemplate <typename Arch> static size_t user_fpregs_struct_size_arch() {\n  return sizeof(typename Arch::user_fpregs_struct);\n}\n\nsize_t user_fpregs_struct_size(SupportedArch arch) {\n  RR_ARCH_FUNCTION(user_fpregs_struct_size_arch, arch)\n}\n\ntemplate <typename Arch> static uint8_t virtual_address_size_arch(remote_ptr<void> ptr) {\n  return sizeof(typename Arch::unsigned_word) * 8 - Arch::clz_ptr(ptr);\n}\n\nuint8_t virtual_address_size(SupportedArch arch, remote_ptr<void> ptr) {\n  RR_ARCH_FUNCTION(virtual_address_size_arch, arch, ptr)\n}\n\ntemplate <typename Arch> static uint8_t default_virtual_address_size_arch() {\n  return Arch::default_virtual_address_size;\n}\n\nuint8_t default_virtual_address_size(SupportedArch arch) {\n  RR_ARCH_FUNCTION(default_virtual_address_size_arch, arch)\n}\n\n}\n"
  },
  {
    "path": "src/kernel_abi.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_KERNEL_ABI_H\n#define RR_KERNEL_ABI_H\n\n#include <signal.h>\n\n#include <vector>\n\n#include \"core.h\"\n#include \"log.h\"\n#include \"remote_ptr.h\"\n\n#undef loff_t\n\nnamespace rr {\n\nclass remote_code_ptr;\nclass Task;\n\nenum SupportedArch { x86, x86_64, aarch64, SupportedArch_MAX = aarch64 };\n\n#if defined(__i386__)\nconst SupportedArch RR_NATIVE_ARCH = SupportedArch::x86;\n#elif defined(__x86_64__)\nconst SupportedArch RR_NATIVE_ARCH = SupportedArch::x86_64;\n#elif defined(__aarch64__)\nconst SupportedArch RR_NATIVE_ARCH = SupportedArch::aarch64;\n#else\n#error need to define new SupportedArch enum\n#endif\n\ninline bool is_x86ish(SupportedArch arch_) {\n  return arch_ == x86 || arch_ == x86_64;\n}\n\nint to_audit_arch(SupportedArch arch);\n\ntemplate <SupportedArch a, typename system_type, typename rr_type>\nstruct Verifier {\n  // Optimistically say we are the same size.\n  static const bool same_size = true;\n};\n\ntemplate <typename system_type, typename rr_type>\nstruct Verifier<RR_NATIVE_ARCH, system_type, rr_type> {\n  static const bool same_size = sizeof(system_type) == sizeof(rr_type);\n};\n\ntemplate <typename T> struct Verifier<RR_NATIVE_ARCH, T, T> {\n  // Prevent us from accidentally verifying the size of rr's structure\n  // with itself or (unlikely) the system's structure with itself.\n};\n\n// We want verify that the types have the same size as their\n// counterparts in the system header. To avoid having to include\n// all system headers here, we instead make the verification macros\n// a no-op unless included from kernel_abi.cc.\n#ifndef RR_VERIFY_TYPE\n#define RR_VERIFY_TYPE_ARCH(arch_, system_type_, rr_type_) // no-op\n#define RR_VERIFY_TYPE_EXPLICIT(system_type_, rr_type_)    // no-op\n#define RR_VERIFY_TYPE(x)                                  // no-op\n#endif\n\n// For structs whose native definitions only exist on x86\n#ifndef RR_VERIFY_TYPE_X86\n#define RR_VERIFY_TYPE_X86_ARCH(arch_, system_type_, rr_type_) // no-op\n#define RR_VERIFY_TYPE_X86(x)                                  // no-op\n#endif\n\nstruct KernelConstants {\n  // These are the same across all architectures. The kernel defines them for\n  // all architectures in the uapi headers, but the libc's headers may not.\n  // Further, the libc headers may conflict with the kernel headers, so for\n  // simplicity, we just define everything here:\n  static const int PTRACE_TRACEME = 0;\n  static const int PTRACE_PEEKTEXT = 1;\n  static const int PTRACE_PEEKDATA = 2;\n  static const int PTRACE_PEEKUSR = 3;\n  // PEEKUSER is a libc alias.\n  static const int PTRACE_PEEKUSER = PTRACE_PEEKUSR;\n  static const int PTRACE_POKETEXT = 4;\n  static const int PTRACE_POKEDATA = 5;\n  static const int PTRACE_POKEUSR = 6;\n  // POKEUSER is a libc alias.\n  static const int PTRACE_POKEUSER = PTRACE_POKEUSR;\n  static const int PTRACE_CONT = 7;\n  static const int PTRACE_KILL = 8;\n  static const int PTRACE_SINGLESTEP = 9;\n  // PTRACE_GETREGS actually does vary but it's 12 on every arch we care about.\n  static const int PTRACE_GETREGS = 12;\n  static const int PTRACE_GETFPREGS = 14;\n  static const int PTRACE_SETFPREGS = 15;\n  static const int PTRACE_ATTACH = 16;\n  static const int PTRACE_DETACH = 17;\n  static const int PTRACE_SYSCALL = 24;\n  static const int PTRACE_SETOPTIONS = 0x4200;\n  static const int PTRACE_GETEVENTMSG = 0x4201;\n  static const int PTRACE_GETSIGINFO = 0x4202;\n  static const int PTRACE_SETSIGINFO = 0x4203;\n  static const int PTRACE_GETREGSET = 0x4204;\n  static const int PTRACE_SETREGSET = 0x4205;\n  static const int PTRACE_SEIZE = 0x4206;\n  static const int PTRACE_INTERRUPT = 0x4207;\n  static const int PTRACE_LISTEN = 0x4208;\n  static const int PTRACE_GETSIGMASK = 0x420a;\n  static const int PTRACE_SETSIGMASK = 0x420b;\n  static const int PTRACE_GET_SYSCALL_INFO = 0x420e;\n\n  static const int PTRACE_EVENT_NONE = 0;\n  static const int PTRACE_EVENT_FORK = 1;\n  static const int PTRACE_EVENT_VFORK = 2;\n  static const int PTRACE_EVENT_CLONE = 3;\n  static const int PTRACE_EVENT_EXEC = 4;\n  static const int PTRACE_EVENT_VFORK_DONE = 5;\n  static const int PTRACE_EVENT_EXIT = 6;\n  static const int PTRACE_EVENT_SECCOMP = 7; // ubuntu 12.10 and future kernels\n  static const int PTRACE_EVENT_SECCOMP_OBSOLETE = 8; // ubuntu 12.04\n  static const int PTRACE_EVENT_STOP = 128;\n\n  static const int PTRACE_O_TRACESYSGOOD = 1;\n  static const int PTRACE_O_TRACEFORK = 1 << PTRACE_EVENT_FORK;\n  static const int PTRACE_O_TRACEVFORK = 1 << PTRACE_EVENT_VFORK;\n  static const int PTRACE_O_TRACECLONE = 1 << PTRACE_EVENT_CLONE;\n  static const int PTRACE_O_TRACEEXEC = 1 << PTRACE_EVENT_EXEC;\n  static const int PTRACE_O_TRACEVFORKDONE = 1 << PTRACE_EVENT_VFORK_DONE;\n  static const int PTRACE_O_TRACEEXIT = 1 << PTRACE_EVENT_EXIT;\n  static const int PTRACE_O_TRACESECCOMP = 1 << PTRACE_EVENT_SECCOMP;\n  static const int PTRACE_O_EXITKILL = 1 << 20;\n\n  static const int PTRACE_SYSCALL_INFO_NONE = 0;\n  static const int PTRACE_SYSCALL_INFO_ENTRY = 1;\n  static const int PTRACE_SYSCALL_INFO_EXIT = 2;\n  static const int PTRACE_SYSCALL_INFO_SECCOMP = 3;\n\n  static const ::size_t SIGINFO_MAX_SIZE = 128;\n\n  // These types are the same size everywhere.\n  typedef int32_t pid_t;\n  typedef uint32_t uid_t;\n  typedef uint32_t gid_t;\n  typedef uint32_t socklen_t;\n  typedef uint64_t dev_t;\n  typedef uint32_t mode_t;\n  typedef int32_t __kernel_timer_t;\n};\n\n// These duplicate the matching F_* constants for commands for fcntl, with two\n// small differences: we unconditionally define the *64 variants to their values\n// for 32-bit systems.  This change enables us to always use our constants in\n// switch cases without worrying about duplicated case values and makes dealing\n// with 32-bit and 64-bit tracees in the same rr process simpler.\n//\n// The other small difference is that we define these constants without the F_\n// prefix, so as to not run afoul of the C preprocessor.\nstruct FcntlConstants {\n  enum FcntlOperation {\n    DUPFD = 0,\n    GETFD = 1,\n    SETFD = 2,\n    GETFL = 3,\n    SETFL = 4,\n    GETLK = 5,\n    SETLK = 6,\n    SETLKW = 7,\n    SETOWN = 8,\n    GETOWN = 9,\n    SETSIG = 10,\n    GETSIG = 11,\n    GETLK64 = 12,\n    SETLK64 = 13,\n    SETLKW64 = 14,\n    SETOWN_EX = 15,\n    GETOWN_EX = 16,\n    // Open File descriptor locks (Linux specific)\n    OFD_GETLK = 36,\n    OFD_SETLK = 37,\n    OFD_SETLKW = 38,\n    // Other Linux-specific operations\n    SETLEASE = 0x400,\n    GETLEASE = 0x400 + 1,\n    NOTIFY = 0x400 + 2,\n    DUPFD_CLOEXEC = 0x400 + 6,\n    SETPIPE_SZ = 0x400 + 7,\n    GETPIPE_SZ = 0x400 + 8,\n    ADD_SEALS = 0x400 + 9,\n    GET_SEALS = 0x400 + 10,\n    GET_RW_HINT = 0x400 + 11,\n    SET_RW_HINT = 0x400 + 12,\n    GET_FILE_RW_HINT = 0x400 + 13,\n    SET_FILE_RW_HINT = 0x400 + 14,\n  };\n};\n\n// Various ELF constants we use. These are verified to be the same\n// as those in the system headers by kernel_abi.cc\nenum ELFCLASS { CLASSNONE = 0, CLASS32 = 1, CLASS64 = 2 };\nenum ELFENDIAN { DATA2LSB = 1 };\nenum EM {\n  I386 = 3,\n  X86_64 = 62,\n  AARCH64 = 183\n};\n\nstruct WordSize32Defs {\n  static const ::size_t SIGINFO_PAD_SIZE =\n      (KernelConstants::SIGINFO_MAX_SIZE / sizeof(int32_t)) - 3;\n\n  typedef int16_t signed_short;\n  typedef uint16_t unsigned_short;\n\n  typedef int32_t signed_int;\n  typedef uint32_t unsigned_int;\n\n  typedef int32_t signed_long;\n  typedef uint32_t unsigned_long;\n\n  typedef int32_t signed_word;\n  typedef uint32_t unsigned_word;\n\n  typedef uint32_t size_t;\n  typedef int32_t ssize_t;\n\n  // These really only exist as proper abstractions so that adding x32\n  // (x86-64's ILP32 ABI) support is relatively easy.\n  typedef int32_t syscall_slong_t;\n  typedef uint32_t syscall_ulong_t;\n  typedef int32_t sigchld_clock_t;\n  typedef uint32_t __statfs_word;\n\n  static const size_t elfclass = ELFCLASS::CLASS32;\n  typedef struct {\n    uint8_t e_ident[16];\n    uint16_t e_type;\n    uint16_t e_machine;\n    uint32_t e_version;\n    uint32_t e_entry;\n    uint32_t e_phoff;\n    uint32_t e_shoff;\n    uint32_t e_flags;\n    uint16_t e_ehsize;\n    uint16_t e_phentsize;\n    uint16_t e_phnum;\n    uint16_t e_shentsize;\n    uint16_t e_shnum;\n    uint16_t e_shstrndx;\n  } ElfEhdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Ehdr, ElfEhdr);\n  typedef struct {\n    uint32_t p_type;\n    uint32_t p_offset;\n    uint32_t p_vaddr;\n    uint32_t p_paddr;\n    uint32_t p_filesz;\n    uint32_t p_memsz;\n    uint32_t p_flags;\n    uint32_t p_align;\n  } ElfPhdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Phdr, ElfPhdr);\n  typedef struct {\n    uint32_t sh_name;\n    uint32_t sh_type;\n    uint32_t sh_flags;\n    uint32_t sh_addr;\n    uint32_t sh_offset;\n    uint32_t sh_size;\n    uint32_t sh_link;\n    uint32_t sh_info;\n    uint32_t sh_addralign;\n    uint32_t sh_entsize;\n  } ElfShdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Shdr, ElfShdr);\n  typedef struct {\n    uint32_t ch_type;\n    uint32_t ch_size;\n    uint32_t ch_addralign;\n  } ElfChdr;\n  typedef struct {\n    uint32_t st_name;\n    uint32_t st_value;\n    uint32_t st_size;\n    uint8_t st_info;\n    uint8_t st_other;\n    uint16_t st_shndx;\n  } ElfSym;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Sym, ElfSym);\n  typedef struct {\n    int32_t d_tag;\n    uint32_t d_val;\n  } ElfDyn;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Dyn, ElfDyn);\n  typedef struct {\n    uint32_t n_namesz;\n    uint32_t n_descsz;\n    uint32_t n_type;\n  } ElfNhdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Nhdr, ElfNhdr);\n  typedef struct {\n    uint32_t r_offset;\n    uint32_t r_info;\n  } ElfRel;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Rel, ElfRel);\n  typedef struct {\n    uint32_t r_offset;\n    uint32_t r_info;\n    int32_t r_addend;\n  } ElfRela;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf32_Rela, ElfRela);\n\n  static uint8_t clz_ptr(remote_ptr<void> ptr) {\n    return __builtin_clz(ptr.as_int());\n  }\n};\n\nstruct WordSize64Defs {\n  static const ::size_t SIGINFO_PAD_SIZE =\n      (KernelConstants::SIGINFO_MAX_SIZE / sizeof(int32_t)) - 4;\n\n  typedef int16_t signed_short;\n  typedef uint16_t unsigned_short;\n\n  typedef int32_t signed_int;\n  typedef uint32_t unsigned_int;\n\n  typedef int64_t signed_long;\n  typedef uint64_t unsigned_long;\n\n  typedef int64_t signed_word;\n  typedef uint64_t unsigned_word;\n\n  typedef uint64_t size_t;\n  typedef int64_t ssize_t;\n\n  // These really only exist as proper abstractions so that adding x32\n  // (x86-64's ILP32 ABI) support is relatively easy.\n  typedef int64_t syscall_slong_t;\n  typedef uint64_t syscall_ulong_t;\n  typedef int64_t sigchld_clock_t;\n  typedef signed_long __statfs_word;\n\n  static const size_t elfclass = ELFCLASS::CLASS64;\n  typedef struct {\n    uint8_t e_ident[16];\n    uint16_t e_type;\n    uint16_t e_machine;\n    uint32_t e_version;\n    uint64_t e_entry;\n    uint64_t e_phoff;\n    uint64_t e_shoff;\n    uint32_t e_flags;\n    uint16_t e_ehsize;\n    uint16_t e_phentsize;\n    uint16_t e_phnum;\n    uint16_t e_shentsize;\n    uint16_t e_shnum;\n    uint16_t e_shstrndx;\n  } ElfEhdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Ehdr, ElfEhdr);\n  typedef struct {\n    uint32_t p_type;\n    uint32_t p_flags;\n    uint64_t p_offset;\n    uint64_t p_vaddr;\n    uint64_t p_paddr;\n    uint64_t p_filesz;\n    uint64_t p_memsz;\n    uint64_t p_align;\n  } ElfPhdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Phdr, ElfPhdr);\n  typedef struct {\n    uint32_t sh_name;\n    uint32_t sh_type;\n    uint64_t sh_flags;\n    uint64_t sh_addr;\n    uint64_t sh_offset;\n    uint64_t sh_size;\n    uint32_t sh_link;\n    uint32_t sh_info;\n    uint64_t sh_addralign;\n    uint64_t sh_entsize;\n  } ElfShdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Shdr, ElfShdr);\n  typedef struct {\n    uint32_t ch_type;\n    uint32_t ch_reserved;\n    uint64_t ch_size;\n    uint64_t ch_addralign;\n  } ElfChdr;\n  typedef struct {\n    uint32_t st_name;\n    uint8_t st_info;\n    uint8_t st_other;\n    uint16_t st_shndx;\n    uint64_t st_value;\n    uint64_t st_size;\n  } ElfSym;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Sym, ElfSym);\n  typedef struct {\n    uint64_t d_tag;\n    uint64_t d_val;\n  } ElfDyn;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Dyn, ElfDyn);\n  typedef struct {\n    uint32_t n_namesz;\n    uint32_t n_descsz;\n    uint32_t n_type;\n  } ElfNhdr;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Nhdr, ElfNhdr);\n  typedef struct {\n    uint64_t r_offset;\n    uint64_t r_info;\n  } ElfRel;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Rel, ElfRel);\n  typedef struct {\n    uint64_t r_offset;\n    uint64_t r_info;\n    int64_t r_addend;\n  } ElfRela;\n  RR_VERIFY_TYPE_ARCH(RR_NATIVE_ARCH, ::Elf64_Rela, ElfRela);\n\n  static uint8_t clz_ptr(remote_ptr<void> ptr) {\n    return __builtin_clzl(ptr.as_int());\n  }\n};\n\n/**\n * Structs defined in BaseArch and its derivatives should not contain any\n * holes. Holes can cause divergence if such structs are copied from rr to\n * the tracee.\n */\ntemplate <SupportedArch arch_, typename wordsize>\nstruct BaseArch : public wordsize,\n                  public FcntlConstants,\n                  public KernelConstants {\n  static SupportedArch arch() { return arch_; }\n  static bool is_x86ish() {\n    return rr::is_x86ish(arch_);\n  }\n\n  typedef typename wordsize::syscall_slong_t syscall_slong_t;\n  typedef typename wordsize::syscall_ulong_t syscall_ulong_t;\n  typedef typename wordsize::signed_int signed_int;\n  typedef typename wordsize::unsigned_int unsigned_int;\n  typedef typename wordsize::signed_short signed_short;\n  typedef typename wordsize::unsigned_short unsigned_short;\n  typedef typename wordsize::signed_long signed_long;\n  typedef typename wordsize::unsigned_long unsigned_long;\n  typedef typename wordsize::unsigned_word unsigned_word;\n  typedef typename wordsize::size_t size_t;\n  typedef typename wordsize::ssize_t ssize_t;\n  typedef typename wordsize::sigchld_clock_t sigchld_clock_t;\n  typedef typename wordsize::__statfs_word __statfs_word;\n\n  typedef syscall_slong_t time_t;\n  typedef syscall_slong_t off_t;\n  typedef syscall_slong_t blkcnt_t;\n  typedef syscall_slong_t blksize_t;\n  typedef syscall_ulong_t rlim_t;\n  typedef syscall_ulong_t fsblkcnt_t;\n  typedef syscall_ulong_t fsfilcnt_t;\n  typedef syscall_ulong_t ino_t;\n  typedef syscall_ulong_t nlink_t;\n\n  typedef int64_t off64_t;\n  typedef int64_t loff_t;\n  typedef uint64_t rlim64_t;\n  typedef uint64_t ino64_t;\n  typedef int64_t blkcnt64_t;\n\n  typedef syscall_slong_t clock_t;\n  typedef signed_int __kernel_key_t;\n  typedef signed_int __kernel_uid32_t;\n  typedef signed_int __kernel_gid32_t;\n  typedef unsigned_int __kernel_mode_t;\n  typedef unsigned_long __kernel_ulong_t;\n  typedef signed_long __kernel_long_t;\n  typedef __kernel_long_t __kernel_time_t;\n  typedef __kernel_long_t __kernel_suseconds_t;\n  typedef signed_int __kernel_pid_t;\n  typedef int64_t __kernel_loff_t;\n\n  typedef uint32_t __u32;\n  typedef uint64_t __u64;\n  typedef __u64 aligned_u64 __attribute((aligned(8)));\n\n  // If they are defined in the header, undef them now.\n  // In rr, we always refer to them as these constants.\n#undef PTRACE_GETREGS\n#undef PTRACE_SETREGS\n#undef PTRACE_GETFPREGS\n#undef PTRACE_SETFPREGS\n#undef PTRACE_GETFPXREGS\n#undef PTRACE_SETFPXREGS\n#undef PTRACE_OLDSETOPTIONS\n#undef PTRACE_GET_THREAD_AREA\n#undef PTRACE_SET_THREAD_AREA\n#undef PTRACE_ARCH_PRCTL\n#undef PTRACE_SYSEMU\n#undef PTRACE_SYSEMU_SINGLESTEP\n\n  // These are architecture specific and may not exist on any given\n  // architecture or the number assigned on the architecture may vary.\n  // Here we give each of these a unique negative number that makes writing\n  // architecture generic code easier (the same approach is used for\n  // architecture specific syscalls).\n  static const int PTRACE_GETREGS = -1;\n  static const int PTRACE_SETREGS = -2;\n  static const int PTRACE_GETFPREGS = -3;\n  static const int PTRACE_SETFPREGS = -4;\n  static const int PTRACE_GETFPXREGS = -5;\n  static const int PTRACE_SETFPXREGS = -6;\n  static const int PTRACE_OLDSETOPTIONS = -7;\n  static const int PTRACE_GET_THREAD_AREA = -8;\n  static const int PTRACE_SET_THREAD_AREA = -9;\n  static const int PTRACE_ARCH_PRCTL = -10;\n  static const int PTRACE_SYSEMU = -11;\n  static const int PTRACE_SYSEMU_SINGLESTEP = -12;\n\n  template <typename T> struct ptr {\n    typedef T Referent;\n    unsigned_word val;\n    template <typename U> operator remote_ptr<U>() const { return rptr(); }\n    /**\n     * Sometimes you need to call rptr() directly to resolve ambiguous\n     * overloading.\n     */\n    remote_ptr<T> rptr() const { return remote_ptr<T>(val); }\n    template <typename U> ptr<T>& operator=(remote_ptr<U> p) {\n      remote_ptr<T> pt = p;\n      val = pt.as_int();\n      DEBUG_ASSERT(val == pt.as_int());\n      return *this;\n    }\n    operator bool() const { return val; }\n    static size_t referent_size() { return sizeof(T); }\n  };\n\n  template <typename T> struct ptr64 {\n    typedef T Referent;\n    aligned_u64 val;\n    template <typename U> operator remote_ptr<U>() const { return rptr(); }\n    /**\n     * Sometimes you need to call rptr() directly to resolve ambiguous\n     * overloading.\n     */\n    remote_ptr<T> rptr() const { return remote_ptr<T>(val); }\n    template <typename U> ptr64<T>& operator=(remote_ptr<U> p) {\n      remote_ptr<T> pt = p;\n      val = pt.as_int();\n      DEBUG_ASSERT(val == pt.as_int());\n      return *this;\n    }\n    operator bool() const { return val; }\n    static size_t referent_size() { return sizeof(T); }\n  };\n\n  union sigval_t {\n    signed_int sival_int;\n    ptr<void> sival_ptr;\n  };\n\n  struct sockaddr {\n    unsigned_short sa_family;\n    char sa_data[14];\n  };\n  RR_VERIFY_TYPE(sockaddr);\n\n  struct sockaddr_storage {\n    char sa_data[128];\n  };\n  RR_VERIFY_TYPE(sockaddr_storage);\n\n  struct sockaddr_un {\n    unsigned_short sun_family;\n    char sun_path[108];\n  };\n  RR_VERIFY_TYPE(sockaddr_un);\n\n  struct timeval {\n    __kernel_time_t tv_sec;\n    __kernel_suseconds_t tv_usec;\n  };\n  RR_VERIFY_TYPE(timeval);\n\n  struct timespec {\n    __kernel_time_t tv_sec;\n    syscall_slong_t tv_nsec;\n  };\n  RR_VERIFY_TYPE(timespec);\n\n  struct pollfd {\n    signed_int fd;\n    signed_short events;\n    signed_short revents;\n  };\n  RR_VERIFY_TYPE(pollfd);\n\n  struct iovec {\n    ptr<void> iov_base;\n    size_t iov_len;\n  };\n  RR_VERIFY_TYPE(iovec);\n\n  struct msghdr {\n    ptr<void> msg_name;\n    socklen_t msg_namelen;\n    char _padding[sizeof(ptr<void>) - sizeof(socklen_t)];\n\n    ptr<iovec> msg_iov;\n    size_t msg_iovlen;\n\n    ptr<void> msg_control;\n    size_t msg_controllen;\n\n    signed_int msg_flags;\n  };\n  RR_VERIFY_TYPE(msghdr);\n\n  struct cmsghdr {\n    size_t cmsg_len;\n    int cmsg_level;\n    int cmsg_type;\n  };\n  RR_VERIFY_TYPE(cmsghdr);\n\n  struct mmsghdr {\n    msghdr msg_hdr;\n    unsigned_int msg_len;\n  };\n  RR_VERIFY_TYPE(mmsghdr);\n\n// x86-64 is the only architecture to pack this structure, and it does\n// so to make the x86 and x86-64 definitions identical.  So even if\n// we're compiling on an x86-64 host that will support recording\n// 32-bit and 64-bit programs, this is the correct way to declare\n// epoll_event for both kinds of recordees.\n// See <linux/eventpoll.h>.\n#if defined(__x86_64__)\n#define RR_EPOLL_PACKED __attribute__((packed))\n#else\n#define RR_EPOLL_PACKED\n#endif\n  struct epoll_event {\n    union epoll_data {\n      ptr<void> ptr_;\n      signed_int fd;\n      uint32_t u32;\n      uint64_t u64;\n    };\n\n    uint32_t events;\n    epoll_data data;\n  } RR_EPOLL_PACKED;\n  RR_VERIFY_TYPE(epoll_event);\n#undef RR_EPOLL_PACKED\n\n  struct rusage {\n    timeval ru_utime;\n    timeval ru_stime;\n    signed_long ru_maxrss;\n    signed_long ru_ixrss;\n    signed_long ru_idrss;\n    signed_long ru_isrss;\n    signed_long ru_minflt;\n    signed_long ru_majflt;\n    signed_long ru_nswap;\n    signed_long ru_inblock;\n    signed_long ru_oublock;\n    signed_long ru_msgnsd;\n    signed_long ru_msgrcv;\n    signed_long ru_nsignals;\n    signed_long ru_nvcsw;\n    signed_long ru_nivcsw;\n  };\n  RR_VERIFY_TYPE(rusage);\n\n  struct siginfo_t {\n    signed_int si_signo;\n    signed_int si_errno;\n    signed_int si_code;\n    union {\n      signed_int padding[wordsize::SIGINFO_PAD_SIZE];\n      // <bits/siginfo.h> #defines all the field names belong due to X/Open\n      // requirements, so we append '_'.\n      struct {\n        pid_t si_pid_;\n        uid_t si_uid_;\n      } _kill;\n      struct {\n        signed_int si_tid_;\n        signed_int si_overrun_;\n        sigval_t si_sigval_;\n      } _timer;\n      struct {\n        pid_t si_pid_;\n        uid_t si_uid_;\n        sigval_t si_sigval_;\n      } _rt;\n      struct {\n        pid_t si_pid_;\n        uid_t si_uid_;\n        signed_int si_status_;\n        sigchld_clock_t si_utime_;\n        sigchld_clock_t si_stime_;\n      } _sigchld;\n      struct {\n        ptr<void> si_addr_;\n        signed_short si_addr_lsb_;\n        union {\n          struct {\n            ptr<void> _lower;\n            ptr<void> _upper;\n          } _addr_bnds;\n          uint32_t _pkey;\n        } _bounds;\n      } _sigfault;\n      struct {\n        signed_long si_band_;\n        signed_int si_fd_;\n      } _sigpoll;\n      struct {\n        ptr<void> _call_addr;\n        signed_int _syscall;\n        unsigned_int _arch;\n      } _sigsys;\n    } _sifields;\n  };\n  RR_VERIFY_TYPE_EXPLICIT(siginfo_t, ::siginfo_t)\n\n  typedef unsigned char cc_t;\n  typedef unsigned_int speed_t;\n  typedef unsigned_int tcflag_t;\n\n  struct termios {\n    tcflag_t c_iflag;\n    tcflag_t c_oflag;\n    tcflag_t c_cflag;\n    tcflag_t c_lflag;\n    cc_t c_line;\n    cc_t c_cc[19];\n  };\n  /* We don't verify termios because the kernel and glibc don't agree on its\n   * layout and ensuring that we only have the kernel termios visible here is\n   * a pain.\n   */\n\n  struct termio {\n    unsigned_short c_iflag;\n    unsigned_short c_oflag;\n    unsigned_short c_cflag;\n    unsigned_short c_lflag;\n    unsigned char c_line;\n    unsigned char c_cc[8];\n  };\n\n  struct seccomp_notif_sizes {\n    uint16_t seccomp_notif;\n    uint16_t seccomp_notif_resp;\n    uint16_t seccomp_data;\n  };\n  // seccomp_notif_sizes is not present in older kernels\n  // RR_VERIFY_TYPE(seccomp_notif_sizes);\n\n  struct serial_struct {\n    signed_int type;\n    signed_int line;\n    unsigned_int port;\n    signed_int irq;\n    signed_int flags;\n    signed_int xmit_fifo_size;\n    signed_int custom_divisor;\n    signed_int baud_base;\n    unsigned_short close_delay;\n    char io_type;\n    char reserved_char[1];\n    signed_int hub6;\n    unsigned_short closing_wait;\n    unsigned_short closing_wait2;\n    ptr<unsigned char> iomem_base;\n    unsigned_short iomem_reg_shift;\n    unsigned_int port_high;\n    unsigned_long iomap_base;\n  };\n  RR_VERIFY_TYPE(serial_struct);\n\n  struct serial_icounter_struct {\n    int cts;\n    int dsr;\n    int rng;\n    int dcd;\n    int rx;\n    int tx;\n    int frame;\n    int overrun;\n    int parity;\n    int brk;\n    int buf_overrun;\n    int reserved[9];\n  };\n  RR_VERIFY_TYPE(serial_icounter_struct);\n\n  struct winsize {\n    unsigned_short ws_row;\n    unsigned_short ws_col;\n    unsigned_short ws_xpixel;\n    unsigned_short ws_ypixel;\n  };\n  RR_VERIFY_TYPE(winsize);\n\n  struct ipc64_perm {\n    __kernel_key_t key;\n    __kernel_uid32_t uid;\n    __kernel_gid32_t gid;\n    __kernel_uid32_t cuid;\n    __kernel_gid32_t cgid;\n    __kernel_mode_t mode;\n    unsigned_short seq;\n    unsigned_short __pad2;\n    char __pad3[sizeof(__kernel_ulong_t) - 2 * sizeof(unsigned_short)];\n    __kernel_ulong_t unused1;\n    __kernel_ulong_t unused2;\n  };\n  RR_VERIFY_TYPE(ipc64_perm);\n\n  struct msqid64_ds {\n    ipc64_perm msg_perm;\n    // These msg*time fields are really __kernel_time_t plus\n    // appropriate padding.  We don't touch the fields, though.\n    //\n    // We do, however, suffix them with _only_little_endian to\n    // urge anybody who does touch them to make sure the right\n    // thing is done for big-endian systems.\n    uint64_t msg_stime_only_little_endian;\n    uint64_t msg_rtime_only_little_endian;\n    uint64_t msg_ctime_only_little_endian;\n    __kernel_ulong_t msg_cbytes;\n    __kernel_ulong_t msg_qnum;\n    __kernel_ulong_t msg_qbytes;\n    __kernel_pid_t msg_lspid;\n    __kernel_pid_t msg_lrpid;\n    __kernel_ulong_t unused1;\n    __kernel_ulong_t unused2;\n  };\n  RR_VERIFY_TYPE(msqid64_ds);\n\n  struct msginfo {\n    signed_int msgpool;\n    signed_int msgmap;\n    signed_int msgmax;\n    signed_int msgmnb;\n    signed_int msgmni;\n    signed_int msgssz;\n    signed_int msgtql;\n    unsigned_short msgseg;\n  };\n  RR_VERIFY_TYPE(msginfo);\n\n  /* Don't align for the 64-bit values on 32-bit x86 */\n  struct __attribute__((packed)) shmid64_ds {\n    ipc64_perm shm_perm;\n    size_t shm_segsz;\n    uint64_t shm_atime_only_little_endian;\n    uint64_t shm_dtime_only_little_endian;\n    uint64_t shm_ctime_only_little_endian;\n    __kernel_pid_t shm_cpid;\n    __kernel_pid_t shm_lpid;\n    __kernel_ulong_t shm_nattch;\n    __kernel_ulong_t unused4;\n    __kernel_ulong_t unused5;\n  };\n  RR_VERIFY_TYPE(shmid64_ds);\n\n  struct shminfo64 {\n    __kernel_ulong_t shmmax;\n    __kernel_ulong_t shmmin;\n    __kernel_ulong_t shmmni;\n    __kernel_ulong_t shmseg;\n    __kernel_ulong_t shmall;\n    __kernel_ulong_t unused1;\n    __kernel_ulong_t unused2;\n    __kernel_ulong_t unused3;\n    __kernel_ulong_t unused4;\n  };\n  RR_VERIFY_TYPE(shminfo64);\n\n  struct shm_info {\n    int used_ids;\n    char __pad[sizeof(__kernel_ulong_t) - sizeof(int)];\n    __kernel_ulong_t shm_tot;\n    __kernel_ulong_t shm_rss;\n    __kernel_ulong_t shm_swp;\n    __kernel_ulong_t swap_attempts;\n    __kernel_ulong_t swap_successes;\n  };\n  RR_VERIFY_TYPE(shm_info);\n\n  struct seminfo {\n    int semmap;\n    int semmni;\n    int semmns;\n    int semmnu;\n    int semmsl;\n    int semopm;\n    int semume;\n    int semusz;\n    int semvmx;\n    int semaem;\n  };\n  RR_VERIFY_TYPE(seminfo);\n\n  // The clone(2) syscall has four (!) different calling conventions,\n  // depending on what architecture it's being compiled for.  We describe\n  // the orderings for x86oids here.\n  enum CloneParameterOrdering {\n    FlagsStackParentTLSChild,\n    FlagsStackParentChildTLS,\n  };\n\n  // Despite the clone(2) manpage describing the clone syscall as taking a\n  // pointer to |struct user_desc*|, the actual kernel interface treats the\n  // TLS value as a opaque cookie, which architectures are then free to do\n  // whatever they like with.  See for instance the definition of TLS_VALUE\n  // in nptl/sysdeps/pthread/createthread.c in the glibc source.  We need to\n  // describe what the architecture uses so we can record things accurately.\n  enum CloneTLSType {\n    // |struct user_desc*|\n    UserDescPointer,\n    // This is the default choice for TLS_VALUE in the glibc source.\n    PthreadStructurePointer,\n  };\n\n  struct user_desc {\n    unsigned_int entry_number;\n    unsigned_int base_addr;\n    unsigned_int limit;\n    unsigned_int seg_32bit : 1;\n    unsigned_int contents : 2;\n    unsigned_int read_exec_only : 1;\n    unsigned_int limit_in_pages : 1;\n    unsigned_int seg_not_present : 1;\n    unsigned_int useable : 1;\n    unsigned_int lm : 1;\n  };\n  RR_VERIFY_TYPE_X86(user_desc);\n\n  struct __user_cap_header_struct {\n    __u32 version;\n    int pid;\n  };\n  RR_VERIFY_TYPE(__user_cap_header_struct);\n\n  struct __user_cap_data_struct {\n    __u32 effective;\n    __u32 permitted;\n    __u32 inheritable;\n  };\n  RR_VERIFY_TYPE(__user_cap_data_struct);\n\n  // This structure uses fixed-size fields, but the padding rules\n  // for 32-bit vs. 64-bit architectures dictate that it be\n  // defined in full.\n  struct dqblk {\n    uint64_t dqb_bhardlimit;\n    uint64_t dqb_bsoftlimit;\n    uint64_t dqb_curspace;\n    uint64_t dqb_ihardlimit;\n    uint64_t dqb_isoftlimit;\n    uint64_t dqb_curinodes;\n    uint64_t dqb_btime;\n    uint64_t dqb_itime;\n    uint32_t dqb_valid;\n  };\n  RR_VERIFY_TYPE(dqblk);\n\n  struct dqinfo {\n    uint64_t dqi_bgrace;\n    uint64_t dqi_igrace;\n    uint32_t dqi_flags;\n    uint32_t dqi_valid;\n  };\n  RR_VERIFY_TYPE(dqinfo);\n\n  struct ifmap {\n    unsigned_long mem_start;\n    unsigned_long mem_end;\n    unsigned_short base_addr;\n    unsigned char irq;\n    unsigned char dma;\n    unsigned char port;\n  };\n  RR_VERIFY_TYPE(ifmap);\n\n  struct if_settings {\n    unsigned_int type;\n    unsigned_int size;\n    union {\n      ptr<void> raw_hdlc;\n      ptr<void> cisco;\n      ptr<void> fr;\n      ptr<void> fr_pvc;\n      ptr<void> fr_pvc_info;\n      ptr<void> sync;\n      ptr<void> tel;\n    } ifs_ifsu;\n  };\n  RR_VERIFY_TYPE(if_settings);\n\n  struct ifreq {\n    union {\n      char ifrn_name[16];\n    } ifr_ifrn;\n    union {\n      sockaddr ifru_addr;\n      sockaddr ifru_dstaddr;\n      sockaddr ifru_broadaddr;\n      sockaddr ifru_netmask;\n      sockaddr ifru_hwaddr;\n      signed_short ifru_flags;\n      signed_int ifru_ivalue;\n      signed_int ifru_mtu;\n      ifmap ifru_map;\n      char ifru_slave[16];\n      char ifru_newname[16];\n      ptr<void> ifru_data;\n      if_settings ifru_settings;\n    } ifr_ifru;\n  };\n  RR_VERIFY_TYPE(ifreq);\n\n  struct ifconf {\n    signed_int ifc_len;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    union {\n      ptr<char> ifcu_buf;\n      ptr<ifreq> ifcu_req;\n    } ifc_ifcu;\n  };\n  RR_VERIFY_TYPE(ifconf);\n\n  struct iw_param {\n    int32_t value;\n    uint8_t fixed;\n    uint8_t disabled;\n    uint16_t flags;\n  };\n  RR_VERIFY_TYPE(iw_param);\n\n  struct iw_point {\n    ptr<void> pointer;\n    uint16_t length;\n    uint16_t flags;\n  };\n  RR_VERIFY_TYPE(iw_point);\n\n  struct iw_freq {\n    int32_t m;\n    int16_t e;\n    uint8_t i;\n    uint8_t flags;\n  };\n  RR_VERIFY_TYPE(iw_freq);\n\n  struct iw_quality {\n    uint8_t qual;\n    uint8_t level;\n    uint8_t noise;\n    uint8_t updated;\n  };\n  RR_VERIFY_TYPE(iw_quality);\n\n  union iwreq_data {\n    char name[16];\n    iw_point essid;\n    iw_param nwid;\n    iw_freq freq;\n    iw_param sens;\n    iw_param bitrate;\n    iw_param txpower;\n    iw_param rts;\n    iw_param frag;\n    uint32_t mode;\n    iw_param retry;\n    iw_point encoding;\n    iw_param power;\n    iw_quality qual;\n    sockaddr ap_addr;\n    sockaddr addr;\n    iw_param param;\n    iw_point data;\n  };\n  RR_VERIFY_TYPE(iwreq_data);\n\n  struct iwreq {\n    union {\n      char ifrn_name[16];\n    } ifr_ifrn;\n    iwreq_data u;\n  };\n  RR_VERIFY_TYPE(iwreq);\n\n  struct _flock {\n    signed_short l_type;\n    signed_short l_whence;\n    char __pad[sizeof(off_t) - 2 * sizeof(short)];\n    off_t l_start;\n    off_t l_len;\n    pid_t l_pid;\n  };\n  // Doesn't verify on x86-32 where our system off_t is 64 bits because\n  // we need to access large files.\n\n  struct flock64 {\n    signed_short l_type;\n    signed_short l_whence;\n    // No padding on 32-bit, 4 bytes of padding on 64-bit\n    char __pad[sizeof(uint32_t) - 2 * sizeof(short)];\n    uint64_t l_start;\n    uint64_t l_len;\n    pid_t l_pid;\n  };\n  RR_VERIFY_TYPE(flock64);\n\n  struct f_owner_ex {\n    signed_int type;\n    __kernel_pid_t pid;\n  };\n  RR_VERIFY_TYPE(f_owner_ex);\n\n  // Define various structures that package up syscall arguments.\n  // The types of their members are part of the ABI, and defining\n  // them here makes their definitions more concise.\n  struct accept_args {\n    signed_int sockfd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<sockaddr> addr;\n    ptr<socklen_t> addrlen;\n  };\n\n  struct accept4_args {\n    signed_int sockfd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<sockaddr> addr;\n    ptr<socklen_t> addrlen;\n    signed_long flags;\n  };\n\n  struct getsockname_args {\n    signed_int sockfd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<sockaddr> addr;\n    ptr<socklen_t> addrlen;\n  };\n\n  struct getsockopt_args {\n    signed_int sockfd;\n    signed_int level;\n    signed_int optname;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<void> optval;\n    ptr<socklen_t> optlen;\n  };\n\n  struct setsockopt_args {\n    signed_long sockfd;\n    signed_long level;\n    signed_long optname;\n    ptr<void> optval;\n    signed_long optlen;\n  };\n\n  struct connect_args {\n    signed_long sockfd;\n    ptr<void> addr;\n    socklen_t addrlen;\n  };\n\n  struct recv_args {\n    signed_int sockfd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<void> buf;\n    size_t len;\n    signed_int flags;\n  };\n\n  struct recvfrom_args {\n    signed_long sockfd;\n    ptr<void> buf;\n    size_t len;\n    signed_long flags;\n    ptr<sockaddr> src_addr;\n    ptr<socklen_t> addrlen;\n  };\n\n  struct recvmsg_args {\n    signed_int fd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<msghdr> msg;\n    signed_int flags;\n  };\n\n  struct recvmmsg_args {\n    signed_int sockfd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<mmsghdr> msgvec;\n    unsigned_int vlen;\n    unsigned_int flags;\n    ptr<timespec> timeout;\n  };\n\n  struct sendmsg_args {\n    signed_int fd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<msghdr> msg;\n    signed_int flags;\n  };\n\n  struct sendmmsg_args {\n    signed_int sockfd;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<mmsghdr> msgvec;\n    unsigned_int vlen;\n    unsigned_int flags;\n  };\n\n  struct socketpair_args {\n    signed_int domain;\n    signed_int type;\n    signed_int protocol;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<signed_int> sv; // int sv[2]\n  };\n\n  // All architectures have an mmap syscall, but it has architecture-specific\n  // calling semantics. We describe those here, and specializations need to\n  // indicate which semantics they use.\n  enum MmapCallingSemantics {\n    StructArguments,   // x86-ish, packaged into mmap_args, below\n    RegisterArguments, // arguments passed in registers, the offset\n                       // is assumed to be in bytes, not in pages.\n  };\n\n  struct mmap_args {\n    ptr<void> addr;\n    size_t len;\n    signed_int prot;\n    signed_int flags;\n    signed_int fd;\n    char __pad[sizeof(off_t) - sizeof(int)];\n    off_t offset;\n  };\n\n  // All architectures have a select syscall, but like mmap, there are two\n  // different calling styles: one that packages the args into a structure,\n  // and one that handles the args in registers.  (Architectures using the\n  // first style, like the x86, sometimes support the register-args version\n  // as a separate syscall.)\n  //\n  // (Yes, we'd like to call these StructArguments and RegisterArguments, but\n  // that would conflict with MmapCallingSemantics, above.)\n  enum SelectCallingSemantics {\n    SelectStructArguments,\n    SelectRegisterArguments,\n  };\n\n  static const size_t MAX_FDS = 1024;\n  struct fd_set {\n    unsigned_long fds_bits[MAX_FDS / (8 * sizeof(unsigned_long))];\n  };\n\n  struct select_args {\n    signed_int n_fds;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<fd_set> read_fds;\n    ptr<fd_set> write_fds;\n    ptr<fd_set> except_fds;\n    ptr<struct timeval> timeout;\n  };\n\n  /**\n   *  Some ipc calls require 7 params, so two of them are stashed into\n   *  one of these structs and a pointer to this is passed instead.\n   */\n  struct ipc_kludge_args {\n    ptr<void> msgbuf;\n    signed_long msgtype;\n  };\n\n  struct __sysctl_args {\n    ptr<signed_int> name;\n    signed_int nlen;\n    char __pad[sizeof(ptr<void>) - sizeof(int)];\n    ptr<void> oldval;\n    ptr<size_t> oldlenp;\n    ptr<void> newval;\n    ptr<size_t> newlen;\n    unsigned_long __rr_unused[4];\n  };\n  RR_VERIFY_TYPE(__sysctl_args);\n\n  // libc reserves some space in the user facing structures for future\n  // extensibility, so we are careful to use the kernel definition here.\n  typedef struct {\n    unsigned_long __val[64 / (8 * sizeof(unsigned_long))];\n  } kernel_sigset_t;\n\n  typedef struct {\n    ptr<const kernel_sigset_t> ss;\n    size_t ss_len;\n  } pselect6_arg6;\n\n  struct kernel_sigaction {\n    ptr<void> k_sa_handler;\n    unsigned_long sa_flags;\n    ptr<void> sa_restorer;\n    kernel_sigset_t sa_mask;\n  };\n  struct tms {\n    clock_t tms_utime;\n    clock_t tms_stime;\n    clock_t tms_cutime;\n    clock_t tms_cstime;\n  };\n  RR_VERIFY_TYPE(tms);\n\n  struct rlimit {\n    rlim_t rlim_cur;\n    rlim_t rlim_max;\n  };\n  // Doesn't verify on x86-32 where our system off_t is 64 bits because\n  // we need to access large files.\n\n  struct rlimit64 {\n    rlim64_t rlim_cur;\n    rlim64_t rlim_max;\n  };\n  RR_VERIFY_TYPE(rlimit64);\n\n  struct timezone {\n    int tz_minuteswest;\n    int tz_dsttime;\n  };\n  RR_VERIFY_TYPE_EXPLICIT(struct ::timezone, timezone);\n\n  struct statfs_t {\n    __statfs_word f_type;\n    __statfs_word f_bsize;\n    __statfs_word f_blocks;\n    __statfs_word f_bfree;\n    __statfs_word f_bavail;\n    __statfs_word f_files;\n    __statfs_word f_ffree;\n    struct {\n      int __val[2];\n    } f_fsid;\n    __statfs_word f_namelen;\n    __statfs_word f_frsize;\n    __statfs_word f_flags;\n    __statfs_word f_spare[4];\n  };\n  // Doesn't verify on x86-32 where our system __fsblkcnt_t is 64 bits because\n  // we need to access large files.\n\n  /* Don't align for the 64-bit values on 32-bit x86 */\n  struct __attribute__((packed)) statfs64_t {\n    __statfs_word f_type;\n    __statfs_word f_bsize;\n    uint64_t f_blocks;\n    uint64_t f_bfree;\n    uint64_t f_bavail;\n    uint64_t f_files;\n    uint64_t f_ffree;\n    struct {\n      int __val[2];\n    } f_fsid;\n    __statfs_word f_namelen;\n    __statfs_word f_frsize;\n    __statfs_word f_flags;\n    __statfs_word f_spare[4];\n  };\n  RR_VERIFY_TYPE_EXPLICIT(struct ::statfs64, statfs64_t);\n\n  struct itimerval {\n    timeval it_interval;\n    timeval it_value;\n  };\n  RR_VERIFY_TYPE(itimerval);\n\n  struct itimerspec {\n    timespec it_interval;\n    timespec it_value;\n  };\n  RR_VERIFY_TYPE(itimerspec);\n\n  typedef struct sigaltstack {\n    ptr<void> ss_sp;\n    int ss_flags;\n    char __pad[sizeof(size_t) - sizeof(int)];\n    size_t ss_size;\n  } stack_t;\n  RR_VERIFY_TYPE(stack_t);\n\n  struct sysinfo_t {\n    __kernel_long_t uptime;\n    __kernel_ulong_t loads[3];\n    __kernel_ulong_t totalram;\n    __kernel_ulong_t freeram;\n    __kernel_ulong_t sharedram;\n    __kernel_ulong_t bufferram;\n    __kernel_ulong_t totalswap;\n    __kernel_ulong_t freeswap;\n    uint16_t procs;\n    uint16_t pad;\n    char __pad[sizeof(__kernel_ulong_t) - 2 * sizeof(uint16_t)];\n    __kernel_ulong_t totalhigh;\n    __kernel_ulong_t freehigh;\n    uint32_t mem_unit;\n    char _f[20 - 2 * sizeof(__kernel_ulong_t) - sizeof(uint32_t)];\n  };\n  RR_VERIFY_TYPE_EXPLICIT(struct ::sysinfo, sysinfo_t);\n\n  static const ::size_t UTSNAME_LENGTH = 65;\n  struct utsname {\n    char sysname[UTSNAME_LENGTH];\n    char nodename[UTSNAME_LENGTH];\n    char release[UTSNAME_LENGTH];\n    char version[UTSNAME_LENGTH];\n    char machine[UTSNAME_LENGTH];\n    char domainname[UTSNAME_LENGTH];\n  };\n  RR_VERIFY_TYPE(utsname);\n\n  struct sched_param {\n    int __sched_priority;\n  };\n  RR_VERIFY_TYPE(sched_param);\n\n  static void* cmsg_data(cmsghdr* cmsg) { return cmsg + 1; }\n  static constexpr size_t cmsg_align(size_t len) {\n    return (len + sizeof(size_t) - 1) & ~(sizeof(size_t) - 1);\n  }\n  static constexpr size_t cmsg_space(size_t len) {\n    return cmsg_align(sizeof(cmsghdr)) + cmsg_align(len);\n  }\n  static size_t cmsg_len(size_t len) {\n    return cmsg_align(sizeof(cmsghdr)) + len;\n  }\n\n  struct v4l2_timecode {\n    uint32_t type;\n    uint32_t flags;\n    uint8_t frames;\n    uint8_t seconds;\n    uint8_t minutes;\n    uint8_t hours;\n    uint8_t userbits[4];\n  };\n  RR_VERIFY_TYPE(v4l2_timecode);\n\n  struct v4l2_buffer {\n    uint32_t index;\n    uint32_t type;\n    uint32_t bytesused;\n    uint32_t flags;\n    uint32_t field;\n    char __pad[sizeof(__kernel_ulong_t) - sizeof(uint32_t)];\n    struct timeval timestamp;\n    struct v4l2_timecode timecode;\n    uint32_t sequence;\n    uint32_t memory;\n    union {\n      uint32_t offset;\n      unsigned_long userptr;\n      ptr<void> planes;\n      int32_t fd;\n    } m;\n    uint32_t length;\n    uint32_t reserved2;\n    uint32_t reserved;\n  };\n  RR_VERIFY_TYPE(v4l2_buffer);\n\n  struct sock_filter {\n    uint16_t code;\n    uint8_t jt;\n    uint8_t jf;\n    uint32_t k;\n  };\n  RR_VERIFY_TYPE(sock_filter);\n\n  struct sock_fprog {\n    uint16_t len;\n    char _padding[sizeof(ptr<void>) - sizeof(uint16_t)];\n    ptr<sock_filter> filter;\n  };\n  RR_VERIFY_TYPE(sock_fprog);\n\n  struct robust_list {\n    ptr<robust_list> next;\n  };\n  RR_VERIFY_TYPE(robust_list);\n\n  struct robust_list_head {\n    robust_list list;\n    signed_long futex_offset;\n    ptr<robust_list> list_op_pending;\n  };\n  RR_VERIFY_TYPE(robust_list_head);\n\n  struct snd_ctl_card_info {\n    int card;\n    int pad;\n    unsigned char id[16];\n    unsigned char driver[16];\n    unsigned char name[32];\n    unsigned char longname[80];\n    unsigned char reserved_[16];\n    unsigned char mixername[80];\n    unsigned char components[128];\n  };\n  RR_VERIFY_TYPE(snd_ctl_card_info);\n\n  struct usbdevfs_iso_packet_desc {\n    unsigned int length;\n    unsigned int actual_length;\n    unsigned int status;\n  };\n  RR_VERIFY_TYPE(usbdevfs_iso_packet_desc);\n\n  struct usbdevfs_urb {\n    unsigned char type;\n    unsigned char endpoint;\n    int status;\n    unsigned int flags;\n    ptr<void> buffer;\n    int buffer_length;\n    int actual_length;\n    int start_frame;\n    union {\n      int number_of_packets;\n      unsigned int stream_id;\n    };\n    int error_count;\n    unsigned int signr;\n    ptr<void> usercontext;\n    struct usbdevfs_iso_packet_desc iso_frame_desc[0];\n  };\n  RR_VERIFY_TYPE(usbdevfs_urb);\n\n  struct usbdevfs_ioctl {\n    int ifno;\n    int ioctl_code;\n    ptr<void> data;\n  };\n  RR_VERIFY_TYPE(usbdevfs_ioctl);\n\n  struct usbdevfs_ctrltransfer {\n    uint8_t bRequestType;\n    uint8_t bRequest;\n    uint16_t wValue;\n    uint16_t wIndex;\n    uint16_t wLength;\n    uint32_t timeout;\n    ptr<void> data;\n  };\n  RR_VERIFY_TYPE(usbdevfs_ctrltransfer);\n\n  struct dirent {\n    ino_t d_ino;\n    off_t d_off;\n    uint16_t d_reclen;\n    //    uint8_t d_type;\n    uint8_t d_name[256];\n  };\n  // Doesn't verify on x86-32 where our system dirent uses 64-bit ino/off because\n  // we need to access large files.\n\n  struct dirent64 {\n    ino64_t d_ino;\n    off64_t d_off;\n    uint16_t d_reclen;\n    uint8_t d_type;\n    uint8_t d_name[256];\n  };\n  RR_VERIFY_TYPE(dirent64);\n\n  struct mq_attr {\n    signed_long mq_flags;\n    signed_long mq_maxmsg;\n    signed_long mq_msgsize;\n    signed_long mq_curmsgs;\n    signed_long __reserved[4];\n  };\n  RR_VERIFY_TYPE(mq_attr);\n\n  struct xt_counters {\n    uint64_t pcnt, bcnt;\n  };\n  RR_VERIFY_TYPE(xt_counters);\n\n  struct ipt_replace {\n    uint8_t name[32];\n    uint32_t valid_hook;\n    uint32_t num_entries;\n    uint32_t size;\n    uint32_t hook_entry[5];\n    uint32_t underflow[5];\n    uint32_t num_counters;\n    ptr<xt_counters> counters; // ptr<xt_counters>\n    // Plus hangoff here\n  };\n  // The corresponding header requires -fpermissive, which we don't pass. Skip\n  // this check.\n  // RR_VERIFY_TYPE(ipt_replace);\n\n  struct ip6t_replace {\n    uint8_t name[32];\n    uint32_t valid_hook;\n    uint32_t num_entries;\n    uint32_t size;\n    uint32_t hook_entry[5];\n    uint32_t underflow[5];\n    uint32_t num_counters;\n    ptr<xt_counters> counters; // ptr<xt_counters>\n    // Plus hangoff here\n  };\n  // The corresponding header requires -fpermissive, which we don't pass. Skip\n  // this check.\n  // RR_VERIFY_TYPE(ip6t_replace);\n\n  struct cap_header {\n    uint32_t version;\n    int pid;\n  };\n\n  struct cap_data {\n    uint32_t effective;\n    uint32_t permitted;\n    uint32_t inheritable;\n  };\n\n  struct hci_dev_req {\n    uint16_t dev_id;\n    uint32_t dev_opt;\n  };\n\n  struct hci_dev_list_req {\n    uint16_t dev_num;\n    struct hci_dev_req dev_req[0];\n  };\n\n  typedef struct { uint8_t b[6]; } __attribute__((__packed__)) bdaddr_t;\n\n  struct hci_dev_stats {\n    uint32_t err_rx;\n    uint32_t err_tx;\n    uint32_t cmd_tx;\n    uint32_t evt_rx;\n    uint32_t acl_tx;\n    uint32_t acl_rx;\n    uint32_t sco_tx;\n    uint32_t sco_rx;\n    uint32_t byte_rx;\n    uint32_t byte_tx;\n  };\n\n  struct hci_dev_info {\n    uint16_t dev_id;\n    char name[8];\n\n    bdaddr_t bdaddr;\n\n    uint32_t flags;\n    uint8_t type;\n\n    uint8_t features[8];\n\n    uint32_t pkt_type;\n    uint32_t link_policy;\n    uint32_t link_mode;\n\n    uint16_t acl_mtu;\n    uint16_t acl_pkts;\n    uint16_t sco_mtu;\n    uint16_t sco_pkts;\n\n    struct hci_dev_stats stat;\n  };\n\n  struct rseq_t {\n    uint32_t cpu_id_start;\n    uint32_t cpu_id;\n    uint64_t rseq_cs;\n    uint32_t flags;\n  } __attribute__((aligned(32)));\n\n  struct rseq_cs {\n    uint32_t version;\n    uint32_t flags;\n    uint64_t start_ip;\n    uint64_t post_commit_offset;\n    uint64_t abort_ip;\n  } __attribute__((aligned(32)));\n\n  typedef struct ifbond {\n    int32_t bond_mode;\n    int32_t num_slaves;\n    int32_t miimon;\n  } ifbond;\n  RR_VERIFY_TYPE(ifbond);\n\n  typedef struct timex {\n    unsigned int modes;\n    __kernel_long_t offset;\n    __kernel_long_t freq;\n    __kernel_long_t maxerror;\n    __kernel_long_t esterror;\n    int status;\n    __kernel_long_t constant;\n    __kernel_long_t precision;\n    __kernel_long_t tolerance;\n    timeval time;\n    __kernel_long_t tick;\n    __kernel_long_t ppsfreq;\n    __kernel_long_t jitter;\n    int shift;\n    __kernel_long_t stabil;\n    __kernel_long_t jitcnt;\n    __kernel_long_t calcnt;\n    __kernel_long_t errcnt;\n    __kernel_long_t stbcnt;\n    int tai;\n\n    // Further padding bytes to allow for future expansion.\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n    int : 32;\n  } timex;\n  RR_VERIFY_TYPE(timex);\n\n  typedef struct statx_timestamp {\n    int64_t tv_sec;\n    uint32_t tv_nsec;\n    int32_t __reserved;\n  } statx_timestamp;\n  // statx_timestamp not yet widely available in system headers\n  // RR_VERIFY_TYPE(statx_timestamp);\n\n  typedef struct statx_struct {\n    uint32_t stx_mask;\n    uint32_t stx_blksize;\n    uint64_t stx_attributes;\n    uint32_t stx_nlink;\n    uint32_t stx_uid;\n    uint32_t stx_gid;\n    uint16_t stx_mode;\n    uint16_t __spare0;\n    uint64_t stx_ino;\n    uint64_t stx_size;\n    uint64_t stx_blocks;\n    uint64_t stx_attributes_mask;\n    statx_timestamp stx_atime;\n    statx_timestamp stx_btime;\n    statx_timestamp stx_ctime;\n    statx_timestamp stx_mtime;\n    uint32_t stx_rdev_major;\n    uint32_t stx_rdev_minor;\n    uint32_t stx_dev_major;\n    uint32_t stx_dev_minor;\n    uint64_t __spare2[14];\n  } statx;\n  // statx not yet widely available in system headers\n  // RR_VERIFY_TYPE_EXPLICIT(struct ::statx, statx);\n\n  struct sg_io_hdr {\n    int interface_id;\n    int dxfer_direction;\n    unsigned char cmd_len;\n    unsigned char mx_sb_len;\n    unsigned short int iovec_count;\n    unsigned int dxfer_len;\n    ptr<void> dxferp;\n    ptr<unsigned char> cmdp;\n    ptr<unsigned char> sbp;\n    unsigned int timeout;\n    unsigned int flags;\n    int pack_id;\n    ptr<void> usr_ptr;\n    unsigned char status;\n    unsigned char masked_status;\n    unsigned char msg_status;\n    unsigned char sb_len_wr;\n    unsigned short int host_status;\n    unsigned short int driver_status;\n    int resid;\n    unsigned int duration;\n    unsigned int info;\n  };\n  RR_VERIFY_TYPE(sg_io_hdr);\n\n  union bpf_attr {\n    struct {\n      __u32 map_type;\n      __u32 key_size;\n      __u32 value_size;\n      __u32 max_entries;\n      __u32 map_flags;\n      __u32 inner_map_fd;\n      __u32 numa_node;\n      char map_name[16];\n      __u32 map_ifindex;\n      __u32 btf_fd;\n      __u32 btf_key_type_id;\n      __u32 btf_value_type_id;\n    };\n    struct {\n      __u32 map_fd;\n      ptr64<void> key;\n      union {\n        ptr64<void> value;\n        ptr64<void> next_key;\n      };\n      __u64 flags;\n    };\n    struct { /* used by BPF_PROG_LOAD */\n      __u32 prog_type;\n      __u32 insn_cnt;\n      ptr64<void> insns;\n      ptr64<const char> license;\n      __u32 log_level;\n      __u32 log_size;\n      ptr64<char> log_buf;\n      __u32 kern_version;\n      __u32 prog_flags;\n      char prog_name[16];\n      __u32 prog_ifindex;\n      __u32 expected_attach_type;\n      __u32 prog_btf_fd;\n      __u32 func_info_rec_size;\n      aligned_u64 func_info;\n      __u32 func_info_cnt;\n      __u32 line_info_rec_size;\n      aligned_u64 line_info;\n      __u32 line_info_cnt;\n    };\n\n    struct { /* anonymous struct used by BPF_PROG_QUERY command */\n      union {\n        __u32 target_fd; /* target object to query or ... */\n        __u32 target_ifindex; /* target ifindex */\n      };\n      __u32 attach_type;\n      __u32 query_flags;\n      __u32 attach_flags;\n      ptr64<__u32> prog_ids;\n      union {\n        __u32 prog_cnt;\n        __u32 count;\n      };\n      __u32 :32;\n      /* output: per-program attach_flags.\n       * not allowed to be set during effective query.\n       */\n      ptr64<__u32> prog_attach_flags;\n      ptr64<__u32> link_ids;\n      ptr64<__u32> link_attach_flags;\n      __u64 revision;\n    } query;\n    struct { /* anonymous struct used by RR_BPF_OBJ_GET_INFO_BY_FD command */\n      __u32 bpf_fd;\n      __u32 info_len;\n      __u64 info;\n    } info;\n  };\n\n  struct file_handle {\n    unsigned int handle_bytes;\n    int handle_type;\n    uint8_t f_handle[0];\n  };\n\n  // This is technically a libc ABI, but we'll just put it here for convenience\n  struct link_map {\n    ptr<void> l_addr;\n    ptr<char> l_name;\n    ptr<void> l_ld;\n    ptr<link_map> l_next;\n    ptr<link_map> l_prev;\n    // More fields that are libc ...\n  };\n\n  struct r_debug {\n    int r_version;\n    ptr<link_map> r_map;\n    // More fields we don't need (and are potentially libc specific)\n  };\n\n  struct prctl_mm_map {\n    __u64 start_code;\n    __u64 end_code;\n    __u64 start_data;\n    __u64 end_data;\n    __u64 start_brk;\n    __u64 brk;\n    __u64 start_stack;\n    __u64 arg_start;\n    __u64 arg_end;\n    __u64 env_start;\n    __u64 env_end;\n    ptr<__u64> auxv;\n    __u32 auxv_size;\n    __u32 exe_fd;\n  };\n  RR_VERIFY_TYPE(prctl_mm_map);\n\n  struct fiemap_extent {\n    __u64 fe_logical;\n    __u64 fe_physical;\n    __u64 fe_length;\n    __u64 fe_reserved64[2];\n    __u32 fe_flags;\n    __u32 fe_reserved[3];\n  };\n  RR_VERIFY_TYPE(fiemap_extent);\n  struct fiemap {\n    __u64 fm_start;\n    __u64 fm_length;\n    __u32 fm_flags;\n    __u32 fm_mapped_extents;\n    __u32 fm_extent_count;\n    __u32 fm_reserved;\n    struct fiemap_extent fm_extents[0];\n  };\n  RR_VERIFY_TYPE(fiemap);\n\n  struct vt_stat {\n    unsigned short v_active;\n    unsigned short v_signal;\n    unsigned short v_state;\n  };\n  RR_VERIFY_TYPE(vt_stat);\n\n  struct fb_fix_screeninfo {\n    char id[16];\n    unsigned long smem_start;\n    __u32 smem_len;\n    __u32 type;\n    __u32 type_aux;\n    __u32 visual;\n    uint16_t xpanstep;\n    uint16_t ypanstep;\n    uint16_t xwrapstep;\n    __u32 line_length;\n    unsigned long mmio_start;\n    __u32 mmio_len;\n    __u32 accel;\n    uint16_t capabilities;\n    uint16_t reserved[2];\n  };\n  RR_VERIFY_TYPE(fb_fix_screeninfo);\n\n  struct fb_bitfield {\n    __u32 offset;\n    __u32 length;\n    __u32 msb_right;\n  };\n  RR_VERIFY_TYPE(fb_bitfield);\n  struct fb_var_screeninfo {\n    __u32 xres;\n    __u32 yres;\n    __u32 xres_virtual;\n    __u32 yres_virtual;\n    __u32 xoffset;\n    __u32 yoffset;\n    __u32 bits_per_pixel;\n    __u32 grayscale;\n    struct fb_bitfield red;\n    struct fb_bitfield green;\n    struct fb_bitfield blue;\n    struct fb_bitfield transp;\n    __u32 nonstd;\n    __u32 active;\n    __u32 height;\n    __u32 width;\n    __u32 accel_flags;\n    __u32 pixclock;\n    __u32 left_margin;\n    __u32 right_margin;\n    __u32 upper_margin;\n    __u32 lower_margin;\n    __u32 hsync_len;\n    __u32 vsync_len;\n    __u32 sync;\n    __u32 vmode;\n    __u32 rotate;\n    __u32 colorspace;\n    __u32 reserved[4];\n  };\n  RR_VERIFY_TYPE(fb_var_screeninfo);\n\n  struct cdrom_tochdr {\n    uint8_t cdth_trk0;\n    uint8_t cdth_trk1;\n  };\n  RR_VERIFY_TYPE(cdrom_tochdr);\n\n  struct cdrom_msf0 {\n    uint8_t minute;\n    uint8_t second;\n    uint8_t frame;\n  };\n  union cdrom_addr {\n    struct cdrom_msf0 msf;\n    int lba;\n  };\n  struct cdrom_tocentry {\n    uint8_t cdte_track;\n    uint8_t cdte_adr : 4;\n    uint8_t cdte_ctrl : 4;\n    uint8_t cdte_format;\n    union cdrom_addr cdte_addr;\n    uint8_t cdte_datamode;\n  };\n  RR_VERIFY_TYPE(cdrom_tocentry);\n\n  struct mtd_read_req_ecc_stats {\n    uint32_t uncorrectable_errors;\n    uint32_t corrected_bitflips;\n    uint32_t max_bitflips;\n  };\n\n  struct mtd_read_req {\n    uint64_t start;\n    uint64_t len;\n    uint64_t ooblen;\n    uint64_t usr_data;\n    uint64_t usr_oob;\n    uint8_t mode;\n    uint8_t padding[7];\n    struct mtd_read_req_ecc_stats ecc_stats;\n  };\n  // mtd_read_req was only added in kernel 6.1 so don't try to verify it yet.\n\n  struct ptrace_syscall_info {\n    uint8_t op;\n    uint32_t arch;\n    uint64_t instruction_pointer;\n    uint64_t stack_pointer;\n    union {\n        struct {\n            uint64_t nr;\n            uint64_t args[6];\n        } entry;\n        struct {\n            int64_t rval;\n            uint8_t is_error;\n        } exit;\n        struct {\n            uint64_t nr;\n            uint64_t args[6];\n            uint32_t ret_data;\n        } seccomp;\n    };\n  };\n};\n\nstruct X64Arch : public BaseArch<SupportedArch::x86_64, WordSize64Defs> {\n  typedef X64Arch Arch64;\n\n  static const uint8_t default_virtual_address_size = 47;\n\n  static const size_t elfmachine = EM::X86_64;\n  static const size_t elfendian = ELFENDIAN::DATA2LSB;\n\n  static const MmapCallingSemantics mmap_semantics = RegisterArguments;\n  static const CloneTLSType clone_tls_type = PthreadStructurePointer;\n  static const CloneParameterOrdering clone_parameter_ordering =\n      FlagsStackParentChildTLS;\n  static const SelectCallingSemantics select_semantics =\n      SelectRegisterArguments;\n\n  typedef uint32_t legacy_uid_t;\n  typedef uint32_t legacy_gid_t;\n\n#include \"SyscallEnumsX64.generated\"\n\n  // Architecture specific ptrace commands\n\n  static const int PTRACE_GETREGS = 12;\n  static const int PTRACE_SETREGS = 13;\n  static const int PTRACE_GETFPREGS = 14;\n  static const int PTRACE_SETFPREGS = 15;\n  static const int PTRACE_GETFPXREGS = 18;\n  static const int PTRACE_SETFPXREGS = 19;\n  static const int PTRACE_OLDSETOPTIONS = 21;\n  static const int PTRACE_GET_THREAD_AREA = 25;\n  static const int PTRACE_SET_THREAD_AREA = 26;\n  static const int PTRACE_ARCH_PRCTL = 30;\n  static const int PTRACE_SYSEMU = 31;\n  static const int PTRACE_SYSEMU_SINGLESTEP = 32;\n\n  struct user_regs_struct {\n    uint64_t r15;\n    uint64_t r14;\n    uint64_t r13;\n    uint64_t r12;\n    uint64_t rbp;\n    uint64_t rbx;\n    uint64_t r11;\n    uint64_t r10;\n    uint64_t r9;\n    uint64_t r8;\n    uint64_t rax;\n    uint64_t rcx;\n    uint64_t rdx;\n    uint64_t rsi;\n    uint64_t rdi;\n    // Unsigned type matches <sys/user.h>, but we need to treat this as\n    // signed in practice.\n    uint64_t orig_rax;\n    uint64_t rip;\n    uint64_t cs;\n    uint64_t eflags;\n    uint64_t rsp;\n    uint64_t ss;\n    // These _base registers are architecturally defined MSRs and really do\n    // need to be 64-bit.\n    uint64_t fs_base;\n    uint64_t gs_base;\n    uint64_t ds;\n    uint64_t es;\n    uint64_t fs;\n    uint64_t gs;\n  };\n  RR_VERIFY_TYPE_X86_ARCH(SupportedArch::x86_64, ::user_regs_struct,\n                          user_regs_struct);\n\n  struct sigcontext {\n    uint64_t r8;\n    uint64_t r9;\n    uint64_t r10;\n    uint64_t r11;\n    uint64_t r12;\n    uint64_t r13;\n    uint64_t r14;\n    uint64_t r15;\n    uint64_t di;\n    uint64_t si;\n    uint64_t bp;\n    uint64_t bx;\n    uint64_t dx;\n    uint64_t ax;\n    uint64_t cx;\n    uint64_t sp;\n    uint64_t ip;\n    uint64_t flags;\n    uint16_t cs;\n    uint16_t gs;\n    uint16_t fs;\n    uint16_t __pad0;\n    uint64_t err;\n    uint64_t trapno;\n    uint64_t oldmask;\n    uint64_t cr2;\n    uint64_t fpstate;\n    uint64_t reserved[8];\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, ::sigcontext, sigcontext);\n\n  struct user_fpregs_struct {\n    uint16_t cwd;\n    uint16_t swd;\n    uint16_t ftw;\n    uint16_t fop;\n    uint64_t rip;\n    uint64_t rdp;\n    uint32_t mxcsr;\n    uint32_t mxcr_mask;\n    uint32_t st_space[32];\n    uint32_t xmm_space[64];\n    uint32_t padding[24];\n  };\n  RR_VERIFY_TYPE_X86_ARCH(SupportedArch::x86_64, ::user_fpregs_struct,\n                          user_fpregs_struct);\n\n  struct user {\n    struct user_regs_struct regs;\n    int u_fpvalid;\n    struct user_fpregs_struct i387;\n    uint64_t u_tsize;\n    uint64_t u_dsize;\n    uint64_t u_ssize;\n    uint64_t start_code;\n    uint64_t start_stack;\n    int64_t signal;\n    int reserved;\n    union {\n      struct user_regs_struct* u_ar0;\n      uint64_t __u_ar0_word;\n    };\n    union {\n      struct user_fpregs_struct* u_fpstate;\n      uint64_t __u_fpstate_word;\n    };\n    uint64_t magic;\n    char u_comm[32];\n    uint64_t u_debugreg[8];\n    uint64_t error_code;\n    uint64_t fault_address;\n  };\n  // Can't verify this one because glibc leaves out the last two members and the\n  // kernel header isn't available to userspace.\n\n  struct stat_t {\n    dev_t st_dev;\n    ino_t st_ino;\n    nlink_t st_nlink;\n    mode_t st_mode;\n    uid_t st_uid;\n    gid_t st_gid;\n    int __pad0;\n    dev_t st_rdev;\n    off_t st_size;\n    blksize_t st_blksize;\n    blkcnt_t st_blocks;\n    struct timespec st_atim;\n    struct timespec st_mtim;\n    struct timespec st_ctim;\n    syscall_slong_t __rr_unused[3];\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::stat, struct stat_t);\n\n  struct stat64_t : public stat_t {};\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::stat64, struct stat64_t);\n\n  struct semid64_ds {\n    ipc64_perm sem_perm;\n    __kernel_time_t sem_otime;\n    __kernel_ulong_t __unused1;\n    __kernel_time_t sem_ctime;\n    __kernel_ulong_t __unused2;\n    __kernel_ulong_t sem_nsems;\n    __kernel_ulong_t __unused3;\n    __kernel_ulong_t __unused4;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::semid64_ds, struct semid64_ds);\n\n  struct ethtool_rx_flow_spec {\n    uint32_t flow_type;\n    char h_u[52];\n    char h_ext[20];\n    char m_u[52];\n    char m_ext[20];\n    uint64_t ring_cookie;\n    uint32_t location;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::ethtool_rx_flow_spec, struct ethtool_rx_flow_spec);\n\n  struct ethtool_rxnfc {\n    uint32_t cmd;\n    uint32_t flow_type;\n    uint64_t data;\n    struct ethtool_rx_flow_spec fs;\n    union {\n      uint32_t rule_cnt;\n      uint32_t rss_context;\n    };\n    uint32_t rule_locs[0];\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::ethtool_rxnfc, struct ethtool_rxnfc);\n\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::flock, _flock);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::rlimit, rlimit);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::statfs, statfs_t);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::dirent, dirent);\n};\n\nstruct X86Arch : public BaseArch<SupportedArch::x86, WordSize32Defs> {\n  typedef X64Arch Arch64;\n\n  static const uint8_t default_virtual_address_size = 32;\n\n  static const size_t elfmachine = EM::I386;\n  static const size_t elfendian = ELFENDIAN::DATA2LSB;\n\n  static const MmapCallingSemantics mmap_semantics = StructArguments;\n  static const CloneTLSType clone_tls_type = UserDescPointer;\n  static const CloneParameterOrdering clone_parameter_ordering =\n      FlagsStackParentTLSChild;\n  static const SelectCallingSemantics select_semantics = SelectStructArguments;\n\n  // The getgroups syscall (as well as several others) differs between\n  // architectures depending on whether they ever supported 16-bit\n  // {U,G}IDs or not.  Architectures such as x86, which did support\n  // 16-bit {U,G}IDs, have a getgroups syscall for the 16-bit GID case\n  // and a getgroups32 syscall for the 32-bit GID case.  Architectures\n  // such as as x86-64, which support 32-bit GIDs exclusively, have only\n  // a getgroups syscall.  We need to know which one we're dealing with\n  // when recording and replaying getgroups and related syscalls.\n  typedef uint16_t legacy_uid_t;\n  typedef uint16_t legacy_gid_t;\n\n#include \"SyscallEnumsX86.generated\"\n\n  // The same as x86_64\n  static const int PTRACE_GETREGS = Arch64::PTRACE_GETREGS;\n  static const int PTRACE_SETREGS = Arch64::PTRACE_SETREGS;\n  static const int PTRACE_GETFPREGS = Arch64::PTRACE_GETFPREGS;\n  static const int PTRACE_SETFPREGS = Arch64::PTRACE_SETFPREGS;\n  static const int PTRACE_GETFPXREGS = Arch64::PTRACE_GETFPXREGS;\n  static const int PTRACE_SETFPXREGS = Arch64::PTRACE_SETFPXREGS;\n  static const int PTRACE_OLDSETOPTIONS = Arch64::PTRACE_OLDSETOPTIONS;\n  static const int PTRACE_GET_THREAD_AREA = Arch64::PTRACE_GET_THREAD_AREA;\n  static const int PTRACE_SET_THREAD_AREA = Arch64::PTRACE_SET_THREAD_AREA;\n  // PTRACE_ARCH_PRCTL does not exist on x86\n  static const int PTRACE_SYSEMU = Arch64::PTRACE_SYSEMU;\n  static const int PTRACE_SYSEMU_SINGLESTEP = Arch64::PTRACE_SYSEMU_SINGLESTEP;\n  static const int RR_AT_SYSINFO = 32;\n\n  struct user_regs_struct {\n    int32_t ebx;\n    int32_t ecx;\n    int32_t edx;\n    int32_t esi;\n    int32_t edi;\n    int32_t ebp;\n    int32_t eax;\n    int32_t xds;\n    int32_t xes;\n    int32_t xfs;\n    int32_t xgs;\n    int32_t orig_eax;\n    int32_t eip;\n    int32_t xcs;\n    int32_t eflags;\n    int32_t esp;\n    int32_t xss;\n  };\n  RR_VERIFY_TYPE_X86_ARCH(SupportedArch::x86, ::user_regs_struct, user_regs_struct);\n\n  struct user_fpregs_struct {\n    int32_t cwd;\n    int32_t swd;\n    int32_t twd;\n    int32_t fip;\n    int32_t fcs;\n    int32_t foo;\n    int32_t fos;\n    int32_t st_space[20];\n  };\n  RR_VERIFY_TYPE_X86_ARCH(SupportedArch::x86, ::user_fpregs_struct,\n                          user_fpregs_struct);\n\n  struct user_fpxregs_struct {\n    uint16_t cwd;\n    uint16_t swd;\n    uint16_t twd;\n    uint16_t fop;\n    int32_t fip;\n    int32_t fcs;\n    int32_t foo;\n    int32_t fos;\n    int32_t mxcsr;\n    int32_t reserved;\n    int32_t st_space[32];\n    int32_t xmm_space[32];\n    int32_t padding[56];\n  };\n#if defined(__i386__)\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86, ::user_fpxregs_struct,\n                      user_fpxregs_struct);\n#endif\n\n  struct sigcontext {\n    uint16_t gs, __gsh;\n    uint16_t fs, __fsh;\n    uint16_t es, __esh;\n    uint16_t ds, __dsh;\n    uint32_t di;\n    uint32_t si;\n    uint32_t bp;\n    uint32_t sp;\n    uint32_t bx;\n    uint32_t dx;\n    uint32_t cx;\n    uint32_t ax;\n    uint32_t trapno;\n    uint32_t err;\n    uint32_t ip;\n    uint16_t cs, __csh;\n    uint32_t flags;\n    uint32_t sp_at_signal;\n    uint16_t ss, __ssh;\n    uint32_t fpstate;\n    uint32_t oldmask;\n    uint32_t cr2;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86, ::sigcontext, sigcontext);\n\n  struct user {\n    user_regs_struct regs;\n    int u_fpvalid;\n    user_fpregs_struct i387;\n    uint32_t u_tsize;\n    uint32_t u_dsize;\n    uint32_t u_ssize;\n    uint32_t start_code;\n    uint32_t start_stack;\n    int32_t signal;\n    int reserved;\n    ptr<user_regs_struct> u_ar0;\n    ptr<user_fpregs_struct> u_fpstate;\n    uint32_t magic;\n    char u_comm[32];\n    int u_debugreg[8];\n  };\n  RR_VERIFY_TYPE_X86_ARCH(SupportedArch::x86, ::user, user);\n\n  struct stat_t {\n    dev_t st_dev;\n    unsigned_short __pad1;\n    ino_t st_ino;\n    mode_t st_mode;\n    nlink_t st_nlink;\n    uid_t st_uid;\n    gid_t st_gid;\n    dev_t st_rdev;\n    unsigned_short __pad2;\n    off_t st_size;\n    blksize_t st_blksize;\n    blkcnt_t st_blocks;\n    timespec st_atim;\n    timespec st_mtim;\n    timespec st_ctim;\n    unsigned_long __unused4;\n    unsigned_long __unused5;\n  };\n  // Doesn't verify on x86-32 where various fields are 64 bits because\n  // we need to access large files/filesystems.\n\n  struct __attribute__((packed)) stat64_t {\n    dev_t st_dev;\n    unsigned_int __pad1;\n    ino_t __st_ino;\n    mode_t st_mode;\n    nlink_t st_nlink;\n    uid_t st_uid;\n    gid_t st_gid;\n    dev_t st_rdev;\n    unsigned_int __pad2;\n    off64_t st_size;\n    blksize_t st_blksize;\n    blkcnt64_t st_blocks;\n    timespec st_atim;\n    timespec st_mtim;\n    timespec st_ctim;\n    ino64_t st_ino;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86, struct ::stat64, struct stat64_t);\n\n  struct semid64_ds {\n    ipc64_perm sem_perm;\n    __kernel_time_t sem_otime;\n    __kernel_ulong_t sem_otime_high;\n    __kernel_time_t sem_ctime;\n    __kernel_ulong_t sem_ctime_high;\n    __kernel_ulong_t sem_nsems;\n    __kernel_ulong_t __unused3;\n    __kernel_ulong_t __unused4;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86, struct ::semid64_ds, struct semid64_ds);\n\n  struct __attribute__((packed)) ethtool_rx_flow_spec {\n    uint32_t flow_type;\n    char h_u[52];\n    char h_ext[20];\n    char m_u[52];\n    char m_ext[20];\n    uint64_t ring_cookie;\n    uint32_t location;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86, struct ::ethtool_rx_flow_spec, struct ethtool_rx_flow_spec);\n\n  struct __attribute__((packed)) ethtool_rxnfc {\n    uint32_t cmd;\n    uint32_t flow_type;\n    uint64_t data;\n    struct ethtool_rx_flow_spec fs;\n    union {\n      uint32_t rule_cnt;\n      uint32_t rss_context;\n    };\n    uint32_t rule_locs[0];\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86, struct ::ethtool_rxnfc, struct ethtool_rxnfc);\n};\n\n// Archs that inherit Linux's \"generic\" data structures\ntemplate <SupportedArch arch_, typename wordsize>\nstruct GenericArch : public BaseArch<arch_, wordsize> {\n  // All architectures using the generic syscall table only ever use 32-bit\n  // UIDs. See explanation of legacy_uid_t above.\n  typedef uint32_t legacy_uid_t;\n  typedef uint32_t legacy_gid_t;\n\n  // See kernel include/uapi/asm-generic/stat.h\n  struct stat_t {\n    typename BaseArch<arch_, wordsize>::unsigned_long st_dev;\n    typename BaseArch<arch_, wordsize>::unsigned_long st_ino;\n    typename BaseArch<arch_, wordsize>::unsigned_int st_mode;\n    typename BaseArch<arch_, wordsize>::unsigned_int st_nlink;\n    typename BaseArch<arch_, wordsize>::unsigned_int st_uid;\n    typename BaseArch<arch_, wordsize>::unsigned_int st_gid;\n    typename BaseArch<arch_, wordsize>::unsigned_long st_rdev;\n    typename BaseArch<arch_, wordsize>::unsigned_long __pad1;\n    typename BaseArch<arch_, wordsize>::signed_long st_size;\n    typename BaseArch<arch_, wordsize>::signed_int st_blksize;\n    typename BaseArch<arch_, wordsize>::signed_int __pad2;\n    typename BaseArch<arch_, wordsize>::signed_long st_blocks;\n    typename BaseArch<arch_, wordsize>::timespec st_atim;\n    typename BaseArch<arch_, wordsize>::timespec st_mtim;\n    typename BaseArch<arch_, wordsize>::timespec st_ctim;\n    typename BaseArch<arch_, wordsize>::unsigned_int __rr_unused[2];\n  };\n\n  struct semid64_ds {\n    typename BaseArch<arch_, wordsize>::ipc64_perm sem_perm;\n    uint64_t sem_otime;\n    uint64_t sem_ctime;\n    typename BaseArch<arch_, wordsize>::unsigned_long sem_nsems;\n    typename BaseArch<arch_, wordsize>::unsigned_long __unused3;\n    typename BaseArch<arch_, wordsize>::unsigned_long __unused4;\n  };\n\n  struct stat64_t : public stat_t {};\n};\n\nstruct ARM64Arch : public GenericArch<SupportedArch::aarch64, WordSize64Defs> {\n  typedef ARM64Arch Arch64;\n\n  static const uint8_t default_virtual_address_size = 47;\n\n  static const size_t elfmachine = EM::AARCH64;\n  static const size_t elfendian = ELFENDIAN::DATA2LSB;\n\n  static const MmapCallingSemantics mmap_semantics = RegisterArguments;\n  static const CloneTLSType clone_tls_type = PthreadStructurePointer;\n  static const CloneParameterOrdering clone_parameter_ordering =\n      FlagsStackParentTLSChild;\n  static const SelectCallingSemantics select_semantics =\n      SelectRegisterArguments;\n\n#include \"SyscallEnumsGeneric.generated\"\n\n  // Architecture specific ptrace commands\n  static const int PTRACE_SYSEMU = 31;\n  static const int PTRACE_SYSEMU_SINGLESTEP = 32;\n\n  struct user_pt_regs {\n    uint64_t x[31];\n    uint64_t sp;\n    uint64_t pc;\n    uint64_t pstate;\n  };\n  typedef struct user_pt_regs user_regs_struct;\n\n#if defined (__i386__)\n  typedef struct {\n    uint64_t parts[2];\n  } __uint128_t;\n#endif\n  struct user_fpsimd_state {\n    __uint128_t vregs[32];\n    uint32_t fpsr;\n    uint32_t fpcr;\n    uint32_t rr_reserved[2];\n  };\n  typedef struct user_fpsimd_state user_fpregs_struct;\n\n  struct hw_breakpoint_ctrl {\n    uint32_t enabled:1;\n    uint32_t priv:2;\n    uint32_t type:2;\n    uint32_t length:8;\n    uint32_t _pad:19;\n  };\n  static_assert(sizeof(hw_breakpoint_ctrl) == sizeof(uint32_t), \"Size mismatch\");\n\n  struct hw_bp {\n    uint64_t addr;\n    hw_breakpoint_ctrl ctrl;\n    uint32_t _pad;\n  };\n\n  struct user_hwdebug_state {\n    uint32_t dbg_info;\n    uint32_t pad;\n    struct hw_bp dbg_regs[16];\n  };\n\n  // Also defined as mcontext_t in some headers\n  struct __attribute((aligned(16))) sigcontext {\n    __u64 fault_addr;\n    user_pt_regs regs;\n    // ISA extension state follows here\n    unsigned char __reserved[4096] __attribute((aligned(16)));\n  };\n\n  // Also defined as ucontext_t in some headers\n  struct ucontext {\n    unsigned long\tuc_flags;\n    ptr<ucontext> uc_link;\n    stack_t\t\t  uc_stack;\n    kernel_sigset_t\t  uc_sigmask;\n    /* 128 bytes are reserved for the sigmask so reflect that here */\n    uint8_t __unused1[1024 / 8 - sizeof(kernel_sigset_t)];\n    struct sigcontext uc_mcontext;\n  };\n\n  struct rt_sigframe {\n    siginfo_t info;\n    struct ucontext uc;\n  };\n\n  RR_VERIFY_TYPE_ARCH(SupportedArch::aarch64, struct ::stat, struct stat_t);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::aarch64, struct ::semid64_ds, struct semid64_ds);\n\n  struct ethtool_rx_flow_spec {\n    uint32_t flow_type;\n    char h_u[52];\n    char h_ext[20];\n    char m_u[52];\n    char m_ext[20];\n    uint64_t ring_cookie;\n    uint32_t location;\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::aarch64, struct ::ethtool_rx_flow_spec, struct ethtool_rx_flow_spec);\n\n  struct ethtool_rxnfc {\n    uint32_t cmd;\n    uint32_t flow_type;\n    uint64_t data;\n    struct ethtool_rx_flow_spec fs;\n    union {\n      uint32_t rule_cnt;\n      uint32_t rss_context;\n    };\n    uint32_t rule_locs[0];\n  };\n  RR_VERIFY_TYPE_ARCH(SupportedArch::aarch64, struct ::ethtool_rxnfc, struct ethtool_rxnfc);\n\n  RR_VERIFY_TYPE_ARCH(SupportedArch::aarch64, struct ::flock, _flock);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::aarch64, struct ::rlimit, rlimit);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::statfs, statfs_t);\n  RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, struct ::dirent, dirent);\n\n  struct user_pac_address_keys {\n    __uint128_t apiakey;\n    __uint128_t apibkey;\n    __uint128_t\tapdakey;\n    __uint128_t apdbkey;\n  };\n\n  struct user_pac_generic_keys {\n    __uint128_t apgakey;\n  };\n};\n\n#define RR_ARCH_FUNCTION(f, arch, args...)                                     \\\n  switch (arch) {                                                              \\\n    default:                                                                   \\\n      DEBUG_ASSERT(0 && \"Unknown architecture\");                               \\\n      RR_FALLTHROUGH;                                                          \\\n    case x86:                                                                  \\\n      return f<rr::X86Arch>(args);                                             \\\n    case x86_64:                                                               \\\n      return f<rr::X64Arch>(args);                                             \\\n    case aarch64:                                                              \\\n      return f<rr::ARM64Arch>(args);                                           \\\n  }\n\n#include \"SyscallHelperFunctions.generated\"\n\n/**\n * Return true if |ptr| in task |t| points to an invoke-syscall instruction,\n * and if so, return the architecture for which this is a syscall in *arch.\n */\nbool get_syscall_instruction_arch(Task* t, remote_code_ptr ptr,\n                                  SupportedArch* arch, bool* ok=nullptr);\n\n/**\n * Return true if |ptr| in task |t| points to an invoke-syscall instruction.\n */\nbool is_at_syscall_instruction(Task* t, remote_code_ptr ptr, bool* ok=nullptr);\n\n/**\n * Return the code bytes of an invoke-syscall instruction. The vector must\n * have the length given by |syscall_instruction_length|.\n */\nstd::vector<uint8_t> syscall_instruction(SupportedArch arch);\n\n/**\n * Return the length of all invoke-syscall instructions. Currently,\n * they must all have the same length!\n */\nssize_t syscall_instruction_length(SupportedArch arch);\n\n/**\n * Return the length of the breakpoint instruction.\n */\nssize_t bkpt_instruction_length(SupportedArch arch);\n\n// The maximum breakpoint instruction length for any architecture\nstatic const int MAX_BKPT_INSTRUCTION_LENGTH = 4;\n\n/**\n * Return the length of the vsyscall invocation pattern. Currently,\n * we only support patterns of the form movq %addr, %rax; callq *%rax.\n */\nssize_t vsyscall_entry_length(SupportedArch arch);\n\n/**\n * Return the length of the mov (m),r instruction we use to cause intentional,\n * conditional, memory traps.\n */\nssize_t movrm_instruction_length(SupportedArch arch);\n\nvoid set_arch_siginfo(const siginfo_t& siginfo, SupportedArch a, void* dest,\n                      size_t dest_size);\n\nsize_t sigaction_sigset_size(SupportedArch arch);\n\nsize_t user_regs_struct_size(SupportedArch arch);\nsize_t user_fpregs_struct_size(SupportedArch arch);\n\n/* Returns the number of bits necessary for this particular virtual address. */\nuint8_t virtual_address_size(SupportedArch arch, remote_ptr<void> ptr);\n/* Returns the number of bits supported by default on this architecture for\n * *userspace* virtual addresses.\n */\nuint8_t default_virtual_address_size(SupportedArch arch);\n\n#if defined(__i386__)\ntypedef X86Arch NativeArch;\n#elif defined(__x86_64__)\ntypedef X64Arch NativeArch;\n#elif defined(__aarch64__)\ntypedef ARM64Arch NativeArch;\n#else\n#error need to define new NativeArch\n#endif\n\n} // namespace rr\n\n#endif /* RR_KERNEL_ABI_H */\n"
  },
  {
    "path": "src/kernel_metadata.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"kernel_metadata.h\"\n\n#include <errno.h>\n#include <linux/shm.h>\n#include <signal.h>\n#include <syscall.h>\n#include <sys/resource.h>\n\n#include <sstream>\n\n#include \"kernel_abi.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n#include \"SyscallnameArch.generated\"\n\nstring syscall_name(int syscall, SupportedArch arch) {\n  RR_ARCH_FUNCTION(syscallname_arch, arch, syscall)\n}\n\n#define CASE(_id)                                                              \\\n  case _id:                                                                    \\\n    return #_id;\n\nstring arch_name(SupportedArch arch) {\n  switch (arch) {\n    CASE(x86_64);\n    CASE(x86);\n    CASE(aarch64);\n  default:\n    char buf[100];\n    snprintf(buf, sizeof(buf), \"Unknown architecture %d\", arch);\n    return string(buf);\n  }\n}\n\nstring ptrace_event_name(int event) {\n  switch (event) {\n    CASE(PTRACE_EVENT_FORK);\n    CASE(PTRACE_EVENT_VFORK);\n    CASE(PTRACE_EVENT_CLONE);\n    CASE(PTRACE_EVENT_EXEC);\n    CASE(PTRACE_EVENT_VFORK_DONE);\n    CASE(PTRACE_EVENT_EXIT);\n    /* XXX Ubuntu 12.04 defines a \"PTRACE_EVENT_STOP\", but that\n     * has the same value as the newer EVENT_SECCOMP, so we'll\n     * ignore STOP. */\n    CASE(PTRACE_EVENT_SECCOMP_OBSOLETE);\n    CASE(PTRACE_EVENT_SECCOMP);\n    CASE(PTRACE_EVENT_STOP);\n    /* Special-case this so we don't need to sprintf in this common case.\n     * This case is common because we often pass ptrace_event_name(event) to\n     * assertions when event is 0.\n     */\n    case 0:\n      return \"PTRACE_EVENT(0)\";\n    default: {\n      char buf[100];\n      snprintf(buf, sizeof(buf), \"PTRACE_EVENT(%d)\", event);\n      return string(buf);\n    }\n  }\n}\n\n#define PTRACE_ARCH_CASE(_id)                                                  \\\n  case Arch::_id:                                                              \\\n    return #_id\n\ntemplate <typename Arch>\nstring ptrace_req_name(int request) {\n  switch (request >= 0 ? request : INT32_MAX) {\n    PTRACE_ARCH_CASE(PTRACE_TRACEME);\n    PTRACE_ARCH_CASE(PTRACE_PEEKTEXT);\n    PTRACE_ARCH_CASE(PTRACE_PEEKDATA);\n    PTRACE_ARCH_CASE(PTRACE_PEEKUSR);\n    PTRACE_ARCH_CASE(PTRACE_POKETEXT);\n    PTRACE_ARCH_CASE(PTRACE_POKEDATA);\n    PTRACE_ARCH_CASE(PTRACE_POKEUSR);\n    PTRACE_ARCH_CASE(PTRACE_CONT);\n    PTRACE_ARCH_CASE(PTRACE_KILL);\n    PTRACE_ARCH_CASE(PTRACE_SINGLESTEP);\n    PTRACE_ARCH_CASE(PTRACE_GETREGS);\n    PTRACE_ARCH_CASE(PTRACE_SETREGS);\n    PTRACE_ARCH_CASE(PTRACE_GETFPREGS);\n    PTRACE_ARCH_CASE(PTRACE_SETFPREGS);\n    PTRACE_ARCH_CASE(PTRACE_GETFPXREGS);\n    PTRACE_ARCH_CASE(PTRACE_SETFPXREGS);\n    PTRACE_ARCH_CASE(PTRACE_ATTACH);\n    PTRACE_ARCH_CASE(PTRACE_DETACH);\n    PTRACE_ARCH_CASE(PTRACE_SYSCALL);\n    PTRACE_ARCH_CASE(PTRACE_SETOPTIONS);\n    PTRACE_ARCH_CASE(PTRACE_GETEVENTMSG);\n    PTRACE_ARCH_CASE(PTRACE_GETSIGINFO);\n    PTRACE_ARCH_CASE(PTRACE_SETSIGINFO);\n    PTRACE_ARCH_CASE(PTRACE_GETREGSET);\n    PTRACE_ARCH_CASE(PTRACE_SETREGSET);\n    PTRACE_ARCH_CASE(PTRACE_SEIZE);\n    PTRACE_ARCH_CASE(PTRACE_INTERRUPT);\n    PTRACE_ARCH_CASE(PTRACE_LISTEN);\n    PTRACE_ARCH_CASE(PTRACE_GETSIGMASK);\n    PTRACE_ARCH_CASE(PTRACE_SETSIGMASK);\n    PTRACE_ARCH_CASE(PTRACE_GET_SYSCALL_INFO);\n    // These aren't part of the official ptrace-request enum.\n    PTRACE_ARCH_CASE(PTRACE_SYSEMU);\n    PTRACE_ARCH_CASE(PTRACE_SYSEMU_SINGLESTEP);\n    default: {\n      char buf[100];\n      snprintf(buf, sizeof(buf), \"PTRACE_REQUEST(%d)\", request);\n      return string(buf);\n    }\n  }\n}\n\ntemplate string ptrace_req_name<X86Arch>(int request);\ntemplate string ptrace_req_name<X64Arch>(int request);\ntemplate string ptrace_req_name<ARM64Arch>(int request);\n\nstring signal_name(int sig) {\n  /* strsignal() would be nice to use here, but it provides TMI. */\n  if (32 <= sig && sig <= 64) {\n    char buf[100];\n    snprintf(buf, sizeof(buf) - 1, \"SIGRT%d\", sig);\n    return buf;\n  }\n\n  switch (sig) {\n    CASE(SIGHUP);\n    CASE(SIGINT);\n    CASE(SIGQUIT);\n    CASE(SIGILL);\n    CASE(SIGTRAP);\n    CASE(SIGABRT); /*CASE(SIGIOT);*/\n    CASE(SIGBUS);\n    CASE(SIGFPE);\n    CASE(SIGKILL);\n    CASE(SIGUSR1);\n    CASE(SIGSEGV);\n    CASE(SIGUSR2);\n    CASE(SIGPIPE);\n    CASE(SIGALRM);\n    CASE(SIGTERM);\n    CASE(SIGSTKFLT); /*CASE(SIGCLD);*/\n    CASE(SIGCHLD);\n    CASE(SIGCONT);\n    CASE(SIGSTOP);\n    CASE(SIGTSTP);\n    CASE(SIGTTIN);\n    CASE(SIGTTOU);\n    CASE(SIGURG);\n    CASE(SIGXCPU);\n    CASE(SIGXFSZ);\n    CASE(SIGVTALRM);\n    CASE(SIGPROF);\n    CASE(SIGWINCH); /*CASE(SIGPOLL);*/\n    CASE(SIGIO);\n    CASE(SIGPWR);\n    CASE(SIGSYS);\n    /* Special-case this so we don't need to sprintf in this common case.\n     * This case is common because we often pass signal_name(sig) to assertions\n     * when sig is 0.\n     */\n    case 0:\n      return \"signal(0)\";\n    default: {\n      char buf[100];\n      snprintf(buf, sizeof(buf), \"signal(%d)\", sig);\n      return string(buf);\n    }\n  }\n}\n\nbool is_sigreturn(int syscallno, SupportedArch arch) {\n  return is_sigreturn_syscall(syscallno, arch) ||\n         is_rt_sigreturn_syscall(syscallno, arch);\n}\n\nconst char *errno_name_cstr(int err) {\n  switch (err) {\n    case 0:\n      return \"SUCCESS\";\n      CASE(EPERM);\n      CASE(ENOENT);\n      CASE(ESRCH);\n      CASE(EINTR);\n      CASE(EIO);\n      CASE(ENXIO);\n      CASE(E2BIG);\n      CASE(ENOEXEC);\n      CASE(EBADF);\n      CASE(ECHILD);\n      CASE(EAGAIN);\n      CASE(ENOMEM);\n      CASE(EACCES);\n      CASE(EFAULT);\n      CASE(ENOTBLK);\n      CASE(EBUSY);\n      CASE(EEXIST);\n      CASE(EXDEV);\n      CASE(ENODEV);\n      CASE(ENOTDIR);\n      CASE(EISDIR);\n      CASE(EINVAL);\n      CASE(ENFILE);\n      CASE(EMFILE);\n      CASE(ENOTTY);\n      CASE(ETXTBSY);\n      CASE(EFBIG);\n      CASE(ENOSPC);\n      CASE(ESPIPE);\n      CASE(EROFS);\n      CASE(EMLINK);\n      CASE(EPIPE);\n      CASE(EDOM);\n      CASE(ERANGE);\n      CASE(EDEADLK);\n      CASE(ENAMETOOLONG);\n      CASE(ENOLCK);\n      CASE(ENOSYS);\n      CASE(ENOTEMPTY);\n      CASE(ELOOP);\n      CASE(ENOMSG);\n      CASE(EIDRM);\n      CASE(ECHRNG);\n      CASE(EL2NSYNC);\n      CASE(EL3HLT);\n      CASE(EL3RST);\n      CASE(ELNRNG);\n      CASE(EUNATCH);\n      CASE(ENOCSI);\n      CASE(EL2HLT);\n      CASE(EBADE);\n      CASE(EBADR);\n      CASE(EXFULL);\n      CASE(ENOANO);\n      CASE(EBADRQC);\n      CASE(EBADSLT);\n      CASE(EBFONT);\n      CASE(ENOSTR);\n      CASE(ENODATA);\n      CASE(ETIME);\n      CASE(ENOSR);\n      CASE(ENONET);\n      CASE(ENOPKG);\n      CASE(EREMOTE);\n      CASE(ENOLINK);\n      CASE(EADV);\n      CASE(ESRMNT);\n      CASE(ECOMM);\n      CASE(EPROTO);\n      CASE(EMULTIHOP);\n      CASE(EDOTDOT);\n      CASE(EBADMSG);\n      CASE(EOVERFLOW);\n      CASE(ENOTUNIQ);\n      CASE(EBADFD);\n      CASE(EREMCHG);\n      CASE(ELIBACC);\n      CASE(ELIBBAD);\n      CASE(ELIBSCN);\n      CASE(ELIBMAX);\n      CASE(ELIBEXEC);\n      CASE(EILSEQ);\n      CASE(ERESTART);\n      CASE(ESTRPIPE);\n      CASE(EUSERS);\n      CASE(ENOTSOCK);\n      CASE(EDESTADDRREQ);\n      CASE(EMSGSIZE);\n      CASE(EPROTOTYPE);\n      CASE(ENOPROTOOPT);\n      CASE(EPROTONOSUPPORT);\n      CASE(ESOCKTNOSUPPORT);\n      CASE(EOPNOTSUPP);\n      CASE(EPFNOSUPPORT);\n      CASE(EAFNOSUPPORT);\n      CASE(EADDRINUSE);\n      CASE(EADDRNOTAVAIL);\n      CASE(ENETDOWN);\n      CASE(ENETUNREACH);\n      CASE(ENETRESET);\n      CASE(ECONNABORTED);\n      CASE(ECONNRESET);\n      CASE(ENOBUFS);\n      CASE(EISCONN);\n      CASE(ENOTCONN);\n      CASE(ESHUTDOWN);\n      CASE(ETOOMANYREFS);\n      CASE(ETIMEDOUT);\n      CASE(ECONNREFUSED);\n      CASE(EHOSTDOWN);\n      CASE(EHOSTUNREACH);\n      CASE(EALREADY);\n      CASE(EINPROGRESS);\n      CASE(ESTALE);\n      CASE(EUCLEAN);\n      CASE(ENOTNAM);\n      CASE(ENAVAIL);\n      CASE(EISNAM);\n      CASE(EREMOTEIO);\n      CASE(EDQUOT);\n      CASE(ENOMEDIUM);\n      CASE(EMEDIUMTYPE);\n      CASE(ECANCELED);\n      CASE(ENOKEY);\n      CASE(EKEYEXPIRED);\n      CASE(EKEYREVOKED);\n      CASE(EKEYREJECTED);\n      CASE(EOWNERDEAD);\n      CASE(ENOTRECOVERABLE);\n      CASE(ERFKILL);\n      CASE(EHWPOISON);\n    default: return NULL;\n  }\n}\n\nstring errno_name(int err) {\n  const char *name = errno_name_cstr(err);\n  if (name == NULL) {\n    char buf[100];\n    snprintf(buf, sizeof(buf), \"errno(%d)\", err);\n    return string(buf);\n  }\n  return string(name);\n}\n\nstring sicode_name(int code, int sig) {\n  switch (code) {\n    CASE(SI_USER);\n    CASE(SI_KERNEL);\n    CASE(SI_QUEUE);\n    CASE(SI_TIMER);\n    CASE(SI_MESGQ);\n    CASE(SI_ASYNCIO);\n    CASE(SI_SIGIO);\n    CASE(SI_TKILL);\n    CASE(SI_ASYNCNL);\n  }\n\n  switch (sig) {\n    case SIGSEGV:\n      switch (code) {\n        CASE(SEGV_MAPERR);\n        CASE(SEGV_ACCERR);\n      }\n      break;\n    case SIGTRAP:\n      switch (code) {\n        CASE(TRAP_BRKPT);\n        CASE(TRAP_TRACE);\n        CASE(TRAP_HWBKPT);\n      }\n      break;\n    case SIGILL:\n      switch (code) {\n        CASE(ILL_ILLOPC);\n        CASE(ILL_ILLOPN);\n        CASE(ILL_ILLADR);\n        CASE(ILL_ILLTRP);\n        CASE(ILL_PRVOPC);\n        CASE(ILL_PRVREG);\n        CASE(ILL_COPROC);\n        CASE(ILL_BADSTK);\n      }\n      break;\n    case SIGFPE:\n      switch (code) {\n        CASE(FPE_INTDIV);\n        CASE(FPE_INTOVF);\n        CASE(FPE_FLTDIV);\n        CASE(FPE_FLTOVF);\n        CASE(FPE_FLTUND);\n        CASE(FPE_FLTRES);\n        CASE(FPE_FLTINV);\n        CASE(FPE_FLTSUB);\n      }\n      break;\n    case SIGBUS:\n      switch (code) {\n        CASE(BUS_ADRALN);\n        CASE(BUS_ADRERR);\n        CASE(BUS_OBJERR);\n        CASE(BUS_MCEERR_AR);\n        CASE(BUS_MCEERR_AO);\n      }\n      break;\n    case SIGCHLD:\n      switch (code) {\n        CASE(CLD_EXITED);\n        CASE(CLD_KILLED);\n        CASE(CLD_DUMPED);\n        CASE(CLD_TRAPPED);\n        CASE(CLD_STOPPED);\n        CASE(CLD_CONTINUED);\n      }\n      break;\n    case SIGPOLL:\n      switch (code) {\n        CASE(POLL_IN);\n        CASE(POLL_OUT);\n        CASE(POLL_MSG);\n        CASE(POLL_ERR);\n        CASE(POLL_PRI);\n        CASE(POLL_HUP);\n      }\n      break;\n  }\n\n  char buf[100];\n  snprintf(buf, sizeof(buf), \"sicode(%d)\", code);\n  return string(buf);\n}\n\nint shm_flags_to_mmap_prot(int flags) {\n  return PROT_READ | ((flags & SHM_RDONLY) ? 0 : PROT_WRITE) |\n         ((flags & SHM_EXEC) ? PROT_EXEC : 0);\n}\n\nstring xsave_feature_string(uint64_t xsave_features) {\n  string ret;\n  if (xsave_features & 0x01) {\n    ret += \"x87 \";\n  }\n  if (xsave_features & 0x02) {\n    ret += \"SSE \";\n  }\n  if (xsave_features & 0x04) {\n    ret += \"AVX \";\n  }\n  if (xsave_features & 0x08) {\n    ret += \"MPX-BNDREGS \";\n  }\n  if (xsave_features & 0x10) {\n    ret += \"MPX-BNDCSR \";\n  }\n  if (xsave_features & 0x20) {\n    ret += \"AVX512-opmask \";\n  }\n  if (xsave_features & 0x40) {\n    ret += \"AVX512-ZMM_Hi256 \";\n  }\n  if (xsave_features & 0x80) {\n    ret += \"AVX512-Hi16_ZMM \";\n  }\n  if (xsave_features & 0x100) {\n    ret += \"PT \";\n  }\n  if (xsave_features & 0x200) {\n    ret += \"PKRU \";\n  }\n  if (xsave_features & 0x2000) {\n    ret += \"HDC \";\n  }\n  if (ret.size() > 0) {\n    ret = ret.substr(0, ret.size() - 1);\n  }\n  return ret;\n}\n\nbool is_coredumping_signal(int signo) {\n  switch (signo) {\n    case SIGQUIT:\n    case SIGILL:\n    case SIGTRAP:\n    case SIGABRT:\n    case SIGFPE:\n    case SIGSEGV:\n    case SIGBUS:\n    case SIGSYS:\n    case SIGXCPU:\n    case SIGXFSZ:\n        return true;\n    default:\n        return false;\n  }\n}\n\n#define SI_COPY(f) result._sifields.f = si._sifields.f\n\ntemplate <typename Arch>\nNativeArch::siginfo_t convert_to_native_siginfo_arch(const void* data,\n    size_t size) {\n  typename Arch::siginfo_t si;\n  if (size != sizeof(si)) {\n    FATAL() << \"Siginfo has wrong size\";\n  }\n\n  NativeArch::siginfo_t result;\n  if (Arch::arch() == NativeArch::arch()) {\n    // Do the simple correct thing to make sure there are no bugs in this all-important case.\n    memcpy(&result, data, sizeof(result));\n    return result;\n  }\n\n  // We need to translate formats :-(.\n  memcpy(&si, data, sizeof(si));\n\n  result.si_signo = si.si_signo;\n  result.si_errno = si.si_errno;\n  result.si_code = si.si_code;\n  memset(result._sifields.padding, 0, sizeof(result._sifields.padding));\n  if (result.si_code <= 0) {\n    switch (result.si_code) {\n      case SI_USER:\n        SI_COPY(_kill.si_pid_);\n        SI_COPY(_kill.si_uid_);\n        break;\n      case SI_QUEUE:\n      case SI_MESGQ:\n        SI_COPY(_rt.si_pid_);\n        SI_COPY(_rt.si_uid_);\n        SI_COPY(_rt.si_sigval_.sival_ptr.val);\n        break;\n      case SI_TIMER:\n        SI_COPY(_timer.si_tid_);\n        SI_COPY(_timer.si_overrun_);\n        SI_COPY(_timer.si_sigval_.sival_ptr.val);\n        break;\n      default:\n        break;\n    }\n  } else {\n    switch (result.si_signo) {\n      case SIGCHLD:\n        SI_COPY(_sigchld.si_pid_);\n        SI_COPY(_sigchld.si_uid_);\n        SI_COPY(_sigchld.si_status_);\n        SI_COPY(_sigchld.si_stime_);\n        SI_COPY(_sigchld.si_utime_);\n        break;\n      case SIGILL:\n      case SIGFPE:\n      case SIGSEGV:\n      case SIGBUS:\n      case SIGTRAP:\n        SI_COPY(_sigfault.si_addr_.val);\n        SI_COPY(_sigfault.si_addr_lsb_);\n        SI_COPY(_sigfault._bounds._addr_bnds._lower.val);\n        SI_COPY(_sigfault._bounds._addr_bnds._upper.val);\n        break;\n      case SIGPOLL:\n        SI_COPY(_sigpoll.si_band_);\n        SI_COPY(_sigpoll.si_fd_);\n        break;\n      case SIGSYS:\n        SI_COPY(_sigsys._call_addr.val);\n        SI_COPY(_sigsys._syscall);\n        SI_COPY(_sigsys._arch);\n        break;\n    }\n  }\n\n  return result;\n}\n\nNativeArch::siginfo_t convert_to_native_siginfo(SupportedArch arch,\n    const void* data, size_t size) {\n  RR_ARCH_FUNCTION(convert_to_native_siginfo_arch, arch, data, size);\n}\n\nstring rlimit_resource_name(int resource) {\n  switch (resource) {\n    CASE(RLIMIT_AS);\n    CASE(RLIMIT_CORE);\n    CASE(RLIMIT_CPU);\n    CASE(RLIMIT_DATA);\n    CASE(RLIMIT_FSIZE);\n    CASE(RLIMIT_LOCKS);\n    CASE(RLIMIT_MEMLOCK);\n    CASE(RLIMIT_MSGQUEUE);\n    CASE(RLIMIT_NICE);\n    CASE(RLIMIT_NOFILE);\n    CASE(RLIMIT_NPROC);\n    CASE(RLIMIT_RSS);\n    CASE(RLIMIT_RTPRIO);\n    CASE(RLIMIT_RTTIME);\n    CASE(RLIMIT_SIGPENDING);\n    CASE(RLIMIT_STACK);\n  default:\n    char buf[100];\n    snprintf(buf, sizeof(buf), \"Unknown RLIMIT_ %d\", resource);\n    return string(buf);\n  }\n}\n\nstring prot_flags_string(int prot) {\n  char prot_flags[] = \"rwx\";\n  if (!(prot & PROT_READ)) {\n    prot_flags[0] = '-';\n  }\n  if (!(prot & PROT_WRITE)) {\n    prot_flags[1] = '-';\n  }\n  if (!(prot & PROT_EXEC)) {\n    prot_flags[2] = '-';\n  }\n  stringstream ret;\n  ret << prot_flags;\n  if (prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) {\n    ret << \" (\" << HEX(prot) << \")\";\n  }\n  return ret.str();\n}\n\nint addr_bits(SupportedArch arch) {\n  switch (arch) {\n    default:\n      DEBUG_ASSERT(0 && \"Unknown architecture\");\n      RR_FALLTHROUGH;\n    case x86:\n      return 32;\n    // Current x86-64 systems have only 48 bits of virtual address space,\n    // and only the bottom half is usable by user space\n    case x86_64:\n      return 47;\n    // Aarch64 has 48 bit address space, with user and kernel each getting\n    // their own 48 bits worth of address space at opposite end of the full\n    // 64-bit address space.\n    case aarch64:\n      return 48;\n  }\n}\n\nremote_ptr<void> usable_address_space_end(SupportedArch arch) {\n  auto addr_end = remote_ptr<void>((uint64_t(1) << addr_bits(arch)) - page_size());\n#if defined(__i386)\n  // Further limit address space in 32-bit rr to avoid interfering with kernel space.\n  addr_end = min(addr_end, remote_ptr<void>(0xc0000000 - page_size()));\n#endif\n  return addr_end;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/kernel_metadata.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_SYSCALLS_H_\n#define RR_SYSCALLS_H_\n\n#include <signal.h>\n\n#include <iostream>\n#include <string>\n\n#include \"kernel_abi.h\"\n#include \"remote_ptr.h\"\n\nnamespace rr {\n\n/**\n * Return the symbolic name of the architecture `arch`.\n */\nstd::string arch_name(SupportedArch arch);\n\n/**\n * Return the symbolic name of |syscall|, f.e. \"read\", or \"syscall(%d)\"\n * if unknown.\n */\nstd::string syscall_name(int syscall, SupportedArch arch);\n\n/**\n * Return the symbolic name of the PTRACE_EVENT_* |event|, or\n * \"PTRACE_EVENT(%d)\" if unknown.\n */\nstd::string ptrace_event_name(int event);\n\n/**\n * Return the symbolic name of the PTRACE_ |request|, or \"PTRACE_REQUEST(%d)\" if\n * unknown.\n */\ntemplate <typename Arch>\nstd::string ptrace_req_name(int request);\n\n/**\n * Return the symbolic name of |sig|, f.e. \"SIGILL\", or \"signal(%d)\" if\n * unknown.\n */\nstd::string signal_name(int sig);\n\n/**\n * Return true if this is some kind of sigreturn syscall.\n */\nbool is_sigreturn(int syscall, SupportedArch arch);\n\n/**\n * Return the symbolic error name (e.g. \"EINVAL\") for errno.\n */\nstd::string errno_name(int err);\n\n/* Same as errno_name, but returns a pointer to static memory or NULL if\nallocation would be required. Suitable for use in volatile contexts */\nconst char *errno_name_cstr(int err);\n\n/**\n * Return the symbolic name (e.g. \"SI_USER\") for an si_code.\n */\nstd::string sicode_name(int code, int sig);\n\nint shm_flags_to_mmap_prot(int flags);\n\n/**\n * Print string explaining xsave feature bits\n */\nstd::string xsave_feature_string(uint64_t xsave_features);\n\n/**\n * Return whether this is a core dumping signal or not.\n */\nbool is_coredumping_signal(int signo);\n\n/**\n * Convert a raw native siginfo_t to our arch siginfo_t.\n */\nNativeArch::siginfo_t convert_to_native_siginfo(SupportedArch arch,\n    const void* data, size_t size);\n\n/**\n * Stringify the prot bits.\n */\nstd::string prot_flags_string(int prot);\n\n/**\n * Return the number of usable address space bits for this arch.\n */\nint addr_bits(SupportedArch arch);\n\n/**\n * Return the end of the usable address space for this arch.\n */\nremote_ptr<void> usable_address_space_end(SupportedArch arch);\n\n/**\n * Convert an rlimit resource name to a string.\n */\nstd::string rlimit_resource_name(int resource);\n\n} // namespace rr\n\n#endif\n"
  },
  {
    "path": "src/kernel_supplement.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_KERNEL_SUPPLEMENT_H_\n#define RR_KERNEL_SUPPLEMENT_H_\n\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n\n#include <linux/capability.h>\n#include <linux/dma-buf.h>\n#include <linux/if_tun.h>\n#include <linux/mman.h>\n#include <linux/seccomp.h>\n#include <linux/usbdevice_fs.h>\n#include <sched.h>\n#include <signal.h>\n#include <stdint.h>\n#include <sys/ioctl.h>\n#include <sys/wait.h>\n\nnamespace rr {\n\n/* Definitions that should be part of system headers (and maybe are on some but\n * not all systems).\n * This should not contain anything for which rr needs all the definitions\n * across architectures; those definitions belong in kernel_abi.h.\n */\n\n#define KERNEL_CONSTANT(constant) \\\n  constant = KernelConstants::constant\n\nenum _ptrace_request {\n  KERNEL_CONSTANT(PTRACE_TRACEME),\n  KERNEL_CONSTANT(PTRACE_PEEKTEXT),\n  KERNEL_CONSTANT(PTRACE_PEEKDATA),\n  KERNEL_CONSTANT(PTRACE_PEEKUSR),\n  KERNEL_CONSTANT(PTRACE_PEEKUSER),\n  KERNEL_CONSTANT(PTRACE_POKETEXT),\n  KERNEL_CONSTANT(PTRACE_POKEDATA),\n  KERNEL_CONSTANT(PTRACE_POKEUSR),\n  KERNEL_CONSTANT(PTRACE_POKEUSER),\n  KERNEL_CONSTANT(PTRACE_CONT),\n  KERNEL_CONSTANT(PTRACE_KILL),\n  KERNEL_CONSTANT(PTRACE_SINGLESTEP),\n  KERNEL_CONSTANT(PTRACE_GETREGS),\n  KERNEL_CONSTANT(PTRACE_GETFPREGS),\n  KERNEL_CONSTANT(PTRACE_SETFPREGS),\n  KERNEL_CONSTANT(PTRACE_ATTACH),\n  KERNEL_CONSTANT(PTRACE_DETACH),\n  KERNEL_CONSTANT(PTRACE_SYSCALL),\n  KERNEL_CONSTANT(PTRACE_SETOPTIONS),\n  KERNEL_CONSTANT(PTRACE_GETEVENTMSG),\n  KERNEL_CONSTANT(PTRACE_GETSIGINFO),\n  KERNEL_CONSTANT(PTRACE_SETSIGINFO),\n  KERNEL_CONSTANT(PTRACE_GETREGSET),\n  KERNEL_CONSTANT(PTRACE_SETREGSET),\n  KERNEL_CONSTANT(PTRACE_SEIZE),\n  KERNEL_CONSTANT(PTRACE_INTERRUPT),\n  KERNEL_CONSTANT(PTRACE_LISTEN),\n  KERNEL_CONSTANT(PTRACE_GETSIGMASK),\n  KERNEL_CONSTANT(PTRACE_SETSIGMASK),\n  KERNEL_CONSTANT(PTRACE_GET_SYSCALL_INFO),\n};\n\nenum _ptrace_eventcodes {\n  KERNEL_CONSTANT(PTRACE_EVENT_NONE),\n  KERNEL_CONSTANT(PTRACE_EVENT_FORK),\n  KERNEL_CONSTANT(PTRACE_EVENT_VFORK),\n  KERNEL_CONSTANT(PTRACE_EVENT_CLONE),\n  KERNEL_CONSTANT(PTRACE_EVENT_EXEC),\n  KERNEL_CONSTANT(PTRACE_EVENT_VFORK_DONE),\n  KERNEL_CONSTANT(PTRACE_EVENT_EXIT),\n  KERNEL_CONSTANT(PTRACE_EVENT_SECCOMP),\n  KERNEL_CONSTANT(PTRACE_EVENT_SECCOMP_OBSOLETE),\n  KERNEL_CONSTANT(PTRACE_EVENT_STOP),\n};\n\nenum _ptrace_options {\n  KERNEL_CONSTANT(PTRACE_O_TRACESYSGOOD),\n  KERNEL_CONSTANT(PTRACE_O_TRACEFORK),\n  KERNEL_CONSTANT(PTRACE_O_TRACEVFORK),\n  KERNEL_CONSTANT(PTRACE_O_TRACECLONE),\n  KERNEL_CONSTANT(PTRACE_O_TRACEEXEC),\n  KERNEL_CONSTANT(PTRACE_O_TRACEVFORKDONE),\n  KERNEL_CONSTANT(PTRACE_O_TRACEEXIT),\n  KERNEL_CONSTANT(PTRACE_O_TRACESECCOMP),\n  KERNEL_CONSTANT(PTRACE_O_EXITKILL),\n};\n\nenum _ptrace_get_syscall_info_op {\n  KERNEL_CONSTANT(PTRACE_SYSCALL_INFO_NONE),\n  KERNEL_CONSTANT(PTRACE_SYSCALL_INFO_ENTRY),\n  KERNEL_CONSTANT(PTRACE_SYSCALL_INFO_EXIT),\n  KERNEL_CONSTANT(PTRACE_SYSCALL_INFO_SECCOMP),\n};\n\n#undef KERNEL_CONSTANT\n\n#ifndef SECCOMP_SET_MODE_STRICT\n#define SECCOMP_SET_MODE_STRICT 0\n#endif\n#ifndef SECCOMP_SET_MODE_FILTER\n#define SECCOMP_SET_MODE_FILTER 1\n#endif\n#ifndef SECCOMP_FILTER_FLAG_TSYNC\n#define SECCOMP_FILTER_FLAG_TSYNC 1\n#endif\n#ifndef SECCOMP_GET_ACTION_AVAIL\n#define SECCOMP_GET_ACTION_AVAIL 2\n#endif\n#ifndef SECCOMP_GET_NOTIF_SIZES\n#define SECCOMP_GET_NOTIF_SIZES 3\n#endif\n\n#ifndef SYS_SECCOMP\n#define SYS_SECCOMP 1\n#endif\n\n#ifndef SOL_NETLINK\n#define SOL_NETLINK 270\n#endif\n\n#ifndef PR_GET_SPECULATION_CTRL\n#define PR_GET_SPECULATION_CTRL 52\n#endif\n#ifndef PR_SET_SPECULATION_CTRL\n#define PR_SET_SPECULATION_CTRL 53\n#endif\n\n// This is used on AArch64 and available in linux/signal.h, but\n// including that header will conflict with a number of our\n// struct definitions.\n#ifndef TRAP_HWBKPT\n#define TRAP_HWBKPT 4\n#endif\n\n// This is used on AArch64 and not available on CentOS 7.8\n#ifndef NT_ARM_SYSTEM_CALL\n#define NT_ARM_SYSTEM_CALL 0x404\n#endif\n\n#ifndef NT_ARM_PACA_KEYS\n#define NT_ARM_PACA_KEYS 0x407\n#endif\n\n#ifndef NT_ARM_PACG_KEYS\n#define NT_ARM_PACG_KEYS 0x408\n#endif\n\n// These are defined by the include/linux/errno.h in the kernel tree.\n// Since userspace doesn't see these errnos in normal operation, that\n// header apparently isn't distributed with libc.\n#define ERESTARTSYS 512\n#define ERESTARTNOINTR 513\n#define ERESTARTNOHAND 514\n#define ERESTART_RESTARTBLOCK 516\n\n// These definitions haven't made it out to current libc-dev packages\n// yet.\n#ifndef GRND_NONBLOCK\n#define GRND_NONBLOCK 0x0001\n#define GRND_RANDOM 0x0002\n#endif\n\n/* We need to complement sigsets in order to update the Task blocked\n * set, but POSIX doesn't appear to define a convenient helper.  So we\n * define our own linux-compatible sig_set_t and use bit operators to\n * manipulate sigsets. */\ntypedef uint64_t sig_set_t;\nstatic_assert(_NSIG / 8 == sizeof(sig_set_t), \"Update sig_set_t for _NSIG.\");\n\n#ifndef BTRFS_IOCTL_MAGIC\n#define BTRFS_IOCTL_MAGIC 0x94\n#endif\n#ifndef BTRFS_IOC_CLONE\n#define BTRFS_IOC_CLONE _IOW(BTRFS_IOCTL_MAGIC, 9, int)\n#endif\n#ifndef BTRFS_IOC_CLONE_RANGE\nstruct btrfs_ioctl_clone_range_args {\n  int64_t src_fd;\n  uint64_t src_offset;\n  uint64_t src_length;\n  uint64_t dest_offset;\n};\n#define BTRFS_IOC_CLONE_RANGE                                                  \\\n  _IOW(BTRFS_IOCTL_MAGIC, 13, struct btrfs_ioctl_clone_range_args)\n#endif\n\n#ifndef USBDEVFS_GET_CAPABILITIES\n#define USBDEVFS_GET_CAPABILITIES _IOR('U', 26, __u32)\n#endif\n#ifndef USBDEVFS_DISCONNECT_CLAIM\nstruct usbdevfs_disconnect_claim {\n  unsigned int interface;\n  unsigned int flags;\n  char driver[USBDEVFS_MAXDRIVERNAME + 1];\n};\n#define USBDEVFS_DISCONNECT_CLAIM                                              \\\n  _IOR('U', 27, struct usbdevfs_disconnect_claim)\n#endif\n#ifndef USBDEVFS_ALLOC_STREAMS\nstruct usbdevfs_streams {\n  unsigned int num_streams;\n  unsigned int num_eps;\n  unsigned char eps[0];\n};\n#define USBDEVFS_ALLOC_STREAMS _IOR('U', 28, struct usbdevfs_streams)\n#define USBDEVFS_FREE_STREAMS _IOR('U', 29, struct usbdevfs_streams)\n#endif\n\n#ifndef TUNSETVNETLE\n#define TUNSETVNETLE _IOW('T', 220, int)\n#endif\n#ifndef TUNGETVNETLE\n#define TUNGETVNETLE _IOR('T', 221, int)\n#endif\n#ifndef TUNSETVNETBE\n#define TUNSETVNETBE _IOW('T', 222, int)\n#endif\n#ifndef TUNGETVNETBE\n#define TUNGETVNETBE _IOR('T', 223, int)\n#endif\n\n#ifndef TIOCGPKT\n#define TIOCGPKT _IOR('T', 0x38, int)\n#endif\n#ifndef TIOCGPTLCK\n#define TIOCGPTLCK _IOR('T', 0x39, int)\n#endif\n#ifndef TIOCGEXCL\n#define TIOCGEXCL _IOR('T', 0x40, int)\n#endif\n#ifndef TIOCGPTPEER\n#define TIOCGPTPEER _IO('T', 0x41)\n#endif\n\nstruct rr_input_mask {\n  uint32_t type;\n  uint32_t codes_size;\n  uint64_t codes_ptr;\n};\n\n#ifndef EVIOCGMASK\n#define EVIOCGMASK _IOR('E', 0x92, struct rr_input_mask)\n#endif\n\n#ifndef MADV_FREE\n#define MADV_FREE 8\n#endif\n#ifndef MADV_DONTDUMP\n#define MADV_DONTDUMP 16\n#endif\n#ifndef MADV_DODUMP\n#define MADV_DODUMP 17\n#endif\n#ifndef MADV_WIPEONFORK\n#define MADV_WIPEONFORK 18\n#endif\n#ifndef MADV_KEEPONFORK\n#define MADV_KEEPONFORK 19\n#endif\n#ifndef MADV_SOFT_OFFLINE\n#define MADV_SOFT_OFFLINE 101\n#endif\n#ifndef MADV_COLD\n#define MADV_COLD 20\n#endif\n#ifndef MADV_PAGEOUT\n#define MADV_PAGEOUT 21\n#endif\n#ifndef MADV_POPULATE_READ\n#define MADV_POPULATE_READ 22\n#endif\n#ifndef MADV_POPULATE_WRITE\n#define MADV_POPULATE_WRITE 23\n#endif\n#ifndef MADV_DONTNEED_LOCKED\n#define MADV_DONTNEED_LOCKED 24\n#endif\n#ifndef MADV_COLLAPSE\n#define MADV_COLLAPSE 25\n#endif\n#ifndef MADV_GUARD_INSTALL\n#define MADV_GUARD_INSTALL 102\n#endif\n#ifndef MADV_GUARD_REMOVE\n#define MADV_GUARD_REMOVE 103\n#endif\n\n#ifndef BUS_MCEERR_AR\n#define BUS_MCEERR_AR 4\n#endif\n\n#ifndef BUS_MCEERR_AO\n#define BUS_MCEERR_AO 5\n#endif\n\n// Defined in the ip_tables header for each protocol, but always to the same,\n// value, so it should be fine to set this here\n#ifndef IPT_SO_SET_REPLACE\n#define IPT_SO_SET_REPLACE 64\n#endif\n#ifndef IPV6T_SO_SET_REPLACE\n#define IPV6T_SO_SET_REPLACE 64\n#endif\n\n#ifndef HCIGETDEVLIST\n#define HCIGETDEVLIST _IOR('H', 210, int)\n#endif\n#ifndef HCIGETDEVINFO\n#define HCIGETDEVINFO _IOR('H', 211, int)\n#endif\n\n// Unfortunately the header that defines these is not C++ safe, we we'll\n// have to redefine them here\n#ifndef KEYCTL_GET_KEYRING_ID\n#define KEYCTL_GET_KEYRING_ID 0\n#endif\n#ifndef KEYCTL_JOIN_SESSION_KEYRING\n#define KEYCTL_JOIN_SESSION_KEYRING 1\n#endif\n#ifndef KEYCTL_UPDATE\n#define KEYCTL_UPDATE 2\n#endif\n#ifndef KEYCTL_REVOKE\n#define KEYCTL_REVOKE 3\n#endif\n#ifndef KEYCTL_CHOWN\n#define KEYCTL_CHOWN 4\n#endif\n#ifndef KEYCTL_SETPERM\n#define KEYCTL_SETPERM 5\n#endif\n#ifndef KEYCTL_DESCRIBE\n#define KEYCTL_DESCRIBE 6\n#endif\n#ifndef KEYCTL_CLEAR\n#define KEYCTL_CLEAR 7\n#endif\n#ifndef KEYCTL_LINK\n#define KEYCTL_LINK 8\n#endif\n#ifndef KEYCTL_UNLINK\n#define KEYCTL_UNLINK 9\n#endif\n#ifndef KEYCTL_SEARCH\n#define KEYCTL_SEARCH 10\n#endif\n#ifndef KEYCTL_READ\n#define KEYCTL_READ 11\n#endif\n#ifndef KEYCTL_INSTANTIATE\n#define KEYCTL_INSTANTIATE 12\n#endif\n#ifndef KEYCTL_NEGATE\n#define KEYCTL_NEGATE 13\n#endif\n#ifndef KEYCTL_SET_REQKEY_KEYRING\n#define KEYCTL_SET_REQKEY_KEYRING 14\n#endif\n#ifndef KEYCTL_SET_TIMEOUT\n#define KEYCTL_SET_TIMEOUT 15\n#endif\n#ifndef KEYCTL_ASSUME_AUTHORITY\n#define KEYCTL_ASSUME_AUTHORITY 16\n#endif\n#ifndef KEYCTL_GET_SECURITY\n#define KEYCTL_GET_SECURITY 17\n#endif\n#ifndef KEYCTL_SESSION_TO_PARENT\n#define KEYCTL_SESSION_TO_PARENT 18\n#endif\n#ifndef KEYCTL_REJECT\n#define KEYCTL_REJECT 19\n#endif\n#ifndef KEYCTL_INSTANTIATE_IOV\n#define KEYCTL_INSTANTIATE_IOV 20\n#endif\n#ifndef KEYCTL_INVALIDATE\n#define KEYCTL_INVALIDATE 21\n#endif\n#ifndef KEYCTL_GET_PERSISTENT\n#define KEYCTL_GET_PERSISTENT 22\n#endif\n#ifndef KEYCTL_DH_COMPUTE\n#define KEYCTL_DH_COMPUTE 23\n#endif\n\n#ifndef PR_CAP_AMBIENT\n#define PR_CAP_AMBIENT 47\n#endif\n#ifndef PR_CAP_AMBIENT_CLEAR_ALL\n#define PR_CAP_AMBIENT_CLEAR_ALL 4\n#endif\n\n// New in the 3.17 kernel.\n#ifndef VIDIOC_QUERY_EXT_CTRL\n/* This definition omits the size because in prepare_ioctl\n   it is masked away anyway. And the real size is taken from\n   the real request by _IOC_SIZE(request). */\n#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, 0)\n#endif\n\n// New in the 4.6 kernel.\n#ifndef CLONE_NEWCGROUP\n#define CLONE_NEWCGROUP 0x02000000\n#endif\n\n// These are only defined on x86. For simplicity, we defined\n// them here for all architectures.\n#ifndef ARCH_SET_GS\n#define ARCH_SET_GS 0x1001\n#endif\n#ifndef ARCH_SET_FS\n#define ARCH_SET_FS 0x1002\n#endif\n#ifndef ARCH_GET_FS\n#define ARCH_GET_FS 0x1003\n#endif\n#ifndef ARCH_GET_GS\n#define ARCH_GET_GS 0x1004\n#endif\n\n// New in the 4.12 kernel\n#ifndef ARCH_GET_CPUID\n#define ARCH_GET_CPUID 0x1011\n#endif\n#ifndef ARCH_SET_CPUID\n#define ARCH_SET_CPUID 0x1012\n#endif\n\n// New in the 4.15 kernel\n#ifndef MAP_SYNC\n#define MAP_SYNC  0x80000\n#endif\n#ifndef MAP_FIXED_NOREPLACE\n#define MAP_FIXED_NOREPLACE 0x100000\n#endif\n\nenum {\n  RR_BPF_MAP_CREATE,\n  RR_BPF_MAP_LOOKUP_ELEM,\n  RR_BPF_MAP_UPDATE_ELEM,\n  RR_BPF_MAP_DELETE_ELEM,\n  RR_BPF_MAP_GET_NEXT_KEY,\n  RR_BPF_PROG_LOAD,\n  RR_BPF_OBJ_PIN,\n  RR_BPF_OBJ_GET,\n  RR_BPF_PROG_ATTACH,\n  RR_BPF_PROG_DETACH,\n  RR_BPF_PROG_TEST_RUN,\n  RR_BPF_PROG_GET_NEXT_ID,\n  RR_BPF_MAP_GET_NEXT_ID,\n  RR_BPF_PROG_GET_FD_BY_ID,\n  RR_BPF_MAP_GET_FD_BY_ID,\n  RR_BPF_OBJ_GET_INFO_BY_FD,\n  RR_BPF_PROG_QUERY,\n  RR_BPF_RAW_TRACEPOINT_OPEN,\n  RR_BPF_BTF_LOAD,\n  RR_BPF_BTF_GET_FD_BY_ID,\n  RR_BPF_TASK_FD_QUERY,\n  RR_BPF_MAP_LOOKUP_AND_DELETE_ELEM,\n  RR_BPF_MAP_FREEZE,\n  RR_BPF_BTF_GET_NEXT_ID,\n  RR_BPF_MAP_LOOKUP_BATCH,\n  RR_BPF_MAP_LOOKUP_AND_DELETE_BATCH,\n  RR_BPF_MAP_UPDATE_BATCH,\n  RR_BPF_MAP_DELETE_BATCH,\n  RR_BPF_LINK_CREATE,\n  RR_BPF_LINK_UPDATE,\n  RR_BPF_LINK_GET_FD_BY_ID,\n  RR_BPF_LINK_GET_NEXT_ID,\n  RR_BPF_ENABLE_STATS,\n  RR_BPF_ITER_CREATE,\n  RR_BPF_LINK_DETACH,\n  RR_BPF_PROG_BIND_MAP,\n  RR_BPF_TOKEN_CREATE,\n};\n\n#ifndef O_PATH\n#define O_PATH 040000000\n#endif\n\n#ifndef MAX_HANDLE_SZ\n#define MAX_HANDLE_SZ 128\n#endif\n\n#ifndef P_PIDFD\n#define P_PIDFD 3\n#endif\n\n#ifndef CLONE_PIDFD\n#define CLONE_PIDFD 0x1000\n#endif\n\n#ifndef RLIMIT_RTTIME\n#define RLIMIT_RTTIME 15\n#endif\n\n#ifndef CAP_PERFMON\n#define CAP_PERFMON 38\n#endif\n\n#ifndef SEGV_PKUERR\n#define SEGV_PKUERR 4\n#endif\n\n#define RR_RSEQ_FLAG_UNREGISTER (1 << 0)\n#define RR_RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT 0\n#define RR_RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT 1\n#define RR_RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT 2\n#define RR_RSEQ_CPU_ID_UNINITIALIZED -1\n\n// New in the 4.20 kernel\n#ifndef BLKGETZONESZ\n#define BLKGETZONESZ _IOR(0x12, 132, __u32)\n#endif\n#ifndef BLKGETNRZONES\n#define BLKGETNRZONES _IOR(0x12, 133, __u32)\n#endif\n\n// New in the 5.4 kernel\n#ifndef PR_SET_TAGGED_ADDR_CTRL\n#define PR_SET_TAGGED_ADDR_CTRL 55\n#endif\n#ifndef PR_GET_TAGGED_ADDR_CTRL\n#define PR_GET_TAGGED_ADDR_CTRL 56\n#endif\n#ifndef PR_TAGGED_ADDR_ENABLE\n#define PR_TAGGED_ADDR_ENABLE (1 << 0)\n#endif\n\n// New in the 5.5 kernel\n#ifndef BLKOPENZONE\n#define BLKOPENZONE _IOW(0x12, 134, struct blk_zone_range)\n#endif\n#ifndef BLKCLOSEZONE\n#define BLKCLOSEZONE _IOW(0x12, 135, struct blk_zone_range)\n#endif\n#ifndef BLKFINISHZONE\n#define BLKFINISHZONE _IOW(0x12, 136, struct blk_zone_range)\n#endif\n\n// New in the 5.7 kernel\n#ifndef MREMAP_DONTUNMAP\n#define MREMAP_DONTUNMAP 4\n#endif\n\n// New in the 5.13 kernel\n#ifndef OTPERASE\n#define OTPERASE _IOW('M', 25, struct otp_info)\n#endif\n\n// New in the 5.15 kernel\n#ifndef BLKGETDISKSEQ\n#define BLKGETDISKSEQ _IOR(0x12,128,__u64)\n#endif\n\n// New in the 5.17 kernel\n#ifndef PR_SET_VMA\n#define PR_SET_VMA 0x53564d41\n#endif\n#ifndef PR_SET_VMA_ANON_NAME\n#define PR_SET_VMA_ANON_NAME 0\n#endif\n\n// New in the 6.1 kernel\n#ifndef MEMREAD\n#define MEMREAD _IOWR('M', 26, typename Arch::mtd_read_req)\n#endif\n\n// New in the 6.3 kernel\n#ifndef PR_GET_MDWE\n#define PR_GET_MDWE 66\n#endif\n\n// New in the 6.4 kernel\n#ifndef PR_GET_AUXV\n#define PR_GET_AUXV 0x41555856\n#endif\n\n// Technically not \"kernel\" constants, exactly, since these are defined\n// in libc, but required for compat with older libcs like the rest of\n// this file.\n#ifndef SHF_COMPRESSED\n#define SHF_COMPRESSED (1 << 11)\n#endif\n\n#ifndef ELFCOMPRESS_ZLIB\n#define ELFCOMPRESS_ZLIB 1\n#endif\n#ifndef ELFCOMPRESS_ZSTD\n#define ELFCOMPRESS_ZSTD 2\n#endif\n\n// O_LARGEFILE is defined to 0 for 64-bit builds. We need to know the\n// value that is used for 32-bit processes.\n#define RR_LARGEFILE_32 0x8000\n\n#ifndef ARCH_GET_XCOMP_SUPP\n#define ARCH_GET_XCOMP_SUPP 0x1021\n#endif\n#ifndef ARCH_GET_XCOMP_PERM\n#define ARCH_GET_XCOMP_PERM 0x1022\n#endif\n#ifndef ARCH_REQ_XCOMP_PERM\n#define ARCH_REQ_XCOMP_PERM 0x1023\n#endif\n\n#ifndef DMA_BUF_IOCTL_EXPORT_SYNC_FILE\n#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)\nstruct dma_buf_export_sync_file {\n  uint32_t flags;\n  int32_t fd;\n};\n#endif\n\n#ifndef RENAME_NOREPLACE\n#define RENAME_NOREPLACE 1\n#endif\n\n#ifndef ZFS_SUPER_MAGIC\n#define ZFS_SUPER_MAGIC 0x2fc12fc1\n#endif\n\n} // namespace rr\n\n// We can't include libc's ptrace.h, so declare this here.\nextern \"C\" long int ptrace (enum rr::_ptrace_request _request, ...);\n\n#endif /* RR_KERNEL_SUPPLEMENT_H_ */\n"
  },
  {
    "path": "src/launch_debugger.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <stdio.h>\n#include <stdlib.h>\n#include <unistd.h>\n#include <sys/socket.h>\n#include <sys/syscall.h>\n\n#include <limits.h>\n#include <memory>\n#include <sstream>\n#include <string>\n\n#include \"launch_debugger.h\"\n\n#include \"DebuggerExtensionCommandHandler.h\"\n#include \"GdbServer.h\"\n#include \"GdbServerConnection.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"StringVectorToCharArray.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n// Special-sauce macros defined by rr when launching the gdb client,\n// which implement functionality outside of the gdb remote protocol.\n// (Don't stare at them too long or you'll go blind ;).)\nstatic string gdb_rr_macros(const string* file_to_delete) {\n  stringstream ss;\n  ss << DebuggerExtensionCommandHandler::gdb_macros()\n     // gdb warns about redefining inbuilt commands, silence that by\n     // wrapping it in python code\n     << \"python gdb.execute('define jump\\\\nrr-denied jump\\\\nend')\\n\"\n     << \"python gdb.execute('define restart\\\\nrun c$arg0\\\\nend')\\n\"\n     << \"document restart\\n\"\n     << \"restart at checkpoint N\\n\"\n     << \"checkpoints are created with the 'checkpoint' command\\n\"\n     << \"end\\n\"\n     << \"define seek-ticks\\n\"\n     << \"  run t$arg0\\n\"\n     << \"end\\n\"\n     << \"document seek-ticks\\n\"\n     << \"restart at given ticks value\\n\"\n     << \"end\\n\"\n     // In gdb version \"Fedora 7.8.1-30.fc21\", a raw \"run\" command\n     // issued before any user-generated resume-execution command\n     // results in gdb hanging just after the inferior hits an internal\n     // gdb breakpoint.  This happens outside of rr, with gdb\n     // controlling gdbserver, as well.  We work around that by\n     // ensuring *some* resume-execution command has been issued before\n     // restarting the session.  But, only if the inferior hasn't\n     // already finished execution ($_thread != 0).  If it has and we\n     // issue the \"stepi\" command, then gdb refuses to restart\n     // execution.\n     << \"define hook-run\\n\"\n     << \"  rr-hook-run\\n\"\n     << \"end\\n\"\n     << \"define hookpost-continue\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-step\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-stepi\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-next\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-nexti\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-finish\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-reverse-continue\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-reverse-step\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-reverse-stepi\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-reverse-finish\\n\"\n     << \"  rr-set-suppress-run-hook 1\\n\"\n     << \"end\\n\"\n     << \"define hookpost-run\\n\"\n     << \"  rr-set-suppress-run-hook 0\\n\"\n     << \"end\\n\"\n     << \"set unwindonsignal on\\n\"\n     << \"set non-stop off\\n\"\n     << \"handle SIGURG stop\\n\"\n     << \"set prompt (rr) \\n\"\n     // Try both \"set target-async\" and \"maint set target-async\" since\n     // that changed recently.\n     << \"python\\n\"\n     << \"import re\\n\"\n     << \"import os\\n\"\n     << \"m = re.compile(r\"\n     << \"'[^0-9]*([0-9]+)\\\\.([0-9]+)(\\\\.([0-9]+))?'\"\n     << \").match(gdb.VERSION)\\n\"\n     << \"ver = int(m.group(1))*10000 + int(m.group(2))*100\\n\"\n     << \"if m.group(4):\\n\"\n     << \"    ver = ver + int(m.group(4))\\n\"\n     << \"\\n\"\n     << \"if ver == 71100:\\n\"\n     << \"    gdb.write(\"\n     << \"'This version of gdb (7.11.0) has known bugs that break rr. \"\n     << \"Install 7.11.1 or later.\\\\n', gdb.STDERR)\\n\"\n     << \"\\n\"\n     << \"if ver < 71101:\\n\"\n     << \"    gdb.execute('set target-async 0')\\n\"\n     << \"    gdb.execute('maint set target-async 0')\\n\";\n  if (file_to_delete) {\n    ss << \"os.unlink('\" << *file_to_delete << \"')\\n\";\n  }\n  ss << \"end\\n\";\n  return ss.str();\n}\n\nstatic const string& lldb_python_rr_macros(\n    const string* file_to_delete, const string* module_name) {\n  static string s;\n\n  if (s.empty()) {\n    auto cmds = DebuggerExtensionCommandHandler::lldb_python_macros(\n        module_name);\n    stringstream ss;\n    ss << cmds.toplevel_definitions\n       << \"import os\\n\"\n       << \"def  __lldb_init_module(debugger, internal_dict):\\n\"\n       << cmds.run_on_startup\n       << \"    debugger.HandleCommand('set set prompt \\\"(rr) \\\"')\\n\";\n    if (file_to_delete) {\n      ss << \"    os.unlink('\" << *file_to_delete << \"')\\n\";\n    }\n    ss << \"\\n\";\n    s = ss.str();\n  }\n  return s;\n}\n\nstatic void push_default_gdb_options(vector<string>& vec, bool serve_files) {\n  // The gdb protocol uses the \"vRun\" packet to reload\n  // remote targets.  The packet is specified to be like\n  // \"vCont\", in which gdb waits infinitely long for a\n  // stop reply packet.  But in practice, gdb client\n  // expects the vRun to complete within the remote-reply\n  // timeout, after which it issues vCont.  The timeout\n  // causes gdb<-->rr communication to go haywire.\n  //\n  // rr can take a very long time indeed to send the\n  // stop-reply to gdb after restarting replay; the time\n  // to reach a specified execution target is\n  // theoretically unbounded.  Timing out on vRun is\n  // technically a gdb bug, but because the rr replay and\n  // the gdb reload models don't quite match up, we'll\n  // work around it on the rr side by disabling the\n  // remote-reply timeout.\n  vec.push_back(\"-l\");\n  vec.push_back(\"10000\");\n  if (!serve_files) {\n    // For now, avoid requesting binary files through vFile. That is slow and\n    // hard to make work correctly, because gdb requests files based on the\n    // names it sees in memory and in ELF, and those names may be symlinks to\n    // the filenames in the trace, so it's hard to match those names to files in\n    // the trace.\n    vec.push_back(\"-ex\");\n    vec.push_back(\"set sysroot /\");\n  }\n}\n\nstatic void push_gdb_target_remote_cmd(vector<string>& vec, int socket_domain,\n                                       const string& host,\n                                       unsigned short port) {\n  vec.push_back(\"-ex\");\n  stringstream ss;\n  switch (socket_domain) {\n    case AF_INET:\n      // If we omit the address, then gdb can try to resolve \"localhost\" which\n      // in some broken environments may not actually resolve to the local host\n      ss << \"target extended-remote \" << host << \":\" << port;\n      break;\n    case AF_INET6:\n      ss << \"target extended-remote tcp6:[\" << host << \"]:\" << port;\n      break;\n    default:\n      FATAL() << \"Unknown socket domain \" << socket_domain;\n      break;\n  }\n  vec.push_back(ss.str());\n}\n\nstatic void push_lldb_target_remote_cmd(vector<string>& vec, int socket_domain,\n                                        const string& host,\n                                        unsigned short port) {\n  vec.push_back(\"-o\");\n  stringstream ss;\n  switch (socket_domain) {\n    case AF_INET:\n    case AF_INET6:\n      ss << \"gdb-remote [\" << host << \"]:\" << port;\n      break;\n    default:\n      FATAL() << \"Unknown socket domain \" << socket_domain;\n      break;\n  }\n  vec.push_back(ss.str());\n}\n\nstring saved_debugger_launch_command;\n\nvector<string> debugger_launch_command(Task* t, int socket_domain,\n                                       const string& host,\n                                       unsigned short port,\n                                       bool serve_files,\n                                       const string& debugger_name,\n                                       DebuggerType debugger_type) {\n  vector<string> cmd;\n  cmd.push_back(debugger_name);\n  switch (debugger_type) {\n    case DebuggerType::GDB:\n      push_default_gdb_options(cmd, serve_files);\n      push_gdb_target_remote_cmd(cmd, socket_domain, host, port);\n      break;\n    case DebuggerType::LLDB:\n      cmd.push_back(\"--source-quietly\");\n      push_lldb_target_remote_cmd(cmd, socket_domain, host, port);\n      break;\n    default:\n      FATAL() << \"Unknown debugger type\";\n      break;\n  }\n  cmd.push_back(t->vm()->exe_image());\n  saved_debugger_launch_command = to_shell_string(cmd);\n  return cmd;\n}\n\nstring to_shell_string(const vector<string>& args) {\n  stringstream ss;\n  for (auto& a : args) {\n    ss << \"'\" << a << \"' \";\n  }\n  return ss.str();\n}\n\nstatic bool needs_target(const string& option) {\n  return !strncmp(option.c_str(), \"continue\", option.size());\n}\n\n/**\n * Exec the debuger using the params that were written to\n * `params_pipe_fd`.\n */\nvoid launch_debugger(ScopedFd& params_pipe_fd,\n                     const string& debugger_file_path,\n                     DebuggerType debugger_type,\n                     const vector<string>& options,\n                     bool serve_files) {\n  DebuggerParams params;\n  ssize_t nread;\n  while (true) {\n    nread = read(params_pipe_fd, &params, sizeof(params));\n    if (nread == 0) {\n      // pipe was closed. Probably rr failed/died.\n      return;\n    }\n    if (nread != -1 || errno != EINTR) {\n      break;\n    }\n  }\n  DEBUG_ASSERT(nread == sizeof(params));\n\n  const string& host(params.host);\n  int socket_domain(params.socket_domain);\n  uint16_t port(params.port);\n\n  vector<string> cmd;\n  cmd.push_back(debugger_file_path);\n  vector<string> env = current_env();\n\n  // LLDB 'command script import' requires the filename to be a valid Python\n  // identifier.\n  TempFile file = create_temporary_file(\"rr_debugger_commands_XXXXXX\");\n  switch (debugger_type) {\n    case DebuggerType::GDB: {\n      push_default_gdb_options(cmd, serve_files);\n      string script = gdb_rr_macros(&file.name);\n      write_all(file.fd, script.data(), script.size());\n      cmd.push_back(\"-x\");\n      cmd.push_back(file.name);\n\n      bool did_set_remote = false;\n      for (size_t i = 0; i < options.size(); ++i) {\n        if (!did_set_remote && options[i] == \"-ex\" &&\n            i + 1 < options.size() && needs_target(options[i + 1])) {\n          push_gdb_target_remote_cmd(cmd, socket_domain, host, port);\n          did_set_remote = true;\n        }\n        cmd.push_back(options[i]);\n      }\n      if (!did_set_remote) {\n        push_gdb_target_remote_cmd(cmd, socket_domain, host, port);\n      }\n\n      env.push_back(\"GDB_UNDER_RR=1\");\n      break;\n    }\n    case DebuggerType::LLDB: {\n      cmd.push_back(\"--source-quietly\");\n      cmd.insert(cmd.end(), options.begin(), options.end());\n      push_lldb_target_remote_cmd(cmd, socket_domain, host, port);\n      // LLDB 'command script import' requires the file to end in '.py'.\n      string new_name = file.name + \".py\";\n      if (::syscall(SYS_renameat2, AT_FDCWD, file.name.c_str(), AT_FDCWD, new_name.c_str(),\n                    RENAME_NOREPLACE)) {\n        FATAL() << \"Can't fix temp file name\";\n      }\n      string module_name(basename(file.name.c_str()));\n      string script = lldb_python_rr_macros(&new_name, &module_name);\n      write_all(file.fd, script.data(), script.size());\n      cmd.push_back(\"-o\");\n      cmd.push_back(\"command script import \" + new_name);\n      env.push_back(\"LLDB_UNDER_RR=1\");\n      break;\n    }\n    default:\n      FATAL() << \"Unknown debugger type\";\n      break;\n  }\n\n  cmd.push_back(params.exe_image);\n\n  LOG(debug) << \"launching \" << to_shell_string(cmd);\n\n  StringVectorToCharArray c_args(cmd);\n  StringVectorToCharArray c_env(env);\n  execvpe(debugger_file_path.c_str(), c_args.get(), c_env.get());\n  CLEAN_FATAL() << \"Failed to exec \" << debugger_file_path << \".\";\n}\n\nvoid emergency_debug(Task* t) {\n  // See the comment in |guard_overshoot()| explaining why we do\n  // this.  Unlike in that context though, we don't know if |t|\n  // overshot an internal breakpoint.  If it did, cover that\n  // breakpoint up.\n  if (t->vm()) {\n    t->vm()->remove_all_breakpoints();\n  }\n\n  // Don't launch a debugger on fatal errors; the user is most\n  // likely already in a debugger, and wouldn't be able to\n  // control another session. Instead, launch a new GdbServer and wait for\n  // the user to connect from another window.\n  GdbServerConnection::Features features;\n  // Don't advertise reverse_execution to gdb because a) it won't work and\n  // b) some gdb versions will fail if the user doesn't turn off async\n  // mode (and we don't want to require users to do that)\n  features.reverse_execution = false;\n  OpenedSocket listen_socket = open_socket(string(), t->tid, PROBE_PORT);\n\n  {\n    ScopedFd fd(STDERR_FILENO);\n    dump_rr_stack(fd);\n    fd.extract();\n  }\n\n  char* test_monitor_pid = getenv(\"RUNNING_UNDER_TEST_MONITOR\");\n  if (test_monitor_pid) {\n    pid_t pid = atoi(test_monitor_pid);\n    // Tell test-monitor to wake up and take a snapshot. It will also\n    // connect the emergency debugger so let that happen.\n    FILE* gdb_cmd = fopen(\"gdb_cmd\", \"w\");\n    if (gdb_cmd) {\n      fputs(to_shell_string(\n          debugger_launch_command(t, listen_socket.domain,\n              listen_socket.host, listen_socket.port, false, \"gdb\",\n              DebuggerType::GDB)).c_str(), gdb_cmd);\n      fclose(gdb_cmd);\n    }\n    kill(pid, SIGURG);\n  } else {\n    vector<string> cmd = debugger_launch_command(t,\n        listen_socket.domain, listen_socket.host, listen_socket.port,\n        false, \"gdb\", DebuggerType::GDB);\n    fprintf(stderr, \"Launch debugger with\\n  %s\\n\", to_shell_string(cmd).c_str());\n  }\n  unique_ptr<GdbServerConnection> dbg =\n      GdbServerConnection::await_connection(t, listen_socket.fd, DebuggerType::GDB, features);\n  GdbServer::serve_emergency_debugger(std::move(dbg), t);\n}\n\nstring gdb_init_script() { return gdb_rr_macros(nullptr); }\n\nstring lldb_init_script() { return lldb_python_rr_macros(nullptr, nullptr); }\n\n} // namespace rr\n"
  },
  {
    "path": "src/launch_debugger.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_LAUNCH_DEBUGGER_H_\n#define RR_LAUNCH_DEBUGGER_H_\n\n#include <limits.h>\n\n#include <string>\n#include <vector>\n\n#include \"ScopedFd.h\"\n#include \"Task.h\"\n\nnamespace rr {\n\n// Controls the command-line arguments and command syntax we'll use\n// to control the debugger.\nenum class DebuggerType {\n  // GDB and compatible debuggers\n  GDB,\n  // LLDB and compatible debuggers\n  LLDB,\n};\n\nstruct DebuggerParams {\n  char exe_image[PATH_MAX];\n  int socket_domain;\n  char host[128];\n  short port;\n};\n\n/**\n * exec()'s the debuger using parameters read from params_pipe_fd.\n */\nvoid launch_debugger(ScopedFd& params_pipe_fd, const std::string& debugger_file_path,\n                     DebuggerType debugger_type, const std::vector<std::string>& options,\n                     bool serve_files);\n\n/**\n * Produces the command line needed to launch the debugger.\n */\nstd::vector<std::string> debugger_launch_command(Task* t, int socket_domain,\n                                                 const std::string& host,\n                                                 unsigned short port,\n                                                 bool serve_files,\n                                                 const std::string& debugger_name,\n                                                 DebuggerType debugger_type);\n\n/**\n * Convert the command line to a string containing quoted parameters.\n */\nstd::string to_shell_string(const std::vector<std::string>& args);\n\n/**\n * Start a debugging connection for |t| and return when there are no\n * more requests to process (usually because the debugger detaches).\n *\n * This helper doesn't attempt to determine whether blocking rr on a\n * debugger connection might be a bad idea.  It will always open the debug\n * socket and block awaiting a connection.\n */\nvoid emergency_debug(Task* t);\n\n/**\n * A string containing the default gdbinit script that we load into gdb.\n */\nstd::string gdb_init_script();\n\n/**\n * A string containing the default lldbinit script that we load into lldb.\n */\nstd::string lldb_init_script();\n\n} // namespace rr\n\n#endif /* RR_LAUNCH_DEBUGGER_H_ */\n"
  },
  {
    "path": "src/log.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"log.h\"\n\n#include <stdlib.h>\n#include <string.h>\n\n#include <deque>\n#include <fstream>\n#include <memory>\n#include <sstream>\n#include <unordered_map>\n\n#include \"DumpCommand.h\"\n#include \"Flags.h\"\n#include \"GdbServerConnection.h\"\n#include \"GdbServer.h\"\n#include \"RecordSession.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"core.h\"\n#include \"ftrace.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"launch_debugger.h\"\n#include \"processor_trace_check.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nostream& operator<<(ostream& stream, const siginfo_t& siginfo) {\n  stream << \"{signo:\" << rr::signal_name(siginfo.si_signo)\n         << \",errno:\" << rr::errno_name(siginfo.si_errno)\n         << \",code:\" << rr::sicode_name(siginfo.si_code, siginfo.si_signo);\n  bool show_pid = false;\n  switch (siginfo.si_signo) {\n    case SIGILL:\n    case SIGFPE:\n    case SIGSEGV:\n    case SIGBUS:\n    case SIGTRAP:\n      stream << \",addr:\" << siginfo.si_addr;\n      break;\n    case SIGCHLD:\n      show_pid = true;\n      break;\n    default:\n      break;\n  }\n  switch (siginfo.si_code) {\n    case SI_USER:\n    case SI_QUEUE:\n    case SI_TKILL:\n      show_pid = true;\n      break;\n    default:\n      break;\n  }\n  if (show_pid) {\n    stream << \",pid:\" << siginfo.si_pid;\n  }\n  stream << \"}\";\n  return stream;\n}\n\nnamespace rr {\n\nstruct LogModule {\n  string name;\n  LogLevel level;\n};\n\nstatic LogLevel to_log_level(const string& str) {\n  if (str == \"debug\") {\n    return LOG_debug;\n  }\n  if (str == \"info\") {\n    return LOG_info;\n  }\n  if (str == \"warn\") {\n    return LOG_warn;\n  }\n  if (str == \"error\") {\n    return LOG_error;\n  }\n  if (str == \"fatal\") {\n    return LOG_fatal;\n  }\n  fprintf(stderr, \"Log level %s in RR_LOG is not valid, assuming 'fatal'\\n\",\n          str.c_str());\n  return LOG_fatal;\n}\n\nstatic char simple_to_lower(char ch) {\n  // to_lower sucks because it's locale-dependent\n  if (ch >= 'A' && ch <= 'Z') {\n    return ch + 'a' - 'A';\n  }\n  return ch;\n}\n\nstatic string simple_to_lower(const string& s) {\n  std::unique_ptr<char[]> buf(new char[s.size() + 1]);\n  for (size_t i = 0; i < s.size(); ++i) {\n    buf[i] = simple_to_lower(s[i]);\n  }\n  buf[s.size()] = 0;\n  return string(buf.get());\n}\n\n#if __has_attribute(require_constant_initialization)\n#define _CONSTANT_STATIC                                                       \\\n  __attribute__((__require_constant_initialization__)) static\n#else\n#define _CONSTANT_STATIC static\n#endif\n\nstatic bool log_globals_initialized = false;\nstatic LogLevel default_level = LOG_error;\n\n// These need to be available to other static constructors, so we need to be\n// sure that they can be constant-initialized. Unfortunately some versions of\n// C++ libraries have a bug that causes them not to be. _CONSTANT_STATIC should\n// turn this into a compile error rather than a runtime crash for compilers\n// that support the attribute.\n\n// This is the assignment of log levels to module names.\n// Any module name not mentioned here gets the default_log_level.\n_CONSTANT_STATIC unique_ptr<unordered_map<string, LogLevel>> level_map;\n// This is a cache mapping unlimited-lifetime file name pointers (usually\n// derived from __FILE__) to the associated module name and log level.\n// It's OK for this to contain multiple entries for the same string but\n// with different pointers.\n_CONSTANT_STATIC unique_ptr<unordered_map<const void*, LogModule>> log_modules;\n// This collects a single log message.\n_CONSTANT_STATIC unique_ptr<stringstream> logging_stream;\n// When non-null, log messages are accumulated into this buffer.\n_CONSTANT_STATIC unique_ptr<deque<char>> log_buffer;\n// When non-null, log messages are flushed to this file.\n_CONSTANT_STATIC ostream* log_file;\n// Maximum size of `log_buffer`.\nsize_t log_buffer_size;\n\nstatic void flush_log_file() { log_file->flush(); }\n\nstatic void init_log_globals();\n\nvoid apply_log_spec(const char *spec) {\n  init_log_globals();\n  char *env = strdup(spec);\n  DEBUG_ASSERT(env);\n  for (int i = 0; env[i]; ++i) {\n    env[i] = simple_to_lower(env[i]);\n  }\n  char* p = env;\n  while (*p) {\n    char* end = strchrnul(p, ',');\n    char* sep = strchrnul(p, ':');\n    string n;\n    LogLevel level;\n    if (sep >= end) {\n      n = string(p, end - p);\n      level = LOG_debug;\n    } else {\n      n = string(p, sep - p);\n      if (sep + 1 == end) {\n        level = LOG_fatal;\n      } else {\n        level = to_log_level(string(sep + 1, end - (sep + 1)));\n      }\n    }\n    if (n == \"\" || n == \"all\") {\n      level_map->clear();\n      default_level = level;\n    } else {\n      (*level_map)[n] = level;\n    }\n    if (*end) {\n      p = end + 1;\n    } else {\n      p = end;\n    }\n  }\n  free(env);\n  log_modules->clear();\n}\n\nvoid apply_log_spec_from_env() {\n  const char* log_env = \"RR_LOG\";\n  if (running_under_rr()) {\n    log_env = \"RR_UNDER_RR_LOG\";\n  }\n  char* env = getenv(log_env);\n  if (env) {\n    apply_log_spec(env);\n  }\n}\n\nstatic void init_log_globals() {\n  if (log_globals_initialized) {\n    return;\n  }\n  log_globals_initialized = true;\n  level_map = unique_ptr<unordered_map<string, LogLevel>>(\n      new unordered_map<string, LogLevel>());\n  log_modules = unique_ptr<unordered_map<const void*, LogModule>>(\n      new unordered_map<const void*, LogModule>());\n  logging_stream = unique_ptr<stringstream>(new stringstream());\n\n  const char* buffer = getenv(\"RR_LOG_BUFFER\");\n  if (buffer) {\n    log_buffer_size = atoi(buffer);\n    if (log_buffer_size) {\n      log_buffer = unique_ptr<deque<char>>(new deque<char>());\n    }\n  }\n\n  const char* filename = getenv(\"RR_LOG_FILE\");\n  ios_base::openmode log_file_open_mode = std::ofstream::out;\n  if (!filename) {\n    filename = getenv(\"RR_APPEND_LOG_FILE\");\n    log_file_open_mode |= std::ofstream::app;\n  }\n  if (filename) {\n    auto file = new ofstream(filename, log_file_open_mode);\n    if (!file->good()) {\n      delete file;\n    } else {\n      log_file = file;\n      atexit(flush_log_file);\n    }\n  }\n\n  if (!log_file) {\n    log_file = &cerr;\n  }\n\n  apply_log_spec_from_env();\n}\n\nstatic LogLevel get_log_level(const string& name) {\n  init_log_globals();\n\n  auto it = level_map->find(simple_to_lower(name));\n  if (it == level_map->end()) {\n    return default_level;\n  }\n  return it->second;\n}\n\nstatic string file_to_name(const char* file) {\n  const char* base = strrchr(file, '/');\n  if (base) {\n    ++base;\n  } else {\n    base = file;\n  }\n  const char* dot = strrchr(base, '.');\n  string r;\n  if (dot) {\n    r = string(base, dot - base);\n  } else {\n    r = string(base);\n  }\n  return r;\n}\n\nLogModule& get_log_module(const char* file) {\n  init_log_globals();\n\n  auto it = log_modules->find(file);\n  if (it != log_modules->end()) {\n    return it->second;\n  }\n  LogModule m;\n  m.name = file_to_name(file);\n  m.level = get_log_level(m.name);\n  (*log_modules)[file] = m;\n  return (*log_modules)[file];\n}\n\nvoid set_all_logging(LogLevel level) {\n  default_level = level;\n  level_map->clear();\n  log_modules->clear();\n}\n\nvoid set_logging(const char* name, LogLevel level) {\n  (*level_map)[simple_to_lower(name)] = level;\n  log_modules->clear();\n}\n\nstatic const char* log_name(LogLevel level) {\n  switch (level) {\n    case LOG_fatal:\n      return \"FATAL\";\n    case LOG_error:\n      return \"ERROR\";\n    case LOG_warn:\n      return \"WARN\";\n    case LOG_info:\n      return \"INFO\";\n    default:\n      return \"???\";\n  }\n}\n\nostream& log_stream() {\n  init_log_globals();\n  return *logging_stream;\n}\n\nstatic void flush_log_stream() {\n  string s = logging_stream->str();\n  ftrace::write(s);\n  if (log_buffer) {\n    size_t len = s.size();\n    if (len >= log_buffer_size) {\n      log_buffer->clear();\n      log_buffer->insert(log_buffer->end(), s.c_str() + (len - log_buffer_size),\n                         s.c_str() + len);\n    } else {\n      if (log_buffer->size() + len > log_buffer_size) {\n        log_buffer->erase(log_buffer->begin(),\n                          log_buffer->begin() +\n                              (log_buffer->size() + len - log_buffer_size));\n      }\n      log_buffer->insert(log_buffer->end(), s.c_str(), s.c_str() + len);\n    }\n  } else {\n    *log_file << s;\n  }\n\n  logging_stream->str(string());\n}\n\nvoid flush_log_buffer(unique_ptr<deque<char>> &this_log_buffer) {\n  if (this_log_buffer) {\n    for (char c : *this_log_buffer) {\n      // We could accumulate in a string to speed things up, but this could get\n      // called in low-memory situations so be safe.\n      *log_file << c;\n    }\n    this_log_buffer->clear();\n  }\n}\n\nvoid flush_log_buffer() {\n  flush_log_buffer(log_buffer);\n}\n\ntemplate <typename T>\nstatic void write_prefix(T& stream, LogLevel level, const char* file, int line,\n                         const char* function) {\n  int err = errno;\n  stream << \"[\" << log_name(level) << \" \";\n  if (level <= LOG_error) {\n    stream << file << \":\" << line << \":\";\n  }\n  stream << function << \"()\";\n  if (level <= LOG_warn && err) {\n    stream << \" errno: \" << errno_name(err);\n  }\n  stream << \"] \";\n}\n\nbool is_logging_enabled(LogLevel level, const char* file) {\n  LogModule& m = get_log_module(file);\n  return level <= m.level;\n}\n\nNewlineTerminatingOstream::NewlineTerminatingOstream(LogLevel level,\n                                                     const char* file, int line,\n                                                     const char* function)\n    : level(level) {\n  LogModule& m = get_log_module(file);\n  enabled = level <= m.level;\n  if (enabled) {\n    if (level == LOG_debug) {\n      *this << \"[\" << m.name << \"] \";\n    } else {\n      write_prefix(*this, level, file, line, function);\n    }\n  }\n}\n\nNewlineTerminatingOstream::NewlineTerminatingOstream(LogModule** m_ptr,\n                                                     LogLevel level,\n                                                     const char* file, int line,\n                                                     const char* function)\n    : level(level) {\n  if (!*m_ptr) {\n    *m_ptr = &get_log_module(file);\n  }\n  LogModule& m = **m_ptr;\n  enabled = level <= m.level;\n  if (enabled) {\n    if (level == LOG_debug) {\n      *this << \"[\" << m.name << \"] \";\n    } else {\n      write_prefix(*this, level, file, line, function);\n    }\n  }\n}\n\n// We try not to allocate in here.\nstatic void dump_stack_and_abort() {\n  int pipes[2];\n  int ret = pipe(pipes);\n  if (ret >= 0) {\n    // Default pipe size is 64K which should be enough\n    {\n      ScopedFd write_fd(pipes[1]);\n      dump_rr_stack(write_fd);\n    }\n    ScopedFd read_fd(pipes[0]);\n    while (true) {\n      char buf[1024];\n      ret = read(read_fd, buf, sizeof(buf) - 1);\n      if (ret <= 0) {\n        break;\n      }\n      log_stream().write(buf, ret);\n    }\n  }\n  flush_log_stream();\n  flush_log_file();\n  notifying_abort();\n}\n\nNewlineTerminatingOstream::~NewlineTerminatingOstream() {\n  if (enabled) {\n    log_stream() << endl;\n    if (Flags::get().fatal_errors_and_warnings && level <= LOG_warn) {\n      dump_stack_and_abort();\n    } else {\n      flush_log_stream();\n    }\n  }\n}\n\nCleanFatalOstream::CleanFatalOstream(const char* file, int line,\n                                     const char* function) {\n  errno = 0;\n  write_prefix(*this, LOG_fatal, file, line, function);\n}\n\nCleanFatalOstream::~CleanFatalOstream() {\n  cerr << endl;\n  flush_log_stream();\n  flush_log_buffer();\n  exit(1);\n}\n\nFatalOstream::FatalOstream(const char* file, int line, const char* function) {\n  write_prefix(*this, LOG_fatal, file, line, function);\n}\n\nFatalOstream::~FatalOstream() {\n  log_stream() << endl;\n  dump_stack_and_abort();\n}\n\nstatic const int LAST_EVENT_COUNT = 20;\n\nstatic void dump_last_events(const TraceStream& trace) {\n  fputs(\"Tail of trace dump:\\n\", stderr);\n\n  DumpFlags flags;\n  flags.dump_syscallbuf = true;\n  flags.dump_recorded_data_metadata = true;\n  flags.dump_mmaps = true;\n  FrameTime end = trace.time();\n  vector<string> specs;\n  char buf[100];\n  sprintf(buf, \"%lld-%lld\", (long long)(end - LAST_EVENT_COUNT), (long long)(end + 1));\n  specs.push_back(string(buf));\n  dump(trace.dir(), flags, specs, stderr);\n}\n\nstatic void start_emergency_debug(Task* t) {\n  ftrace::stop();\n\n  // Enable SIGINT in case it was disabled. Users want to be able to ctrl-C\n  // out of this.\n  struct sigaction sa;\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_handler = SIG_DFL;\n  sigaction(SIGINT, &sa, nullptr);\n\n  RecordSession* record_session = t->session().as_record();\n  if (record_session) {\n    record_session->close_trace_writer(TraceWriter::CLOSE_ERROR);\n  }\n  if (t->session().is_replaying()) {\n    emergency_check_intel_pt(static_cast<ReplayTask*>(t), log_stream());\n  }\n\n  // Capture the log buffer now to prevent the log messages from the trace\n  // stream read below from overwriting any data from the actual failure.\n  flush_log_stream();\n  std::unique_ptr<deque<char>> captured_log_buffer = std::move(log_buffer);\n\n  TraceStream* trace_stream = t->session().trace_stream();\n  if (trace_stream) {\n    dump_last_events(*trace_stream);\n  }\n\n  flush_log_buffer(captured_log_buffer);\n\n  if (probably_not_interactive() && !Flags::get().force_things &&\n      !getenv(\"RUNNING_UNDER_TEST_MONITOR\")) {\n    CLEAN_FATAL()\n        << \"(session doesn't look interactive, aborting emergency debugging)\";\n  }\n  if (!t->thread_group()) {\n    CLEAN_FATAL() << \"(task is in a bad state, aborting emergency debugging)\";\n  }\n\n  emergency_debug(t);\n  CLEAN_FATAL() << \"Can't resume execution from invalid state\";\n}\n\nEmergencyDebugOstream::EmergencyDebugOstream(bool cond, const Task* t,\n                                             const char* file, int line,\n                                             const char* function,\n                                             const char* cond_str)\n    : t(const_cast<Task*>(t)), cond(cond) {\n  if (!cond) {\n    write_prefix(*this, LOG_fatal, file, line, function);\n    *this << \"\\n (task \" << t->tid << \" (rec:\" << t->rec_tid << \") at time \"\n          << t->trace_time() << \")\"\n          << \"\\n -> Assertion `\" << cond_str << \"' failed to hold. \";\n  }\n}\n\nEmergencyDebugOstream::~EmergencyDebugOstream() {\n  if (!cond) {\n    log_stream() << endl;\n    flush_log_stream();\n    t->log_pending_events();\n    start_emergency_debug(t);\n  }\n}\n\nostream& operator<<(ostream& stream, const vector<uint8_t>& bytes) {\n  for (uint32_t i = 0; i < bytes.size(); ++i) {\n    if (i > 0) {\n      stream << ' ';\n    }\n    stream << HEX(bytes[i]);\n  }\n  return stream;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/log.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_LOG_H\n#define RR_LOG_H\n\n#include <features.h>\n#include <signal.h>\n\n#include <iostream>\n#include <type_traits>\n#include <vector>\n#include <cstdint>\n\n/**\n * Print siginfo on ostream.\n */\nstd::ostream& operator<<(std::ostream& stream, const siginfo_t& siginfo);\n\nnamespace rr {\n\nclass Task;\n\nenum LogLevel { LOG_fatal, LOG_error, LOG_warn, LOG_info, LOG_debug };\n\nstruct LogModule;\n\n/* A log module is just a string where any uppercase ASCII characters have\n * been lowercased. We assign a LogLevel for each log module; this assignment\n * can be configured via the `RR_LOG` environment variable and also modified\n * dynamically.\n *\n * We derive a log module name from a source file name (typically given in\n * __FILE__) by chopping off any directory parts and chopping off the trailing\n * file extension (if any), and lowercasing any uppercase ASCII characters.\n * e.g. <rr-dir>/src/Task.cc becomes the log module \"task\".\n *\n * This logging infrastructure is not thread safe. Use only on the main thread.\n */\n\n/**\n * Get the LogModule from a __FILE__. Useful for caching the module.\n */\nLogModule& get_log_module(const char* file);\n\n/**\n * Return the ostream to which log data will be written.\n */\nstd::ostream& log_stream();\n\n/**\n * Dynamically set all log levels to 'level'\n */\nvoid set_all_logging(LogLevel level);\n\n/**\n * Set log level for 'name' to 'level'\n */\nvoid set_logging(const char* name, LogLevel level);\n\nstd::ostream& operator<<(std::ostream& stream,\n                         const std::vector<uint8_t>& bytes);\n\nstd::ostream& operator<<(std::ostream& stream,\n                         const std::vector<uint8_t>& bytes);\n\n/**\n * Check whether logging is enabled for the given source file.\n * `file` must be a pointer that is valid forever, preferably\n * some value of `__FILE__`.\n */\nbool is_logging_enabled(LogLevel level, const char* file);\n\n/**\n * Flush the current log message in log_stream() to the log\n * output file or circular buffer.\n */\nvoid flush_log_buffer();\n\n/**\n * Parse the (RR_UNDER_)RR_LOG environment variable and logging\n * levels appropriately.\n */\nvoid apply_log_spec_from_env();\n\n/**\n * Set log level according to the specification in spec, according to the format\n * used by (RR_UNDER_)RR_LOG and `rr --log`.\n */\nvoid apply_log_spec(const char *spec);\n\nstruct NewlineTerminatingOstream {\n  /**\n   * `file` must be a pointer that is valid forever, preferably\n   * some value of `__FILE__`.\n   */\n  NewlineTerminatingOstream(LogLevel level, const char* file, int line,\n                            const char* function);\n  /**\n   * `file` must be a pointer that is valid forever, preferably\n   * some value of `__FILE__`.\n   * Use this variant to cached the LogModule for efficiency.\n   */\n  NewlineTerminatingOstream(LogModule** m, LogLevel level, const char* file, int line,\n                            const char* function);\n  ~NewlineTerminatingOstream();\n\n  bool enabled;\n  LogLevel level;\n};\ntemplate <typename T>\nconst NewlineTerminatingOstream& operator<<(\n    const NewlineTerminatingOstream& stream, const T& v) {\n  if (stream.enabled) {\n    log_stream() << v;\n  }\n  return stream;\n}\n// TODO: support stream modifiers.\n\n/**\n * Print clean fatal errors. These include the file, line and function name\n * but not errno or a stack trace. They go to stderr instead of the log file.\n */\nstruct CleanFatalOstream {\n  /**\n   * `file` must be a pointer that is valid forever, preferably\n   * some value of `__FILE__`.\n   */\n  CleanFatalOstream(const char* file, int line, const char* function);\n  ~CleanFatalOstream();\n};\ntemplate <typename T>\nconst CleanFatalOstream& operator<<(const CleanFatalOstream& stream,\n                                    const T& v) {\n  std::cerr << v;\n  return stream;\n}\n\n/**\n * Print detailed fatal errors. These include the file, line and function name\n * plus errno and a stack trace. Used for fatal errors where detailed\n * diagnostics may be required.\n */\nstruct FatalOstream {\n  FatalOstream(const char* file, int line, const char* function);\n  ~FatalOstream();\n};\ntemplate <typename T>\nconst FatalOstream& operator<<(const FatalOstream& stream, const T& v) {\n  log_stream() << v;\n  return stream;\n}\n\nstruct EmergencyDebugOstream {\n  /**\n   * `file` must be a pointer that is valid forever, preferably\n   * some value of `__FILE__`.\n   */\n  EmergencyDebugOstream(bool cond, const Task* t, const char* file, int line,\n                        const char* function, const char* cond_str);\n  ~EmergencyDebugOstream();\n  Task* t;\n  bool cond;\n};\ntemplate <typename T>\nconst EmergencyDebugOstream& operator<<(const EmergencyDebugOstream& stream,\n                                        const T& v) {\n  if (!stream.cond) {\n    log_stream() << v;\n  }\n  return stream;\n}\n\n/**\n * Write logging output at the given level, which can be one of |{\n * error, warn, info, debug }| in decreasing order of severity.\n */\n#define LOG(_level)                                                            \\\n  NewlineTerminatingOstream(LOG_##_level, __FILE__, __LINE__, __FUNCTION__)\n\n#define IS_LOGGING(_level) is_logging_enabled(LOG_##_level, __FILE__)\n\n#define FILE_CACHE_LOG_MODULE() static LogModule* cached_log_module\n\n/**\n * Like LOG but with a cached module\n */\n#define LOGM(_level)                                                            \\\n  NewlineTerminatingOstream(&cached_log_module, LOG_##_level, __FILE__, __LINE__, __FUNCTION__)\n\n/** A fatal error has occurred.  Log the error and exit. */\n#define FATAL() FatalOstream(__FILE__, __LINE__, __FUNCTION__)\n\n#define CLEAN_FATAL() CleanFatalOstream(__FILE__, __LINE__, __FUNCTION__)\n\n#ifndef __has_builtin\n#define __has_builtin(x) 0\n#endif\n#ifndef __GNUC_PREREQ\n#define __GNUC_PREREQ(maj, min) 0\n#endif\n#if __has_builtin(__builtin_expect) || __GNUC_PREREQ(4, 0)\n#define RR_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false)\n#else\n#define RR_UNLIKELY(EXPR) (EXPR)\n#endif\n\n/**\n * Assert a condition related to a Task.  If the condition fails, an\n * emergency debugger for the task is launched.\n */\n#define ASSERT(_t, _cond)                                                      \\\n  EmergencyDebugOstream(_cond, _t, __FILE__, __LINE__, __FUNCTION__, #_cond)\n#define ASSERT_ACTIONS(_t, _cond, _actions)                                    \\\n  do {                                                                         \\\n    bool _ASSERT_cond = _cond;                                                 \\\n    if (RR_UNLIKELY(!_ASSERT_cond)) {                                          \\\n      EmergencyDebugOstream(_ASSERT_cond, _t, __FILE__, __LINE__,              \\\n                            __FUNCTION__, #_cond) _actions;                    \\\n    }                                                                          \\\n  } while (0)\n\n/* use of assert() causes \"unused variable\" warnings in non-DEBUG builds\n * when a variable is only used in an assertion. DEBUG_ASSERT fixes that\n * problem. Use DEBUG_ASSERT instead of assert().\n * This also gives us a stack trace if the assertion fails.\n */\n#ifdef DEBUG\n#define DEBUG_ASSERT(cond) \\\n  do {                     \\\n    if (!(cond)) {         \\\n      FATAL() << #cond;    \\\n    }                      \\\n  } while(0)\n#else\n#define DEBUG_ASSERT(cond)                                                     \\\n  do {                                                                         \\\n    size_t s __attribute__((unused)) = sizeof(cond);                           \\\n  } while (0)\n#endif\n\n/**\n * Ensure that |_v| is streamed in hex format.\n * We make sure that signed types are *not* sign-extended.\n */\ntemplate <typename T> inline void* HEX(T v) {\n  return reinterpret_cast<void*>(\n      static_cast<typename std::make_unsigned<T>::type>(v));\n}\n\n} // namespace rr\n\n#endif // RR_LOG_H\n"
  },
  {
    "path": "src/main.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"main.h\"\n\n#include <limits.h>\n#include <linux/version.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/utsname.h>\n\n#include <sstream>\n\n#include \"Command.h\"\n#include \"Flags.h\"\n#include \"RecordCommand.h\"\n#include \"ReplayCommand.h\"\n#include \"core.h\"\n#include \"extra_version_string.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\n// Show version and quit.\nstatic bool show_version = false;\nstatic bool show_cmd_list = false;\n\nvoid assert_prerequisites(bool use_syscall_buffer) {\n  struct utsname uname_buf;\n  memset(&uname_buf, 0, sizeof(uname_buf));\n  if (!uname(&uname_buf)) {\n    unsigned int major, minor;\n    char dot;\n    stringstream stream(uname_buf.release);\n    stream >> major >> dot >> minor;\n    if (KERNEL_VERSION(major, minor, 0) < KERNEL_VERSION(3, 4, 0)) {\n      FATAL() << \"Kernel doesn't support necessary ptrace \"\n              << \"functionality; need 3.4.0 or better.\";\n    }\n\n    if (use_syscall_buffer &&\n        KERNEL_VERSION(major, minor, 0) < KERNEL_VERSION(3, 5, 0)) {\n      FATAL() << \"Your kernel does not support syscall \"\n              << \"filtering; please use the -n option\";\n    }\n  }\n}\n\nvoid print_version(FILE* out) { fprintf(out, \"rr version %s %s\\n\", RR_VERSION, EXTRA_VERSION_STRING); }\n\nvoid print_global_options(FILE* out) {\n  fputs(\n      \"Global options:\\n\"\n      \"  --disable-cpuid-faulting   disable use of CPUID faulting\\n\"\n      \"  --disable-ptrace-exit_events disable use of PTRACE_EVENT_EXIT\\n\"\n      \"  --resource-path=PATH       specify the paths that rr should use to \"\n      \"find\\n\"\n      \"                             files such as rr_page_*.  These files \"\n      \"should\\n\"\n      \"                             be located in PATH/bin, PATH/lib[64], and\\n\"\n      \"                             PATH/share as appropriate.\\n\"\n      \"  -A, --microarch=<NAME>     force rr to assume it's running on a CPU\\n\"\n      \"                             with microarch NAME even if runtime \"\n      \"detection\\n\"\n      \"                             says otherwise.  NAME should be a string \"\n      \"like\\n\"\n      \"                             'Ivy Bridge'. Note that rr will not work \"\n      \"with\\n\"\n      \"                             Intel Merom or Penryn microarchitectures.\\n\"\n      \"  -F, --force-things         force rr to do some things that don't \"\n      \"seem\\n\"\n      \"                             like good ideas, for example launching an\\n\"\n      \"                             interactive emergency debugger if stderr\\n\"\n      \"                             isn't a tty.\\n\"\n      \"  -E, --fatal-errors         any warning or error that is printed is\\n\"\n      \"                             treated as fatal\\n\"\n      \"  -M, --mark-stdio           mark stdio writes with [rr <PID> <EV>]\\n\"\n      \"                             where EV is the global trace time at\\n\"\n      \"                             which the write occurs and PID is the pid\\n\"\n      \"                             of the process it occurs in.\\n\"\n      \"  -N, --version              print the version number and exit\\n\"\n      \"  -S, --suppress-environment-warnings\\n\"\n      \"                             suppress warnings about issues in the\\n\"\n      \"                             environment that rr has no control over\\n\"\n      \"  --log=<spec>               Set logging config to <spec>. See RR_LOG.\\n\"\n      \"\\n\"\n      \"Environment variables:\\n\"\n      \" $RR_LOG        logging configuration ; e.g. RR_LOG=all:warn,Task:debug\\n\"\n      \" $RR_TMPDIR     to use a different TMPDIR than the recorded program\\n\"\n      \" $_RR_TRACE_DIR where traces will be stored;\\n\"\n      \"                falls back to $XDG_DATA_HOME / $HOME/.local/share/rr\\n\",\n      out);\n}\n\nvoid list_commands(FILE* out) {\n  Command::print_help_all(out);\n}\n\nvoid print_usage(FILE* out) {\n  print_version(out);\n  fputs(\"\\nUsage:\\n\", out);\n  list_commands(out);\n  fputs(\"\\nIf no subcommand is provided, we check if the first non-option\\n\"\n        \"argument is a directory. If it is, we assume the 'replay' subcommand\\n\"\n        \"otherwise we assume the 'record' subcommand.\\n\\n\",\n        out);\n  print_global_options(out);\n\n  /* we should print usage when utility being wrongly used.\n     use 'exit' with failure code */\n  exit(EXIT_FAILURE);\n}\n\nstatic void init_random() {\n  // Not very good, but good enough for our non-security-sensitive needs.\n  int key;\n  good_random(&key, sizeof(key));\n  srandom(key);\n  srand(key);\n}\n\nbool parse_global_option(std::vector<std::string>& args) {\n  static const OptionSpec options[] = {\n    { 0, \"disable-cpuid-faulting\", NO_PARAMETER },\n    { 1, \"disable-ptrace-exit-events\", NO_PARAMETER },\n    { 2, \"resource-path\", HAS_PARAMETER },\n    { 3, \"log\", HAS_PARAMETER },\n    { 4, \"non-interactive\", NO_PARAMETER },\n    { 'A', \"microarch\", HAS_PARAMETER },\n    { 'C', \"checksum\", HAS_PARAMETER },\n    { 'D', \"dump-on\", HAS_PARAMETER },\n    { 'E', \"fatal-errors\", NO_PARAMETER },\n    { 'F', \"force-things\", NO_PARAMETER },\n    { 'K', \"check-cached-mmaps\", NO_PARAMETER },\n    { 'L', \"list-commands\", NO_PARAMETER },\n    { 'M', \"mark-stdio\", NO_PARAMETER },\n    { 'N', \"version\", NO_PARAMETER },\n    { 'S', \"suppress-environment-warnings\", NO_PARAMETER },\n    { 'T', \"dump-at\", HAS_PARAMETER },\n  };\n\n  ParsedOption opt;\n  if (!Command::parse_option(args, options, &opt)) {\n    return false;\n  }\n\n  Flags& flags = Flags::get_for_init();\n  switch (opt.short_name) {\n    case 0:\n      flags.disable_cpuid_faulting = true;\n      break;\n    case 1:\n      flags.disable_ptrace_exit_events = true;\n      break;\n    case 2:\n      flags.resource_path = opt.value;\n      if (flags.resource_path.back() != '/') {\n        flags.resource_path.append(\"/\");\n      }\n      break;\n    case 3:\n      apply_log_spec(opt.value.c_str());\n      break;\n    case 4:\n      flags.non_interactive = true;\n      break;\n    case 'A':\n      flags.forced_uarch = opt.value;\n      break;\n    case 'C':\n      if (opt.value == \"on-syscalls\") {\n        LOG(info) << \"checksumming on syscall exit\";\n        flags.checksum = Flags::CHECKSUM_SYSCALL;\n      } else if (opt.value == \"on-all-events\") {\n        LOG(info) << \"checksumming on all events\";\n        flags.checksum = Flags::CHECKSUM_ALL;\n      } else {\n        flags.checksum = strtoll(opt.value.c_str(), NULL, 10);\n        LOG(info) << \"checksumming on at event \" << flags.checksum;\n      }\n      break;\n    case 'D':\n      if (opt.value == \"RDTSC\") {\n        flags.dump_on = Flags::DUMP_ON_RDTSC;\n      } else {\n        flags.dump_on = strtoll(opt.value.c_str(), NULL, 10);\n      }\n      break;\n    case 'E':\n      flags.fatal_errors_and_warnings = true;\n      break;\n    case 'F':\n      flags.force_things = true;\n      break;\n    case 'K':\n      flags.check_cached_mmaps = true;\n      break;\n    case 'M':\n      flags.mark_stdio = true;\n      break;\n    case 'S':\n      flags.suppress_environment_warnings = true;\n      break;\n    case 'T':\n      flags.dump_at = strtoll(opt.value.c_str(), NULL, 10);\n      break;\n    case 'N':\n      show_version = true;\n      break;\n    case 'L':\n      show_cmd_list = true;\n      break;\n    default:\n      DEBUG_ASSERT(0 && \"Invalid flag\");\n  }\n  return true;\n}\n\nstatic char* saved_argv0_;\nstatic size_t saved_argv0_space_;\n\nchar* saved_argv0() {\n  return saved_argv0_;\n}\nsize_t saved_argv0_space() {\n  return saved_argv0_space_;\n}\n\n} // namespace rr\n\nusing namespace rr;\n\nint main(int argc, char* argv[]) {\n  rr::saved_argv0_ = argv[0];\n  rr::saved_argv0_space_ = argv[argc - 1] + strlen(argv[argc - 1]) + 1 - rr::saved_argv0_;\n\n  init_random();\n  raise_resource_limits();\n\n  vector<string> args;\n  for (int i = 1; i < argc; ++i) {\n    args.push_back(argv[i]);\n  }\n\n  while (parse_global_option(args)) {\n  }\n\n  if (show_version) {\n    print_version(stdout);\n    return 0;\n  }\n  if (show_cmd_list) {\n    list_commands(stdout);\n    return 0;\n  }\n\n  if (args.size() == 0) {\n    print_usage(stderr);\n  }\n\n  auto command = Command::command_for_name(args[0]);\n  if (command) {\n    args.erase(args.begin());\n  } else {\n    if (!Command::verify_not_option(args)) {\n      print_usage(stderr);\n    }\n    if (is_directory(args[0].c_str())) {\n      command = ReplayCommand::get();\n    } else {\n      command = RecordCommand::get();\n    }\n  }\n\n  return command->run(args);\n}\n"
  },
  {
    "path": "src/main.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_MAIN_H_\n#define RR_MAIN_H_\n\n#include <string>\n#include <vector>\n\nnamespace rr {\n\nvoid assert_prerequisites(bool use_syscall_buffer = false);\n\nvoid print_global_options(FILE*);\nvoid print_usage(FILE*);\n\nbool parse_global_option(std::vector<std::string>& args);\n\nchar* saved_argv0();\n// Space available at `saved_argv0` including trailing null bytes.\nsize_t saved_argv0_space();\n\n} // namespace rr\n\n#endif // RR_MAIN_H_\n"
  },
  {
    "path": "src/perf-test/many-threads-wake.c",
    "content": "#include <stdint.h>\n#include <linux/futex.h>\n#include <sys/syscall.h>\n#include <pthread.h>\n#include <unistd.h>\n\nstatic volatile uint32_t futex_val;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  if (futex_val == 0) {\n    syscall(SYS_futex, &futex_val, FUTEX_WAIT, 0, NULL);\n  }\n  futex_val = 0;\n  syscall(SYS_futex, &futex_val, FUTEX_WAKE, 0, NULL);\n  pause();\n  return NULL;\n}\n\nint main(void) {\n  for (int i = 0; i < 5000; ++i) {\n    pthread_t th;\n    pthread_create(&th, NULL, do_thread, NULL);\n    futex_val = 1;\n    syscall(SYS_futex, &futex_val, FUTEX_WAKE, 1);\n    syscall(SYS_futex, &futex_val, FUTEX_WAIT, 1, NULL);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/perf-test/many-threads-wake.md",
    "content": "`many-threads-wake` creates 5000 threads. Each new thread has to wait for the creator thread to exit a critical section before proceeding.\n\nCheat sheet:\n````\ncd ~/rr/obj\ncmake -DCMAKE_BUILD_TYPE=RELEASE ../rr\nmake -j8\n\ngcc -g -o many-threads-wake ../rr/src/perf-test/many-threads-wake.c\ntime bin/rr record ./many-threads-wake\n````\n"
  },
  {
    "path": "src/perf-test/many-threads.c",
    "content": "#include <stdio.h>\n#include <pthread.h>\n#include <unistd.h>\n\nstatic int main_to_child_fds[2];\nstatic int child_to_main_fds[2];\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  pause();\n  return NULL;\n}\n\nstatic void* do_thread2(__attribute__((unused)) void* p) {\n  for (int i = 0; i < 20000; ++i) {\n    char ch;\n    read(main_to_child_fds[0], &ch, 1);\n    write(child_to_main_fds[1], \"y\", 1);\n  }\n  return NULL;\n}\n\nint main(void) {\n  pipe(main_to_child_fds);\n  pipe(child_to_main_fds);\n  for (int i = 0; i < 5000; ++i) {\n    pthread_t th;\n    pthread_create(&th, NULL, do_thread, NULL);\n  }\n  puts(\"Created ballast threads\");\n  pthread_t th;\n  pthread_create(&th, NULL, do_thread2, NULL);\n  for (int i = 0; i < 20000; ++i) {\n    char ch;\n    write(main_to_child_fds[1], \"x\", 1);\n    read(child_to_main_fds[0], &ch, 1);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/perf-test/many-threads.md",
    "content": "`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.\n\nCheat sheet:\n````\ncd ~/rr/obj\ncmake -DCMAKE_BUILD_TYPE=RELEASE ../rr\nmake -j8\n\ngcc -g -o many-threads ../rr/src/perf-test/many-threads.c\ntime bin/rr record ./many-threads\n````\n"
  },
  {
    "path": "src/perf-test/unbuffered-syscalls.c",
    "content": "#include <unistd.h>\n\nint main(void) {\n  for (int i = 0; i < 500000; ++i) {\n    getsid(0);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/perf-test/unbuffered-syscalls.md",
    "content": "`unbuffered-syscalls` is a simple test for the performance of handling\ntrivial system calls. It stresses the basic ptrace syscall-handling\nmachinery, and reading/writing trace events. It can also provide a basic\ncheck of trace size. It executes 500K syscalls (i.e. 1M trace events) and\ncurrently takes about 10 seconds to record and 8 seconds to replay on my\nSkylake laptop, with an `events` file size of about 5.5 MB.\n\nCheat sheet:\n````\ncd ~/rr/obj\ncmake -DCMAKE_BUILD_TYPE=RELEASE ../rr\nmake -j8\n\ngcc -g -o unbuffered-syscalls ../rr/src/perf-test/unbuffered-syscalls.c\ntime bin/rr record ./unbuffered-syscalls\ntime bin/rr replay -a\nls -l ~/.local/share/rr/latest-trace/events\n\nperf record --call-graph lbr bin/rr record ./unbuffered-syscalls\nperf report\nperf record --call-graph lbr bin/rr replay -a\nperf report\n````\n"
  },
  {
    "path": "src/preload/overrides.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define RR_IMPLEMENT_PRELOAD\n\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n\n#include <dlfcn.h>\n#include <pthread.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/syscall.h>\n#include <unistd.h>\n\n#include \"preload_interface.h\"\n#include \"syscallbuf.h\"\n\n#define PTHREAD_MUTEX_PRIO_INHERIT_NP 32\n\n#define DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE 1\n#ifdef __GLIBC_PREREQ\n#if __GLIBC_PREREQ(2, 34)\n#undef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\n#endif\n#endif\n\n#ifndef __BIONIC__\n\n// Use an old version of dlsym so this code still works when built against glibc > 2.34\n// but loaded into a process linking a pre-2.34 glibc.\n#ifdef __x86_64__\n__asm__(\".symver dlsym,dlsym@GLIBC_2.2.5\");\n#elif defined(__i386__)\n__asm__(\".symver dlsym,dlsym@GLIBC_2.0\");\n#endif\n\nstatic int (*real_pthread_mutex_init)(void* mutex, const void* attr);\nstatic int (*real_pthread_mutex_lock)(void* mutex);\nstatic int (*real_pthread_mutex_trylock)(void* mutex);\nstatic int (*real_pthread_mutex_timedlock)(void* mutex,\n                                           const struct timespec* abstime);\nstatic int (*real_pthread_mutexattr_setprotocol)(void* attr, int protocol);\n\nstatic void __attribute__((constructor)) init_override(void) {\n  real_pthread_mutex_init = dlsym(RTLD_NEXT, \"pthread_mutex_init\");\n  real_pthread_mutex_lock = dlsym(RTLD_NEXT, \"pthread_mutex_lock\");\n  real_pthread_mutex_trylock = dlsym(RTLD_NEXT, \"pthread_mutex_trylock\");\n  real_pthread_mutex_timedlock = dlsym(RTLD_NEXT, \"pthread_mutex_timedlock\");\n  real_pthread_mutexattr_setprotocol = dlsym(RTLD_NEXT, \"pthread_mutexattr_setprotocol\");\n}\n\nstatic void fix_mutex_kind(pthread_mutex_t* mutex) {\n  /* Disable priority inheritance. */\n  mutex->__data.__kind &= ~PTHREAD_MUTEX_PRIO_INHERIT_NP;\n}\n\n#ifdef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\n/*\n * We need to able to call directly to __pthread_mutex_lock and\n * __pthread_mutex_trylock because setting up our indirect function pointers\n * calls dlsym which itself can call pthread_mutex_lock (e.g. via application\n * code overriding malloc/calloc to use a pthreads-based implementation).\n * So before our pointers are set up, call these.\n *\n * If we're building against glibc 2.34 *but* we get run against a binary\n * linking with glibc < 2.34 *and* the application overrides malloc to use\n * pthreads-based synchronization then this won't work and we lose. Let's\n * hope this doesn't happen.\n */\nextern int __pthread_mutex_init(pthread_mutex_t* mutex,\n                                const pthread_mutexattr_t* attr);\nextern int __pthread_mutex_lock(pthread_mutex_t* mutex);\nextern int __pthread_mutex_trylock(pthread_mutex_t* mutex);\n#endif\n\nint pthread_mutex_init(pthread_mutex_t* mutex,\n                       const pthread_mutexattr_t* attr) {\n  int ret;\n  pthread_mutexattr_t realattr;\n\n  if (attr) {\n    /* We wish to enforce the use of plain (no PI) mutex to avoid\n     * needing to handle PI futex() operations.\n     * We also wish to ensure that pthread_mutexattr_getprotocol()\n     * still returns the requested protocol.\n     * So we copy the attribute and force PTHREAD_PRIO_NONE.\n     */\n    memcpy(&realattr, attr, sizeof(realattr));\n    // We assume dlsym doesn't call pthread_mutex_init with attributes.\n    // We avoid calling pthread_mutexattr_setprotocol (and any other pthread functions)\n    // directly because that won't work when we're built against glibc 2.34 but loaded\n    // into a process using glibc < 2.34. (pthread functions got a symbol version bump\n    // in 2.34.)\n    //\n    // But note that we can't use dlsym in cases where we would want to use the double\n    // underscore methods (i.e. glibc < 2.34). There is no double underscore version of\n    // pthread_mutexattr_setprotocol, so we call it directly.\n    if (!real_pthread_mutexattr_setprotocol) {\n#ifdef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\n      ret = pthread_mutexattr_setprotocol(&realattr, PTHREAD_PRIO_NONE);\n      goto setprotocol;\n#else\n      real_pthread_mutexattr_setprotocol = dlsym(RTLD_NEXT, \"pthread_mutexattr_setprotocol\");\n#endif\n    }\n    ret = real_pthread_mutexattr_setprotocol(&realattr, PTHREAD_PRIO_NONE);\n#ifdef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\nsetprotocol:\n#endif\n    if (ret) {\n      return ret;\n    }\n    attr = &realattr;\n  }\n  if (!real_pthread_mutex_init) {\n#ifdef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\n    return __pthread_mutex_init(mutex, attr);\n#else\n    real_pthread_mutex_init = dlsym(RTLD_NEXT, \"pthread_mutex_init\");\n#endif\n  }\n  return real_pthread_mutex_init(mutex, attr);\n}\n\n/* Prevent use of lock elision; Haswell's TSX/RTM features used by\n   lock elision increment the rbc perf counter for instructions which\n   are later rolled back if the transaction fails. */\nint pthread_mutex_lock(pthread_mutex_t* mutex) {\n  fix_mutex_kind(mutex);\n  if (!real_pthread_mutex_lock) {\n#ifdef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\n    return __pthread_mutex_lock(mutex);\n#else\n    real_pthread_mutex_lock = dlsym(RTLD_NEXT, \"pthread_mutex_lock\");\n#endif\n  }\n  return real_pthread_mutex_lock(mutex);\n}\n\nint pthread_mutex_timedlock(pthread_mutex_t* mutex,\n                            const struct timespec* abstime) {\n  fix_mutex_kind(mutex);\n  /* No __pthread_mutex_timedlock stub exists, so we have to use the\n   * indirect call no matter what.\n   */\n  if (!real_pthread_mutex_timedlock) {\n    real_pthread_mutex_timedlock = dlsym(RTLD_NEXT, \"pthread_mutex_timedlock\");\n  }\n  return real_pthread_mutex_timedlock(mutex, abstime);\n}\n\nint pthread_mutex_trylock(pthread_mutex_t* mutex) {\n  fix_mutex_kind(mutex);\n  if (!real_pthread_mutex_trylock) {\n#ifdef DOUBLE_UNDERSCORE_PTHREAD_LOCK_AVAILABLE\n    return __pthread_mutex_trylock(mutex);\n#else\n    real_pthread_mutex_trylock = dlsym(RTLD_NEXT, \"pthread_mutex_trylock\");\n#endif\n  }\n  return real_pthread_mutex_trylock(mutex);\n}\n\n#endif\n\ntypedef void* Dlopen(const char* filename, int flags);\n\nvoid* dlopen(const char* filename, int flags) {\n  // Give up our timeslice now. This gives us a full timeslice to\n  // execute the dlopen(), reducing the chance we'll hit\n  // https://sourceware.org/bugzilla/show_bug.cgi?id=19329.\n  Dlopen* f_ptr = (Dlopen*)dlsym(RTLD_NEXT, \"dlopen\");\n  sched_yield();\n  return f_ptr(filename, flags);\n}\n\n/** Disable XShm since rr doesn't work with it */\nint XShmQueryExtension(__attribute__((unused)) void* dpy) { return 0; }\n\n/** Make sure XShmCreateImage returns null in case an application doesn't do\n    extension checks first. */\nvoid* XShmCreateImage(__attribute__((unused)) register void* dpy,\n                      __attribute__((unused)) register void* visual,\n                      __attribute__((unused)) unsigned int depth,\n                      __attribute__((unused)) int format,\n                      __attribute__((unused)) char* data,\n                      __attribute__((unused)) void* shminfo,\n                      __attribute__((unused)) unsigned int width,\n                      __attribute__((unused)) unsigned int height) {\n  return 0;\n}\n\nRR_HIDDEN char impose_syscall_delay;\nRR_HIDDEN char impose_spurious_desched;\n\n/**\n * This is for testing purposes only.\n */\nvoid delayed_syscall(struct syscall_info* info) {\n  impose_syscall_delay = 1;\n  /* Make sure 'result' is used so it's not optimized out! */\n  syscall(info->no, info->args[0], info->args[1], info->args[2], info->args[3],\n          info->args[4], info->args[5]);\n  impose_syscall_delay = 0;\n}\n\n/**\n * This is for testing purposes only.\n * Note that this must be defined outside of the syscallbuf code.\n * Otherwise, the signal recording code may expect exit from this function\n * to trigger the syscallbuf exit breakpoint.\n */\nvoid* syscallbuf_ptr(void) {\n  return ((struct preload_thread_locals*)PRELOAD_THREAD_LOCALS_ADDR)->buffer;\n}\n\n/**\n * This is for testing purposes only.\n */\nvoid spurious_desched_syscall(struct syscall_info* info) {\n  impose_spurious_desched = 1;\n  /* Make sure 'result' is used so it's not optimized out! */\n  syscall(info->no, info->args[0], info->args[1], info->args[2], info->args[3],\n          info->args[4], info->args[5]);\n  impose_spurious_desched = 0;\n}\n\n/**\n * clang's LeakSanitizer has regular threads call sched_yield() in a loop while\n * a helper thread ptrace-attaches to them. If we let sched_yield() enter the\n * syscallbuf, the helper thread sees that the regular thread SP register\n * is pointing to the syscallbuf alt-stack, outside the stack region it\n * expects, which causes it to freak out.\n * So, override sched_yield() to perform the syscall in a way that can't\n * be syscall-buffered.\n */\nint sched_yield(void) {\n#ifdef __i386__\n  // We have no syscall hook for `syscall` followed by `inc %ecx`\n  int trash;\n  asm volatile (\"int $0x80; inc %0\" : \"=c\"(trash) : \"a\"(SYS_sched_yield));\n#elif defined(__x86_64__)\n  // We have no syscall hook for `syscall` followed by `inc %ecx`\n  int trash;\n  asm volatile (\"syscall; inc %0\" : \"=c\"(trash) : \"a\"(SYS_sched_yield));\n#elif defined(__aarch64__)\n  register long x8 __asm__(\"x8\") = SYS_sched_yield;\n  // We explicitly blacklisted syscall that follows `mov x8, 0xdc`\n  // to avoid patching clone. Abuse that to prevent this from being patched.\n  __asm__ __volatile__(\"b 1f\\n\\t\"\n                       \"mov x8, 0xdc\\n\"\n                       \"1:\\n\\t\"\n                       \"svc 0\\n\"\n                       :: \"r\"(x8) : \"x0\", \"x30\"); // x30 = lr\n#else\n#error \"Unknown architecture\"\n#endif\n  return 0;\n}\n\n#ifndef __aarch64__\n\n/**\n * glibc geteuid() can be compiled to instructions ending in \"syscall; ret\"\n * which sometimes can't be hooked. So override it here with something that\n * can be hooked.\n * This is not an issue on aarch64 since we only need to patch a single instruction.\n */\nuid_t geteuid(void) {\n#ifdef __i386__\n  return syscall(SYS_geteuid32);\n#else\n  return syscall(SYS_geteuid);\n#endif\n}\n\nstatic void libstdcpp_not_found(void) {\n  const char msg[] = \"[rr] Interposition for libstdc++ called but symbol lookups into libstdc++ failed.\\n\"\n    \"Was libstdc++ loaded with RTLD_LOCAL? Try recording with `-v LD_PRELOAD=libstdc++.so.6`.\\n\"\n    \"About to crash! \";\n  syscall(SYS_write, STDERR_FILENO, msg, sizeof(msg));\n}\n\n/**\n * libstdc++3 uses RDRAND. Bypass that with this incredible hack.\n */\nvoid _ZNSt13random_device7_M_initERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE(\n    void* this, __attribute__((unused)) void* token) {\n  static void (*assign_string)(void *, char*) = NULL;\n  static void (*random_init)(void *, void*) = NULL;\n  if (!assign_string) {\n    assign_string = (void (*)(void *, char*))dlsym(RTLD_NEXT,\n      \"_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE6assignEPKc\");\n    if (!assign_string) {\n      libstdcpp_not_found();\n    }\n  }\n  assign_string(token, \"/dev/urandom\");\n  if (!random_init) {\n    random_init = (void (*)(void *, void*))dlsym(RTLD_NEXT, __func__);\n    if (!random_init) {\n      libstdcpp_not_found();\n    }\n  }\n  random_init(this, token);\n}\n\n/**\n * gcc 4.8.4 in Ubuntu 14.04-32\n */\nvoid _ZNSt13random_device7_M_initERKSs(void* this,\n                                       __attribute__((unused)) void* token) {\n  static void (*assign_string)(void *, char*) = NULL;\n  static void (*random_init)(void *, void*) = NULL;\n  if (!assign_string) {\n    assign_string = (void (*)(void *, char*))dlsym(RTLD_NEXT,\n      \"_ZNSs6assignEPKc\");\n    if (!assign_string) {\n      libstdcpp_not_found();\n    }\n  }\n  assign_string(token, \"/dev/urandom\");\n  if (!random_init) {\n    random_init = (void (*)(void *, void*))dlsym(RTLD_NEXT, __func__);\n    if (!random_init) {\n      libstdcpp_not_found();\n    }\n  }\n  random_init(this, token);\n}\n\n#endif\n"
  },
  {
    "path": "src/preload/preload_interface.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PRELOAD_INTERFACE_H_\n#define RR_PRELOAD_INTERFACE_H_\n\n/* Bump this whenever the interface between syscallbuf and rr changes in a way\n * that would require changes to replay. So be very careful making changes to\n * this file! Many changes would require a bump in this value, and support\n * code in rr to handle old protocol versions. And when we bump it we'll need\n * to figure out a way to test the old protocol versions.\n * To be clear, changes that only affect recording and not replay, such as\n * changes to the layout of syscall_patch_hook, do not need to bump this.\n * Note also that SYSCALLBUF_PROTOCOL_VERSION is stored in the trace header, so\n * replay always has access to the SYSCALLBUF_PROTOCOL_VERSION used during\n * recording, even before the preload library is ever loaded.\n *\n * Version 0: initial rr 5.0.0 release\n */\n#define SYSCALLBUF_PROTOCOL_VERSION 0\n\n#if defined(RR_IMPLEMENT_PRELOAD) || defined(RR_IMPLEMENT_AUDIT)\n/* Avoid using <string.h> library functions */\nstatic inline int streq(const char* s1, const char* s2) {\n  while (1) {\n    if (*s1 != *s2) {\n      return 0;\n    }\n    if (!*s1) {\n      return 1;\n    }\n    ++s1;\n    ++s2;\n  }\n  return 1;\n}\nstatic inline size_t rrstrlen(const char* s) {\n  size_t ret = 0;\n  while (*s) {\n    ++s;\n    ++ret;\n  }\n  return ret;\n}\n#else\n#include <string.h>\nstatic inline int streq(const char* s1, const char* s2) {\n  return !strcmp(s1, s2);\n}\nstatic inline size_t rrstrlen(const char* s) { return strlen(s); }\n#include \"../remote_ptr.h\"\n#endif\n\n#include <stdint.h>\n#include <stddef.h>\n\nstatic inline int strprefix(const char* s1, const char* s2) {\n  while (1) {\n    if (!*s1) {\n      return 1;\n    }\n    if (*s1 != *s2) {\n      return 0;\n    }\n    ++s1;\n    ++s2;\n  }\n  return 1;\n}\n\nstatic inline const char* extract_file_name(const char* s) {\n  const char* ret = s;\n  while (*s) {\n    if (*s == '/') {\n      ret = s + 1;\n    }\n    ++s;\n  }\n  return ret;\n}\n\n/* This header file is included by preload.c and various rr .cc files. It\n * defines the interface between the preload library and rr. preload.c\n * #defines RR_IMPLEMENT_PRELOAD to let us handle situations where rr and\n * preload.c need to see slightly different definitions of the same constructs.\n *\n * preload.c compiles this as C code. All rr modules compile this as C++ code.\n * We do not use 'extern \"C\"' because we don't actually link between C and C++\n * and 'extern \"C\"' is not compatible with our use of templates below.\n */\n\n#define SYSCALLBUF_LIB_FILENAME_BASE \"librrpreload\"\n#define SYSCALLBUF_LIB_FILENAME SYSCALLBUF_LIB_FILENAME_BASE \".so\"\n#define SYSCALLBUF_LIB_FILENAME_PADDED SYSCALLBUF_LIB_FILENAME_BASE \".so:::\"\n#define SYSCALLBUF_LIB_FILENAME_32 SYSCALLBUF_LIB_FILENAME_BASE \"_32.so\"\n\n#define RTLDAUDIT_LIB_FILENAME_BASE \"librraudit\"\n#define RTLDAUDIT_LIB_FILENAME RTLDAUDIT_LIB_FILENAME_BASE \".so\"\n#define RTLDAUDIT_LIB_FILENAME_PADDED RTLDAUDIT_LIB_FILENAME_BASE \".so:::\"\n#define RTLDAUDIT_LIB_FILENAME_32 RTLDAUDIT_LIB_FILENAME_BASE \"_32.so\"\n\n#define RRPAGE_LIB_FILENAME_BASE \"librrpage\"\n#define RRPAGE_LIB_FILENAME RRPAGE_LIB_FILENAME_BASE \".so\"\n#define RRPAGE_LIB_FILENAME_32 RRPAGE_LIB_FILENAME_BASE \"_32.so\"\n\n/* Set this env var to enable syscall buffering. */\n#define SYSCALLBUF_ENABLED_ENV_VAR \"_RR_USE_SYSCALLBUF\"\n\n/* Size of table mapping fd numbers to syscallbuf-disabled flag. */\n#define SYSCALLBUF_FDS_DISABLED_SIZE 16384\n\n#define MPROTECT_RECORD_COUNT 1000\n\n#if defined(__x86_64__) || defined(__i386__)\n#define RR_PAGE_SYSCALL_STUB_SIZE 3\n#define RR_PAGE_SYSCALL_INSTRUCTION_END 2\n#elif defined(__aarch64__)\n#define RR_PAGE_SYSCALL_STUB_SIZE 8\n#define RR_PAGE_SYSCALL_INSTRUCTION_END 4\n#else\n#error \"Must be defined for this architecture\"\n#endif\n\n/* Must match generate_rr_page.py */\n#define RR_PAGE_ADDR 0x70000000\n#ifdef __aarch64__\n#define PRELOAD_LIBRARY_PAGE_SIZE 65536\n#else\n#define PRELOAD_LIBRARY_PAGE_SIZE 4096\n#endif\n#define RR_PAGE_SYSCALL_ADDR(index)                                            \\\n  ((void*)(RR_PAGE_ADDR + RR_PAGE_SYSCALL_STUB_SIZE * (index)))\n#define RR_PAGE_SYSCALL_TRACED RR_PAGE_SYSCALL_ADDR(0)\n#define RR_PAGE_SYSCALL_PRIVILEGED_TRACED RR_PAGE_SYSCALL_ADDR(1)\n#define RR_PAGE_SYSCALL_UNTRACED RR_PAGE_SYSCALL_ADDR(2)\n#define RR_PAGE_SYSCALL_UNTRACED_REPLAY_ONLY RR_PAGE_SYSCALL_ADDR(3)\n#define RR_PAGE_SYSCALL_UNTRACED_RECORDING_ONLY RR_PAGE_SYSCALL_ADDR(4)\n#define RR_PAGE_SYSCALL_PRIVILEGED_UNTRACED RR_PAGE_SYSCALL_ADDR(5)\n#define RR_PAGE_SYSCALL_PRIVILEGED_UNTRACED_REPLAY_ONLY RR_PAGE_SYSCALL_ADDR(6)\n#define RR_PAGE_SYSCALL_PRIVILEGED_UNTRACED_RECORDING_ONLY                     \\\n  RR_PAGE_SYSCALL_ADDR(7)\n#define RR_PAGE_SYSCALL_UNTRACED_REPLAY_ASSIST RR_PAGE_SYSCALL_ADDR(8)\n#define RR_PAGE_IN_REPLAY_FLAG (RR_PAGE_ADDR + RR_PAGE_SYSCALL_STUB_SIZE * 9)\n#define RR_PAGE_BREAKPOINT_VALUE (RR_PAGE_IN_REPLAY_FLAG + 4)\n\n/* Not ABI stable - in record page only */\n#define RR_PAGE_FF_BYTES RR_PAGE_BREAKPOINT_VALUE\n\n#define RR_DL_RUNTIME_RESOLVE_CLEAR_FIP (RR_PAGE_ADDR - PRELOAD_LIBRARY_PAGE_SIZE)\n\n/* PRELOAD_THREAD_LOCALS_ADDR should not change.\n * Tools depend on this address. */\n#define PRELOAD_THREAD_LOCALS_ADDR (RR_PAGE_ADDR + PRELOAD_LIBRARY_PAGE_SIZE)\n#ifdef __aarch64__\n#define PRELOAD_THREAD_LOCAL_SCRATCH2_SIZE (1024 + 8 * 2)\n#else\n#define PRELOAD_THREAD_LOCAL_SCRATCH2_SIZE 0\n#endif\n#define PRELOAD_THREAD_LOCALS_SIZE (144 + PRELOAD_THREAD_LOCAL_SCRATCH2_SIZE)\n\n#include \"rrcalls.h\"\n\n/* Define macros that let us compile a struct definition either \"natively\"\n * (when included by preload.c) or as a template over Arch for use by rr.\n */\n#if defined(RR_IMPLEMENT_PRELOAD) || defined(RR_IMPLEMENT_AUDIT)\n#define TEMPLATE_ARCH\n#define PTR(T) T*\n#define PTR_ARCH(T) T*\n#define EMBED_STRUCT(T) struct T\n#define VOLATILE volatile\n#define SIGNED_LONG long\n#define UNSIGNED_LONG unsigned long\n#else\n#define TEMPLATE_ARCH template <typename Arch>\n#define PTR(T) typename Arch::template ptr<T>\n#define PTR_ARCH(T) typename Arch::template ptr<T<Arch>>\n#define EMBED_STRUCT(T) T<Arch>\n#define VOLATILE\n#define SIGNED_LONG typename Arch::signed_long\n#define UNSIGNED_LONG typename Arch::unsigned_long\n#endif\n\n#define PATCH_IS_MULTIPLE_INSTRUCTIONS (1 << 0)\n/* The syscall instruction is the last instruction in the patched area\n * (rather than the first), which requires special handling.\n */\n#define PATCH_SYSCALL_INSTRUCTION_IS_LAST (1 << 1)\n/* All instructions in the patch are nop and their execution is thus not\n * observable. This may allow more aggressive handling of interfering branches.\n */\n#define PATCH_IS_NOP_INSTRUCTIONS (1 << 2)\n/* The trailing 4 bytes of the instruction following the syscall/rdtsc are\n * variable. Do not try to match on them.\n * Also we preserve those bytes instead of overwriting with NOPs.\n */\n#define PATCH_NO_MATCH_TRAILING_4_BYTES (1 << 3)\n\n\n/**\n * To support syscall buffering, we replace syscall instructions with a \"call\"\n * instruction that calls a hook in the preload library to handle the syscall.\n * Since the call instruction takes more space than the syscall instruction,\n * the patch replaces one or more instructions after the syscall instruction as\n * well; those instructions are folded into the tail of the hook function\n * and we have multiple hook functions, each one corresponding to an\n * instruction that follows a syscall instruction.\n * Each instance of this struct describes an instruction that can follow a\n * syscall and a hook function to patch with.\n *\n * This is not (and must not ever be) used during replay so we can change it\n * without bumping SYSCALLBUF_PROTOCOL_VERSION.\n */\nstruct syscall_patch_hook {\n  uint8_t flags;\n  uint8_t patch_region_length;\n  /* Avoid any padding or anything that would make the layout arch-specific. */\n  uint8_t patch_region_bytes[14];\n  uint64_t hook_address;\n};\n\n/**\n * We buffer mprotect syscalls. Their effects need to be noted so we can\n * update AddressSpace's cache of memory layout, which stores prot bits. So,\n * the preload code builds a list of mprotect_records corresponding to the\n * mprotect syscalls that have been buffered. This list is read by rr whenever\n * we flush the syscallbuf, and its effects performed. The actual mprotect\n * syscalls are performed during recording and replay.\n *\n * We simplify things by making this arch-independent.\n */\nstruct mprotect_record {\n  uint64_t start;\n  uint64_t size;\n  int32_t prot;\n  int32_t padding;\n};\n\nenum ContextSwitchEventStrategy {\n  STRATEGY_SW_CONTEXT_SWITCHES,\n  STRATEGY_RECORD_SWITCH\n};\n\n/**\n * Must be arch-independent.\n * Variables used to communicate between preload and rr.\n * We package these up into a single struct to simplify the preload/rr\n * interface.\n * You can add to the end of this struct without breaking trace compatibility,\n * but don't move existing fields. Do not write to it during replay except for\n * the 'in_replay' field. Be careful reading fields during replay as noted\n * below, since they don't all exist in all trace versions.\n */\nstruct preload_globals {\n  /* RESERVED in current versions of rr.\n   *\n   * QUIRK: With UsesGlobalsInReplayQuirk:\n   * 0 during recording, 1 during replay. Set by rr.\n   * This MUST NOT be used in conditional branches. It should only be used\n   * as the condition for conditional moves so that control flow during replay\n   * does not diverge from control flow during recording.\n   * We also have to be careful that values different between record and replay\n   * don't accidentally leak into other memory locations or registers.\n   * USE WITH CAUTION.\n   */\n  unsigned char reserved_legacy_in_replay;\n  /* 0 during recording and replay, 1 during diversion. Set by rr.\n   */\n  unsigned char in_diversion;\n  /* 1 if chaos mode is enabled. DO NOT READ from rr during replay, because\n     this field is not initialized in old traces. */\n  unsigned char in_chaos;\n  /* The signal to use for desched events */\n  unsigned char desched_sig;\n  /* RESERVED */\n  int reserved;\n  /**\n   * Set by rr.\n   * For each fd, indicate a class that is valid for all fds with the given\n   * number in all tasks that share this address space. For fds >=\n   * SYSCALLBUF_FDS_DISABLED_SIZE - 1, the class is given by by\n   * syscallbuf_fd_class[SYSCALLBUF_FDS_DISABLED_SIZE - 1]. See the\n   */\n  VOLATILE char syscallbuf_fd_class[SYSCALLBUF_FDS_DISABLED_SIZE];\n\n  /* WARNING! SYSCALLBUF_FDS_DISABLED_SIZE can change, so\n     access to the following fields during replay is dangerous. Use\n     PRELOAD_GLOBALS_FIELD_AFTER_SYSCALLBUF_FDS_DISABLED or something\n     like it! */\n  /* mprotect records. Set by preload. Use\n     PRELOAD_GLOBALS_FIELD_AFTER_SYSCALLBUF_FDS_DISABLED to access. */\n  struct mprotect_record mprotect_records[MPROTECT_RECORD_COUNT];\n  /* Random seed that can be used for various purposes. DO NOT READ from rr\n     during replay, because this field does not exist in old traces. */\n  uint64_t random_seed;\n  /* RESERVED in current versions of rr.\n   *\n   * QUIRK: With UsesGlobalsInReplayQuirk:\n   * Indicates the value (in 8-byte increments) at which to raise a SIGSEGV\n   * trap once reached. NOTE: This remains constant during record, and is\n   * used only during replay. The same restrictions as in_replay above apply.\n   *\n   * Use PRELOAD_GLOBALS_FIELD_AFTER_SYSCALLBUF_FDS_DISABLED to access during\n   * replay. */\n  uint64_t reserved_legacy_breakpoint_value;\n  /* Indicates whether or not all tasks in this address space have the same\n     fd table. Set by rr during record (modifications are recorded).\n     Read by the syscallbuf. Not read during replay. */\n  unsigned char fdt_uniform;\n  /* The CPU we're bound to, if any; -1 if not bound. Not read during replay. */\n  int32_t cpu_binding;\n  enum ContextSwitchEventStrategy context_switch_event_strategy;\n};\n\n/**\n * Represents syscall params.  Makes it simpler to pass them around,\n * and avoids pushing/popping all the data for calls.\n */\nTEMPLATE_ARCH\nstruct syscall_info {\n  SIGNED_LONG no;\n  SIGNED_LONG args[6];\n};\n\nTEMPLATE_ARCH\nstruct robust_list_info {\n  PTR(void) head;\n  uint32_t len;\n};\n\nTEMPLATE_ARCH\nstruct rseq_info {\n  PTR(void) rseq;\n  uint32_t len;\n  uint32_t sig;\n};\n\n/**\n * Can be architecture dependent. The rr process does not manipulate\n * these except to save and restore the values on task switches so that\n * the values are always effectively local to the current task. rr also\n * sets the |syscallbuf_stub_alt_stack| field.\n * We use this instead of regular libc TLS because sometimes buggy application\n * code breaks libc TLS for some tasks. With this approach we can be sure\n * thread-locals are usable for any task in any state.\n */\nTEMPLATE_ARCH\nstruct preload_thread_locals {\n  /* The offset of this field MUST NOT CHANGE, it is part of the preload ABI\n   * rr depends on.\n   * Offset of this field is hardcoded in syscall_hook.S and\n   * assembly_templates.py.\n   * Pointer to alt-stack used by syscallbuf stubs (allocated at the end of\n   * the scratch buffer.\n   */\n  PTR(void) syscallbuf_stub_alt_stack;\n  /* The offset of this field MUST NOT CHANGE, it is part of the preload ABI\n   * tools can depend on.\n   * Where syscall result will be (or during replay, has been) saved.\n   */\n  PTR(int64_t) pending_untraced_syscall_result;\n  /* The offset of this field MUST NOT CHANGE, it is part of the preload ABI\n   * rr depends on.\n   * Scratch space used by stub code.\n   */\n  PTR(void) stub_scratch_1;\n  /* The offset of this field MUST NOT CHANGE, it is part of the preload ABI\n   * rr depends on.\n   */\n  int32_t alt_stack_nesting_level;\n  /* Syscall hook saved flags (bottom 16 bits only) */\n  int32_t saved_flags;\n  /* The offset of this field MUST NOT CHANGE, it is part of the preload ABI\n   * rr depends on. It contains the parameters to the patched syscall, or\n   * zero if we're not processing a buffered syscall. Do not depend on this\n   * existing during replay, some traces with SYSCALLBUF_PROTOCOL_VERSION 0\n   * don't have it.\n   */\n  PTR_ARCH(const struct syscall_info) original_syscall_parameters;\n\n  /* Nonzero when thread-local state like the syscallbuf has been\n   * initialized.  */\n  int32_t thread_inited;\n  /* The offset of this field MUST NOT CHANGE, it is part of the ABI tools\n   * depend on. When buffering is enabled, points at the thread's mapped buffer\n   * segment.  At the start of the segment is an object of type |struct\n   * syscallbuf_hdr|, so |buffer| is also a pointer to the buffer\n   * header. */\n  PTR(uint8_t) buffer;\n  UNSIGNED_LONG buffer_size;\n  /* This is used to support the buffering of \"may-block\" system calls.\n   * The problem that needs to be addressed can be introduced with a\n   * simple example; assume that we're buffering the \"read\" and \"write\"\n   * syscalls.\n   *\n   *  o (Tasks W and R set up a synchronous-IO pipe open between them; W\n   *    \"owns\" the write end of the pipe; R owns the read end; the pipe\n   *    buffer is full)\n   *  o Task W invokes the write syscall on the pipe\n   *  o Since write is a buffered syscall, the seccomp filter traps W\n   *    directly to the kernel; there's no trace event for W delivered\n   *    to rr.\n   *  o The pipe is full, so W is descheduled by the kernel because W\n   *    can't make progress.\n   *  o rr thinks W is still running and doesn't schedule R.\n   *\n   * At this point, progress in the recorded application can only be\n   * made by scheduling R, but no one tells rr to do that.  Oops!\n   *\n   * Thus enter the \"desched counter\".  It's a perf_event for the \"sw t\n   * switches\" event (which, more precisely, is \"sw deschedule\"; it\n   * counts schedule-out, not schedule-in).  We program the counter to\n   * deliver a signal to this task when there's new counter data\n   * available.  And we set up the \"sample period\", how many descheds\n   * are triggered before the signal is delivered, to be \"1\".  This\n   * means that when the counter is armed, the next desched (i.e., the\n   * next time the desched counter is bumped up) of this task will\n   * deliver the signal to it.  And signal delivery always generates a\n   * ptrace trap, so rr can deduce that this task was descheduled and\n   * schedule another.\n   *\n   * The description above is sort of an idealized view; there are\n   * numerous implementation details that are documented in\n   * handle_signal.c, where they're dealt with. */\n  int32_t desched_counter_fd;\n  int32_t cloned_file_data_fd;\n  SIGNED_LONG cloned_file_data_offset;\n  PTR(void) scratch_buf;\n  UNSIGNED_LONG usable_scratch_size;\n\n  PTR(struct msghdr) notify_control_msg;\n\n  /* The offset of this field MUST NOT CHANGE, it is part of the preload ABI\n   * rr depends on, on ARM.\n   */\n  uint8_t stub_scratch_2[PRELOAD_THREAD_LOCAL_SCRATCH2_SIZE];\n\n  /** When the size is non-zero, there has been a buffered set_robust_list\n   * that must be accounted for. Set by preload code only, read by rr\n   * only during recording.\n   */\n  EMBED_STRUCT(robust_list_info) robust_list;\n\n  /** True when either a buffered rseq or unbuffered rseq has been called\n   * for this thread. Set by rr for buffered rseq and preload for unbuffered\n   * rseq. */\n  int32_t rseq_called;\n\n  /** When the len is non-zero, there has been a buffered rseq\n   * that must be accounted for. Set by preload code only, read by rr\n   * only during recording.\n   */\n  EMBED_STRUCT(rseq_info) rseq;\n};\n#if defined(__aarch64__) && (defined(RR_IMPLEMENT_PRELOAD) || \\\n                             defined(RR_IMPLEMENT_AUDIT))\n// On aarch64, we the stub_scratch_2 offset is hardcoded in the syscallbuf code\n_Static_assert(offsetof(struct preload_thread_locals, stub_scratch_2) == 8 * 13,\n               \"stub_scratch_2 offset mismatch\");\n#endif\n\n// The set of flags that can be set for each fd in syscallbuf_fds_disabled.\nenum syscallbuf_fd_classes {\n  // fd is invalid, all syscalls will error (syscallbuf internal use only)\n  FD_CLASS_INVALID = -1,\n  // The fd is allowed to be completely untraced. No notification to the\n  // syscall buf is required.\n  FD_CLASS_UNTRACED = 0x0,\n  // This is the most conservative option. All operations on this fd are\n  // always traced. If there is a conflict between other options, this one\n  // should be chosen.\n  FD_CLASS_TRACED   = 0x1,\n  // This fd either refers to a /proc/<pid>/mem or is untrace (if this as\n  // is shared with another fd table)\n  FD_CLASS_PROC_MEM = 0x2,\n};\n\n#define CURRENT_INIT_PRELOAD_PARAMS_VERSION 2\n\n/**\n * Packs up the parameters passed to |SYS_rrcall_init_preload|.\n * We use this struct because it's a little cleaner.\n * When evolving this struct, add new fields at the end and don't\n * depend on them during replay.\n */\nTEMPLATE_ARCH\nstruct rrcall_init_preload_params {\n  /* All \"In\" params. */\n  /* The syscallbuf lib's idea of whether buffering is enabled.\n   * We let the syscallbuf code decide in order to more simply\n   * replay the same decision that was recorded. */\n  int syscallbuf_enabled;\n  int syscall_patch_hook_count;\n  PTR(struct syscall_patch_hook) syscall_patch_hooks;\n  PTR(void) unused;\n  PTR(void) syscallbuf_code_start;\n  PTR(void) syscallbuf_code_end;\n  PTR(void) get_pc_thunks_start;\n  PTR(void) get_pc_thunks_end;\n  PTR(void) syscallbuf_final_exit_instruction;\n  PTR(struct preload_globals) globals;\n  union {\n    struct {\n    /* Address of the first entry of the breakpoint table.\n     * After processing a sycallbuf record (and unlocking the syscallbuf),\n     * we call a function in this table corresponding to the record processed.\n     * rr can set a breakpoint in this table to break on the completion of a\n     * particular syscallbuf record.\n     * This method of setting the breakpoint is deprecated. Instead, use the\n     * interface below. It is retained for compatibility */\n      PTR(void) breakpoint_table;\n      int breakpoint_table_entry_size;\n    };\n    struct {\n      PTR(void) breakpoint_instr_addr;\n      // Set of -1 to indicate non-legacy mode\n      int breakpoint_mode_sentinel;\n    };\n  };\n  PTR(void) syscallbuf_syscall_hook;\n};\n\n/**\n * Packs up the inout parameters passed to |SYS_rrcall_init_buffers|.\n * We use this struct because there are too many params to pass\n * through registers on at least x86.  (It's also a little cleaner.)\n */\nTEMPLATE_ARCH\nstruct rrcall_init_buffers_params {\n  /* The fd we're using to track desched events. */\n  int desched_counter_fd;\n  /* \"Out\" params. */\n  int cloned_file_data_fd;\n  /* Returned pointer to and size of the shared syscallbuf\n   * segment. */\n  PTR(void) syscallbuf_ptr;\n  /* Returned pointer to rr's syscall scratch buffer */\n  PTR(void) scratch_buf;\n  uint32_t syscallbuf_size;\n  uint32_t usable_scratch_size;\n};\n\n/**\n * The syscall buffer comprises an array of these variable-length\n * records, along with the header below.\n */\nstruct syscallbuf_record {\n  /* Return value from the syscall.  This can be a memory\n   * address, so must be as big as a memory address can be.\n   * We use 64 bits rather than make syscallbuf_record Arch-specific as that\n   * gets cumbersome.\n   */\n  int64_t ret;\n  /* Syscall number.\n   *\n   * NB: the x86 linux ABI has 350 syscalls as of 3.9.6 and\n   * x86-64 defines 313, so this is a pretty safe storage\n   * allocation.  It would be an earth-shattering event if the\n   * syscall surface were doubled in a short period of time, and\n   * even then we would have a comfortable cushion.  Still,\n   *\n   * TODO: static_assert this can hold largest syscall num */\n  uint16_t syscallno;\n  /* Did the tracee arm/disarm the desched notification for this\n   * syscall? */\n  uint8_t desched : 1;\n  /* Does this record require an assist during replay ? */\n  uint8_t replay_assist : 1;\n  uint8_t _flags_padding : 6;\n  uint8_t _padding;\n  /* Size of entire record in bytes: this struct plus extra\n   * recorded data stored inline after the last field, not\n   * including padding.\n   *\n   * TODO: static_assert this can repr >= buffer size */\n  uint32_t size;\n  /* Extra recorded outparam data starts here. */\n  uint8_t extra_data[0];\n};\n\n/**\n * This struct summarizes the state of the syscall buffer.  It happens\n * to be located at the start of the buffer.\n */\nstruct syscallbuf_hdr {\n  /* The number of valid syscallbuf_record bytes in the buffer,\n   * not counting this header.\n   * Make this volatile so that memory writes aren't reordered around\n   * updates to this field. */\n  volatile uint32_t num_rec_bytes;\n  /* Number of mprotect calls since last syscallbuf flush. The last record in\n   * the list may not have been applied yet.\n   */\n  volatile uint32_t mprotect_record_count;\n  /* Number of records whose syscalls have definitely completed.\n   * May be one less than mprotect_record_count.\n   */\n  volatile uint32_t mprotect_record_count_completed;\n  /* True if the current syscall should not be committed to the\n   * buffer, for whatever reason; likely interrupted by\n   * desched. Set by rr. */\n  volatile uint8_t abort_commit;\n  /* True if, next time we exit the syscall buffer hook, libpreload should\n   * execute SYS_rrcall_notify_syscall_hook_exit to give rr the opportunity to\n   * deliver a signal and/or reset the syscallbuf. */\n  volatile uint8_t notify_on_syscall_hook_exit;\n  /* This tracks whether the buffer is currently in use for a\n   * system call or otherwise unavailable. This is helpful when\n   * a signal handler runs during a wrapped system call; we don't want\n   * it to use the buffer for its system calls. The different reasons why the\n   * buffer could be locked, use different bits of this field and the buffer\n   * may be used only if all are clear. See enum syscallbuf_locked_why for\n   * used bits.\n   */\n  volatile uint8_t locked;\n  /* Nonzero when rr needs to worry about the desched signal.\n   * When it's zero, the desched signal can safely be\n   * discarded. */\n  volatile uint8_t desched_signal_may_be_relevant;\n  /* A copy of the tasks's signal mask. Updated by preload when a buffered\n   * rt_sigprocmask executes.\n   */\n  volatile uint64_t blocked_sigs;\n  /* Incremented by preload every time a buffered rt_sigprocmask executes.\n   * Cleared during syscallbuf reset.\n   */\n  volatile uint32_t blocked_sigs_generation;\n  /* Nonzero when preload is in the process of calling an untraced\n   * sigprocmask; the real sigprocmask may or may not match blocked_sigs.\n   */\n  volatile uint8_t in_sigprocmask_critical_section;\n  /* Nonzero when the syscall was aborted during preparation without doing\n   * anything. This is set when a user seccomp filter forces a SIGSYS. */\n  volatile uint8_t failed_during_preparation;\n\n  uint8_t padding[2];\n} __attribute__((__packed__));\n#ifdef __cplusplus\nstatic_assert(sizeof(struct syscallbuf_hdr) % 8 == 0,\n              \"syscallbuf_hdr size must be multiple of 8\");\n#endif\n\n/**\n * Each bit of of syscallbuf_hdr->locked indicates a reason why the syscallbuf\n * is locked. These are all the bits that are currently defined.\n */\nenum syscallbuf_locked_why {\n  /* Used by the tracee, during interruptible syscalls to avoid recursion */\n  SYSCALLBUF_LOCKED_TRACEE = 0x1,\n  /* Used by the tracer to prevent syscall buffering when necessary to preserve\n     semantics (e.g. for ptracees whose syscalls are being observed) */\n  SYSCALLBUF_LOCKED_TRACER = 0x2\n};\n\n/**\n * Return the amount of space that a record of |length| will occupy in\n * the buffer if committed, including padding.\n */\ninline static long stored_record_size(size_t length) {\n  /* Round up to a whole number of 64-bit words. */\n  return (length + 7) & ~7;\n}\n\n/**\n * Return nonzero if an attempted open() of |filename| should be\n * blocked.\n *\n * The background of this hack is that rr doesn't support DRI/DRM\n * currently, so we use the blunt stick of refusing to open this\n * interface file as a way of disabling it entirely.  (In addition to\n * tickling xorg.conf, which doesn't entirely do the trick.)  It's\n * known how to fix this particular, so let's not let this hack grow\n * too much by piling on.\n */\ninline static int is_blacklisted_filename(const char* filename) {\n  const char* f;\n  if (strprefix(\"/dev/dri/\", filename) || streq(\"/dev/nvidiactl\", filename) ||\n      streq(\"/usr/share/alsa/alsa.conf\", filename) ||\n      streq(\"/dev/nvidia-uvm\", filename)) {\n    return 1;\n  }\n  f = extract_file_name(filename);\n  return strprefix(\"rr-test-blacklist-file_name\", f) ||\n         strprefix(\"pulse-shm-\", f);\n}\n\ninline static int is_blacklisted_memfd(const char* name) {\n  return streq(\"pulseaudio\", name);\n}\n\ninline static int is_blacklisted_socket(const char* filename) {\n  /* Blacklist the nscd socket because glibc communicates with the daemon over\n   * shared memory rr can't handle.\n   */\n  return streq(\"/var/run/nscd/socket\", filename);\n}\n\ninline static int is_gcrypt_deny_file(const char* filename) {\n  return streq(\"/etc/gcrypt/hwf.deny\", filename);\n}\n\ninline static int is_terminal(const char* filename) {\n  return strprefix(\"/dev/tty\", filename) || strprefix(\"/dev/pts\", filename);\n}\n\ninline static int is_proc_mem_file(const char* filename) {\n  if (!strprefix(\"/proc/\", filename)) {\n    return 0;\n  }\n  return streq(filename + rrstrlen(filename) - 4, \"/mem\");\n}\n\ninline static int is_proc_fd_dir(const char* filename) {\n  if (!strprefix(\"/proc/\", filename)) {\n    return 0;\n  }\n\n  int len = rrstrlen(filename);\n  const char* fd_bit = filename + len;\n  if (*fd_bit == '/') {\n    fd_bit--;\n  }\n\n  return strprefix(\"/fd\", fd_bit - 3);\n}\n\ninline static int is_sys_cpu_online_file(const char* filename) {\n  return streq(\"/sys/devices/system/cpu/online\", filename);\n}\n\ninline static int is_proc_stat_file(const char* filename) {\n  return streq(\"/proc/stat\", filename);\n}\n\ninline static int is_rr_page_lib(const char* filename) {\n  return streq(extract_file_name(filename), RRPAGE_LIB_FILENAME) ||\n         streq(extract_file_name(filename), RRPAGE_LIB_FILENAME_32);\n}\n\n/**\n * Returns nonzero if an attempted open() of |filename| can be syscall-buffered.\n * When this returns zero, the open must be forwarded to the rr process.\n * |filename| must be absolute.\n * This is imperfect because it doesn't handle hard links and files (re)mounted\n * in different places.\n */\ninline static int allow_buffered_open(const char* filename) {\n  return filename &&\n         !is_blacklisted_filename(filename) && !is_gcrypt_deny_file(filename) &&\n         !is_terminal(filename) && !is_proc_mem_file(filename) &&\n         !is_proc_fd_dir(filename) && !is_sys_cpu_online_file(filename) &&\n         !is_proc_stat_file(filename) && !is_rr_page_lib(filename);\n}\n\n#endif /* RR_PRELOAD_INTERFACE_H_ */\n"
  },
  {
    "path": "src/preload/raw_syscall.S",
    "content": "#if defined(__i386__)\n        .text\n        .globl _raw_syscall\n        .hidden _raw_syscall\n        .type _raw_syscall, @function\n_raw_syscall:     /* syscallno = 4(%esp) */\n        .cfi_startproc\n        pushl %ebx        /* syscallno = 8(%esp) */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %ebx, 0\n        pushl %esi        /* syscallno = 12(%esp) */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %esi, 0\n        pushl %edi        /* syscallno = 16(%esp) */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %edi, 0\n        pushl %ebp        /* syscallno = 20(%esp) */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %ebp, 0\n\n        movl 20(%esp), %eax /* %eax = syscallno */\n        movl 24(%esp), %ebx /* %ebx = a0 */\n        movl 28(%esp), %ecx /* %ecx = a1 */\n        movl 32(%esp), %edx /* %edx = a2 */\n        movl 36(%esp), %esi /* %esi = a3 */\n        movl 40(%esp), %edi /* %edi = a4 */\n        movl 44(%esp), %ebp /* %ebp = a5 */\n\n        pushl 56(%esp)\n        .cfi_adjust_cfa_offset 4\n        pushl 56(%esp)\n        .cfi_adjust_cfa_offset 4\n\n        call *56(%esp)\n\n        addl $8,%esp\n        .cfi_adjust_cfa_offset -8\n        popl %ebp\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %ebp\n        popl %edi\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %edi\n        popl %esi\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %esi\n        popl %ebx\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %ebx\n        ret\n        .cfi_endproc\n        .size _raw_syscall, . - _raw_syscall\n\n#elif defined(__x86_64__)\n        .text\n        .globl _raw_syscall\n        .hidden _raw_syscall\n        .type _raw_syscall, @function\n_raw_syscall:\n        .cfi_startproc\n        /* Incoming args are in %rdi, %rsi, %rdx, %rcx, %r8, %r9, and 8(%rsp).\n\t       Syscall arguments are %rdi, %rsi, %rdx, %r10, %r8, %r9. */\n        movq %rdi, %rax         /* syscall number */\n        movq %rsi, %rdi         /* first syscall arg */\n        movq %rdx, %rsi         /* second syscall arg */\n        movq %rcx, %rdx         /* third syscall arg */\n        movq %r8, %r10          /* fourth syscall arg */\n        movq %r9, %r8           /* fifth syscall arg */\n        movq 8(%rsp), %r9       /* sixth syscall arg */\n\n        pushq 32(%rsp)\n        .cfi_adjust_cfa_offset 8\n        pushq 32(%rsp)\n        .cfi_adjust_cfa_offset 8\n\n        /* During a system call the kernel makes some user-space-visible\n           register changes:\n           a) on entry, %r11 is set to %rflags\n           b) %rcx is sometimes set to -1 (perhaps because of something rr does)\n           c) on entry or exit, some flags are sometimes changed\n           Also, during replay we may perform single-stepping which can set\n           TF (trace flag). We need to hide this.\n\n           fixup_syscall_registers is responsible for fixing up registers\n           to hide these effects when we get a ptrace trap from system calls\n           in the kernel: it clears TF from %r11, forces %rcx to -1, and sets\n           flags to fixed values (ZF+PF+IF+reserved, same as for \"xor reg,reg\").\n           Task::canonicalize_and_set_regs is responsible for fixing up registers\n           when we emulate a system call that was traced during recording (by\n           running to a breakpoint at that system call). It does the above\n           effects after setting %r11 to %rflags.\n\n           For untraced system calls there is no trap to rr during recording or\n           replay, so we must handle these issues here. We do not need\n           untraced system calls to behave exactly the same as traced\n           system calls, since whether a given system call was traced or not is\n           the same whether recording or replaying, but it's a good idea to\n           make them as similar as possible. We do need register values\n           to be perfectly consistent at every instruction in every replay\n           whether or not singlestepping is used (because a ReplayTimeline::mark\n           might be created at any point). During replay, untraced syscall\n           instructions are replaced with \"xor %eax,%eax\".\n\n           The following code is harmless for traced syscalls (and needs to be,\n           because traced syscalls go through here too).\n         */\n\n        /* Set %r11 and %rcx to the values we expect them to have after the\n           system call.\n           Set flags to ZF+PF+IF+reserved (0x246) first. This simplifies\n           everything.\n           This all has to be independent of TF being set at any point during\n           replay! But the way we're doing it here, it's trivial.\n         */\n        xor %ecx,%ecx\n        /* At this point, flags are 0x246 + possibly TF. */\n        movq $0x246,%r11\n        movq $-1,%rcx\n\n        callq *32(%rsp)\n\n        /* At this point, during recording we don't trust the kernel to have\n           restored flags correctly. It probably doesn't matter, but fix it\n           anyway. */\n        xor %ecx,%ecx\n        /* At this point, the high 32 bits of %rcx are unknown. Fix that by\n           setting to -1 to match traced syscalls. */\n        movq $-1,%rcx\n        /* At this point, %r11 is always 0x246 during replay and during\n           recording (because TF is never set during recording). Nothing to\n           fix in %r11. */\n\n        addq $16,%rsp\n        .cfi_adjust_cfa_offset -16\n        ret\n        .cfi_endproc\n        .size _raw_syscall, . - _raw_syscall\n\n#elif defined(__aarch64__)\n        .text\n        .globl _raw_syscall\n        .hidden _raw_syscall\n        .type _raw_syscall, @function\n_raw_syscall:\n        .cfi_startproc\n        // The two stack arguments needs to be at sp + 8 and sp + 16\n        // but they are currently at sp and sp + 8.\n        // Since sp needs to be 16 bytes aligned we need to load and push them again.\n        str x30, [sp, -32]!\n        .cfi_def_cfa_offset 32\n        .cfi_offset x30, -32\n        ldp x8, x30, [sp, 32]\n        stp x8, x30, [sp, 8]\n        mov x8,x0\n        mov x0,x1\n        mov x1,x2\n        mov x2,x3\n        mov x3,x4\n        mov x4,x5\n        mov x5,x6\n        blr x7\n        ldr x30, [sp], 32\n        .cfi_def_cfa_offset 0\n        .cfi_restore x30\n        ret\n        .cfi_endproc\n        .size _raw_syscall, . - _raw_syscall\n#else\n#error unknown CPU architecture\n#endif /* __i386__/__x86_64__ */\n        .global _syscallbuf_code_end\n        .hidden _syscallbuf_code_end\n_syscallbuf_code_end:\n\n        .section .note.GNU-stack,\"\",@progbits\n        .previous\n"
  },
  {
    "path": "src/preload/rr_page.S",
    "content": "// # Layout of the librrpage.so file\n//\n// The `rr page` is a special page mapped in low memory (at RR_PAGE_ADDR) that\n// contains syscall instructions at known ip values. These values must be fixed\n// for all processes in a given rr session, since rr cannot adjust the seccomp\n// filter that makes use of these values once it has been set. `librrpage.so`\n// contains this page, and rr will map it in place at process start and inform\n// the process about it by passing it as the address of the vdso. This way\n// the tracee's unwinders, as well as GDB will load the librrpage.so symbols and\n// unwind info and function correctly if execution is stopped in these locations.\n//\n// The `librrpage.so` file is made up of five pages:\n// 1: The ELF header, dynamic symbol/string table, and eh_frame sections\n// 2: The ELF section, symbol string tables (moved here in a post-processing step)\n// 3: A fake vdso that rr will ask the kernel to treat as the real vdso\n// 4: The rr page to be used during recording\n// 5: The rr page to be used during replay\n//\n// During record, rr will map the first four pages of librrpage.so only.\n// During replay, rr will replace the record page by the replay page.\n// Note however, that we only have one copy of the eh_frame and symbol\n// information - we expect all offsets and unwind instructions to match between\n// the record and replay versions (anything else would likely result in\n// divergences anyway)\n\n#ifdef __i386__\n#define CALL \\\n    int $0x80; \\\n    ret\n#define NOCALL \\\n    xor %eax, %eax; \\\n    ret\n#define TRAP \\\n    nop; int $3; \\\n    ret\n#define PAGE_ALIGN \\\n    .align 0x1000\n#define PRELOAD_LIBRARY_PAGE_SIZE 0x1000\n#elif defined(__x86_64__)\n#define CALL \\\n    syscall; \\\n    ret\n#define NOCALL \\\n    xor %eax, %eax; \\\n    ret\n#define TRAP \\\n    nop; int $3; \\\n    ret\n#define PAGE_ALIGN \\\n    .align 0x1000\n#define PRELOAD_LIBRARY_PAGE_SIZE 0x1000\n#elif defined(__aarch64__)\n#define CALL \\\n    svc #0; \\\n    ret\n#define NOCALL \\\n    movz x0, #0; \\\n    ret\n#define TRAP \\\n    brk #0; \\\n    ret\n#define PAGE_ALIGN \\\n    .align 16\n#define PRELOAD_LIBRARY_PAGE_SIZE 0x10000\n#endif\n\n.section .sh_placeholder, \"a\"\nPAGE_ALIGN\n.fill PRELOAD_LIBRARY_PAGE_SIZE, 1, 0xff\n\n#include \"rr_vdso.S\"\n\n.section .record.text, \"a\", @progbits\nPAGE_ALIGN\n\n.global rr_page_start\nrr_page_start:\n\n#define LABEL(name) #name:;\n#define STARTPROC(name) #name:; .cfi_startproc\n#define STARTPROC_GLOBAL(name) .global #name; #name:; .cfi_startproc\n#define CFI_ENDPROC .cfi_endproc\n#include \"rr_page_instructions.S\"\n\n.section .replay.text, \"\", @progbits\nPAGE_ALIGN\nreplay_page:\n// No CFI instructions or symbols for the replay page - we'll implicitly share\n// those of the record copy\n#undef LABEL\n#undef STARTPROC\n#undef CFI_ENDPROC\n#define LABEL(name)\n#define STARTPROC(name)\n#define CFI_ENDPROC\n#define IS_REPLAY 1\n#include \"rr_page_instructions.S\"\n"
  },
  {
    "path": "src/preload/rr_page.ld.in",
    "content": "PHDRS\n{\n  text PT_LOAD FLAGS(5) FILEHDR PHDRS;\n  dynamic PT_DYNAMIC FLAGS(4);\n  note PT_NOTE FLAGS(4);\n  eh_frame 0x6474e550;\n  replay PT_NULL;\n}\nSECTIONS\n{\n  rr_page_start = 3 * @PRELOAD_LIBRARY_PAGE_SIZE@;\n  . = SIZEOF_HEADERS;\n  .eh_frame_hdr   : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } :text :eh_frame\n  .eh_frame       : { KEEP (*(.eh_frame)) *(.eh_frame.*) } :text :eh_frame\n  .note.gnu.build-id  : { *(.note.gnu.build-id) } :text :note\n  .note.gnu.property : { *(.note.gnu.property) } :text :note\n  .hash           : { *(.hash) } :text\n  .gnu.hash       : { *(.gnu.hash) } :text\n  .dynsym         : { *(.dynsym) } :text\n  .dynstr         : { *(.dynstr) } :text\n  .dynamic        : { *(.dynamic) } :text :dynamic\n  .gnu.version    : { *(.gnu.version) } :text\n  .gnu.version_d  : { *(.gnu.version_d) } :text\n  .gnu.version_r  : { *(.gnu.version_r) } :text\n  .got            : { *(.got) } :text\n  .got.plt        : { *(.got.plt) } :text\n  . = rr_page_start - 2 * @PRELOAD_LIBRARY_PAGE_SIZE@;\n  /* This space in .sh_placeholder is reserved for the section table\n     symtab/strtab, which ordinarily go after the text sections,\n     but we need to have before the rr page.\n     We move it there in a post-processing step, since linker\n     scripts can't specify these locations for legacy reasons */\n  .sh_placeholder : { *(.sh_placeholder) } :text\n  . = rr_page_start - @PRELOAD_LIBRARY_PAGE_SIZE@;\n  .plt       : { *(.plt) } :text\n  .vdso.text : { *(.vdso.text) } :text\n  . = rr_page_start;\n  .record.text : { *(.record.text) } :text\n  . = rr_page_start + @PRELOAD_LIBRARY_PAGE_SIZE@;\n  .replay.text : { *(.replay.text) } :replay\n  /DISCARD/ : { *(.debug_* ) }\n}\n\nVERSION {\n  @VDSO_NAME@ {\n    global:\n      @VDSO_SYMBOLS@\n  };\n}\n"
  },
  {
    "path": "src/preload/rr_page_instructions.S",
    "content": "// See rr_page.S\n\n#ifdef IS_REPLAY\n#define REPLAY_ONLY_CALL CALL\n#define RECORD_ONLY_CALL NOCALL\n#else\n#define REPLAY_ONLY_CALL NOCALL\n#define RECORD_ONLY_CALL CALL\n#endif\n\nSTARTPROC(syscall_traced)\n    CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_priv_traced)\n    CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_untraced)\n    CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_untraced_replay_only)\n    REPLAY_ONLY_CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_untraced_record_only)\n    RECORD_ONLY_CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_priv_untraced)\n    CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_priv_untraced_replay_only)\n    REPLAY_ONLY_CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_priv_untraced_record_only)\n    RECORD_ONLY_CALL\n    CFI_ENDPROC\nSTARTPROC(syscall_untraced_replay_assist)\n#ifdef IS_REPLAY\n    TRAP\n#else\n    CALL\n#endif\n    CFI_ENDPROC\n\nLABEL(in_replay_flag)\n#ifdef IS_REPLAY\n    .byte 0x01\n#else\n    .byte 0x00\n#endif\n.byte 0x00, 0x00, 0x00\n\n// During replay, we put the breakpoint_value here. During record this remains\n// as -1, giving us 8 ff bytes at a well known address during record. These are used\n// during exit.\nLABEL(breakpoint_value)\nLABEL(ff_bytes)\n.byte 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff\n\n// ABI stability ends here.\n\n#undef REPLAY_ONLY_CALL\n#undef RECORD_ONLY_CALL\n"
  },
  {
    "path": "src/preload/rr_vdso.S",
    "content": "#ifdef __aarch64__\n#define STARTPROC_GLOBAL(name) .globl #name; .type #name, @function; \\\n #name:; .cfi_startproc\n#else\n#define STARTPROC_GLOBAL(name) .global #name; .type #name, @function; \\\n #name:; .cfi_startproc\n#endif\n#define CFI_ENDPROC .cfi_endproc\n\n// Older libs don't use the __vdso symbols, but try to look for the syscall\n// names directly. Follow the kernel vdso and make them weak aliases\n#define WEAK_ALIAS(sym, target) .weak sym; .set sym, target\n\n#if defined(__x86_64__)\n\n.section .plt, \"a\", @progbits\nPAGE_ALIGN\n\n// Current address is 0x70000000 - PRELOAD_LIBRARY_PAGE_SIZE\n// The following is equal to __rr_dl_runtime_resolve_prelude,\n// but doesn't introduce a relocation record.\n.quad  0x70000000 - PRELOAD_LIBRARY_PAGE_SIZE + 8\n\nSTARTPROC_GLOBAL(__rr_dl_runtime_resolve_prelude)\nfstenv -32(%rsp)\nmovq $0,-12(%rsp)\nfldenv -32(%rsp)\nxchg (%rsp),%rbx\n# r11 is destroyed anyway by _dl_runtime_resolve, so we can use it here.\nmov %rbx,%r11\nmov %rsp,%rbx\nand $0xffffffffffffffc0,%rsp\npush %r11\nret\nCFI_ENDPROC\n\n.section .vdso.text, \"a\", @progbits\n\n#define SYSCALL(which) \\\n    movq $which, %rax;  \\\n    syscall; \\\n    nop; \\\n    nop; \\\n    nop; \\\n    retq\n\nSTARTPROC_GLOBAL(__vdso_clock_getres)\nSYSCALL(229)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_getcpu)\nSYSCALL(309)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_time)\nSYSCALL(201)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_clock_gettime)\nSYSCALL(228)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_gettimeofday)\nSYSCALL(96)\nCFI_ENDPROC\n\nWEAK_ALIAS(clock_getres, __vdso_clock_getres)\nWEAK_ALIAS(getcpu, __vdso_getcpu)\nWEAK_ALIAS(time, __vdso_time)\nWEAK_ALIAS(clock_gettime, __vdso_clock_gettime)\nWEAK_ALIAS(gettimeofday,__vdso_gettimeofday)\n\n.symver gettimeofday,gettimeofday@LINUX_2.6\n.symver clock_gettime,clock_gettime@LINUX_2.6\n.symver __vdso_gettimeofday,__vdso_gettimeofday@LINUX_2.6\n.symver __vdso_clock_getres,__vdso_clock_getres@LINUX_2.6\n.symver __vdso_time,__vdso_time@LINUX_2.6\n.symver __vdso_clock_gettime,__vdso_clock_gettime@LINUX_2.6\n.symver __vdso_getcpu,__vdso_getcpu@LINUX_2.6\n\n#elif defined(__i386__)\n\n.section .vdso.text, \"a\", @progbits\nPAGE_ALIGN\n\n// __vdso functions use the C calling convention, so\n// we have to set up the syscall parameters here.\n// No x86-32 __vdso functions take more than two parameters.\n#define SYSCALL(which) \\\n    push %ebx; \\\n    .cfi_adjust_cfa_offset 4; \\\n    .cfi_rel_offset %ebx, 0; \\\n    mov 8(%esp),%ebx; \\\n    mov 12(%esp),%ecx; \\\n    mov $which, %eax;  \\\n    int $0x80; \\\n    nop; \\\n    nop; \\\n    nop; \\\n    pop %ebx; \\\n    .cfi_adjust_cfa_offset -4; \\\n    .cfi_restore %ebx; \\\n    ret\n\n// N.B.: We depend on this being the first symbol in the vdso page.\nSTARTPROC_GLOBAL(__kernel_vsyscall)\nint $0x80\nnop\nnop\nnop\nret\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_clock_getres)\nSYSCALL(266)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_time)\nSYSCALL(13)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_clock_gettime)\nSYSCALL(265)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_clock_gettime64)\nSYSCALL(403)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__vdso_gettimeofday)\nSYSCALL(78)\nCFI_ENDPROC\n\nWEAK_ALIAS(clock_getres, __vdso_clock_getres)\nWEAK_ALIAS(time, __vdso_time)\nWEAK_ALIAS(clock_gettime, __vdso_clock_gettime)\nWEAK_ALIAS(clock_gettime64, __vdso_clock_gettime64)\nWEAK_ALIAS(gettimeofday,__vdso_gettimeofday)\n\n.symver __vdso_gettimeofday,__vdso_gettimeofday@LINUX_2.6\n.symver __vdso_clock_getres,__vdso_clock_getres@LINUX_2.6\n.symver __vdso_time,__vdso_time@LINUX_2.6\n.symver __vdso_clock_gettime,__vdso_clock_gettime@LINUX_2.6\n.symver __vdso_getcpu,__vdso_getcpu@LINUX_2.6\n\n#elif defined(__aarch64__)\n\n.section .vdso.text, \"a\", @progbits\nPAGE_ALIGN\n\n#define SYSCALL(which)          \\\n        mov     x8, which;      \\\n        svc     0;              \\\n        ret\n\nSTARTPROC_GLOBAL(__kernel_clock_getres)\nSYSCALL(114)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__kernel_rt_sigreturn)\nSYSCALL(139)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__kernel_gettimeofday)\nSYSCALL(169)\nCFI_ENDPROC\nSTARTPROC_GLOBAL(__kernel_clock_gettime)\nSYSCALL(113)\nCFI_ENDPROC\n\n#else\n\n#error \"VDSO Hooks not defined for this platform\"\n\n#endif\n\n#undef STARTPROC_GLOBAL\n#undef CFI_ENDPROC\n"
  },
  {
    "path": "src/preload/rrcalls.h",
    "content": "/* \"Magic\" (rr-implemented) syscalls that we use to initialize the\n * syscallbuf.\n *\n * NB: magic syscalls must be positive, because with at least linux\n * 3.8.0 / eglibc 2.17, rr only gets a trap for the *entry* of invalid\n * syscalls, not the exit.  rr can't handle that yet. */\n/* TODO: static_assert(LAST_SYSCALL < SYS_rrcall_init_buffers) */\n\n#define RR_CALL_BASE 1000\n\n/**\n * The preload library calls SYS_rrcall_init_preload during its\n * initialization.\n */\n#define SYS_rrcall_init_preload RR_CALL_BASE\n/**\n * The preload library calls SYS_rrcall_init_buffers in each thread that\n * gets created (including the initial main thread).\n */\n#define SYS_rrcall_init_buffers (RR_CALL_BASE + 1)\n/**\n * The preload library calls SYS_rrcall_notify_syscall_hook_exit when\n * unlocking the syscallbuf and notify_after_syscall_hook_exit has been set.\n * The word at 4/8(sp) is returned in the syscall result and the word at\n * 8/16(sp) is stored in original_syscallno.\n */\n#define SYS_rrcall_notify_syscall_hook_exit (RR_CALL_BASE + 2)\n/**\n * When the preload library detects that control data has been received in a\n * syscallbuf'ed recvmsg, it calls this syscall with a pointer to the\n * 'struct msg' returned.\n */\n#define SYS_rrcall_notify_control_msg (RR_CALL_BASE + 3)\n/**\n * When rr replay has restored the auxv vectors for a new process (completing\n * emulation of exec), it calls this syscall. It takes one parameter, the tid\n * of the task that it has restored auxv vectors for.\n */\n#define SYS_rrcall_reload_auxv (RR_CALL_BASE + 4)\n/**\n * When rr replay has flushed a syscallbuf 'mprotect' record, notify any outer\n * rr of that flush. The first parameter is the tid of the task, the second\n * parameter is the address, the third parameter is the length, and the\n * fourth parameter is the prot.\n */\n#define SYS_rrcall_mprotect_record (RR_CALL_BASE + 5)\n/**\n * The audit library calls SYS_rrcall_notify_stap_semaphore_added once a batch\n * of SystemTap semaphores have been incremented. The first parameter is the\n * beginning of an address interval containing semaphores (inclusive) and the\n * second parameter is the end of the address interval (exclusive).\n *\n * In practice a particular probe may be listed in an object's notes more than\n * once, so be prepared to handle overlapping or redundant intervals.\n */\n#define SYS_rrcall_notify_stap_semaphore_added (RR_CALL_BASE + 6)\n/**\n * The audit library calls SYS_rrcall_notify_stap_semaphore_removed once a\n * batch of previously-incremented SystemTap semaphores have been decremented.\n * The first parameter is the beginning of an address interval containing\n * semaphores (inclusive) and the second parameter is the end of the address\n * interval (exclusive).\n *\n * In practice a particular probe may be listed in an object's notes more than\n * once, so be prepared to handle overlapping or redundant intervals.\n */\n#define SYS_rrcall_notify_stap_semaphore_removed (RR_CALL_BASE + 7)\n/**\n * This syscall can be used be the application being recorded to check for the\n * presence of the rr recorder. It is used e.g. to enable nested recording of\n * rr itself. Use of this syscall should be limited to situations where it is\n * absolutely necessary to avoid deviation of behavior depending on the\n * presence of absence of rr.\n */\n#define SYS_rrcall_check_presence (RR_CALL_BASE + 8)\n   /*\n    * If `arg1` is `RRCALL_CHECK_SYSCALLBUF_USED_OR_DISABLED`,\n    * SYS_rrcall_check_presence returns 0 only if\n    * 1) The syscallbuf was used to service the syscall\n    * 2) The syscallbuf is disabled\n    *\n    * Otherwise returns ENOTSUP.\n    */\n    #define RRCALL_CHECK_SYSCALLBUF_USED_OR_DISABLED 1\n/**\n * Requests that rr detach from this process and re-create outside of its\n * process tree, such that it may run without seccomp.\n */\n#define SYS_rrcall_detach_teleport (RR_CALL_BASE + 9)\n/**\n * Requests that rr reset the time slice signal to the\n * requested period. Used for testing interaction corner\n * cases between the time slice signal and other rr behavior.\n */\n#define SYS_rrcall_arm_time_slice (RR_CALL_BASE + 10)\n/**\n * Use as\n *\n *  int rr_freeze_tid(pid_t tid, int freeze) {\n *      return syscall(SYS_rrcall_freeze_tid, tid, freeze, 0, 0, 0, 0); }\n *\n * With `freeze=1`, requests that rr's Scheduler not schedule task `tid` again\n * until unfrozen using `rr_freeze_tid(tid, 0)`. Note that kernel scheduling\n * behavior is unaffected. Used for testing Scheduler-sensitive scenarios.\n */\n#define SYS_rrcall_freeze_tid (RR_CALL_BASE + 11)\n/**\n * Requests a simulated (buffered) RDTSC.\n * The RDTSC value is returned as a 64-bit value stored in the\n * memory location given by the first argument. RAX returns 0.\n */\n#define SYS_rrcall_rdtsc (RR_CALL_BASE + 12)"
  },
  {
    "path": "src/preload/syscall_hook.S",
    "content": "#if defined(__aarch64__)\n        .set preload_thread_locals,0x70010000\n#else\n        .set preload_thread_locals,0x70001000\n#endif\n\n        .global _syscallbuf_code_start\n        .hidden _syscallbuf_code_start\n\n        .global _syscallbuf_final_exit_instruction\n        .hidden _syscallbuf_final_exit_instruction\n        .type _syscallbuf_final_exit_instruction, @function\n\n#define DW_OP_CONST4U(val)                      \\\n        0x0c, /* DW_OP_const4u */               \\\n        /* Individually place bytes */          \\\n        (val) & 0xFF,                           \\\n        ((val) & (0xFF <<  0x8)) >>  0x8,       \\\n        ((val) & (0xFF << 0x10)) >> 0x10,       \\\n        ((val) & (0xFF << 0x18)) >> 0x18\n\n#define DW_OP_CONST8U(val)                      \\\n        0x0e, /* DW_OP_const8u */               \\\n        /* Individually place bytes */          \\\n        (val) & 0xFF,                           \\\n        ((val) & (0xFF <<  0x8)) >>  0x8,       \\\n        ((val) & (0xFF << 0x10)) >> 0x10,       \\\n        ((val) & (0xFF << 0x18)) >> 0x18,       \\\n        ((val) & (0xFF << 0x20)) >> 0x20,       \\\n        ((val) & (0xFF << 0x28)) >> 0x28,       \\\n        ((val) & (0xFF << 0x30)) >> 0x30,       \\\n        ((val) & (0xFF << 0x38)) >> 0x38\n\n#define REG_AT_ADDR32(reg, addr)                                \\\n        .cfi_escape 0x10, /* DW_CFA_expression */               \\\n                    reg,                                        \\\n                    0x05, /* 5 byte expression follows */       \\\n                    DW_OP_CONST4U(addr)\n#define REG_AT_ADDR64(reg, addr)                                \\\n        .cfi_escape 0x10, /* DW_CFA_expression */               \\\n                    reg,                                        \\\n                    0x09, /* 9 byte expression follows */       \\\n                    DW_OP_CONST8U(addr)\n\n// 10 bytes LEB128 is enough to encode 64bit integer and we shouldn't\n// really need anything longer than that.\n#define COUNT_LEB128(lebs...)                                   \\\n        _COUNT_LEB128(lebs, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1)\n#define _COUNT_LEB128(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N\n\n#define REG_AT_REG_OFFSET(reg, base, lebs...)                                   \\\n        .cfi_escape 0x10, /* DW_CFA_expression */                               \\\n                    reg,                                                        \\\n                    (COUNT_LEB128(lebs) + 1), /* 1 byte + LEB128 bytes */       \\\n                    (0x70 + base), /* DW_OP_breg0 + base */                     \\\n                    lebs\n\n#if defined(__i386__)\n.text\n.set syscallbuf_stub_alt_stack, preload_thread_locals\n.set stub_scratch_1, preload_thread_locals + 8\n.set alt_stack_nesting_level, preload_thread_locals + 12\n.set saved_flags, preload_thread_locals + 16\n\n.p2align 4\n\n_syscallbuf_code_start:\n/* Insert a NOP here so we have no symbol clashes. Otherwise\n   in some configurations (gdb 7.7.1, Ubuntu 14.04) gdb sometimes gets confused.\n */\n        nop\n\n\n_syscallbuf_final_exit_instruction:\n        jmp *(stub_scratch_1)\n\n_syscall_hook_trampoline:\n        .cfi_startproc\n        /* Build a |struct syscall_info| by pushing all the syscall\n         * args and the number onto the stack. */\n                          /* struct syscall_info info; */\n        pushl %ebp        /* info.args[5] = $ebp; */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %ebp, 0\n        pushl %edi        /* info.args[4] = $edi; */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %edi, 0\n        pushl %esi        /* info.args[3] = $esi; */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %esi, 0\n        pushl %edx        /* info.args[2] = $edx; */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %edx, 0\n        pushl %ecx        /* info.args[1] = $ecx; */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %ecx, 0\n        pushl %ebx        /* info.args[0] = $ebx; */\n        .cfi_adjust_cfa_offset 4\n        .cfi_rel_offset %ebx, 0\n        pushl %eax        /* info.no = $eax; */\n        .cfi_adjust_cfa_offset 4\n\n        /* $esp points at &info.  Push that pointer on the stack as\n         * our arg for vsyscall_hook().\n         * Use %ebp as our temporary CFA register here. Don't use %ebx or\n         * any other GP register, since x86-64 gdb 7.7 (at least) treats all GP\n         * regs other than %esp/%ebp as *signed* and sign-extends their values.\n         * Having some CFA values sign-extended and others not breaks gdb\n         * stack walking.\n         */\n        movl %esp, %ebp\n        .cfi_def_cfa_register %ebp\n\n        /* Align stack to 16 bytes */\n        and $0xfffffff0,%esp\n\n        /* Save XMM registers */\n        sub $0x80,%esp\n        movdqa %xmm0,(%esp)\n        movdqa %xmm1,0x10(%esp)\n        movdqa %xmm2,0x20(%esp)\n        movdqa %xmm3,0x30(%esp)\n        movdqa %xmm4,0x40(%esp)\n        movdqa %xmm5,0x50(%esp)\n        movdqa %xmm6,0x60(%esp)\n        movdqa %xmm7,0x70(%esp)\n\n        sub $12,%esp\n        pushl %ebp\n\n        call syscall_hook\n        /* $eax = vsyscall_hook(&info); */\n\n        movdqa 0x10(%esp),%xmm0\n        movdqa 0x20(%esp),%xmm1\n        movdqa 0x30(%esp),%xmm2\n        movdqa 0x40(%esp),%xmm3\n        movdqa 0x50(%esp),%xmm4\n        movdqa 0x60(%esp),%xmm5\n        movdqa 0x70(%esp),%xmm6\n        movdqa 0x80(%esp),%xmm7\n\n        mov $saved_flags, %esp\n        popfw\n        /* From here on, non-application flag changes are not allowed */\n\n        /* Restore ESP */\n        mov %ebp, %esp\n        .cfi_def_cfa_register %esp\n\n        /* $eax is now the syscall return value.  Erase |info.no| from the\n         * stack so that we can restore the other registers we saved. */\n        lea 4(%esp),%esp\n        .cfi_adjust_cfa_offset -4\n\n        /* Contract of __kernel_vsyscall() and real syscalls is that even\n         * callee-save registers aren't touched, so we restore everything\n         * here. */\n        popl %ebx\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %ebx\n        popl %ecx\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %ecx\n        popl %edx\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %edx\n        popl %esi\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %esi\n        popl %edi\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %edi\n        mov (alt_stack_nesting_level),%ebp\n        lea -1(%ebp),%ebp\n        mov %ebp,(alt_stack_nesting_level)\n        popl %ebp\n        .cfi_adjust_cfa_offset -4\n        .cfi_restore %ebp\n\n        ret\n        .cfi_endproc\n        .size _syscall_hook_trampoline, .-_syscall_hook_trampoline\n\n#define SYSCALLHOOK_START(name) \\\n       .global name;            \\\n       .hidden name;            \\\n       .type name, @function;   \\\nname:                           \\\n       .cfi_startproc;          \\\n       .cfi_def_cfa_offset 0;   \\\n       .cfi_offset %eip, 0;     \\\n       .cfi_offset %esp, 4\n\n#define SYSCALLHOOK_END(name)                                   \\\n        pop (stub_scratch_1);                                   \\\n        .cfi_adjust_cfa_offset -4;                              \\\n        pop %esp;                                               \\\n        .cfi_same_value %esp;                                   \\\n        REG_AT_ADDR32(0x08 /* %eip */, stub_scratch_1);         \\\n        jmp _syscallbuf_final_exit_instruction;                 \\\n       .cfi_endproc;                                            \\\n       .size name, .-name\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_3d_01_f0_ff_ff)\n        call _syscall_hook_trampoline\n        cmpl $0xfffff001,%eax\nSYSCALLHOOK_END(_syscall_hook_trampoline_3d_01_f0_ff_ff)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_90_90_90)\n        call _syscall_hook_trampoline\nSYSCALLHOOK_END(_syscall_hook_trampoline_90_90_90)\n\n/* Declare gcc get_pc thunks here so they're in a known region of code */\n\n        .global _get_pc_thunks_start\n        .hidden _get_pc_thunks_start\n_get_pc_thunks_start:\n\n#define THUNK(name, reg) \\\n        .section        .text.__x86.get_pc_thunk.name,\"axG\",@progbits,__x86.get_pc_thunk.name,comdat; \\\n        .global  __x86.get_pc_thunk.name; \\\n        .hidden __x86.get_pc_thunk.name; \\\n        .type   __x86.get_pc_thunk.name, @function; \\\n__x86.get_pc_thunk.name: \\\n        .cfi_startproc; \\\n        movl    (%esp), %reg; \\\n        ret; \\\n        .cfi_endproc\n\nTHUNK(ax, eax)\nTHUNK(bx, ebx)\nTHUNK(cx, ecx)\nTHUNK(dx, edx)\nTHUNK(si, esi)\nTHUNK(di, edi)\nTHUNK(bp, ebp)\n\n        .global _get_pc_thunks_end\n        .hidden _get_pc_thunks_end\n_get_pc_thunks_end:\n\n#elif defined(__x86_64__)\n        .text\n\n        .set stub_scratch_1, preload_thread_locals + 16\n        .set alt_stack_nesting_level, preload_thread_locals + 24\n        .set saved_flags, preload_thread_locals + 28\n\n        .p2align 4\n_syscallbuf_code_start:\n\n_syscall_hook_trampoline:\n        .cfi_startproc\n        /* Save RBX because we need a callee-saves register */\n        pushq %rbx\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %rbx, 0\n\n        /* Build a |struct syscall_info| on the stack by pushing the arguments\n           and syscall number. */\n        pushq %r9\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %r9, 0\n        pushq %r8\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %r8, 0\n        pushq %r10\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %r10, 0\n        pushq %rdx\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %rdx, 0\n        pushq %rsi\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %rsi, 0\n        pushq %rdi\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %rdi, 0\n        pushq %rax\n        .cfi_adjust_cfa_offset 8\n        .cfi_rel_offset %rax, 0\n\n        /* Align stack */\n        mov %rsp,%rbx\n        .cfi_def_cfa_register %rbx\n        and $0xfffffffffffffff0,%rsp\n\n        /* Save XMM registers */\n        sub $0x80,%rsp\n        movdqa %xmm0,(%rsp)\n        movdqa %xmm1,0x10(%rsp)\n        movdqa %xmm2,0x20(%rsp)\n        movdqa %xmm3,0x30(%rsp)\n        movdqa %xmm4,0x40(%rsp)\n        movdqa %xmm5,0x50(%rsp)\n        movdqa %xmm6,0x60(%rsp)\n        movdqa %xmm7,0x70(%rsp)\n\n        /* Save registers that aren't callee-saves preserved by syscall_hook,\n           and that we aren't already restoring from the syscall args */\n        push %rcx\n        push %r11\n        /* stack is 16-byte aligned again for entry to C */\n\n        /* Call our hook. */\n        mov %rbx,%rdi\n        callq syscall_hook\n\n        pop %r11\n        pop %rcx\n\n        /* Restore XMM registers */\n        movdqa (%rsp),%xmm0\n        movdqa 0x10(%rsp),%xmm1\n        movdqa 0x20(%rsp),%xmm2\n        movdqa 0x30(%rsp),%xmm3\n        movdqa 0x40(%rsp),%xmm4\n        movdqa 0x50(%rsp),%xmm5\n        movdqa 0x60(%rsp),%xmm6\n        movdqa 0x70(%rsp),%xmm7\n\n        mov $saved_flags, %rsp\n        popfw\n        /* From here on, non-application flag changes are not allowed */\n\n        mov %rbx,%rsp\n        .cfi_def_cfa_register %rsp\n\n        /* On entrance, we pushed the %rax, the syscall number. But we don't\n           want to |pop %rax|, as that will overwrite our return value. Skip over it. */\n        pop %rdi\n        .cfi_adjust_cfa_offset -8\n\n        /* We don't really *need* to restore these, since the kernel could have\n           trashed them all anyway. But it seems reasonable to do so. */\n        pop %rdi\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %rdi\n        pop %rsi\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %rsi\n        pop %rdx\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %rdx\n        pop %r10\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %r10\n        pop %r8\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %r8\n        mov (alt_stack_nesting_level),%r9d\n        lea -1(%r9),%r9\n        mov %r9d,(alt_stack_nesting_level)\n        pop %r9\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %r9\n\n        pop %rbx\n        .cfi_adjust_cfa_offset -8\n        .cfi_restore %rbx\n\n        /* ...and we're done. */\n        ret\n        .cfi_endproc\n        .size _syscall_hook_trampoline, . - _syscall_hook_trampoline\n\n_syscallbuf_final_exit_instruction:\n        jmp *(stub_scratch_1)\n\n/**\n * Ok, bear with me here. When gdb sees our stack switch, it gets suspicious and if\n * we're unlucky may decide that our unwind info is broken and abort the unwind. However,\n * it decides to allow the unwind to proceed anyway if we happen to be in a function called\n * __morestack (because that's what gcc calls its stack switching mechanism). Now,\n * GDB does the stack switching comparison based on the CFA. What we thus need to do is keep the\n * CFA pointing to the old stack until we get to a function named __morestack. We set the CFA for every\n * syscallhook to what it will be at the end of the function (which, well, is an ok definition\n * of the CFA). Then, we insert a __morestack function (still with the old CFA) that just jumps\n * through to the trampoline. This way, we can force gdb's stack switch detection to think the\n * stack switch happens between the hook and the common trampoline code (and add a __morestack\n * local symbol to the trampoline code to avoid GDB messing with our stack trace).\n */\n#define CFA_AT_RSP_OFFSET(offset) \\\n.cfi_escape 0x0f, /* DW_CFA_def_cfa_expression */\\\n        0x03, /* 3 bytes follow */\\\n        0x77, offset, /* DW_OP_breg7, offset */\\\n        0x06; /* DW_OP_deref */\n\n#define RSP_IS_CFA \\\n.cfi_escape 0x16, /* DW_CFA_val_expression */\\\n            0x7,  /* %rsp */\\\n            0;     /* 0 bytes follow */\n\n#define RSP_IS_CFA_PLUS_OFFSET(offset) \\\n.cfi_escape 0x16, /* DW_CFA_val_expression */\\\n            0x7,  /* %rsp */\\\n            2,     /* 2 bytes follow */\\\n            0x23, /* DW_OP_plus_uconst */\\\n            offset;\n\n#define RSP_IS_RSP_PLUS_OFFSET(offset) \\\n.cfi_escape 0x16, /* DW_CFA_val_expression */\\\n            0x07, /* %rsp */\\\n            0x02, /* 2 bytes follow */\\\n            0x77, offset; /* DW_OP_breg7, offset */\n\n#define RIP_IS_DEREF_RSP(offset) REG_AT_REG_OFFSET(0x10 /* %rip */, 7, offset)\n\n/**\n * On syscallhook entry, the stack has been switched to the end of per-task\n * scratch space, then the old RSP and the return address have been pushed.\n */\n#define SYSCALLHOOK_START(name)    \\\n        .global name;              \\\n        .hidden name;              \\\n        .type name, @function;     \\\nname:                              \\\n        .cfi_startproc;            \\\n        CFA_AT_RSP_OFFSET(8)       \\\n        RSP_IS_CFA                 \\\n        RIP_IS_DEREF_RSP(0)\n\n#define SYSCALLHOOK_END(name)                                   \\\n        pop (stub_scratch_1);                                   \\\n        CFA_AT_RSP_OFFSET(0)                                    \\\n        REG_AT_ADDR32(0x10 /* %rip */, stub_scratch_1);         \\\n        pop %rsp;                                               \\\n        .cfi_def_cfa %rsp, 0;                                   \\\n        jmp _syscallbuf_final_exit_instruction;                 \\\n        .cfi_endproc;                                           \\\n        .size name, .-name\n\n/* See note above on what __morestack is for */\n.global __morestack\n.hidden __morestack\n.type __morestack, @function\n__morestack:\n.cfi_startproc\nCFA_AT_RSP_OFFSET(16)\nRSP_IS_RSP_PLUS_OFFSET(8)\nRIP_IS_DEREF_RSP(0)\ncallq _syscall_hook_trampoline\n/* GDB likes to override valid CFI with its own heuristics if the current\n   instruction is a retq. This becomes a problem here, because GDB will set\n   a breakpoint at the next instruction after the callq when continuing out of\n   `_syscall_hook_trampoline`. This `nop` makes said instruction not a retq,\n   thus preventing that GDB heuristic from kicking in and letting GDB realize\n   that it did in fact manage to step out of the `_syscall_hook_trampoline`\n   frame. */\nnop\nretq\n.cfi_endproc\n.size __morestack, .-__morestack\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_3d_01_f0_ff_ff)\n        callq __morestack\n        cmpq $0xfffffffffffff001,%rax\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_3d_01_f0_ff_ff)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_3d_00_f0_ff_ff)\n        callq __morestack\n        cmpq $0xfffffffffffff000,%rax\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_3d_00_f0_ff_ff)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_85_c0)\n        callq __morestack\n        test %rax,%rax\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_85_c0)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_3d_00_f0_ff_ff)\n        callq __morestack\n        cmpl $0xfffff000,%eax\nSYSCALLHOOK_END(_syscall_hook_trampoline_3d_00_f0_ff_ff)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_89_45_f8)\n        callq __morestack\n        mov %rax,-8(%rbp)\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_89_45_f8)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_89_c3)\n        callq __morestack\n        mov %rax,%rbx\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_89_c3)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_8b_3c_24)\n         callq __morestack\n         /* The original instruction after the syscall is movq (%rsp),%rdi. */\n         movq 8(%rsp),%rdi\n         movq (%rdi),%rdi\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_8b_3c_24)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_4c_8b_0d)\n        callq __morestack\n        push %rax\n        push %rbx\n        /* Get return address into %rbx */\n        mov 16(%rsp),%rbx\n        /* Get PC-relative offset of patched instruction into %eax */\n        mov -4(%rbx),%eax\n        movsx %eax,%rax\n        mov (%rbx,%rax),%r9\n        pop %rbx\n        pop %rax\nSYSCALLHOOK_END(_syscall_hook_trampoline_4c_8b_0d)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_5a_5e_c3)\n        .cfi_offset %rip, 16\n        RSP_IS_CFA_PLUS_OFFSET(24)\n        callq __morestack\n        /* The original instructions after the syscall are\n           pop %rdx; pop %rsi; retq. */\n        /* We're not returning to the dynamically generated stub, so\n           we need to fix the stack pointer ourselves. */\n        pop %rdx\n        CFA_AT_RSP_OFFSET(0)\n        pop %rsp\n        .cfi_def_cfa %rsp, 0;\n        pop %rdx\n        .cfi_adjust_cfa_offset -8\n        pop %rsi\n        .cfi_adjust_cfa_offset -8\n        pop (stub_scratch_1)\n        .cfi_adjust_cfa_offset -8\n        jmp _syscallbuf_final_exit_instruction\n\n        .cfi_endproc\n        .size _syscall_hook_trampoline_5a_5e_c3, .-_syscall_hook_trampoline_5a_5e_c3\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_89_c2_f7_da)\n        call __morestack\n        mov %eax,%edx\n        neg %edx\nSYSCALLHOOK_END(_syscall_hook_trampoline_89_c2_f7_da)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_90_90_90)\n        call __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_90_90_90)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_ba_01_00_00_00)\n        call __morestack\n        mov $1,%edx\nSYSCALLHOOK_END(_syscall_hook_trampoline_ba_01_00_00_00)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_89_c1_31_d2)\n        call __morestack\n        mov %eax,%ecx\n        xor %edx,%edx\nSYSCALLHOOK_END(_syscall_hook_trampoline_89_c1_31_d2)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_c3_nop)\n        .cfi_offset %rip, 16\n        RSP_IS_CFA_PLUS_OFFSET(24)\n        callq __morestack\n        /* The original instructions after the syscall are\n           retq; nopl 0x0(%rax,%rax,1) */\n        /* We're not returning to the dynamically generated stub, so\n           we need to fix the stack pointer ourselves. */\n        pop %rdx\n        CFA_AT_RSP_OFFSET(0)\n        pop %rsp\n        .cfi_def_cfa %rsp, 0;\n        pop (stub_scratch_1)\n        .cfi_adjust_cfa_offset -8\n        jmp _syscallbuf_final_exit_instruction\n\n        .cfi_endproc\n        .size _syscall_hook_trampoline_c3_nop, .-_syscall_hook_trampoline_c3_nop\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_40_80_f6_81)\n\txor $0x81, %sil\n\tcall __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_40_80_f6_81)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_8d_b3_f0_08_00_00)\n\tlea    0x8f0(%rbx),%rsi\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_8d_b3_f0_08_00_00)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_49_89_ca)\n\tmov %rcx, %r10\n\tcall __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_49_89_ca)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_89_c1)\n        callq __morestack\n        mov %rax, %rcx\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_89_c1)\n\n#define MOV_RDX_VARIANTS \\\n  MOV_RDX_TO_REG(48, d0) \\\n  MOV_RDX_TO_REG(48, d1) \\\n  MOV_RDX_TO_REG(48, d2) \\\n  MOV_RDX_TO_REG(48, d3) \\\n  MOV_RDX_TO_REG(48, d4) \\\n  MOV_RDX_TO_REG(48, d5) \\\n  MOV_RDX_TO_REG(48, d6) \\\n  MOV_RDX_TO_REG(48, d7) \\\n  MOV_RDX_TO_REG(49, d0) \\\n  MOV_RDX_TO_REG(49, d1) \\\n  MOV_RDX_TO_REG(49, d2) \\\n  MOV_RDX_TO_REG(49, d3) \\\n  MOV_RDX_TO_REG(49, d4) \\\n  MOV_RDX_TO_REG(49, d5) \\\n  MOV_RDX_TO_REG(49, d6) \\\n  MOV_RDX_TO_REG(49, d7)\n\n#define MOV_RDX_TO_REG(rex, op) \\\nSYSCALLHOOK_START(_syscall_hook_trampoline_##rex##_89_##op); \\\n        callq __morestack;                                   \\\n        .byte 0x##rex, 0x89, 0x##op;                         \\\nSYSCALLHOOK_END(_syscall_hook_trampoline_##rex##_89_##op);\n\n  MOV_RDX_VARIANTS\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_c1_e2_20)\n        callq __morestack\n        shl $32, %rdx\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_c1_e2_20)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_49_8b_44_24_28)\n        callq __morestack\n        mov 0x28(%r12),%rax\nSYSCALLHOOK_END(_syscall_hook_trampoline_49_8b_44_24_28)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_4c_89_f7)\n        mov %r14, %rdi\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_4c_89_f7)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_4c_89_ff)\n        mov %r15, %rdi\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_4c_89_ff)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_49_c7_c1_ff_ff_ff_ff)\n        mov $0xffffffffffffffff,%r9\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_49_c7_c1_ff_ff_ff_ff)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_b8_0e_00_00_00)\n        mov $0x0e,%eax\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_b8_0e_00_00_00)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_b8_11_01_00_00)\n        mov $0x111,%eax\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_b8_11_01_00_00)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_b8_ca_00_00_00)\n        mov $0xca,%eax\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_b8_ca_00_00_00)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_be_18_00_00_00)\n        mov $0x18,%esi\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_be_18_00_00_00)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_89_e5)\n        /* Previous RSP is stored on the stack above our return address */\n        mov 8(%rsp),%rbp\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_89_e5)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_8b_45_10)\n        mov    0x10(%rbp),%rax\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_8b_45_10)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_48_89_fb)\n        mov %rdi,%rbx\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_48_89_fb)\n\nSYSCALLHOOK_START(_syscall_hook_trampoline_nops)\n        callq __morestack\nSYSCALLHOOK_END(_syscall_hook_trampoline_nops)\n\n#elif defined(__aarch64__)\n        .text\n\n        .set syscallbuf_stub_alt_stack, preload_thread_locals\n        .set stub_scratch_1, preload_thread_locals + 16\n        .set alt_stack_nesting_level, preload_thread_locals + 24\n        .set stub_scratch_2, preload_thread_locals + 8 * 13\n\n// Store a pair of x registers to stack at offset sp.\n// Assuming that CFA register is sp\n#define STPX_STACK(r1, r2, offset)              \\\n        stp     x##r1, x##r2, [sp, offset];     \\\n        .cfi_rel_offset x##r1, offset;          \\\n        .cfi_rel_offset x##r2, offset + 8\n\n#define LDPX_STACK(r1, r2, offset)              \\\n        ldp     x##r1, x##r2, [sp, offset];     \\\n        .cfi_same_value x##r1;                  \\\n        .cfi_same_value x##r2\n\n// Store a pair of q registers to stack at offset sp.\n// Assuming that CFA register is sp\n#define STPQ_STACK(r1, r2, offset)              \\\n        stp     q##r1, q##r2, [sp, offset];     \\\n        .cfi_rel_offset q##r1, offset;          \\\n        .cfi_rel_offset q##r2, offset + 16\n\n#define LDPQ_STACK(r1, r2, offset)              \\\n        ldp     q##r1, q##r2, [sp, offset];     \\\n        .cfi_same_value q##r1;                  \\\n        .cfi_same_value q##r2\n\n// Mark all temporary registers as same_value except x8 and x15\n#define SAME_VALUE_X_NO8_NO15   \\\n        .cfi_same_value x0;     \\\n        .cfi_same_value x1;     \\\n        .cfi_same_value x2;     \\\n        .cfi_same_value x3;     \\\n        .cfi_same_value x4;     \\\n        .cfi_same_value x5;     \\\n        .cfi_same_value x6;     \\\n        .cfi_same_value x7;     \\\n        .cfi_same_value x9;     \\\n        .cfi_same_value x10;    \\\n        .cfi_same_value x11;    \\\n        .cfi_same_value x12;    \\\n        .cfi_same_value x13;    \\\n        .cfi_same_value x14;    \\\n        .cfi_same_value x16;    \\\n        .cfi_same_value x17;    \\\n        .cfi_same_value x18\n\n#define SAME_VALUE_X            \\\n        SAME_VALUE_X_NO8_NO15;  \\\n        .cfi_same_value x8;     \\\n        .cfi_same_value x15\n\n#define SAME_VALUE_ALL_Q        \\\n        .cfi_same_value q0;     \\\n        .cfi_same_value q1;     \\\n        .cfi_same_value q2;     \\\n        .cfi_same_value q3;     \\\n        .cfi_same_value q4;     \\\n        .cfi_same_value q5;     \\\n        .cfi_same_value q6;     \\\n        .cfi_same_value q7;     \\\n        .cfi_same_value q8;     \\\n        .cfi_same_value q9;     \\\n        .cfi_same_value q10;    \\\n        .cfi_same_value q11;    \\\n        .cfi_same_value q12;    \\\n        .cfi_same_value q13;    \\\n        .cfi_same_value q14;    \\\n        .cfi_same_value q15;    \\\n        .cfi_same_value q16;    \\\n        .cfi_same_value q17;    \\\n        .cfi_same_value q18;    \\\n        .cfi_same_value q19;    \\\n        .cfi_same_value q20;    \\\n        .cfi_same_value q21;    \\\n        .cfi_same_value q22;    \\\n        .cfi_same_value q23;    \\\n        .cfi_same_value q24;    \\\n        .cfi_same_value q25;    \\\n        .cfi_same_value q26;    \\\n        .cfi_same_value q27;    \\\n        .cfi_same_value q28;    \\\n        .cfi_same_value q29;    \\\n        .cfi_same_value q30;    \\\n        .cfi_same_value q31\n\n        .p2align 4\n_syscallbuf_code_start:\n\n_syscall_hook_trampoline:\n        // stack frame:\n        // 208-688: q2 - q31\n        // 128-200: x10 - x18\n        // 112-128: x7, x9\n        // 104-112: x6\n        // 48-104: syscall_info\n        // 32-48: x29, x30\n        // 0-32: q0, q1\n        .cfi_startproc\n        // GAS correctly put these in CIE as long as they\n        // appears right after .cfi_startproc\n        SAME_VALUE_X\n        SAME_VALUE_ALL_Q\n        // Store the vector registers at the bottom so that we can take advantage of\n        // the larger pre-offset that can be encoded in the instruction\n        // to adjust the stack pointer.\n        stp     q0, q1, [sp, -688]!\n        .cfi_def_cfa_offset 688\n        .cfi_rel_offset q0, 0\n        .cfi_rel_offset q1, 0 + 16\n        STPX_STACK(29, 30, 32)\n        /* Build a |struct syscall_info| on the stack by pushing the arguments\n           and syscall number. */\n        STPX_STACK(8, 0, 48)\n        add     x0, sp, 48 // x0 saved, store new argument for syscall_hook in x0.\n        STPX_STACK(1, 2, 64)\n        STPX_STACK(3, 4, 80)\n        STPX_STACK(5, 6, 96)\n        STPX_STACK(7, 9, 112)\n        STPX_STACK(10, 11, 128)\n        STPX_STACK(12, 13, 144)\n        STPX_STACK(14, 15, 160)\n        STPX_STACK(16, 17, 176)\n        str     x18, [sp, 192]\n        .cfi_rel_offset x18, 192\n        STPQ_STACK(2, 3, 208)\n        STPQ_STACK(4, 5, 240)\n        STPQ_STACK(6, 7, 272)\n        // function call only maintain the bottom half of v8-v15\n        // whereas syscall maintains all the v registers\n        // so we actually need to save and restore v8-v15 as well...\n        // (in principle we could save only the upper half but\n        //  that's too much effort especially for the unwind info...)\n        STPQ_STACK(8, 9, 304)\n        STPQ_STACK(10, 11, 336)\n        STPQ_STACK(12, 13, 368)\n        STPQ_STACK(14, 15, 400)\n        STPQ_STACK(16, 17, 432)\n        STPQ_STACK(18, 19, 464)\n        STPQ_STACK(20, 21, 496)\n        STPQ_STACK(22, 23, 528)\n        STPQ_STACK(24, 25, 560)\n        STPQ_STACK(26, 27, 592)\n        STPQ_STACK(28, 29, 624)\n        STPQ_STACK(30, 31, 656)\n\n        bl      syscall_hook\n\n        movz    x29, #:abs_g1:alt_stack_nesting_level // assume 32bit address\n        movk    x29, #:abs_g0_nc:alt_stack_nesting_level\n        ldr     w30, [x29]\n        sub     w30, w30, 1\n        str     w30, [x29]\n\n        ldp     x29, x30, [sp, 32]\n        .cfi_same_value x29\n        // x30 should not use same_value since it's value is changed\n        // by the function call instruction\n        .cfi_restore x30\n        ldr     x8, [sp, 48]\n        .cfi_same_value x8\n        LDPX_STACK(1, 2, 64)\n        LDPX_STACK(3, 4, 80)\n        LDPX_STACK(5, 6, 96)\n        LDPX_STACK(7, 9, 112)\n        LDPX_STACK(10, 11, 128)\n        LDPX_STACK(14, 15, 160)\n        LDPX_STACK(16, 17, 176)\n        ldr     x18, [sp, 192]\n        .cfi_same_value x18\n\n        LDPQ_STACK(2, 3, 208)\n        LDPQ_STACK(4, 5, 240)\n        LDPQ_STACK(6, 7, 272)\n        LDPQ_STACK(8, 9, 304)\n        LDPQ_STACK(10, 11, 336)\n        LDPQ_STACK(12, 13, 368)\n        LDPQ_STACK(14, 15, 400)\n        LDPQ_STACK(16, 17, 432)\n        LDPQ_STACK(18, 19, 464)\n        LDPQ_STACK(20, 21, 496)\n        LDPQ_STACK(22, 23, 528)\n        LDPQ_STACK(24, 25, 560)\n        LDPQ_STACK(26, 27, 592)\n        LDPQ_STACK(28, 29, 624)\n        LDPQ_STACK(30, 31, 656)\n\n        ldp     q0, q1, [sp], 688\n        .cfi_same_value q0\n        .cfi_same_value q1\n        .cfi_def_cfa_offset 0\n        ret\n        .cfi_endproc\n        .size   _syscall_hook_trampoline, .-_syscall_hook_trampoline\n\n/**\n * On syscallhook entry, we are still on the old stack,\n * with x30 (lr) points to right after the blr instruction that got us here.\n * The old values of x15 and x30 are saved to [x8], which is the syscall number\n * with an offset to land in the stub_scratch_2 area.\n */\n        .globl _syscall_hook_trampoline_raw\n        .hidden _syscall_hook_trampoline_raw\n        .type _syscall_hook_trampoline_raw, @function\n_syscall_hook_trampoline_raw:\n        .cfi_startproc\n        // GAS correctly put these in CIE as long as they\n        // appears right after .cfi_startproc\n        .cfi_return_column 32 // pc\n        SAME_VALUE_X_NO8_NO15\n        SAME_VALUE_ALL_Q\n        // We define CFA as the value of the stack pointer when we enter this function\n        // as specified in aadwarf64.\n        // Since we aren't using the caller stack, none of the registers\n        // we save will be in the CFA...\n        .cfi_def_cfa sp, 0\n        REG_AT_REG_OFFSET(0x20 /* pc */, 30, 16)\n        REG_AT_REG_OFFSET(0x0f /* x15 */, 8,\n                          (stub_scratch_2 - preload_thread_locals) | 0x80, 0)\n        REG_AT_REG_OFFSET(0x1e /* x30 */, 8,\n                          (stub_scratch_2 - preload_thread_locals + 8) | 0x80, 0)\n        // x8 = x8 - preload_thread_locals\n        // The last byte of the signed number LEB128 contains the top 4 bits\n        // from the 32bit negative number (obtained using the shifted 0xF mask)\n        // and 3 bits of leading ones above it (the `or`ing of the `0x70`).\n        // The top bit of the byte is 0 signaling the end of the LEB128 encoding.\n        .cfi_escape     0x16, /* DW_CFA_val_expression */                       \\\n                        0x08, /* x8 */                                          \\\n                        0x06, /* length 6 */                                    \\\n                        0x78, /* DW_OP_breg8 */                                 \\\n                        ((-preload_thread_locals) & 0x7F) | 0x80,               \\\n                        ((-preload_thread_locals) & (0x7F << 7)) >> 7 | 0x80,   \\\n                        ((-preload_thread_locals) & (0x7F << 14)) >> 14 | 0x80, \\\n                        ((-preload_thread_locals) & (0x7F << 21)) >> 21 | 0x80, \\\n                        ((-preload_thread_locals) & ( 0xF << 28)) >> 28 | 0x70\n        // old gcc version doesn't want to encode bti\n        // unless we specify armv8.5-a even though this was in the nop space.\n        .inst   0xd503245f // bti     c\n        mov     x15, preload_thread_locals\n        // Stash away x30 so that we can have two registers to use again\n        // we can't use stub_scratch_2 since we might overwrite the data there\n        str     x30, [x15, stub_scratch_1 - preload_thread_locals]\n        .cfi_escape     0x10, /* DW_CFA_expression */   \\\n                        0x20, /* pc */                  \\\n                        0x08, /* length 8 */            \\\n                        DW_OP_CONST4U(stub_scratch_1),  \\\n                        0x06, /* DW_OP_deref */         \\\n                        0x23, /* DW_OP_plus_uconst */   \\\n                        16\n        // Move the register stash region from\n        // `x8 + stub_scratch_2 - preload_thread_locals`\n        // (i.e. `stub_scratch_2 + original_x8`) to the start of `stub_scratch_2`\n        // Do it in the forward order since we know x8 >= stub_scratch_2\n        ldr     x30, [x8, stub_scratch_2 - preload_thread_locals]\n        str     x30, [x15, stub_scratch_2 - preload_thread_locals]\n        ldr     x30, [x8, stub_scratch_2 - preload_thread_locals + 8]\n        str     x30, [x15, stub_scratch_2 - preload_thread_locals + 8]\n        // Restore x8\n        movk    x8, 0, lsl 16\n        .cfi_same_value x8\n        REG_AT_ADDR32(0x0f /* x15 */, stub_scratch_2)\n        REG_AT_ADDR32(0x1e /* x30 */, stub_scratch_2 + 8)\n\n        cmp     x8, 0xdc // SYS_clone\n        .cfi_remember_state\n        b.eq    .Lfallback_rawsyscall\n\n        ldr     w30, [x15, alt_stack_nesting_level - preload_thread_locals]\n        cmp     w30, 0\n        add     w30, w30, 1\n        str     w30, [x15, alt_stack_nesting_level - preload_thread_locals]\n\n        b.ne    .Lnest_syscall_hook_trampoline_raw\n        ldr     x30, [x15, syscallbuf_stub_alt_stack - preload_thread_locals]\n        sub     x30, x30, 48\n        b       .Lstackset_syscall_hook_trampoline_raw\n.Lnest_syscall_hook_trampoline_raw:\n        sub     x30, sp, 48\n.Lstackset_syscall_hook_trampoline_raw:\n        // Now x30 points to the new stack with 48 bytes of space allocated\n\n        // Move sp into a normal register. Otherwise we can't store it\n        mov     x15, sp\n        // Save sp to new stack.\n        str     x15, [x30, 16]\n        mov     sp, x30\n        REG_AT_REG_OFFSET(0x1f /* sp */, 31, 16)\n        .cfi_escape     0x0f, /* DW_CFA_def_cfa_expression */   \\\n                        0x03, /* 3 bytes follow */              \\\n                        0x8f, /* DW_OP_breg31 */                \\\n                        16,                                     \\\n                        0x06 /* DW_OP_deref */\n        // sp is switched, x15 and x30 are free to use\n        // [stub_scratch_1] holds the stub address\n\n        // Now we need to construct the stack frame, with everything\n        // in the scratch area copied over so that we can nest again.\n        mov     x15, preload_thread_locals\n        // load runtime stub address\n        ldr     x30, [x15, stub_scratch_1 - preload_thread_locals]\n        // save stub return address\n        str     x30, [sp]\n        // load syscall return address\n        ldr     x30, [x30, 16]\n        str     x30, [sp, 8]\n        ldr     x30, [x15, stub_scratch_2 - preload_thread_locals]\n        str     x30, [sp, 24]\n        ldr     x30, [x15, stub_scratch_2 - preload_thread_locals + 8]\n        str     x30, [sp, 32]\n\n        // stackframe layout\n        // 32: original x30\n        // 24: original x15\n        // 16: original sp\n        // 8: return address to syscall\n        // 0: return address to stub\n        REG_AT_REG_OFFSET(0x20 /* pc */, 31, 8)\n        REG_AT_REG_OFFSET(0x0f /* x15 */, 31, 24)\n        REG_AT_REG_OFFSET(0x1e /* x30 */, 31, 32)\n\n        bl _syscall_hook_trampoline\n\n/**\n * The _syscall_hook_trampoline restores all the registers to the previous values\n * (minus the register for syscall return value) so we just need to restore\n * the registers we’ve overwritten by the end of the stack switch,\n * i.e. x15 , x30 and sp.\n * x15 and x30 will be restored when we get back to the stub\n * so we don’t need to restore them here but we do need to copy their values\n * to stub_scratch_2 again so that the stub can restore them\n * (since without a valid stack that is still the only memory\n * we can use to restore things).\n * We also need to store the return address to stub_scratch_1\n * since that’ll help rr with setting breakpoint.\n */\n\n        movz    x15, #:abs_g1:stub_scratch_2 // assume 32bit address\n        movk    x15, #:abs_g0_nc:stub_scratch_2\n        ldr     x30, [sp, 24] // x15\n        str     x30, [x15]\n        ldr     x30, [sp, 32] // x30\n        str     x30, [x15, 8]\n        REG_AT_ADDR32(0x0f /* x15 */, stub_scratch_2)\n        REG_AT_ADDR32(0x1e /* x30 */, stub_scratch_2 + 8)\n        ldr     x30, [sp, 8] // syscall return address\n        // tell rr breakpoint handling where we are going\n        str     x30, [x15, stub_scratch_1 - stub_scratch_2]\n        REG_AT_ADDR32(0x20 /* pc */, stub_scratch_1)\n        ldr     x30, [sp] // stub return address\n        ldr     x15, [sp, 16] // sp\n        mov     sp, x15\n        .cfi_restore sp\n        .cfi_def_cfa sp, 0\n        movz    x15, #:abs_g1:stub_scratch_2 // assume 32bit address\n        movk    x15, #:abs_g0_nc:stub_scratch_2\n_syscallbuf_final_exit_instruction:\n        ret\n\n.Lfallback_rawsyscall:\n        .cfi_restore_state\n        // Must not touch sp in this branch.\n        // Use x15 to remember the return address since we are only copying\n        // the first two elements of stub_scratch_2 for the child.\n        ldr     x15, [x15, stub_scratch_1 - preload_thread_locals]\n        REG_AT_REG_OFFSET(0x20 /* pc */, 15, 16)\n        mov     x30, 0x70000000 // RR_PAGE_SYSCALL_TRACED\n        blr     x30\n        // stub_scratch_2 content is maintained by rr\n        // we need to put the syscall return address in stub_scratch_1\n        movz    x30, #:abs_g1:stub_scratch_2 // assume 32bit address\n        movk    x30, #:abs_g0_nc:stub_scratch_2\n        str     x15, [x30, 16] // stash away stub address\n        ldr     x15, [x15, 16] // syscall return address\n        .cfi_register 32, x15\n        str     x15, [x30, stub_scratch_1 - stub_scratch_2]\n        REG_AT_ADDR32(0x20 /* pc */, stub_scratch_1)\n        mov     x15, x30\n        ldr     x30, [x15, 16]\n        b       _syscallbuf_final_exit_instruction\n\n        .cfi_endproc\n        .size _syscall_hook_trampoline_raw, .-_syscall_hook_trampoline_raw\n\n#endif /* __aarch64__ */\n\n        .section .note.GNU-stack,\"\",@progbits\n"
  },
  {
    "path": "src/preload/syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define RR_IMPLEMENT_PRELOAD\n\n#ifndef _GNU_SOURCE\n#define _GNU_SOURCE 1\n#endif\n#include \"syscallbuf.h\"\n\n/**\n * Buffer syscalls, so that rr can process the entire buffer with one\n * trap instead of a trap per call.\n *\n * This file is compiled into a dso that's PRELOADed in recorded\n * applications.  The dso replaces libc syscall wrappers with our own\n * implementation that saves nondeterministic outparams in a fixed-size\n * buffer.  When the buffer is full or the recorded application\n * invokes an un-buffered syscall or receives a signal, we trap to rr\n * and it records the state of the buffer.\n *\n * During replay, rr simply refills the buffer with the recorded data\n * when it reaches the \"flush-buffer\" events that were recorded.  Then\n * rr emulates each buffered syscall, and the code here restores the\n * client data from the refilled buffer.\n *\n * The crux of the implementation here is to selectively ptrace-trap\n * syscalls.  The normal (un-buffered) syscalls generate a ptrace\n * trap, and the buffered syscalls trap directly to the kernel.  This\n * is implemented with a seccomp-bpf which examines the syscall and\n * decides how to handle it (see seccomp-bpf.h and Task::spawn).\n *\n * Because this code runs in the tracee's address space and overrides\n * system calls, the code is rather delicate.  The following rules\n * must be followed\n *\n * o No rr headers (other than seccomp-bpf.h and rr.h) may be included\n * o All syscalls invoked by this code must be called directly, not\n *   through libc wrappers (which this file may itself indirectly override)\n *\n * The wrapper functions are named sys_xxxx. Each wrapper normally makes one\n * untraced syscall or one traced syscall of the same type, but there are\n * exceptions. For example sys_read can make a number of untraced syscalls\n * instead of a single untraced syscall. A critical rule is that any traced\n * or MAY_BLOCK untraced syscall *must* be the last syscall performed by the\n * wrapper.\n */\n\n#include <dlfcn.h>\n#include <limits.h>\n#include <unistd.h>\n#include <asm/errno.h>\n#include <asm/ioctls.h>\n#include <asm/poll.h>\n#include <asm/stat.h>\n#include <asm/statfs.h>\n#include <linux/eventpoll.h>\n#include <linux/futex.h>\n#include <linux/fcntl.h>\n#include <linux/if_packet.h>\n#include <linux/ioctl.h>\n#include <linux/mman.h>\n#include <linux/net.h>\n#include <linux/netlink.h>\n#include <linux/perf_event.h>\n#include <linux/ptrace.h>\n#include <linux/quota.h>\n#include <linux/stat.h>\n#include <linux/types.h>\n#include <linux/un.h>\n#include <linux/utsname.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdio.h>\n#include <syscall.h>\n#include <sysexits.h>\n#include <sys/mman.h>\n#include <sys/prctl.h>\n#include <sys/resource.h>\n#include <sys/socket.h>\n#include <sys/time.h>\n#include <unistd.h>\n\n#include \"preload_interface.h\"\n#include \"rr/rr.h\"\n\n#ifndef SOL_NETLINK\n#define SOL_NETLINK 270\n#endif\n\n#ifndef BTRFS_IOCTL_MAGIC\n#define BTRFS_IOCTL_MAGIC 0x94\n#endif\n#ifndef BTRFS_IOC_CLONE_RANGE\nstruct btrfs_ioctl_clone_range_args {\n  int64_t src_fd;\n  uint64_t src_offset;\n  uint64_t src_length;\n  uint64_t dest_offset;\n};\n#define BTRFS_IOC_CLONE_RANGE                                                  \\\n  _IOW(BTRFS_IOCTL_MAGIC, 13, struct btrfs_ioctl_clone_range_args)\n#endif\n#ifndef MADV_FREE\n#define MADV_FREE 8\n#endif\n#ifndef MADV_COLD\n#define MADV_COLD 20\n#endif\n\n#ifndef GRND_NONBLOCK\n#define GRND_NONBLOCK 1\n#endif\n\n#ifndef SOL_IP\n#define SOL_IP 0\n#endif\n#ifndef SOL_IPV6\n#define SOL_IPV6 41\n#endif\n#ifndef IPT_SO_SET_REPLACE\n#define IPT_SO_SET_REPLACE 64\n#endif\n#ifndef IPV6T_SO_SET_REPLACE\n#define IPV6T_SO_SET_REPLACE 64\n#endif\n\nstruct rr_rseq {\n  uint32_t cpu_id_start;\n  uint32_t cpu_id;\n  uint64_t rseq_cs;\n  uint32_t flags;\n} __attribute__((aligned(32)));\n\n/* NB: don't include any other local headers here. */\n\n#ifdef memcpy\n#undef memcpy\n#endif\n#define memcpy you_must_use_local_memcpy\n\n/* POSIX defines it as int while glibc defines it as size_t */\n#if defined (__GLIBC__) || defined (__ANDROID__)\ntypedef size_t rr_iovlen_t;\n#else\ntypedef int rr_iovlen_t;\n#endif\n\nstatic long _traced_init_syscall(int syscallno, long a0, long a1, long a2,\n                                 long a3, long a4, long a5)\n{\n  return syscall(syscallno, a0, a1, a2, a3, a4, a5);\n}\n\n#ifdef syscall\n#undef syscall\n#endif\n#define syscall you_must_use_traced_syscall\n\nstatic inline unsigned char *rr_page_replay_flag_addr(void) {\n  return (unsigned char *)RR_PAGE_IN_REPLAY_FLAG;\n}\n\n/**\n * Declaring this to avoid issues with the declaration of f_owner_ex\n * across distros. See https://github.com/rr-debugger/rr/issues/2693 */\nstruct rr_f_owner_ex {\n  int type;\n  int pid;\n};\n\n#ifndef __ARCH_FLOCK64_PAD\n#define __ARCH_FLOCK64_PAD\n#endif\nstruct rr_flock64 {\n    short  l_type;\n    short  l_whence;\n    __kernel_loff_t l_start;\n    __kernel_loff_t l_len;\n    __kernel_pid_t  l_pid;\n    __ARCH_FLOCK64_PAD\n};\n\n// The alignment of this struct is incorrect, but as long as it's not\n// used inside other structures, defining it this way makes the code below\n// easier.\ntypedef uint64_t kernel_sigset_t;\n\n/* Nonzero when syscall buffering is enabled. */\nstatic int buffer_enabled;\n/* Nonzero after process-global state has been initialized. */\nstatic int process_inited;\n\nRR_HIDDEN struct preload_globals globals;\n\nstatic struct preload_thread_locals* const thread_locals =\n    (struct preload_thread_locals*)PRELOAD_THREAD_LOCALS_ADDR;\n\n/**\n * Return a pointer to the buffer header, which happens to occupy the\n * initial bytes in the mapped region.\n */\nstatic struct syscallbuf_hdr* buffer_hdr(void) {\n  return (struct syscallbuf_hdr*)thread_locals->buffer;\n}\n\n/**\n * Return a pointer to what may be the next syscall record.\n *\n * THIS POINTER IS NOT GUARANTEED TO BE VALID!!!  Caveat emptor.\n */\ninline static struct syscallbuf_record* next_record(\n    struct syscallbuf_hdr* hdr) {\n  uintptr_t next = (uintptr_t)hdr + sizeof(*hdr) + hdr->num_rec_bytes;\n  return (struct syscallbuf_record*)next;\n}\n\n/**\n * Return a pointer to the byte just after the last valid syscall record in\n * the buffer.\n */\nstatic uint8_t* buffer_last(void) {\n  return (uint8_t*)next_record(buffer_hdr());\n}\n\n/**\n * Return a pointer to the byte just after the very end of the mapped\n * region.\n */\nstatic uint8_t* buffer_end(void) {\n  return thread_locals->buffer + thread_locals->buffer_size;\n}\n\n/**\n * Same as libc memcpy(), but usable within syscallbuf transaction\n * critical sections.\n */\nstatic void local_memcpy(void* dest, const void* source, int n) {\n#if defined(__i386__) || defined(__x86_64__)\n  /* On modern x86-ish CPUs rep movsb is fast, usually able to move\n   * 64 bytes at a time.\n   */\n  __asm__ __volatile__(\"rep movsb\\n\\t\"\n                       : \"+S\"(source), \"+D\"(dest), \"+c\"(n)\n                       :\n                       : \"cc\", \"memory\");\n#elif defined(__aarch64__)\n  long c1;\n  long c2;\n  long n_long = n;\n  __asm__ __volatile__(\"subs %4, %2, 16\\n\\t\"\n                       \"b.lt 2f\\n\\t\"\n                       \"1:\\n\\t\"\n                       \"mov %2, %4\\n\\t\"\n                       \"ldp %3, %4, [%1], #16\\n\\t\"\n                       \"stp %3, %4, [%0], #16\\n\\t\"\n                       \"subs %4, %2, #16\\n\\t\"\n                       \"b.ge 1b\\n\"\n                       \"2:\\n\\t\"\n                       \"tbz %2, 3, 3f\\n\\t\"\n                       \"ldr %3, [%1], #8\\n\\t\"\n                       \"str %3, [%0], #8\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"tbz %2, 2, 3f\\n\\t\"\n                       \"ldr %w3, [%1], #4\\n\\t\"\n                       \"str %w3, [%0], #4\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"tbz %2, 1, 3f\\n\\t\"\n                       \"ldrh %w3, [%1], #2\\n\\t\"\n                       \"strh %w3, [%0], #2\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"tbz %2, 0, 3f\\n\\t\"\n                       \"ldrb %w3, [%1]\\n\\t\"\n                       \"strb %w3, [%0]\\n\\t\"\n                       \"3:\\n\\t\"\n                       : \"+r\"(dest), \"+r\"(source), \"+r\"(n_long), \"=&r\"(c1), \"=&r\"(c2)\n                       :\n                       : \"cc\", \"memory\");\n#else\n#error Unknown architecture\n#endif\n}\n\n/**\n * Same as libc memset(), but usable within syscallbuf transaction\n * critical sections.\n */\nstatic void local_memset(void* dest, uint8_t c, int n) {\n#if defined(__i386__) || defined(__x86_64__)\n  /* On modern x86-ish CPUs rep stosb is fast, usually able to move\n   * 64 bytes at a time.\n   */\n  __asm__ __volatile__(\"rep stosb\\n\\t\"\n                       : \"+a\"(c), \"+D\"(dest), \"+c\"(n)\n                       :\n                       : \"cc\", \"memory\");\n#elif defined(__aarch64__)\n  double v1 __attribute__((vector_size(16)));\n  long n2;\n  long n_long = n;\n  __asm__ __volatile__(\"subs %4, %2, 32\\n\\t\"\n                       \"b.lt 2f\\n\\t\"\n                       \"dup %3.16b, %w0\\n\"\n                       \"1:\\n\\t\"\n                       \"mov %2, %4\\n\\t\"\n                       \"stp %q3, %q3, [%1], #32\\n\\t\"\n                       \"subs %4, %2, #32\\n\\t\"\n                       \"b.ge 1b\\n\"\n                       \"2:\\n\\t\"\n                       \"cbz %2, 4f\\n\"\n                       \"3:\\n\\t\"\n                       \"strb %w0, [%1], #1\\n\\t\"\n                       \"subs %2, %2, #1\\n\\t\"\n                       \"b.ne 3b\\n\"\n                       \"4:\\n\\t\"\n                       : \"+r\"(c), \"+r\"(dest), \"+r\"(n_long), \"=x\"(v1), \"=r\"(n2)\n                       :\n                       : \"cc\", \"memory\");\n#else\n#error Unknown architecture\n#endif\n}\n\n/**\n * Xorshift* RNG\n */\nstatic int64_t local_random(void) {\n  uint64_t x = globals.random_seed;\n  x ^= x >> 12;\n  x ^= x << 25;\n  x ^= x >> 27;\n  globals.random_seed = x;\n  return x * 0x2545F4914F6CDD1D;\n}\n\n/* The following are wrappers for the syscalls invoked by this library\n * itself.  These syscalls will generate ptrace traps.\n * stack_param_1 and stack_param_2 are pushed onto the stack just before\n * the syscall, for SYS_rrcall_notify_syscall_hook_exit which takes stack\n * parameters as well as register parameters.\n * syscall_instruction is the actual syscall invocation instruction\n * (a function which we call with the registers set up appropriately).\n */\n\nextern RR_HIDDEN long _raw_syscall(int syscallno, long a0, long a1, long a2,\n                                   long a3, long a4, long a5,\n                                   void* syscall_instruction,\n                                   long stack_param_1, long stack_param_2);\n\nstatic int privileged_traced_syscall(int syscallno, long a0, long a1, long a2,\n                                     long a3, long a4, long a5) {\n  return _raw_syscall(syscallno, a0, a1, a2, a3, a4, a5,\n                      RR_PAGE_SYSCALL_PRIVILEGED_TRACED, 0, 0);\n}\n#define privileged_traced_syscall6(no, a0, a1, a2, a3, a4, a5)                 \\\n  privileged_traced_syscall(no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2,   \\\n                            (uintptr_t)a3, (uintptr_t)a4, (uintptr_t)a5)\n#define privileged_traced_syscall5(no, a0, a1, a2, a3, a4)                     \\\n  privileged_traced_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define privileged_traced_syscall4(no, a0, a1, a2, a3)                         \\\n  privileged_traced_syscall5(no, a0, a1, a2, a3, 0)\n#define privileged_traced_syscall3(no, a0, a1, a2)                             \\\n  privileged_traced_syscall4(no, a0, a1, a2, 0)\n#define privileged_traced_syscall2(no, a0, a1)                                 \\\n  privileged_traced_syscall3(no, a0, a1, 0)\n#define privileged_traced_syscall1(no, a0) privileged_traced_syscall2(no, a0, 0)\n#define privileged_traced_syscall0(no) privileged_traced_syscall1(no, 0)\n\n/**\n * Make a raw traced syscall using the params in |call|.\n */\nstatic long traced_raw_syscall(struct syscall_info* call) {\n  if (call->no == SYS_rrcall_rdtsc) {\n    // Handle this specially because the rrcall writes to a memory out-param\n    // and we need to actually modify the outgoing AX/DX registers instead.\n    uint32_t tsc[2];\n    privileged_traced_syscall1(SYS_rrcall_rdtsc, tsc);\n    // Overwrite RDX (syscall arg 3) with our TSC value.\n    call->args[2] = tsc[1];\n    return tsc[0];\n  }\n  /* FIXME: pass |call| to avoid pushing these on the stack\n   * again. */\n  return _raw_syscall(call->no, call->args[0], call->args[1], call->args[2],\n                      call->args[3], call->args[4], call->args[5],\n                      RR_PAGE_SYSCALL_TRACED, 0, 0);\n}\n\n/**\n * Make a raw traced syscall using the params in |call|, privileged.\n */\nstatic long privileged_traced_raw_syscall(const struct syscall_info* call) {\n  /* FIXME: pass |call| to avoid pushing these on the stack\n   * again. */\n  return _raw_syscall(call->no, call->args[0], call->args[1], call->args[2],\n                      call->args[3], call->args[4], call->args[5],\n                      RR_PAGE_SYSCALL_PRIVILEGED_TRACED, 0, 0);\n}\n\n#if defined(SYS_fcntl64)\n#define RR_FCNTL_SYSCALL SYS_fcntl64\n#else\n#define RR_FCNTL_SYSCALL SYS_fcntl\n#endif\n\nstatic int privileged_traced_fcntl(int fd, int cmd, ...) {\n  va_list ap;\n  void* arg;\n\n  va_start(ap, cmd);\n  arg = va_arg(ap, void*);\n  va_end(ap);\n\n  return privileged_traced_syscall3(RR_FCNTL_SYSCALL, fd, cmd, arg);\n}\n\nstatic pid_t privileged_traced_getpid(void) {\n  return privileged_traced_syscall0(SYS_getpid);\n}\n\nstatic pid_t privileged_traced_gettid(void) {\n  return privileged_traced_syscall0(SYS_gettid);\n}\n\nstatic int privileged_traced_perf_event_open(struct perf_event_attr* attr,\n                                             pid_t pid, int cpu, int group_fd,\n                                             unsigned long flags) {\n  return privileged_traced_syscall5(SYS_perf_event_open, attr, pid, cpu,\n                                    group_fd, flags);\n}\n\nstatic __attribute__((noreturn)) void privileged_traced_raise(int sig) {\n  privileged_traced_syscall2(SYS_kill, privileged_traced_getpid(), sig);\n  __builtin_unreachable();\n}\n\nstatic ssize_t privileged_traced_write(int fd, const void* buf, size_t count) {\n  return privileged_traced_syscall3(SYS_write, fd, buf, count);\n}\n\nstatic void logmsg(const char* msg) {\n  privileged_traced_write(STDERR_FILENO, msg, rrstrlen(msg));\n}\n\n#define STR_HELPER(x) #x\n#define STR(x) STR_HELPER(x)\n\n#ifndef NDEBUG\n#define assert(cond)                                                           \\\n  do {                                                                         \\\n    if (!(cond)) {                                                             \\\n      logmsg(__FILE__ \":\" STR(__LINE__) \": Assertion `\" #cond \"' failed.\\n\");  \\\n      privileged_traced_raise(SIGABRT);                                        \\\n    }                                                                          \\\n  } while (0)\n#else\n#define assert(cond)                                                           \\\n  do {                                                                         \\\n    __attribute__((unused)) size_t s = sizeof(cond);                           \\\n  } while (0)\n#endif\n\n#define fatal(msg)                                                             \\\n  do {                                                                         \\\n    logmsg(__FILE__ \":\" STR(__LINE__) \": Fatal error: \" msg \"\\n\");            \\\n    privileged_traced_raise(SIGABRT);                                          \\\n  } while (0)\n\n/**\n * Unlike |traced_syscall()|, this helper is implicitly \"raw\" (returns\n * the direct kernel return value), because the syscall hooks have to\n * save that raw return value.\n * This is only called from syscall wrappers that are doing a proper\n * buffered syscall.\n */\nstatic long untraced_syscall_full(int syscallno, long a0, long a1, long a2,\n                                  long a3, long a4, long a5,\n                                  void* syscall_instruction,\n                                  long stack_param_1, long stack_param_2) {\n  struct syscallbuf_record* rec = (struct syscallbuf_record*)buffer_last();\n  /* Ensure tools analyzing the replay can find the pending syscall result */\n  thread_locals->pending_untraced_syscall_result = &rec->ret;\n  long ret = _raw_syscall(syscallno, a0, a1, a2, a3, a4, a5,\n                          syscall_instruction, stack_param_1, stack_param_2);\n/* During replay, return the result that's already in the buffer, instead\n   of what our \"syscall\" returned. */\n#if defined(__i386__) || defined(__x86_64__)\n  /* On entry, during recording %eax/%rax are whatever the kernel returned\n   * but during replay they may be invalid (e.g. 0). During replay, reload\n   * %eax/%rax from |rec->ret|. At the end of this sequence all registers\n   * will match between recording and replay. We clobber the temporary\n   * in_replay register, and the condition codes, to ensure this.\n   * This all assumes the compiler doesn't create unnecessary temporaries\n   * holding values like |ret|. Inspection of generated code shows it doesn't.\n   */\n  unsigned char tmp_in_replay = *rr_page_replay_flag_addr();\n  __asm__(\"test %1,%1\\n\\t\"\n          \"cmovne %2,%0\\n\\t\"\n          \"xor %1,%1\\n\\t\"\n          : \"+a\"(ret), \"+c\"(tmp_in_replay)\n          : \"m\"(rec->ret)\n          : \"cc\");\n#elif defined(__aarch64__)\n  unsigned char *globals_in_replay = rr_page_replay_flag_addr();\n  long *rec_ret = &rec->ret;\n  __asm__(\"ldrb %w1, [%1]\\n\\t\" // tmp_in_replay = *rr_page_replay_flag_addr()\n          \"ldr %2, [%2]\\n\\t\" // tmp = rec->ret\n          \"cmp %w1, #0\\n\\t\"\n          \"csel %0, %0, %2, eq\\n\\t\" // ret = tmp_in_replay ? tmp : ret\n          \"subs %1, xzr, xzr\\n\\t\" // clear tmp_in_replay and flag\n          \"mov %2, xzr\\n\\t\" // clear tmp\n          : \"+r\"(ret), \"+r\"(globals_in_replay), \"+r\"(rec_ret)\n          :\n          : \"cc\");\n#else\n#error Unknown architecture\n#endif\n  return ret;\n}\n#define untraced_syscall_base(no, a0, a1, a2, a3, a4, a5, inst) \\\n  untraced_syscall_full(no, a0, a1, a2, a3, a4, a5, inst, 0, 0)\n#define untraced_syscall6(no, a0, a1, a2, a3, a4, a5)                          \\\n  untraced_syscall_base(no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2,       \\\n                        (uintptr_t)a3, (uintptr_t)a4, (uintptr_t)a5,           \\\n                        RR_PAGE_SYSCALL_UNTRACED_RECORDING_ONLY)\n#define untraced_syscall5(no, a0, a1, a2, a3, a4)                              \\\n  untraced_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define untraced_syscall4(no, a0, a1, a2, a3)                                  \\\n  untraced_syscall5(no, a0, a1, a2, a3, 0)\n#define untraced_syscall3(no, a0, a1, a2) untraced_syscall4(no, a0, a1, a2, 0)\n#define untraced_syscall2(no, a0, a1) untraced_syscall3(no, a0, a1, 0)\n#define untraced_syscall1(no, a0) untraced_syscall2(no, a0, 0)\n#define untraced_syscall0(no) untraced_syscall1(no, 0)\n\n#define untraced_replayed_syscall6(no, a0, a1, a2, a3, a4, a5)                 \\\n  untraced_syscall_base(no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2,       \\\n                        (uintptr_t)a3, (uintptr_t)a4, (uintptr_t)a5,           \\\n                        RR_PAGE_SYSCALL_UNTRACED)\n#define untraced_replayed_syscall5(no, a0, a1, a2, a3, a4)                     \\\n  untraced_replayed_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define untraced_replayed_syscall4(no, a0, a1, a2, a3)                         \\\n  untraced_replayed_syscall5(no, a0, a1, a2, a3, 0)\n#define untraced_replayed_syscall3(no, a0, a1, a2)                             \\\n  untraced_replayed_syscall4(no, a0, a1, a2, 0)\n#define untraced_replayed_syscall2(no, a0, a1)                                 \\\n  untraced_replayed_syscall3(no, a0, a1, 0)\n#define untraced_replayed_syscall1(no, a0) untraced_replayed_syscall2(no, a0, 0)\n#define untraced_replayed_syscall0(no) untraced_replayed_syscall1(no, 0)\n\nstatic long __attribute__((unused))\nuntraced_replay_assist_syscall_base(int syscallno, long a0, long a1, long a2,\n                                    long a3, long a4, long a5,\n                                    void* syscall_instruction)  {\n  struct syscallbuf_record* rec = (struct syscallbuf_record*)buffer_last();\n  rec->replay_assist = 1;\n  return untraced_syscall_base(syscallno, a0, a1, a2, a3, a4, a5, syscall_instruction);\n}\n\n#define untraced_replay_assist_syscall6(no, a0, a1, a2, a3, a4, a5)            \\\n  untraced_replay_assist_syscall_base(                                         \\\n                        no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2,       \\\n                        (uintptr_t)a3, (uintptr_t)a4, (uintptr_t)a5,           \\\n                        RR_PAGE_SYSCALL_UNTRACED_REPLAY_ASSIST)\n#define untraced_replay_assist_syscall5(no, a0, a1, a2, a3, a4)                \\\n  untraced_replay_assist_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define untraced_replay_assist_syscall4(no, a0, a1, a2, a3)                    \\\n  untraced_replay_assist_syscall5(no, a0, a1, a2, a3, 0)\n#define untraced_replay_assist_syscall3(no, a0, a1, a2)                        \\\n  untraced_replay_assist_syscall4(no, a0, a1, a2, 0)\n#define untraced_replay_assist_syscall2(no, a0, a1)                            \\\n  untraced_replay_assist_syscall3(no, a0, a1, 0)\n#define untraced_replay_assist_syscall1(no, a0)                                \\\n  untraced_replay_assist_syscall2(no, a0, 0)\n#define untraced_replay_assist_syscall0(no)                                    \\\n  untraced_replay_assist_syscall1(no, 0)\n\n// \"Privileged\" syscalls are not affected by the application's own seccomp\n// filters.\n#define privileged_untraced_syscall6(no, a0, a1, a2, a3, a4, a5)               \\\n  untraced_syscall_base(no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2,       \\\n                        (uintptr_t)a3, (uintptr_t)a4, (uintptr_t)a5,           \\\n                        RR_PAGE_SYSCALL_PRIVILEGED_UNTRACED_RECORDING_ONLY)\n#define privileged_untraced_syscall5(no, a0, a1, a2, a3, a4)                   \\\n  privileged_untraced_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define privileged_untraced_syscall4(no, a0, a1, a2, a3)                       \\\n  privileged_untraced_syscall5(no, a0, a1, a2, a3, 0)\n#define privileged_untraced_syscall3(no, a0, a1, a2)                           \\\n  privileged_untraced_syscall4(no, a0, a1, a2, 0)\n#define privileged_untraced_syscall2(no, a0, a1)                               \\\n  privileged_untraced_syscall3(no, a0, a1, 0)\n#define privileged_untraced_syscall1(no, a0)                                   \\\n  privileged_untraced_syscall2(no, a0, 0)\n#define privileged_untraced_syscall0(no) privileged_untraced_syscall1(no, 0)\n\n// \"Unrecorded\" syscalls are performed during recording only and are \"raw\";\n// they are not associated with syscallbuf records.\n#define privileged_unrecorded_syscall6(no, a0, a1, a2, a3, a4, a5)               \\\n  _raw_syscall(no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2,                  \\\n               (uintptr_t)a3, (uintptr_t)a4, (uintptr_t)a5,                      \\\n               RR_PAGE_SYSCALL_PRIVILEGED_UNTRACED_RECORDING_ONLY, 0, 0)\n#define privileged_unrecorded_syscall5(no, a0, a1, a2, a3, a4)                   \\\n  privileged_unrecorded_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define privileged_unrecorded_syscall4(no, a0, a1, a2, a3)                       \\\n  privileged_unrecorded_syscall5(no, a0, a1, a2, a3, 0)\n#define privileged_unrecorded_syscall3(no, a0, a1, a2)                           \\\n  privileged_unrecorded_syscall4(no, a0, a1, a2, 0)\n#define privileged_unrecorded_syscall2(no, a0, a1)                               \\\n  privileged_unrecorded_syscall3(no, a0, a1, 0)\n#define privileged_unrecorded_syscall1(no, a0)                                   \\\n  privileged_unrecorded_syscall2(no, a0, 0)\n#define privileged_unrecorded_syscall0(no) privileged_unrecorded_syscall1(no, 0)\n\n#define replay_only_syscall6(no, a0, a1, a2, a3, a4, a5)                       \\\n  _raw_syscall(no, (uintptr_t)a0, (uintptr_t)a1, (uintptr_t)a2, (uintptr_t)a3, \\\n               (uintptr_t)a4, (uintptr_t)a5,                                   \\\n               RR_PAGE_SYSCALL_PRIVILEGED_UNTRACED_REPLAY_ONLY, 0, 0)\n#define replay_only_syscall5(no, a0, a1, a2, a3, a4)                           \\\n  replay_only_syscall6(no, a0, a1, a2, a3, a4, 0)\n#define replay_only_syscall4(no, a0, a1, a2, a3)                               \\\n  replay_only_syscall5(no, a0, a1, a2, a3, 0)\n#define replay_only_syscall3(no, a0, a1, a2)                                   \\\n  replay_only_syscall4(no, a0, a1, a2, 0)\n#define replay_only_syscall2(no, a0, a1) replay_only_syscall3(no, a0, a1, 0)\n#define replay_only_syscall1(no, a0) replay_only_syscall2(no, a0, 0)\n#define replay_only_syscall0(no) replay_only_syscall1(no, 0)\n\nstatic int privileged_untraced_close(int fd) {\n  return privileged_unrecorded_syscall1(SYS_close, fd);\n}\n\nstatic int privileged_untraced_fcntl(int fd, int cmd, ...) {\n  va_list ap;\n  void* arg;\n\n  va_start(ap, cmd);\n  arg = va_arg(ap, void*);\n  va_end(ap);\n\n  return privileged_unrecorded_syscall3(RR_FCNTL_SYSCALL, fd, cmd, arg);\n}\n\n/**\n * Do what's necessary to set up buffers for the caller.\n * |untraced_syscall_ip| lets rr know where our untraced syscalls will\n * originate from.  |addr| is the address of the control socket the\n * child expects to connect to.  |msg| is a pre-prepared IPC that can\n * be used to share fds; |fdptr| is a pointer to the control-message\n * data buffer where the fd number being shared will be stored.\n * |args_vec| provides the tracer with preallocated space to make\n * socketcall syscalls.\n *\n * Return a pointer to the syscallbuf (with an initialized header\n * including the available size), if syscallbuf is enabled.\n *\n * This is a \"magic\" syscall implemented by rr.\n */\nstatic void rrcall_init_buffers(struct rrcall_init_buffers_params* args) {\n  privileged_traced_syscall1(SYS_rrcall_init_buffers, args);\n}\n\n/**\n * Return a counter that generates a signal targeted at this task\n * every time the task is descheduled |nr_descheds| times.\n */\nstatic int open_desched_event_counter(pid_t tid) {\n  struct perf_event_attr attr;\n  int tmp_fd, fd;\n  struct rr_f_owner_ex own;\n\n  local_memset(&attr, 0, sizeof(attr));\n  attr.size = sizeof(attr);\n  attr.type = PERF_TYPE_SOFTWARE;\n  switch (globals.context_switch_event_strategy) {\n    case STRATEGY_SW_CONTEXT_SWITCHES:\n      attr.config = PERF_COUNT_SW_CONTEXT_SWITCHES;\n      break;\n    case STRATEGY_RECORD_SWITCH:\n      attr.config = PERF_COUNT_SW_DUMMY;\n      attr.watermark = 1;\n      attr.context_switch = 1;\n      attr.wakeup_watermark = 1;\n      attr.exclude_kernel = 1;\n      attr.exclude_guest = 1;\n      break;\n    default:\n      fatal(\"Unknown strategy\");\n      break;\n  }\n  attr.disabled = 1;\n  attr.sample_period = 1;\n\n  tmp_fd = privileged_traced_perf_event_open(&attr, 0 /*self*/, -1 /*any cpu*/,\n                                             -1, 0);\n  if (0 > tmp_fd) {\n    fatal(\"Failed to perf_event_open\");\n  }\n  fd = privileged_traced_fcntl(tmp_fd, F_DUPFD_CLOEXEC,\n                               RR_DESCHED_EVENT_FLOOR_FD);\n  if (fd > 0) {\n    if (privileged_untraced_close(tmp_fd)) {\n      fatal(\"Failed to close tmp_fd\");\n    }\n  } else {\n    // We may be unable to find an fd above the RR_DESCHED_EVENT_FLOOR_FD (e.g\n    // because of a low ulimit). In that case, just use the tmp_fd we already\n    // have.\n    fd = tmp_fd;\n  }\n  if (privileged_untraced_fcntl(fd, F_SETFL, FASYNC)) {\n    fatal(\"Failed to fcntl(FASYNC) the desched counter\");\n  }\n  own.type = F_OWNER_TID;\n  own.pid = tid;\n  if (privileged_untraced_fcntl(fd, F_SETOWN_EX, &own)) {\n    fatal(\"Failed to fcntl(SETOWN_EX) the desched counter to this\");\n  }\n  if (privileged_untraced_fcntl(fd, F_SETSIG, globals.desched_sig)) {\n    fatal(\"Failed to fcntl(SETSIG) the desched counter\");\n  }\n\n  return fd;\n}\n\n/**\n * Initialize thread-local buffering state, if enabled and not already\n * initialized.\n */\nstatic void init_thread(void) {\n  struct rrcall_init_buffers_params args;\n\n  assert(process_inited);\n  if (thread_locals->thread_inited) {\n    return;\n  }\n  thread_locals->thread_inited = 1;\n\n  /* Do not do any syscall buffering in a DiversionSession! */\n  if (!buffer_enabled || globals.in_diversion) {\n    return;\n  }\n\n  /* NB: we want this setup emulated during replay. */\n  thread_locals->desched_counter_fd =\n      open_desched_event_counter(privileged_traced_gettid());\n\n  args.desched_counter_fd = thread_locals->desched_counter_fd;\n\n  /* Trap to rr: let the magic begin!\n   *\n   * If the desched signal is currently blocked, then the tracer\n   * will clear our TCB guard and we won't be able to buffer\n   * syscalls.  But the tracee will set the guard when (or if)\n   * the signal is unblocked. */\n  rrcall_init_buffers(&args);\n\n  thread_locals->cloned_file_data_fd = args.cloned_file_data_fd;\n  /* rr initializes the buffer header. */\n  thread_locals->buffer = args.syscallbuf_ptr;\n  thread_locals->buffer_size = args.syscallbuf_size;\n  thread_locals->scratch_buf = args.scratch_buf;\n  thread_locals->usable_scratch_size = args.usable_scratch_size;\n}\n\n// We don't include libc headers, since they include with Linux headers,\n// so declared this prototype manually\nextern const char* getenv(const char*);\n\n// getauxval is from glibc 2.16 (2012) - don't assume it exists.\nunsigned long getauxval(unsigned long type) __attribute__((weak));\n#ifndef AT_SYSINFO_EHDR\n#define AT_SYSINFO_EHDR 33\n#endif\n\nextern RR_HIDDEN long syscall_hook(struct syscall_info* call);\n\n/**\n * Initialize process-global buffering state, if enabled.\n * NOTE: constructors go into a special section by default so this won't\n * be counted as syscall-buffering code!\n */\nstatic void __attribute__((constructor)) init_process(void) {\n  struct rrcall_init_preload_params params;\n\n  extern char _syscallbuf_final_exit_instruction;\n  extern char _syscallbuf_code_start;\n  extern char _syscallbuf_code_end;\n  extern char do_breakpoint_fault_addr;\n\n#if defined(__i386__)\n  extern RR_HIDDEN void __morestack(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_3d_01_f0_ff_ff(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_90_90_90(void);\n  struct syscall_patch_hook syscall_patch_hooks[] = {\n    /* pthread_cond_broadcast has 'int 80' followed by\n     * cmp $-4095,%eax (in glibc-2.18-16.fc20.i686) */\n    { 0,\n      5,\n      { 0x3d, 0x01, 0xf0, 0xff, 0xff },\n      (uintptr_t)_syscall_hook_trampoline_3d_01_f0_ff_ff },\n    /* Our vdso syscall patch has 'int 80' followed by onp; nop; nop */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      3,\n      { 0x90, 0x90, 0x90 },\n      (uintptr_t)_syscall_hook_trampoline_90_90_90 }\n  };\n  extern char _get_pc_thunks_start;\n  extern char _get_pc_thunks_end;\n#elif defined(__x86_64__)\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_3d_01_f0_ff_ff(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_3d_00_f0_ff_ff(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_3d_00_f0_ff_ff(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_85_c0(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_8b_3c_24(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_89_45_f8(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_89_c3(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_5a_5e_c3(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_89_c2_f7_da(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_90_90_90(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_ba_01_00_00_00(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_89_c1_31_d2(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_c3_nop(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_40_80_f6_81(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_49_89_ca(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_89_c1(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_c1_e2_20(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_49_8b_44_24_28(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_4c_89_f7(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_4c_89_ff(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_49_c7_c1_ff_ff_ff_ff(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_b8_0e_00_00_00(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_b8_11_01_00_00(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_b8_ca_00_00_00(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_be_18_00_00_00(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_4c_8b_0d(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_89_e5(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_89_fb(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_8b_45_10(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_48_8d_b3_f0_08_00_00(void);\n  extern RR_HIDDEN void _syscall_hook_trampoline_nops(void);\n\n#define MOV_RDX_VARIANTS \\\n  MOV_RDX_TO_REG(48, d0) \\\n  MOV_RDX_TO_REG(48, d1) \\\n  MOV_RDX_TO_REG(48, d2) \\\n  MOV_RDX_TO_REG(48, d3) \\\n  MOV_RDX_TO_REG(48, d4) \\\n  MOV_RDX_TO_REG(48, d5) \\\n  MOV_RDX_TO_REG(48, d6) \\\n  MOV_RDX_TO_REG(48, d7) \\\n  MOV_RDX_TO_REG(49, d0) \\\n  MOV_RDX_TO_REG(49, d1) \\\n  MOV_RDX_TO_REG(49, d2) \\\n  MOV_RDX_TO_REG(49, d3) \\\n  MOV_RDX_TO_REG(49, d4) \\\n  MOV_RDX_TO_REG(49, d5) \\\n  MOV_RDX_TO_REG(49, d6) \\\n  MOV_RDX_TO_REG(49, d7)\n\n#define MOV_RDX_TO_REG(rex, op) \\\n  extern RR_HIDDEN void _syscall_hook_trampoline_##rex##_89_##op(void);\n  MOV_RDX_VARIANTS\n\n  struct syscall_patch_hook syscall_patch_hooks[] = {\n    /* Many glibc syscall wrappers (e.g. read) have 'syscall' followed\n     * by\n     * cmp $-4095,%rax (in glibc-2.18-16.fc20.x86_64) */\n    { 0,\n      6,\n      { 0x48, 0x3d, 0x01, 0xf0, 0xff, 0xff },\n      (uintptr_t)_syscall_hook_trampoline_48_3d_01_f0_ff_ff },\n    /* Many glibc syscall wrappers (e.g. __libc_recv) have 'syscall'\n     * followed by\n     * cmp $-4096,%rax (in glibc-2.18-16.fc20.x86_64) */\n    { 0,\n      6,\n      { 0x48, 0x3d, 0x00, 0xf0, 0xff, 0xff },\n      (uintptr_t)_syscall_hook_trampoline_48_3d_00_f0_ff_ff },\n    /* glibc-2.35-20.fc36.x86_64 start_thread has 'syscall'\n     * followed by 'cmp $-4096,%eax' */\n    { 0,\n      5,\n      { 0x3d, 0x00, 0xf0, 0xff, 0xff },\n      (uintptr_t)_syscall_hook_trampoline_3d_00_f0_ff_ff },\n    /* Some application has'syscall' followed by 'test %rax,%rax' */\n    { 0,\n      3,\n      { 0x48, 0x85, 0xc0 },\n      (uintptr_t)_syscall_hook_trampoline_48_85_c0 },\n    /* Many glibc syscall wrappers (e.g. read) have 'syscall' followed\n     * by\n     * mov (%rsp),%rdi (in glibc-2.18-16.fc20.x86_64) */\n    { 0,\n      4,\n      { 0x48, 0x8b, 0x3c, 0x24 },\n      (uintptr_t)_syscall_hook_trampoline_48_8b_3c_24 },\n    /* Some syscall wrappers have 'syscall' followed\n     * by\n     * mov %rax,-8(%rbp) */\n    { 0,\n      4,\n      { 0x48, 0x89, 0x45, 0xf8 },\n      (uintptr_t)_syscall_hook_trampoline_48_89_45_f8 },\n    /* Some syscall wrappers (e.g. read) have 'syscall' followed\n     * by\n     * mov %rax,%rbx */\n    { 0,\n      3,\n      { 0x48, 0x89, 0xc3 },\n      (uintptr_t)_syscall_hook_trampoline_48_89_c3 },\n    /* Some RDTSC instructions are followed by 'mov %rax,%rcx'. */\n    { 0,\n      3,\n      { 0x48, 0x89, 0xc1 },\n      (uintptr_t)_syscall_hook_trampoline_48_89_c1 },\n    /* __lll_unlock_wake has 'syscall' followed by\n     * pop %rdx; pop %rsi; ret */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      3,\n      { 0x5a, 0x5e, 0xc3 },\n      (uintptr_t)_syscall_hook_trampoline_5a_5e_c3 },\n    /* posix_fadvise64 has 'syscall' followed by\n     * mov %eax,%edx; neg %edx (in glibc-2.22-11.fc23.x86_64) */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      4,\n      { 0x89, 0xc2, 0xf7, 0xda },\n      (uintptr_t)_syscall_hook_trampoline_89_c2_f7_da },\n    /* Our VDSO vsyscall patches have 'syscall' followed by \"nop; nop;\n       nop\" */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      3,\n      { 0x90, 0x90, 0x90 },\n      (uintptr_t)_syscall_hook_trampoline_90_90_90 },\n    /* glibc-2.22-17.fc23.x86_64 has 'syscall' followed by 'mov $1,%rdx'\n     * in\n     * pthread_barrier_wait.\n     */\n    { 0,\n      5,\n      { 0xba, 0x01, 0x00, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_ba_01_00_00_00 },\n    /* pthread_sigmask has 'syscall' followed by 'mov %eax,%ecx; xor\n       %edx,%edx' */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      4,\n      { 0x89, 0xc1, 0x31, 0xd2 },\n      (uintptr_t)_syscall_hook_trampoline_89_c1_31_d2 },\n    /* getpid has 'syscall' followed by 'retq; nopl 0x0(%rax,%rax,1) */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      9,\n      { 0xc3, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_c3_nop },\n    /* liblsan internal_close has 'syscall' followed by 'retq; nopl 0x0(%rax,%rax,1) */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      6,\n      { 0xc3, 0x0f, 0x1f, 0x44, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_c3_nop },\n    /* glibc-2.29-15.fc30.x86_64 getpid has 'syscall' followed by 'retq; nopl 0x0(%rax) */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      5,\n      { 0xc3, 0x0f, 0x1f, 0x40, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_c3_nop },\n    /* liblsan internal_open has 'syscall' followed by 'retq; nopl (%rax) */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      4,\n      { 0xc3, 0x0f, 0x1f, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_c3_nop },\n    /* liblsan internal_dup2 has 'syscall' followed by 'retq; xchg %ax,%ax */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      3,\n      { 0xc3, 0x66, 0x90 },\n      (uintptr_t)_syscall_hook_trampoline_c3_nop },\n    /* Go runtime has 'syscall' followed by 'retq; int3; int3 */\n    { PATCH_IS_MULTIPLE_INSTRUCTIONS,\n      3,\n      { 0xc3, 0xcc, 0xcc },\n      (uintptr_t)_syscall_hook_trampoline_c3_nop },\n    /* glibc-2.31 on Ubuntu 20.04 has 'xor $0x81, %sil' followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      4,\n      { 0x40, 0x80, 0xf6, 0x81 },\n      (uintptr_t)_syscall_hook_trampoline_40_80_f6_81 },\n    /* DynamoRIO has 'mov r10, rcx' followed by 'syscall' */\n    {\n      PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      3,\n      { 0x49, 0x89, 0xca },\n      (uintptr_t)_syscall_hook_trampoline_49_89_ca },\n    /* Some applications have RDTSC followed by 'mov %rdx,any-reg' */\n#undef MOV_RDX_TO_REG\n#define MOV_RDX_TO_REG(rex, op) \\\n    {                         \\\n      0,                      \\\n      3,                      \\\n      { 0x##rex, 0x89, 0x##op }, \\\n      (uintptr_t)_syscall_hook_trampoline_##rex##_89_##op },\n    MOV_RDX_VARIANTS\n    /* Some application has RDTSC followed by 'mov xxxxxx(%rip),%r9' */\n    {\n      PATCH_NO_MATCH_TRAILING_4_BYTES,\n      7,\n      { 0x4c, 0x8b, 0x0d },\n      (uintptr_t)_syscall_hook_trampoline_4c_8b_0d },\n    /* Some application has RDTSC followed by 'shl $32,%rdx' */\n    {\n      0,\n      4,\n      { 0x48, 0xc1, 0xe2, 0x20 },\n      (uintptr_t)_syscall_hook_trampoline_48_c1_e2_20 },\n    /* glibc-2.35-20.fc36.x86_64 __pthread_create_2_1 application has\n       syscall followed by 'mov 0x28(%r12),%rax' */\n    {\n      0,\n      5,\n      { 0x49, 0x8b, 0x44, 0x24, 0x28 },\n      (uintptr_t)_syscall_hook_trampoline_49_8b_44_24_28 },\n    /* glibc-2.35-20.fc36.x86_64 thread_start has\n       'lea 0x8f0(%rbx),%rsi' followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      7,\n      { 0x48, 0x8d, 0xb3, 0xf0, 0x08, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_48_8d_b3_f0_08_00_00 },\n    /* Some application has 'mov %r14,%rdi' followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      3,\n      { 0x4c, 0x89, 0xf7 },\n      (uintptr_t)_syscall_hook_trampoline_4c_89_f7 },\n    /* Some application has 'mov %r15,%rdi' followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      3,\n      { 0x4c, 0x89, 0xff },\n      (uintptr_t)_syscall_hook_trampoline_4c_89_ff },\n    /* Some application has 'mov $0xffffffffffffffff,%r9' followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      7,\n      { 0x49, 0xc7, 0xc1, 0xff, 0xff, 0xff, 0xff },\n      (uintptr_t)_syscall_hook_trampoline_49_c7_c1_ff_ff_ff_ff },\n    /* glibc-2.35-20.fc36.x86_64 __pthread_create_2_1 has\n       'mov $0xe,%eax' (sigprocmask) followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      5,\n      { 0xb8, 0x0e, 0x00, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_b8_0e_00_00_00 },\n    /* glibc-2.35-20.fc36.x86_64 thread_start has\n       'mov $0x111,%eax' (set_robust_list) followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      5,\n      { 0xb8, 0x11, 0x01, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_b8_11_01_00_00 },\n    /* Some application has 'mov $0xca,%eax' (futex) followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      5,\n      { 0xb8, 0xca, 0x00, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_b8_ca_00_00_00 },\n    /* Some application has 'mov $0x18,%esi' (sizeof(robust_list)) followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      5,\n      { 0xbe, 0x18, 0x00, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_be_18_00_00_00 },\n    /* Some application has 'mov %rsp,%rbp' followed by 'rdtsc' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      3,\n      { 0x48, 0x89, 0xe5 },\n      (uintptr_t)_syscall_hook_trampoline_48_89_e5 },\n    /* Some application has 'mov %rdi,%rbx' followed by 'rdtsc' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      3,\n      { 0x48, 0x89, 0xfb },\n      (uintptr_t)_syscall_hook_trampoline_48_89_fb },\n    /* glibc-2.41-5.fc42.x86_64 has 'mov 0x10(%rbp),%rax' followed by 'syscall' */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST,\n      4,\n      { 0x48, 0x8b, 0x45, 0x10 },\n      (uintptr_t)_syscall_hook_trampoline_48_8b_45_10 },\n    /* Support explicit 5 byte nop (`nopl 0(%ax, %ax, 1)`) before 'rdtsc' or syscall (may ignore interfering branches) */\n    { PATCH_SYSCALL_INSTRUCTION_IS_LAST |\n      PATCH_IS_NOP_INSTRUCTIONS,\n      5,\n      { 0x0f, 0x1f, 0x44, 0x00, 0x00 },\n      (uintptr_t)_syscall_hook_trampoline_nops }\n  };\n#elif defined(__aarch64__)\n  extern RR_HIDDEN void _syscall_hook_trampoline_raw(void);\n  struct syscall_patch_hook syscall_patch_hooks[] = {\n    { 0, 4, { 0x01, 0, 0, 0xd4 }, (uintptr_t)_syscall_hook_trampoline_raw }\n  };\n#endif\n\n  assert(sizeof(struct preload_thread_locals) <= PRELOAD_THREAD_LOCALS_SIZE);\n\n  if (process_inited) {\n    return;\n  }\n\n  // Check if the rr page is mapped. We avoid a syscall if it looks like\n  // rr places librrpage as the vdso\n  // Use 1 as size since linux implementation of msync round it up to page size\n  if ((!getauxval || (getauxval(AT_SYSINFO_EHDR) != RR_PAGE_ADDR - 3*PRELOAD_LIBRARY_PAGE_SIZE)) &&\n      msync((void*)RR_PAGE_ADDR, 1, MS_ASYNC) != 0) {\n    // The RR page is not mapped - this process is not rr traced.\n    buffer_enabled = 0;\n    return;\n  }\n\n  buffer_enabled = !!getenv(SYSCALLBUF_ENABLED_ENV_VAR);\n\n  if (!buffer_enabled) {\n    // Don't risk executing the syscall before. If there is an external seccomp\n    // filter that doesn't like unknown syscalls, we risk breaking the recording.\n    return;\n  }\n\n  params.syscallbuf_enabled = buffer_enabled;\n\n#ifdef __i386__\n  params.get_pc_thunks_start = &_get_pc_thunks_start;\n  params.get_pc_thunks_end = &_get_pc_thunks_end;\n#else\n  params.get_pc_thunks_start = NULL;\n  params.get_pc_thunks_end = NULL;\n#endif\n  params.syscallbuf_code_start = &_syscallbuf_code_start;\n  params.syscallbuf_code_end = &_syscallbuf_code_end;\n  params.syscallbuf_final_exit_instruction =\n      &_syscallbuf_final_exit_instruction;\n  params.syscall_patch_hook_count =\n      sizeof(syscall_patch_hooks) / sizeof(syscall_patch_hooks[0]);\n  params.syscall_patch_hooks = syscall_patch_hooks;\n  params.globals = &globals;\n\n  globals.fdt_uniform = 1;\n  params.breakpoint_instr_addr = &do_breakpoint_fault_addr;\n  params.breakpoint_mode_sentinel = -1;\n  params.syscallbuf_syscall_hook = (void*)syscall_hook;\n\n  // We must not make any call into the syscall buffer in the init function\n  // in case a signal is delivered to us during initialization.\n  // This means that we must not call `_raw_syscall`.\n  int err = _traced_init_syscall(SYS_rrcall_init_preload, (long)&params,\n                                 0, 0, 0, 0, 0);\n  if (err != 0) {\n    // Check if the rr tracer is present by looking for the thread local page\n    // (mapped just after the rr page). If it is not present, we were\n    // preloaded without rr listening, which is allowed (e.g. after detach).\n    // Otherwise give an intelligent error message indicating that our connection\n    // to rr is broken.\n    // Use 1 as size since linux implementation of msync round it up to page size\n    if (msync((void*)RR_PAGE_ADDR + PRELOAD_LIBRARY_PAGE_SIZE, 1, MS_ASYNC) == 0) {\n      fatal(\"Failed to communicated with rr tracer.\\n\"\n            \"Perhaps a restrictive seccomp filter is in effect (e.g. docker?)?\\n\"\n            \"Adjust the seccomp filter to allow syscalls above 1000, disable it,\\n\"\n            \"or try using `rr record -n` (slow).\");\n    } else {\n      buffer_enabled = 0;\n      return;\n    }\n  }\n\n  process_inited = 1;\n}\n\n/**\n * syscall hooks start here.\n *\n * !!! NBB !!!: from here on, all code that executes within the\n * critical sections of transactions *MUST KEEP $ip IN THE SYSCALLBUF\n * CODE*.  That means no calls into libc, even for innocent-looking\n * functions like |memcpy()|.\n *\n * How syscall hooks operate:\n *\n * 1. The rr tracer monkey-patches __kernel_vsyscall() to jump to\n *    _syscall_hook_trampoline() above.\n * 2. When a call is made to __kernel_vsyscall(), it jumps to\n *    _syscall_hook_trampoline(), where the syscall params are\n *    packaged up into a call to syscall_hook() below.\n * 3. syscall_hook() dispatches to a syscall processor function.\n * 4. The syscall processor prepares a new record in the buffer. See\n *    struct syscallbuf_record for record fields.  If the buffer runs\n *    out of space, the processor function aborts and makes a traced\n *    syscall, trapping to rr.  rr then flushes the buffer.  Records\n *    are directly saved to trace, and a buffer-flush event is\n *    recorded without execution info because it's a synthetic event.\n * 5. Then, the syscall processor redirects all potential output\n *    for the syscall to the record (and corrects the overall size of\n *    the record while it does so).\n * 6. The syscall is invoked through a asm helper that does *not*\n *    ptrace-trap to rr.\n * 7. The syscall output, written on the buffer, is copied to the\n *    original pointers provided by the user.  Take notice that this\n *    part saves us the injection of the data on replay, as we only\n *    need to push the data to the buffer and the wrapper code will\n *    copy it to the user address for us.\n * 8. The return value and overall size are saved to the record.\n */\n\n/**\n * Call this and save the result at the start of every system call we\n * want to buffer. The result is a pointer into the record space. You\n * can add to this pointer to allocate space in the trace record.\n * However, do not read or write through this pointer until\n * start_commit_syscall() has been called.  And you *must* call\n * start_commit_syscall() after this is called, otherwise buffering\n * state will be inconsistent between syscalls.\n *\n * See |sys_clock_gettime()| for a simple example of how this helper\n * should be used to buffer outparam data.\n */\nstatic void* prep_syscall(void) {\n  /* We don't need to worry about a race between testing\n   * |locked| and setting it here. rr recording is responsible\n   * for ensuring signals are not delivered during\n   * syscall_buffer prologue and epilogue code.\n   *\n   * XXX except for synchronous signals generated in the syscall\n   * buffer code, while reading/writing user pointers */\n  buffer_hdr()->locked |= SYSCALLBUF_LOCKED_TRACEE;\n  /* \"Allocate\" space for a new syscall record, not including\n   * syscall outparam data. */\n  return buffer_last() + sizeof(struct syscallbuf_record);\n}\n\nstatic enum syscallbuf_fd_classes fd_class(int fd) {\n  if (fd < 0) {\n    return FD_CLASS_INVALID;\n  }\n  if (fd >= SYSCALLBUF_FDS_DISABLED_SIZE - 1) {\n    fd = SYSCALLBUF_FDS_DISABLED_SIZE - 1;\n  }\n  return globals.syscallbuf_fd_class[fd];\n}\n\nstatic int is_bufferable_fd(int fd) {\n  switch (fd_class(fd)) {\n    case FD_CLASS_INVALID:\n    case FD_CLASS_UNTRACED:\n      return 1;\n    default:\n      return 0;\n  }\n}\n\n/**\n * Like prep_syscall, but preps a syscall to operate on a particular fd. If\n * syscallbuf is disabled for this fd, returns NULL (in which case\n * start_commit_syscall will abort cleanly and a traced syscall will be used).\n * Allow negative fds to pass through; they'll either trigger an error or\n * receive special treatment by the kernel (e.g. AT_FDCWD).\n */\nstatic void* prep_syscall_for_fd(int fd) {\n  if (!is_bufferable_fd(fd)) {\n    return NULL;\n  }\n  return prep_syscall();\n}\n\nstatic void arm_desched_event(void) {\n  /* Don't trace the ioctl; doing so would trigger a flushing\n   * ptrace trap, which is exactly what this code is trying to\n   * avoid! :) Although we don't allocate extra space for these\n   * ioctl's, we do record that we called them; the replayer\n   * knows how to skip over them. */\n  if ((int)privileged_unrecorded_syscall3(SYS_ioctl,\n                                          thread_locals->desched_counter_fd,\n                                          PERF_EVENT_IOC_ENABLE, 0)) {\n    fatal(\"Failed to ENABLE counter\");\n  }\n}\n\nstatic void disarm_desched_event(void) {\n  /* See above. */\n  if ((int)privileged_unrecorded_syscall3(SYS_ioctl,\n                                          thread_locals->desched_counter_fd,\n                                          PERF_EVENT_IOC_DISABLE, 0)) {\n    fatal(\"Failed to DISABLE counter\");\n  }\n}\n\n/**\n * Return 1 if it's ok to proceed with buffering this system call.\n * Return 0 if we should trace the system call.\n * This must be checked before proceeding with the buffered system call.\n */\n/* (Negative numbers so as to not be valid syscall numbers, in case\n * the |int| arguments below are passed in the wrong order.) */\nenum { MAY_BLOCK = -1, WONT_BLOCK = -2 };\n\nstatic int fd_write_blocks(int fd) {\n  if (!globals.fdt_uniform) {\n    // If we're not uniform, it is possible for this fd to be untraced in one\n    // of the other tasks that share this fd table. Always assume it could block.\n    return MAY_BLOCK;\n  }\n  switch (fd_class(fd)) {\n    case FD_CLASS_UNTRACED:\n    case FD_CLASS_TRACED:\n      return MAY_BLOCK;\n    case FD_CLASS_INVALID:\n    case FD_CLASS_PROC_MEM:\n      return WONT_BLOCK;\n  }\n  fatal(\"Unknown or corrupted fd class\");\n}\n\nstatic int start_commit_buffered_syscall(int syscallno, void* record_end,\n                                         int blockness) {\n  void* record_start;\n  void* stored_end;\n  struct syscallbuf_record* rec;\n\n  if (!thread_locals->buffer) {\n    return 0;\n  }\n  record_start = buffer_last();\n  stored_end = record_start + stored_record_size(record_end - record_start);\n  rec = record_start;\n\n  if (stored_end < record_start + sizeof(struct syscallbuf_record)) {\n    /* Either a catastrophic buffer overflow or\n     * we failed to lock the buffer. Just bail out. */\n    return 0;\n  }\n  if (stored_end > (void*)buffer_end() - sizeof(struct syscallbuf_record)) {\n    /* Buffer overflow.\n     * Unlock the buffer and then execute the system call\n     * with a trap to rr.  Note that we reserve enough\n     * space in the buffer for the next prep_syscall(). */\n    buffer_hdr()->locked &= ~SYSCALLBUF_LOCKED_TRACEE;\n    return 0;\n  }\n  /* Store this breadcrumb so that the tracer can find out what\n   * syscall we're executing if our registers are in a weird\n   * state.  If we end up aborting this syscall, no worry, this\n   * will just be overwritten later.\n   *\n   * NBB: this *MUST* be set before the desched event is\n   * armed. */\n  rec->syscallno = syscallno;\n  rec->desched = MAY_BLOCK == blockness;\n  rec->size = record_end - record_start;\n\n  if (rec->desched) {\n    pid_t pid = 0;\n    pid_t tid = 0;\n    uid_t uid = 0;\n    if (impose_spurious_desched) {\n      pid = privileged_unrecorded_syscall0(SYS_getpid);\n      tid = privileged_unrecorded_syscall0(SYS_gettid);\n      uid = privileged_unrecorded_syscall0(SYS_getuid);\n    }\n\n    /* NB: the ordering of the next two statements is\n     * important.\n     *\n     * We set this flag to notify rr that it should pay\n     * attention to desched signals pending for this task.\n     * We have to set it *before* we arm the notification\n     * because we can't set the flag atomically with\n     * arming the event (too bad there's no ioctl() for\n     * querying the event enabled-ness state).  That's\n     * important because if the notification is armed,\n     * then rr must be confident that when it disarms the\n     * event, the tracee is at an execution point that\n     * *must not* need the desched event.\n     *\n     * If we were to set the flag non-atomically after the\n     * event was armed, then if a desched signal was\n     * delivered right at the instruction that set the\n     * flag, rr wouldn't know that it needed to advance\n     * the tracee to the untraced syscall entry point.\n     * (And if rr didn't do /that/, then the syscall might\n     * block without rr knowing it, and the recording\n     * session would deadlock.) */\n    buffer_hdr()->desched_signal_may_be_relevant = 1;\n    arm_desched_event();\n    if (impose_spurious_desched) {\n      siginfo_t si;\n      si.si_code = POLL_IN;\n      si.si_fd = thread_locals->desched_counter_fd;\n      si.si_pid = pid;\n      si.si_uid = uid;\n      privileged_unrecorded_syscall4(SYS_rt_tgsigqueueinfo, pid, tid,\n                                     globals.desched_sig,\n                                     &si);\n    }\n  }\n  return 1;\n}\n\nstatic void force_tick(void) {\n#if defined(__i386__) || defined(__x86_64__)\n  __asm__ __volatile__(\"je 1f\\n\\t\"\n                       \"1:\");\n#elif defined(__aarch64__)\n  __asm__ __volatile__(\"cbz xzr, 1f\\n\"\n                       \"1:\");\n#else\n#error Unknown architecture\n#endif\n}\n\nstatic void __attribute__((noinline)) do_breakpoint(size_t value)\n{\n  char *unsafe_value = ((char*)-1)-0xf;\n  char **safe_value = &unsafe_value;\n  uint64_t *breakpoint_value_addr = (uint64_t*)RR_PAGE_BREAKPOINT_VALUE;\n#if defined(__i386__) || defined(__x86_64__)\n  __asm__ __volatile__(\n                      \"mov (%1),%1\\n\\t\"\n                      \"cmp %0,%1\\n\\t\"\n                      \"cmove %3,%2\\n\\t\"\n                      // This will segfault if `value` matches\n                      // the `breakpoint_value` set by rr. We\n                      // detect this segfault and treat it\n                      // specially.\n                      \"do_breakpoint_fault_addr:\\n\\t\"\n                      \".global do_breakpoint_fault_addr\\n\\t\"\n                      \"mov (%2),%2\\n\\t\"\n                      \"xor %1,%1\\n\\t\"\n                      \"xor %2,%2\\n\\t\"\n                      \"xor %3,%3\\n\\t\"\n                      : \"+a\"(value), \"+D\"(breakpoint_value_addr),\n                        \"+S\"(safe_value), \"+c\"(unsafe_value)\n                      :\n                      : \"cc\", \"memory\");\n#elif defined(__aarch64__)\n  __asm__ __volatile__(\"ldr %1, [%1]\\n\\t\"\n                       \"cmp %0, %1\\n\\t\"\n                       \"csel %0, %3, %2, eq\\n\\t\"\n                       \"do_breakpoint_fault_addr:\\n\\t\"\n                       \".global do_breakpoint_fault_addr\\n\\t\"\n                       \"ldr %0, [%0]\\n\\t\"\n                       \"subs %0, xzr, xzr\\n\\t\"\n                       \"mov %1, xzr\\n\\t\"\n                       : \"+r\"(value), \"+r\"(breakpoint_value_addr),\n                         \"+r\"(safe_value), \"+r\"(unsafe_value)\n                       :\n                       : \"cc\", \"memory\");\n#else\n#error Unknown architecture\n#endif\n}\n\n/**\n * Commit the record for a buffered system call.  record_end can be\n * adjusted downward from what was passed to\n * start_commit_buffered_syscall, if not all of the initially\n * requested space is needed.  The result of this function should be\n * returned directly by the kernel syscall hook.\n */\nstatic long commit_raw_syscall(int syscallno, void* record_end, long ret) {\n  void* record_start = buffer_last();\n  struct syscallbuf_record* rec = record_start;\n  struct syscallbuf_hdr* hdr = buffer_hdr();\n  int call_breakpoint = 0;\n\n  assert(record_end >= record_start);\n  rec->size = record_end - record_start;\n\n  assert(hdr->locked);\n\n  /* NB: the ordering of this statement with the\n   * |disarm_desched_event()| call below is important.\n   *\n   * We clear this flag to notify rr that the may-block syscall\n   * has finished, so there's no danger of blocking anymore.\n   * (And thus the desched signal is no longer relevant.)  We\n   * have to clear this *before* disarming the event, because if\n   * rr sees the flag set, it has to PTRACE_SYSCALL this task to\n   * ensure it reaches an execution point where the desched\n   * signal is no longer relevant.  We have to use the ioctl()\n   * that disarms the event as a safe \"backstop\" that can be hit\n   * by the PTRACE_SYSCALL.\n   *\n   * If we were to clear the flag *after* disarming the event,\n   * and the signal arrived at the instruction that cleared the\n   * flag, and rr issued the PTRACE_SYSCALL, then this tracee\n   * could fly off to any unknown execution point, including an\n   * iloop.  So the recording session could livelock. */\n  hdr->desched_signal_may_be_relevant = 0;\n\n  if (rec->syscallno != syscallno) {\n    fatal(\"Record syscall number mismatch\");\n  }\n\n  if (hdr->abort_commit) {\n    /* We were descheduled in the middle of a may-block\n     * syscall, and it was recorded as a normal entry/exit\n     * pair.  So don't record the syscall in the buffer or\n     * replay will go haywire. */\n    hdr->abort_commit = 0;\n    hdr->failed_during_preparation = 0;\n    /* Clear the return value that rr puts there during replay */\n    rec->ret = 0;\n  } else {\n    rec->ret = ret;\n    // Finish 'rec' first before updating num_rec_bytes, since\n    // rr might read the record anytime after this update.\n    hdr->num_rec_bytes += stored_record_size(rec->size);\n    call_breakpoint = 1;\n  }\n\n  if (rec->desched) {\n    disarm_desched_event();\n  }\n  /* NBB: for may-block syscalls that are descheduled, the\n   * tracer uses the previous ioctl() as a stable point to reset\n   * the record counter.  Therefore nothing from here on in the\n   * current txn must touch the record counter (at least, must\n   * not assume it's unchanged). */\n\n  buffer_hdr()->locked &= ~SYSCALLBUF_LOCKED_TRACEE;\n\n  if (call_breakpoint) {\n    /* Call the breakpoint function corresponding to the record we just\n     * committed. This function just returns, but during replay it gives rr\n     * a chance to set a breakpoint for when a specific syscallbuf record\n     * has been processed.\n     */\n    do_breakpoint(hdr->num_rec_bytes/8);\n    /* Force a tick now.\n     * During replay, if an async event (SIGKILL) happens between committing the syscall\n     * above and before this forced tick, we can detect that because the number of ticks\n     * recorded for the SIGKILL will be less than or equal to the number of ticks reported\n     * when the replay hits do_breakpoint.\n     */\n    force_tick();\n  }\n\n  return ret;\n}\n\n/**\n * |ret_size| is the result of a syscall indicating how much data was returned\n * in scratch buffer |buf2|; this function copies that data to |buf| and returns\n * a pointer to the end of it. If there is no scratch buffer (|buf2| is NULL)\n * just returns |ptr|.\n */\nstatic void* copy_output_buffer(long ret_size, void* ptr, void* buf,\n                                void* buf2) {\n  if (!buf2) {\n    return ptr;\n  }\n  if (ret_size <= 0 || buffer_hdr()->failed_during_preparation) {\n    return buf2;\n  }\n  local_memcpy(buf, buf2, ret_size);\n  return buf2 + ret_size;\n}\n\n/**\n * Copy an input parameter to the syscallbuf where the kernel needs to\n * read and write it. During replay, we do a no-op self-copy in the buffer\n * so that the buffered data is not lost.\n * This code is written in assembler to ensure that the registers that receive\n * values differing between record and replay (%0, rsi/esi, and flags)\n * are reset to values that are the same between record and replay immediately\n * afterward. This guards against diverging register values leaking into\n * later code.\n * Use local_memcpy or plain assignment instead if the kernel is not going to\n * overwrite the values.\n */\nstatic void memcpy_input_parameter(void* buf, void* src, int size) {\n#if defined(__i386__) || defined(__x86_64__)\n  unsigned char tmp_in_replay = *rr_page_replay_flag_addr();\n  __asm__ __volatile__(\"test %0,%0\\n\\t\"\n                       \"cmovne %1,%2\\n\\t\"\n                       \"rep movsb\\n\\t\"\n                       \"xor %0,%0\\n\\t\"\n                       \"xor %2,%2\\n\\t\"\n                       : \"+a\"(tmp_in_replay), \"+D\"(buf), \"+S\"(src), \"+c\"(size)\n                       :\n                       : \"cc\", \"memory\");\n#elif defined(__aarch64__)\n  long c1;\n  long c2;\n  long size_long = size;\n  unsigned char *globals_in_replay = rr_page_replay_flag_addr();\n  __asm__ __volatile__(\"ldrb %w3, [%5]\\n\\t\"\n                       \"cmp %3, #0\\n\\t\" // eq -> record\n                       \"csel %1, %1, %0, eq\\n\\t\"\n                       \"subs %4, %2, 16\\n\\t\"\n                       \"b.lt 2f\\n\\t\"\n                       \"1:\\n\\t\"\n                       \"mov %2, %4\\n\\t\"\n                       \"ldp %3, %4, [%1], #16\\n\\t\"\n                       \"stp %3, %4, [%0], #16\\n\\t\"\n                       \"subs %4, %2, #16\\n\\t\"\n                       \"b.ge 1b\\n\"\n                       \"2:\\n\\t\"\n                       \"tbz %2, 3, 3f\\n\\t\"\n                       \"ldr %3, [%1], #8\\n\\t\"\n                       \"str %3, [%0], #8\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"tbz %2, 2, 3f\\n\\t\"\n                       \"ldr %w3, [%1], #4\\n\\t\"\n                       \"str %w3, [%0], #4\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"tbz %2, 1, 3f\\n\\t\"\n                       \"ldrh %w3, [%1], #2\\n\\t\"\n                       \"strh %w3, [%0], #2\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"tbz %2, 0, 3f\\n\\t\"\n                       \"ldrb %w3, [%1]\\n\\t\"\n                       \"strb %w3, [%0]\\n\\t\"\n                       \"3:\\n\\t\"\n                       \"subs %3, xzr, xzr\\n\\t\"\n                       \"mov %4, xzr\\n\\t\"\n                       \"mov %1, xzr\\n\\t\"\n                       : \"+r\"(buf), \"+r\"(src),\n                         \"+r\"(size_long), \"=&r\"(c1), \"=&r\"(c2), \"+r\"(globals_in_replay)\n                       :\n                       : \"cc\", \"memory\");\n#else\n#error Unknown architecture\n#endif\n}\n\n#if defined(__i386__) || defined(__x86_64__)\n/**\n * Perform an RDTSC, writing the output to 'buf', but only if we're in recording mode.\n * Otherwise 'buf' is unchanged.\n */\nstatic void rdtsc_recording_only(uint32_t buf[2]) {\n  unsigned char tmp_in_replay = *rr_page_replay_flag_addr();\n  __asm__ __volatile__(\"test %%al,%%al\\n\\t\"\n                       \"jne 1f\\n\\t\"\n                       \"rdtsc\\n\\t\"\n                       \"mov %%eax,(%1)\\n\\t\"\n                       \"mov %%edx,4(%1)\\n\\t\"\n                       \"1:\\n\\t\"\n                       \"xor %%eax,%%eax\\n\\t\"\n                       \"xor %%edx,%%edx\\n\\t\"\n                       : \"+a\"(tmp_in_replay)\n                       : \"S\"(buf)\n                       : \"cc\", \"memory\", \"rdx\");\n}\n#endif\n\n/**\n * During recording, we copy *real to *buf.\n * During replay, we copy *buf to *real.\n * Behaves like memcpy_input_parameter in terms of hiding differences between\n * recording and replay.\n */\nstatic void copy_futex_int(uint32_t* buf, uint32_t* real) {\n#if defined(__i386__) || defined(__x86_64__)\n  uint32_t tmp_in_replay = *rr_page_replay_flag_addr();\n  __asm__ __volatile__(\"test %0,%0\\n\\t\"\n                       \"mov %2,%0\\n\\t\"\n                       \"cmovne %1,%0\\n\\t\"\n                       \"mov %0,%1\\n\\t\"\n                       \"mov %0,%2\\n\\t\"\n                       /* This instruction is just to clear flags */\n                       \"xor %0,%0\\n\\t\"\n                       : \"+a\"(tmp_in_replay)\n                       : \"m\"(*buf), \"m\"(*real)\n                       : \"cc\", \"memory\");\n#elif defined(__aarch64__)\n  unsigned char *globals_in_replay = rr_page_replay_flag_addr();\n  __asm__ __volatile__(\"ldrb %w2, [%2]\\n\\t\"\n                       \"cmp %w2, #0\\n\\t\" // eq -> record\n                       \"csel %2, %1, %0, eq\\n\\t\"\n                       \"ldr %w2, [%2]\\n\\t\"\n                       \"csel %0, %0, %1, eq\\n\\t\"\n                       \"str %w2, [%0]\\n\\t\"\n                       \"subs %0, xzr, xzr\\n\\t\"\n                       \"mov %2, xzr\\n\\t\"\n                       : \"+r\"(buf), \"+r\"(real), \"+r\"(globals_in_replay)\n                       :\n                       : \"cc\", \"memory\");\n#else\n#error Unknown architecture\n#endif\n}\n\nstatic int trace_chaos_mode_syscalls = 0;\nstatic int buffer_chaos_mode_syscalls = 0;\n\nstatic int force_traced_syscall_for_chaos_mode(void) {\n  if (!globals.in_chaos) {\n    return 0;\n  }\n  while (1) {\n    if (buffer_chaos_mode_syscalls) {\n      --buffer_chaos_mode_syscalls;\n      return 0;\n    }\n    if (trace_chaos_mode_syscalls) {\n      --trace_chaos_mode_syscalls;\n      return 1;\n    }\n    /* force a run of up to 50 syscalls to be traced */\n    trace_chaos_mode_syscalls = (local_random() % 50) + 1;\n    buffer_chaos_mode_syscalls = (trace_chaos_mode_syscalls - 5) * 10;\n    if (buffer_chaos_mode_syscalls < 0) {\n      buffer_chaos_mode_syscalls = 0;\n    }\n  }\n}\n\n/* Keep syscalls in alphabetical order, please. */\n\n/**\n * Call this for syscalls that have no memory effects, don't block, and\n * aren't fd-related.\n */\nstatic long sys_generic_nonblocking(struct syscall_info* call) {\n  void* ptr = prep_syscall();\n  long ret;\n\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall6(call->no, call->args[0], call->args[1], call->args[2],\n                          call->args[3], call->args[4], call->args[5]);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\n/**\n * Call this for syscalls that have no memory effects, don't block, and\n * have an fd as their first parameter.\n */\nstatic long sys_generic_nonblocking_fd(struct syscall_info* call) {\n  int fd = call->args[0];\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall6(call->no, fd, call->args[1], call->args[2],\n                          call->args[3], call->args[4], call->args[5]);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\n/**\n * Call this for syscalls that have no memory effects, don't block, and\n * have an fd as their first parameter, and should run privileged.\n */\nstatic long privileged_sys_generic_nonblocking_fd(const struct syscall_info* call) {\n  int fd = call->args[0];\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return privileged_traced_raw_syscall(call);\n  }\n  ret = privileged_untraced_syscall6(call->no, fd, call->args[1], call->args[2],\n                                     call->args[3], call->args[4], call->args[5]);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\nstatic long sys_clock_gettime(struct syscall_info* call) {\n  const int syscallno = SYS_clock_gettime;\n  __kernel_clockid_t clk_id = (__kernel_clockid_t)call->args[0];\n  struct timespec* tp = (struct timespec*)call->args[1];\n\n  void* ptr = prep_syscall();\n  struct timespec* tp2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (tp) {\n    tp2 = ptr;\n    ptr += sizeof(*tp2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall2(syscallno, clk_id, tp2);\n  if (tp && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    /* This is small and won't get optimized to a memcpy call outside\n       our library. */\n    *tp = *tp2;\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n#ifdef SYS_clock_gettime64\n\nstruct kernel_timespec {\n  long long tv_sec;\n  long long tv_nsec;\n};\n\nstatic long sys_clock_gettime64(struct syscall_info* call) {\n  const int syscallno = SYS_clock_gettime64;\n  __kernel_clockid_t clk_id = (__kernel_clockid_t)call->args[0];\n  struct kernel_timespec* tp = (struct kernel_timespec*)call->args[1];\n\n  void* ptr = prep_syscall();\n  struct kernel_timespec* tp2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (tp) {\n    tp2 = ptr;\n    ptr += sizeof(*tp2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall2(syscallno, clk_id, tp2);\n  if (tp && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    /* This is small and won't get optimized to a memcpy call outside\n       our library. */\n    *tp = *tp2;\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#if defined(SYS_creat)\nstatic long sys_open(struct syscall_info* call);\nstatic long sys_creat(struct syscall_info* call) {\n  const char* pathname = (const char*)call->args[0];\n  __kernel_mode_t mode = call->args[1];\n  /* Thus sayeth the man page:\n   *\n   *   creat() is equivalent to open() with flags equal to\n   *   O_CREAT|O_WRONLY|O_TRUNC. */\n  struct syscall_info open_call =\n    { SYS_open, { (long)pathname, O_CREAT | O_TRUNC | O_WRONLY, mode } };\n  return sys_open(&open_call);\n}\n#endif\n\nstatic int sys_fcntl64_no_outparams(struct syscall_info* call) {\n  const int syscallno = RR_FCNTL_SYSCALL;\n  int fd = call->args[0];\n  int cmd = call->args[1];\n  long arg = call->args[2];\n\n  /* None of the no-outparam fcntl's are known to be\n   * may-block. */\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall3(syscallno, fd, cmd, arg);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic int sys_fcntl64_own_ex(struct syscall_info* call) {\n  const int syscallno = RR_FCNTL_SYSCALL;\n  int fd = call->args[0];\n  int cmd = call->args[1];\n  struct rr_f_owner_ex* owner = (struct rr_f_owner_ex*)call->args[2];\n\n  /* The OWN_EX fcntl's aren't may-block. */\n  void* ptr = prep_syscall_for_fd(fd);\n  struct rr_f_owner_ex* owner2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (owner) {\n    owner2 = ptr;\n    ptr += sizeof(*owner2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  if (owner2) {\n    memcpy_input_parameter(owner2, owner, sizeof(*owner2));\n  }\n  ret = untraced_syscall3(syscallno, fd, cmd, owner2);\n  if (owner2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(owner, owner2, sizeof(*owner));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic int sys_fcntl64_setlk64(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Releasing a lock could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = RR_FCNTL_SYSCALL;\n  int fd = call->args[0];\n  int cmd = call->args[1];\n  struct rr_flock64* lock = (struct rr_flock64*)call->args[2];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  struct rr_flock64* lock2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (lock) {\n    lock2 = ptr;\n    ptr += sizeof(*lock2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  if (lock2) {\n    memcpy_input_parameter(lock2, lock, sizeof(*lock2));\n  }\n  ret = untraced_syscall3(syscallno, fd, cmd, lock2);\n  if (lock2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(lock, lock2, sizeof(*lock));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic int sys_fcntl64_setlkw64(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Releasing a lock could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = RR_FCNTL_SYSCALL;\n  int fd = call->args[0];\n  int cmd = call->args[1];\n  struct rr_flock64* lock = (struct rr_flock64*)call->args[2];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall3(syscallno, fd, cmd, lock);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n#if defined(SYS_fcntl64)\n/* 32-bit system */\nstatic long sys_fcntl64(struct syscall_info* call)\n#else\n/* 64-bit system */\nstatic long sys_fcntl(struct syscall_info* call)\n#endif\n{\n  switch (call->args[1]) {\n    case F_SETFL:\n      if (call->args[2] == O_DIRECT) {\n        /* This needs to go to rr so we can disable syscall buffering\n           on this fd. */\n        return traced_raw_syscall(call);\n      }\n      /* Falls through. */\n    case F_DUPFD:\n    case F_GETFD:\n    case F_GETFL:\n    case F_GETOWN:\n    case F_SETFD:\n    case F_SETOWN:\n    case F_SETSIG:\n      return sys_fcntl64_no_outparams(call);\n\n    case F_GETOWN_EX:\n    case F_SETOWN_EX:\n      return sys_fcntl64_own_ex(call);\n\n#ifndef F_SETLK64\n#define F_SETLK64 13\n#endif\n    case F_SETLK64:\n#if !defined(SYS_fcntl64)\n    /* Also uses 64-bit flock format */\n    case F_SETLK:\n#endif\n      return sys_fcntl64_setlk64(call);\n\n#ifndef F_SETLKW64\n#define F_SETLKW64 14\n#endif\n    case F_SETLKW64:\n#if !defined(SYS_fcntl64)\n    /* Also uses 64-bit flock format */\n    case F_SETLKW:\n#endif\n      return sys_fcntl64_setlkw64(call);\n\n    default:\n      return traced_raw_syscall(call);\n  }\n}\n\nstatic long ret_buf_len(long ret, size_t len) {\n  if (ret < 0) {\n    return 0;\n  }\n  if (len > LONG_MAX) {\n    return ret;\n  }\n  return ret < (long)len ? ret : (long)len;\n}\n\nstatic long sys_flistxattr(struct syscall_info* call) {\n  const int syscallno = SYS_flistxattr;\n  int fd = (int)call->args[0];\n  char* buf = (char*)call->args[1];\n  size_t size = call->args[2];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  void* buf2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (buf && size > 0) {\n    buf2 = ptr;\n    ptr += size;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, fd, buf2, size);\n  ptr = copy_output_buffer(ret_buf_len(ret, size), ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_safe_nonblocking_ioctl(struct syscall_info* call) {\n  const int syscallno = SYS_ioctl;\n  int fd = call->args[0];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall3(syscallno, fd, call->args[1], call->args[2]);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_ioctl_fionread(struct syscall_info* call) {\n  const int syscallno = SYS_ioctl;\n  int fd = call->args[0];\n  int* value = (int*)call->args[2];\n  void* buf = NULL;\n\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  if (value) {\n    buf = ptr;\n    ptr += sizeof(*value);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall3(syscallno, fd, FIONREAD, buf);\n  if (buf && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(value, buf, sizeof(*value));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_ioctl(struct syscall_info* call) {\n  switch (call->args[1]) {\n    case BTRFS_IOC_CLONE_RANGE:\n    case FIOCLEX:\n    case FIONCLEX:\n      return sys_safe_nonblocking_ioctl(call);\n    case FIONREAD:\n      return sys_ioctl_fionread(call);\n    default:\n      return traced_raw_syscall(call);\n  }\n}\n\nstatic long sys_futex(struct syscall_info* call) {\n  enum {\n    FUTEX_USES_UADDR2 = 1 << 0,\n  };\n\n  /* This can make wakeups a lot more expensive. We assume\n     that wakeups are only used when some thread is actually waiting,\n     in which case we're at most doubling the overhead of the combined\n     wait + wakeup. */\n  if (globals.in_chaos) {\n    return traced_raw_syscall(call);\n  }\n\n  int op = call->args[1];\n  int flags = 0;\n  switch (FUTEX_CMD_MASK & op) {\n    case FUTEX_WAKE_BITSET:\n    case FUTEX_WAKE:\n      break;\n    case FUTEX_REQUEUE:\n    case FUTEX_CMP_REQUEUE:\n    case FUTEX_WAKE_OP:\n      flags |= FUTEX_USES_UADDR2;\n      break;\n\n    /* It turns out not to be worth buffering the FUTEX_WAIT*\n     * calls.  When a WAIT call is made, we know almost for sure\n     * that the tracee is going to be desched'd (otherwise the\n     * userspace CAS would have succeeded).  This is unlike\n     * read/write, f.e., where the vast majority of calls aren't\n     * desched'd and the overhead is worth it.  So all that\n     * buffering WAIT does is add the overhead of arming/disarming\n     * desched (which is a measurable perf loss).\n     *\n     * NB: don't ever try to buffer FUTEX_LOCK_PI; it requires\n     * special processing in the tracer process (in addition to\n     * not being worth doing for perf reasons). */\n    default:\n      return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_futex;\n  uint32_t* uaddr = (uint32_t*)call->args[0];\n  uint32_t val = call->args[2];\n  const struct timespec* timeout = (const struct timespec*)call->args[3];\n  uint32_t* uaddr2 = (uint32_t*)call->args[4];\n  uint32_t val3 = call->args[5];\n\n  void* ptr = prep_syscall();\n  uint32_t* saved_uaddr;\n  uint32_t* saved_uaddr2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  /* We have to record the value of the futex at kernel exit,\n   * but we can't substitute a scratch pointer for the uaddrs:\n   * the futex identity is the memory cell.  There are schemes\n   * that would allow us to use scratch futexes, but they get\n   * complicated quickly. */\n  saved_uaddr = ptr;\n  ptr += sizeof(*saved_uaddr);\n  if (FUTEX_USES_UADDR2 & flags) {\n    saved_uaddr2 = ptr;\n    ptr += sizeof(*saved_uaddr2);\n  }\n  /* See above; it's not worth buffering may-block futex\n   * calls. */\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall6(syscallno, uaddr, op, val, timeout, uaddr2, val3);\n  /* During recording, save the real outparams to the buffer.\n   * During replay, save the values from the buffer to the real outparams.\n   *\n   * The *ONLY* reason it's correct for us to read the outparams\n   * carelessly is that rr protects this syscallbuf\n   * transaction as as a critical section. */\n  copy_futex_int(saved_uaddr, uaddr);\n  if (saved_uaddr2) {\n    copy_futex_int(saved_uaddr2, uaddr2);\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_getrandom(struct syscall_info* call) {\n  void* buf = (void*)call->args[0];\n  size_t buf_len = (size_t)call->args[1];\n  unsigned int flags = (unsigned int)call->args[2];\n  const int syscallno = SYS_getrandom;\n\n  void* ptr = prep_syscall();\n  void* buf2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (buf && buf_len > 0) {\n    buf2 = ptr;\n    ptr += buf_len;\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, (flags & GRND_NONBLOCK) ? WONT_BLOCK : MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(call->no, buf2, buf_len, flags);\n  ptr = copy_output_buffer(ret, ptr, buf, buf2);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\nstatic long sys_generic_getdents(struct syscall_info* call) {\n  int fd = (int)call->args[0];\n  void* buf = (void*)call->args[1];\n  unsigned int count = (unsigned int)call->args[2];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  void* buf2 = NULL;\n  long ret;\n\n  if (buf && count > 0) {\n    buf2 = ptr;\n    ptr += count;\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(call->no, fd, buf2, count);\n  ptr = copy_output_buffer(ret, ptr, buf, buf2);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\n#if defined(SYS_getdents)\nstatic long sys_getdents(struct syscall_info* call) {\n  return sys_generic_getdents(call);\n}\n#endif\n\nstatic long sys_getdents64(struct syscall_info* call) {\n  return sys_generic_getdents(call);\n}\n\nstatic long sys_gettimeofday(struct syscall_info* call) {\n  const int syscallno = SYS_gettimeofday;\n  struct timeval* tp = (struct timeval*)call->args[0];\n  struct timezone* tzp = (struct timezone*)call->args[1];\n\n  /* XXX it seems odd that clock_gettime() is spec'd to be\n   * async-signal-safe while gettimeofday() isn't, but that's\n   * what the docs say! */\n  void* ptr = prep_syscall();\n  struct timeval* tp2 = NULL;\n  struct timezone* tzp2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (tp) {\n    tp2 = ptr;\n    ptr += sizeof(*tp2);\n  }\n  if (tzp) {\n    tzp2 = ptr;\n    ptr += sizeof(*tzp2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall2(syscallno, tp2, tzp2);\n  if (ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    if (tp) {\n      /* This is small and won't get optimized to a memcpy call outside\n         our library. */\n      *tp = *tp2;\n    }\n    if (tzp) {\n      /* This is small and won't get optimized to a memcpy call outside\n         our library. */\n      *tzp = *tzp2;\n    }\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_generic_getxattr(struct syscall_info* call) {\n  const char* path = (const char*)call->args[0];\n  const char* name = (const char*)call->args[1];\n  void* value = (void*)call->args[2];\n  size_t size = call->args[3];\n\n  void* ptr = prep_syscall();\n  void* value2 = NULL;\n  long ret;\n\n  if (value && size > 0) {\n    value2 = ptr;\n    ptr += size;\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall4(call->no, path, name, value2, size);\n  ptr = copy_output_buffer(ret_buf_len(ret, size), ptr, value, value2);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\nstatic long sys_getxattr(struct syscall_info* call) {\n  return sys_generic_getxattr(call);\n}\n\nstatic long sys_lgetxattr(struct syscall_info* call) {\n  return sys_generic_getxattr(call);\n}\n\nstatic long sys_fgetxattr(struct syscall_info* call) {\n  int fd = (int)call->args[0];\n  const char* name = (const char*)call->args[1];\n  void* value = (void*)call->args[2];\n  size_t size = call->args[3];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  void* value2 = NULL;\n  long ret;\n\n  if (value && size > 0) {\n    value2 = ptr;\n    ptr += size;\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall4(call->no, fd, name, value2, size);\n  ptr = copy_output_buffer(ret_buf_len(ret, size), ptr, value, value2);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\nstatic long sys_generic_listxattr(struct syscall_info* call) {\n  char* path = (char*)call->args[0];\n  char* buf = (char*)call->args[1];\n  size_t size = call->args[2];\n\n  void* ptr = prep_syscall();\n  void* buf2 = NULL;\n  long ret;\n\n  if (buf && size > 0) {\n    buf2 = ptr;\n    ptr += size;\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(call->no, path, buf2, size);\n  ptr = copy_output_buffer(ret_buf_len(ret, size), ptr, buf, buf2);\n  return commit_raw_syscall(call->no, ptr, ret);\n}\n\nstatic long sys_listxattr(struct syscall_info* call) {\n  return sys_generic_listxattr(call);\n}\n\nstatic long sys_llistxattr(struct syscall_info* call) {\n  return sys_generic_listxattr(call);\n}\n\n#if defined(SYS__llseek)\nstatic long sys__llseek(struct syscall_info* call) {\n  const int syscallno = SYS__llseek;\n  int fd = call->args[0];\n  unsigned long offset_high = call->args[1];\n  unsigned long offset_low = call->args[2];\n  __kernel_loff_t* result = (__kernel_loff_t*)call->args[3];\n  unsigned int whence = call->args[4];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  __kernel_loff_t* result2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (result) {\n    result2 = ptr;\n    ptr += sizeof(*result2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  if (result2) {\n    memcpy_input_parameter(result2, result, sizeof(*result2));\n  }\n  ret = untraced_syscall5(syscallno, fd, offset_high, offset_low, result2,\n                          whence);\n  if (result2) {\n    *result = *result2;\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\nstatic long sys_madvise(struct syscall_info* call) {\n  const int syscallno = SYS_madvise;\n  void* addr = (void*)call->args[0];\n  size_t length = call->args[1];\n  int advice = call->args[2];\n\n  void* ptr;\n  long ret;\n\n  switch (advice) {\n    // Advice values that we buffer and are ok to pass through to the kernel\n    // directly.\n    case MADV_NORMAL:\n    case MADV_RANDOM:\n    case MADV_SEQUENTIAL:\n    case MADV_WILLNEED:\n    case MADV_MERGEABLE:\n    case MADV_UNMERGEABLE:\n    case MADV_HUGEPAGE:\n    case MADV_NOHUGEPAGE:\n    case MADV_DONTDUMP:\n    case MADV_DODUMP:\n    // Advice values that we buffer but require special handling.\n    case MADV_DONTNEED:\n    case MADV_FREE:\n      break;\n    default:\n      return traced_raw_syscall(call);\n  }\n\n  ptr = prep_syscall();\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  if (advice == MADV_FREE) {\n    // See record_syscall. We disallow MADV_FREE because it creates\n    // nondeterminism. NB: Since we veto this, we *don't* need to\n    // execute it during replay.\n    ret = privileged_untraced_syscall3(syscallno, addr, length, -1);\n    return commit_raw_syscall(syscallno, ptr, ret);\n  } else if (advice == MADV_DONTNEED) {\n    ret = privileged_untraced_syscall3(syscallno, addr, length, MADV_COLD);\n    commit_raw_syscall(syscallno, ptr, ret);\n    if (ret < 0) {\n      return traced_raw_syscall(call);\n    }\n    ptr = prep_syscall();\n    if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n      return traced_raw_syscall(call);\n    }\n  }\n\n  /* Ensure this syscall happens during replay. In particular MADV_DONTNEED\n   * must be executed.\n   */\n  ret = untraced_replayed_syscall3(syscallno, addr, length, advice);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_mprotect(struct syscall_info* call) {\n  const int syscallno = SYS_mprotect;\n  void* addr = (void*)call->args[0];\n  size_t length = call->args[1];\n  int prot = call->args[2];\n  struct mprotect_record* mrec;\n\n  void* ptr;\n  long ret;\n\n  if ((prot & ~(PROT_READ | PROT_WRITE | PROT_EXEC)) || !buffer_hdr() ||\n      buffer_hdr()->mprotect_record_count >= MPROTECT_RECORD_COUNT) {\n    return traced_raw_syscall(call);\n  }\n\n  ptr = prep_syscall();\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  mrec = &globals.mprotect_records[buffer_hdr()->mprotect_record_count++];\n  mrec->start = (uint64_t)(uintptr_t)addr;\n  mrec->size = length;\n  mrec->prot = prot;\n  ret = untraced_replayed_syscall3(syscallno, addr, length, prot);\n  if (ret < 0 && ret != -ENOMEM) {\n    /* indicate that nothing was mprotected */\n    mrec->size = 0;\n  }\n  buffer_hdr()->mprotect_record_count_completed++;\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic int supported_open(const char* file_name, int flags) {\n  if (!file_name) {\n    /* XXXkhuey what about other bogus but non-null pointers?\n       We're going to crash below. */\n    return 0;\n  }\n\n  if (is_gcrypt_deny_file(file_name)) {\n    /* This needs to be a traced syscall. We want to return an\n       open file even if the file doesn't exist and the untraced syscall\n       returns ENOENT. */\n    return 0;\n  }\n  if (flags & O_DIRECT) {\n    /* O_DIRECT needs to go to rr so we can blacklist the file for\n       syscall buffering. */\n    return 0;\n  }\n  /* Writeable opens need to go to rr to be checked in case\n     they could write to a mapped file.\n     But if they're O_EXCL | O_CREAT, a new file must be created\n     so that will be fine. */\n  return !(flags & (O_RDWR | O_WRONLY)) ||\n    (flags & (O_EXCL | O_CREAT)) == (O_EXCL | O_CREAT);\n}\n\nstatic long sys_readlinkat(struct syscall_info* call, int privileged);\n\nstruct check_open_state {\n  uint8_t did_abort;\n  uint8_t did_fail_during_preparation;\n};\n\nstatic int check_file_open_ok(struct syscall_info* call, int ret, struct check_open_state state) {\n  /* If we failed during preparation then a SIGSYS or similar prevented the syscall\n     from doing anything, so there is nothing for us to do here and we shouldn't\n     try to interpret the \"syscall result\". */\n  if (state.did_fail_during_preparation || ret < 0) {\n    return ret;\n  }\n  char buf[100];\n  sprintf(buf, \"/proc/self/fd/%d\", ret);\n  char link[PATH_MAX];\n  long link_ret;\n  if (state.did_abort) {\n    /* Don't add any new syscallbuf records, that won't work. */\n    link_ret = privileged_traced_syscall4(SYS_readlinkat, -1, (long)buf, (long)link, sizeof(link));\n  } else {\n    struct syscall_info readlink_call =\n      { SYS_readlinkat, { -1, (long)buf, (long)link, sizeof(link), 0, 0 } };\n    link_ret = sys_readlinkat(&readlink_call, 1);\n  }\n  if (link_ret >= 0 && link_ret < (ssize_t)sizeof(link)) {\n    link[link_ret] = 0;\n    if (allow_buffered_open(link)) {\n      return ret;\n    }\n  }\n  /* Clean up by closing the file descriptor we should not have opened and\n     opening it again, traced this time.\n     Use a privileged traced syscall for the close to ensure it\n     can't fail due to lack of privilege.\n     We expect this to return an error.\n     We could try an untraced close syscall here, falling back to traced\n     syscall, but that's a bit more complicated and we're already on\n     the slow (and hopefully rare) path. */\n  privileged_traced_syscall1(SYS_close, ret);\n  return traced_raw_syscall(call);\n}\n\nstatic struct check_open_state capture_check_open_state(void) {\n  struct check_open_state ret;\n  ret.did_abort = buffer_hdr()->abort_commit;\n  ret.did_fail_during_preparation = buffer_hdr()->failed_during_preparation;\n  return ret;\n}\n\n#if defined(SYS_open)\nstatic long sys_open(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Opening a FIFO could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_open;\n  const char* pathname = (const char*)call->args[0];\n  int flags = call->args[1];\n  __kernel_mode_t mode = call->args[2];\n  void* ptr;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!supported_open(pathname, flags)) {\n    return traced_raw_syscall(call);\n  }\n\n  ptr = prep_syscall();\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, pathname, flags, mode);\n  struct check_open_state state = capture_check_open_state();\n  ret = commit_raw_syscall(syscallno, ptr, ret);\n  return check_file_open_ok(call, ret, state);\n}\n#endif\n\nstatic long sys_openat(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Opening a FIFO could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_openat;\n  int dirfd = call->args[0];\n  const char* pathname = (const char*)call->args[1];\n  int flags = call->args[2];\n  __kernel_mode_t mode = call->args[3];\n  void* ptr;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!supported_open(pathname, flags)) {\n    return traced_raw_syscall(call);\n  }\n\n  ptr = prep_syscall();\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall4(syscallno, dirfd, pathname, flags, mode);\n  struct check_open_state state = capture_check_open_state();\n  ret = commit_raw_syscall(syscallno, ptr, ret);\n  return check_file_open_ok(call, ret, state);\n}\n\n#if defined(SYS_openat2)\nstatic long sys_openat2(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Opening a FIFO could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_openat2;\n  int dirfd = call->args[0];\n  const char* pathname = (const char*)call->args[1];\n  struct open_how *how = (struct open_how *)call->args[2];\n  size_t how_size = call->args[3];\n\n  void* ptr;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!supported_open(pathname, how->flags)) {\n    return traced_raw_syscall(call);\n  }\n\n  ptr = prep_syscall();\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall4(syscallno, dirfd, pathname, how, how_size);\n  struct check_open_state state = capture_check_open_state();\n  ret = commit_raw_syscall(syscallno, ptr, ret);\n  return check_file_open_ok(call, ret, state);\n}\n#endif\n\n#if defined(SYS_poll) || defined(SYS_ppoll)\n/**\n * Make this function external so desched_ticks.py can set a breakpoint on it.\n * Make it visibility-\"protected\" so that our local definition binds to it\n * directly and doesn't go through a PLT thunk (which would mean temporarily\n * leaving syscallbuf code).\n */\n__attribute__((visibility(\"protected\"))) void __before_poll_syscall_breakpoint(\n    void) {}\n#endif\n\n#if defined(SYS_poll)\nstatic long sys_poll(struct syscall_info* call) {\n  const int syscallno = SYS_poll;\n  struct pollfd* fds = (struct pollfd*)call->args[0];\n  unsigned int nfds = call->args[1];\n  int timeout = call->args[2];\n\n  void* ptr = prep_syscall();\n  struct pollfd* fds2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (fds && nfds > 0) {\n    fds2 = ptr;\n    ptr += nfds * sizeof(*fds2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  if (fds2) {\n    memcpy_input_parameter(fds2, fds, nfds * sizeof(*fds2));\n  }\n\n  __before_poll_syscall_breakpoint();\n\n  /* Try a no-timeout version of the syscall first. If this doesn't return\n     anything, and we should have blocked, we'll try again with a traced syscall\n     which will be the one that blocks. This usually avoids the\n     need to trigger desched logic, which adds overhead, especially the\n     rrcall_notify_syscall_hook_exit that gets triggered. */\n  ret = untraced_syscall3(syscallno, fds2, nfds, 0);\n\n  if (fds2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    /* NB: even when poll returns 0 indicating no pending\n     * fds, it still sets each .revent outparam to 0.\n     * (Reasonably.)  So we always need to copy on return\n     * value >= 0.\n     * It's important that we not copy when there's an error.\n     * The syscallbuf commit might have been aborted, which means\n     * during replay fds2 might be non-recorded data, so we'd be\n     * incorrectly trashing 'fds'. */\n    local_memcpy(fds, fds2, nfds * sizeof(*fds));\n  }\n  commit_raw_syscall(syscallno, ptr, ret);\n\n  if (ret != 0 || timeout == 0) {\n    return ret;\n  }\n  /* The syscall didn't return anything, and we should have blocked.\n     Just perform a raw syscall now since we're almost certain to block. */\n  return traced_raw_syscall(call);\n}\n#endif\n\n#if defined(SYS_ppoll)\nstatic long sys_ppoll(struct syscall_info* call) {\n  const int syscallno = SYS_ppoll;\n  struct pollfd* fds = (struct pollfd*)call->args[0];\n  unsigned int nfds = call->args[1];\n  const struct timespec *tmo_p = (struct timespec*)call->args[2];\n  const kernel_sigset_t *sigmask = (const kernel_sigset_t*)call->args[3];\n  size_t sigmask_size = call->args[4];\n\n  if (sigmask) {\n    // See ppoll_deliver. ppoll calls that temporarily change the\n    // sigmask are hard to handle; we may get a signal that we can't\n    // deliver later because it's blocked by the application.\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall();\n  struct pollfd* fds2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (fds && nfds > 0) {\n    fds2 = ptr;\n    ptr += nfds * sizeof(*fds2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  if (fds2) {\n    memcpy_input_parameter(fds2, fds, nfds * sizeof(*fds2));\n  }\n\n  __before_poll_syscall_breakpoint();\n\n  /* Try a no-timeout version of the syscall first. If this doesn't return\n     anything, and we should have blocked, we'll try again with a traced syscall\n     which will be the one that blocks. This usually avoids the\n     need to trigger desched logic, which adds overhead, especially the\n     rrcall_notify_syscall_hook_exit that gets triggered. */\n  const struct timespec tmo0 = {0, 0};\n  ret = untraced_syscall5(syscallno, fds2, nfds, &tmo0, sigmask, sigmask_size);\n\n  if (fds2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    /* NB: even when poll returns 0 indicating no pending\n     * fds, it still sets each .revent outparam to 0.\n     * (Reasonably.)  So we always need to copy on return\n     * value >= 0.\n     * It's important that we not copy when there's an error.\n     * The syscallbuf commit might have been aborted, which means\n     * during replay fds2 might be non-recorded data, so we'd be\n     * incorrectly trashing 'fds'. */\n    local_memcpy(fds, fds2, nfds * sizeof(*fds));\n  }\n  commit_raw_syscall(syscallno, ptr, ret);\n\n  if (ret != 0 || (tmo_p && tmo_p->tv_sec == 0 && tmo_p->tv_nsec == 0)) {\n    return ret;\n  }\n  /* The syscall didn't return anything, and we should have blocked.\n     Just perform a raw syscall now since we're almost certain to block. */\n  return traced_raw_syscall(call);\n}\n#endif\n\nstatic long sys_epoll_wait(struct syscall_info* call) {\n  int epfd = call->args[0];\n  struct epoll_event* events = (struct epoll_event*)call->args[1];\n  int max_events = call->args[2];\n  int timeout = call->args[3];\n\n  void* ptr;\n  struct epoll_event* events2 = NULL;\n  long ret;\n\n  ptr = prep_syscall();\n\n  assert(SYS_epoll_pwait == call->no\n#if defined(SYS_epoll_wait)\n        || SYS_epoll_wait == call->no\n#endif\n  );\n\n  if (events && max_events > 0) {\n    events2 = ptr;\n    ptr += max_events * sizeof(*events2);\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  /* Try a no-timeout version of the syscall first. If this doesn't return\n     anything, and we should have blocked, we'll try again with a traced syscall\n     which will be the one that blocks. This usually avoids the\n     need to trigger desched logic, which adds overhead, especially the\n     rrcall_notify_syscall_hook_exit that gets triggered.\n     N.B.: SYS_epoll_wait only has four arguments, but we don't care\n     if the last two arguments are garbage */\n  ret = untraced_syscall6(call->no, epfd, events2, max_events, 0,\n    call->args[4] /*sigmask*/, call->args[5] /*sizeof(*sigmask)*/);\n\n  ptr = copy_output_buffer(ret * sizeof(*events2), ptr, events, events2);\n  ret = commit_raw_syscall(call->no, ptr, ret);\n  if (timeout == 0 || (ret != EINTR && ret != 0)) {\n    /* If we got some real results, or a non-EINTR error, we can just\n       return it directly.\n       If we got no results and the timeout was 0, we can just return 0.\n       If we got EINTR and the timeout was 0, a signal must have\n       interrupted the syscall (not sure if this can happen...). If the signal\n       needs to be handled, we'll handle it as we exit the syscallbuf.\n       Returning EINTR is fine because that's what the syscall would have\n       returned had it run traced. (We didn't enable the desched signal\n       so no extra signals could have affected our untraced syscall that\n       could not have been delivered to a traced syscall.) */\n    return ret;\n  }\n  /* Some timeout was requested and either we got no results or we got\n     EINTR.\n     In the former case we just have to wait, so we do a traced syscall.\n     In the latter case, the syscall must have been interrupted by a\n     signal (which rr will have handled or stashed, and won't deliver until\n     we exit syscallbuf code or do a traced syscall). The kernel doesn't\n     automatically restart the syscall because of a longstanding bug (as of\n     4.17 anyway). Doing a traced syscall will allow a stashed signal to be\n     processed (if necessary) and allow things to proceed normally after that.\n     Note that if rr decides to deliver a signal to the tracee, that will\n     itself interrupt the syscall and cause it to return EINTR just as\n     would happen without rr.\n  */\n  return traced_raw_syscall(call);\n}\n\nstruct timespec64 {\n  uint64_t tv_sec;\n  uint64_t tv_nsec;\n};\n\n#ifdef SYS_epoll_pwait2\nstatic long sys_epoll_pwait2(struct syscall_info* call) {\n  int epfd = call->args[0];\n  struct epoll_event* events = (struct epoll_event*)call->args[1];\n  int max_events = call->args[2];\n  struct timespec64* timeout = (struct timespec64*)call->args[3];\n\n  void* ptr;\n  struct epoll_event* events2 = NULL;\n  long ret;\n\n  ptr = prep_syscall();\n\n  assert(SYS_epoll_pwait2 == call->no);\n\n  if (events && max_events > 0) {\n    events2 = ptr;\n    ptr += max_events * sizeof(*events2);\n  }\n  if (!start_commit_buffered_syscall(call->no, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  /* Try a no-timeout version of the syscall first. If this doesn't return\n     anything, and we should have blocked, we'll try again with a traced syscall\n     which will be the one that blocks. This usually avoids the\n     need to trigger desched logic, which adds overhead, especially the\n     rrcall_notify_syscall_hook_exit that gets triggered. */\n  struct timespec64 no_timeout = { 0, 0 };\n  ret = untraced_syscall6(call->no, epfd, events2, max_events, &no_timeout,\n    call->args[4] /*sigmask*/, call->args[5] /*sizeof(*sigmask)*/);\n\n  ptr = copy_output_buffer(ret * sizeof(*events2), ptr, events, events2);\n  ret = commit_raw_syscall(call->no, ptr, ret);\n  if ((timeout && timeout->tv_sec == 0 && timeout->tv_nsec == 0) ||\n      (ret != EINTR && ret != 0)) {\n    /* If we got some real results, or a non-EINTR error, we can just\n       return it directly.\n       If we got no results and the timeout was 0, we can just return 0.\n       If we got EINTR and the timeout was 0, a signal must have\n       interrupted the syscall (not sure if this can happen...). If the signal\n       needs to be handled, we'll handle it as we exit the syscallbuf.\n       Returning EINTR is fine because that's what the syscall would have\n       returned had it run traced. (We didn't enable the desched signal\n       so no extra signals could have affected our untraced syscall that\n       could not have been delivered to a traced syscall.) */\n    return ret;\n  }\n  /* Some timeout was requested and either we got no results or we got\n     EINTR.\n     In the former case we just have to wait, so we do a traced syscall.\n     In the latter case, the syscall must have been interrupted by a\n     signal (which rr will have handled or stashed, and won't deliver until\n     we exit syscallbuf code or do a traced syscall). The kernel doesn't\n     automatically restart the syscall because of a longstanding bug (as of\n     4.17 anyway). Doing a traced syscall will allow a stashed signal to be\n     processed (if necessary) and allow things to proceed normally after that.\n     Note that if rr decides to deliver a signal to the tracee, that will\n     itself interrupt the syscall and cause it to return EINTR just as\n     would happen without rr.\n  */\n  return traced_raw_syscall(call);\n}\n#endif\n\n#define CLONE_SIZE_THRESHOLD 0x10000\n\nstatic long sys_read(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Reading from a pipe could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_read;\n  int fd = call->args[0];\n  void* buf = (void*)call->args[1];\n  size_t count = call->args[2];\n\n  void* ptr;\n  void* buf2 = NULL;\n  long ret;\n\n  /* Try cloning data using CLONE_RANGE ioctl.\n   * XXX switch to FIOCLONERANGE when that's more widely available. It's the\n   * same ioctl number so it won't affect rr per se but it'd be cleaner code.\n   * 64-bit only for now, since lseek and pread64 need special handling for\n   * 32-bit.\n   * Basically we break down the read into three syscalls lseek, clone and\n   * read-from-clone, each of which is individually syscall-buffered.\n   * Crucially, the read-from-clone syscall does NOT store data in the syscall\n   * buffer; instead, we perform the syscall during replay, assuming that\n   * cloned_file_data_fd is open to the same file during replay.\n   * Reads that hit EOF are rejected by the CLONE_RANGE ioctl so we take the\n   * slow path. That's OK.\n   * There is a possible race here: between cloning the data and reading from\n   * |fd|, |fd|'s data may be overwritten, in which case the data read during\n   * replay will not match the data read during recording, causing divergence.\n   * I don't see any performant way to avoid this race; I tried reading from\n   * the cloned data instead of |fd|, but that is very slow because readahead\n   * doesn't work. (The cloned data file always ends at the current offset so\n   * there is nothing to readahead.) However, if an application triggers this\n   * race, it's almost certainly a bad bug because Linux can return any\n   * interleaving of old+new data for the read even without rr.\n   */\n  if (buf && count >= CLONE_SIZE_THRESHOLD &&\n      thread_locals->cloned_file_data_fd >= 0 && is_bufferable_fd(fd) &&\n      sizeof(void*) == 8 && !(count & 4095)) {\n    struct syscall_info lseek_call = { SYS_lseek,\n                                       { fd, 0, SEEK_CUR, 0, 0, 0 } };\n    off_t lseek_ret = privileged_sys_generic_nonblocking_fd(&lseek_call);\n    if (lseek_ret >= 0 && !(lseek_ret & 4095)) {\n      struct btrfs_ioctl_clone_range_args ioctl_args;\n      int ioctl_ret;\n      void* ioctl_ptr = prep_syscall();\n      ioctl_args.src_fd = fd;\n      ioctl_args.src_offset = lseek_ret;\n      ioctl_args.src_length = count;\n      ioctl_args.dest_offset = thread_locals->cloned_file_data_offset;\n\n      /* Don't call sys_ioctl here; cloned_file_data_fd has syscall buffering\n       * disabled for it so rr can reject attempts to close/dup to it. But\n       * we want to allow syscall buffering of this ioctl on it.\n       */\n      if (!start_commit_buffered_syscall(SYS_ioctl, ioctl_ptr, WONT_BLOCK)) {\n        struct syscall_info ioctl_call = { SYS_ioctl,\n                                           { thread_locals->cloned_file_data_fd,\n                                             BTRFS_IOC_CLONE_RANGE,\n                                             (long)&ioctl_args, 0, 0, 0 } };\n        ioctl_ret = privileged_traced_raw_syscall(&ioctl_call);\n      } else {\n        ioctl_ret =\n            privileged_untraced_syscall3(SYS_ioctl, thread_locals->cloned_file_data_fd,\n                                         BTRFS_IOC_CLONE_RANGE, &ioctl_args);\n        ioctl_ret = commit_raw_syscall(SYS_ioctl, ioctl_ptr, ioctl_ret);\n      }\n\n      if (ioctl_ret >= 0) {\n        struct syscall_info read_call = { SYS_read,\n                                          { fd, (long)buf, count, 0, 0, 0 } };\n        thread_locals->cloned_file_data_offset += count;\n\n        replay_only_syscall3(SYS_dup3, thread_locals->cloned_file_data_fd, fd, 0);\n\n        ptr = prep_syscall();\n        if (count > thread_locals->usable_scratch_size) {\n          if (!start_commit_buffered_syscall(SYS_read, ptr, WONT_BLOCK)) {\n            return traced_raw_syscall(&read_call);\n          }\n          ret = untraced_replayed_syscall3(SYS_read, fd, buf, count);\n        } else {\n          if (!start_commit_buffered_syscall(SYS_read, ptr, MAY_BLOCK)) {\n            return traced_raw_syscall(&read_call);\n          }\n          ret = untraced_replayed_syscall3(SYS_read, fd,\n                                           thread_locals->scratch_buf, count);\n          copy_output_buffer(ret, NULL, buf, thread_locals->scratch_buf);\n        }\n        // Do this now before we finish processing the syscallbuf record.\n        // This means the syscall will be executed in\n        // ReplaySession::flush_syscallbuf instead of\n        // ReplaySession::enter_syscall or something similar.\n        replay_only_syscall1(SYS_close, fd);\n        ret = commit_raw_syscall(SYS_read, ptr, ret);\n        return ret;\n      }\n    }\n  }\n\n  ptr = prep_syscall_for_fd(fd);\n\n  assert(syscallno == call->no);\n\n  if (buf && count > 0) {\n    buf2 = ptr;\n    ptr += count;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, fd, buf2, count);\n  ptr = copy_output_buffer(ret, ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n/* On x86-32, pread/pwrite take the offset in two registers. We don't bother\n * handling that.\n */\n#if !defined(__i386__)\nstatic long sys_pread64(struct syscall_info* call) {\n  const int syscallno = SYS_pread64;\n  int fd = call->args[0];\n  void* buf = (void*)call->args[1];\n  size_t count = call->args[2];\n  off_t offset = call->args[3];\n\n  void* ptr;\n  void* buf2 = NULL;\n  long ret;\n\n  ptr = prep_syscall_for_fd(fd);\n\n  assert(syscallno == call->no);\n\n  if (buf && count > 0) {\n    buf2 = ptr;\n    ptr += count;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall4(syscallno, fd, buf2, count, offset);\n  ptr = copy_output_buffer(ret, ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#if defined(SYS_readlink)\nstatic long sys_readlink(struct syscall_info* call) {\n  const int syscallno = SYS_readlink;\n  const char* path = (const char*)call->args[0];\n  char* buf = (char*)call->args[1];\n  int bufsiz = call->args[2];\n\n  void* ptr = prep_syscall();\n  char* buf2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (buf && bufsiz > 0) {\n    buf2 = ptr;\n    ptr += bufsiz;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, path, buf2, bufsiz);\n  ptr = copy_output_buffer(ret, ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\nstatic long sys_readlinkat(struct syscall_info* call, int privileged) {\n  const int syscallno = SYS_readlinkat;\n  int dirfd = call->args[0];\n  const char* path = (const char*)call->args[1];\n  char* buf = (char*)call->args[2];\n  int bufsiz = call->args[3];\n\n  void* ptr = prep_syscall();\n  char* buf2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (buf && bufsiz > 0) {\n    buf2 = ptr;\n    ptr += bufsiz;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    if (privileged) {\n      return privileged_traced_raw_syscall(call);\n    }\n    return traced_raw_syscall(call);\n  }\n\n  if (privileged) {\n    ret = privileged_untraced_syscall4(syscallno, dirfd, path, buf2, bufsiz);\n  } else {\n    ret = untraced_syscall4(syscallno, dirfd, path, buf2, bufsiz);\n  }\n  ptr = copy_output_buffer(ret, ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n#if defined(SYS_socketcall)\nstatic long sys_socketcall_recv(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Reading from a socket could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_socketcall;\n  long* args = (long*)call->args[1];\n  int sockfd = args[0];\n  void* buf = (void*)args[1];\n  size_t len = args[2];\n  unsigned int flags = args[3];\n  unsigned long new_args[4];\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  void* buf2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (buf && len > 0) {\n    buf2 = ptr;\n    ptr += len;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  new_args[0] = sockfd;\n  new_args[1] = (unsigned long)buf2;\n  new_args[2] = len;\n  new_args[3] = flags;\n  ret = untraced_syscall2(SYS_socketcall, SYS_RECV, new_args);\n  /* Account for MSG_TRUNC */\n  ptr = copy_output_buffer(ret_buf_len(ret, len), ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_socketcall(struct syscall_info* call) {\n  switch (call->args[0]) {\n    case SYS_RECV:\n      return sys_socketcall_recv(call);\n    default:\n      return traced_raw_syscall(call);\n  }\n}\n#endif\n\n#ifdef SYS_recvfrom\nstatic long sys_recvfrom(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Reading from a socket could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_recvfrom;\n  int sockfd = call->args[0];\n  void* buf = (void*)call->args[1];\n  size_t len = call->args[2];\n  int flags = call->args[3];\n  /* struct sockaddr isn't useful here since some sockaddrs are bigger than\n   * it. To avoid making false assumptions, treat the sockaddr parameter\n   * as an untyped buffer.\n   */\n  void* src_addr = (void*)call->args[4];\n  socklen_t* addrlen = (socklen_t*)call->args[5];\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  void* buf2 = NULL;\n  struct sockaddr* src_addr2 = NULL;\n  socklen_t* addrlen2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n  /* If addrlen is NULL then src_addr must also be null */\n  assert(addrlen || !src_addr);\n\n  if (src_addr) {\n    src_addr2 = ptr;\n    ptr += *addrlen;\n  }\n  if (addrlen) {\n    addrlen2 = ptr;\n    ptr += sizeof(*addrlen);\n  }\n  if (buf && len > 0) {\n    buf2 = ptr;\n    ptr += len;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  if (addrlen) {\n    memcpy_input_parameter(addrlen2, addrlen, sizeof(*addrlen2));\n  }\n  ret = untraced_syscall6(syscallno, sockfd, buf2, len, flags, src_addr2,\n                          addrlen2);\n\n  if (ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    if (src_addr2) {\n      socklen_t actual_size = *addrlen2;\n      if (actual_size > *addrlen) {\n        actual_size = *addrlen;\n      }\n      local_memcpy(src_addr, src_addr2, actual_size);\n    }\n    if (addrlen2) {\n      *addrlen = *addrlen2;\n    }\n  }\n  ptr = copy_output_buffer(ret_buf_len(ret, len), ptr, buf, buf2);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#ifdef SYS_recvmsg\n\nstatic int msg_received_file_descriptors(struct msghdr* msg) {\n  struct cmsghdr* cmh;\n  for (cmh = CMSG_FIRSTHDR(msg); cmh; cmh = CMSG_NXTHDR(msg, cmh)) {\n    if (cmh->cmsg_level == SOL_SOCKET && cmh->cmsg_type == SCM_RIGHTS) {\n      return 1;\n    }\n  }\n  return 0;\n}\n\nstatic long sys_recvmsg(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Reading from a socket could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_recvmsg;\n  int sockfd = call->args[0];\n  struct msghdr* msg = (struct msghdr*)call->args[1];\n  int flags = call->args[2];\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  long ret;\n  struct msghdr* msg2;\n  void* ptr_base = ptr;\n  void* ptr_overwritten_end;\n  void* ptr_bytes_start;\n  void* ptr_end;\n  rr_iovlen_t i;\n\n  assert(syscallno == call->no);\n\n  /* Compute final buffer size up front, before writing syscall inputs to the\n   * buffer. Thus if we decide not to buffer this syscall, we bail out\n   * before trying to write to a buffer that won't be recorded and may be\n   * invalid (e.g. overflow).\n   */\n  ptr += sizeof(struct msghdr) + sizeof(struct iovec) * msg->msg_iovlen;\n  if (msg->msg_name) {\n    ptr += msg->msg_namelen;\n  }\n  if (msg->msg_control) {\n    ptr += msg->msg_controllen;\n  }\n  for (i = 0; i < msg->msg_iovlen; ++i) {\n    ptr += msg->msg_iov[i].iov_len;\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  /**\n   * The kernel only writes to the struct msghdr, and the iov buffers. We must\n   * not overwrite that data (except using memcpy_input_parameter) during\n   * replay. For the rest of the data, the values we write here during replay\n   * are guaranteed to match what was recorded in the buffer.\n   * We can't rely on the values we wrote here during recording also being\n   * here during replay since the syscall might have been aborted and our\n   * written data not recorded.\n   */\n  msg2 = ptr = ptr_base;\n  memcpy_input_parameter(msg2, msg, sizeof(*msg));\n  ptr += sizeof(struct msghdr);\n  msg2->msg_iov = ptr;\n  ptr += sizeof(struct iovec) * msg->msg_iovlen;\n  ptr_overwritten_end = ptr;\n  if (msg->msg_name) {\n    msg2->msg_name = ptr;\n    ptr += msg->msg_namelen;\n  }\n  if (msg->msg_control) {\n    msg2->msg_control = ptr;\n    ptr += msg->msg_controllen;\n  }\n  ptr_bytes_start = ptr;\n  for (i = 0; i < msg->msg_iovlen; ++i) {\n    msg2->msg_iov[i].iov_base = ptr;\n    ptr += msg->msg_iov[i].iov_len;\n    msg2->msg_iov[i].iov_len = msg->msg_iov[i].iov_len;\n  }\n\n  ret = untraced_syscall3(syscallno, sockfd, msg2, flags);\n\n  if (ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    size_t bytes = ret;\n    if (msg->msg_name) {\n      local_memcpy(msg->msg_name, msg2->msg_name, msg2->msg_namelen);\n    }\n    msg->msg_namelen = msg2->msg_namelen;\n    if (msg->msg_control) {\n      local_memcpy(msg->msg_control, msg2->msg_control, msg2->msg_controllen);\n    }\n    msg->msg_controllen = msg2->msg_controllen;\n    ptr_end = ptr_bytes_start + bytes;\n    for (i = 0; i < msg->msg_iovlen; ++i) {\n      long copy_bytes =\n          bytes < msg->msg_iov[i].iov_len ? bytes : msg->msg_iov[i].iov_len;\n      local_memcpy(msg->msg_iov[i].iov_base, msg2->msg_iov[i].iov_base,\n                   copy_bytes);\n      bytes -= copy_bytes;\n    }\n    msg->msg_flags = msg2->msg_flags;\n\n    if (msg_received_file_descriptors(msg)) {\n      /* When we reach a safe point, notify rr that the control message with\n       * file descriptors was received.\n       */\n      thread_locals->notify_control_msg = msg;\n    }\n  } else {\n    /* Allocate record space as least to cover the data we overwrote above.\n     * We don't want to start the next record overlapping that data, since then\n     * we'll corrupt it during replay.\n     */\n    ptr_end = ptr_overwritten_end;\n  }\n  return commit_raw_syscall(syscallno, ptr_end, ret);\n}\n#endif\n\n#ifdef SYS_sendmsg\nstatic long sys_sendmsg(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Sending to a socket could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_sendmsg;\n  int sockfd = call->args[0];\n  struct msghdr* msg = (struct msghdr*)call->args[1];\n  int flags = call->args[2];\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, sockfd, msg, flags);\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#ifdef SYS_sendto\nstatic long sys_sendto(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Sending to a socket could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_sendto;\n  int sockfd = call->args[0];\n  void* buf = (void*)call->args[1];\n  size_t len = call->args[2];\n  int flags = call->args[3];\n  const struct sockaddr* dest_addr = (const struct sockaddr*)call->args[4];\n  socklen_t addrlen = call->args[5];\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret =\n      untraced_syscall6(syscallno, sockfd, buf, len, flags, dest_addr, addrlen);\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#ifdef SYS_setsockopt\nstatic long sys_setsockopt(struct syscall_info* call) {\n  const int syscallno = SYS_setsockopt;\n  int sockfd = call->args[0];\n  int level = call->args[1];\n  int optname = call->args[2];\n  void* optval = (void*)call->args[3];\n  socklen_t optlen = (socklen_t)call->args[4];\n\n  if (level == SOL_PACKET &&\n      (optname == PACKET_RX_RING || optname == PACKET_TX_RING)) {\n    // Let rr intercept this (and probably disable it)\n    return traced_raw_syscall(call);\n  }\n  if (level == SOL_NETLINK &&\n      (optname == NETLINK_RX_RING || optname == NETLINK_TX_RING)) {\n    // Let rr intercept this (and probably disable it)\n    return traced_raw_syscall(call);\n  }\n  if ((level == SOL_IP && optname == IPT_SO_SET_REPLACE) ||\n      (level == SOL_IPV6 && optname == IPV6T_SO_SET_REPLACE)) {\n    // Let rr intercept this because it has output parameters :-(\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall5(syscallno, sockfd, level, optname, optval, optlen);\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#ifdef SYS_getsockopt\nstatic long sys_getsockopt(struct syscall_info* call) {\n  const int syscallno = SYS_getsockopt;\n  int sockfd = call->args[0];\n  int level = call->args[1];\n  int optname = call->args[2];\n  void* optval = (void*)call->args[3];\n  socklen_t* optlen = (socklen_t*)call->args[4];\n  socklen_t* optlen2;\n  void* optval2;\n\n  if (!optlen || !optval) {\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  long ret;\n\n  optlen2 = ptr;\n  ptr += sizeof(*optlen2);\n  optval2 = ptr;\n  ptr += *optlen;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  memcpy_input_parameter(optlen2, optlen, sizeof(*optlen2));\n  // Some variance of getsockopt does use the initial content of *optval\n  // (e.g. SOL_IP + IPT_SO_GET_INFO) so we need to copy it.\n  memcpy_input_parameter(optval2, optval, *optlen);\n\n  // We may need to manually restart this syscall due to kernel bug\n  // returning a EFAULT when interrupted by signal and we won't have\n  // access to the actual arg1 on aarch64 in a normal way in such case.\n  // Pass in the arg1 in the stack argument so that we can use it in the tracer.\n  ret = untraced_syscall_full(syscallno, sockfd, level, optname,\n                              (long)optval2, (long)optlen2, 0,\n                              RR_PAGE_SYSCALL_UNTRACED_RECORDING_ONLY, sockfd, 0);\n\n  if (ret >= 0) {\n    socklen_t val_len = *optlen < *optlen2 ? *optlen : *optlen2;\n    local_memcpy(optval, optval2, val_len);\n    local_memcpy(optlen, optlen2, sizeof(*optlen));\n  }\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#ifdef SYS_getsockname\nstatic long sys_getsockname(struct syscall_info* call) {\n  const int syscallno = SYS_getsockname;\n  int sockfd = call->args[0];\n  struct sockaddr* addr = (struct sockaddr*)call->args[1];\n  socklen_t* addrlen = (socklen_t*)call->args[2];\n  socklen_t* addrlen2;\n  struct sockaddr* addr2 = NULL;\n\n  void* ptr = prep_syscall_for_fd(sockfd);\n  long ret;\n\n  addrlen2 = ptr;\n  ptr += sizeof(*addrlen2);\n  if (addr) {\n    addr2 = ptr;\n    ptr += *addrlen;\n  }\n\n  assert(syscallno == call->no);\n\n  if (addrlen2) {\n    memcpy_input_parameter(addrlen2, addrlen, sizeof(*addrlen2));\n  }\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, MAY_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, sockfd, addr2, addrlen2);\n\n  if (ret >= 0) {\n    if (addr) {\n      socklen_t addr_len = *addrlen < *addrlen2 ? *addrlen : *addrlen2;\n      local_memcpy(addr, addr2, addr_len);\n    }\n    local_memcpy(addrlen, addrlen2, sizeof(*addrlen));\n  }\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#ifdef SYS_socketpair\ntypedef int two_ints[2];\nstatic long sys_socketpair(struct syscall_info* call) {\n  const int syscallno = SYS_socketpair;\n  int domain = call->args[0];\n  int type = call->args[1];\n  int protocol = call->args[2];\n  two_ints* sv = (two_ints*)call->args[3];\n\n  void* ptr = prep_syscall();\n  struct timezone* sv2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  sv2 = ptr;\n  ptr += sizeof(*sv2);\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall4(syscallno, domain, type, protocol, sv2);\n  if (ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(sv, sv2, sizeof(*sv));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\nstatic long sys_uname(struct syscall_info* call) {\n  const int syscallno = SYS_uname;\n  void* buf = (void*)call->args[0];\n\n  void* ptr = prep_syscall();\n  void* buf2;\n  long ret;\n  size_t bufsize = sizeof(struct new_utsname);\n\n  assert(syscallno == call->no);\n\n  buf2 = ptr;\n  ptr += bufsize;\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall1(syscallno, buf2);\n  if (ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(buf, buf2, bufsize);\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n\n#if defined(SYS_time)\nstatic long sys_time(struct syscall_info* call) {\n  const int syscallno = SYS_time;\n  __kernel_time_t* tp = (__kernel_time_t*)call->args[0];\n\n  void* ptr = prep_syscall();\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall1(syscallno, NULL);\n  if (tp) {\n    /* No error is possible here. */\n    *tp = ret;\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\n#if defined(__i386__)\ntypedef struct stat64 stat64_t;\n#else\ntypedef struct stat stat64_t;\n#endif\nstatic long sys_xstat64(struct syscall_info* call) {\n  const int syscallno = call->no;\n  /* NB: this arg may be a string or an fd, but for the purposes\n   * of this generic helper we don't care. */\n  long what = call->args[0];\n  stat64_t* buf = (stat64_t*)call->args[1];\n\n  /* Like open(), not arming the desched event because it's not\n   * needed for correctness, and there are no data to suggest\n   * whether it's a good idea perf-wise. */\n  void* ptr = prep_syscall();\n  stat64_t* buf2 = NULL;\n  long ret;\n\n  if (buf) {\n    buf2 = ptr;\n    ptr += sizeof(*buf2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall2(syscallno, what, buf2);\n  if (buf2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(buf, buf2, sizeof(*buf));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n#ifdef SYS_statx\n/* Like sys_xstat64, but with different arguments */\nstatic long sys_statx(struct syscall_info* call) {\n  const int syscallno = call->no;\n  struct statx* buf = (struct statx*)call->args[4];\n\n  void* ptr = prep_syscall();\n  struct statx* buf2 = NULL;\n  long ret;\n\n  if (buf) {\n    buf2 = ptr;\n    ptr += sizeof(*buf2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall5(syscallno,\n    call->args[0], call->args[1], call->args[2], call->args[3],\n    buf2);\n  if (buf2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(buf, buf2, sizeof(*buf));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\nstatic long sys_fstatat(struct syscall_info* call) {\n  const int syscallno = call->no;\n  stat64_t* buf = (stat64_t*)call->args[2];\n\n  /* Like stat(), not arming the desched event because it's not\n   * needed for correctness, and there are no data to suggest\n   * whether it's a good idea perf-wise. */\n  void* ptr = prep_syscall();\n  stat64_t* buf2 = NULL;\n  long ret;\n\n  if (buf) {\n    buf2 = ptr;\n    ptr += sizeof(*buf2);\n  }\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall4(syscallno,\n    call->args[0], call->args[1], buf2, call->args[3]);\n  if (buf2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(buf, buf2, sizeof(*buf));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_quotactl(struct syscall_info* call) {\n  const int syscallno = call->no;\n  int cmd = call->args[0];\n  const char* special = (const char*)call->args[1];\n  int id = call->args[2];\n  void* addr = (void*)call->args[3];\n\n  if ((cmd >> SUBCMDSHIFT) != Q_GETQUOTA) {\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall();\n  struct if_dqblk* buf2 = NULL;\n  long ret;\n\n  if (addr) {\n    buf2 = ptr;\n    ptr += sizeof(*buf2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall4(syscallno, cmd, special, id, buf2);\n  if (buf2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(addr, buf2, sizeof(*buf2));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_statfs(struct syscall_info* call) {\n  const int syscallno = call->no;\n  /* NB: this arg may be a string or an fd, but for the purposes\n   * of this generic helper we don't care. */\n  long what = call->args[0];\n  struct statfs* buf = (struct statfs*)call->args[1];\n\n  /* Like open(), not arming the desched event because it's not\n   * needed for correctness, and there are no data to suggest\n   * whether it's a good idea perf-wise. */\n  void* ptr = prep_syscall();\n  struct statfs* buf2 = NULL;\n  long ret;\n\n  if (buf) {\n    buf2 = ptr;\n    ptr += sizeof(*buf2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall2(syscallno, what, buf2);\n  if (buf2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(buf, buf2, sizeof(*buf));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_write(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Writing to a pipe or FIFO could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  const int syscallno = SYS_write;\n  int fd = call->args[0];\n  const void* buf = (const void*)call->args[1];\n  size_t count = call->args[2];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, fd_write_blocks(fd))) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, fd, buf, count);\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n/* On x86-32, pread/pwrite take the offset in two registers. We don't bother\n * handling that.\n */\n#if !defined(__i386__)\nstatic long sys_pwrite64(struct syscall_info* call) {\n  const int syscallno = SYS_pwrite64;\n  int fd = call->args[0];\n  const void* buf = (const void*)call->args[1];\n  size_t count = call->args[2];\n  off_t offset = call->args[3];\n\n  enum syscallbuf_fd_classes cls = fd_class(fd);\n  if (cls == FD_CLASS_TRACED) {\n    return traced_raw_syscall(call);\n  }\n  void* ptr = prep_syscall();\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, fd_write_blocks(fd))) {\n    return traced_raw_syscall(call);\n  }\n\n  long ret;\n  if (cls == FD_CLASS_PROC_MEM) {\n    ret = untraced_replay_assist_syscall4(syscallno, fd, buf, count, offset);\n  } else {\n    ret = untraced_syscall4(syscallno, fd, buf, count, offset);\n  }\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n#endif\n\nstatic long sys_writev(struct syscall_info* call) {\n  if (force_traced_syscall_for_chaos_mode()) {\n    /* Writing to a pipe or FIFO could unblock a higher priority task */\n    return traced_raw_syscall(call);\n  }\n\n  int syscallno = SYS_writev;\n  int fd = call->args[0];\n  const struct iovec* iov = (const struct iovec*)call->args[1];\n  unsigned long iovcnt = call->args[2];\n\n  void* ptr = prep_syscall_for_fd(fd);\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, fd_write_blocks(fd))) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall3(syscallno, fd, iov, iovcnt);\n\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_prctl(struct syscall_info* call) {\n  int syscallno = SYS_prctl;\n  long option = call->args[0];\n  unsigned long arg2 = call->args[1];\n  unsigned long arg3 = call->args[2];\n  unsigned long arg4 = call->args[3];\n  unsigned long arg5 = call->args[4];\n\n  if (option != PR_SET_NAME) {\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall();\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_replay_assist_syscall5(syscallno, option, arg2, arg3, arg4, arg5);\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_set_robust_list(struct syscall_info* call) {\n  int syscallno = SYS_set_robust_list;\n  void* head = (void*)call->args[0];\n  size_t len = call->args[1];\n  long ret;\n\n  assert(syscallno == call->no);\n\n  /* Avoid len values we don't support via our buffering mechanism */\n  if (len == 0 || len >= UINT32_MAX) {\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall();\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall2(syscallno, head, len);\n  if (!ret) {\n    thread_locals->robust_list.head = head;\n    thread_locals->robust_list.len = len;\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\n#if defined(SYS_rseq)\nstatic long sys_rseq(struct syscall_info* call) {\n  int syscallno = SYS_rseq;\n  struct rr_rseq* rseq = (struct rr_rseq*)call->args[0];\n  size_t rseq_len = call->args[1];\n  int flags = call->args[2];\n  uint32_t sig = call->args[3];\n\n  assert(syscallno == call->no);\n\n  if (flags || ((uintptr_t)rseq & 31) || rseq_len != sizeof(*rseq) ||\n      thread_locals->rseq_called || globals.cpu_binding < 0) {\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall();\n  /* Allow buffering only for the simplest case: setting up the\n     initial rseq, all parameters OK and CPU binding in place. */\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  /* We don't actually need to make a syscall since rr is\n     going to emulate everything. */\n  rseq->cpu_id_start = rseq->cpu_id = globals.cpu_binding;\n  thread_locals->rseq_called = 1;\n  thread_locals->rseq.rseq = rseq;\n  thread_locals->rseq.len = rseq_len;\n  thread_locals->rseq.sig = sig;\n  /* We do need to commit a syscallbuf record to ensure that flushing\n     happens with associated processing. */\n  return commit_raw_syscall(syscallno, ptr, 0);\n}\n#endif\n\nstatic long sys_ptrace(struct syscall_info* call) {\n  int syscallno = SYS_ptrace;\n  long request = call->args[0];\n  pid_t pid = call->args[1];\n  void* addr = (void*)call->args[2];\n  void* data = (void*)call->args[3];\n\n  if (request != PTRACE_PEEKDATA || !data) {\n    return traced_raw_syscall(call);\n  }\n\n  /* We try to emulate PTRACE_PEEKDATA using process_vm_readv. That might not\n   * work for permissions reasons; if it fails for any reason, we retry with\n   * a traced syscall.\n   * This does mean that if a process issues a PTRACE_PEEKDATA while not\n   * actually ptracing the target, it might succeed under rr whereas normally\n   * it would have failed. That's hard to avoid and unlikely to be a real\n   * problem in practice (typically it would fail on some other ptrace call like\n   * PTRACE_GETREGS before or after the PEEKDATA).\n   */\n  void* ptr = prep_syscall();\n  long ret;\n  void* data2;\n\n  assert(syscallno == call->no);\n  syscallno = SYS_process_vm_readv;\n\n  data2 = ptr;\n  ptr += sizeof(long);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  struct iovec local_iov = { data2, sizeof(long) };\n  struct iovec remote_iov = { addr, sizeof(long) };\n  ret = untraced_syscall6(syscallno, pid, &local_iov, 1, &remote_iov, 1, 0);\n  if (ret > 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(data, data2, ret);\n  }\n  commit_raw_syscall(syscallno, ptr, ret);\n\n  if (ret != sizeof(long)) {\n    return traced_raw_syscall(call);\n  }\n  return ret;\n}\n\nstatic long sys_getrusage(struct syscall_info* call) {\n  const int syscallno = SYS_getrusage;\n  int who = (int)call->args[0];\n  struct rusage* buf = (struct rusage*)call->args[1];\n  void* ptr = prep_syscall();\n  long ret;\n  struct rusage* buf2 = NULL;\n\n  assert(syscallno == call->no);\n\n  if (buf) {\n    buf2 = ptr;\n    ptr += sizeof(struct rusage);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  ret = untraced_syscall2(syscallno, who, buf2);\n  if (buf2 && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    local_memcpy(buf, buf2, sizeof(*buf));\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_rt_sigprocmask(struct syscall_info* call) {\n  const int syscallno = SYS_rt_sigprocmask;\n  long ret;\n  kernel_sigset_t modified_set;\n  void* oldset2;\n  struct syscallbuf_hdr* hdr;\n\n  if (call->args[3] != sizeof(kernel_sigset_t)) {\n    // Unusual sigset size. Bail.\n    return traced_raw_syscall(call);\n  }\n\n  void* ptr = prep_syscall();\n\n  int how = (int)call->args[0];\n  const kernel_sigset_t* set = (const kernel_sigset_t*)call->args[1];\n  kernel_sigset_t* oldset = (kernel_sigset_t*)call->args[2];\n\n  oldset2 = ptr;\n  ptr += sizeof(kernel_sigset_t);\n\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  if (set && (how == SIG_BLOCK || how == SIG_SETMASK)) {\n    local_memcpy(&modified_set, set, sizeof(kernel_sigset_t));\n    // SIGSTKFLT (PerfCounters::TIME_SLICE_SIGNAL) and\n    // SIGPWR(SYSCALLBUF_DESCHED_SIGNAL) are used by rr\n    modified_set &=\n        ~(((uint64_t)1) << (SIGSTKFLT - 1)) &\n        ~(((uint64_t)1) << (globals.desched_sig - 1));\n    set = &modified_set;\n  }\n\n  hdr = buffer_hdr();\n  hdr->in_sigprocmask_critical_section = 1;\n\n  ret =\n      untraced_syscall4(syscallno, how, set, oldset2, sizeof(kernel_sigset_t));\n  if (ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    if (oldset) {\n      local_memcpy(oldset, oldset2, sizeof(kernel_sigset_t));\n    }\n    if (set) {\n      kernel_sigset_t previous_set;\n      local_memcpy(&previous_set, oldset2, sizeof(kernel_sigset_t));\n      switch (how) {\n        case SIG_UNBLOCK:\n          previous_set &= ~*set;\n          break;\n        case SIG_BLOCK:\n          previous_set |= *set;\n          break;\n        case SIG_SETMASK:\n          previous_set = *set;\n          break;\n      }\n      hdr->blocked_sigs = previous_set;\n      // We must update the generation last to ensure that an update is not\n      // lost.\n      ++hdr->blocked_sigs_generation;\n    }\n  }\n  hdr->in_sigprocmask_critical_section = 0;\n\n  commit_raw_syscall(syscallno, ptr, ret);\n\n  if (ret == -EAGAIN) {\n    // The rr supervisor emulated EAGAIN because there was a pending signal.\n    // Retry using a traced syscall so the pending signal(s) can be delivered.\n    return traced_raw_syscall(call);\n  }\n  return ret;\n}\n\nstatic long sys_sigaltstack(struct syscall_info* call) {\n  const int syscallno = SYS_sigaltstack;\n  stack_t* ss = (void*)call->args[0];\n  stack_t* old_ss = (void*)call->args[1];\n\n  void* ptr = prep_syscall();\n  stack_t* old_ss2 = NULL;\n  long ret;\n\n  assert(syscallno == call->no);\n\n  if (old_ss) {\n    old_ss2 = ptr;\n    ptr += sizeof(*old_ss2);\n  }\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n  ret = untraced_syscall2(syscallno, ss, old_ss2);\n  if (old_ss && ret >= 0 && !buffer_hdr()->failed_during_preparation) {\n    /* This is small and won't get optimized to a memcpy call outside\n       our library. */\n    *old_ss = *old_ss2;\n  }\n  return commit_raw_syscall(syscallno, ptr, ret);\n}\n\nstatic long sys_rrcall_rdtsc(struct syscall_info* call) {\n#if defined(__i386__) || defined(__x86_64__)\n  const int syscallno = SYS_rrcall_rdtsc;\n  uint32_t tsc[2];\n  void* ptr = prep_syscall();\n  void* buf = ptr;\n  ptr += 8;\n  if (!start_commit_buffered_syscall(syscallno, ptr, WONT_BLOCK)) {\n    return traced_raw_syscall(call);\n  }\n\n  // Do an RDTSC without context-switching to rr. This is still a lot slower\n  // than a plain RDTSC. Maybe we coud do something better with RDPMC...\n  privileged_unrecorded_syscall5(SYS_prctl, PR_SET_TSC, PR_TSC_ENABLE, 0, 0, 0);\n  rdtsc_recording_only(buf);\n  privileged_unrecorded_syscall5(SYS_prctl, PR_SET_TSC, PR_TSC_SIGSEGV, 0, 0, 0);\n\n  local_memcpy(tsc, buf, sizeof(tsc));\n  // Overwrite RDX (syscall arg 3) with our TSC value.\n  call->args[2] = tsc[1];\n  return commit_raw_syscall(syscallno, ptr, tsc[0]);\n#else\n  (void)call;\n  fatal(\"RDTSC not supported in this architecture\");\n  return 0;\n#endif\n}\n\nstatic long syscall_hook_internal(struct syscall_info* call) {\n  switch (call->no) {\n#define CASE(syscallname)                                                      \\\n  case SYS_##syscallname:                                                      \\\n    return sys_##syscallname(call)\n#define CASE_GENERIC_NONBLOCKING(syscallname)                                  \\\n  case SYS_##syscallname:                                                      \\\n    return sys_generic_nonblocking(call)\n#define CASE_GENERIC_NONBLOCKING_FD(syscallname)                               \\\n  case SYS_##syscallname:                                                      \\\n    return sys_generic_nonblocking_fd(call)\n    CASE(rrcall_rdtsc);\n#if defined(SYS_access)\n    CASE_GENERIC_NONBLOCKING(access);\n#endif\n    CASE(clock_gettime);\n#if defined(SYS_clock_gettime64)\n    CASE(clock_gettime64);\n#endif\n    CASE_GENERIC_NONBLOCKING_FD(close);\n#if defined(SYS_creat)\n    CASE(creat);\n#endif\n    CASE_GENERIC_NONBLOCKING_FD(dup);\n    CASE_GENERIC_NONBLOCKING_FD(epoll_ctl);\n#if defined(SYS_epoll_wait)\ncase SYS_epoll_wait:\n#endif\ncase SYS_epoll_pwait:\n    return sys_epoll_wait(call);\n#if defined(SYS_openat2)\n    CASE(openat2);\n#endif\n#if defined(SYS_epoll_pwait2)\n    CASE(epoll_pwait2);\n#endif\n    CASE_GENERIC_NONBLOCKING_FD(fadvise64);\n    CASE_GENERIC_NONBLOCKING(fchmod);\n#if defined(SYS_fcntl64)\n    CASE(fcntl64);\n#else\n    CASE(fcntl);\n#endif\n    CASE(fgetxattr);\n    CASE(flistxattr);\n    CASE_GENERIC_NONBLOCKING_FD(fsetxattr);\n    CASE_GENERIC_NONBLOCKING_FD(ftruncate);\n    CASE(futex);\n#if defined(SYS_getdents)\n    CASE(getdents);\n#endif\n    CASE(getdents64);\n    CASE_GENERIC_NONBLOCKING(getegid);\n    CASE_GENERIC_NONBLOCKING(geteuid);\n    CASE_GENERIC_NONBLOCKING(getgid);\n    CASE_GENERIC_NONBLOCKING(getpid);\n    CASE_GENERIC_NONBLOCKING(getppid);\n    CASE(getrandom);\n    CASE(getrusage);\n    CASE_GENERIC_NONBLOCKING(gettid);\n    CASE(gettimeofday);\n    CASE_GENERIC_NONBLOCKING(getuid);\n    CASE(getxattr);\n    CASE(ioctl);\n#if defined(lchown)\n    CASE_GENERIC_NONBLOCKING(lchown);\n#endif\n    CASE(lgetxattr);\n    CASE(listxattr);\n    CASE(llistxattr);\n#if defined(SYS__llseek)\n    CASE(_llseek);\n#endif\n    CASE_GENERIC_NONBLOCKING_FD(lseek);\n    CASE(madvise);\n#if defined(SYS_mkdir)\n    CASE_GENERIC_NONBLOCKING(mkdir);\n#endif\n#if defined(SYS_mkdor)\n    CASE_GENERIC_NONBLOCKING(mknod);\n#endif\n    CASE(mprotect);\n#if defined(SYS_open)\n    CASE(open);\n#endif\n    CASE(openat);\n#if defined(SYS_poll)\n    CASE(poll);\n#endif\n#if defined(SYS_ppoll)\n    CASE(ppoll);\n#endif\n    CASE(prctl);\n#if !defined(__i386__)\n    CASE(pread64);\n    CASE(pwrite64);\n#endif\n    CASE(ptrace);\n    CASE(quotactl);\n    CASE(read);\n#if defined(SYS_readlink)\n    CASE(readlink);\n#endif\n    case SYS_readlinkat:\n      return sys_readlinkat(call, 0);\n#if defined(SYS_recvfrom)\n    CASE(recvfrom);\n#endif\n#if defined(SYS_recvmsg)\n    CASE(recvmsg);\n#endif\n#if defined(SYS_rseq)\n    CASE(rseq);\n#endif\n#if defined(SYS_rmdir)\n    CASE_GENERIC_NONBLOCKING(rmdir);\n#endif\n    CASE(rt_sigprocmask);\n#if defined(SYS_sendmsg)\n    CASE(sendmsg);\n#endif\n#if defined(SYS_sendto)\n    CASE(sendto);\n#endif\n    CASE(set_robust_list);\n#if defined(SYS_setsockopt)\n    CASE(setsockopt);\n#endif\n#if defined(SYS_getsockopt)\n    CASE(getsockopt);\n#endif\n#if defined(SYS_getsockname)\n    CASE(getsockname);\n#endif\n    CASE_GENERIC_NONBLOCKING(setxattr);\n    CASE(sigaltstack);\n#if defined(SYS_socketcall)\n    CASE(socketcall);\n#endif\n#if defined(SYS_socketpair)\n    CASE(socketpair);\n#endif\n#if defined(SYS_symlink)\n    CASE_GENERIC_NONBLOCKING(symlink);\n#endif\n#if defined(SYS_time)\n    CASE(time);\n#endif\n    CASE_GENERIC_NONBLOCKING(truncate);\n    CASE(uname);\n#if defined(SYS_unlink)\n    CASE_GENERIC_NONBLOCKING(unlink);\n#endif\n    CASE_GENERIC_NONBLOCKING(unlinkat);\n    CASE_GENERIC_NONBLOCKING_FD(utimensat);\n    CASE(write);\n    CASE(writev);\n#if defined(SYS_fstat64)\n    case SYS_fstat64:\n#elif defined(SYS_fstat)\n    case SYS_fstat:\n#endif\n#if defined(SYS_lstat64)\n    case SYS_lstat64:\n#elif defined(SYS_lstat)\n    case SYS_lstat:\n#endif\n#if defined(SYS_stat64)\n    case SYS_stat64:\n#elif defined(SYS_stat)\n    case SYS_stat:\n#endif\n      return sys_xstat64(call);\n#if defined(SYS_statx)\n    case SYS_statx:\n      return sys_statx(call);\n#endif\n    case SYS_statfs:\n    case SYS_fstatfs:\n      return sys_statfs(call);\n#if defined(SYS_newfstatat)\n    case SYS_newfstatat:\n#elif defined(SYS_fstatat64)\n    case SYS_fstatat64:\n#endif\n      return sys_fstatat(call);\n#undef CASE\n#undef CASE_GENERIC_NONBLOCKING\n#undef CASE_GENERIC_NONBLOCKING_FD\n    case SYS_rrcall_check_presence:\n      if (call->args[0] == RRCALL_CHECK_SYSCALLBUF_USED_OR_DISABLED &&\n          call->args[1] == 0 && call->args[2] == 0 && call->args[3] == 0 &&\n          call->args[4] == 0 && call->args[5] == 0) {\n        return 0;\n      }\n      // fallthrough\n    default:\n      return traced_raw_syscall(call);\n  }\n}\n\n/* Delay for testing purposes */\nstatic void do_delay(void) {\n  int i;\n  int result = 0;\n  for (i = 0; i < 10000000; ++i) {\n    result += i * i;\n  }\n  // Make sure result is used so this doesn't get optimized away\n  impose_syscall_delay = result | 1;\n}\n\n/* Explicitly declare this as hidden so we can call it from\n * _syscall_hook_trampoline without doing all sorts of special PIC handling.\n */\nRR_HIDDEN long syscall_hook(struct syscall_info* call) {\n  // Initialize thread-local state if this is the first syscall for this\n  // thread.\n  init_thread();\n\n  if (!thread_locals->buffer || buffer_hdr()->locked) {\n    /* We may be reentering via a signal handler. Bail. */\n    return traced_raw_syscall(call);\n  }\n\n  thread_locals->original_syscall_parameters = call;\n\n  if (impose_syscall_delay) {\n    do_delay();\n  }\n\n  long result = syscall_hook_internal(call);\n  if (buffer_hdr() && buffer_hdr()->notify_on_syscall_hook_exit) {\n    // Sometimes a signal is delivered to interrupt an untraced syscall in\n    // a non-restartable way (e.g. seccomp SIGSYS). Those signals must be\n    // handled outside any syscallbuf transactions. We defer them until\n    // this SYS_rrcall_notify_syscall_hook_exit, which is triggered by rr\n    // setting notify_on_syscall_hook_exit. The parameters to the\n    // SYS_rrcall_notify_syscall_hook_exit are magical and fully control\n    // the syscall parameters and result seen by the signal handler.\n    //\n    // SYS_rrcall_notify_syscall_hook_exit will clear\n    // notify_on_syscall_hook_exit. Clearing it ourselves is tricky to get\n    // right without races.\n    //\n    // During recording, this flag is set when the recorder needs to delay\n    // delivery of a signal until we've stopped using the syscallbuf.\n    // During replay, this flag is set when the next event is entering a\n    // SYS_rrcall_notify_syscall_hook_exit.\n    //\n    // The correctness argument is as follows:\n    // Correctness requires that a) replay's setting of the flag happens before\n    // we read the flag in the call to syscall_hook that triggered the\n    // SYS_rrcall_notify_syscall_hook_exit and b) replay's setting of the flag\n    // must happen after we read the flag in the previous execution of\n    // syscall_hook.\n    // Condition a) holds as long as no events are recorded between the\n    // checking of the flag above and the execution of this syscall. This\n    // should be the case; no synchronous signals or syscalls are\n    // triggerable, all async signals other than SYSCALLBUF_DESCHED_SIGNAL\n    // are delayed, and SYSCALLBUF_DESCHED_SIGNAL shouldn't fire since we've\n    // disarmed the desched fd at this point. SYSCALLBUF_FLUSH events may be\n    // emitted when we process the SYS_rrcall_notify_syscall_hook_exit event,\n    // but replay of those events ends at the last flushed syscall, before\n    // we exit syscall_hook_internal.\n    // Condition b) failing would mean no new events were generated between\n    // testing the flag in the previous syscall_hook and the execution of this\n    // SYS_rrcall_notify_syscall_hook_exit. However, every invocation of\n    // syscall_hook_internal generates either a traced syscall or a syscallbuf\n    // record that would be flushed by SYSCALLBUF_FLUSH, so that can't\n    // happen.\n    result = _raw_syscall(SYS_rrcall_notify_syscall_hook_exit, call->args[0],\n                          call->args[1], call->args[2], call->args[3],\n                          call->args[4], call->args[5],\n                          RR_PAGE_SYSCALL_PRIVILEGED_TRACED, result, call->no);\n  }\n  // Do work that can only be safely done after syscallbuf can be flushed\n  if (thread_locals->notify_control_msg) {\n    privileged_traced_syscall1(SYS_rrcall_notify_control_msg,\n                               thread_locals->notify_control_msg);\n    thread_locals->notify_control_msg = NULL;\n  }\n  thread_locals->original_syscall_parameters = NULL;\n  return result;\n}\n"
  },
  {
    "path": "src/preload/syscallbuf.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_SYSCALLBUF_H_\n#define RR_SYSCALLBUF_H_\n\nstruct timespec;\n\n#define RR_HIDDEN __attribute__((visibility(\"hidden\")))\n\nRR_HIDDEN extern struct preload_globals globals;\n\nRR_HIDDEN extern char impose_syscall_delay;\nRR_HIDDEN extern char impose_spurious_desched;\n\n#endif /* RR_SYSCALLBUF_H_ */\n"
  },
  {
    "path": "src/preload/tweak_librrpage.py",
    "content": "#!/usr/bin/env python3\n# This script adjusts librrpage.so to have the final layout that we want\n# See rr_page.S for a description of the expected final layout of librrpage\n\nimport struct\nimport os\nimport sys\n\n# How much space (and where) we reserved in the middle of the file for\n# the section header\nnew_table_offset = int(sys.argv[2])\nreserved_size = int(sys.argv[2])\n\n# Force this alignment for any sections\nsect_align = 0x10\n\n# some constants\nELFCLASS32 = 1\nELFCLASS64 = 2\n\ndef read_byte(f):\n\treturn struct.unpack('b', f.read(1))[0]\n\ndef read_uint64(f):\n\treturn struct.unpack('Q', f.read(8))[0]\n\ndef write_uint64(f, v):\n\treturn f.write(struct.pack('Q', v))\n\ndef read_uint32(f):\n\treturn struct.unpack('I', f.read(4))[0]\n\ndef write_uint32(f, v):\n\treturn f.write(struct.pack('I', v))\n\ndef read_uint16(f):\n\treturn struct.unpack('H', f.read(2))[0]\n\ndef seek_nth_section_sh_offset(f, shtable, e_shentsize, n, offset):\n\tf.seek(shtable + n*e_shentsize + offset)\n\ndef read_uptr(is64, f):\n\tif is64:\n\t\treturn read_uint64(f)\n\telse:\n\t\treturn read_uint32(f)\n\ndef write_uptr(is64, f, v):\n\tif is64:\n\t\treturn write_uint64(f, v)\n\telse:\n\t\treturn write_uint32(f, v)\n\nwith open(sys.argv[1], 'rb+') as f:\n\tassert f.read(4) == b'\\x7fELF'\n\telfclass = read_byte(f)\n\tassert (elfclass == ELFCLASS32) or (elfclass == ELFCLASS64)\n\tis64 = elfclass == ELFCLASS64\n\n\t# Hardcoded offsets for fields of the ELF header - a more sophisticated\n\t# tweaker would parse the structure, but we only need to make some very\n\t# small tweaks\n\tif is64:\n\t\te_shoff_offset = 0x28\n\t\te_shentsize_offset = 0x3a\n\t\te_shnum_offset = 0x3c\n\t\t# offset of sh_offset  the section header\n\t\tsh_offset_offset = 0x18\n\telse:\n\t\te_shoff_offset = 0x20\n\t\te_shentsize_offset = 0x2e\n\t\te_shnum_offset = 0x30\n\t\tsh_offset_offset = 0x10\n\n\tf.seek(e_shoff_offset)\n\te_shoff = read_uptr(is64, f)\n\n\tf.seek(e_shentsize_offset)\n\te_shentsize = read_uint16(f)\n\n\tf.seek(e_shnum_offset)\n\te_shnum = read_uint16(f)\n\n\told_offset = e_shoff\n\tsize = e_shentsize * e_shnum\n\n\tassert size <= reserved_size\n\tfile_size = os.stat(sys.argv[1]).st_size\n\tassert old_offset + size == file_size\n\n\tf.seek(old_offset)\n\tdata = f.read(size)\n\n\tf.seek(new_table_offset)\n\tf.write(data)\n\n\tf.seek(e_shoff_offset)\n\twrite_uptr(is64, f, new_table_offset)\n\n\talloc_offset = new_table_offset + size\n\tfor n in range(e_shnum-3, e_shnum):\n\t\tseek_nth_section_sh_offset(f, new_table_offset, e_shentsize, n, sh_offset_offset)\n\t\tsh_offs = read_uptr(is64, f)\n\t\tsh_size = read_uptr(is64, f)\n\n\t\tf.seek(sh_offs)\n\t\tsh_data = f.read(sh_size)\n\n\t\tnew_section_offset = (alloc_offset + sect_align - 1) & ~(sect_align-1)\n\t\tf.seek(new_section_offset)\n\n\t\tf.write(sh_data)\n\n\t\tseek_nth_section_sh_offset(f, new_table_offset, e_shentsize, n, sh_offset_offset)\n\t\twrite_uptr(is64, f, new_section_offset)\n\n\t\talloc_offset = new_section_offset + sh_size\n\t\tassert (alloc_offset - new_section_offset) <= reserved_size\n\n\t# At replay time, Gdb may try to read the full image of the librrpage.so.\n\t# If the runtime page size and the block size in librrpage.so does not agree\n\t# the memory past the end of the first page of memory at 0x70000000 may not exist\n\t# and it can cause gdb to not read any symbol for librrpage.so\n\t# Simply make sure the file is long enough and the mapping is valid.\n\tif file_size < 5 * reserved_size:\n\t\tf.seek(file_size)\n\t\tf.write(b'\\0' * (5 * reserved_size - file_size))\n"
  },
  {
    "path": "src/processor_trace_check.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"processor_trace_check.h\"\n\n#include <ostream>\n#include <sstream>\n#include <string>\n#include <vector>\n\n#include \"PerfCounters.h\"\n#include \"ProcessorTraceDecoder.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"remote_code_ptr.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic bool get_next_instruction(ReplayTask* t, ProcessorTraceDecoder& decoder,\n                                 ProcessorTraceDecoder::Instruction* out,\n                                 remote_code_ptr instruction_to_ignore = remote_code_ptr()) {\n  while (true) {\n    bool result = decoder.next_instruction(out);\n    if (!result) {\n      return false;\n    }\n    if (out->address == t->vm()->do_breakpoint_fault_addr() ||\n        out->address == instruction_to_ignore) {\n      continue;\n    }\n    return true;\n  }\n}\n\nstatic string intel_pt_context(ReplayTask* t, const vector<uint8_t>& record_pt_data,\n    const vector<uint8_t>& replay_pt_data, int instruction_count,\n    remote_ptr<void> patch_addr,\n    const vector<uint8_t>& patch_data,\n    remote_code_ptr record_instruction_to_ignore) {\n  stringstream out;\n  unordered_map<remote_code_ptr, int> execution_counts;\n  ProcessorTraceDecoder record_pt_decoder(t, record_pt_data,\n      ProcessorTraceDecoder::IS_RECORDING);\n  record_pt_decoder.set_patch(patch_addr, patch_data);\n  ProcessorTraceDecoder replay_pt_decoder(t, replay_pt_data,\n      ProcessorTraceDecoder::IS_REPLAY);\n  replay_pt_decoder.set_patch(patch_addr, patch_data);\n  int start_at = max(0, instruction_count - 100);\n  out << \"\\nrecord and replay (\" << start_at << \" instructions skipped)\";\n  for (int i = 0; i < instruction_count; ++i) {\n    ProcessorTraceDecoder::Instruction tmp;\n    get_next_instruction(t, record_pt_decoder, &tmp, record_instruction_to_ignore);\n    get_next_instruction(t, replay_pt_decoder, &tmp);\n    ++execution_counts[tmp.address];\n    if (i >= start_at) {\n      out << \"\\n\" << tmp.address << \" (execution \"\n          << execution_counts[tmp.address] << \")\";\n    }\n  }\n  out << \"\\nrecord\";\n  for (int i = 0; i < 10; ++i) {\n    ProcessorTraceDecoder::Instruction tmp;\n    if (get_next_instruction(t, record_pt_decoder, &tmp, record_instruction_to_ignore)) {\n      out << \"\\n\" << tmp.address;\n    } else {\n      break;\n    }\n  }\n  out << \"\\nreplay\";\n  for (int i = 0; i < 10; ++i) {\n    ProcessorTraceDecoder::Instruction tmp;\n    if (get_next_instruction(t, replay_pt_decoder, &tmp)) {\n      out << \"\\n\" << tmp.address;\n    } else {\n      break;\n    }\n  }\n  return out.str();\n}\n\nstatic vector<uint8_t> flatten_vector(const vector<vector<uint8_t>>& data) {\n  vector<uint8_t> ret;\n  size_t total_size = 0;\n  for (const auto& d : data) {\n    total_size += d.size();\n  }\n  ret.resize(total_size);\n  if (total_size) {\n    size_t offset = 0;\n    for (const auto& d : data) {\n      memcpy(ret.data() + offset, d.data(), d.size());\n      offset += d.size();\n    }\n  }\n  return ret;\n}\n\nstatic bool check_intel_pt_internal(ReplayTask* t,\n    const PTData& replay_pt_data, ostream& stream) {\n  remote_ptr<void> patch_addr;\n  vector<uint8_t> patch_data;\n  remote_code_ptr record_instruction_to_ignore;\n\n  const Event& ev = t->session().current_trace_frame().event();\n  switch (ev.type()) {\n    case EV_PATCH_SYSCALL:\n      // The task now has the syscallbuf patch applied.\n      // But when we executed this code, there was a syscall\n      // there.\n      patch_addr = t->ip().to_data_ptr<void>();\n      patch_data = syscall_instruction(t->arch());\n      break;\n    case EV_SYSCALL:\n      // This instruction may not be executed due to the breakpoint\n      // optimization we do during replay.\n      record_instruction_to_ignore =\n        t->session().current_trace_frame().regs().ip().decrement_by_syscall_insn_length(\n          t->arch());\n      break;\n    default:\n      break;\n  }\n\n  vector<uint8_t> replay_data = flatten_vector(replay_pt_data.data);\n\n  FrameTime recorded_pt_data_time = t->current_frame_time();\n  if (ev.has_ticks_slop()) {\n    // This is for an emergency debugging dump. Look for PT data\n    // associated with the next event instead since that will have\n    // accumulated the data for this event.\n    ++recorded_pt_data_time;\n  }\n  vector<uint8_t> record_pt_data = read_pt_data(t, recorded_pt_data_time);\n  ProcessorTraceDecoder record_pt_decoder(t, record_pt_data,\n      ProcessorTraceDecoder::IS_RECORDING);\n  record_pt_decoder.set_patch(patch_addr, patch_data);\n  ProcessorTraceDecoder replay_pt_decoder(t, replay_data,\n      ProcessorTraceDecoder::IS_REPLAY);\n  replay_pt_decoder.set_patch(patch_addr, patch_data);\n\n  int instruction_count = 0;\n  while (true) {\n    ProcessorTraceDecoder::Instruction record_instruction;\n    bool got_record_instruction =\n        get_next_instruction(t, record_pt_decoder, &record_instruction,\n            record_instruction_to_ignore);\n    ProcessorTraceDecoder::Instruction replay_instruction;\n    bool got_replay_instruction =\n        get_next_instruction(t, replay_pt_decoder, &replay_instruction);\n    if (got_record_instruction != got_replay_instruction) {\n      stream << \"Instruction sequence ended early: got_record_instruction \"\n          << got_record_instruction << \" got_replay_instruction \"\n          << got_replay_instruction\n          << intel_pt_context(t, record_pt_data, replay_data, instruction_count,\n                              patch_addr, patch_data, record_instruction_to_ignore) << \"\\n\";\n      return false;\n    }\n    if (!got_record_instruction) {\n      break;\n    }\n    if (record_instruction.address != replay_instruction.address) {\n      stream << \"Control flow diverged\"\n          << intel_pt_context(t, record_pt_data, replay_data, instruction_count,\n                              patch_addr, patch_data, record_instruction_to_ignore) << \"\\n\";\n      return false;\n    }\n    ++instruction_count;\n  }\n  if (instruction_count) {\n    LOG(debug) << \"check_intel_pt verified \" << instruction_count << \" instructions\";\n  }\n  return true;\n}\n\nvoid check_intel_pt_if_enabled(ReplayTask* t) {\n  const Event& ev = t->session().current_trace_frame().event();\n  if (ev.has_ticks_slop()) {\n    // Only check PT data at events whose timing is exactly\n    // the same between record and replay.\n    return;\n  }\n\n  // Always extract PT data if there is any, and throw it\n  // away if we don't want to check it.\n  PTData replay_pt_data = t->hpc.extract_intel_pt_data();\n\n  FrameTime start_checking_event =\n    t->session().flags().intel_pt_start_checking_event;\n  if (start_checking_event < 0) {\n    return;\n  }\n  FrameTime current_time = t->current_frame_time();\n  if (start_checking_event > current_time ||\n      !t->session().done_initial_exec()) {\n    return;\n  }\n  stringstream stream;\n  bool ok = check_intel_pt_internal(t, replay_pt_data, stream);\n  ASSERT(t, ok) << \"Intel PT detected control flow divergence: \"\n      << stream.str();\n}\n\nvoid emergency_check_intel_pt(ReplayTask* t, ostream& stream) {\n  PTData replay_pt_data = t->hpc.extract_intel_pt_data();\n  if (!replay_pt_data.data.empty()) {\n    check_intel_pt_internal(t, replay_pt_data, stream);\n  }\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/processor_trace_check.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PROCESSOR_TRACE_CHECK_H_\n#define RR_PROCESSOR_TRACE_CHECK_H_\n\n#include <ostream>\n\nnamespace rr {\n\nclass ReplayTask;\n\nvoid check_intel_pt_if_enabled(ReplayTask* t);\n\nvoid emergency_check_intel_pt(ReplayTask* t, std::ostream& stream);\n\n} // namespace rr\n\n#endif /* RR_PROCESSOR_TRACE_CHECK_H_ */\n"
  },
  {
    "path": "src/record_signal.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"record_signal.h\"\n\n#include <fcntl.h>\n#include <linux/perf_event.h>\n#include <sched.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/prctl.h>\n#include <sys/resource.h>\n#include <sys/user.h>\n#include <syscall.h>\n\n#include \"preload/preload_interface.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"Flags.h\"\n#include \"PerfCounters.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"TraceStream.h\"\n#include \"VirtualPerfCounterMonitor.h\"\n#include \"core.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"util.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nstatic void restore_sighandler_if_not_default(RecordTask* t, int sig) {\n  if (t->sig_disposition(sig) != SIGNAL_DEFAULT) {\n    LOG(debug) << \"Restoring signal handler for \" << signal_name(sig);\n    AutoRemoteSyscalls remote(t);\n    size_t sigset_size = sigaction_sigset_size(remote.arch());\n    const vector<uint8_t>& sa = t->signal_action(sig);\n    AutoRestoreMem child_sa(remote, sa.data(), sa.size());\n    remote.infallible_syscall(syscall_number_for_rt_sigaction(remote.arch()),\n                              sig, child_sa.get().as_int(), nullptr,\n                              sigset_size);\n  }\n}\n\n/**\n * Restore the blocked-ness and sigaction for |sig| from |t|'s local\n * copy.\n */\nstatic void restore_signal_state(RecordTask* t, int sig,\n                                 SignalBlocked signal_was_blocked) {\n  restore_sighandler_if_not_default(t, sig);\n  if (signal_was_blocked) {\n    LOG(debug) << \"Restoring signal blocked-ness for \" << signal_name(sig);\n    AutoRemoteSyscalls remote(t);\n    size_t sigset_size = sigaction_sigset_size(remote.arch());\n    vector<uint8_t> bytes;\n    bytes.resize(sigset_size);\n    memset(bytes.data(), 0, sigset_size);\n    sig_set_t mask = signal_bit(sig);\n    ASSERT(t, sigset_size >= sizeof(mask));\n    memcpy(bytes.data(), &mask, sizeof(mask));\n    AutoRestoreMem child_block(remote, bytes.data(), bytes.size());\n    remote.infallible_syscall(syscall_number_for_rt_sigprocmask(remote.arch()),\n                              SIG_BLOCK, child_block.get().as_int(), nullptr,\n                              sigset_size);\n    // We just changed the sigmask ourselves.\n    t->invalidate_sigmask();\n  }\n}\n\n/**\n * Return true if |t| was stopped because of a SIGSEGV resulting\n * from a disabled instruction and |t| was updated appropriately, false\n * otherwise.\n */\nstatic bool try_handle_trapped_instruction(RecordTask* t, siginfo_t* si) {\n  ASSERT(t, si->si_signo == SIGSEGV);\n\n  auto special_instruction = special_instruction_at(t, t->ip());\n  switch (special_instruction.opcode) {\n    case SpecialInstOpcode::ARM_MRS_CNTFRQ_EL0:\n    case SpecialInstOpcode::ARM_MRS_CNTVCT_EL0:\n    case SpecialInstOpcode::ARM_MRS_CNTVCTSS_EL0:\n    case SpecialInstOpcode::X86_RDTSC:\n    case SpecialInstOpcode::X86_RDTSCP:\n      if (t->tsc_mode == PR_TSC_SIGSEGV) {\n        return false;\n      }\n      break;\n    case SpecialInstOpcode::X86_CPUID:\n      if (t->cpuid_mode == 0) {\n        return false;\n      }\n      break;\n    default:\n      return false;\n  }\n\n  size_t len = special_instruction_len(special_instruction.opcode);\n  ASSERT(t, len > 0);\n\n  Registers r = t->regs();\n  bool should_retry_patch = false;\n  if (special_instruction.opcode == SpecialInstOpcode::ARM_MRS_CNTVCT_EL0 ||\n      special_instruction.opcode == SpecialInstOpcode::ARM_MRS_CNTVCTSS_EL0) {\n    if (special_instruction.regno != 31) {\n      r.set_x(special_instruction.regno, cntvct());\n    }\n  } else if (special_instruction.opcode == SpecialInstOpcode::ARM_MRS_CNTFRQ_EL0) {\n    if (special_instruction.regno != 31) {\n      r.set_x(special_instruction.regno, cntfrq());\n    }\n  } else if (special_instruction.opcode == SpecialInstOpcode::X86_RDTSC ||\n             special_instruction.opcode == SpecialInstOpcode::X86_RDTSCP) {\n    if (special_instruction.opcode == SpecialInstOpcode::X86_RDTSC &&\n        t->vm()->monkeypatcher().try_patch_trapping_instruction(t, len, true, should_retry_patch)) {\n      Event ev = Event::patch_syscall();\n      ev.PatchSyscall().patch_trapping_instruction = true;\n      t->record_event(ev);\n      t->push_event(Event::noop());\n      return true;\n    }\n\n    unsigned long long current_time = rdtsc();\n    r.set_rdtsc_output(current_time);\n\n    LOG(debug) << \" trapped for rdtsc: returning \" << current_time;\n  } else if (special_instruction.opcode == SpecialInstOpcode::X86_CPUID) {\n    auto eax = r.syscallno();\n    auto ecx = r.cx();\n    auto cpuid_data = cpuid(eax, ecx);\n    t->session().disable_cpuid_features()\n        .amend_cpuid_data(eax, ecx, &cpuid_data);\n    r.set_cpuid_output(cpuid_data.eax, cpuid_data.ebx, cpuid_data.ecx,\n                       cpuid_data.edx);\n    LOG(debug) << \" trapped for cpuid: \" << HEX(eax) << \":\" << HEX(ecx);\n  }\n\n  r.set_ip(r.ip() + len);\n  t->set_regs(r);\n  t->record_event(Event::instruction_trap());\n\n  if (should_retry_patch) {\n    LOG(debug) << \"Retrying deferred syscall patching\";\n    should_retry_patch = false;\n    if (t->vm()->monkeypatcher().try_patch_trapping_instruction(t, len, false, should_retry_patch)) {\n      // Instruction was patched. Emit event.\n      auto ev = Event::patch_syscall();\n      ev.PatchSyscall().patch_after_syscall = true;\n      t->record_event(ev);\n    }\n    ASSERT(t, !should_retry_patch);\n  }\n\n  t->push_event(Event::noop());\n  return true;\n}\n\n/**\n * Return true if |t| was stopped because of a SIGSEGV and we want to retry\n * the instruction after emulating MAP_GROWSDOWN.\n */\nstatic bool try_grow_map(RecordTask* t, siginfo_t* si) {\n  ASSERT(t, si->si_signo == SIGSEGV);\n\n  // Use kernel_abi to avoid odd inconsistencies between distros\n  auto arch_si = reinterpret_cast<NativeArch::siginfo_t*>(si);\n  auto addr = arch_si->_sifields._sigfault.si_addr_.rptr();\n  if (t->try_grow_map(addr)) {\n    t->push_event(Event::noop());\n    return true;\n  }\n  return false;\n}\n\nvoid disarm_desched_event(RecordTask* t) {\n  ScopedFd& fd = t->desched_fd.tracee_fd();\n  if (fd.is_open() && ioctl(fd, PERF_EVENT_IOC_DISABLE, 0)) {\n    FATAL() << \"Failed to disarm desched event\";\n  }\n}\n\nvoid arm_desched_event(RecordTask* t) {\n  ScopedFd& fd = t->desched_fd.tracee_fd();\n  if (fd.is_open() && ioctl(fd, PERF_EVENT_IOC_ENABLE, 0)) {\n    FATAL() << \"Failed to arm desched event\";\n  }\n}\n\nbool desched_event_armed(RecordTask *t) {\n  if (t->syscallbuf_child == nullptr) {\n    return false;\n  }\n  bool ok = true;\n  bool is_armed = t->read_mem(\n    REMOTE_PTR_FIELD(t->syscallbuf_child, desched_signal_may_be_relevant), &ok);\n  if (!ok) {\n    // If we can't read this (perhaps syscallbuf isn't actually mapped), it's not armed\n    return false;\n  }\n  return is_armed;\n}\n\ntemplate <typename Arch>\nstatic remote_code_ptr get_stub_scratch_1_arch(RecordTask* t) {\n  auto remote_locals = AddressSpace::preload_thread_locals_start()\n    .cast<preload_thread_locals<Arch>>();\n  auto remote_stub_scratch_1 = REMOTE_PTR_FIELD(remote_locals, stub_scratch_1);\n  return t->read_mem(remote_stub_scratch_1).rptr().as_int();\n}\n\nstatic remote_code_ptr get_stub_scratch_1(RecordTask* t) {\n  RR_ARCH_FUNCTION(get_stub_scratch_1_arch, t->arch(), t);\n}\n\ntemplate <typename Arch>\nstatic void get_stub_scratch_2_arch(RecordTask* t, void *buff, size_t sz) {\n  auto remote_locals = AddressSpace::preload_thread_locals_start()\n    .cast<preload_thread_locals<Arch>>();\n  auto remote_stub_scratch_2 = REMOTE_PTR_FIELD(remote_locals, stub_scratch_2);\n  t->read_bytes_helper(remote_stub_scratch_2, sz, buff);\n}\n\nstatic void get_stub_scratch_2(RecordTask* t, void *buff, size_t sz) {\n  RR_ARCH_FUNCTION(get_stub_scratch_2_arch, t->arch(), t, buff, sz);\n}\n\n/**\n * This function is responsible for handling breakpoints we set in syscallbuf\n * code to detect sigprocmask calls and syscallbuf exit. It's called when we\n * get a SIGTRAP. Returns true if the SIGTRAP was called by one of our\n * breakpoints and should be hidden from the application.\n * If it was triggered by one of our breakpoints, we have to call\n * restore_sighandler_if_not_default(t, SIGTRAP) to make sure the SIGTRAP\n * handler is properly restored if the kernel cleared it.\n */\nbool handle_syscallbuf_breakpoint(RecordTask* t) {\n  if (t->is_at_syscallbuf_final_instruction_breakpoint()) {\n    LOG(debug) << \"Reached final syscallbuf instruction, singlestepping to \"\n                  \"enable signal dispatch\";\n    // Emulate the effect of the return from syscallbuf.\n    // On x86, this is a single instruction that jumps to the location stored in\n    // preload_thread_locals::stub_scratch_1.\n    // On aarch64, the target of the jump is an instruction that restores\n    // x15 and x30 and then jump back to the syscall.\n    // To minimize the surprise to the tracee if we decide to deliver a signal\n    // we'll emulate the register restore and return directly to the syscall site.\n    // The address in stub_scratch_1 is already the correct address for this.\n    if (t->arch() == aarch64) {\n      uint64_t x15_x30[2];\n      get_stub_scratch_2(t, x15_x30, 16);\n      Registers r = t->regs();\n      r.set_x(15, x15_x30[0]);\n      r.set_x(30, x15_x30[1]);\n      t->set_regs(r);\n      t->count_direct_jump();\n    }\n    t->emulate_jump(get_stub_scratch_1(t));\n\n    restore_sighandler_if_not_default(t, SIGTRAP);\n    // Now we're back in application code so any pending stashed signals\n    // will be handled.\n    return true;\n  }\n\n  if (t->is_at_syscallstub_exit_breakpoint()) {\n    LOG(debug) << \"Reached syscallstub exit instruction, singlestepping to \"\n                  \"enable signal dispatch\";\n    ASSERT(t, t->arch() == aarch64 && t->syscallstub_exit_breakpoint);\n    auto retaddr_addr = t->syscallstub_exit_breakpoint.to_data_ptr<uint8_t>() + 3 * 4;\n    uint64_t retaddr;\n    t->read_bytes_helper(retaddr_addr, sizeof(retaddr), &retaddr);\n    Registers r = t->regs();\n    r.set_ip(retaddr);\n    t->set_regs(r);\n    t->count_direct_jump();\n    t->syscallstub_exit_breakpoint = nullptr;\n    restore_sighandler_if_not_default(t, SIGTRAP);\n    // Now we're back in application code so any pending stashed signals\n    // will be handled.\n    return true;\n  }\n\n  if (!t->is_at_syscallbuf_syscall_entry_breakpoint()) {\n    return false;\n  }\n\n  Registers r = t->regs();\n  r.set_ip(r.ip().undo_executed_bkpt(t->arch()));\n  t->set_regs(r);\n\n  if (t->is_at_traced_syscall_entry()) {\n    // We will automatically dispatch stashed signals now since this is an\n    // allowed place to dispatch signals.\n    LOG(debug) << \"Allowing signal dispatch at traced-syscall breakpoint\";\n    restore_sighandler_if_not_default(t, SIGTRAP);\n    return true;\n  }\n\n  // We're at an untraced-syscall entry point.\n  // To allow an AutoRemoteSyscall, we need to make sure desched signals are\n  // disarmed (and rearmed afterward).\n  bool armed_desched_event = desched_event_armed(t);\n  if (armed_desched_event) {\n    disarm_desched_event(t);\n  }\n  restore_sighandler_if_not_default(t, SIGTRAP);\n  if (armed_desched_event) {\n    arm_desched_event(t);\n  }\n\n  // This is definitely a native-arch syscall.\n  if (is_rt_sigprocmask_syscall(r.syscallno(), t->arch())) {\n    // Don't proceed with this syscall. Emulate it returning EAGAIN.\n    // Syscallbuf logic will retry using a traced syscall instead.\n    r.set_syscall_result(-EAGAIN);\n    r.set_ip(r.ip().increment_by_syscall_insn_length(t->arch()));\n    t->set_regs(r);\n    t->canonicalize_regs(t->arch());\n    LOG(debug) << \"Emulated EAGAIN to avoid untraced sigprocmask with pending \"\n                  \"stashed signal\";\n    // Leave breakpoints enabled since we want to break at the traced-syscall\n    // fallback for rt_sigprocmask.\n    return true;\n  }\n\n  // We can proceed with the untraced syscall. Either it will complete and\n  // execution will continue until we reach some point where we can deliver our\n  // signal, or it will block at which point we'll be able to deliver our\n  // signal.\n  LOG(debug) << \"Disabling breakpoints at untraced syscalls\";\n  t->break_at_syscallbuf_untraced_syscalls = false;\n  return true;\n}\n\n/**\n * Return the event needing to be processed after this desched of |t|.\n * The tracee's execution may be advanced, and if so |regs| is updated\n * to the tracee's latest state.\n */\nstatic void handle_desched_event(RecordTask* t) {\n  /* If the tracee isn't in the critical section where a desched\n   * event is relevant, we can ignore it.  See the long comments\n   * in syscall_buffer.c.\n   *\n   * It's OK if the tracee is in the critical section for a\n   * may-block syscall B, but this signal was delivered by an\n   * event programmed by a previous may-block syscall A.\n   *\n   * If we're running in a signal handler inside an interrupted syscallbuf\n   * system call, never do anything here. Syscall buffering is disabled and\n   * the desched_signal_may_be_relevant was set by the outermost syscallbuf\n   * invocation.\n   */\n  if (!desched_event_armed(t) || t->running_inside_desched()) {\n    LOG(debug) << \"  (not entering may-block syscall; resuming)\";\n    /* We have to disarm the event just in case the tracee\n     * has cleared the relevancy flag, but not yet\n     * disarmed the event itself. */\n    disarm_desched_event(t);\n    t->push_event(Event::noop());\n    return;\n  }\n\n  /* TODO: how can signals interrupt us here? */\n\n  /* The desched event just fired.  That implies that the\n   * arm-desched ioctl went into effect, and that the\n   * disarm-desched syscall didn't take effect.  Since a signal\n   * is pending for the tracee, then if the tracee was in a\n   * syscall, linux has exited it with an -ERESTART* error code.\n   * That means the tracee is about to (re-)enter either\n   *\n   *  1. buffered syscall\n   *  2. disarm-desched ioctl syscall\n   *\n   * We can figure out which one by simply issuing a\n   * ptrace(SYSCALL) and examining the tracee's registers.\n   *\n   * If the tracee enters the disarm-desched ioctl, it's going\n   * to commit a record of the buffered syscall to the\n   * syscallbuf, and we can safely send the tracee back on its\n   * way, ignoring the desched completely.\n   *\n   * If it enters the buffered syscall, then the desched event\n   * has served its purpose and we need to prepare the tracee to\n   * be context-switched.\n   *\n   * An annoyance of the desched signal is that when the tracer\n   * is descheduled in interval (C) above, we see normally (see\n   * below) see *two* signals.  The current theory of what's\n   * happening is\n   *\n   *  o child gets descheduled, bumps counter to i and schedules\n   *    signal\n   *  o signal notification \"schedules\" child, but it doesn't\n   *    actually run any application code\n   *  o child is being ptraced, so we \"deschedule\" child to\n   *    notify parent and bump counter to i+1.  (The parent\n   *    hasn't had a chance to clear the counter yet.)\n   *  o another counter signal is generated, but signal is\n   *    already pending so this one is queued\n   *  o parent is notified and sees counter value i+1\n   *  o parent stops delivery of first signal and disarms\n   *    counter\n   *  o second signal dequeued and delivered, notifying parent\n   *    (counter is disarmed now, so no pseudo-desched possible\n   *    here)\n   *  o parent notifiedand sees counter value i+1 again\n   *  o parent stops delivery of second signal and we continue on\n   *\n   * So we \"work around\" this by the tracer expecting two signal\n   * notifications, and silently discarding both.\n   *\n   * One really fun edge case is that sometimes the desched\n   * signal will interrupt the arm-desched syscall itself.\n   * Continuing to the next syscall boundary seems to restart\n   * the arm-desched syscall, and advancing to the boundary\n   * again exits it and we start receiving desched signals\n   * again.\n   *\n   * That may be a kernel bug, but we handle it by just\n   * continuing until we we continue past the arm-desched\n   * syscall *and* stop seeing signals. */\n\n  const auto untraced_record_only_entry =\n    uintptr_t(RR_PAGE_SYSCALL_UNTRACED_RECORDING_ONLY);\n  auto syscall_entry_ip = t->ip().decrement_by_syscall_insn_length(t->arch());\n  if (syscall_entry_ip == remote_code_ptr(untraced_record_only_entry) &&\n      t->regs().syscall_result_signed() == -EFAULT) {\n    intptr_t syscallno;\n    if (t->arch() == aarch64) {\n      // Untraced syscall, we may not have set original_syscallno for this on aarch64.\n      syscallno = t->regs().syscallno();\n    } else {\n      // On x86, syscall no is overwritten by return value.\n      ASSERT(t, is_x86ish(t->arch()));\n      syscallno = t->regs().original_syscallno();\n    }\n    if (syscallno == syscall_number_for_getsockopt(t->arch())) {\n      // We've observed interrupted getsockopt syscalls returning `EFAULT`\n      // rather than the normal ERESTART*.\n      // This is a kernel bug caused by CONFIG_BPFILTER_UMH.\n      // Try to reduce the effect caused by rr generated signals\n      // by manually restarting the syscall\n      // (since the previous syscall returned EFAULT\n      //  we would in the worst case just get another EFAULT).\n      // Note that setting syscall result to ERESTART* wouldn't work on aarch64\n      // if the arg1 has been overwritten by AutoRemoteSyscalls.\n      auto r = t->regs();\n      r.set_ip(syscall_entry_ip);\n      if (t->arch() == aarch64) {\n        // On AArch64, we need to restore arg1 from the stack argument from syscallbuf.\n        auto orig_arg1_ptr = r.sp() + sizeof(long);\n        auto orig_arg1 = t->read_mem(orig_arg1_ptr.cast<long>());\n        r.set_arg1(orig_arg1);\n      } else {\n        ASSERT(t, is_x86ish(t->arch()));\n        // On x86, we need to restore syscall number\n        r.set_syscallno(syscallno);\n      }\n      t->set_regs(r);\n    }\n  }\n\n  while (true) {\n    // Prevent further desched notifications from firing\n    // while we're advancing the tracee.  We're going to\n    // leave it in a consistent state anyway, so the event\n    // is no longer useful.  We have to do this in each\n    // loop iteration because a restarted arm-desched\n    // syscall may have re-armed the event.\n    disarm_desched_event(t);\n\n    if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_UNLIMITED_TICKS)) {\n      LOG(debug) << \"  (got exit, bailing out)\";\n      t->push_event(Event::noop());\n      return;\n    }\n\n    if (t->status().is_syscall()) {\n      t->apply_syscall_entry_regs();\n      if (t->is_arm_desched_event_syscall()) {\n        continue;\n      }\n      break;\n    }\n    if (t->ptrace_event() == PTRACE_EVENT_SECCOMP) {\n      ASSERT(t,\n             t->session().syscall_seccomp_ordering() ==\n                 Session::SECCOMP_BEFORE_PTRACE_SYSCALL);\n      // This is the old kernel event ordering. This must be a SECCOMP event\n      // for the buffered syscall; it's not rr-generated because this is an\n      // untraced syscall, but it could be generated by a tracee's\n      // seccomp filter.\n      break;\n    }\n\n    // Completely ignore spurious desched signals and\n    // signals that aren't going to be delivered to the\n    // tracee.\n    //\n    // Also ignore time-slice signals.  If the tracee ends\n    // up at the disarm-desched ioctl, we'll reschedule it\n    // with the ticks interrupt still programmed.  At worst,\n    // the tracee will get an extra time-slice out of\n    // this, on average, so we don't worry too much about\n    // it.\n    //\n    // TODO: it's theoretically possible for this to\n    // happen an unbounded number of consecutive times\n    // and the tracee never switched out.\n    int sig = t->stop_sig();\n    ASSERT(t, sig) << \"expected stop-signal, got \" << t->status();\n    if (SIGTRAP == sig && handle_syscallbuf_breakpoint(t)) {\n      // We stopped at a breakpoint on an untraced may-block syscall.\n      // This can't be relevant to us since sigprocmask isn't may-block.\n      LOG(debug) << \" disabling breakpoints on untraced syscalls\";\n      continue;\n    }\n    if (t->session().syscallbuf_desched_sig() == sig ||\n        PerfCounters::TIME_SLICE_SIGNAL == sig || t->is_sig_ignored(sig)) {\n      LOG(debug) << \"  dropping ignored \" << signal_name(sig);\n      continue;\n    }\n\n    LOG(debug) << \"  stashing \" << signal_name(sig);\n    t->stash_sig();\n  }\n\n  if (t->is_disarm_desched_event_syscall()) {\n    LOG(debug)\n        << \"  (at disarm-desched, so finished buffered syscall; resuming)\";\n    t->push_event(Event::noop());\n    return;\n  }\n\n  if (t->desched_rec()) {\n    // We're already processing a desched. We probably reexecuted the\n    // system call (e.g. because a signal was processed) and the syscall\n    // blocked again. Carry on with the current desched.\n  } else {\n    /* This prevents the syscallbuf record counter from being\n     * reset until we've finished guiding the tracee through this\n     * interrupted call.  We use the record counter for\n     * assertions. */\n    ASSERT(t, !t->delay_syscallbuf_reset_for_desched);\n    t->delay_syscallbuf_reset_for_desched = true;\n    LOG(debug) << \"Desched initiated\";\n\n    /* The tracee is (re-)entering the buffered syscall.  Stash\n     * away this breadcrumb so that we can figure out what syscall\n     * the tracee was in, and how much \"scratch\" space it carved\n     * off the syscallbuf, if needed. */\n    remote_ptr<const struct syscallbuf_record> desched_rec =\n        t->next_syscallbuf_record();\n    t->push_event(DeschedEvent(desched_rec));\n    int call = t->read_mem(REMOTE_PTR_FIELD(t->desched_rec(), syscallno));\n\n    /* The descheduled syscall was interrupted by a signal, like\n     * all other may-restart syscalls, with the exception that\n     * this one has already been restarted (which we'll detect\n     * back in the main loop). */\n    t->push_event(Event(interrupted, SyscallEvent(call, t->arch())));\n    SyscallEvent& ev = t->ev().Syscall();\n    ev.desched_rec = desched_rec;\n  }\n\n  SyscallEvent& ev = t->ev().Syscall();\n  ev.regs = t->regs();\n  /* For some syscalls (at least poll) but not all (at least not read),\n   * repeated cont_syscall()s above of the same interrupted syscall\n   * can set $orig_eax to 0 ... for unclear reasons. Fix that up here\n   * otherwise we'll get a divergence during replay, which will not\n   * encounter this problem.\n   */\n  int call = t->read_mem(REMOTE_PTR_FIELD(t->desched_rec(), syscallno));\n  ev.regs.set_original_syscallno(call);\n  t->set_regs(ev.regs);\n  // runnable_state_changed will observe us entering this syscall and change\n  // state to ENTERING_SYSCALL\n\n  LOG(debug) << \"  resuming (and probably switching out) blocked `\"\n             << syscall_name(call, ev.arch()) << \"'\";\n}\n\nstatic bool is_safe_to_deliver_signal(RecordTask* t, siginfo_t* si) {\n  if (!t->is_in_syscallbuf()) {\n    /* The tracee is outside the syscallbuf code,\n     * so in most cases can't possibly affect\n     * syscallbuf critical sections.  The\n     * exception is signal handlers \"re-entering\"\n     * desched'd syscalls, which are OK. */\n    LOG(debug) << \"Safe to deliver signal at \" << t->ip()\n               << \" because not in syscallbuf\";\n    return true;\n  }\n\n  // Note that this will never fire on aarch64 in a signal stop\n  // since the ip has been moved to the syscall entry.\n  // We will catch it in the traced_syscall_entry case below.\n  // We will miss the exit for rrcall_notify_syscall_hook_exit\n  // but that should not be a big problem.\n  if (t->is_in_traced_syscall()) {\n    LOG(debug) << \"Safe to deliver signal at \" << t->ip()\n               << \" because in traced syscall\";\n    return true;\n  }\n\n  // Don't deliver signals just before entering rrcall_notify_syscall_hook_exit.\n  // At that point, notify_on_syscall_hook_exit will be set, but we have\n  // passed the point at which syscallbuf code has checked that flag.\n  // Replay will set notify_on_syscall_hook_exit when we replay towards the\n  // rrcall_notify_syscall_hook_exit *after* handling this signal, but\n  // that will be too late for syscallbuf to notice.\n  // It's OK to delay signal delivery until after rrcall_notify_syscall_hook_exit\n  // anyway.\n  if (t->is_at_traced_syscall_entry() &&\n      !is_rrcall_notify_syscall_hook_exit_syscall(t->regs().syscallno(), t->arch())) {\n    LOG(debug) << \"Safe to deliver signal at \" << t->ip()\n               << \" because at entry to traced syscall\";\n    return true;\n  }\n\n  // On aarch64, the untraced syscall here include both entry and exit\n  // if we are at a signal stop.\n  if (t->is_in_untraced_syscall() && t->desched_rec()) {\n    // Untraced syscalls always use the architecture of the process\n    LOG(debug) << \"Safe to deliver signal at \" << t->ip()\n               << \" because tracee interrupted by desched of \"\n               << syscall_name(t->read_mem(REMOTE_PTR_FIELD(t->desched_rec(),\n                                                            syscallno)),\n                               t->arch());\n    return true;\n  }\n\n  if (t->is_in_untraced_syscall() && si->si_signo == SIGSYS &&\n      si->si_code == SYS_SECCOMP) {\n    LOG(debug) << \"Safe to deliver signal at \" << t->ip()\n               << \" because signal is seccomp trap.\";\n    return true;\n  }\n\n  // If the syscallbuf buffer hasn't been created yet, just delay the signal\n  // with no need to set notify_on_syscall_hook_exit; the signal will be\n  // delivered when rrcall_init_buffers is called.\n  if (t->syscallbuf_child) {\n    if (t->read_mem(REMOTE_PTR_FIELD(t->syscallbuf_child, locked)) & 2) {\n      LOG(debug) << \"Safe to deliver signal at \" << t->ip()\n                 << \" because the syscallbuf is locked\";\n      return true;\n    }\n\n    // A signal (e.g. seccomp SIGSYS) interrupted a untraced syscall in a\n    // non-restartable way. Defer it until SYS_rrcall_notify_syscall_hook_exit.\n    if (t->is_in_untraced_syscall()) {\n      // Our emulation of SYS_rrcall_notify_syscall_hook_exit clears this flag.\n      t->write_mem(\n          REMOTE_PTR_FIELD(t->syscallbuf_child, notify_on_syscall_hook_exit),\n          (uint8_t)1);\n    }\n  }\n\n  LOG(debug) << \"Not safe to deliver signal at \" << t->ip();\n  return false;\n}\n\nSignalHandled handle_signal(RecordTask* t, siginfo_t* si,\n                            SignalDeterministic deterministic,\n                            SignalBlocked signal_was_blocked) {\n  int sig = si->si_signo;\n  LOG(debug) << t->tid << \": handling signal \" << signal_name(sig)\n             << \" (pevent: \" << ptrace_event_name(t->ptrace_event())\n             << \", event: \" << t->ev();\n\n  // Conservatively invalidate the sigmask in case just accepting a signal has\n  // sigmask effects.\n  t->invalidate_sigmask();\n\n  if (deterministic == DETERMINISTIC_SIG) {\n    // When a deterministic signal is triggered, but the signal is currently\n    // blocked or ignored, the kernel (in |force_sig_info|) unblocks it and\n    // sets its disposition to SIG_DFL. It never undoes this (probably\n    // because it expects the signal to be fatal, which it always would be\n    // unless a ptracer intercepts the signal as we do). Therefore, if the\n    // signal was generated for rr's purposes, we need to restore the signal\n    // state ourselves.\n    if (sig == SIGSEGV &&\n        (try_handle_trapped_instruction(t, si) || try_grow_map(t, si))) {\n      if (signal_was_blocked || t->is_sig_ignored(sig)) {\n        restore_signal_state(t, sig, signal_was_blocked);\n      }\n      return SIGNAL_HANDLED;\n    }\n\n    // Since we're not undoing the kernel's changes, update our signal handler\n    // state to match the kernel's.\n    if (signal_was_blocked || t->is_sig_ignored(sig)) {\n      t->did_set_sig_handler_default(sig);\n    }\n  }\n\n  if (!VirtualPerfCounterMonitor::is_virtual_perf_counter_signal(si)) {\n    /* We have to check for a desched event first, because for\n     * those we *do not* want to (and cannot, most of the time)\n     * step the tracee out of the syscallbuf code before\n     * attempting to deliver the signal. */\n    if (t->session().syscallbuf_desched_sig() == si->si_signo &&\n        si->si_code == POLL_IN) {\n      handle_desched_event(t);\n      return SIGNAL_HANDLED;\n    }\n\n    if (!is_safe_to_deliver_signal(t, si)) {\n      return DEFER_SIGNAL;\n    }\n\n    t->set_siginfo_for_synthetic_SIGCHLD(si);\n\n    if (sig == PerfCounters::TIME_SLICE_SIGNAL) {\n      t->push_event(Event::sched());\n      return SIGNAL_HANDLED;\n    }\n  } else {\n    // Clear the magic flag so it doesn't leak into the program.\n    si->si_errno = 0;\n  }\n\n  /* This signal was generated by the program or an external\n   * source, record it normally. */\n\n  if (t->emulate_ptrace_stop(WaitStatus::for_stop_sig(sig), si)) {\n    // Record an event so that replay progresses the tracee to the\n    // current point before we notify the tracer.\n    // If the signal is deterministic, record it as an EV_SIGNAL so that\n    // we replay it using the deterministic-signal replay path. This is\n    // more efficient than emulate_async_signal. Also emulate_async_signal\n    // currently assumes it won't encounter a deterministic SIGTRAP (due to\n    // a hardcoded breakpoint in the tracee).\n    if (deterministic == DETERMINISTIC_SIG) {\n      t->record_event(Event(EV_SIGNAL, SignalEvent(*si, deterministic,\n                                                   t->sig_resolved_disposition(\n                                                       sig, deterministic))));\n    } else {\n      t->record_event(Event::sched());\n    }\n    // ptracer has been notified, so don't deliver the signal now.\n    // The signal won't be delivered for real until the ptracer calls\n    // PTRACE_CONT with the signal number (which we don't support yet!).\n    return SIGNAL_PTRACE_STOP;\n  }\n\n  t->push_event(Event(\n      EV_SIGNAL, SignalEvent(*si, deterministic,\n                             t->sig_resolved_disposition(sig, deterministic))));\n  return SIGNAL_HANDLED;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/record_signal.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_HANDLE_SIGNAL_H__\n#define RR_HANDLE_SIGNAL_H__\n\n#include <signal.h>\n\n#include \"Event.h\"\n\nnamespace rr {\n\nclass RecordTask;\n\nconst int SIGCHLD_SYNTHETIC = 0xbeadf00d;\n\nvoid disarm_desched_event(RecordTask* t);\nvoid arm_desched_event(RecordTask* t);\nbool desched_event_armed(RecordTask *t);\nbool handle_syscallbuf_breakpoint(RecordTask* t);\n\nenum SignalBlocked { SIG_UNBLOCKED = 0, SIG_BLOCKED = 1 };\nenum SignalHandled { SIGNAL_HANDLED, SIGNAL_PTRACE_STOP, DEFER_SIGNAL };\n/**\n * Handle the given signal for |t|.\n * Returns SIGNAL_HANDLED if we handled the signal, SIGNAL_PTRACE_STOP if we\n * didn't handle the signal due to an emulated ptrace-stop, and SIGNAL_DEFER\n * if we can't handle the signal right now and should try calling\n * handle_signal again later in task execution.\n * Handling the signal means we either pushed a new signal event, new\n * desched + syscall-interruption events, or no-op.\n */\nSignalHandled handle_signal(RecordTask* t, siginfo_t* si,\n                            SignalDeterministic deterministic,\n                            SignalBlocked signal_was_blocked);\n\n} // namespace rr\n\n#endif /* RR_HANDLE_SIGNAL_H__ */\n"
  },
  {
    "path": "src/record_syscall.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <arpa/inet.h>\n#include <dirent.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <linux/auxvec.h>\n#include <linux/blkzoned.h>\n#include <linux/capability.h>\n#include <linux/cdrom.h>\n#include <linux/dma-buf.h>\n#include <linux/elf.h>\n#include <linux/ethtool.h>\n#include <linux/fb.h>\n#include <linux/fiemap.h>\n#include <linux/fs.h>\n#include <linux/futex.h>\n#include <linux/hidraw.h>\n#include <linux/if.h>\n#include <linux/if_bridge.h>\n#include <linux/if_packet.h>\n#include <linux/if_tun.h>\n#include <linux/input.h>\n#include <linux/ipc.h>\n#include <linux/joystick.h>\n#include <linux/kd.h>\n#include <linux/msdos_fs.h>\n#include <linux/msg.h>\n#include <linux/net.h>\n#include <linux/netlink.h>\n#include <linux/perf_event.h>\n#include <linux/personality.h>\n#include <linux/prctl.h>\n#include <linux/random.h>\n#include <linux/seccomp.h>\n#include <linux/sem.h>\n#include <linux/shm.h>\n#include <linux/sockios.h>\n#include <linux/videodev2.h>\n#include <linux/vt.h>\n#include <linux/wireless.h>\n#include <mtd/mtd-user.h>\n#include <poll.h>\n#include <sched.h>\n#include <scsi/sg.h>\n#include <sound/asound.h>\n#include <sys/epoll.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/quota.h>\n#include <sys/resource.h>\n#include <sys/socket.h>\n#include <sys/syscall.h>\n#include <sys/sysinfo.h>\n#include <sys/time.h>\n#include <sys/times.h>\n#include <sys/un.h>\n#include <sys/utsname.h>\n#include <sys/vfs.h>\n#include <sys/wait.h>\n#include <sys/xattr.h>\n#include <termios.h>\n\n#include <limits>\n#include <sstream>\n#include <utility>\n#include <unordered_set>\n\n#include <rr/rr.h>\n\n#include \"record_syscall.h\"\n\n#include \"preload/preload_interface.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"BpfMapMonitor.h\"\n#include \"CPUs.h\"\n#include \"DiversionSession.h\"\n#include \"ElfReader.h\"\n#include \"FileMonitor.h\"\n#include \"Flags.h\"\n#include \"MmappedFileMonitor.h\"\n#include \"NonvirtualPerfCounterMonitor.h\"\n#include \"ODirectFileMonitor.h\"\n#include \"ProcFdDirMonitor.h\"\n#include \"ProcMemMonitor.h\"\n#include \"ProcStatMonitor.h\"\n#include \"RRPageMonitor.h\"\n#include \"RecordSession.h\"\n#include \"RecordTask.h\"\n#include \"Scheduler.h\"\n#include \"StdioMonitor.h\"\n#include \"SysCpuMonitor.h\"\n#include \"TraceStream.h\"\n#include \"VirtualPerfCounterMonitor.h\"\n#include \"cpp_supplement.h\"\n#include \"ftrace.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"util.h\"\n\n// muslc defines those, but we want a typedef instead\n#if defined(loff_t)\ntypedef loff_t __musl_loff_t;\n#undef loff_t\ntypedef __musl_loff_t loff_t;\n#endif\n\nusing namespace std;\n\n#ifndef HAVE_TERMIOS2\n// The kernel header that defines this conflicts badly with glibc headers\n// (but not bionic, which does define this) so we define it ourselves.\n// NB: We need this struct defined so that the preprocessor macro for\n// TCGETS2 will evaluate. But we use IOCTL_MASK_SIZE on it and we use\n// the size from the tracee to determine how many bytes to record, so\n// we don't actually depend on this being *accurate*.\nstruct termios2 {\n  tcflag_t c_iflag;\n  tcflag_t c_oflag;\n  tcflag_t c_cflag;\n  tcflag_t c_lflag;\n  cc_t c_line;\n  cc_t c_cc[19];\n  speed_t c_ispeed;\n  speed_t c_ospeed;\n};\n#endif\n\nnamespace rr {\n\nunion _semun {\n  int val;\n  struct semid64_ds* buf;\n  unsigned short int* array;\n  struct seminfo* __buf;\n};\n\n/* We can't include <sys/shm.h> to get shmctl because it clashes with\n * linux/shm.h.\n */\nstatic int _shmctl(int shmid, int cmd, shmid64_ds* buf) {\n#ifdef SYS_shmctl\n  int ret = syscall(SYS_shmctl, shmid, cmd, buf);\n  if (ret >= 0 || errno != ENOSYS) {\n    return ret;\n  }\n#endif\n#ifdef SYS_ipc\n  if (sizeof(void*) == 4) {\n    cmd |= IPC_64;\n  }\n  return syscall(SYS_ipc, SHMCTL, shmid, cmd, 0, buf);\n#else\n  return ret;\n#endif\n}\nstatic int _semctl(int semid, int semnum, int cmd, _semun un_arg) {\n#ifdef SYS_semctl\n  int ret = syscall(SYS_semctl, semid, semnum, cmd, un_arg);\n  if (ret >= 0 || errno != ENOSYS) {\n    return ret;\n  }\n#endif\n#ifdef SYS_ipc\n  if (sizeof(void*) == 4) {\n    cmd |= IPC_64;\n  }\n  return syscall(SYS_ipc, SEMCTL, semid, semnum, cmd, &un_arg);\n#else\n  return ret;\n#endif\n}\n\n/**\n * Modes used to register syscall memory parameter with TaskSyscallState.\n */\nenum ArgMode {\n  // Syscall memory parameter is an in-parameter only.\n  // This is only important when we want to move the buffer to scratch memory\n  // so we can modify it without making the modifications potentially visible\n  // to user code. Otherwise, such parameters can be ignored.\n  IN,\n  // Syscall memory parameter is out-parameter only.\n  OUT,\n  // Syscall memory parameter is an in-out parameter.\n  IN_OUT,\n  // Syscall memory parameter is an in-out parameter but we must not use\n  // scratch (e.g. for futexes, we must use the actual memory word).\n  IN_OUT_NO_SCRATCH\n};\n\n/**\n * Specifies how to determine the size of a syscall memory\n * parameter. There is usually an incoming size determined before the syscall\n * executes (which we need in order to allocate scratch memory), combined\n * with an optional final size taken from the syscall result or a specific\n * memory location after the syscall has executed. The minimum of the incoming\n * and final sizes is used, if both are present.\n */\nstruct ParamSize {\n  ParamSize() : incoming_size(size_t(-1)), from_syscall_multiplier(0) {}\n  // Clamp incoming_size to INTPTR_MAX. No system call can read more data\n  // than that in practice (to a single output parameter).\n  ParamSize(size_t incoming_size)\n      : incoming_size(min<size_t>(INTPTR_MAX, incoming_size)),\n        from_syscall_multiplier(0) {}\n  /**\n   * p points to a tracee location that is already initialized with a\n   * \"maximum buffer size\" passed in by the tracee, and which will be filled\n   * in with the size of the data by the kernel when the syscall exits.\n   */\n  template <typename T>\n  static ParamSize from_initialized_mem(RecordTask* t, remote_ptr<T> p) {\n    ParamSize r(p.is_null() ? size_t(0) : size_t(t->read_mem(p)));\n    r.mem_ptr = p;\n    r.read_size = sizeof(T);\n    return r;\n  }\n  /**\n   * p points to a tracee location which will be filled in with the size of\n   * the data by the kernel when the syscall exits, but the location\n   * is uninitialized before the syscall.\n   */\n  template <typename T> static ParamSize from_mem(remote_ptr<T> p) {\n    ParamSize r;\n    r.mem_ptr = p;\n    r.read_size = sizeof(T);\n    return r;\n  }\n  /**\n   * When the syscall exits, the syscall result will be of type T and contain\n   * the size of the data. 'incoming_size', if present, is a bound on the size\n   * of the data.\n   */\n  template <typename T> static ParamSize from_syscall_result() {\n    ParamSize r;\n    r.from_syscall_multiplier = 1;\n    r.read_size = sizeof(T);\n    return r;\n  }\n  template <typename T>\n  static ParamSize from_syscall_result(size_t incoming_size, uint32_t multiplier = 1) {\n    ParamSize r(incoming_size);\n    r.from_syscall_multiplier = multiplier;\n    r.read_size = sizeof(T);\n    return r;\n  }\n  /**\n   * Indicate that the size will be at most 'max'.\n   */\n  ParamSize limit_size(size_t max) const {\n    ParamSize r(*this);\n    r.incoming_size = min(r.incoming_size, max);\n    return r;\n  }\n\n  /**\n   * Return true if 'other' takes its dynamic size from the same source as\n   * this.\n   * When multiple syscall memory parameters take their dynamic size from the\n   * same source, the source size is distributed among them, with the first\n   * registered parameter taking up to its max_size bytes, followed by the next,\n   * etc. This lets us efficiently record iovec buffers.\n   */\n  bool is_same_source(const ParamSize& other) const {\n    return ((!mem_ptr.is_null() && other.mem_ptr == mem_ptr) ||\n            (from_syscall_multiplier && other.from_syscall_multiplier)) &&\n           (read_size == other.read_size);\n  }\n  /**\n   * Compute the actual size after the syscall has executed.\n   * 'already_consumed' bytes are subtracted from the syscall-result/\n   * memory-location part of the size.\n   */\n  size_t eval(RecordTask* t, size_t already_consumed) const;\n\n  size_t incoming_size;\n  /** If non-null, the size is limited by the value at this location after\n   *  the syscall. */\n  remote_ptr<void> mem_ptr;\n  /** Size of the value at mem_ptr or in the syscall result register. */\n  size_t read_size;\n  /** If from_syscall_multiplier > 0, the size is limited by the value of\n   * the syscall result * from_syscall_multiplier. */\n  uint32_t from_syscall_multiplier;\n};\n\nsize_t ParamSize::eval(RecordTask* t, size_t already_consumed) const {\n  size_t s = incoming_size;\n  if (!mem_ptr.is_null()) {\n    size_t mem_size;\n    switch (read_size) {\n      case 4:\n        mem_size = t->read_mem(mem_ptr.cast<uint32_t>());\n        break;\n      case 8:\n        mem_size = t->read_mem(mem_ptr.cast<uint64_t>());\n        break;\n      default:\n        ASSERT(t, false) << \"Unknown read_size\";\n        return 0;\n    }\n    ASSERT(t, already_consumed <= mem_size);\n    s = min(s, mem_size - already_consumed);\n  }\n  if (from_syscall_multiplier) {\n    size_t syscall_size = max<ssize_t>(0, t->regs().syscall_result_signed())\n      * from_syscall_multiplier;\n    switch (read_size) {\n      case 4:\n        syscall_size = uint32_t(syscall_size);\n        break;\n      case 8:\n        syscall_size = uint64_t(syscall_size);\n        break;\n      default:\n        ASSERT(t, false) << \"Unknown read_size\";\n        return 0;\n    }\n    ASSERT(t, already_consumed <= syscall_size);\n    s = min(s, syscall_size - already_consumed);\n  }\n  ASSERT(t, s < size_t(-1));\n  return s;\n}\n\ntypedef bool (*ArgMutator)(RecordTask*, remote_ptr<void>, void*);\n\n/**\n * When tasks enter syscalls that may block and so must be\n * prepared for a context-switch, and the syscall params\n * include (in)outparams that point to buffers, we need to\n * redirect those arguments to scratch memory.  This allows rr\n * to serialize execution of what may be multiple blocked\n * syscalls completing \"simultaneously\" (from rr's\n * perspective).  After the syscall exits, we restore the data\n * saved in scratch memory to the original buffers.\n *\n * Then during replay, we simply restore the saved data to the\n * tracee's passed-in buffer args and continue on.\n *\n * This is implemented by having rec_prepare_syscall_arch set up\n * a record in param_list for syscall in-memory  parameter (whether\n * \"in\" or \"out\"). Then done_preparing is called, which does the actual\n * scratch setup. process_syscall_results is called when the syscall is\n * done, to write back scratch results to the real parameters and\n * clean everything up.\n *\n * ... a fly in this ointment is may-block buffered syscalls.\n * If a task blocks in one of those, it will look like it just\n * entered a syscall that needs a scratch buffer.  However,\n * it's too late at that point to fudge the syscall args,\n * because processing of the syscall has already begun in the\n * kernel.  But that's OK: the syscallbuf code has already\n * swapped out the original buffer-pointers for pointers into\n * the syscallbuf (which acts as its own scratch memory).  We\n * just have to worry about setting things up properly for\n * replay.\n *\n * The descheduled syscall will \"abort\" its commit into the\n * syscallbuf, so the outparam data won't actually be saved\n * there (and thus, won't be restored during replay).  During\n * replay, we have to restore them like we restore the\n * non-buffered-syscall scratch data. This is done by recording\n * the relevant syscallbuf record data in rec_process_syscall_arch.\n */\nstruct TaskSyscallState : TaskSyscallStateBase {\n  static TaskSyscallState& get(RecordTask* t) {\n    auto base = t->syscall_state.get();\n    ASSERT(t, base) << \"Expected syscall-state but didn't find one\";\n    return *static_cast<TaskSyscallState*>(base);\n  }\n  static TaskSyscallState* maybe_get(RecordTask* t) {\n    auto base = t->syscall_state.get();\n    return static_cast<TaskSyscallState*>(base);\n  }\n\n  void init(RecordTask* t) {\n    if (preparation_done) {\n      return;\n    }\n    this->t = t;\n    scratch = t->scratch_ptr;\n  }\n\n  /**\n   * Identify a syscall memory parameter whose address is in register 'arg'\n   * with type T.\n   * Returns a remote_ptr to the data in the child (before scratch relocation)\n   * or null if parameters have already been prepared (the syscall is\n   * resuming).\n   */\n  template <typename T>\n  remote_ptr<T> reg_parameter(int arg, ArgMode mode = OUT,\n                              ArgMutator mutator = nullptr) {\n    return reg_parameter(arg, sizeof(T), mode, mutator).cast<T>();\n  }\n  /**\n   * Identify a syscall memory parameter whose address is in register 'arg'\n   * with size 'size'.\n   * Returns a remote_ptr to the data in the child (before scratch relocation)\n   * or null if parameters have already been prepared (the syscall is\n   * resuming).\n   */\n  remote_ptr<void> reg_parameter(int arg, const ParamSize& size,\n                                 ArgMode mode = OUT,\n                                 ArgMutator mutator = nullptr);\n  /**\n   * Identify a syscall memory parameter whose address is in memory at\n   * location 'addr_of_buf_ptr' with type T.\n   * Returns a remote_ptr to the data in the child (before scratch relocation)\n   * or null if parameters have already been prepared (the syscall is\n   * resuming).\n   * addr_of_buf_ptr must be in a buffer identified by some init_..._parameter\n   * call.\n   */\n  template <typename T>\n  remote_ptr<T> mem_ptr_parameter(remote_ptr<void> addr_of_buf_ptr,\n                                  ArgMode mode = OUT,\n                                  ArgMutator mutator = nullptr) {\n    return mem_ptr_parameter(addr_of_buf_ptr, sizeof(T), mode, mutator)\n        .cast<T>();\n  }\n  /**\n   * Identify a syscall memory parameter whose address is in memory at\n   * location 'addr_of_buf_ptr' with type T.\n   * Returns a remote_ptr to the data in the child (before scratch relocation)\n   * or null if parameters have already been prepared (the syscall is\n   * resuming).\n   * addr_of_buf_ptr must be in a buffer identified by some init_..._parameter\n   * call.\n   */\n  template <typename Ptr>\n  remote_ptr<typename Ptr::Referent> mem_ptr_parameter_inferred(\n      remote_ptr<Ptr> addr_of_buf_ptr, ArgMode mode = OUT,\n      ArgMutator mutator = nullptr) {\n    remote_ptr<void> p =\n        mem_ptr_parameter(addr_of_buf_ptr, Ptr::referent_size(), mode, mutator);\n    return p.cast<typename Ptr::Referent>();\n  }\n  /**\n   * Identify a syscall memory parameter whose address is in memory at\n   * location 'addr_of_buf_ptr' with size 'size'.\n   * Returns a remote_ptr to the data in the child (before scratch relocation)\n   * or null if parameters have already been prepared (the syscall is\n   * resuming).\n   * addr_of_buf_ptr must be in a buffer identified by some init_..._parameter\n   * call.\n   */\n  remote_ptr<void> mem_ptr_parameter(remote_ptr<void> addr_of_buf_ptr,\n                                     const ParamSize& size, ArgMode mode = OUT,\n                                     ArgMutator mutator = nullptr);\n\n  typedef void (*AfterSyscallAction)(RecordTask* t);\n  // Register a callback to run when the syscall has completed.\n  // This runs after parameters have been restored.\n  void after_syscall_action(AfterSyscallAction action) {\n    after_syscall_actions.push_back(action);\n  }\n\n  void emulate_result(uint64_t result) {\n    ASSERT(t, !preparation_done);\n    ASSERT(t, !should_emulate_result);\n    should_emulate_result = true;\n    emulated_result = result;\n  }\n\n  /**\n   * Internal method that takes 'ptr', an address within some memory parameter,\n   * and relocates it to the parameter's location in scratch memory.\n   */\n  remote_ptr<void> relocate_pointer_to_scratch(remote_ptr<void> ptr);\n  /**\n   * Internal method that takes the index of a MemoryParam and a vector\n   * containing the actual sizes assigned to each param < param_index, and\n   * computes the actual size to use for parameter param_index.\n   */\n  size_t eval_param_size(size_t param_index, vector<size_t>& actual_sizes);\n  /**\n   * Called when all memory parameters have been identified. If 'sw' is\n   * ALLOW_SWITCH, sets up scratch memory and updates registers etc as\n   * necessary.\n   * If scratch can't be used for some reason, returns PREVENT_SWITCH,\n   * otherwise returns 'sw'.\n   */\n  Switchable done_preparing(Switchable sw);\n  Switchable done_preparing_internal(Switchable sw);\n  enum WriteBack { WRITE_BACK, NO_WRITE_BACK };\n  /**\n   * Called when a syscall exits to copy results from scratch memory to their\n   * original destinations, update registers, etc.\n   */\n  void process_syscall_results();\n  /**\n   * Called when a syscall has been completely aborted to undo any changes we\n   * made.\n   */\n  void abort_syscall_results();\n\n  /**\n   * Upon successful syscall completion, each RestoreAndRecordScratch record\n   * in param_list consumes num_bytes from the t->scratch_ptr\n   * buffer, copying the data to remote_dest and recording the data at\n   * remote_dest. If ptr_in_reg is greater than zero, updates the task's\n   * ptr_in_reg register with 'remote_dest'. If ptr_in_memory is non-null,\n   * updates the ptr_in_memory location with the value 'remote_dest'.\n   */\n  struct MemoryParam {\n    MemoryParam() : ptr_in_reg(0) {}\n\n    remote_ptr<void> dest;\n    remote_ptr<void> scratch;\n    ParamSize num_bytes;\n    remote_ptr<void> ptr_in_memory;\n    int ptr_in_reg;\n    ArgMode mode;\n    ArgMutator mutator;\n  };\n\n  RecordTask* t;\n\n  vector<MemoryParam> param_list;\n  /** Tracks the position in t's scratch_ptr buffer where we should allocate\n   *  the next scratch area.\n   */\n  remote_ptr<void> scratch;\n\n  vector<AfterSyscallAction> after_syscall_actions;\n\n  std::unique_ptr<TraceTaskEvent> exec_saved_event;\n\n  RecordTask* emulate_wait_for_child;\n\n  /** Saved syscall-entry registers, used by code paths that modify the\n   *  registers temporarily.\n   */\n  Registers syscall_entry_registers;\n\n  /** When nonzero, syscall is expected to return the given errno and we should\n   *  die if it does not. This is set when we detect an error condition during\n   *  syscall-enter preparation.\n   */\n  int expect_errno;\n\n  /** When should_emulate_result is true, syscall result should be adjusted to\n   *  be emulated_result. */\n  bool should_emulate_result;\n  uint64_t emulated_result;\n\n  /** Records whether the syscall is switchable. Only valid when\n   *  preparation_done is true. */\n  Switchable switchable;\n\n  /** Whether we should write back the syscall results from scratch. Only\n   *  valid when preparation_done is true. */\n  WriteBack write_back;\n\n  /** When true, this syscall has already been prepared and should not\n   *  be set up again.\n   */\n  bool preparation_done;\n  /** When true, the scratch area is enabled, otherwise we're letting\n   *  syscall outputs be written directly to their destinations.\n   *  Only valid when preparation_done is true.\n   */\n  bool scratch_enabled;\n\n  /** Miscellaneous saved data that can be used by particular syscalls */\n  vector<uint8_t> saved_data;\n\n  TaskSyscallState()\n      : t(nullptr),\n        emulate_wait_for_child(nullptr),\n        expect_errno(0),\n        should_emulate_result(false),\n        preparation_done(false),\n        scratch_enabled(false) {}\n};\n\ntemplate <typename Arch>\nstatic void set_remote_ptr_arch(RecordTask* t, remote_ptr<void> addr,\n                                remote_ptr<void> value) {\n  auto typed_addr = addr.cast<typename Arch::unsigned_word>();\n  t->write_mem(typed_addr, (typename Arch::unsigned_word)value.as_int());\n}\n\nstatic void set_remote_ptr(RecordTask* t, remote_ptr<void> addr,\n                           remote_ptr<void> value) {\n  RR_ARCH_FUNCTION(set_remote_ptr_arch, t->arch(), t, addr, value);\n}\n\ntemplate <typename Arch>\nstatic remote_ptr<void> get_remote_ptr_arch(RecordTask* t,\n                                            remote_ptr<void> addr) {\n  auto typed_addr = addr.cast<typename Arch::unsigned_word>();\n  auto old = t->read_mem(typed_addr);\n  return remote_ptr<void>(old);\n}\n\nstatic remote_ptr<void> get_remote_ptr(RecordTask* t, remote_ptr<void> addr) {\n  RR_ARCH_FUNCTION(get_remote_ptr_arch, t->arch(), t, addr);\n}\n\nstatic void align_scratch(remote_ptr<void>* scratch, uintptr_t amount = 8) {\n  *scratch = (scratch->as_int() + amount - 1) & ~(amount - 1);\n}\n\nremote_ptr<void> TaskSyscallState::reg_parameter(int arg, const ParamSize& size,\n                                                 ArgMode mode,\n                                                 ArgMutator mutator) {\n  if (preparation_done) {\n    return remote_ptr<void>();\n  }\n\n  MemoryParam param;\n  param.dest = syscall_entry_registers.arg(arg);\n  if (param.dest.is_null()) {\n    return remote_ptr<void>();\n  }\n  param.num_bytes = size;\n  param.mode = mode;\n  param.mutator = mutator;\n  ASSERT(t, !mutator || mode == IN);\n  if (mode != IN_OUT_NO_SCRATCH) {\n    param.scratch = scratch;\n    scratch += param.num_bytes.incoming_size;\n    align_scratch(&scratch);\n    param.ptr_in_reg = arg;\n  }\n  param_list.push_back(param);\n  return param.dest;\n}\n\nremote_ptr<void> TaskSyscallState::mem_ptr_parameter(\n    remote_ptr<void> addr_of_buf_ptr, const ParamSize& size, ArgMode mode,\n    ArgMutator mutator) {\n  if (preparation_done || addr_of_buf_ptr.is_null()) {\n    return remote_ptr<void>();\n  }\n\n  MemoryParam param;\n  param.dest = get_remote_ptr(t, addr_of_buf_ptr);\n  if (param.dest.is_null()) {\n    return remote_ptr<void>();\n  }\n  param.num_bytes = size;\n  param.mode = mode;\n  param.mutator = mutator;\n  ASSERT(t, !mutator || mode == IN);\n  if (mode != IN_OUT_NO_SCRATCH) {\n    param.scratch = scratch;\n    scratch += param.num_bytes.incoming_size;\n    align_scratch(&scratch);\n    param.ptr_in_memory = addr_of_buf_ptr;\n  }\n  param_list.push_back(param);\n  return param.dest;\n}\n\nremote_ptr<void> TaskSyscallState::relocate_pointer_to_scratch(\n    remote_ptr<void> ptr) {\n  int num_relocations = 0;\n  remote_ptr<void> result;\n  for (auto& param : param_list) {\n    if (param.dest <= ptr && ptr < param.dest + param.num_bytes.incoming_size) {\n      result = param.scratch + (ptr - param.dest);\n      ++num_relocations;\n    }\n  }\n  DEBUG_ASSERT(\n      num_relocations > 0 &&\n      \"Pointer in non-scratch memory being updated to point to scratch?\");\n  DEBUG_ASSERT(num_relocations <= 1 &&\n               \"Overlapping buffers containing relocated pointer?\");\n  return result;\n}\n\nSwitchable TaskSyscallState::done_preparing_internal(Switchable sw) {\n  ASSERT(t, !preparation_done);\n\n  preparation_done = true;\n  write_back = WRITE_BACK;\n  switchable = sw;\n\n  if (!t->scratch_ptr) {\n    return switchable;\n  }\n\n  ASSERT(t, scratch >= t->scratch_ptr);\n\n  if (sw == ALLOW_SWITCH &&\n      scratch > t->scratch_ptr + t->usable_scratch_size()) {\n    LOG(warn)\n        << \"`\" << t->ev().Syscall().syscall_name()\n        << \"' needed a scratch buffer of size \" << scratch - t->scratch_ptr\n        << \", but only \" << t->usable_scratch_size()\n        << \" was available.  Allowing the syscall to proceed without scratch, which may race.\";\n    return switchable;\n  }\n  if (switchable == PREVENT_SWITCH || param_list.empty()) {\n    return switchable;\n  }\n\n  scratch_enabled = true;\n\n  // Step 1: Copy all IN/IN_OUT parameters to their scratch areas\n  for (auto& param : param_list) {\n    ASSERT(t, param.num_bytes.incoming_size < size_t(-1));\n    if (param.mode == IN_OUT || param.mode == IN) {\n      // Initialize scratch buffer with input data\n      std::unique_ptr<uint8_t[]> buf(\n          new uint8_t[param.num_bytes.incoming_size]);\n      t->read_bytes_helper(param.dest, param.num_bytes.incoming_size,\n                           buf.get());\n      t->write_bytes_helper(param.scratch, param.num_bytes.incoming_size,\n                            buf.get());\n    }\n  }\n  // Step 2: Update pointers in registers/memory to point to scratch areas\n  {\n    Registers r = t->regs();\n    for (auto& param : param_list) {\n      if (param.ptr_in_reg) {\n        r.set_arg(param.ptr_in_reg, param.scratch.as_int());\n      }\n      if (!param.ptr_in_memory.is_null()) {\n        // Pointers being relocated must themselves be in scratch memory.\n        // We don't want to modify non-scratch memory. Find the pointer's\n        // location\n        // in scratch memory.\n        auto p = relocate_pointer_to_scratch(param.ptr_in_memory);\n        // Update pointer to point to scratch.\n        // Note that this can only happen after step 1 is complete and all\n        // parameter data has been copied to scratch memory.\n        set_remote_ptr(t, p, param.scratch);\n      }\n      // If the number of bytes to record is coming from a memory location,\n      // update that location to scratch.\n      if (!param.num_bytes.mem_ptr.is_null()) {\n        param.num_bytes.mem_ptr =\n            relocate_pointer_to_scratch(param.num_bytes.mem_ptr);\n      }\n    }\n    t->set_regs(r);\n  }\n  return switchable;\n}\n\nSwitchable TaskSyscallState::done_preparing(Switchable sw) {\n  if (preparation_done) {\n    return switchable;\n  }\n\n  sw = done_preparing_internal(sw);\n  ASSERT(t, sw == switchable);\n\n  // Step 3: Execute mutators. This must run even if the scratch steps do not.\n  for (auto& param : param_list) {\n    if (param.mutator) {\n      // Mutated parameters must be IN. If we have scratch space, we don't need\n      // to save anything.\n      void* saved_data_loc = nullptr;\n      if (!scratch_enabled) {\n        auto prev_size = saved_data.size();\n        saved_data.resize(prev_size + param.num_bytes.incoming_size);\n        saved_data_loc = saved_data.data() + prev_size;\n      }\n      if (!(*param.mutator)(t, scratch_enabled ? param.scratch : param.dest,\n                            saved_data_loc)) {\n        // Nothing was modified, no need to clean up when we unwind.\n        param.mutator = nullptr;\n        if (!scratch_enabled) {\n          saved_data.resize(saved_data.size() - param.num_bytes.incoming_size);\n        }\n      }\n    }\n  }\n  return switchable;\n}\n\nsize_t TaskSyscallState::eval_param_size(size_t i,\n                                         vector<size_t>& actual_sizes) {\n  DEBUG_ASSERT(actual_sizes.size() == i);\n\n  size_t already_consumed = 0;\n  for (size_t j = 0; j < i; ++j) {\n    if (param_list[j].num_bytes.is_same_source(param_list[i].num_bytes)) {\n      already_consumed += actual_sizes[j];\n    }\n  }\n  size_t size = param_list[i].num_bytes.eval(t, already_consumed);\n  actual_sizes.push_back(size);\n  return size;\n}\n\nvoid TaskSyscallState::process_syscall_results() {\n  ASSERT(t, preparation_done);\n\n  // XXX what's the best way to handle failed syscalls? Currently we just\n  // record everything as if it succeeded. That handles failed syscalls that\n  // wrote partial results, but doesn't handle syscalls that failed with\n  // EFAULT.\n  vector<size_t> actual_sizes;\n  if (scratch_enabled) {\n    size_t scratch_num_bytes = scratch - t->scratch_ptr;\n    auto data = t->read_mem(t->scratch_ptr.cast<uint8_t>(), scratch_num_bytes);\n    Registers r = t->regs();\n    // Step 1: compute actual sizes of all buffers and copy outputs\n    // from scratch back to their origin\n    for (size_t i = 0; i < param_list.size(); ++i) {\n      auto& param = param_list[i];\n      size_t size = eval_param_size(i, actual_sizes);\n      if (write_back == WRITE_BACK &&\n          (param.mode == IN_OUT || param.mode == OUT)) {\n        const uint8_t* d = data.data() + (param.scratch - t->scratch_ptr);\n        t->write_bytes_helper(param.dest, size, d);\n      }\n    }\n    bool memory_cleaned_up = false;\n    // Step 2: restore modified in-memory pointers and registers\n    for (size_t i = 0; i < param_list.size(); ++i) {\n      auto& param = param_list[i];\n      if (param.ptr_in_reg) {\n        r.set_orig_arg(param.ptr_in_reg, param.dest.as_int());\n      }\n      if (!param.ptr_in_memory.is_null()) {\n        memory_cleaned_up = true;\n        set_remote_ptr(t, param.ptr_in_memory, param.dest);\n      }\n    }\n    if (write_back == WRITE_BACK) {\n      // Step 3: record all output memory areas\n      for (size_t i = 0; i < param_list.size(); ++i) {\n        auto& param = param_list[i];\n        size_t size = actual_sizes[i];\n        if (param.mode == IN_OUT_NO_SCRATCH) {\n          t->record_remote(param.dest, size);\n        } else if (param.mode == IN_OUT || param.mode == OUT) {\n          // If pointers in memory were fixed up in step 2, then record\n          // from tracee memory to ensure we record such fixes. Otherwise we\n          // can record from our local data.\n          // XXX This optimization can be improved if necessary...\n          if (memory_cleaned_up) {\n            t->record_remote(param.dest, size);\n          } else {\n            const uint8_t* d = data.data() + (param.scratch - t->scratch_ptr);\n            t->record_local(param.dest, size, d);\n          }\n        }\n      }\n    }\n    t->set_regs(r);\n  } else {\n    // Step 1: Determine the size of all output memory areas\n    for (size_t i = 0; i < param_list.size(); ++i) {\n      eval_param_size(i, actual_sizes);\n    }\n    // Step 2: restore all mutated memory\n    for (auto& param : param_list) {\n      if (param.mutator) {\n        size_t size = param.num_bytes.incoming_size;\n        ASSERT(t, saved_data.size() >= size);\n        // If this intersects an output region, we need to be careful not to\n        // clobber what the kernel gave us.\n        for (size_t i = 0; i < param_list.size(); ++i) {\n          auto& param2 = param_list[i];\n          size_t param2_size = actual_sizes[i];\n          if (param2.mode == IN) {\n            continue;\n          }\n          MemoryRange intersection = MemoryRange(param2.dest, param2_size).\n            intersect(MemoryRange(param.dest, size));\n          if (intersection.size() != 0) {\n            // Just update the saved data we already have. We could try\n            // splitting the range and only writing what needs to still change,\n            // but we'd probably just end up doing the exact same number of\n            // syscalls and this is simpler.\n            t->read_bytes_helper(intersection.start(), intersection.size(),\n              saved_data.data() + (intersection.start() - param.dest));\n          }\n        }\n        t->write_bytes_helper(param.dest, size, saved_data.data());\n        saved_data.erase(saved_data.begin(), saved_data.begin() + size);\n      }\n    }\n    ASSERT(t, saved_data.empty());\n    // Step 3: record all output memory areas\n    for (size_t i = 0; i < param_list.size(); ++i) {\n      auto& param = param_list[i];\n      size_t size = actual_sizes[i];\n      if (param.mode != IN) {\n        t->record_remote(param.dest, size);\n      }\n    }\n  }\n\n  if (should_emulate_result) {\n    Registers r = t->regs();\n    r.set_syscall_result(emulated_result);\n    t->set_regs(r);\n  }\n\n  for (auto& action : after_syscall_actions) {\n    action(t);\n  }\n}\n\nvoid TaskSyscallState::abort_syscall_results() {\n  ASSERT(t, preparation_done);\n\n  if (scratch_enabled) {\n    Registers r = t->regs();\n    // restore modified in-memory pointers and registers\n    for (size_t i = 0; i < param_list.size(); ++i) {\n      auto& param = param_list[i];\n      if (param.ptr_in_reg) {\n        r.set_arg(param.ptr_in_reg, param.dest.as_int());\n      }\n      if (!param.ptr_in_memory.is_null()) {\n        set_remote_ptr(t, param.ptr_in_memory, param.dest);\n      }\n    }\n    t->set_regs(r);\n  } else {\n    for (auto& param : param_list) {\n      if (param.mutator) {\n        size_t size = param.num_bytes.incoming_size;\n        ASSERT(t, saved_data.size() >= size);\n        t->write_bytes_helper(param.dest, size, saved_data.data());\n        saved_data.erase(saved_data.begin(), saved_data.begin() + size);\n      }\n    }\n  }\n}\n\ntemplate <typename Arch>\nstatic void prepare_recvmsg(RecordTask* t, TaskSyscallState& syscall_state,\n                            remote_ptr<typename Arch::msghdr> msgp,\n                            const ParamSize& io_size) {\n  auto namelen_ptr = REMOTE_PTR_FIELD(msgp, msg_namelen);\n  syscall_state.mem_ptr_parameter(\n      REMOTE_PTR_FIELD(msgp, msg_name),\n      ParamSize::from_initialized_mem(t, namelen_ptr));\n\n  auto msg = t->read_mem(msgp);\n  remote_ptr<void> iovecsp_void = syscall_state.mem_ptr_parameter(\n      REMOTE_PTR_FIELD(msgp, msg_iov),\n      sizeof(typename Arch::iovec) * msg.msg_iovlen, IN);\n  auto iovecsp = iovecsp_void.cast<typename Arch::iovec>();\n  auto iovecs = t->read_mem(iovecsp, msg.msg_iovlen);\n  for (size_t i = 0; i < msg.msg_iovlen; ++i) {\n    syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(iovecsp + i, iov_base),\n                                    io_size.limit_size(iovecs[i].iov_len));\n  }\n\n  auto controllen_ptr = REMOTE_PTR_FIELD(msgp, msg_controllen);\n  syscall_state.mem_ptr_parameter(\n      REMOTE_PTR_FIELD(msgp, msg_control),\n      ParamSize::from_initialized_mem(t, controllen_ptr));\n}\n\ntemplate <typename Arch>\nstatic void prepare_recvmmsg(RecordTask* t, TaskSyscallState& syscall_state,\n                             remote_ptr<typename Arch::mmsghdr> mmsgp,\n                             unsigned int vlen) {\n  for (unsigned int i = 0; i < vlen; ++i) {\n    auto msgp = mmsgp + i;\n    prepare_recvmsg<Arch>(t, syscall_state, REMOTE_PTR_FIELD(msgp, msg_hdr),\n                          ParamSize::from_mem(REMOTE_PTR_FIELD(msgp, msg_len)));\n  }\n}\n\nstatic bool block_sock_opt(int level, int optname,\n                           TaskSyscallState& syscall_state) {\n  switch (level) {\n    case SOL_PACKET:\n      switch (optname) {\n        case PACKET_RX_RING:\n        case PACKET_TX_RING:\n          syscall_state.emulate_result(-ENOPROTOOPT);\n          return true;\n      }\n      break;\n    case SOL_NETLINK:\n      switch (optname) {\n        case NETLINK_RX_RING:\n        case NETLINK_TX_RING:\n          syscall_state.emulate_result(-ENOPROTOOPT);\n          return true;\n      }\n      break;\n  }\n  return false;\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_setsockopt(RecordTask* t,\n                                     TaskSyscallState& syscall_state,\n                                     typename Arch::setsockopt_args& args) {\n  if (block_sock_opt(args.level, args.optname, syscall_state)) {\n    Registers r = t->regs();\n    r.set_arg1(-1);\n    t->set_regs(r);\n  } else {\n    if (args.level == SOL_IP && args.optname == IPT_SO_SET_REPLACE) {\n      if (args.optlen < (ssize_t)sizeof(typename Arch::ipt_replace)) {\n        return PREVENT_SWITCH;\n      }\n      auto repl_ptr =\n          args.optval.rptr().template cast<typename Arch::ipt_replace>();\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(repl_ptr, counters),\n          t->read_mem(REMOTE_PTR_FIELD(repl_ptr, num_counters)) *\n              sizeof(typename Arch::xt_counters));\n    } else if (args.level == SOL_IPV6 && args.optname == IPV6T_SO_SET_REPLACE) {\n      if (args.optlen < (ssize_t)sizeof(typename Arch::ip6t_replace)) {\n        return PREVENT_SWITCH;\n      }\n      auto repl_ptr =\n          args.optval.rptr().template cast<typename Arch::ip6t_replace>();\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(repl_ptr, counters),\n          t->read_mem(REMOTE_PTR_FIELD(repl_ptr, num_counters)) *\n              sizeof(typename Arch::xt_counters));\n    }\n  }\n  return PREVENT_SWITCH;\n}\n\ntemplate <typename Arch>\nstatic Switchable maybe_blacklist_connect(RecordTask* t,\n                                          remote_ptr<void> addr_ptr,\n                                          socklen_t addrlen) {\n  struct sockaddr_un addr;\n  memset(&addr, 0, sizeof(addr));\n  t->read_bytes_fallible(addr_ptr, min<socklen_t>(sizeof(addr), addrlen),\n                         &addr);\n  // Ensure null termination;\n  addr.sun_path[sizeof(addr.sun_path) - 1] = 0;\n  if (addr.sun_family == AF_UNIX && is_blacklisted_socket(addr.sun_path)) {\n    LOG(warn) << \"Cowardly refusing to connect to \" << addr.sun_path;\n    // Hijack the syscall.\n    Registers r = t->regs();\n    r.set_original_syscallno(Arch::gettid);\n    t->set_regs(r);\n  }\n  return PREVENT_SWITCH;\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_socketcall(RecordTask* t,\n                                     TaskSyscallState& syscall_state) {\n  /* int socketcall(int call, unsigned long *args) {\n   *   long a[6];\n   *   copy_from_user(a,args);\n   *   sys_recv(a0, (void __user *)a1, a[2], a[3]);\n   * }\n   *\n   *  (from http://lxr.linux.no/#linux+v3.6.3/net/socket.c#L2354)\n   */\n  switch ((int)t->regs().arg1_signed()) {\n    /* int socket(int domain, int type, int protocol); */\n    case SYS_SOCKET:\n    /* int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); */\n    case SYS_BIND:\n    /* int listen(int sockfd, int backlog) */\n    case SYS_LISTEN:\n    /* int shutdown(int socket, int how) */\n    case SYS_SHUTDOWN:\n      break;\n\n    /* int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);\n     */\n    case SYS_CONNECT: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::connect_args>(2, IN);\n      auto args = t->read_mem(argsp);\n      return maybe_blacklist_connect<Arch>(t, args.addr.rptr(), args.addrlen);\n    }\n\n    /* ssize_t send(int sockfd, const void *buf, size_t len, int flags) */\n    case SYS_SEND:\n    /* ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const\n     * struct sockaddr *dest_addr, socklen_t addrlen); */\n    case SYS_SENDTO:\n      // These can block when socket buffers are full.\n      return ALLOW_SWITCH;\n\n    /* int setsockopt(int sockfd, int level, int optname, const void *optval,\n     * socklen_t optlen); */\n    case SYS_SETSOCKOPT: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::setsockopt_args>(2, IN);\n      auto args = t->read_mem(argsp);\n      return prepare_setsockopt<Arch>(t, syscall_state, args);\n    }\n\n    /*  int getsockopt(int sockfd, int level, int optname, const void *optval,\n     * socklen_t* optlen);\n     */\n    case SYS_GETSOCKOPT: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::getsockopt_args>(2, IN);\n      auto optlen_ptr = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, optlen), IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, optval),\n          ParamSize::from_initialized_mem(t, optlen_ptr));\n      break;\n    }\n\n    /* int socketpair(int domain, int type, int protocol, int sv[2]);\n     *\n     * values returned in sv\n     */\n    case SYS_SOCKETPAIR: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::socketpair_args>(2, IN);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, sv),\n                                      sizeof(int) * 2);\n      break;\n    }\n\n    /* int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);\n     */\n    case SYS_GETPEERNAME:\n    /* int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);\n     */\n    case SYS_GETSOCKNAME: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::getsockname_args>(2, IN);\n      auto addrlen_ptr = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, addrlen), IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, addr),\n          ParamSize::from_initialized_mem(t, addrlen_ptr));\n      break;\n    }\n\n    /* ssize_t recv([int sockfd, void *buf, size_t len, int flags]) */\n    case SYS_RECV: {\n      auto argsp = syscall_state.reg_parameter<typename Arch::recv_args>(2, IN);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, buf),\n          ParamSize::from_syscall_result<typename Arch::ssize_t>(args.len));\n      return ALLOW_SWITCH;\n    }\n\n    /* int accept([int sockfd, struct sockaddr *addr, socklen_t *addrlen]) */\n    case SYS_ACCEPT: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::accept_args>(2, IN);\n      auto addrlen_ptr = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, addrlen), IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, addr),\n          ParamSize::from_initialized_mem(t, addrlen_ptr));\n      return ALLOW_SWITCH;\n    }\n\n    /* int accept4([int sockfd, struct sockaddr *addr, socklen_t *addrlen, int\n     * flags]) */\n    case SYS_ACCEPT4: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::accept4_args>(2, IN);\n      auto addrlen_ptr = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, addrlen), IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, addr),\n          ParamSize::from_initialized_mem(t, addrlen_ptr));\n      return ALLOW_SWITCH;\n    }\n\n    case SYS_RECVFROM: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::recvfrom_args>(2, IN);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, buf),\n          ParamSize::from_syscall_result<typename Arch::ssize_t>(args.len));\n      auto addrlen_ptr = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, addrlen), IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, src_addr),\n          ParamSize::from_initialized_mem(t, addrlen_ptr));\n      return ALLOW_SWITCH;\n    }\n\n    case SYS_RECVMSG: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::recvmsg_args>(2, IN);\n      auto msgp = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, msg), IN_OUT);\n      prepare_recvmsg<Arch>(\n          t, syscall_state, msgp,\n          ParamSize::from_syscall_result<typename Arch::ssize_t>());\n\n      auto args = t->read_mem(argsp);\n      if (!(args.flags & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      break;\n    }\n\n    case SYS_RECVMMSG: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::recvmmsg_args>(2, IN);\n      auto args = t->read_mem(argsp);\n      remote_ptr<void> mmsgp_void = syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, msgvec),\n          sizeof(typename Arch::mmsghdr) * args.vlen, IN_OUT);\n      auto mmsgp = mmsgp_void.cast<typename Arch::mmsghdr>();\n      prepare_recvmmsg<Arch>(t, syscall_state, mmsgp, args.vlen);\n      if (!(args.flags & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      break;\n    }\n\n    /* ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags) */\n    case SYS_SENDMSG: {\n      auto argsp = remote_ptr<typename Arch::sendmsg_args>(t->regs().arg2());\n      auto args = t->read_mem(argsp);\n      if (!(args.flags & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      break;\n    }\n\n    case SYS_SENDMMSG: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::sendmmsg_args>(2, IN);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, msgvec),\n          sizeof(typename Arch::mmsghdr) * args.vlen, IN_OUT);\n      if (!(args.flags & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      break;\n    }\n\n    default:\n      syscall_state.expect_errno = EINVAL;\n      break;\n  }\n  return PREVENT_SWITCH;\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_msgctl(TaskSyscallState& syscall_state, int cmd,\n                                 int ptr_reg) {\n  switch (cmd) {\n    case IPC_STAT:\n    case MSG_STAT:\n      syscall_state.reg_parameter<typename Arch::msqid64_ds>(ptr_reg);\n      break;\n    case IPC_INFO:\n    case MSG_INFO:\n      syscall_state.reg_parameter<typename Arch::msginfo>(ptr_reg);\n      break;\n\n    case IPC_SET:\n    case IPC_RMID:\n      break;\n\n    default:\n      syscall_state.expect_errno = EINVAL;\n      break;\n  }\n  return PREVENT_SWITCH;\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_shmctl(TaskSyscallState& syscall_state, int cmd,\n                                 int ptr_reg) {\n  switch (cmd) {\n    case IPC_SET:\n    case IPC_RMID:\n    case SHM_LOCK:\n    case SHM_UNLOCK:\n      break;\n\n    case IPC_STAT:\n    case SHM_STAT:\n      syscall_state.reg_parameter<typename Arch::shmid64_ds>(ptr_reg);\n      break;\n\n    case IPC_INFO:\n      syscall_state.reg_parameter<typename Arch::shminfo64>(ptr_reg);\n      break;\n\n    case SHM_INFO:\n      syscall_state.reg_parameter<typename Arch::shm_info>(ptr_reg);\n      break;\n\n    default:\n      syscall_state.expect_errno = EINVAL;\n      break;\n  }\n  return PREVENT_SWITCH;\n}\n\nenum SemctlDereference { DEREFERENCE, USE_DIRECTLY };\n\ntemplate <typename Arch>\nstatic Switchable prepare_semctl(RecordTask* t, TaskSyscallState& syscall_state,\n                                 int semid, int cmd, int ptr_reg,\n                                 SemctlDereference deref) {\n  switch (cmd) {\n    case IPC_SET:\n    case IPC_RMID:\n    case GETNCNT:\n    case GETPID:\n    case GETVAL:\n    case GETZCNT:\n    case SETALL:\n    case SETVAL:\n      break;\n\n    case IPC_STAT:\n    case SEM_STAT:\n      if (deref == DEREFERENCE) {\n        syscall_state.mem_ptr_parameter<typename Arch::semid64_ds>(\n            syscall_state.reg_parameter<typename Arch::unsigned_long>(ptr_reg));\n      } else {\n        syscall_state.reg_parameter<typename Arch::semid64_ds>(ptr_reg);\n      }\n      break;\n\n    case IPC_INFO:\n    case SEM_INFO:\n      if (deref == DEREFERENCE) {\n        syscall_state.mem_ptr_parameter<typename Arch::seminfo>(\n            syscall_state.reg_parameter<typename Arch::unsigned_long>(ptr_reg));\n      } else {\n        syscall_state.reg_parameter<typename Arch::seminfo>(ptr_reg);\n      }\n      break;\n\n    case GETALL: {\n      semid64_ds ds;\n      _semun un_arg;\n      un_arg.buf = &ds;\n      int ret = _semctl(semid, 0, IPC_STAT, un_arg);\n      msan_unpoison(&ds, sizeof(semid64_ds));\n      ASSERT(t, ret == 0);\n\n      ParamSize size = sizeof(unsigned short) * ds.sem_nsems;\n      if (deref == DEREFERENCE) {\n        syscall_state.mem_ptr_parameter(\n            syscall_state.reg_parameter<typename Arch::unsigned_long>(ptr_reg),\n            size);\n      } else {\n        syscall_state.reg_parameter(ptr_reg, size);\n      }\n      break;\n    }\n\n    default:\n      syscall_state.expect_errno = EINVAL;\n      break;\n  }\n  return PREVENT_SWITCH;\n}\n\n/**\n * A change has been made to file 'fd' in task t. If the file has been mmapped\n * somewhere in t's address space, record the changes.\n * We check for matching files by comparing file names. This may not be\n * reliable but hopefully it's good enough for the cases where we need this.\n * This doesn't currently handle shared mappings very well. A file mapped\n * shared in multiple locations will be recorded once per location.\n * This doesn't handle mappings of the file into other address spaces.\n */\nstatic void record_v4l2_buffer_change(RecordTask* t, int fd, uint64_t cookie) {\n  string file_name = t->file_name_of_fd(fd);\n\n  for (const auto& m : t->vm()->maps()) {\n    if (m.map.fsname() == file_name &&\n        m.map.file_offset_bytes() == cookie) {\n      t->record_remote(m.map.start(), m.map.size());\n    }\n  };\n}\n\ntemplate <typename Arch>\nstatic void record_v4l2_buffer_contents(RecordTask* t) {\n  remote_ptr<typename Arch::v4l2_buffer> bufp = t->regs().arg3();\n  auto buf = t->read_mem(bufp);\n\n  switch (buf.memory) {\n    case V4L2_MEMORY_MMAP:\n      record_v4l2_buffer_change(t, (int)t->regs().arg1_signed(), buf.m.offset);\n      return;\n\n    default:\n      ASSERT(t, false) << \"Unhandled V4L2 memory type \" << buf.memory;\n      return;\n  }\n}\n\ntemplate <typename Arch> static void record_usbdevfs_reaped_urb(RecordTask* t) {\n  if (t->regs().syscall_failed()) {\n    return;\n  }\n\n  remote_ptr<typename Arch::unsigned_word> pp = t->regs().arg3();\n  remote_ptr<typename Arch::usbdevfs_urb> p = t->read_mem(pp);\n  t->record_remote(p);\n  auto urb = t->read_mem(p);\n  size_t length;\n  if (urb.type == USBDEVFS_URB_TYPE_ISO) {\n    auto iso_frame_descs_ptr = REMOTE_PTR_FIELD(p, iso_frame_desc[0]);\n    auto iso_frame_descs =\n        t->read_mem(iso_frame_descs_ptr, urb.number_of_packets);\n    length = 0;\n    for (auto& f : iso_frame_descs) {\n      length += f.length;\n    }\n    t->record_local(iso_frame_descs_ptr, iso_frame_descs.data(),\n                    iso_frame_descs.size());\n  } else {\n    length = urb.buffer_length;\n  }\n  // It's tempting to use actual_length here but in some cases the kernel\n  // writes back more data than that.\n  t->record_remote(urb.buffer, length);\n}\n\nstatic void record_page_below_stack_ptr(RecordTask* t) {\n  /* Record.the page above the top of |t|'s stack.  The SIOC* ioctls\n   * have been observed to write beyond the end of tracees' stacks, as\n   * if they had allocated scratch space for themselves.  All we can do\n   * for now is try to record the scratch data.\n   */\n  t->record_remote(t->regs().sp() - page_size(), page_size());\n}\n\n#define IOCTL_MASK_SIZE(v) ((v) & ~(_IOC_SIZEMASK << _IOC_SIZESHIFT))\n\ntypedef ethtool_gstrings GStrings;\n\ntemplate <typename Arch> void get_ethtool_gstrings_arch(RecordTask* t) {\n  auto& syscall_state = TaskSyscallState::get(t);\n  Registers& regs = syscall_state.syscall_entry_registers;\n  bool ok = true;\n  auto ifreq = t->read_mem(remote_ptr<typename Arch::ifreq>(regs.arg3()), &ok);\n  Registers new_regs = t->regs();\n  if (!ok) {\n    new_regs.set_syscall_result(-EFAULT);\n    t->set_regs(new_regs);\n    return;\n  }\n  remote_ptr<void> p = ifreq.ifr_ifru.ifru_data.rptr();\n  auto orig_gstrings = p.cast<ethtool_gstrings>();\n  auto et_gstrings = t->read_mem(orig_gstrings, &ok);\n  if (!ok) {\n    new_regs.set_syscall_result(-EFAULT);\n    t->set_regs(new_regs);\n    return;\n  }\n  if (et_gstrings.string_set >= 64) {\n    new_regs.set_syscall_result(-EOPNOTSUPP);\n    t->set_regs(new_regs);\n    return;\n  }\n\n  AutoRemoteSyscalls remote(t);\n\n  // Do a ETHTOOL_GSSET_INFO to get the number of strings\n  ethtool_sset_info et;\n  et.cmd = ETHTOOL_GSSET_INFO;\n  et.reserved = 0;\n  et.sset_mask = 1 << et_gstrings.string_set;\n  std::vector<uint8_t> buffer;\n  buffer.resize(sizeof(et) + sizeof(uint32_t));\n  memcpy(buffer.data(), &et, sizeof(et));\n  memset(buffer.data() + sizeof(et), 0, sizeof(uint32_t));\n  AutoRestoreMem et_mem(remote, buffer.data(), buffer.size());\n\n  ifreq.ifr_ifru.ifru_data = et_mem.get();\n  AutoRestoreMem ifr_mem(remote, &ifreq, sizeof(ifreq));\n\n  long ret = remote.syscall(regs.original_syscallno(), regs.arg1(),\n      SIOCETHTOOL, ifr_mem.get());\n  if (ret < 0) {\n    remote.regs().set_syscall_result(ret);\n    return;\n  }\n\n  uint32_t data = t->read_mem((et_mem.get() + sizeof(et)).cast<uint32_t>());\n  // Now do the ETHTOOL_GSTRINGS call\n  ret = remote.syscall(regs.original_syscallno(), regs.arg1(), SIOCETHTOOL,\n      regs.arg3());\n  remote.regs().set_syscall_result(ret);\n  if (ret < 0) {\n    return;\n  }\n  t->record_remote(orig_gstrings, sizeof(ethtool_gstrings) + ETH_GSTRING_LEN*data);\n}\n\nstatic void get_ethtool_gstrings(RecordTask* t) {\n  RR_ARCH_FUNCTION(get_ethtool_gstrings_arch, t->arch(), t);\n}\n\ntemplate <typename Arch> void prepare_ethtool_ioctl(RecordTask* t, TaskSyscallState& syscall_state) {\n  auto ifrp = syscall_state.reg_parameter<typename Arch::ifreq>(3, IN_OUT);\n  bool ok = true;\n  auto ifreq = t->read_mem(ifrp, &ok);\n  if (!ok) {\n    syscall_state.expect_errno = EFAULT;\n    return;\n  }\n  remote_ptr<void> payload = REMOTE_PTR_FIELD(ifrp, ifr_ifru.ifru_data);\n  remote_ptr<void> buf_ptr = ifreq.ifr_ifru.ifru_data.rptr();\n  uint32_t cmd = t->read_mem(buf_ptr.cast<uint32_t>(), &ok);\n  if (!ok) {\n    syscall_state.expect_errno = EFAULT;\n    return;\n  }\n\n  switch (cmd) {\n    case ETHTOOL_GSET:\n      syscall_state.mem_ptr_parameter<ethtool_cmd>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GDRVINFO:\n      syscall_state.mem_ptr_parameter<ethtool_drvinfo>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GWOL:\n      syscall_state.mem_ptr_parameter<ethtool_wolinfo>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GLINK:\n      syscall_state.mem_ptr_parameter<ethtool_value>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GRXRINGS:\n      syscall_state.mem_ptr_parameter<typename Arch::ethtool_rxnfc>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GREGS: {\n      auto buf = t->read_mem(buf_ptr.cast<ethtool_regs>(), &ok);\n      if (ok) {\n        syscall_state.mem_ptr_parameter(payload, ParamSize(sizeof(buf) + buf.len), IN_OUT);\n      } else {\n        syscall_state.expect_errno = EFAULT;\n        return;\n      }\n      break;\n    }\n    case ETHTOOL_GMODULEEEPROM:\n    case ETHTOOL_GEEPROM: {\n      auto buf = t->read_mem(buf_ptr.cast<ethtool_eeprom>(), &ok);\n      if (ok) {\n        syscall_state.mem_ptr_parameter(payload, ParamSize(sizeof(buf) + buf.len), IN_OUT);\n      } else {\n        syscall_state.expect_errno = EFAULT;\n        return;\n      }\n      break;\n    }\n    case ETHTOOL_GEEE:\n      syscall_state.mem_ptr_parameter<ethtool_eee>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GMODULEINFO:\n      syscall_state.mem_ptr_parameter<ethtool_modinfo>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GCOALESCE:\n      syscall_state.mem_ptr_parameter<ethtool_coalesce>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GRINGPARAM:\n      syscall_state.mem_ptr_parameter<ethtool_ringparam>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GCHANNELS:\n      syscall_state.mem_ptr_parameter<ethtool_channels>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GPAUSEPARAM:\n      syscall_state.mem_ptr_parameter<ethtool_pauseparam>(payload, IN_OUT);\n      break;\n    case ETHTOOL_GSSET_INFO: {\n      auto buf = t->read_mem(buf_ptr.cast<ethtool_sset_info>(), &ok);\n      if (ok) {\n        int bits = pop_count(buf.sset_mask);\n        syscall_state.mem_ptr_parameter(payload, ParamSize(sizeof(buf) + bits*sizeof(uint32_t)), IN_OUT);\n      } else {\n        syscall_state.expect_errno = EFAULT;\n        return;\n      }\n      break;\n    }\n    case ETHTOOL_GSTRINGS: {\n      // These are an enormous pain because to know how much data will be written\n      // back by the kernel, we have to perform a ETHTOOL_GSSET_INFO first.\n      // We can't do that right here because we've already entered the kernel.\n      // So, we emulate this.\n      Registers r = t->regs();\n      r.set_arg1(-1);\n      t->set_regs(r);\n      syscall_state.after_syscall_action(get_ethtool_gstrings);\n      break;\n    }\n    case ETHTOOL_GFEATURES: {\n      auto buf = t->read_mem(buf_ptr.cast<ethtool_gfeatures>(), &ok);\n      if (ok) {\n        syscall_state.mem_ptr_parameter(payload, ParamSize(sizeof(buf) + buf.size*sizeof(ethtool_get_features_block)), IN_OUT);\n      } else {\n        syscall_state.expect_errno = EFAULT;\n        return;\n      }\n      break;\n    }\n    case ETHTOOL_GPERMADDR: {\n      auto buf = t->read_mem(buf_ptr.cast<ethtool_perm_addr>(), &ok);\n      if (ok) {\n        syscall_state.mem_ptr_parameter(payload, ParamSize(sizeof(buf) + buf.size), IN_OUT);\n      } else {\n        syscall_state.expect_errno = EFAULT;\n        return;\n      }\n      break;\n    }\n    case ETHTOOL_SSET:\n    case ETHTOOL_SWOL:\n    case ETHTOOL_SEEPROM:\n    case ETHTOOL_SEEE:\n    case ETHTOOL_SCOALESCE:\n    case ETHTOOL_SRINGPARAM:\n    case ETHTOOL_SCHANNELS:\n    case ETHTOOL_SPAUSEPARAM:\n    case ETHTOOL_SFEATURES:\n      break;\n    default:\n      LOG(debug) << \"Unknown ETHTOOL cmd \" << cmd;\n      syscall_state.expect_errno = EINVAL;\n      return;\n  }\n  syscall_state.after_syscall_action(record_page_below_stack_ptr);\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_ioctl(RecordTask* t,\n                                TaskSyscallState& syscall_state) {\n  int fd = t->regs().arg1();\n  uint64_t result;\n  if (t->fd_table()->emulate_ioctl(fd, t, &result)) {\n    // Don't perform this syscall.\n    Registers r = t->regs();\n    r.set_arg1(-1);\n    t->set_regs(r);\n    syscall_state.emulate_result(result);\n    return PREVENT_SWITCH;\n  }\n\n  unsigned int request = t->regs().arg2();\n  int type = _IOC_TYPE(request);\n  int nr = _IOC_NR(request);\n  int dir = _IOC_DIR(request);\n  int size = _IOC_SIZE(request);\n\n  LOG(debug) << \"handling ioctl(\" << HEX(request) << \"): type:\" << HEX(type)\n             << \" nr:\" << HEX(nr) << \" dir:\" << HEX(dir) << \" size:\" << size;\n\n  ASSERT(t, !t->is_desched_event_syscall())\n      << \"Failed to skip past desched ioctl()\";\n\n  /* Some ioctl()s are irregular and don't follow the _IOC()\n   * conventions.  Special case them here. */\n  switch (request) {\n    case 0xc020462a: // Nvidia driver ioctl\n    case 0xc0181b01: // RDMA ioctl\n      syscall_state.emulate_result(-ENOTTY);\n      return PREVENT_SWITCH;\n\n    case SIOCETHTOOL:\n      prepare_ethtool_ioctl<Arch>(t, syscall_state);\n      return PREVENT_SWITCH;\n\n    case SIOCGIFCONF: {\n      auto ifconfp =\n          syscall_state.reg_parameter<typename Arch::ifconf>(3, IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(ifconfp, ifc_ifcu.ifcu_buf),\n          ParamSize::from_initialized_mem(t,\n                                          REMOTE_PTR_FIELD(ifconfp, ifc_len)));\n      syscall_state.after_syscall_action(record_page_below_stack_ptr);\n      return PREVENT_SWITCH;\n    }\n\n    /* Privileged ioctls */\n    case SIOCSIFADDR:\n    case SIOCSIFDSTADDR:\n    case SIOCSIFBRDADDR:\n    case SIOCSIFHWADDR:\n    case SIOCSIFFLAGS:\n    case SIOCSIFPFLAGS:\n    case SIOCSIFTXQLEN:\n    case SIOCSIFMTU:\n    case SIOCSIFNAME:\n    case SIOCSIFNETMASK:\n    case SIOCSIFMETRIC:\n    case SIOCSIFHWBROADCAST:\n    case SIOCSIFMAP:\n    case SIOCADDMULTI:\n    case SIOCDELMULTI:\n    /* Bridge ioctls */\n    case SIOCBRADDBR:\n    case SIOCBRDELBR:\n    case SIOCBRADDIF:\n    case SIOCBRDELIF:\n    /* Routing table ioctls */\n    case SIOCADDRT:\n    case SIOCDELRT:\n      return PREVENT_SWITCH;\n\n    case SIOCBONDINFOQUERY: {\n      auto ifrp = syscall_state.reg_parameter<typename Arch::ifreq>(3, IN);\n      syscall_state.mem_ptr_parameter<typename Arch::ifbond>(\n          REMOTE_PTR_FIELD(ifrp, ifr_ifru.ifru_data));\n      syscall_state.after_syscall_action(record_page_below_stack_ptr);\n      return PREVENT_SWITCH;\n    }\n\n    case SIOCGIFADDR:\n    case SIOCGIFDSTADDR:\n    case SIOCGIFBRDADDR:\n    case SIOCGIFHWADDR:\n    case SIOCGIFFLAGS:\n    case SIOCGIFPFLAGS:\n    case SIOCGIFTXQLEN:\n    case SIOCGIFINDEX:\n    case SIOCGIFMTU:\n    case SIOCGIFNAME:\n    case SIOCGIFNETMASK:\n    case SIOCGIFMETRIC:\n    case SIOCGIFMAP:\n    case SIOCGMIIPHY:\n    case SIOCGMIIREG:\n      syscall_state.reg_parameter<typename Arch::ifreq>(3);\n      syscall_state.after_syscall_action(record_page_below_stack_ptr);\n      return PREVENT_SWITCH;\n\n    // https://github.com/torvalds/linux/blob/254ec036db1123b10e23e1412c191a3cf70dce71/net/bridge/br_ioctl.c#L316-L369\n    case SIOCGIFBR: {\n        auto params = syscall_state.reg_parameter<unsigned long>(3, IN);\n        auto op = t->read_mem(params + 0);\n        switch (op) {\n            // does not mutate memory\n            case BRCTL_GET_VERSION:\n                break;\n            case BRCTL_GET_BRIDGES: {\n                auto len = t->read_mem(params + 2);\n                syscall_state.mem_ptr_parameter(params + 1, len * sizeof(int));\n                break;\n            }\n            case BRCTL_ADD_BRIDGE:\n            case BRCTL_DEL_BRIDGE:\n                syscall_state.mem_ptr_parameter<uint8_t[IFNAMSIZ]>(params + 1, IN);\n                break;\n        }\n        return PREVENT_SWITCH;\n    }\n\n    // These haven't been observed to write beyond\n    // tracees' stacks, but we record a stack page here\n    // just in case the behavior is driver-dependent.\n    case SIOCGIWFREQ:\n    case SIOCGIWMODE:\n    case SIOCGIWNAME:\n    case SIOCGIWRATE:\n    case SIOCGIWSENS:\n      syscall_state.reg_parameter<typename Arch::iwreq>(3);\n      syscall_state.after_syscall_action(record_page_below_stack_ptr);\n      return PREVENT_SWITCH;\n    case SIOCGIWESSID: {\n      auto argsp = syscall_state.reg_parameter<typename Arch::iwreq>(3, IN_OUT);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, u.essid.pointer),\n                                      args.u.essid.length);\n      syscall_state.after_syscall_action(record_page_below_stack_ptr);\n      return PREVENT_SWITCH;\n    }\n\n    case SIOCGSTAMP:\n      syscall_state.reg_parameter<typename Arch::timeval>(3);\n      return PREVENT_SWITCH;\n\n    case SIOCGSTAMPNS:\n      syscall_state.reg_parameter<typename Arch::timespec>(3);\n      return PREVENT_SWITCH;\n\n    case TCGETS:\n    case TIOCGLCKTRMIOS:\n      syscall_state.reg_parameter<typename Arch::termios>(3);\n      return PREVENT_SWITCH;\n\n    case TCGETA:\n      syscall_state.reg_parameter<typename Arch::termio>(3);\n      return PREVENT_SWITCH;\n\n    case TIOCLINUX:\n      syscall_state.reg_parameter<char>(3);\n      return PREVENT_SWITCH;\n\n    case BLKSSZGET:\n    case BLKALIGNOFF:\n    case KDGKBMODE:\n    case RNDGETENTCNT:\n    case TIOCINQ: // == FIONREAD == SIOCOUTQ\n    case TIOCOUTQ:\n    case TIOCGETD:\n    case TIOCMGET:\n    case TIOCMSET:\n    case TIOCSERGETLSR:\n    case VT_OPENQRY:\n    case SIOCOUTQNSD:\n      syscall_state.reg_parameter<int>(3);\n      return PREVENT_SWITCH;\n\n    case BLKROGET:\n    case BLKIOMIN:\n    case BLKIOOPT:\n    case BLKPBSZGET:\n    case BLKDISCARDZEROES:\n      syscall_state.reg_parameter<unsigned int>(3);\n      return PREVENT_SWITCH;\n\n    case BLKGETSIZE:\n      syscall_state.reg_parameter<typename Arch::unsigned_long>(3);\n      return PREVENT_SWITCH;\n\n    case BLKRAGET:\n    case BLKFRAGET:\n      syscall_state.reg_parameter<typename Arch::signed_long>(3);\n      return PREVENT_SWITCH;\n\n    case BLKSECTGET:\n    case BLKROTATIONAL:\n      syscall_state.reg_parameter<typename Arch::unsigned_short>(3);\n      return PREVENT_SWITCH;\n\n    case BLKGETNRZONES:\n    case BLKGETZONESZ:\n    case BLKREPORTZONE:\n    case BLKCLOSEZONE:\n    case BLKOPENZONE:\n    case BLKRESETZONE:\n    case BLKFINISHZONE:\n      syscall_state.reg_parameter<typename Arch::signed_long>(3);\n      return PREVENT_SWITCH;\n\n    case TIOCGWINSZ:\n      syscall_state.reg_parameter<typename Arch::winsize>(3);\n      return PREVENT_SWITCH;\n\n    case TIOCGPGRP:\n    case TIOCGSID:\n      syscall_state.reg_parameter<typename Arch::pid_t>(3);\n      return PREVENT_SWITCH;\n\n    case TIOCGSERIAL:\n      syscall_state.reg_parameter<typename Arch::serial_struct>(3);\n      return PREVENT_SWITCH;\n    case TIOCSSERIAL:\n      return PREVENT_SWITCH;\n\n    case TIOCGICOUNT:\n      syscall_state.reg_parameter<typename Arch::serial_icounter_struct>(3);\n      return PREVENT_SWITCH;\n\n    case SNDRV_CTL_IOCTL_PVERSION:\n      syscall_state.reg_parameter<int>(3);\n      return PREVENT_SWITCH;\n\n    case SNDRV_CTL_IOCTL_CARD_INFO:\n      syscall_state.reg_parameter<typename Arch::snd_ctl_card_info>(3);\n      return PREVENT_SWITCH;\n\n    case HCIGETDEVINFO:\n      syscall_state.reg_parameter<typename Arch::hci_dev_info>(3);\n      return PREVENT_SWITCH;\n\n    case HCIGETDEVLIST:\n      syscall_state.reg_parameter<typename Arch::hci_dev_list_req>(3);\n      return PREVENT_SWITCH;\n\n    case SG_EMULATED_HOST:\n    case SG_GET_RESERVED_SIZE:\n    case SG_GET_SG_TABLESIZE:\n    case SG_GET_VERSION_NUM:\n      syscall_state.reg_parameter<typename Arch::signed_int>(3);\n      return PREVENT_SWITCH;\n\n    case SG_IO: {\n      auto argsp = syscall_state.reg_parameter<typename Arch::sg_io_hdr>(3, IN_OUT);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, dxferp), args.dxfer_len);\n      //cmdp: The user memory pointed to is only read (not written to).\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, sbp), args.mx_sb_len);\n      //usr_ptr: This value is not acted upon by the sg driver.\n      return PREVENT_SWITCH;\n    }\n\n    case VT_GETSTATE:\n      syscall_state.reg_parameter<typename Arch::vt_stat>(3);\n      return PREVENT_SWITCH;\n\n    case FBIOGET_FSCREENINFO:\n      syscall_state.reg_parameter<typename Arch::fb_fix_screeninfo>(3);\n      return PREVENT_SWITCH;\n\n    case FBIOGET_VSCREENINFO:\n      syscall_state.reg_parameter<typename Arch::fb_var_screeninfo>(3);\n      return PREVENT_SWITCH;\n\n    case CDROMREADTOCHDR:\n      syscall_state.reg_parameter<typename Arch::cdrom_tochdr>(3);\n      return PREVENT_SWITCH;\n\n    case CDROMREADTOCENTRY:\n      syscall_state.reg_parameter<typename Arch::cdrom_tocentry>(3);\n      return PREVENT_SWITCH;\n  }\n\n  /* In ioctl language, \"_IOC_READ\" means \"outparam\".  Both\n   * READ and WRITE can be set for inout params.\n   * USBDEVFS ioctls seem to be mostly backwards in their interpretation of the\n   * read/write bits :-(.\n   */\n  if (!(_IOC_READ & dir)) {\n    switch (IOCTL_MASK_SIZE(request)) {\n      // Order by value\n      // Older ioctls don't use IOC macros at all, so don't mask size for them\n      case TCSETS:\n      case TCSETSW:\n      case TCSETSF:\n      case TCSETA:\n      case TCSETAW:\n      case TCSETAF:\n      case TIOCSLCKTRMIOS:\n      case TCSBRK:\n      case TCSBRKP:\n      case TIOCSBRK:\n      case TIOCCBRK:\n      case TCXONC:\n      case TCFLSH:\n      case TIOCEXCL:\n      case TIOCNXCL:\n      case TIOCSCTTY:\n      case TIOCNOTTY:\n      case TIOCSPGRP:\n      case TIOCSTI:\n      case TIOCSWINSZ:\n      // No test for TIOCCONS because if run as root it would do bad things\n      case TIOCCONS:\n      case TIOCPKT:\n      case FIONBIO:\n      case FIOASYNC:\n      case TIOCSETD:\n      case IOCTL_MASK_SIZE(TIOCSPTLCK):\n      case IOCTL_MASK_SIZE(TIOCGPTPEER):\n      case FIOCLEX:\n      case FIONCLEX:\n      case IOCTL_MASK_SIZE(BTRFS_IOC_CLONE):\n      case IOCTL_MASK_SIZE(BTRFS_IOC_CLONE_RANGE):\n      case IOCTL_MASK_SIZE(USBDEVFS_DISCARDURB):\n      case IOCTL_MASK_SIZE(USBDEVFS_RESET):\n      case IOCTL_MASK_SIZE(TUNSETNOCSUM):\n      case IOCTL_MASK_SIZE(TUNSETDEBUG):\n      case IOCTL_MASK_SIZE(TUNSETPERSIST):\n      case IOCTL_MASK_SIZE(TUNSETOWNER):\n      case IOCTL_MASK_SIZE(TUNSETLINK):\n      case IOCTL_MASK_SIZE(TUNSETGROUP):\n      case IOCTL_MASK_SIZE(TUNSETOFFLOAD):\n      case IOCTL_MASK_SIZE(TUNSETTXFILTER):\n      case IOCTL_MASK_SIZE(TUNSETSNDBUF):\n      case IOCTL_MASK_SIZE(TUNATTACHFILTER):\n      case IOCTL_MASK_SIZE(TUNDETACHFILTER):\n      case IOCTL_MASK_SIZE(TUNSETVNETHDRSZ):\n      case IOCTL_MASK_SIZE(TUNSETQUEUE):\n      case IOCTL_MASK_SIZE(TUNSETIFINDEX):\n      case IOCTL_MASK_SIZE(TUNSETVNETLE):\n      case IOCTL_MASK_SIZE(TUNSETVNETBE):\n      case IOCTL_MASK_SIZE(TCSETS2):\n      case IOCTL_MASK_SIZE(TCSETSW2):\n      case IOCTL_MASK_SIZE(TCSETSF2):\n        return PREVENT_SWITCH;\n      case IOCTL_MASK_SIZE(USBDEVFS_GETDRIVER):\n        // Reads and writes its parameter despite not having the _IOC_READ bit.\n        syscall_state.reg_parameter(3, size);\n        return PREVENT_SWITCH;\n      case IOCTL_MASK_SIZE(USBDEVFS_REAPURB):\n      case IOCTL_MASK_SIZE(USBDEVFS_REAPURBNDELAY):\n        syscall_state.reg_parameter(3, size);\n        syscall_state.after_syscall_action(record_usbdevfs_reaped_urb<Arch>);\n        return ALLOW_SWITCH;\n      case IOCTL_MASK_SIZE(TUNSETIFF):\n        // Reads and writes its parameter despite not having the _IOC_READ\n        // bit...\n        // And the parameter is an ifreq, not an int as in the ioctl definition!\n        syscall_state.reg_parameter<typename Arch::ifreq>(3);\n        return PREVENT_SWITCH;\n    }\n\n    switch (type) {\n      case 0x54: // TIO*\n      case 0x89: // SIO*\n      case 0x8B: // SIO* wireless interface ioctls\n        // These ioctls are known to be irregular and don't usually have the\n        // correct |dir| bits. They must be handled above\n        syscall_state.expect_errno = EINVAL;\n        return PREVENT_SWITCH;\n    }\n\n    /* If the kernel isn't going to write any data back to\n     * us, we hope and pray that the result of the ioctl\n     * (observable to the tracee) is deterministic.\n     * We're also assuming it doesn't block.\n     * This is risky! Many ioctls use irregular ioctl codes\n     * that do not have the _IOC_READ bit set but actually do write to\n     * user-space! */\n    LOG(debug) << \"  (presumed ignorable ioctl, nothing to do)\";\n    return PREVENT_SWITCH;\n  }\n\n  /* There are lots of ioctl values for EVIOCGBIT */\n  if (type == 'E' && nr >= 0x20 && nr <= 0x7f) {\n    syscall_state.reg_parameter(3, size);\n    return PREVENT_SWITCH;\n  }\n\n  /* The following are thought to be \"regular\" ioctls, the\n   * processing of which is only known to (observably) write to\n   * the bytes in the structure passed to the kernel.  So all we\n   * need is to record |size| bytes.\n   * Since the size may vary across architectures we mask it out here to check\n   * only the type + number. */\n  switch (IOCTL_MASK_SIZE(request)) {\n    case IOCTL_MASK_SIZE(VIDIOC_QUERYCAP):\n    case IOCTL_MASK_SIZE(VIDIOC_ENUM_FMT):\n    case IOCTL_MASK_SIZE(VIDIOC_ENUM_FRAMESIZES):\n    case IOCTL_MASK_SIZE(VIDIOC_ENUM_FRAMEINTERVALS):\n    case IOCTL_MASK_SIZE(VIDIOC_ENUMINPUT):\n    case IOCTL_MASK_SIZE(VIDIOC_G_FMT):\n    case IOCTL_MASK_SIZE(VIDIOC_S_FMT):\n    case IOCTL_MASK_SIZE(VIDIOC_TRY_FMT):\n    case IOCTL_MASK_SIZE(VIDIOC_G_PARM):\n    case IOCTL_MASK_SIZE(VIDIOC_S_PARM):\n    case IOCTL_MASK_SIZE(VIDIOC_REQBUFS):\n    case IOCTL_MASK_SIZE(VIDIOC_QUERYBUF):\n    case IOCTL_MASK_SIZE(VIDIOC_QUERYCTRL):\n    case IOCTL_MASK_SIZE(VIDIOC_QBUF):\n    case IOCTL_MASK_SIZE(VIDIOC_G_CTRL):\n    case IOCTL_MASK_SIZE(VIDIOC_G_OUTPUT):\n    case IOCTL_MASK_SIZE(VIDIOC_S_CTRL):\n    case IOCTL_MASK_SIZE(VIDIOC_G_INPUT):\n    case IOCTL_MASK_SIZE(VIDIOC_QUERY_EXT_CTRL):\n    case IOCTL_MASK_SIZE(VIDIOC_G_PRIORITY):\n    case IOCTL_MASK_SIZE(VIDIOC_EXPBUF):\n    case IOCTL_MASK_SIZE(VFAT_IOCTL_READDIR_BOTH):\n    case IOCTL_MASK_SIZE(DMA_BUF_IOCTL_EXPORT_SYNC_FILE):\n    case IOCTL_MASK_SIZE(MEMWRITEOOB):\n    case IOCTL_MASK_SIZE(MEMREADOOB):\n    case IOCTL_MASK_SIZE(MEMGETREGIONINFO):\n    case IOCTL_MASK_SIZE(MEMWRITEOOB64):\n    case IOCTL_MASK_SIZE(MEMREADOOB64):\n      syscall_state.reg_parameter(3, size, IN_OUT);\n      return PREVENT_SWITCH;\n\n    case IOCTL_MASK_SIZE(TIOCGPTN):\n    case IOCTL_MASK_SIZE(TIOCGPKT):\n    case IOCTL_MASK_SIZE(TIOCGPTLCK):\n    case IOCTL_MASK_SIZE(TIOCGEXCL):\n    case IOCTL_MASK_SIZE(USBDEVFS_GET_CAPABILITIES):\n    case IOCTL_MASK_SIZE(FS_IOC_FSGETXATTR):\n    // FS_IOC_GETVERSION has the same number as VIDIOCGCAP (but different size)\n    // but the same treatment works for both.\n    case IOCTL_MASK_SIZE(FS_IOC_GETVERSION):\n    case IOCTL_MASK_SIZE(FS_IOC_GETFLAGS):\n    case IOCTL_MASK_SIZE(TUNGETFEATURES):\n    case IOCTL_MASK_SIZE(TUNGETSNDBUF):\n    case IOCTL_MASK_SIZE(TUNGETVNETHDRSZ):\n    case IOCTL_MASK_SIZE(TUNGETVNETLE):\n    case IOCTL_MASK_SIZE(TUNGETVNETBE):\n    case IOCTL_MASK_SIZE(EVIOCGVERSION):\n    case IOCTL_MASK_SIZE(EVIOCGID):\n    case IOCTL_MASK_SIZE(EVIOCGREP):\n    case IOCTL_MASK_SIZE(EVIOCGKEYCODE): /* also covers EVIOCGKEYCODE_V2 */\n    case IOCTL_MASK_SIZE(EVIOCGNAME(0)):\n    case IOCTL_MASK_SIZE(EVIOCGPHYS(0)):\n    case IOCTL_MASK_SIZE(EVIOCGUNIQ(0)):\n    case IOCTL_MASK_SIZE(EVIOCGPROP(0)):\n    case IOCTL_MASK_SIZE(EVIOCGMTSLOTS(0)):\n    case IOCTL_MASK_SIZE(EVIOCGKEY(0)):\n    case IOCTL_MASK_SIZE(EVIOCGLED(0)):\n    case IOCTL_MASK_SIZE(EVIOCGSND(0)):\n    case IOCTL_MASK_SIZE(EVIOCGSW(0)):\n    case IOCTL_MASK_SIZE(EVIOCGEFFECTS):\n    case IOCTL_MASK_SIZE(EVIOCGMASK):\n    case IOCTL_MASK_SIZE(JSIOCGVERSION):\n    case IOCTL_MASK_SIZE(JSIOCGAXES):\n    case IOCTL_MASK_SIZE(JSIOCGBUTTONS):\n    // This gets a list of js_corr structures whose length we don't know without\n    // querying the device ourselves.\n    // case IOCTL_MASK_SIZE(JSIOCGCORR):\n    case IOCTL_MASK_SIZE(JSIOCGAXMAP):\n    case IOCTL_MASK_SIZE(JSIOCGBTNMAP):\n    case IOCTL_MASK_SIZE(JSIOCGNAME(0)):\n    case IOCTL_MASK_SIZE(HIDIOCGRAWINFO):\n    case IOCTL_MASK_SIZE(HIDIOCGRAWNAME(0)):\n    case IOCTL_MASK_SIZE(HIDIOCGRDESCSIZE):\n    case IOCTL_MASK_SIZE(HIDIOCGRDESC):\n    case IOCTL_MASK_SIZE(BLKBSZGET):\n    case IOCTL_MASK_SIZE(BLKGETDISKSEQ):\n    case IOCTL_MASK_SIZE(MEMGETINFO):\n    case IOCTL_MASK_SIZE(MEMGETREGIONCOUNT):\n    case IOCTL_MASK_SIZE(MEMGETOOBSEL):\n    case IOCTL_MASK_SIZE(OTPGETREGIONCOUNT):\n    case IOCTL_MASK_SIZE(OTPGETREGIONINFO):\n    case IOCTL_MASK_SIZE(ECCGETLAYOUT):\n    case IOCTL_MASK_SIZE(ECCGETSTATS):\n    case IOCTL_MASK_SIZE(TCGETS2):\n      syscall_state.reg_parameter(3, size);\n      return PREVENT_SWITCH;\n\n    case IOCTL_MASK_SIZE(PERF_EVENT_IOC_ID):\n      syscall_state.reg_parameter<uint64_t>(3);\n      return PREVENT_SWITCH;\n\n    case IOCTL_MASK_SIZE(USBDEVFS_ALLOC_STREAMS):\n    case IOCTL_MASK_SIZE(USBDEVFS_CLAIMINTERFACE):\n    case IOCTL_MASK_SIZE(USBDEVFS_CLEAR_HALT):\n    case IOCTL_MASK_SIZE(USBDEVFS_DISCONNECT_CLAIM):\n    case IOCTL_MASK_SIZE(USBDEVFS_FREE_STREAMS):\n    case IOCTL_MASK_SIZE(USBDEVFS_RELEASEINTERFACE):\n    case IOCTL_MASK_SIZE(USBDEVFS_SETCONFIGURATION):\n    case IOCTL_MASK_SIZE(USBDEVFS_SETINTERFACE):\n    case IOCTL_MASK_SIZE(USBDEVFS_SUBMITURB):\n    case IOCTL_MASK_SIZE(MEMERASE):\n    case IOCTL_MASK_SIZE(MEMLOCK):\n    case IOCTL_MASK_SIZE(MEMUNLOCK):\n    case IOCTL_MASK_SIZE(MEMGETBADBLOCK):\n    case IOCTL_MASK_SIZE(MEMSETBADBLOCK):\n    case IOCTL_MASK_SIZE(OTPSELECT):\n    case IOCTL_MASK_SIZE(OTPLOCK):\n    case IOCTL_MASK_SIZE(OTPERASE):\n    case IOCTL_MASK_SIZE(MTDFILEMODE):\n    case IOCTL_MASK_SIZE(MEMERASE64):\n    case IOCTL_MASK_SIZE(MEMISLOCKED):\n    case IOCTL_MASK_SIZE(MEMWRITE):\n      // Doesn't actually seem to write to userspace\n      return PREVENT_SWITCH;\n\n    case IOCTL_MASK_SIZE(BLKGETSIZE64):\n      // The ioctl definition says \"size_t\" but it's actually a uint64!\n      syscall_state.reg_parameter<uint64_t>(3);\n      return PREVENT_SWITCH;\n\n    case IOCTL_MASK_SIZE(TUNGETIFF):\n      // The ioctl definition says \"unsigned int\" but it's actually a\n      // struct ifreq!\n      syscall_state.reg_parameter<typename Arch::ifreq>(3);\n      return PREVENT_SWITCH;\n    case IOCTL_MASK_SIZE(TUNGETFILTER):\n      // The ioctl definition says \"struct sock_fprog\" but there is no kernel\n      // compat code so a 32-bit task on a 64-bit kernel needs to use the\n      // 64-bit type.\n      if (sizeof(void*) == 8) {\n        // 64-bit rr build. We must be on a 64-bit kernel so use the 64-bit\n        // sock_fprog type.\n        syscall_state.reg_parameter<typename NativeArch::sock_fprog>(3);\n      } else {\n        FATAL() << \"TUNGETFILTER not supported on 32-bit since its behavior \"\n                   \"depends on 32-bit vs 64-bit kernel\";\n      }\n      return PREVENT_SWITCH;\n\n    case IOCTL_MASK_SIZE(USBDEVFS_IOCTL): {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::usbdevfs_ioctl>(3, IN);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, data),\n                                      _IOC_SIZE(args.ioctl_code));\n      return PREVENT_SWITCH;\n    }\n    case IOCTL_MASK_SIZE(USBDEVFS_CONTROL): {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::usbdevfs_ctrltransfer>(3,\n                                                                            IN);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, data),\n                                      args.wLength);\n      return PREVENT_SWITCH;\n    }\n    case IOCTL_MASK_SIZE(FS_IOC_FIEMAP): {\n      auto argsp = remote_ptr<typename Arch::fiemap>(t->regs().arg3());\n      auto args = t->read_mem(argsp);\n      size = sizeof(typename Arch::fiemap) +\n             sizeof(typename Arch::fiemap_extent) * args.fm_extent_count;\n      syscall_state.reg_parameter(3, size, IN_OUT);\n      return PREVENT_SWITCH;\n    }\n  }\n\n  /* These ioctls are mostly regular but require additional recording. */\n  switch (IOCTL_MASK_SIZE(request)) {\n    case IOCTL_MASK_SIZE(MEMREAD): {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::mtd_read_req>(3, IN_OUT);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, usr_data),\n                                      args.len);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, usr_oob),\n                                      args.ooblen);\n      return PREVENT_SWITCH;\n    }\n\n    case IOCTL_MASK_SIZE(VIDIOC_DQBUF): {\n      if (size == sizeof(typename Arch::v4l2_buffer)) {\n        syscall_state.reg_parameter(3, size, IN_OUT);\n        syscall_state.after_syscall_action(record_v4l2_buffer_contents<Arch>);\n        // VIDIOC_DQBUF can block. It can't if the fd was opened O_NONBLOCK,\n        // but we don't try to determine that.\n        // Note that we're exposed to potential race conditions here because\n        // VIDIOC_DQBUF (blocking or not) assumes the driver has filled\n        // the mmapped data region at some point since the buffer was queued\n        // with VIDIOC_QBUF, and we don't/can't know exactly when that\n        // happened. Replay could fail if this thread or another thread reads\n        // the contents of mmapped contents queued with the driver.\n        return ALLOW_SWITCH;\n      }\n    }\n  }\n\n  syscall_state.expect_errno = EINVAL;\n  return PREVENT_SWITCH;\n}\n\ntemplate <typename Arch> static BpfMapMonitor* bpf_map_monitor(RecordTask* t,\n    TaskSyscallState& syscall_state, remote_ptr<typename Arch::bpf_attr>* argsp_out) {\n  auto argsp = syscall_state.reg_parameter<typename Arch::bpf_attr>(2, IN);\n  auto args = t->read_mem(argsp);\n  FileMonitor* monitor = t->fd_table()->get_monitor(args.map_fd);\n  ASSERT(t, monitor) << \"We need a BpfMapMonitor to handle this, but couldn't find it for fd \" << args.map_fd;\n  ASSERT(t, monitor->type() == FileMonitor::BpfMap);\n  *argsp_out = argsp;\n  return static_cast<BpfMapMonitor*>(monitor);\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_bpf(RecordTask* t,\n                              TaskSyscallState& syscall_state) {\n  int cmd = t->regs().arg1();\n  switch (cmd) {\n    case RR_BPF_MAP_CREATE:\n    case RR_BPF_MAP_UPDATE_ELEM:\n    case RR_BPF_MAP_DELETE_ELEM:\n    case RR_BPF_BTF_LOAD:\n    case RR_BPF_PROG_DETACH:\n    case RR_BPF_PROG_ATTACH:\n    case RR_BPF_MAP_FREEZE:\n    case RR_BPF_PROG_BIND_MAP:\n    case RR_BPF_TOKEN_CREATE:\n      break;\n    case RR_BPF_OBJ_GET:\n      return ALLOW_SWITCH;\n    case RR_BPF_PROG_LOAD: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::bpf_attr>(2, IN);\n      auto args = t->read_mem(argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, log_buf),\n                                      args.log_size);\n      break;\n    }\n    case RR_BPF_MAP_LOOKUP_ELEM: {\n      remote_ptr<typename Arch::bpf_attr> argsp;\n      BpfMapMonitor* monitor = bpf_map_monitor<Arch>(t, syscall_state, &argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, value),\n                                      monitor->value_size());\n      break;\n    }\n    case RR_BPF_MAP_GET_NEXT_KEY: {\n      remote_ptr<typename Arch::bpf_attr> argsp;\n      BpfMapMonitor* monitor = bpf_map_monitor<Arch>(t, syscall_state, &argsp);\n      syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(argsp, next_key),\n                                      monitor->key_size());\n      break;\n    }\n    case RR_BPF_PROG_QUERY: {\n      auto attr_size = t->regs().arg3();\n      auto attr_begin = syscall_state.reg_parameter(2, attr_size, IN_OUT);\n      auto attr_buf = MemoryRange(attr_begin, attr_size);\n      auto attrp = attr_begin.cast<typename Arch::bpf_attr>();\n\n      // if the offset of the prog_cnt is out of the buffer,\n      // the syscall will fail and we can't track anything\n      auto prog_cnt_p = REMOTE_PTR_FIELD(attrp, query.prog_cnt);\n      if (!attr_buf.contains(prog_cnt_p)) {\n        break;\n      }\n      bool ok = true;\n      auto prog_cnt = t->read_mem(prog_cnt_p, &ok);\n      if (!ok) {\n        break;\n      }\n\n      auto buf_size = prog_cnt * sizeof(__u32);\n      // for each output array, only track changes if the field is\n      // within the bounds of the user provided buffer\n      auto prog_ids_p = REMOTE_PTR_FIELD(attrp, query.prog_ids);\n      if (attr_buf.contains(prog_ids_p)) {\n        syscall_state.mem_ptr_parameter(prog_ids_p, buf_size);\n      }\n\n      auto prog_attach_flags_p = REMOTE_PTR_FIELD(attrp, query.prog_attach_flags);\n      if (attr_buf.contains(prog_attach_flags_p)) {\n        syscall_state.mem_ptr_parameter(prog_attach_flags_p, buf_size);\n      }\n\n      auto link_ids_p = REMOTE_PTR_FIELD(attrp, query.link_ids);\n      if (attr_buf.contains(link_ids_p)) {\n        syscall_state.mem_ptr_parameter(link_ids_p, buf_size);\n      }\n\n      auto link_attach_flags_p = REMOTE_PTR_FIELD(attrp, query.link_attach_flags);\n      if (attr_buf.contains(link_attach_flags_p)) {\n        syscall_state.mem_ptr_parameter(link_attach_flags_p, buf_size);\n      }\n      break;\n    }\n    case RR_BPF_OBJ_GET_INFO_BY_FD: {\n      auto attr_size = t->regs().arg3();\n      auto attr_begin = syscall_state.reg_parameter(2, attr_size, IN_OUT);\n      auto attr_buf = MemoryRange(attr_begin, attr_size);\n      auto attrp = attr_begin.cast<typename Arch::bpf_attr>();\n\n      auto info_len_p = REMOTE_PTR_FIELD(attrp, info.info_len);\n      if (!attr_buf.contains(info_len_p)) {\n        break;\n      }\n      bool ok = true;\n      auto info_len = t->read_mem(info_len_p, &ok);\n      if (!ok) {\n        break;\n      }\n\n      auto info_p = REMOTE_PTR_FIELD(attrp, info.info);\n      // *info_p is actually a uint64_t, so for 32-bit tracees we're assuming\n      // they're little-endian here. That's true for now since x86 is the only\n      // 32-bit architecture we support. We could fix this by making\n      // mem_ptr_parameter take a remote_ptr<T> and checking the size of T.\n      syscall_state.mem_ptr_parameter(info_p, info_len);\n      break;\n    }\n    default:\n      syscall_state.expect_errno = EINVAL;\n      break;\n  }\n  return PREVENT_SWITCH;\n}\n\nstatic bool maybe_emulate_wait(RecordTask* t, TaskSyscallState& syscall_state) {\n  if (t->in_wait_type == WAIT_TYPE_NONE) {\n    return false;\n  }\n\n  for (Task* thread : t->thread_group()->task_set()) {\n    RecordTask* rthread = static_cast<RecordTask*>(thread);\n    for (RecordTask* child : rthread->emulated_ptrace_tracees) {\n      if (t->is_waiting_for_ptrace(child) && child->emulated_stop_pending) {\n        syscall_state.emulate_wait_for_child = child;\n        return true;\n      }\n    }\n  }\n\n  for (ThreadGroup* child_process : t->thread_group()->children()) {\n    for (Task* child : child_process->task_set()) {\n      auto rchild = static_cast<RecordTask*>(child);\n      if (rchild->emulated_stop_type == NOT_STOPPED) {\n        continue;\n      }\n      if (!(t->in_wait_options & WUNTRACED) && rchild->emulated_stop_type != CHILD_STOP) {\n        continue;\n      }\n      if (!rchild->emulated_stop_pending || !t->is_waiting_for(rchild)) {\n        continue;\n      }\n      syscall_state.emulate_wait_for_child = rchild;\n      return true;\n    }\n  }\n  return false;\n}\n\nstatic void maybe_pause_instead_of_waiting(RecordTask* t) {\n  if (t->in_wait_type != WAIT_TYPE_PID || (t->in_wait_options & WNOHANG)) {\n    return;\n  }\n  RecordTask* child = t->session().find_task(t->in_wait_pid);\n  if (!child) {\n    LOG(debug) << \"Child \" << t->in_wait_pid << \" not found!\";\n  }\n  if (!child || !t->is_waiting_for_ptrace(child) || t->is_waiting_for(child)) {\n    return;\n  }\n  // OK, t is waiting for a ptrace child by tid, but since t is not really\n  // ptracing child, entering a real wait syscall will not actually wait for\n  // the child, so the kernel may error out with ECHILD (non-ptracers can't\n  // wait on specific threads of another process, or for non-child processes).\n  // To avoid this problem, we'll replace the wait syscall with a pause()\n  // syscall.\n  // It would be nice if we didn't have to do this, but I can't see a better\n  // way.\n  Registers r = t->regs();\n  // pause() would be sufficient here, but we don't have that on all\n  // architectures, so use ppoll(NULL, 0, NULL, NULL), which is what\n  // glibc uses to implement pause() on architectures where the former\n  // doesn't exist\n  r.set_original_syscallno(syscall_number_for_ppoll(t->arch()));\n  r.set_arg1(0);\n  r.set_arg2(0);\n  r.set_arg3(0);\n  r.set_arg4(0);\n  t->set_regs(r);\n}\n\nstatic RecordTask* verify_ptrace_target(RecordTask* tracer,\n                                        TaskSyscallState& syscall_state,\n                                        pid_t pid,\n                                        bool require_stopped = true) {\n  RecordTask* tracee = tracer->session().find_task(pid);\n  if (!tracee) {\n    LOG(debug) << \"tracee pid \" << pid << \" is unknown to rr\";\n    syscall_state.emulate_result(-ESRCH);\n    return nullptr;\n  }\n  if (tracee->emulated_ptracer != tracer) {\n    LOG(debug) << pid << \" is not traced by \" << tracer->tid;\n    syscall_state.emulate_result(-ESRCH);\n    return nullptr;\n  }\n  if (require_stopped && tracee->emulated_stop_type == NOT_STOPPED) {\n    LOG(debug) << pid << \" is not in a ptrace stop\";\n    syscall_state.emulate_result(-ESRCH);\n    return nullptr;\n  }\n  return tracee;\n}\n\nstatic void prepare_ptrace_cont(RecordTask* tracee, int sig, int command) {\n  if (sig) {\n    siginfo_t si = tracee->take_ptrace_signal_siginfo(sig);\n    LOG(debug) << \"Doing ptrace resume with signal \" << signal_name(sig);\n    // Treat signal as nondeterministic; it won't happen just by\n    // replaying the tracee.\n    tracee->push_event(\n        Event(EV_SIGNAL, SignalEvent(si, NONDETERMINISTIC_SIG,\n                                     tracee->sig_resolved_disposition(\n                                         si.si_signo, NONDETERMINISTIC_SIG))));\n  }\n\n  tracee->emulated_stop_type = NOT_STOPPED;\n  tracee->emulated_stop_pending = false;\n  tracee->emulated_stop_code = WaitStatus();\n  tracee->emulated_ptrace_cont_command = command;\n\n  if (tracee->ev().is_syscall_event() &&\n      PROCESSING_SYSCALL == tracee->ev().Syscall().state) {\n    // Continue the task since we didn't in enter_syscall\n    tracee->resume_execution(RESUME_SYSCALL, RESUME_NONBLOCKING,\n                             RESUME_NO_TICKS);\n  }\n}\n\nstatic uint64_t widen_buffer_unsigned(const void* buf, size_t size) {\n  switch (size) {\n    case 1:\n      return *reinterpret_cast<const uint8_t*>(buf);\n    case 2:\n      return *reinterpret_cast<const uint16_t*>(buf);\n    case 4:\n      return *reinterpret_cast<const uint32_t*>(buf);\n    case 8:\n      return *reinterpret_cast<const uint64_t*>(buf);\n    default:\n      DEBUG_ASSERT(0 && \"Unsupported size\");\n      return 0;\n  }\n}\n\nstatic int64_t widen_buffer_signed(const void* buf, size_t size) {\n  switch (size) {\n    case 1:\n      return *reinterpret_cast<const int8_t*>(buf);\n    case 2:\n      return *reinterpret_cast<const int16_t*>(buf);\n    case 4:\n      return *reinterpret_cast<const int32_t*>(buf);\n    case 8:\n      return *reinterpret_cast<const int64_t*>(buf);\n    default:\n      DEBUG_ASSERT(0 && \"Unsupported size\");\n      return 0;\n  }\n}\n\nstatic uint64_t path_inode_number(const char* path) {\n  struct stat st;\n  int ret = stat(path, &st);\n  DEBUG_ASSERT(ret == 0);\n  return st.st_ino;\n}\n\nstatic bool is_same_namespace(const char* name, pid_t tid1, pid_t tid2) {\n  char path1[PATH_MAX];\n  char path2[PATH_MAX];\n  sprintf(path1, \"/proc/%d/ns/%s\", tid1, name);\n  sprintf(path2, \"/proc/%d/ns/%s\", tid2, name);\n  return path_inode_number(path1) == path_inode_number(path2);\n}\n\ntemplate <typename Arch>\nstatic void ptrace_get_reg_set(RecordTask* t, TaskSyscallState& syscall_state,\n                               const vector<uint8_t>& regs) {\n  auto piov = syscall_state.reg_parameter<typename Arch::iovec>(4, IN_OUT);\n  auto iov = t->read_mem(piov);\n  iov.iov_len = min<size_t>(iov.iov_len, regs.size());\n  t->write_mem(piov, iov);\n  auto data = syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(piov, iov_base),\n                                              iov.iov_len);\n  t->write_bytes_helper(data, iov.iov_len, regs.data());\n  syscall_state.emulate_result(0);\n}\n\ntemplate <typename Arch>\nstatic void ptrace_verify_set_reg_set(RecordTask* t, size_t min_size,\n                                      TaskSyscallState& syscall_state) {\n  auto iov = t->read_mem(remote_ptr<typename Arch::iovec>(t->regs().arg4()));\n  if (iov.iov_len < min_size) {\n    syscall_state.emulate_result(-EIO);\n    return;\n  }\n  syscall_state.emulate_result(0);\n}\n\nstatic bool verify_ptrace_options(RecordTask* t,\n                                  TaskSyscallState& syscall_state) {\n  // We \"support\" PTRACE_O_SYSGOOD because we don't support PTRACE_SYSCALL yet\n  static const int supported_ptrace_options =\n      PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXIT | PTRACE_O_TRACEFORK |\n      PTRACE_O_TRACECLONE | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEVFORKDONE;\n\n  if ((int)t->regs().arg4() & ~supported_ptrace_options) {\n    LOG(debug) << \"Unsupported ptrace options \" << HEX(t->regs().arg4());\n    syscall_state.emulate_result(-EINVAL);\n    return false;\n  }\n  return true;\n}\n\nstatic void check_ptracer_compatible(RecordTask* tracer, RecordTask* tracee) {\n  // Don't allow a 32-bit process to trace a 64-bit process. That doesn't\n  // make much sense (manipulating registers gets crazy), and would be hard to\n  // support.\n  ASSERT(tracer, !(tracer->arch() == x86 && tracee->arch() == x86_64));\n}\n\nstatic RecordTask* prepare_ptrace_attach(RecordTask* tracer, pid_t attach_to_tid,\n                                         TaskSyscallState& syscall_state) {\n  // To simplify things, require that a ptracer be in the same pid\n  // namespace as rr itself. I.e., tracee tasks sandboxed in a pid\n  // namespace can't use ptrace. This is normally a requirement of\n  // sandboxes anyway.\n  // This could be supported, but would require some work to translate\n  // rr's pids to/from the ptracer's pid namespace.\n  ASSERT(tracer, is_same_namespace(\"pid\", tracer->tid, getpid()));\n  RecordTask* tracee = tracer->session().find_task(attach_to_tid);\n  if (!tracee) {\n    // XXX This prevents a tracer from attaching to a process which isn't\n    // under rr's control. We could support this but it would complicate\n    // things.\n    syscall_state.emulate_result(-ESRCH);\n    return nullptr;\n  }\n  if (tracee->emulated_ptracer || tracee->tgid() == tracer->tgid()) {\n    syscall_state.emulate_result(-EPERM);\n    return nullptr;\n  }\n  check_ptracer_compatible(tracer, tracee);\n  return tracee;\n}\n\nstatic RecordTask* prepare_ptrace_traceme(RecordTask* tracee,\n                                          TaskSyscallState& syscall_state) {\n  RecordTask* tracer = nullptr;\n  pid_t parent_pid = tracee->get_parent_pid();\n  if (tracee->creator_tid != 0) {\n    RecordTask* creator = tracee->session().find_task(tracee->creator_tid);\n    if (creator && creator->thread_group()->tgid == parent_pid) {\n      tracer = creator;\n    }\n  }\n  if (!tracer) {\n    ThreadGroup* tg = tracee->session().find_thread_group(parent_pid);\n    if (tg) {\n      tracer = static_cast<RecordTask*>(tg->first_running_task());\n    }\n    if (!tracer) {\n      syscall_state.emulate_result(0);\n      return nullptr;\n    }\n  }\n  if (tracee->emulated_ptracer || tracee->tgid() == tracer->tgid()) {\n    syscall_state.emulate_result(-EPERM);\n    return nullptr;\n  }\n  check_ptracer_compatible(tracer, tracee);\n  return tracer;\n}\n\nstatic void ptrace_attach_to_already_stopped_task(RecordTask* t) {\n  ASSERT(t, t->emulated_stop_type == GROUP_STOP);\n  // tracee is already stopped because of a group-stop signal.\n  // Sending a SIGSTOP won't work, but we don't need to.\n  t->force_emulate_ptrace_stop(WaitStatus::for_stop_sig(SIGSTOP), t->emulated_stop_type);\n  siginfo_t si;\n  memset(&si, 0, sizeof(si));\n  si.si_signo = SIGSTOP;\n  si.si_code = SI_USER;\n  t->save_ptrace_signal_siginfo(si);\n}\n\n/**\n * The PTRACE_GETREGS/PTRACE_SETREGS commands, as well various PEEK_* and POKE_*\n * ptrace commands are legacy and not implemented on newer architectures.\n * We split them out here, since these newer platforms\n * will not define the requisite data structure to serve them.\n */\ntemplate <typename Arch>\nstatic void prepare_ptrace_legacy(RecordTask* t,\n                                  TaskSyscallState& syscall_state)\n{\n  pid_t pid = (pid_t)t->regs().arg2_signed();\n  int command = (int)t->regs().arg1_signed();\n  switch (command) {\n    case Arch::PTRACE_PEEKUSR: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        // The actual syscall returns the data via the 'data' out-parameter.\n        // The behavior of returning the data as the system call result is\n        // provided by the glibc wrapper.\n        size_t addr = t->regs().arg3();\n        typename Arch::unsigned_word data;\n        if ((addr & (sizeof(data) - 1)) ||\n            addr >= sizeof(typename Arch::user)) {\n          syscall_state.emulate_result(-EIO);\n          break;\n        }\n\n        auto datap =\n            syscall_state.reg_parameter<typename Arch::unsigned_word>(4);\n        if (addr < sizeof(typename Arch::user_regs_struct)) {\n          uint8_t buf[Registers::MAX_SIZE];\n          bool defined;\n          size_t size =\n              tracee->regs().read_register_by_user_offset(buf, addr, &defined);\n          if (defined) {\n            // For unclear reasons, all 32-bit user_regs_struct members are\n            // signed while all 64-bit user_regs_struct members are unsigned.\n            if (Arch::arch() == x86) {\n              data = widen_buffer_signed(buf, size);\n            } else {\n              data = widen_buffer_unsigned(buf, size);\n            }\n          } else {\n            data = 0;\n          }\n        } else if (addr >= offsetof(typename Arch::user, u_debugreg[0]) &&\n                   addr < offsetof(typename Arch::user, u_debugreg[8])) {\n          size_t regno = (addr - offsetof(typename Arch::user, u_debugreg[0])) /\n                         sizeof(data);\n          data = tracee->get_debug_reg(regno);\n        } else {\n          data = 0;\n        }\n\n        t->write_mem(datap, data);\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case Arch::PTRACE_POKEUSR: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        // The actual syscall returns the data via the 'data' out-parameter.\n        // The behavior of returning the data as the system call result is\n        // provided by the glibc wrapper.\n        size_t addr = t->regs().arg3();\n        if ((addr & (sizeof(typename Arch::unsigned_word) - 1)) ||\n            addr >= sizeof(typename Arch::user)) {\n          syscall_state.emulate_result(-EIO);\n          break;\n        }\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case Arch::PTRACE_GETREGS: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        auto data =\n            syscall_state.reg_parameter<typename Arch::user_regs_struct>(4);\n        auto regs = tracee->regs().get_ptrace_for_arch(Arch::arch());\n        ASSERT(t, regs.size() == data.referent_size());\n        t->write_bytes_helper(data, regs.size(), regs.data());\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case Arch::PTRACE_GETFPREGS: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        auto data =\n            syscall_state.reg_parameter<typename Arch::user_fpregs_struct>(4);\n        if (auto extra_regs = tracee->extra_regs_fallible()) {\n          auto regs = extra_regs->get_user_fpregs_struct(Arch::arch());\n          ASSERT(t, regs.size() == data.referent_size());\n          t->write_bytes_helper(data, regs.size(), regs.data());\n          syscall_state.emulate_result(0);\n        } else {\n          syscall_state.emulate_result(-ESRCH);\n        }\n      }\n      break;\n    }\n    case Arch::PTRACE_GETFPXREGS: {\n      if (Arch::arch() != x86) {\n        // GETFPXREGS is x86-32 only\n        syscall_state.expect_errno = EIO;\n        break;\n      }\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        auto data =\n            syscall_state.reg_parameter<X86Arch::user_fpxregs_struct>(4);\n        if (auto extra_regs = tracee->extra_regs_fallible()) {\n          auto regs = extra_regs->get_user_fpxregs_struct();\n          t->write_mem(data, regs);\n          syscall_state.emulate_result(0);\n        } else {\n          syscall_state.emulate_result(-ESRCH);\n        }\n      }\n      break;\n    }\n    case Arch::PTRACE_SETREGS: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        // The actual register effects are performed by\n        // Task::on_syscall_exit_arch\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case Arch::PTRACE_SETFPREGS: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        // The actual register effects are performed by\n        // Task::on_syscall_exit_arch\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case Arch::PTRACE_SETFPXREGS: {\n      if (Arch::arch() != x86) {\n        // SETFPXREGS is x86-32 only\n        syscall_state.expect_errno = EIO;\n        break;\n      }\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, pid);\n      if (tracee) {\n        // The actual register effects are performed by\n        // Task::on_syscall_exit_arch\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n  }\n}\n\ntemplate <>\nvoid prepare_ptrace_legacy<ARM64Arch>(RecordTask*, TaskSyscallState&) {\n  // Nothing to do - unimplemented on this architecture\n}\n\nstatic int non_negative_command(int command) { return command < 0 ? INT32_MAX : command; }\n\ntemplate <typename Arch>\nstatic Switchable prepare_ptrace(RecordTask* t,\n                                 TaskSyscallState& syscall_state) {\n  pid_t tid = (pid_t)t->regs().arg2_signed();\n  bool emulate = true;\n  int command = (int)t->regs().arg1_signed();\n  switch (non_negative_command(command)) {\n    case PTRACE_ATTACH: {\n      RecordTask* tracee = prepare_ptrace_attach(t, tid, syscall_state);\n      if (!tracee) {\n        break;\n      }\n      tracee->set_emulated_ptracer(t);\n      tracee->emulated_ptrace_seized = false;\n      tracee->emulated_ptrace_options = 0;\n      syscall_state.emulate_result(0);\n      if (tracee->emulated_stop_type == NOT_STOPPED) {\n        // Send SIGSTOP to this specific thread. Otherwise the kernel might\n        // deliver SIGSTOP to some other thread of the process, and we won't\n        // generate any ptrace event if that thread isn't being ptraced.\n        tracee->tgkill(SIGSTOP);\n      } else {\n        ptrace_attach_to_already_stopped_task(tracee);\n      }\n      break;\n    }\n    case PTRACE_TRACEME: {\n      RecordTask* tracer = prepare_ptrace_traceme(t, syscall_state);\n      if (!tracer) {\n        break;\n      }\n      t->set_emulated_ptracer(tracer);\n      t->emulated_ptrace_seized = false;\n      t->emulated_ptrace_options = 0;\n      syscall_state.emulate_result(0);\n      break;\n    }\n    case PTRACE_SEIZE: {\n      RecordTask* tracee = prepare_ptrace_attach(t, tid, syscall_state);\n      if (!tracee) {\n        break;\n      }\n      if (t->regs().arg3()) {\n        syscall_state.emulate_result(-EIO);\n        break;\n      }\n      if (!verify_ptrace_options(t, syscall_state)) {\n        break;\n      }\n      tracee->set_emulated_ptracer(t);\n      tracee->emulated_ptrace_seized = true;\n      tracee->emulated_ptrace_options = (int)t->regs().arg4();\n      if (tracee->emulated_stop_type == GROUP_STOP) {\n        ptrace_attach_to_already_stopped_task(tracee);\n      }\n      syscall_state.emulate_result(0);\n      break;\n    }\n    case Arch::PTRACE_OLDSETOPTIONS:\n      RR_FALLTHROUGH;\n    case PTRACE_SETOPTIONS: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        if (!verify_ptrace_options(t, syscall_state)) {\n          break;\n        }\n        tracee->emulated_ptrace_options = (int)t->regs().arg4();\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case PTRACE_GETEVENTMSG: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        auto datap =\n            syscall_state.reg_parameter<typename Arch::unsigned_long>(4);\n        t->write_mem(\n            datap,\n            (typename Arch::unsigned_long)tracee->emulated_ptrace_event_msg);\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case PTRACE_GETSIGINFO: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        auto datap = syscall_state.reg_parameter<typename Arch::siginfo_t>(4);\n        typename Arch::siginfo_t dest;\n        memset(&dest, 0, sizeof(dest));\n        set_arch_siginfo(tracee->get_saved_ptrace_siginfo(), Arch::arch(),\n                         &dest, sizeof(dest));\n        t->write_mem(datap, dest);\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case PTRACE_GETREGSET: {\n      switch ((int)t->regs().arg3()) {\n        case NT_PRSTATUS: {\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            auto regs = tracee->regs().get_ptrace_for_arch(tracee->arch());\n            ptrace_get_reg_set<Arch>(t, syscall_state, regs);\n          }\n          break;\n        }\n        case NT_PRFPREG: {\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            if (auto extra_regs = tracee->extra_regs_fallible()) {\n              auto regs =\n                  extra_regs->get_user_fpregs_struct(tracee->arch());\n              ptrace_get_reg_set<Arch>(t, syscall_state, regs);\n            } else {\n              syscall_state.emulate_result(-ESRCH);\n            }\n          }\n          break;\n        }\n        case NT_ARM_SYSTEM_CALL: {\n          if (Arch::arch() != aarch64) {\n            syscall_state.expect_errno = EINVAL;\n            emulate = false;\n            break;\n          }\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            int syscallno = tracee->regs().original_syscallno();\n            uint8_t *data = (uint8_t*)&syscallno;\n            vector<uint8_t> regs(data, data+sizeof(syscallno));\n            ptrace_get_reg_set<Arch>(t, syscall_state, regs);\n          }\n          break;\n        }\n        case NT_ARM_HW_BREAK:\n        case NT_ARM_HW_WATCH: {\n          if (Arch::arch() != aarch64) {\n            syscall_state.expect_errno = EINVAL;\n            emulate = false;\n            break;\n          }\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            ARM64Arch::user_hwdebug_state bps;\n            bool ok = tracee->get_aarch64_debug_regs((int)t->regs().arg3(), &bps);\n            ASSERT(tracee, ok);\n            uint8_t *data = (uint8_t*)&bps;\n            vector<uint8_t> regs(data, data+sizeof(bps));\n            ptrace_get_reg_set<Arch>(t, syscall_state, regs);\n          }\n          break;\n        }\n        case NT_X86_XSTATE: {\n          if (!Arch::is_x86ish()) {\n            syscall_state.expect_errno = EINVAL;\n            emulate = false;\n            break;\n          }\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            if (auto extra_regs = tracee->extra_regs_fallible()) {\n              switch (extra_regs->format()) {\n                case ExtraRegisters::XSAVE:\n                  ptrace_get_reg_set<Arch>(t, syscall_state, extra_regs->data());\n                  break;\n                default:\n                  syscall_state.emulate_result(-EINVAL);\n                  break;\n              }\n            } else {\n              syscall_state.emulate_result(-ESRCH);\n            }\n          }\n          break;\n        }\n        default:\n          syscall_state.expect_errno = EINVAL;\n          emulate = false;\n          break;\n      }\n      break;\n    }\n    case PTRACE_SETREGSET: {\n      // The actual register effects are performed by\n      // Task::on_syscall_exit_arch\n      switch ((int)t->regs().arg3()) {\n        case NT_PRSTATUS: {\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            ptrace_verify_set_reg_set<Arch>(\n                t, user_regs_struct_size(tracee->arch()), syscall_state);\n          }\n          break;\n        }\n        case NT_PRFPREG: {\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            ptrace_verify_set_reg_set<Arch>(\n                t, user_fpregs_struct_size(tracee->arch()), syscall_state);\n          }\n          break;\n        }\n        case NT_ARM_SYSTEM_CALL: {\n          if (Arch::arch() != aarch64) {\n            syscall_state.expect_errno = EINVAL;\n            emulate = false;\n            break;\n          }\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            ptrace_verify_set_reg_set<Arch>(\n                t, sizeof(int), syscall_state);\n          }\n          break;\n        }\n        case NT_ARM_HW_WATCH:\n        case NT_ARM_HW_BREAK: {\n          if (Arch::arch() != aarch64) {\n            syscall_state.expect_errno = EINVAL;\n            emulate = false;\n            break;\n          }\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            ptrace_verify_set_reg_set<Arch>(\n                t, offsetof(ARM64Arch::user_hwdebug_state, dbg_regs[0]),\n                syscall_state);\n          }\n          break;\n        }\n        case NT_X86_XSTATE: {\n          if (!Arch::is_x86ish()) {\n            syscall_state.expect_errno = EINVAL;\n            emulate = false;\n            break;\n          }\n          RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n          if (tracee) {\n            if (auto extra_regs = tracee->extra_regs_fallible()) {\n              switch (extra_regs->format()) {\n                case ExtraRegisters::XSAVE:\n                  ptrace_verify_set_reg_set<Arch>(\n                      t, extra_regs->data_size(), syscall_state);\n                  break;\n                default:\n                  syscall_state.emulate_result(-EINVAL);\n                  break;\n              }\n            } else {\n              syscall_state.emulate_result(-ESRCH);\n            }\n          }\n          break;\n        }\n        default:\n          syscall_state.expect_errno = EINVAL;\n          emulate = false;\n          break;\n      }\n      break;\n    }\n    case PTRACE_SYSCALL:\n    case PTRACE_SINGLESTEP:\n    case Arch::PTRACE_SYSEMU:\n    case Arch::PTRACE_SYSEMU_SINGLESTEP:\n    case PTRACE_CONT: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      // If the tracer wants to observe syscall entries, we can't use the\n      // syscallbuf, because the tracer may want to change syscall numbers\n      // which the syscallbuf code is not prepared to handle. Additionally,\n      // we also lock the syscallbuf for PTRACE_SINGLESTEP, since we usually\n      // try to avoid delivering signals (e.g. PTRACE_SINGLESTEP's SIGTRAP)\n      // inside syscallbuf code. However, if the syscallbuf if locked, doing\n      // so should be safe.\n      if (tracee) {\n        if (!((unsigned int)t->regs().arg4() < _NSIG)) {\n          // Invalid signals in ptrace resume cause EIO\n          syscall_state.emulate_result(-EIO);\n          break;\n        }\n        tracee->set_syscallbuf_locked(command != PTRACE_CONT);\n        prepare_ptrace_cont(tracee, t->regs().arg4(), command);\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case PTRACE_DETACH: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        tracee->set_syscallbuf_locked(0);\n        tracee->emulated_ptrace_options = 0;\n        tracee->emulated_ptrace_cont_command = 0;\n        tracee->emulated_stop_pending = false;\n        prepare_ptrace_cont(tracee, t->regs().arg4(), 0);\n        tracee->set_emulated_ptracer(nullptr);\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case PTRACE_KILL: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        tracee->kill_if_alive();\n        syscall_state.emulate_result(0);\n      }\n      break;\n    }\n    case PTRACE_INTERRUPT: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid, false);\n      if (tracee) {\n        uint64_t result = 0;\n        if (!tracee->is_stopped()) {\n          // Running in a blocked syscall. Forward the PTRACE_INTERRUPT.\n          // Regular syscall exit handling will take over from here.\n          LOG(debug) << \"Interrupting \" << tracee->tid;\n          errno = 0;\n          tracee->fallible_ptrace(PTRACE_INTERRUPT, nullptr, nullptr);\n          result = -errno;\n          // Technically PTRACE_INTERRUPT stops are distinct from group stops,\n          // but not in any way we currently care about.\n          // NB: Despite the ptrace man page claiming the kernel sends SIGTRAP\n          // in practice it actually sends SIGSTOP.\n          tracee->apply_group_stop(SIGSTOP);\n        } else if (tracee->status().is_syscall()) {\n          tracee->emulate_ptrace_stop(tracee->status(), SYSCALL_EXIT_STOP);\n        } else if (tracee->emulated_stop_pending == NOT_STOPPED) {\n          // The tracee is stopped from our perspective, but not stopped from\n          // the perspective of the ptracer. Emulate a stop now.\n          tracee->apply_group_stop(SIGSTOP);\n        }\n        // Otherwise, there's nothing to do.\n        syscall_state.emulate_result(result);\n      }\n      break;\n    }\n    case PTRACE_GET_SYSCALL_INFO: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        remote_ptr<uint8_t> remote_addr(t->regs().arg4());\n        bool ok = true;\n        typename Arch::ptrace_syscall_info info;\n        memset(&info, 0, sizeof(info));\n        info.op =\n          tracee->emulated_stop_type == SYSCALL_ENTRY_STOP ? PTRACE_SYSCALL_INFO_ENTRY :\n          tracee->emulated_stop_type == SYSCALL_EXIT_STOP  ? PTRACE_SYSCALL_INFO_EXIT :\n          tracee->emulated_stop_type == SECCOMP_STOP       ? PTRACE_SYSCALL_INFO_SECCOMP :\n                                                             PTRACE_SYSCALL_INFO_NONE;\n        info.arch = to_audit_arch(tracee->arch());\n        info.instruction_pointer = tracee->ip().register_value();\n        info.stack_pointer = tracee->regs().sp().as_int();\n        size_t max_size = 0;\n        if (info.op == PTRACE_SYSCALL_INFO_ENTRY) {\n          info.entry.nr = tracee->regs().original_syscallno();\n          for (int i = 0; i < 6; ++i) {\n            info.entry.args[i] = tracee->regs().arg(i+1);\n          }\n          max_size = ((char*)&info.entry.args[6] - (char*)&info);\n        } else if (info.op == PTRACE_SYSCALL_INFO_EXIT) {\n          info.exit.rval = tracee->regs().syscall_result_signed();\n          info.exit.is_error = tracee->regs().syscall_result_signed() < 0;\n          max_size = ((char*)&info.exit.is_error - (char*)&info) + 1;\n        } else if (info.op == PTRACE_SYSCALL_INFO_SECCOMP) {\n          ASSERT(tracee, false) << \"Unimplemented: PTRACE_SYSCALL_INFO_SECCOMP\";\n        }\n        size_t user_size = t->regs().arg3();\n        size_t to_write = min(user_size, max_size);\n        t->write_mem(remote_addr, (uint8_t*)&info, to_write, &ok);\n        if (!ok) {\n          syscall_state.emulate_result(-EFAULT);\n          break;\n        }\n        t->record_local(remote_addr, (uint8_t*)&info, to_write);\n        syscall_state.emulate_result(max_size);\n      }\n      break;\n    }\n    case Arch::PTRACE_GET_THREAD_AREA:\n    case Arch::PTRACE_SET_THREAD_AREA: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        if (tracee->arch() != SupportedArch::x86) {\n          // This syscall should fail if the tracee is not x86\n          syscall_state.expect_errno = EIO;\n          emulate = false;\n          break;\n        }\n        remote_ptr<X86Arch::user_desc> remote_addr(t->regs().arg4());\n        bool ok = true;\n        struct X86Arch::user_desc desc;\n        memset(&desc, 0, sizeof(struct X86Arch::user_desc));\n        // Do the ptrace request ourselves\n        if (command == Arch::PTRACE_GET_THREAD_AREA) {\n          int ret = -tracee->emulate_get_thread_area(t->regs().arg3(), desc);\n          if (ret == 0) {\n            t->write_mem(remote_addr, desc, &ok);\n            if (!ok) {\n              syscall_state.emulate_result(-EFAULT);\n              break;\n            }\n            t->record_local(remote_addr, &desc);\n          }\n          syscall_state.emulate_result(ret);\n        } else {\n          desc = t->read_mem(remote_addr, &ok);\n          if (!ok) {\n            syscall_state.emulate_result(-EFAULT);\n            break;\n          }\n          syscall_state.emulate_result(\n              -tracee->emulate_set_thread_area((int)t->regs().arg3(), desc));\n        }\n      }\n      break;\n    }\n    case Arch::PTRACE_ARCH_PRCTL: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        if (tracee->arch() != SupportedArch::x86_64) {\n          // This syscall should fail if the tracee is not\n          // x86_64\n          syscall_state.expect_errno = EIO;\n          emulate = false;\n          break;\n        }\n        int code = (int)t->regs().arg4();\n        switch (code) {\n          case ARCH_GET_FS:\n          case ARCH_GET_GS: {\n            bool ok = true;\n            remote_ptr<uint64_t> addr(t->regs().arg3());\n            uint64_t data = code == ARCH_GET_FS ?\n                            tracee->regs().fs_base() : tracee->regs().gs_base();\n            t->write_mem(addr, data, &ok);\n            if (ok) {\n              t->record_local(addr, &data);\n              syscall_state.emulate_result(0);\n            } else {\n              syscall_state.emulate_result(-EIO);\n            }\n            break;\n          }\n          case ARCH_SET_FS:\n          case ARCH_SET_GS:\n            syscall_state.emulate_result(0);\n            break;\n          default:\n            syscall_state.emulate_result(-EINVAL);\n            break;\n        }\n      }\n      break;\n    }\n    case PTRACE_PEEKTEXT:\n    case PTRACE_PEEKDATA: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        // The actual syscall returns the data via the 'data' out-parameter.\n        // The behavior of returning the data as the system call result is\n        // provided by the glibc wrapper.\n        auto datap =\n            syscall_state.reg_parameter<typename Arch::unsigned_word>(4);\n        remote_ptr<typename Arch::unsigned_word> addr = t->regs().arg3();\n        bool ok = true;\n        auto v = tracee->read_mem(addr, &ok);\n        if (ok) {\n          t->write_mem(datap, v);\n          syscall_state.emulate_result(0);\n        } else {\n          syscall_state.emulate_result(-EIO);\n        }\n      }\n      break;\n    }\n    case PTRACE_POKETEXT:\n    case PTRACE_POKEDATA: {\n      RecordTask* tracee = verify_ptrace_target(t, syscall_state, tid);\n      if (tracee) {\n        remote_ptr<typename Arch::unsigned_word> addr = t->regs().arg3();\n        typename Arch::unsigned_word data = t->regs().arg4();\n        bool ok = true;\n        tracee->write_mem(addr, data, &ok);\n        if (ok) {\n          // Since we're recording data that might not be for |t|, we have to\n          // handle this specially during replay.\n          tracee->record_local(addr, &data);\n          syscall_state.emulate_result(0);\n        } else {\n          syscall_state.emulate_result(-EIO);\n        }\n      }\n      break;\n    }\n    case Arch::PTRACE_PEEKUSR:\n    case Arch::PTRACE_POKEUSR:\n    case Arch::PTRACE_GETREGS:\n    case Arch::PTRACE_GETFPREGS:\n    case Arch::PTRACE_GETFPXREGS:\n    case Arch::PTRACE_SETREGS:\n    case Arch::PTRACE_SETFPREGS:\n    case Arch::PTRACE_SETFPXREGS:\n      prepare_ptrace_legacy<Arch>(t, syscall_state);\n      break;\n    default:\n      syscall_state.expect_errno = EIO;\n      emulate = false;\n      break;\n  }\n  if (emulate) {\n    Registers r = t->regs();\n    r.set_arg1((intptr_t)-1);\n    t->set_regs(r);\n  }\n  return PREVENT_SWITCH;\n}\n\nstatic void check_signals_while_exiting(RecordTask* t) {\n  const RecordTask::StashedSignal* s = t->peek_stashed_sig_to_deliver();\n  if (s) {\n    // An unblockable signal (SIGKILL, SIGSTOP) might be received\n    // and stashed. Since these signals are unblockable they take\n    // effect no matter what and we don't need to deliver them to an exiting\n    // thread.\n    int sig = s->siginfo.si_signo;\n    ASSERT(t, sig == SIGKILL || sig == SIGSTOP)\n        << \"Got unexpected signal \" << s->siginfo\n        << \" (should have been blocked)\";\n  }\n}\n\nstatic bool send_signal_during_init_buffers() {\n  static bool send = getenv(\"RR_INIT_BUFFERS_SEND_SIGNAL\") != nullptr;\n  return send;\n}\n\n/**\n * At thread exit time, undo the work that init_buffers() did.\n *\n * Call this when the tracee has already entered SYS_exit/SYS_exit_group. The\n * tracee will be returned at a state in which it has entered (or\n * re-entered) SYS_exit/SYS_exit_group.\n */\nstatic void prepare_exit(RecordTask* t) {\n  // RecordSession is responsible for ensuring we don't get here with\n  // pending signals.\n  ASSERT(t, !t->has_stashed_sig());\n\n  t->stable_exit = true;\n  t->session().scheduler().in_stable_exit(t);\n\n  Registers r = t->regs();\n  Registers exit_regs = r;\n  SupportedArch arch = t->ev().Syscall().arch();\n  ASSERT(t,\n         is_exit_syscall(exit_regs.original_syscallno(), arch) ||\n             is_exit_group_syscall(exit_regs.original_syscallno(), arch))\n      << \"Tracee should have been at exit/exit_group, but instead at \"\n      << t->ev().Syscall().syscall_name();\n\n  // The first thing we need to do is to block all signals to prevent\n  // a signal being delivered to the thread (since it's going to exit and\n  // won't be able to handle any more signals).\n  //\n  // The tracee is at the entry to SYS_exit/SYS_exit_group, but hasn't started\n  // the call yet.  We can't directly start injecting syscalls\n  // because the tracee is still in the kernel.  And obviously,\n  // if we finish the SYS_exit/SYS_exit_group syscall, the tracee isn't around\n  // anymore.\n  //\n  // So hijack this SYS_exit call and rewrite it into a SYS_rt_sigprocmask.\n  r.set_original_syscallno(syscall_number_for_rt_sigprocmask(arch));\n  r.set_arg1(SIG_BLOCK);\n  r.set_arg2(AddressSpace::rr_page_record_ff_bytes());\n  r.set_arg3(0);\n  r.set_arg4(sizeof(sig_set_t));\n  t->set_regs(r);\n  // This exits the SYS_rt_sigprocmask.  Now the tracee is ready to do our\n  // bidding.\n  t->exit_syscall(arch);\n  check_signals_while_exiting(t);\n\n  // Do the actual buffer and fd cleanup.\n  t->destroy_buffers();\n\n  check_signals_while_exiting(t);\n\n  // Restore these regs to what they would have been just before\n  // the tracee trapped at SYS_exit/SYS_exit_group.  When we've finished\n  // cleanup, we'll restart the call.\n  exit_regs.set_syscallno(exit_regs.original_syscallno());\n  exit_regs.set_original_syscallno(-1);\n  exit_regs.set_ip(exit_regs.ip() - syscall_instruction_length(arch));\n  ASSERT(t, is_at_syscall_instruction(t, exit_regs.ip()))\n      << \"Tracee should have entered through int $0x80.\";\n  // Restart the SYS_exit call.\n  t->set_regs(exit_regs);\n  t->enter_syscall(arch);\n  check_signals_while_exiting(t);\n\n  if (t->emulated_ptrace_options & PTRACE_O_TRACEEXIT) {\n    t->emulate_ptrace_stop(WaitStatus::for_ptrace_event(PTRACE_EVENT_EXIT));\n  }\n}\n\nstatic void prepare_mmap_register_params(RecordTask* t) {\n  Registers r = t->regs();\n\n  FileMonitor* monitor = t->fd_table()->get_monitor(r.arg5_signed());\n  if (monitor) {\n    switch (monitor->type()) {\n      case FileMonitor::VirtualPerfCounter:\n      case FileMonitor::NonvirtualPerfCounter:\n        LOG(info) << \"Faking failure of mmap for perf event counter\";\n        // Force mmap to fail by setting fd to our tracee socket\n        r.set_arg5(t->session().tracee_fd_number());\n        t->set_regs(r);\n        return;\n      default:\n        break;\n    }\n  }\n\n  intptr_t mask_flag = MAP_FIXED | MAP_FIXED_NOREPLACE;\n#ifdef MAP_32BIT\n  mask_flag |= MAP_32BIT;\n#endif\n  int flags = r.arg4_signed() & ~MAP_GROWSDOWN;\n  if (t->enable_chaos_memory_allocations() && !(r.arg4_signed() & mask_flag)) {\n    // Not MAP_FIXED. Randomize the allocation address.\n    remote_ptr<void> hint = floor_page_size(r.arg1());\n    size_t orig_len = ceil_page_size(r.arg1() + r.arg2()) - hint.as_int();\n    size_t len = orig_len;\n    if (r.arg4_signed() & MAP_GROWSDOWN) {\n      // Ensure stacks can grow to the minimum size we choose\n      len = max<size_t>(AddressSpace::chaos_mode_min_stack_size(), len);\n    }\n    remote_ptr<void> addr = t->vm()->chaos_mode_find_free_memory(t, len, hint);\n    if (addr.is_null()) {\n      // force ENOMEM if other flags are valid\n      r.set_arg2(uintptr_t(1) << (word_size(t->arch())*8 - 1));\n      t->set_regs(r);\n      return;\n    }\n    r.set_arg1(addr + len - orig_len);\n    // Force the kernel to allocate at our hint address.\n    // AddressSpace::chaos_mode_find_free_memory() will have guaranteed\n    // that this mapping doesn't overlap any existing mapping.\n    // https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=efa7df3e3bb5da8e6abbe37727417f32a37fba47\n    // caused various kinds of rounding so our hint address is not always\n    // honoured without MAP_FIXED even when we ensure nothing is mapped\n    // overlapping that range.\n    flags |= MAP_FIXED;\n    LOG(debug) << \"Chaos mode selected address \" << HEX(r.arg1());\n  }\n  r.set_arg4(flags);\n  t->set_regs(r);\n}\n\nenum ScratchAddrType { FIXED_ADDRESS, DYNAMIC_ADDRESS };\n/* Pointer used when running RR in WINE. Memory below this address is\n   unmapped by WINE immediately after exec, so start the scratch buffer\n   here. */\nstatic const uintptr_t FIXED_SCRATCH_PTR = 0x68000000;\n\nstatic void init_scratch_memory(RecordTask* t,\n                                ScratchAddrType addr_type = DYNAMIC_ADDRESS) {\n  const int scratch_size = 512 * page_size();\n  size_t sz = scratch_size;\n  // The PROT_EXEC looks scary, and it is, but it's to prevent\n  // this region from being coalesced with another anonymous\n  // segment mapped just after this one.  If we named this\n  // segment, we could remove this hack.\n  int prot = PROT_READ | PROT_WRITE | PROT_EXEC;\n  int flags = MAP_PRIVATE | MAP_ANONYMOUS;\n  {\n    /* initialize the scratchpad for blocking system calls */\n    AutoRemoteSyscalls remote(t);\n\n    if (addr_type == DYNAMIC_ADDRESS) {\n      t->scratch_ptr = remote.infallible_mmap_syscall_if_alive(remote_ptr<void>(), sz,\n                                                               prot, flags, -1, 0);\n    } else {\n      t->scratch_ptr =\n          remote.infallible_mmap_syscall_if_alive(remote_ptr<void>(FIXED_SCRATCH_PTR),\n                                                  sz, prot, flags | MAP_FIXED, -1, 0);\n    }\n    t->scratch_size = scratch_size;\n  }\n\n  t->setup_preload_thread_locals();\n\n  // record this mmap for the replay\n  Registers r = t->regs();\n  uintptr_t saved_result = r.syscall_result();\n  r.set_syscall_result(t->scratch_ptr);\n  t->set_regs(r);\n\n  KernelMapping km =\n      t->vm()->map(t, t->scratch_ptr, sz, prot, flags, 0, string());\n  struct stat stat;\n  memset(&stat, 0, sizeof(stat));\n  auto record_in_trace = t->trace_writer().write_mapped_region(t,\n    km, stat, km.fsname(), vector<TraceRemoteFd>());\n  ASSERT(t, record_in_trace == TraceWriter::DONT_RECORD_IN_TRACE);\n\n  r.set_syscall_result(saved_result);\n  t->set_regs(r);\n}\n\nstatic int ptrace_option_for_event(int ptrace_event) {\n  switch (ptrace_event) {\n    case PTRACE_EVENT_FORK:\n      return PTRACE_O_TRACEFORK;\n    case PTRACE_EVENT_CLONE:\n      return PTRACE_O_TRACECLONE;\n    case PTRACE_EVENT_VFORK:\n      return PTRACE_O_TRACEVFORK;\n    default:\n      FATAL() << \"Unsupported ptrace event\";\n      return 0;\n  }\n}\n\ntemplate <typename Arch>\nstatic Switchable prepare_clone(RecordTask* t, TaskSyscallState& syscall_state) {\n  uintptr_t flags;\n  CloneParameters params;\n  Registers r = t->regs();\n  int original_syscall = r.original_syscallno();\n  int ptrace_event;\n  int termination_signal = SIGCHLD;\n\n  if (is_clone_syscall(original_syscall, Arch::arch())) {\n    params = extract_clone_parameters(t);\n    flags = r.arg1();\n    r.set_arg1(flags & ~uintptr_t(CLONE_UNTRACED));\n    t->set_regs(r);\n    termination_signal = flags & 0xff;\n    if (flags & CLONE_VFORK) {\n      ptrace_event = PTRACE_EVENT_VFORK;\n    } else if (termination_signal == SIGCHLD) {\n      ptrace_event = PTRACE_EVENT_FORK;\n    } else {\n      ptrace_event = PTRACE_EVENT_CLONE;\n    }\n  } else if (is_vfork_syscall(original_syscall, Arch::arch())) {\n    ptrace_event = PTRACE_EVENT_VFORK;\n    flags = CLONE_VM | CLONE_VFORK | SIGCHLD;\n  } else {\n    ptrace_event = PTRACE_EVENT_FORK;\n    flags = SIGCHLD;\n  }\n\n  while (true) {\n    if (!t->resume_execution(RESUME_SYSCALL, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS)) {\n      // Tracee died unexpectedly during clone.\n      return ALLOW_SWITCH;\n    }\n    // XXX handle stray signals?\n    if (t->ptrace_event()) {\n      break;\n    }\n    ASSERT(t, !t->stop_sig());\n    ASSERT(t, t->regs().syscall_result_signed() < 0);\n    if (!t->regs().syscall_may_restart()) {\n      LOG(debug) << \"clone failed, returning \"\n                 << errno_name(-t->regs().syscall_result_signed());\n      syscall_state.emulate_result(t->regs().syscall_result());\n      // clone failed and we're exiting the syscall with an error. Reenter\n      // the syscall so that we're in the same state as the normal execution\n      // path.\n      t->ev().Syscall().failed_during_preparation = true;\n      // Restore register we might have changed\n      r.set_arg1(syscall_state.syscall_entry_registers.arg1());\n      r.set_syscallno(Arch::gettid);\n      r.set_ip(r.ip().decrement_by_syscall_insn_length(Arch::arch()));\n      t->set_regs(r);\n      t->enter_syscall(Arch::arch());\n      r.set_ip(t->regs().ip());\n      r.set_syscallno(original_syscall);\n      r.set_original_syscallno(original_syscall);\n      t->set_regs(r);\n      t->canonicalize_regs(Arch::arch());\n      return ALLOW_SWITCH;\n    }\n    // Reenter the syscall. If we try to return an ERESTART* error using the\n    // code path above, our set_syscallno(SYS_gettid) fails to take effect and\n    // we actually do the clone, and things get horribly confused.\n    r.set_syscallno(r.original_syscallno());\n    r.set_ip(r.ip().decrement_by_syscall_insn_length(Arch::arch()));\n    t->set_regs(r);\n    t->enter_syscall(Arch::arch());\n  }\n\n  ASSERT(t, t->ptrace_event() == ptrace_event);\n\n  pid_t new_tid = t->get_ptrace_eventmsg_pid();\n  RecordTask* new_task = static_cast<RecordTask*>(\n      t->session().clone(t, clone_flags_to_task_flags(flags), params.stack,\n                         params.tls, params.ctid, new_tid));\n\n  // Restore modified registers in cloned task\n  Registers new_r = new_task->regs();\n  new_r.set_original_syscallno(\n      syscall_state.syscall_entry_registers.original_syscallno());\n  new_r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n  new_task->set_regs(new_r);\n  new_task->canonicalize_regs(Arch::arch());\n  new_task->set_termination_signal(termination_signal);\n  // If the task got killed right away, we need to treat this\n  // as if we are just finished a syscall\n  // so as not to trigger the logic in handle_ptrace_exit_event().\n  // Otherwise, we'll capture the current registers as if it's a syscall entry\n  // which would look like a clone/fork/vfork syscall on the dead thread.\n  // During replay, we'll see this ghost clone and would fail to find\n  // the resulting thread from the clone and crash.\n  new_task->ip_at_last_recorded_syscall_exit = new_r.ip();\n\n  /* record child id here */\n  if (is_clone_syscall(original_syscall, r.arch())) {\n    CloneParameters child_params = extract_clone_parameters(new_task);\n    t->record_remote_even_if_null(params.ptid);\n\n    if (Arch::clone_tls_type == Arch::UserDescPointer) {\n      t->record_remote_even_if_null(\n          params.tls.cast<typename Arch::user_desc>());\n      new_task->record_remote_even_if_null(\n          child_params.tls.cast<typename Arch::user_desc>());\n    } else {\n      DEBUG_ASSERT(Arch::clone_tls_type == Arch::PthreadStructurePointer);\n    }\n    new_task->record_remote_even_if_null(child_params.ptid);\n    new_task->record_remote_even_if_null(child_params.ctid);\n  }\n  t->session().trace_writer().write_task_event(TraceTaskEvent::for_clone(\n      new_task->tid, t->tid, new_task->own_namespace_rec_tid, flags));\n\n  init_scratch_memory(new_task);\n\n  Switchable switchable = (flags & CLONE_VFORK) ? ALLOW_SWITCH : PREVENT_SWITCH;\n  if ((t->emulated_ptrace_options & ptrace_option_for_event(ptrace_event)) &&\n      !(flags & CLONE_UNTRACED)) {\n    new_task->set_emulated_ptracer(t->emulated_ptracer);\n    new_task->emulated_ptrace_seized = t->emulated_ptrace_seized;\n    new_task->emulated_ptrace_options = t->emulated_ptrace_options;\n    t->emulated_ptrace_event_msg = new_task->rec_tid;\n    t->emulate_ptrace_stop(WaitStatus::for_ptrace_event(ptrace_event));\n    // ptrace(2) man page says that SIGSTOP is used here, but it's really\n    // SIGTRAP (in 4.4.4-301.fc23.x86_64 anyway).\n    new_task->apply_group_stop(SIGTRAP);\n    switchable = ALLOW_SWITCH;\n  }\n\n  // Restore our register modifications now, so that the emulated ptracer will\n  // see the original registers without our modifications if it inspects them\n  // in the ptrace event.\n  r = t->regs();\n  r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n  r.set_original_syscallno(\n      syscall_state.syscall_entry_registers.original_syscallno());\n  t->set_regs(r);\n  t->canonicalize_regs(Arch::arch());\n\n  // We're in a PTRACE_EVENT_FORK/VFORK/CLONE so the next PTRACE_SYSCALL for\n  // |t| will go to the exit of the syscall, as expected.\n\n  // For non-vfork cases, resume the cloning thread, not the new thread.\n  // In some applications the new thread must wait for the cloning thread to\n  // exit a critical section. Allowing the cloning thread to run reduces the\n  // likelihood that the new thread will have to block on that wait.\n  return switchable;\n}\n\nstatic bool protect_rr_sigs(RecordTask* t, remote_ptr<void> p, void* save) {\n  remote_ptr<sig_set_t> setp = p.cast<sig_set_t>();\n  if (setp.is_null()) {\n    return false;\n  }\n\n  auto sig_set = t->read_mem(setp);\n  auto new_sig_set = sig_set;\n  new_sig_set &= ~t->session().rr_signal_mask();\n  if (sig_set == new_sig_set) {\n    return false;\n  }\n\n  t->write_mem(setp, new_sig_set);\n  if (save) {\n    memcpy(save, &sig_set, sizeof(sig_set));\n  }\n\n  return true;\n}\n\ntemplate <typename Arch>\nstatic bool protect_rr_sigs_sa_mask_arch(RecordTask* t, remote_ptr<void> p,\n                                         void* save) {\n  remote_ptr<typename Arch::kernel_sigaction> sap =\n      p.cast<typename Arch::kernel_sigaction>();\n  if (sap.is_null()) {\n    return false;\n  }\n\n  auto sa = t->read_mem(sap);\n  auto new_sig_set = sa.sa_mask;\n  // Don't let the tracee block TIME_SLICE_SIGNAL or\n  // SYSCALLBUF_DESCHED_SIGNAL.\n  new_sig_set.__val[0] &= ~t->session().rr_signal_mask();\n\n  if (!memcmp(&sa.sa_mask, &new_sig_set, sizeof(new_sig_set))) {\n    return false;\n  }\n\n  if (save) {\n    memcpy(save, &sa, sizeof(sa));\n  }\n  sa.sa_mask = new_sig_set;\n  t->write_mem(sap, sa);\n\n  return true;\n}\n\nstatic bool protect_rr_sigs_sa_mask(RecordTask* t, remote_ptr<void> p,\n                                    void* save) {\n  RR_ARCH_FUNCTION(protect_rr_sigs_sa_mask_arch, t->arch(), t, p, save);\n}\n\nstatic void record_ranges(RecordTask* t,\n                          const vector<FileMonitor::Range>& ranges,\n                          size_t size) {\n  size_t s = size;\n  for (auto& r : ranges) {\n    size_t bytes = min(s, r.length);\n    if (bytes > 0) {\n      t->record_remote(r.data, bytes);\n      s -= bytes;\n    }\n  }\n}\n\nstatic pid_t do_detach_teleport(RecordTask *t)\n{\n  DiversionSession session(t->session().cpu_binding());\n  // Use the old task's exe path to make sure that /proc/<pid>/exe looks right\n  // for the teleported task.\n  std::string exe_path(t->proc_exe_path());\n  std::vector<std::string> argv, env;\n  ScopedFd error_fd;\n  int tracee_fd_number = t->session().tracee_fd_number();\n  Task *new_t = Task::spawn(session, error_fd, &session.tracee_socket_fd(),\n                  &session.tracee_socket_receiver_fd(),\n                  &tracee_fd_number,\n                  exe_path, argv, env,\n                  -1);\n  pid_t new_tid = new_t->tid;\n  LOG(debug) << \"Detached task with tid \" << new_tid;\n  session.on_create(new_t);\n  session.set_tracee_fd_number(tracee_fd_number);\n  new_t->os_exec(t->arch(), exe_path);\n  session.post_exec();\n  new_t->post_exec(exe_path);\n  new_t->post_exec_syscall(exe_path);\n  new_t->dup_from(t);\n  // Emulate the success of the syscall in the new task\n  Registers regs = new_t->regs();\n  regs.set_arg1(0);\n  new_t->set_regs(regs);\n  // Disable syscall buffering. XXX: We could also try to unpatch syscalls here\n  new_t->hpc.close();\n  new_t->set_in_diversion(true);\n  // Just clean up some additional state\n  new_t->reenable_cpuid_tsc();\n  {\n    AutoRemoteSyscalls remote(new_t, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);\n    remote.infallible_close_syscall_if_alive(tracee_fd_number);\n  }\n  t->vm()->monkeypatcher().unpatch_syscalls_in(new_t);\n  // Try to reset the scheduler affinity that we enforced upon the task.\n  // XXX: It would be nice to track what affinity the tracee requested and\n  // restore that.\n  // For now honor whatever affinity rr itself has (e.g. for running on P-cores\n  // on Alder Lake).\n  CPUs::get().restore_initial_affinity(new_t->tid);\n  // Task::spawn my lave the task in a group-stop if the task SIGSTOPs itself\n  // before we can PTRACE_SEIZE it. Kick it out of that group-stop now.\n  ::kill(new_tid, SIGCONT);\n  new_t->detach();\n  new_t->did_kill();\n  delete new_t;\n  return new_tid;\n}\n\ntemplate <typename Arch>\nstatic Switchable did_emulate_read(int syscallno, RecordTask* t,\n                                   const std::vector<FileMonitor::Range>& ranges,\n                                   uint64_t result,\n                                   TaskSyscallState& syscall_state)\n{\n  syscall_state.emulate_result(result);\n  record_ranges(t, ranges, result);\n  if (syscallno == Arch::pread64 || syscallno == Arch::preadv || result <= 0) {\n    // Don't perform this syscall.\n    Registers r = t->regs();\n    r.set_arg1(-1);\n    t->set_regs(r);\n  } else {\n    // Turn this into an lseek to emulate the advance of the fd ptr\n    Registers r = t->regs();\n    r.set_original_syscallno(Arch::lseek);\n    r.set_arg2(result);\n    r.set_arg3(SEEK_CUR);\n    t->set_regs(r);\n  }\n  return PREVENT_SWITCH;\n}\n\nstatic ParamSize select_param_size(intptr_t nfds, SupportedArch arch) {\n  nfds = (int)nfds;\n  size_t size = 0;\n  if (nfds > 0) {\n    size_t long_size = word_size(arch);\n    size = ((nfds + long_size*8 - 1)/(long_size*8))*long_size;\n  }\n  return ParamSize(size);\n}\n\ntemplate <typename Arch>\nstatic Switchable rec_prepare_syscall_arch(RecordTask* t,\n                                           TaskSyscallState& syscall_state,\n                                           const Registers& regs) {\n  int syscallno = t->ev().Syscall().number;\n\n  if (t->regs().original_syscallno() == SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO) {\n    // rr vetoed this syscall. Don't do any pre-processing.\n    return PREVENT_SWITCH;\n  }\n\n  syscall_state.syscall_entry_registers = regs;\n\n  if (t->desched_rec()) {\n    /* |t| was descheduled while in a buffered syscall.  We normally don't\n     * use scratch memory for the call, because the syscallbuf itself\n     * is serving that purpose. More importantly, we *can't* set up\n     * scratch for |t|, because it's already in the syscall. Instead, we will\n     * record the syscallbuf memory in rec_process_syscall_arch.\n     *\n     * However there is one case where we use scratch memory: when\n     * sys_read's block-cloning path is interrupted. In that case, record\n     * the scratch memory.\n     */\n    if (syscallno == Arch::read &&\n        remote_ptr<void>(regs.arg2()) == t->scratch_ptr) {\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                 (size_t)regs.arg3()),\n          IN_OUT_NO_SCRATCH);\n    }\n    return ALLOW_SWITCH;\n  }\n\n  if (syscallno < 0) {\n    // Invalid syscall. Don't let it accidentally match a\n    // syscall number below that's for an undefined syscall.\n    if (!Arch::is_x86ish()) {\n      // On architectures where arg1 is shared with the return value, the kernel\n      // may not set -ENOSYS for us. There, it instead copies the arg1 to the return\n      // value (frankly this is probably a bug, but likely nothing we can do\n      // about it).\n      Registers new_regs = regs;\n      new_regs.set_syscall_result(-ENOSYS);\n      t->set_regs(new_regs);\n    }\n    syscall_state.expect_errno = ENOSYS;\n    return PREVENT_SWITCH;\n  }\n\n  switch (syscallno) {\n// All the regular syscalls are handled here.\n#include \"SyscallRecordCase.generated\"\n\n    case Arch::splice: {\n      syscall_state.reg_parameter<loff_t>(2, IN_OUT);\n      syscall_state.reg_parameter<loff_t>(4, IN_OUT);\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::sendfile: {\n      syscall_state.reg_parameter<typename Arch::off_t>(3, IN_OUT);\n      return ALLOW_SWITCH;\n    }\n    case Arch::sendfile64: {\n      syscall_state.reg_parameter<typename Arch::off64_t>(3, IN_OUT);\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::capget: {\n      auto hdr = t->read_mem(\n          syscall_state.reg_parameter<typename Arch::__user_cap_header_struct>(\n              1, IN_OUT));\n      int struct_count;\n      switch (hdr.version) {\n        case _LINUX_CAPABILITY_VERSION_1:\n          struct_count = _LINUX_CAPABILITY_U32S_1;\n          break;\n        case _LINUX_CAPABILITY_VERSION_2:\n          struct_count = _LINUX_CAPABILITY_U32S_2;\n          break;\n        case _LINUX_CAPABILITY_VERSION_3:\n          struct_count = _LINUX_CAPABILITY_U32S_3;\n          break;\n        default:\n          struct_count = 0;\n          break;\n      }\n      if (struct_count > 0) {\n        syscall_state.reg_parameter(\n            2, sizeof(typename Arch::__user_cap_data_struct) * struct_count,\n            OUT);\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::vfork:\n    case Arch::fork:\n    case Arch::clone:\n      return prepare_clone<Arch>(t, syscall_state);\n\n    case Arch::exit:\n      prepare_exit(t);\n      return ALLOW_SWITCH;\n\n    case Arch::exit_group:\n      if (t->thread_group()->task_set().size() == 1) {\n        prepare_exit(t);\n        return ALLOW_SWITCH;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::execve:\n    case Arch::execveat: {\n      t->session().scheduler().did_enter_execve(t);\n      vector<string> cmd_line;\n      remote_ptr<typename Arch::unsigned_word> argv;\n      string raw_filename;\n      t->did_execveat = syscallno == Arch::execveat;\n      bool ok = true;\n      if (t->did_execveat) {\n        argv = regs.arg3();\n        raw_filename = t->read_c_str(regs.arg2(), &ok);\n      } else {\n        argv = regs.arg2();\n        raw_filename = t->read_c_str(regs.arg1(), &ok);\n      }\n      if (!ok) {\n        syscall_state.expect_errno = EFAULT;\n        return ALLOW_SWITCH;\n      }\n\n      while (true) {\n        auto p = t->read_mem(argv, &ok);\n        if (!ok) {\n          syscall_state.expect_errno = EFAULT;\n          return ALLOW_SWITCH;\n        }\n        if (!p) {\n          break;\n        }\n        cmd_line.push_back(t->read_c_str(p, &ok));\n        if (!ok) {\n          syscall_state.expect_errno = EFAULT;\n          return ALLOW_SWITCH;\n        }\n        argv++;\n      }\n\n      // Save the event. We can't record it here because the exec might fail.\n      syscall_state.exec_saved_event =\n          unique_ptr<TraceTaskEvent>(new TraceTaskEvent(\n              TraceTaskEvent::for_exec(t->tid, raw_filename, cmd_line)));\n\n      // This can trigger exits of non-main threads, so we have to\n      // allow them to be handled.\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::fcntl:\n    case Arch::fcntl64: {\n      int fd = regs.arg1();\n      uint64_t result;\n      if (t->fd_table()->emulate_fcntl(fd, t, &result)) {\n        // Don't perform this syscall.\n        Registers r = regs;\n        r.set_arg1(-1);\n        t->set_regs(r);\n        syscall_state.emulate_result(result);\n        return PREVENT_SWITCH;\n      }\n      switch ((int)regs.arg2_signed()) {\n        case Arch::DUPFD:\n        case Arch::DUPFD_CLOEXEC:\n        case Arch::GETFD:\n        case Arch::GETFL:\n        case Arch::SETFL:\n        case Arch::SETLK:\n        case Arch::SETLK64:\n        case Arch::OFD_SETLK:\n        case Arch::SETOWN:\n        case Arch::SETOWN_EX:\n        case Arch::GETSIG:\n        case Arch::SETSIG:\n        case Arch::NOTIFY:\n        case Arch::SETPIPE_SZ:\n        case Arch::GETPIPE_SZ:\n        case Arch::ADD_SEALS:\n        case Arch::GET_SEALS:\n        case Arch::SET_RW_HINT:\n        case Arch::SET_FILE_RW_HINT:\n        case Arch::SETLEASE:\n        case Arch::GETLEASE:\n          break;\n\n        case Arch::SETFD:\n          if (t->fd_table()->is_rr_fd(fd)) {\n            // Don't let tracee set FD_CLOEXEC on this fd. Disable the syscall,\n            // but emulate a successful return.\n            Registers r = regs;\n            r.set_arg1(-1);\n            t->set_regs(r);\n            syscall_state.emulate_result(0);\n          }\n          break;\n\n        case Arch::GETLK:\n          syscall_state.reg_parameter<typename Arch::_flock>(3, IN_OUT);\n          break;\n\n        case Arch::OFD_GETLK:\n        case Arch::GETLK64:\n          // flock and flock64 better be different on 32-bit architectures,\n          // but on 64-bit architectures, it's OK if they're the same.\n          static_assert(\n              sizeof(typename Arch::_flock) < sizeof(typename Arch::flock64) ||\n                  Arch::elfclass == ELFCLASS64,\n              \"struct flock64 not declared differently from struct flock\");\n          syscall_state.reg_parameter<typename Arch::flock64>(3, IN_OUT);\n          break;\n\n        case Arch::GETOWN_EX:\n          syscall_state.reg_parameter<typename Arch::f_owner_ex>(3);\n          break;\n\n        case Arch::SETLKW:\n        case Arch::SETLKW64:\n        case Arch::OFD_SETLKW:\n          // SETLKW blocks, but doesn't write any\n          // outparam data to the |struct flock|\n          // argument, so no need for scratch.\n          return ALLOW_SWITCH;\n\n        case Arch::GET_RW_HINT:\n        case Arch::GET_FILE_RW_HINT:\n          syscall_state.reg_parameter<int64_t>(3);\n          break;\n\n        default:\n          // Unknown command should trigger EINVAL.\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    /* futex parameters are in-out but they can't be moved to scratch\n     * addresses. */\n    case Arch::futex_time64:\n    case Arch::futex: {\n      int op = regs.arg2_signed();\n      switch (op & FUTEX_CMD_MASK) {\n        case FUTEX_WAIT:\n        case FUTEX_WAIT_BITSET:\n          return ALLOW_SWITCH;\n\n        case FUTEX_REQUEUE:\n        case FUTEX_CMP_REQUEUE:\n        case FUTEX_WAKE_OP:\n          syscall_state.reg_parameter<int>(5, IN_OUT_NO_SCRATCH);\n          break;\n\n        case FUTEX_WAKE:\n        case FUTEX_WAKE_BITSET:\n          break;\n\n        case FUTEX_LOCK_PI:\n        case FUTEX_UNLOCK_PI:\n        case FUTEX_TRYLOCK_PI:\n        case FUTEX_CMP_REQUEUE_PI:\n        case FUTEX_WAIT_REQUEUE_PI: {\n          Registers r = regs;\n          r.set_arg2(-1);\n          t->set_regs(r);\n          syscall_state.emulate_result(-ENOSYS);\n          break;\n        }\n\n        default:\n          syscall_state.expect_errno = ENOSYS;\n          break;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::getrandom:\n      syscall_state.reg_parameter(\n          1, ParamSize::from_syscall_result<int>((size_t)regs.arg2()));\n      return (GRND_NONBLOCK & regs.arg3()) ? PREVENT_SWITCH : ALLOW_SWITCH;\n\n    case Arch::get_thread_area:\n    case Arch::set_thread_area:\n      syscall_state.reg_parameter<typename Arch::user_desc>(1, IN_OUT);\n      return PREVENT_SWITCH;\n\n    case Arch::ipc:\n      switch ((int)regs.arg1_signed()) {\n        case MSGGET:\n        case SHMDT:\n        case SHMGET:\n        case SEMGET:\n          break;\n\n        case MSGCTL: {\n          int cmd = (int)regs.arg3_signed() & ~IPC_64;\n          return prepare_msgctl<Arch>(syscall_state, cmd, 5);\n        }\n\n        case MSGSND:\n        case SEMOP:\n        case SEMTIMEDOP:\n          return ALLOW_SWITCH;\n\n        case MSGRCV: {\n          size_t msgsize = regs.arg3();\n          auto kluge_args =\n              syscall_state.reg_parameter<typename Arch::ipc_kludge_args>(5,\n                                                                          IN);\n          syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(kluge_args, msgbuf),\n                                          sizeof(typename Arch::signed_long) +\n                                              msgsize);\n          return ALLOW_SWITCH;\n        }\n\n        case SHMAT: {\n          // Insane legacy feature: ipc SHMAT returns its pointer via an\n          // in-memory out parameter.\n          syscall_state.reg_parameter<typename Arch::unsigned_long>(4);\n          return PREVENT_SWITCH;\n        }\n\n        case SHMCTL: {\n          int cmd = (int)regs.arg3_signed() & ~IPC_64;\n          return prepare_shmctl<Arch>(syscall_state, cmd, 5);\n        }\n\n        case SEMCTL: {\n          int cmd = (int)regs.arg4_signed() & ~IPC_64;\n          return prepare_semctl<Arch>(t, syscall_state, (int)regs.arg2_signed(),\n                                      cmd, 5, DEREFERENCE);\n        }\n\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::msgctl:\n      return prepare_msgctl<Arch>(syscall_state, (int)regs.arg2_signed(), 3);\n\n    case Arch::msgrcv: {\n      size_t msgsize = regs.arg3();\n      syscall_state.reg_parameter(2,\n                                  sizeof(typename Arch::signed_long) + msgsize);\n      return ALLOW_SWITCH;\n    }\n\n    // Various syscalls that can block but don't otherwise have behavior we need\n    // to record.\n    case Arch::fdatasync:\n    case Arch::fsync:\n    case Arch::msgsnd:\n    case Arch::msync:\n    case Arch::open:\n    case Arch::openat:\n    case Arch::openat2:\n    case Arch::semop:\n    case Arch::semtimedop_time64:\n    case Arch::semtimedop:\n    case Arch::sync:\n    case Arch::sync_file_range:\n    case Arch::syncfs:\n      return ALLOW_SWITCH;\n\n    case Arch::sysfs: {\n      int option = regs.arg1();\n      switch (option) {\n        case 1:\n        case 3:\n          break;\n        case 2: {\n          remote_ptr<char> buf(regs.arg3());\n          // Assume no filesystem type name is more than 1K\n          char tmp[1024];\n          ssize_t bytes = t->read_bytes_fallible(buf, sizeof(tmp), tmp);\n          if (bytes > 0) {\n            syscall_state.reg_parameter(3, bytes);\n          }\n          break;\n        }\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::socketcall:\n      return prepare_socketcall<Arch>(t, syscall_state);\n\n    case Arch::select:\n    case Arch::_newselect:\n      if (syscallno == Arch::select &&\n          Arch::select_semantics == Arch::SelectStructArguments) {\n        auto argsp =\n            syscall_state.reg_parameter<typename Arch::select_args>(1, IN);\n        auto args = t->read_mem(argsp);\n        ParamSize size = select_param_size(args.n_fds, Arch::arch());\n        syscall_state.mem_ptr_parameter(\n            REMOTE_PTR_FIELD(argsp, read_fds), size, IN_OUT);\n        syscall_state.mem_ptr_parameter(\n            REMOTE_PTR_FIELD(argsp, write_fds), size, IN_OUT);\n        syscall_state.mem_ptr_parameter(\n            REMOTE_PTR_FIELD(argsp, except_fds), size, IN_OUT);\n        syscall_state.mem_ptr_parameter_inferred(\n            REMOTE_PTR_FIELD(argsp, timeout), IN_OUT);\n      } else {\n        ParamSize size = select_param_size(regs.arg1_signed(), Arch::arch());\n        syscall_state.reg_parameter(2, size, IN_OUT);\n        syscall_state.reg_parameter(3, size, IN_OUT);\n        syscall_state.reg_parameter(4, size, IN_OUT);\n        syscall_state.reg_parameter<typename Arch::timeval>(5, IN_OUT);\n      }\n      return ALLOW_SWITCH;\n\n    case Arch::pselect6_time64:\n    case Arch::pselect6: {\n      ParamSize size = select_param_size(regs.arg1_signed(), Arch::arch());\n      syscall_state.reg_parameter(2, size, IN_OUT);\n      syscall_state.reg_parameter(3, size, IN_OUT);\n      syscall_state.reg_parameter(4, size, IN_OUT);\n      if (syscallno == Arch::pselect6) {\n        syscall_state.reg_parameter<typename Arch::timespec>(5, IN_OUT);\n      } else {\n        syscall_state.reg_parameter<typename Arch::Arch64::timespec>(5, IN_OUT);\n      }\n      auto arg6p =\n          syscall_state.reg_parameter<typename Arch::pselect6_arg6>(6, IN);\n      syscall_state.mem_ptr_parameter_inferred(REMOTE_PTR_FIELD(arg6p, ss), IN,\n                                               protect_rr_sigs);\n      t->invalidate_sigmask();\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::recvfrom: {\n      syscall_state.reg_parameter(\n          2,\n          ParamSize::from_syscall_result<typename Arch::ssize_t>(regs.arg3()));\n      auto addrlen_ptr =\n          syscall_state.reg_parameter<typename Arch::socklen_t>(6, IN_OUT);\n      syscall_state.reg_parameter(\n          5, ParamSize::from_initialized_mem(t, addrlen_ptr));\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::recvmsg: {\n      auto msgp = syscall_state.reg_parameter<typename Arch::msghdr>(2, IN_OUT);\n      prepare_recvmsg<Arch>(\n          t, syscall_state, msgp,\n          ParamSize::from_syscall_result<typename Arch::ssize_t>());\n      if (!((int)regs.arg3() & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::recvmmsg_time64:\n    case Arch::recvmmsg: {\n      auto vlen = (unsigned int)regs.arg3();\n      auto mmsgp =\n          syscall_state\n              .reg_parameter(2, sizeof(typename Arch::mmsghdr) * vlen, IN_OUT)\n              .cast<typename Arch::mmsghdr>();\n      prepare_recvmmsg<Arch>(t, syscall_state, mmsgp, vlen);\n      if (!((unsigned int)regs.arg4() & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::sendto:\n      if (!((unsigned int)regs.arg4() & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::sendmsg:\n      if (!((unsigned int)regs.arg3() & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::sendmmsg: {\n      auto vlen = (unsigned int)regs.arg3();\n      syscall_state.reg_parameter(2, sizeof(typename Arch::mmsghdr) * vlen,\n                                  IN_OUT);\n      if (!((unsigned int)regs.arg4() & MSG_DONTWAIT)) {\n        return ALLOW_SWITCH;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::getsockname:\n    case Arch::getpeername: {\n      auto addrlen_ptr =\n          syscall_state.reg_parameter<typename Arch::socklen_t>(3, IN_OUT);\n      syscall_state.reg_parameter(\n          2, ParamSize::from_initialized_mem(t, addrlen_ptr));\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::setsockopt: {\n      typename Arch::setsockopt_args args;\n      args.sockfd = regs.arg1();\n      args.level = regs.arg2();\n      args.optname = regs.arg3();\n      args.optval = remote_ptr<void>(regs.arg4());\n      args.optlen = regs.arg5();\n      return prepare_setsockopt<Arch>(t, syscall_state, args);\n    }\n\n    case Arch::getsockopt: {\n      auto optlen_ptr =\n          syscall_state.reg_parameter<typename Arch::socklen_t>(5, IN_OUT);\n      syscall_state.reg_parameter(\n          4, ParamSize::from_initialized_mem(t, optlen_ptr));\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::pread64:\n    /* ssize_t read(int fd, void *buf, size_t count); */\n    case Arch::read: {\n      int fd = regs.arg1();\n      uint64_t result;\n      vector<FileMonitor::Range> ranges;\n      ranges.push_back(FileMonitor::Range(regs.arg2(), regs.arg3()));\n      FileMonitor::LazyOffset offset(t, regs, syscallno);\n      if (t->fd_table()->emulate_read(fd, t, ranges, offset, &result)) {\n        return did_emulate_read<Arch>(syscallno, t, ranges, result, syscall_state);\n      }\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                 (size_t)regs.arg3()));\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::accept:\n    case Arch::accept4: {\n      auto addrlen_ptr =\n          syscall_state.reg_parameter<typename Arch::socklen_t>(3, IN_OUT);\n      syscall_state.reg_parameter(\n          2, ParamSize::from_initialized_mem(t, addrlen_ptr));\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::getcwd:\n      syscall_state.reg_parameter(\n          1, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                 (size_t)regs.arg2()));\n      return PREVENT_SWITCH;\n\n    case Arch::getdents:\n    case Arch::getdents64:\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<int>((unsigned int)regs.arg3()));\n      return PREVENT_SWITCH;\n\n    case Arch::readlink:\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                 (size_t)regs.arg3()));\n      return PREVENT_SWITCH;\n\n    case Arch::readlinkat:\n      syscall_state.reg_parameter(\n          3, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                 (size_t)regs.arg4()));\n      return PREVENT_SWITCH;\n\n    case Arch::close_range:\n    case Arch::clone3:\n    case Arch::io_uring_setup:\n    case Arch::io_setup: {\n      // Prevent the various syscalls that we don't support from being used by\n      // applications and fake an ENOSYS return.\n      Registers r = regs;\n      r.set_arg2(0);\n      t->set_regs(r);\n      syscall_state.emulate_result(-ENOSYS);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::rseq: {\n      auto rseq = remote_ptr<typename Arch::rseq_t>(regs.arg1());\n      uint32_t rseq_len = regs.arg2();\n      int flags = regs.arg3();\n      uint32_t sig = regs.arg4();\n\n      // Clear size to ensure syscall fails.\n      Registers r = regs;\n      r.set_arg2(0);\n      t->set_regs(r);\n\n      if (flags & RR_RSEQ_FLAG_UNREGISTER) {\n        if ((flags & ~RR_RSEQ_FLAG_UNREGISTER) || !t->rseq_state ||\n            t->rseq_state->ptr != rseq || rseq_len != sizeof(typename Arch::rseq_t)) {\n          syscall_state.emulate_result(-EINVAL);\n        } else if (t->rseq_state->abort_prefix_signature != sig) {\n          syscall_state.emulate_result(-EPERM);\n        } else {\n          auto addr = REMOTE_PTR_FIELD(rseq, cpu_id);\n          uint32_t cpu_id = RR_RSEQ_CPU_ID_UNINITIALIZED;\n          t->write_mem(addr, cpu_id);\n          t->record_local(addr, &cpu_id);\n          addr = REMOTE_PTR_FIELD(rseq, cpu_id_start);\n          int cpu = t->session().trace_stream()->bound_to_cpu();\n          uint32_t cpu_id_start = cpu >= 0 ? cpu : 0;\n          t->write_mem(addr, cpu_id_start);\n          t->record_local(addr, &cpu_id_start);\n          t->rseq_state = nullptr;\n          syscall_state.emulate_result(0);\n        }\n        return PREVENT_SWITCH;\n      }\n\n      if (flags) {\n        syscall_state.emulate_result(-EINVAL);\n        return PREVENT_SWITCH;\n      }\n\n      if (t->rseq_state) {\n        if (t->rseq_state->ptr != rseq || rseq_len != sizeof(typename Arch::rseq_t)) {\n          syscall_state.emulate_result(-EINVAL);\n        } else if (t->rseq_state->abort_prefix_signature != sig) {\n          syscall_state.emulate_result(-EPERM);\n        } else {\n          syscall_state.emulate_result(-EBUSY);\n        }\n        return PREVENT_SWITCH;\n      }\n\n      if ((rseq.as_int() & 31) || rseq_len != sizeof(typename Arch::rseq_t)) {\n        syscall_state.emulate_result(-EINVAL);\n        return PREVENT_SWITCH;\n      }\n\n      t->rseq_state = make_unique<RseqState>(rseq, sig);\n      ASSERT(t, t->session().trace_writer().bound_to_cpu() >= 0) << \"rseq not supported with unbound tasks\";\n      uint32_t cpu_id = t->session().trace_writer().bound_to_cpu();\n      auto addr = REMOTE_PTR_FIELD(rseq, cpu_id);\n      // We can only support rseq when the tracee is bound to a specific CPU. otherwise cpu_id_start\n      // and cpu_id fields would need to be managed by rr and would not match reality.\n      t->write_mem(addr, cpu_id);\n      t->record_local(addr, &cpu_id);\n      addr = REMOTE_PTR_FIELD(rseq, cpu_id_start);\n      t->write_mem(addr, cpu_id);\n      t->record_local(addr, &cpu_id);\n\n      auto remote_locals = AddressSpace::preload_thread_locals_start()\n        .cast<preload_thread_locals<Arch>>();\n      if (remote_locals) {\n        auto rseq_called_ptr = REMOTE_PTR_FIELD(remote_locals, rseq_called);\n        int32_t rseq_called = 1;\n        t->write_mem(rseq_called_ptr, rseq_called);\n        t->record_local(rseq_called_ptr, &rseq_called);\n      }\n\n      syscall_state.emulate_result(0);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::userfaultfd: {\n      // Pretend the kernel doesn't support this.\n      Registers r = regs;\n      r.set_arg1(0xffffffff);\n      t->set_regs(r);\n      syscall_state.emulate_result(-ENOSYS);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::memfd_create: {\n      bool ok = true;\n      string name = t->read_c_str(remote_ptr<char>(regs.arg1()), &ok);\n      if (!ok) {\n        syscall_state.expect_errno = EFAULT;\n      } else if (is_blacklisted_memfd(name.c_str())) {\n        LOG(warn) << \"Cowardly refusing to memfd_create \" << name;\n        Registers r = regs;\n        r.set_arg1(0);\n        t->set_regs(r);\n        syscall_state.emulate_result(-ENOSYS);\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::getgroups:\n      // We could record a little less data by restricting the recorded data\n      // to the syscall result * sizeof(Arch::legacy_gid_t), but that would\n      // require more infrastructure and it's not worth worrying about.\n      syscall_state.reg_parameter(\n          2, (int)regs.arg1_signed() * sizeof(typename Arch::legacy_gid_t));\n      return PREVENT_SWITCH;\n\n    case Arch::getgroups32:\n      // We could record a little less data by restricting the recorded data\n      // to the syscall result * sizeof(Arch::gid_t), but that would\n      // require more infrastructure and it's not worth worrying about.\n      syscall_state.reg_parameter(\n          2, (int)regs.arg1_signed() * sizeof(typename Arch::gid_t));\n      return PREVENT_SWITCH;\n\n    case Arch::write:\n    case Arch::writev: {\n      int fd = (int)regs.arg1_signed();\n      return t->fd_table()->will_write(t, fd);\n    }\n\n    case Arch::copy_file_range: {\n      syscall_state.reg_parameter<typename Arch::loff_t>(2, IN_OUT);\n      syscall_state.reg_parameter<typename Arch::loff_t>(4, IN_OUT);\n      int in_fd = (int)regs.arg1_signed();\n      int out_fd = (int)regs.arg3_signed();\n      ASSERT(t, !t->fd_table()->is_monitoring(in_fd) &&\n             !t->fd_table()->is_monitoring(out_fd))\n             << \"copy_file_range for monitored fds not supported yet\";\n      return ALLOW_SWITCH;\n    }\n\n    /* ssize_t readv(int fd, const struct iovec *iov, int iovcnt); */\n    case Arch::readv:\n    /* ssize_t preadv(int fd, const struct iovec *iov, int iovcnt,\n                      off_t offset); */\n    case Arch::preadv: {\n      int fd = (int)regs.arg1_signed();\n      int iovcnt = (int)regs.arg3_signed();\n      remote_ptr<void> iovecsp_void = syscall_state.reg_parameter(\n          2, sizeof(typename Arch::iovec) * iovcnt, IN);\n      auto iovecsp = iovecsp_void.cast<typename Arch::iovec>();\n      auto iovecs = t->read_mem(iovecsp, iovcnt);\n      uint64_t result;\n      vector<FileMonitor::Range> ranges;\n      ranges.reserve(iovcnt);\n      for (int i = 0; i < iovcnt; ++i) {\n        ranges.push_back(\n            FileMonitor::Range(iovecs[i].iov_base, iovecs[i].iov_len));\n      }\n      FileMonitor::LazyOffset offset(t, regs, syscallno);\n      if (t->fd_table()->emulate_read(fd, t, ranges, offset, &result)) {\n        return did_emulate_read<Arch>(syscallno, t, ranges, result, syscall_state);\n      }\n      ParamSize io_size =\n          ParamSize::from_syscall_result<typename Arch::ssize_t>();\n      for (int i = 0; i < iovcnt; ++i) {\n        syscall_state.mem_ptr_parameter(REMOTE_PTR_FIELD(iovecsp + i, iov_base),\n                                        io_size.limit_size(iovecs[i].iov_len));\n      }\n      return ALLOW_SWITCH;\n    }\n\n    /* pid_t waitpid(pid_t pid, int *status, int options); */\n    /* pid_t wait4(pid_t pid, int *status, int options, struct rusage\n     * *rusage);\n     */\n    case Arch::waitpid:\n    case Arch::wait4: {\n      Switchable should_switch = ALLOW_SWITCH;\n      pid_t pid = (pid_t)regs.arg1_signed();\n      if (pid < -1) {\n        t->in_wait_type = WAIT_TYPE_PGID;\n        t->in_wait_pid = -pid;\n      } else if (pid == -1) {\n        t->in_wait_type = WAIT_TYPE_ANY;\n      } else if (pid == 0) {\n        t->in_wait_type = WAIT_TYPE_SAME_PGID;\n      } else {\n        t->in_wait_type = WAIT_TYPE_PID;\n        t->in_wait_pid = pid;\n      }\n      t->in_wait_options = (int)regs.arg3();\n      if (maybe_emulate_wait(t, syscall_state)) {\n        Registers r = regs;\n        // Set options to an invalid value to force syscall to fail\n        r.set_arg3(0xffffffff);\n        t->set_regs(r);\n        should_switch = PREVENT_SWITCH;\n      } else {\n        maybe_pause_instead_of_waiting(t);\n      }\n      // We may modify emulated parameters so to make things\n      // simple, don't use scratch.\n      syscall_state.reg_parameter<int>(2, IN_OUT_NO_SCRATCH);\n      if (syscallno == Arch::wait4) {\n        syscall_state.reg_parameter<typename Arch::rusage>(4,\n            IN_OUT_NO_SCRATCH);\n      }\n      return should_switch;\n    }\n\n    case Arch::waitid: {\n      id_t wait_pid = (id_t)regs.arg2();\n      switch ((uint32_t)regs.arg1()) {\n        case P_ALL:\n          t->in_wait_type = WAIT_TYPE_ANY;\n          break;\n        case P_PID:\n          t->in_wait_type = WAIT_TYPE_PID;\n          break;\n        case P_PGID:\n          t->in_wait_type = WAIT_TYPE_PGID;\n          break;\n        case P_PIDFD:\n          wait_pid = t->pid_of_pidfd(regs.arg2());\n          if (!t->session().find_task(wait_pid)) {\n            // Waiting on a non-tracee; just let it happen as normal\n            // We also take this path if pid_of_pidfd returns -1\n            // because the fd is not a pidfd.\n            syscall_state.reg_parameter<typename Arch::siginfo_t>(3);\n            return ALLOW_SWITCH;\n          }\n          t->in_wait_type = WAIT_TYPE_PID;\n          break;\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      Switchable should_switch = ALLOW_SWITCH;\n      t->in_wait_pid = wait_pid;\n      t->in_wait_options = (int)regs.arg4();\n      if (maybe_emulate_wait(t, syscall_state)) {\n        Registers r = regs;\n        // Set options to an invalid value to force syscall to fail\n        r.set_arg4(0xffffffff);\n        t->set_regs(r);\n        should_switch = PREVENT_SWITCH;\n      } else {\n        maybe_pause_instead_of_waiting(t);\n      }\n      // We may modify emulated *infop so to make things\n      // simple, don't use scratch.\n      syscall_state.reg_parameter<typename Arch::siginfo_t>(3, IN_OUT_NO_SCRATCH);\n      return should_switch;\n    }\n\n    case Arch::setpriority:\n      // The syscall might fail due to insufficient\n      // permissions (e.g. while trying to decrease the nice value\n      // while not root).\n      // We'll choose to honor the new value anyway since we'd like\n      // to be able to test configurations where a child thread\n      // has a lower nice value than its parent, which requires\n      // lowering the child's nice value.\n      if ((int)regs.arg1_signed() == PRIO_PROCESS) {\n        RecordTask* target =\n            (int)regs.arg2_signed()\n                ? t->session().find_task((int)regs.arg2_signed())\n                : t;\n        if (target) {\n          LOG(debug) << \"Setting nice value for tid \" << t->tid << \" to \"\n                     << regs.arg3();\n          target->session().scheduler().update_task_priority(\n              target, (int)regs.arg3_signed());\n        }\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::pause:\n      return ALLOW_SWITCH;\n\n    case Arch::ppoll_time64:\n    case Arch::ppoll:\n      /* The raw syscall modifies this with the time remaining. The libc\n         does not expose this functionality however */\n      if (syscallno == Arch::ppoll) {\n        syscall_state.reg_parameter<typename Arch::timespec>(3, IN_OUT);\n      } else {\n        syscall_state.reg_parameter<typename Arch::Arch64::timespec>(3, IN_OUT);\n      }\n      syscall_state.reg_parameter<typename Arch::kernel_sigset_t>(\n          4, IN, protect_rr_sigs);\n      t->invalidate_sigmask();\n      RR_FALLTHROUGH;\n    case Arch::poll: {\n      auto nfds = (nfds_t)regs.arg2();\n      syscall_state.reg_parameter(1, sizeof(typename Arch::pollfd) * nfds,\n                                  IN_OUT);\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::perf_event_open: {\n      RecordTask* target = t->session().find_task((pid_t)regs.arg2_signed());\n      int cpu = regs.arg3_signed();\n      unsigned long flags = regs.arg5();\n      int allowed_perf_flags = PERF_FLAG_FD_CLOEXEC;\n      if (target && cpu == -1 && !(flags & ~allowed_perf_flags)) {\n        auto attr =\n            t->read_mem(remote_ptr<struct perf_event_attr>(regs.arg1()));\n        if (VirtualPerfCounterMonitor::should_virtualize(attr)) {\n          Registers r = regs;\n          // Turn this into an inotify_init() syscall. This just gives us an\n          // allocated fd. Syscalls using this fd will be emulated (except for\n          // close()).\n          r.set_original_syscallno(Arch::inotify_init1);\n          int in_flags = (flags & PERF_FLAG_FD_CLOEXEC) ? O_CLOEXEC : 0;\n          r.set_arg1(in_flags);\n          t->set_regs(r);\n        }\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::connect:\n      return maybe_blacklist_connect<Arch>(t, regs.arg2(), regs.arg3());\n\n    case Arch::close:\n      if (t->fd_table()->is_rr_fd((int)regs.arg1())) {\n        // Don't let processes close this fd. Abort with EBADF by setting\n        // oldfd to -1, as if the fd is already closed.\n        Registers r = regs;\n        r.set_arg1(intptr_t(-1));\n        t->set_regs(r);\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::dup2:\n    case Arch::dup3:\n      if (t->fd_table()->is_rr_fd((int)regs.arg2())) {\n        // Don't let processes dup over this fd. Abort with EBADF by setting\n        // oldfd to -1.\n        Registers r = regs;\n        r.set_arg1(intptr_t(-1));\n        t->set_regs(r);\n      }\n      return PREVENT_SWITCH;\n\n    /* int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned\n     * long arg4, unsigned long arg5); */\n    case Arch::prctl:\n      switch ((int)regs.arg1_signed()) {\n        case PR_GET_CHILD_SUBREAPER:\n        case PR_GET_ENDIAN:\n        case PR_GET_FPEMU:\n        case PR_GET_FPEXC:\n        case PR_GET_PDEATHSIG:\n        case PR_GET_UNALIGN:\n          syscall_state.reg_parameter<int>(2);\n          break;\n\n        case PR_GET_KEEPCAPS:\n        case PR_GET_NO_NEW_PRIVS:\n        case PR_GET_TIMERSLACK:\n        case PR_MCE_KILL:\n        case PR_MCE_KILL_GET:\n        case PR_SET_CHILD_SUBREAPER:\n        case PR_SET_KEEPCAPS:\n        case PR_SET_NAME:\n        case PR_SET_PDEATHSIG:\n        case PR_SET_TIMERSLACK:\n        case PR_CAP_AMBIENT:\n        case PR_CAPBSET_DROP:\n        case PR_CAPBSET_READ:\n        case PR_GET_SPECULATION_CTRL:\n        case PR_SET_SPECULATION_CTRL:\n        case PR_GET_THP_DISABLE:\n        case PR_SET_THP_DISABLE:\n        case PR_SET_SECUREBITS:\n        case PR_GET_SECUREBITS:\n        case PR_GET_TAGGED_ADDR_CTRL:\n        case PR_GET_MDWE:\n          break;\n\n        case PR_SET_TAGGED_ADDR_CTRL:\n          if (regs.arg2() & ~PR_TAGGED_ADDR_ENABLE) {\n            // For now we only support enabling the tagged address ABI which\n            // only affects the semantics of syscalls. We don't support setting\n            // any of the MTE-related bits because they affect the semantics of\n            // normal load/store instructions (implying replay is required) as\n            // well as exposing non-determinism in the following ways:\n            // 1) With a non-empty tag inclusion mask, the tag computed by the\n            //    IRG instruction will be effectively random.\n            // 2) It is indeterminate when a SIGSEGV/SEGV_MTEAERR signal will\n            //    be raised if an asynchronous tag check fault is taken.\n            // Both of these issues should be fixable with some kernel changes.\n            syscall_state.emulate_result(-EINVAL);\n          }\n          break;\n\n        case PR_SET_DUMPABLE:\n          if (regs.arg2() == 0) {\n            // Don't let processes make themselves undumpable. If a process\n            // becomes undumpable, calling perf_event_open on it fails.\n            Registers r = regs;\n            r.set_arg1(intptr_t(-1));\n            t->set_regs(r);\n            syscall_state.emulate_result(0);\n            t->thread_group()->dumpable = false;\n          } else if (regs.arg2() == 1) {\n            t->thread_group()->dumpable = true;\n          }\n          break;\n\n        case PR_GET_DUMPABLE:\n          syscall_state.emulate_result(t->thread_group()->dumpable);\n          break;\n\n        case PR_GET_SECCOMP:\n          syscall_state.emulate_result(t->prctl_seccomp_status);\n          break;\n\n        case PR_GET_TSC: {\n          // Prevent the actual GET_TSC call and return our emulated state.\n          Registers r = regs;\n          r.set_arg1(intptr_t(-1));\n          t->set_regs(r);\n          syscall_state.emulate_result(0);\n          t->write_mem(syscall_state.reg_parameter<int>(2, IN_OUT_NO_SCRATCH),\n                       t->tsc_mode);\n          break;\n        }\n\n        case PR_SET_TSC: {\n          // Prevent the actual SET_TSC call.\n          Registers r = regs;\n          r.set_arg1(intptr_t(-1));\n          t->set_regs(r);\n          int val = (int)regs.arg2();\n          if (val != PR_TSC_ENABLE && val != PR_TSC_SIGSEGV) {\n            syscall_state.emulate_result(-EINVAL);\n          } else {\n            syscall_state.emulate_result(0);\n            t->tsc_mode = val;\n          }\n          break;\n        }\n\n        case PR_GET_NAME:\n          syscall_state.reg_parameter(2, 16);\n          break;\n\n        case PR_SET_NO_NEW_PRIVS:\n          if ((unsigned long)regs.arg2() != 1) {\n            syscall_state.expect_errno = EINVAL;\n          }\n          break;\n\n        case PR_SET_SECCOMP:\n          // Allow all known seccomp calls. We must allow the seccomp call\n          // that rr triggers when spawning the initial tracee.\n          switch ((unsigned long)regs.arg2()) {\n            case SECCOMP_MODE_STRICT:\n              break;\n            case SECCOMP_MODE_FILTER: {\n              // If we're bootstrapping then this must be rr's own syscall\n              // filter, so just install it normally now.\n              if (t->session().done_initial_exec()) {\n                // Prevent the actual prctl call. We'll fix this up afterwards.\n                Registers r = regs;\n                r.set_arg1(intptr_t(-1));\n                t->set_regs(r);\n              }\n              break;\n            }\n            default:\n              syscall_state.expect_errno = EINVAL;\n              break;\n          }\n          break;\n\n        case PR_SET_PTRACER: {\n          // Prevent any PR_SET_PTRACER call, but pretend it succeeded, since\n          // we don't want any interference with our ptracing.\n          Registers r = regs;\n          r.set_arg1(intptr_t(-1));\n          t->set_regs(r);\n          syscall_state.emulate_result(0);\n          break;\n        }\n\n        case PR_SET_MM: {\n          switch ((unsigned long)regs.arg2()) {\n            case PR_SET_MM_MAP_SIZE:\n              syscall_state.reg_parameter(3, sizeof(unsigned int));\n              break;\n\n            case PR_SET_MM_ARG_START:\n            case PR_SET_MM_ARG_END:\n              break;\n\n            default:\n              syscall_state.expect_errno = EINVAL;\n              break;\n          }\n          break;\n        }\n\n        case PR_SET_VMA: {\n          switch ((unsigned long)regs.arg2()) {\n            case PR_SET_VMA_ANON_NAME:\n              break;\n            default:\n              syscall_state.expect_errno = EINVAL;\n              break;\n          }\n          break;\n        }\n\n        case PR_GET_AUXV: {\n          syscall_state.reg_parameter(\n              2, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                  (size_t)regs.arg3()));\n          break;\n        }\n\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::arch_prctl:\n      switch ((int)regs.arg1_signed()) {\n        case ARCH_SET_FS:\n        case ARCH_SET_GS:\n          break;\n\n        case ARCH_GET_FS:\n        case ARCH_GET_GS:\n          syscall_state.reg_parameter<typename Arch::unsigned_long>(2);\n          break;\n\n        case ARCH_SET_CPUID: {\n          if (!t->session().has_cpuid_faulting()) {\n            // Not supported or not working. Allow the call to go\n            // through to get the right result.\n            break;\n          }\n\n          // Prevent the actual SET_CPUID call.\n          Registers r = t->regs();\n          r.set_arg1(intptr_t(-1));\n          t->set_regs(r);\n          int val = (int)t->regs().arg2();\n          t->cpuid_mode = !!val;\n          syscall_state.emulate_result(0);\n          break;\n        }\n\n        case ARCH_GET_CPUID: {\n          if (!t->session().has_cpuid_faulting()) {\n            // Not supported or not working. Allow the call to go\n            // through to get the right result.\n            break;\n          }\n\n          // Prevent the actual GET_CPUID call and return our emulated state.\n          Registers r = t->regs();\n          r.set_arg1(intptr_t(-1));\n          t->set_regs(r);\n          syscall_state.emulate_result(t->cpuid_mode);\n          break;\n        }\n\n        case ARCH_GET_XCOMP_SUPP:\n        case ARCH_GET_XCOMP_PERM:\n          syscall_state.reg_parameter<uint64_t>(2);\n          break;\n        case ARCH_REQ_XCOMP_PERM:\n          break;\n\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::ioctl:\n      return prepare_ioctl<Arch>(t, syscall_state);\n\n    case Arch::bpf:\n      return prepare_bpf<Arch>(t, syscall_state);\n\n    case Arch::_sysctl: {\n      auto argsp =\n          syscall_state.reg_parameter<typename Arch::__sysctl_args>(1, IN);\n      auto oldlenp = syscall_state.mem_ptr_parameter_inferred(\n          REMOTE_PTR_FIELD(argsp, oldlenp), IN_OUT);\n      syscall_state.mem_ptr_parameter(\n          REMOTE_PTR_FIELD(argsp, oldval),\n          ParamSize::from_initialized_mem(t, oldlenp));\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::quotactl:\n      switch (regs.arg1() >> SUBCMDSHIFT) {\n        case Q_GETQUOTA:\n          syscall_state.reg_parameter<typename Arch::dqblk>(4);\n          break;\n        case Q_GETINFO:\n          syscall_state.reg_parameter<typename Arch::dqinfo>(4);\n          break;\n        case Q_GETFMT:\n          syscall_state.reg_parameter<int>(4);\n          break;\n        case Q_SETQUOTA:\n          FATAL() << \"Trying to set disk quota usage, this may interfere with \"\n                     \"rr recording\";\n          // not reached; the break is just to silence fallthrough warnings\n          break;\n        case Q_QUOTAON:\n        case Q_QUOTAOFF:\n        case Q_SETINFO:\n        case Q_SYNC:\n          break;\n        default:\n          // Don't set expect_errno here because quotactl can fail with\n          // various error codes before checking the command\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::keyctl:\n      switch ((int)regs.arg1_signed()) {\n        case KEYCTL_GET_KEYRING_ID:\n        case KEYCTL_JOIN_SESSION_KEYRING:\n        case KEYCTL_UPDATE:\n        case KEYCTL_REVOKE:\n        case KEYCTL_CHOWN:\n        case KEYCTL_SETPERM:\n        case KEYCTL_CLEAR:\n        case KEYCTL_LINK:\n        case KEYCTL_UNLINK:\n        case KEYCTL_SEARCH:\n        case KEYCTL_INSTANTIATE:\n        case KEYCTL_INSTANTIATE_IOV:\n        case KEYCTL_NEGATE:\n        case KEYCTL_REJECT:\n        case KEYCTL_SET_REQKEY_KEYRING:\n        case KEYCTL_SET_TIMEOUT:\n        case KEYCTL_ASSUME_AUTHORITY:\n        case KEYCTL_SESSION_TO_PARENT:\n        case KEYCTL_INVALIDATE:\n        case KEYCTL_GET_PERSISTENT:\n          break;\n\n        case KEYCTL_DESCRIBE:\n        case KEYCTL_READ:\n        case KEYCTL_GET_SECURITY:\n        case KEYCTL_DH_COMPUTE:\n          syscall_state.reg_parameter(\n              3, ParamSize::from_syscall_result<typename Arch::signed_long>(\n                     regs.arg4()));\n          break;\n\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    /* int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int\n     * timeout); */\n    case Arch::epoll_wait:\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<int>(sizeof(typename Arch::epoll_event) * regs.arg3_signed(),\n              sizeof(typename Arch::epoll_event)));\n      return ALLOW_SWITCH;\n\n    case Arch::epoll_pwait2:\n    case Arch::epoll_pwait: {\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<int>(sizeof(typename Arch::epoll_event) * regs.arg3_signed(),\n              sizeof(typename Arch::epoll_event)));\n      t->invalidate_sigmask();\n      return ALLOW_SWITCH;\n    }\n\n    /* The following two syscalls enable context switching not for\n     * liveness/correctness reasons, but rather because if we\n     * didn't context-switch away, rr might end up busy-waiting\n     * needlessly.  In addition, albeit far less likely, the\n     * client program may have carefully optimized its own context\n     * switching and we should take the hint. */\n\n    case Arch::nanosleep:\n      syscall_state.reg_parameter<typename Arch::timespec>(2);\n      return ALLOW_SWITCH;\n\n    case Arch::clock_nanosleep:\n      syscall_state.reg_parameter<typename Arch::timespec>(4);\n      return ALLOW_SWITCH;\n\n    case Arch::clock_nanosleep_time64:\n      syscall_state.reg_parameter<typename Arch::Arch64::timespec>(4);\n      return ALLOW_SWITCH;\n\n    case Arch::sched_yield:\n      t->session().scheduler().schedule_one_round_robin(t);\n      return ALLOW_SWITCH;\n\n    case Arch::rt_sigpending:\n      syscall_state.reg_parameter(1, (size_t)regs.arg2());\n      return PREVENT_SWITCH;\n\n    case Arch::rt_sigtimedwait_time64:\n    case Arch::rt_sigtimedwait:\n      syscall_state.reg_parameter<typename Arch::siginfo_t>(2);\n      return ALLOW_SWITCH;\n\n    case Arch::rt_sigprocmask:\n    case Arch::sigprocmask: {\n      syscall_state.reg_parameter<typename Arch::kernel_sigset_t>(3);\n      syscall_state.reg_parameter<typename Arch::kernel_sigset_t>(\n          2, IN, protect_rr_sigs);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::sigaction:\n    case Arch::rt_sigaction: {\n      syscall_state.reg_parameter<typename Arch::kernel_sigaction>(\n          2, IN, protect_rr_sigs_sa_mask);\n      syscall_state.reg_parameter<typename Arch::kernel_sigaction>(3, OUT);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::getxattr:\n    case Arch::lgetxattr:\n    case Arch::fgetxattr:\n      syscall_state.reg_parameter(\n          3, ParamSize::from_syscall_result<ssize_t>(regs.arg4()));\n      return PREVENT_SWITCH;\n\n    case Arch::listxattr:\n    case Arch::llistxattr:\n    case Arch::flistxattr:\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<ssize_t>(regs.arg3()));\n      return PREVENT_SWITCH;\n\n    case Arch::sched_getattr: {\n      syscall_state.reg_parameter(2, ParamSize(regs.arg3()));\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::sched_setaffinity: {\n      // Ignore all sched_setaffinity syscalls. They might interfere\n      // with our own affinity settings.\n      Registers r = regs;\n      // Set arg1 to an invalid PID to ensure this syscall is ignored.\n      r.set_arg1(-1);\n      t->set_regs(r);\n      syscall_state.emulate_result(0);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::sched_getaffinity:\n      syscall_state.reg_parameter(3, ParamSize(regs.arg2()));\n      return PREVENT_SWITCH;\n\n    case Arch::ptrace:\n      return prepare_ptrace<Arch>(t, syscall_state);\n\n    case Arch::mincore:\n      syscall_state.reg_parameter(\n          3, (regs.arg2() + page_size() - 1) / page_size());\n      return PREVENT_SWITCH;\n\n    case Arch::shmctl:\n      return prepare_shmctl<Arch>(syscall_state, (int)regs.arg2_signed(), 3);\n\n    case Arch::semctl:\n      return prepare_semctl<Arch>(t, syscall_state, (int)regs.arg1_signed(),\n                                  (int)regs.arg3_signed(), 4, USE_DIRECTLY);\n\n    case Arch::seccomp:\n      switch ((unsigned int)regs.arg1()) {\n        case SECCOMP_SET_MODE_STRICT:\n        case SECCOMP_GET_ACTION_AVAIL:\n          break;\n        case SECCOMP_SET_MODE_FILTER: {\n          // Prevent the actual seccomp call. We'll fix this up afterwards.\n          Registers r = regs;\n          r.set_arg1(intptr_t(-1));\n          t->set_regs(r);\n          break;\n        }\n        case SECCOMP_GET_NOTIF_SIZES:\n          syscall_state.reg_parameter<typename Arch::seccomp_notif_sizes>(3);\n          break;\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::get_mempolicy: {\n      syscall_state.reg_parameter(1, sizeof(int));\n      unsigned long maxnode = t->regs().arg3();\n      unsigned long align_mask = 8 * sizeof(typename Arch::unsigned_long) - 1;\n      unsigned long aligned_maxnode = (maxnode + align_mask) & ~align_mask;\n      syscall_state.reg_parameter(2, aligned_maxnode / 8);\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::madvise:\n      switch ((int)regs.arg3()) {\n        case MADV_NORMAL:\n        case MADV_RANDOM:\n        case MADV_SEQUENTIAL:\n        case MADV_WILLNEED:\n        case MADV_DONTNEED:\n        case MADV_REMOVE:\n        case MADV_DONTFORK:\n        case MADV_DOFORK:\n        case MADV_SOFT_OFFLINE:\n        case MADV_HWPOISON:\n        case MADV_MERGEABLE:\n        case MADV_UNMERGEABLE:\n        case MADV_HUGEPAGE:\n        case MADV_NOHUGEPAGE:\n        case MADV_DONTDUMP:\n        case MADV_DODUMP:\n        case MADV_WIPEONFORK:\n        case MADV_KEEPONFORK:\n        case MADV_COLD:\n        case MADV_PAGEOUT:\n        case MADV_POPULATE_READ:\n        case MADV_POPULATE_WRITE:\n        case MADV_DONTNEED_LOCKED:\n        case MADV_COLLAPSE:\n          break;\n        case MADV_FREE: {\n          // MADV_FREE introduces nondeterminism --- the kernel zeroes the\n          // pages when under memory pressure. So we don't allow it.\n          Registers r = regs;\n          r.set_arg3(-1);\n          t->set_regs(r);\n          break;\n        }\n        case MADV_GUARD_INSTALL:\n        case MADV_GUARD_REMOVE:\n          syscall_state.emulate_result(-EINVAL);\n          break;\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::personality: {\n      int p = regs.arg1();\n      if (p == -1) {\n        // A special argument that only returns the existing personality.\n        return PREVENT_SWITCH;\n      }\n      switch ((uint8_t)p) {\n        case PER_LINUX32:\n        case PER_LINUX:\n          // The default personality requires no handling.\n          break;\n        default:\n          syscall_state.expect_errno = EINVAL;\n          break;\n      }\n\n      if (t->session().enable_chaos()) {\n        bool disable_randomize =\n          (p & (ADDR_COMPAT_LAYOUT | ADDR_NO_RANDOMIZE |\n                ADDR_LIMIT_32BIT | ADDR_LIMIT_3GB)) != 0;\n        t->vm()->disable_layout_randomization(disable_randomize);\n      }\n      if (p & 0xffffff00 &\n          ~(ADDR_COMPAT_LAYOUT | ADDR_NO_RANDOMIZE | ADDR_LIMIT_32BIT |\n            ADDR_LIMIT_3GB | FDPIC_FUNCPTRS | MMAP_PAGE_ZERO | SHORT_INODE |\n            STICKY_TIMEOUTS | UNAME26 | WHOLE_SECONDS | READ_IMPLIES_EXEC)) {\n        syscall_state.expect_errno = EINVAL;\n      }\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::mmap:\n      switch (Arch::mmap_semantics) {\n        case Arch::StructArguments: {\n          auto args =\n              t->read_mem(remote_ptr<typename Arch::mmap_args>(regs.arg1()));\n          // XXX fix these unsupported features?\n          // only the most ancient code should be using old-style mmap on 32bit,\n          // modern glibc uses mmap2.\n          FileMonitor* monitor = t->fd_table()->get_monitor(args.fd);\n          if (monitor) {\n            FileMonitor::Type monitor_type = monitor->type();\n            ASSERT(t, monitor_type != FileMonitor::VirtualPerfCounter &&\n              monitor_type != FileMonitor::NonvirtualPerfCounter);\n          }\n          ASSERT(t, !(args.flags & MAP_GROWSDOWN));\n          break;\n        }\n        case Arch::RegisterArguments: {\n          prepare_mmap_register_params(t);\n          break;\n        }\n      }\n      return PREVENT_SWITCH;\n\n    case Arch::mmap2:\n      prepare_mmap_register_params(t);\n      return PREVENT_SWITCH;\n\n    case Arch::pkey_mprotect:\n    case Arch::mprotect:\n      // Since we're stripping MAP_GROWSDOWN from kernel mmap calls, we need\n      // to implement PROT_GROWSDOWN ourselves.\n      t->vm()->fixup_mprotect_growsdown_parameters(t);\n      return PREVENT_SWITCH;\n\n    case SYS_rrcall_notify_control_msg:\n    case SYS_rrcall_init_preload:\n    case SYS_rrcall_notify_stap_semaphore_added:\n    case SYS_rrcall_notify_stap_semaphore_removed:\n      syscall_state.emulate_result(0);\n      return PREVENT_SWITCH;\n\n    // This normally won't be executed but it can be if an RDTSC traps to\n    // the syscallbuf as a fake rrcall_rdtsc, but we then can't buffer it\n    // because the buffer is full or disabled.\n    case SYS_rrcall_rdtsc: {\n      syscall_state.emulate_result(0);\n      uint64_t tsc = rdtsc();\n      remote_ptr<uint64_t> addr(t->regs().arg1());\n      t->write_mem(addr, tsc);\n      t->record_local(addr, &tsc);\n      return PREVENT_SWITCH;\n    }\n\n    case SYS_rrcall_init_buffers:\n      // This is purely for testing purposes. See signal_during_preload_init.\n      if (send_signal_during_init_buffers()) {\n        syscall(SYS_tgkill, t->tgid(), t->tid, SIGCHLD);\n      }\n      syscall_state.reg_parameter<rrcall_init_buffers_params<Arch>>(1, IN_OUT);\n      return PREVENT_SWITCH;\n\n    case SYS_rrcall_check_presence: {\n      // Since this is \"user\" facing, we follow best practices for regular\n      // syscalls and make sure that unused arguments (in this case all of them)\n      // are zero.\n      bool arguments_are_zero = true;\n      Registers r = t->regs();\n      int first_zero_reg = 1;\n      uintptr_t ret = 0;\n      if (r.arg(1) == RRCALL_CHECK_SYSCALLBUF_USED_OR_DISABLED) {\n        if (!!getenv(SYSCALLBUF_ENABLED_ENV_VAR)) {\n          // Syscallbuf is enabled, but we reached here anyway. Return -ENOTSUP.\n          ret = (uintptr_t)-ENOTSUP;\n        }\n        first_zero_reg = 2;\n      }\n      for (int i = first_zero_reg; i <= 6; ++i) {\n        arguments_are_zero &= r.arg(i) == 0;\n      }\n      if (!arguments_are_zero)\n        syscall_state.emulate_result((uintptr_t)-EINVAL);\n      else\n        syscall_state.emulate_result(ret);\n      syscall_state.expect_errno = ENOSYS;\n      return PREVENT_SWITCH;\n    }\n\n    case SYS_rrcall_detach_teleport: {\n      bool arguments_are_zero = true;\n      Registers r = t->regs();\n      for (int i = 1; i <= 6; ++i) {\n        arguments_are_zero &= r.arg(i) == 0;\n      }\n      if (!arguments_are_zero) {\n        syscall_state.emulate_result((uintptr_t)-EINVAL);\n        syscall_state.expect_errno = ENOSYS;\n        return PREVENT_SWITCH;\n      }\n\n      t->exit_syscall(Arch::arch());\n      pid_t new_tid = do_detach_teleport(t);\n\n      // Leave the proxy where it is --- just exited the detach_teleport\n      // syscall. We won't resume it again until we kill it in ~RecordTask.\n      t->detached_proxy = true;\n      // Just have the same task object represent both the zombie task\n      // and be able to receive death notices for the detached tracee\n      // to forward.\n      t->session().on_proxy_detach(t, new_tid);\n      t->rec_tid = new_tid;\n\n      return ALLOW_SWITCH;\n    }\n\n    case SYS_rrcall_arm_time_slice: {\n      Registers r = t->regs();\n      bool arguments_are_zero = true;\n      for (int i = 2; i <= 6; ++i) {\n        arguments_are_zero &= r.arg(i) == 0;\n      }\n      // Ticks request of zero is invalid for the moment\n      // for purposes of this syscall. In the future we\n      // want to have it mean to simulate a timeslice expiry\n      // at the end of this syscall, but we have no use for\n      // that at the moment.\n      if (r.arg(1) == 0 || r.arg(1) > (uintptr_t)MAX_TICKS_REQUEST ||\n          !arguments_are_zero) {\n        syscall_state.emulate_result((uintptr_t)-EINVAL);\n        syscall_state.expect_errno = ENOSYS;\n        return PREVENT_SWITCH;\n      }\n      t->tick_request_override = (TicksRequest)r.arg(1);\n      syscall_state.emulate_result(0);\n      syscall_state.expect_errno = ENOSYS;\n      return PREVENT_SWITCH;\n    }\n\n    case SYS_rrcall_freeze_tid: {\n      Registers r = t->regs();\n      bool arguments_are_zero = true;\n      for (int i = 3; i <= 6; ++i) {\n        arguments_are_zero &= r.arg(i) == 0;\n      }\n      pid_t tid = r.arg(1);\n      int enable = r.arg(2);\n      if (!arguments_are_zero || (enable != 0 && enable != 1)) {\n        syscall_state.emulate_result((uintptr_t)-EINVAL);\n        syscall_state.expect_errno = ENOSYS;\n        return PREVENT_SWITCH;\n      }\n      RecordTask *requested_task = t->session().find_task(tid);\n      if (!requested_task) {\n        syscall_state.emulate_result((uintptr_t)-ESRCH);\n        syscall_state.expect_errno = ENOSYS;\n        return PREVENT_SWITCH;\n      }\n      requested_task->schedule_frozen = enable;\n      syscall_state.emulate_result(0);\n      syscall_state.expect_errno = ENOSYS;\n      return PREVENT_SWITCH;\n    }\n\n    case Arch::brk:\n    case Arch::munmap:\n    case Arch::process_vm_readv:\n    case Arch::process_vm_writev:\n    case SYS_rrcall_notify_syscall_hook_exit:\n    case Arch::mremap:\n    case Arch::shmat:\n    case Arch::shmdt:\n      return PREVENT_SWITCH;\n\n    case Arch::sigsuspend:\n    case Arch::rt_sigsuspend:\n      t->invalidate_sigmask();\n      return ALLOW_SWITCH;\n\n    case Arch::sigreturn:\n    case Arch::rt_sigreturn:\n      // If a sigreturn/rt_sigreturn ever comes through the syscallbuf, we\n      // have switched to the syscallbuf stack (which does not contain any of the\n      // kernel's sigframe data) and we are about to explode (when the kernel restores\n      // the program's registers to random garbage from the syscallbuf stack). Die now\n      // with a useful error message.\n      //\n      // We decline to patch syscall instructions when they're invoked with the\n      // sigreturn/rt_sigreturn syscall. This covers the kernel's inserted sigreturn\n      // trampolines. If the program intentionally invokes these syscalls through a\n      // generic wrapper like syscall(2), it'll have to be recorded with the syscallbuf\n      // disabled.\n      ASSERT(t, !t->is_in_rr_page()) <<\n        \"sigreturn/rt_sigreturn syscalls cannot be processed through the syscallbuf \"\n        \"because the stack pointer will be wrong. Is this program invoking them \"\n        \"through the glibc `syscall` wrapper?\\nrerecord with -n to fix this\";\n      if (t->arch() == aarch64) {\n        // This is a bit of a hack, but we don't really have a\n        // good way to do this otherwise. We need to record the\n        // restored x7 register, but the kernel will lie to us\n        // about it.\n        remote_ptr<ARM64Arch::rt_sigframe> frame = t->regs().sp().cast<ARM64Arch::rt_sigframe>();\n        auto x_regs_arr = REMOTE_PTR_FIELD(REMOTE_PTR_FIELD(\n          REMOTE_PTR_FIELD(REMOTE_PTR_FIELD(frame, uc), uc_mcontext),\n          regs),x);\n        auto x7 = t->read_mem(x_regs_arr.field((uintptr_t*)nullptr,\n          7 * sizeof(uintptr_t)));\n        syscall_state.syscall_entry_registers.set_x(7, x7);\n      }\n      t->invalidate_sigmask();\n      return PREVENT_SWITCH;\n\n    case Arch::mq_timedreceive_time64:\n    case Arch::mq_timedreceive: {\n      syscall_state.reg_parameter(\n          2, ParamSize::from_syscall_result<typename Arch::ssize_t>(\n                 (size_t)regs.arg3()));\n      syscall_state.reg_parameter<unsigned>(4);\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::modify_ldt: {\n      int func = regs.arg1();\n      if (func == 0 || func == 2) {\n        syscall_state.reg_parameter(\n            2, ParamSize::from_syscall_result<int>((size_t)regs.arg3()));\n      }\n      // N.B. Unlike set_thread_area, the entry number is not written\n      // for (func == 1 || func == 0x11)\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::name_to_handle_at: {\n      syscall_state.reg_parameter(3,\n                                  sizeof(typename Arch::file_handle) + MAX_HANDLE_SZ);\n      syscall_state.reg_parameter(4, sizeof(int));\n      return ALLOW_SWITCH;\n    }\n\n    case Arch::syslog: {\n      int type = regs.arg1();\n      if (type < 0 || type > 10) {\n        syscall_state.expect_errno = EINVAL;\n      } else if (type == 2 || type == 3 || type == 4) {\n        syscall_state.reg_parameter(\n            2, ParamSize::from_syscall_result<int>((size_t)regs.arg3()));\n      }\n      return PREVENT_SWITCH;\n    }\n\n    default:\n      // Invalid syscalls return -ENOSYS. Assume any such\n      // result means the syscall was completely ignored by the\n      // kernel so it's OK for us to not do anything special.\n      // Other results mean we probably need to understand this\n      // syscall, but we don't.\n      syscall_state.expect_errno = ENOSYS;\n      return PREVENT_SWITCH;\n  }\n}\n\nstatic Switchable rec_prepare_syscall_internal(\n    RecordTask* t, TaskSyscallState& syscall_state) {\n  SupportedArch arch = t->ev().Syscall().arch();\n  return with_converted_registers<Switchable>(\n      t->regs(), arch, [&](const Registers& regs) -> Switchable {\n        RR_ARCH_FUNCTION(rec_prepare_syscall_arch, arch, t, syscall_state,\n                         regs);\n      });\n}\n\nSwitchable rec_prepare_syscall(RecordTask* t) {\n  t->syscall_state = make_unique<TaskSyscallState>();\n  auto& syscall_state = TaskSyscallState::get(t);\n  syscall_state.init(t);\n\n  Switchable s = rec_prepare_syscall_internal(t, syscall_state);\n  return syscall_state.done_preparing(s);\n}\n\nvoid rec_abort_prepared_syscall(RecordTask* t) {\n  auto syscall_state = TaskSyscallState::maybe_get(t);\n  if (!syscall_state) {\n    return;\n  }\n  syscall_state->abort_syscall_results();\n  t->syscall_state = nullptr;\n}\n\nbool rec_return_normally_from_wait(RecordTask* t) {\n  auto syscall_state = TaskSyscallState::maybe_get(t);\n  if (!syscall_state) {\n    return false;\n  }\n  if (syscall_state->emulate_wait_for_child) {\n    return true;\n  }\n  if (maybe_emulate_wait(t, *syscall_state)) {\n    return true;\n  }\n  return false;\n}\n\nstatic void aarch64_kernel_bug_workaround(RecordTask *t,\n                                          const TaskSyscallState &syscall_state)\n{\n  if (syscall_state.syscall_entry_registers.arch() == aarch64) {\n    // The kernel lies about the real register state during syscall exits.\n    // Try to fix that up to retain some measure of sanity (otherwise we\n    // might leak an incorrect register into userspace, causing an\n    // un-recorded divergence). I'm really hoping to get this fixed\n    // in the kernel.\n    Registers r = t->regs();\n    r.set_x(7, syscall_state.syscall_entry_registers.x(7));\n    t->set_regs(r);\n  }\n}\n\ntemplate <typename Arch>\nstatic void rec_prepare_restart_syscall_arch(RecordTask* t,\n                                             TaskSyscallState& syscall_state) {\n  int syscallno = t->ev().Syscall().number;\n  aarch64_kernel_bug_workaround(t, syscall_state);\n  switch (syscallno) {\n    case Arch::nanosleep:\n    case Arch::clock_nanosleep:\n    case Arch::clock_nanosleep_time64:\n      /* Hopefully uniquely among syscalls, nanosleep()/clock_nanosleep()\n       * requires writing to its remaining-time outparam\n       * *only if* the syscall fails with -EINTR.  When a\n       * nanosleep() is interrupted by a signal, we don't\n       * know a priori whether it's going to be eventually\n       * restarted or not.  (Not easily, anyway.)  So we\n       * don't know whether it will eventually return -EINTR\n       * and would need the outparam written.  To resolve\n       * that, we do what the kernel does, and update the\n       * outparam at the -ERESTART_RESTART interruption\n       * regardless. */\n      syscall_state.process_syscall_results();\n      break;\n    case Arch::ppoll:\n    case Arch::ppoll_time64:\n    case Arch::pselect6:\n    case Arch::pselect6_time64:\n    case Arch::sigsuspend:\n    case Arch::rt_sigsuspend:\n      t->invalidate_sigmask();\n      break;\n    case Arch::wait4:\n    case Arch::waitid:\n    case Arch::waitpid: {\n      Registers r = t->regs();\n      r.set_original_syscallno(\n          syscall_state.syscall_entry_registers.original_syscallno());\n      t->set_regs(r);\n      t->canonicalize_regs(Arch::arch());\n      t->in_wait_type = WAIT_TYPE_NONE;\n      t->in_wait_options = 0;\n      break;\n    }\n  }\n}\n\nstatic void rec_prepare_restart_syscall_internal(\n    RecordTask* t, TaskSyscallState& syscall_state) {\n  RR_ARCH_FUNCTION(rec_prepare_restart_syscall_arch, t->arch(), t,\n                   syscall_state);\n}\n\nvoid rec_prepare_restart_syscall(RecordTask* t) {\n  auto& syscall_state = TaskSyscallState::get(t);\n  rec_prepare_restart_syscall_internal(t, syscall_state);\n  t->syscall_state = nullptr;\n}\n\nstatic const char* dropped_privs_warning =\n    \"[WARNING] rr: Executed file with setuid or file capabilities set.\\n\"\n    \"          Capabilities did not take effect. Errors may follow.\\n\"\n    \"          To record this execution faithfully, re-run rr as:\\n\"\n    \"\\n\"\n    \"             sudo -EP --preserve-env=HOME rr record --setuid-sudo\\n\"\n    \"\\n\";\n\nstatic bool is_privileged_executable(RecordTask* t, const string& path) {\n  struct vfs_cap_data actual, empty;\n  memset(actual.data, 0, sizeof(actual.data));\n  memset(empty.data, 0, sizeof(empty.data));\n  if (-1 != getxattr(path.c_str(), \"security.capability\", &actual,\n                     sizeof(vfs_cap_data))) {\n    if (memcmp(&actual, &empty, sizeof(actual.data)) != 0) {\n      return true;\n    }\n  } else {\n    if (errno == ENOENT) {\n      return false;\n    }\n    ASSERT(t, errno == ENODATA || errno == ENOTSUP);\n  }\n  struct stat buf;\n  stat(path.c_str(), &buf);\n  if (buf.st_mode & (S_ISUID | S_ISGID)) {\n    return true;\n  }\n  return false;\n}\n\nstatic bool in_same_mount_namespace_as(RecordTask* t) {\n  char proc_ns_mount[PATH_MAX];\n  snprintf(proc_ns_mount, sizeof(proc_ns_mount), \"/proc/%d/ns/mnt\", t->tid);\n  struct stat my_buf, their_buf;\n  ASSERT(t, stat(\"/proc/self/ns/mnt\", &my_buf) == 0);\n  ASSERT(t, stat(proc_ns_mount, &their_buf) == 0);\n  return my_buf.st_ino == their_buf.st_ino;\n}\n\nstatic void check_privileged_exe(RecordTask* t) {\n  // Check if the executable we just execed has setuid bits or file capabilities\n  // If so (and rr doesn't have CAP_SYS_ADMIN, which would have let us avoid,\n  // no_new privs), they may have been ignored, due to our no_new_privs setting\n  // in the tracee. That's most likely not what the user intended (and setuid\n  // applications may not handle not being root particularly gracefully - after\n  // all under usual circumstances, it would be an exec-time error). Give a loud\n  // warning to tell the user what happened, but continue anyway.\n  static bool gave_stern_warning = false;\n  if (!in_same_mount_namespace_as(t)) {\n    // We could try to enter the mount namespace and perform the below check\n    // there, but don't bother. We know we must have privileges over the mount\n    // namespaces (either because it's an unprivileged user namespace, in which\n    // case we have full privileges, or because at some point one of our\n    // tracees had to have CAP_SYS_ADMIN/CAP_SETUID to create the mount\n    // namespace - as a result we must have at least as much privilege).\n    // Nevertheless, we still need to stop the hpc counters, since\n    // the executable may be privileged with respect to its namespace.\n    t->hpc.close();\n  } else if (is_privileged_executable(t, t->vm()->exe_image())) {\n    if (has_effective_caps(1 << CAP_SYS_ADMIN)) {\n      // perf_events may have decided to stop counting for security reasons.\n      // To be safe, close all perf counters now, to force re-opening the\n      // perf file descriptors the next time we resume the task.\n      t->hpc.close();\n    } else {\n      // Only issue the warning once. If it's a problem, the user will likely\n      // find out soon enough. If not, no need to keep bothering them.\n      if (!gave_stern_warning) {\n        fputs(dropped_privs_warning, stderr);\n        gave_stern_warning = true;\n      }\n    }\n  }\n}\n\nstatic uint64_t word_at(uint8_t* buf, size_t wsize) {\n  union {\n    uint8_t buf[8];\n    uint64_t v;\n  } u;\n  memcpy(u.buf, buf, wsize);\n  memset(u.buf + wsize, 0, 8 - wsize);\n  return u.v;\n}\n\nstatic pair<remote_ptr<void>, remote_ptr<void>> get_exe_entry_interp_base(Task* t) {\n  remote_ptr<void> exe_entry;\n  remote_ptr<void> interp_base;\n  vector<uint8_t> v = read_auxv(t);\n  size_t i = 0;\n  size_t wsize = word_size(t->arch());\n  while ((i + 1)*wsize*2 <= v.size()) {\n    if (word_at(v.data() + i*2*wsize, wsize) == AT_ENTRY) {\n      exe_entry = word_at(v.data() + (i*2 + 1)*wsize, wsize);\n    } else if (word_at(v.data() + i*2*wsize, wsize) == AT_BASE) {\n      interp_base = word_at(v.data() + (i*2 + 1)*wsize, wsize);\n    }\n    ++i;\n  }\n  return make_pair(exe_entry, interp_base);\n}\n\n/**\n * Given `file_name`, where `file_name` is relative to our root directory\n * but is in the mount namespace of `t`, try to make it a file we can read.\n */\nstatic string try_make_process_file_name(RecordTask* t,\n                                         const std::string& file_name) {\n  if (file_name == \"/\") {\n    // The kernel sometimes returns \"/\" as the file name of a mapped\n    // segment. (We've seen this when the actual file was a bind-mount\n    // that has been opened with O_PATH and then lazily unmounted, then\n    // the O_PATH fd was execed with `execveat`.)\n    // In that case, we have no idea what the actual file is so\n    // return a name that will never work instead \"/proc/.../root/\"\n    // which can be stat(), causing confusion.\n    return \"\";\n  }\n\n  char proc_root[32];\n  // /proc/<pid>/root has magical properties; not only is it a link, but\n  // it links to a view of the filesystem as the process sees it, taking into\n  // account the process mount namespace etc.\n  snprintf(proc_root, sizeof(proc_root), \"/proc/%d/root\", t->tid);\n  char root[PATH_MAX];\n  ssize_t ret = readlink(proc_root, root, sizeof(root) - 1);\n  ASSERT(t, ret >= 0);\n  root[ret] = 0;\n\n  if (strncmp(root, file_name.c_str(), ret)) {\n    LOG(debug) << \"File \" << file_name << \" is outside known root \"\n               << proc_root;\n    return file_name;\n  }\n  return string(proc_root) + (ret == 1 ? file_name : file_name.substr(ret));\n}\n\nenum class PageState {\n  PRESENT,\n  NOT_PRESENT\n};\n\n// Returns pages that satisfy the given PageState constraint.\nstatic vector<MemoryRange> find_pages(RecordTask* t, MemoryRange range, PageState state) {\n  ScopedFd& pagemap = t->pagemap_fd();\n  ASSERT(t, pagemap.is_open());\n  remote_ptr<void> addr = floor_page_size(range.start());\n  remote_ptr<void> end = ceil_page_size(range.end());\n  vector<uint64_t> pfns;\n  pfns.resize((end - addr)/page_size());\n  ssize_t r = read_to_end(pagemap, addr.as_int() / page_size() * sizeof(uint64_t),\n                          pfns.data(), pfns.size() * sizeof(uint64_t));\n  ASSERT(t, r == (ssize_t)pfns.size() * 8);\n  vector<MemoryRange> ret;\n  for (size_t i = 0; i < pfns.size(); ++i) {\n    bool is_present = pfns[i] & ((1ULL << 63) | (1ULL << 62));\n    bool match;\n    switch (state) {\n      case PageState::PRESENT:\n        match = is_present;\n        break;\n      case PageState::NOT_PRESENT:\n        match = !is_present;\n        break;\n      default:\n        FATAL() << \"Invalid PageState\";\n        return ret;\n    }\n    if (match) {\n      remote_ptr<void> p = addr + i * page_size();\n      remote_ptr<void> p_end = p + page_size();\n      if (ret.empty() || ret.back().end() != p) {\n        ret.push_back(MemoryRange(p, p_end));\n      } else {\n        ret.back() = MemoryRange(ret.back().start(), p_end);\n      }\n    }\n  }\n  return ret;\n}\n\nstatic void process_execve(RecordTask* t, TaskSyscallState& syscall_state) {\n  Registers r = t->regs();\n  if (r.syscall_failed()) {\n    // Otherwise we would have done this during PTRACE_EVENT_EXEC\n    t->session().scheduler().did_exit_execve(t);\n    return;\n  }\n\n  string interp_name;\n  {\n    std::string exe_path = t->proc_exe_path();\n    ScopedFd fd(exe_path.c_str(), O_RDONLY);\n    ASSERT(t, fd.is_open());\n\n    if (ElfFileReader::is_x32_abi(fd)) {\n      // NB: We opened proc_exe_path because exe_path may not be correct in\n      // this namespace, but we want to report something more useful than\n      // /proc/<pid>/exe in the event of a failure.\n      FATAL() << \"rr does not support the x32 ABI, but \" << t->exe_path()\n              << \" is an x32 ABI program.\";\n    }\n\n    ElfFileReader reader(fd);\n    interp_name = reader.read_interp();\n  }\n\n  t->post_exec_syscall(t->exe_path());\n  t->ev().Syscall().exec_fds_to_close =\n      t->fd_table()->fds_to_close_after_exec(t);\n\n  check_privileged_exe(t);\n\n  KernelMapping rr_page_mapping =\n      t->vm()->mapping_of(AddressSpace::rr_page_start()).map;\n  auto mode = t->trace_writer().write_mapped_region(\n      t, rr_page_mapping, rr_page_mapping.fake_stat(),\n      rr_page_mapping.fsname(),\n      vector<TraceRemoteFd>(),\n      TraceWriter::RR_BUFFER_MAPPING);\n  ASSERT(t, mode == TraceWriter::DONT_RECORD_IN_TRACE);\n\n  KernelMapping preload_thread_locals_mapping =\n      t->vm()->mapping_of(AddressSpace::preload_thread_locals_start()).map;\n  mode = t->trace_writer().write_mapped_region(\n      t, preload_thread_locals_mapping,\n      preload_thread_locals_mapping.fake_stat(),\n      preload_thread_locals_mapping.fsname(),\n      vector<TraceRemoteFd>(),\n      TraceWriter::RR_BUFFER_MAPPING);\n  ASSERT(t, mode == TraceWriter::DONT_RECORD_IN_TRACE);\n\n  KernelMapping vvar;\n  KernelMapping vvar_vclock;\n  KernelMapping vdso;\n\n  // get the remote executable entry point\n  // with the pointer, we find out which mapping is the executable\n  auto auxv_pointers = get_exe_entry_interp_base(t);\n  auto exe_entry = auxv_pointers.first;\n  auto interp_base = auxv_pointers.second;\n  // NB: A binary is not required to have an interpreter.\n\n  // Write out stack mappings first since during replay we need to set up the\n  // stack before any files get mapped.\n  vector<KernelMapping> stacks;\n  for (const auto& m : t->vm()->maps()) {\n    auto& km = m.map;\n    if (km.is_stack()) {\n      stacks.push_back(km);\n    } else if (km.is_vvar()) {\n      vvar = km;\n    } else if (km.is_vvar_vclock()) {\n      vvar_vclock = km;\n    } else if (km.is_vdso()) {\n      vdso = km;\n    }\n\n    // if true, this mapping is our executable\n    if (km.start() <= exe_entry && exe_entry < km.end()) {\n      ASSERT(t, km.prot() & PROT_EXEC) << \"Entry point not in executable code?\";\n      syscall_state.exec_saved_event->set_exe_base(km.start());\n    }\n    if (km.start() == interp_base) {\n      t->vm()->set_interp_base(interp_base);\n      syscall_state.exec_saved_event->set_interp_base(interp_base);\n      t->vm()->set_interp_name(interp_name);\n      syscall_state.exec_saved_event->set_interp_name(interp_name);\n    }\n  }\n\n  syscall_state.exec_saved_event->set_pac_data(t->pac_keys());\n  t->session().trace_writer().write_task_event(*syscall_state.exec_saved_event);\n\n  {\n    AutoRemoteSyscalls remote(t, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);\n\n    if (vvar.size()) {\n      // We're not going to map [vvar] during replay --- that wouldn't\n      // make sense, since it contains data from the kernel that isn't correct\n      // for replay, and we patch out the vdso syscalls that would use it.\n      // Unmapping it now makes recording look more like replay.\n      // Also note that under 4.0.7-300.fc22.x86_64 (at least) /proc/<pid>/mem\n      // can't read the contents of [vvar].\n      remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                                vvar.start(), vvar.size());\n      t->vm()->unmap(t, vvar.start(), vvar.size());\n    }\n    if (vvar_vclock.size()) {\n      // Give [vvar_vclock] the same treatment.\n      remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                                vvar_vclock.start(), vvar_vclock.size());\n      t->vm()->unmap(t, vvar_vclock.start(), vvar_vclock.size());\n    }\n\n    if (t->session().unmap_vdso() && vdso.size()) {\n      remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                                vdso.start(), vdso.size());\n      t->vm()->unmap(t, vdso.start(), vdso.size());\n    }\n\n    for (auto& km : stacks) {\n      mode = t->trace_writer().write_mapped_region(t, km, km.fake_stat(),\n                                                   km.fsname(), vector<TraceRemoteFd>(),\n                                                   TraceWriter::EXEC_MAPPING);\n      ASSERT(t, mode == TraceWriter::RECORD_IN_TRACE);\n      auto buf = t->read_mem(km.start().cast<uint8_t>(), km.size());\n      t->trace_writer().write_raw(t->rec_tid, buf.data(), km.size(),\n                                  km.start());\n\n      // Remove MAP_GROWSDOWN from stacks by remapping the memory and\n      // writing the contents back.\n      int flags = (km.flags() & ~MAP_GROWSDOWN) | MAP_ANONYMOUS;\n      remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                                km.start(), km.size());\n      if (!t->vm()->has_mapping(km.start() - page_size())) {\n        // Unmap an extra page at the start; this seems to be necessary\n        // to properly wipe out the growsdown mapping. Doing it as a separate\n        // munmap call also seems to be necessary.\n        remote.infallible_syscall(syscall_number_for_munmap(remote.arch()),\n                                  km.start() - page_size(), page_size());\n      }\n      remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(), flags,\n                                              -1, 0);\n      t->write_mem(km.start().cast<uint8_t>(), buf.data(), buf.size());\n    }\n  }\n\n  // The kernel may modify some of the pages in the mapping according to\n  // ELF BSS metadata. We use /proc/<pid>/pagemap to observe which pages\n  // have been changed and mark them for recording.\n  vector<MemoryRange> memory_to_record;\n\n  for (const auto& m : t->vm()->maps()) {\n    auto& km = m.map;\n    if (km.start() == AddressSpace::rr_page_start() ||\n        km.start() == AddressSpace::preload_thread_locals_start()) {\n      continue;\n    }\n    if (km.is_stack() || km.is_vsyscall()) {\n      // [stack] has already been handled.\n      // [vsyscall] can't be read via /proc/<pid>/mem, *should*\n      // be the same across all execs, and can't be munmapped so we can't fix\n      // it even if it does vary. Plus no-one should be using it anymore.\n      continue;\n    }\n    struct stat st;\n    // Maybe we should use /proc/.../map_files instead?\n    string file_name = try_make_process_file_name(t, km.fsname());\n    if (stat(file_name.c_str(), &st) != 0) {\n      st = km.fake_stat();\n      // Size is not real. Don't confuse the logic below\n      st.st_size = 0;\n    }\n    if (t->trace_writer().write_mapped_region(t, km, st, file_name, vector<TraceRemoteFd>(),\n                                              TraceWriter::EXEC_MAPPING) ==\n        TraceWriter::RECORD_IN_TRACE) {\n      if (st.st_size > 0) {\n        off_t end = (off_t)st.st_size - km.file_offset_bytes();\n        t->record_remote(km.start(), min(end, (off_t)km.size()));\n      } else {\n        // st_size is not valid. Some device files are mmappable but have zero\n        // size. We also take this path if there's no file at all (vdso etc).\n        t->record_remote(km.start(), km.size());\n      }\n    } else {\n      vector<MemoryRange> present_pages = find_pages(t, km, PageState::PRESENT);\n      memory_to_record.insert(memory_to_record.end(),\n          present_pages.begin(), present_pages.end());\n    }\n  }\n\n  for (const auto& mr : memory_to_record) {\n    t->record_remote(mr.start(), mr.size());\n  }\n\n  // Patch LD_PRELOAD and VDSO after saving the mappings. Replay will apply\n  // patches to the saved mappings.\n  t->vm()->monkeypatcher().patch_after_exec(t);\n\n  init_scratch_memory(t, FIXED_ADDRESS);\n}\n\nstatic bool is_writable(RecordTask* t, int fd) {\n  struct stat lst = t->lstat_fd(fd);\n  return (lst.st_mode & S_IWUSR) != 0;\n}\n\n// Returns true if the fd used to map the file is writable and thus needs\n// monitoring.\nstatic bool monitor_fd_for_mapping(RecordTask* mapped_t, int mapped_fd, const struct stat& file,\n                                   vector<TraceRemoteFd>& extra_fds) {\n  unordered_set<FdTable*> tables;\n  bool found_our_mapping = false;\n  bool our_mapping_writable = false;\n  auto mapped_table = mapped_t->fd_table();\n  for (auto& ts : mapped_t->session().tasks()) {\n    auto rt = static_cast<RecordTask*>(ts.second);\n    if (rt->already_exited()) {\n      continue;\n    }\n    auto table = rt->fd_table();\n    if (tables.find(table.get()) != tables.end()) {\n      continue;\n    }\n\n    char buf[100];\n    sprintf(buf, \"/proc/%d/fd\", rt->tid);\n    DIR* dir = opendir(buf);\n    if (!dir && (errno == EACCES || errno == ENOENT)) {\n      LOG(warn) << \"Task must have exited out from underneath us. Skipping it\";\n      continue;\n    }\n    ASSERT(rt, dir) << \"Can't open fd directory \" << buf;\n    tables.insert(table.get());\n\n    struct dirent* d;\n    errno = 0;\n    vector<string> names;\n    while ((d = readdir(dir)) != nullptr) {\n      char* end;\n      int fd = strtol(d->d_name, &end, 10);\n      if (*end) {\n        // Some kind of parse error\n        continue;\n      }\n      struct stat fd_stat = rt->stat_fd(fd);\n      if (fd_stat.st_dev != file.st_dev || fd_stat.st_ino != file.st_ino) {\n        // Not our file\n        continue;\n      }\n      bool writable = is_writable(rt, fd);\n      if (table == mapped_table && fd == mapped_fd) {\n        // This is what we're using to do the mmap. Don't put it in extra_fds.\n        found_our_mapping = true;\n        our_mapping_writable = writable;\n        continue;\n      }\n      if (!writable) {\n        // Ignore non-writable fds since they can't modify memory\n        continue;\n      }\n      extra_fds.push_back({ rt->tid, fd });\n    }\n    ASSERT(rt, !errno) << \"Can't read fd directory \" << buf;\n    closedir(dir);\n  }\n  ASSERT(mapped_t, found_our_mapping) << \"Can't find fd for mapped file\";\n  return our_mapping_writable;\n}\n\nstatic bool os_has_broken_zfs() {\n  static bool is_broken = true, did_check = false;\n  if (did_check) {\n    return is_broken;\n  }\n  did_check = true;\n  DIR* zfs_dir = opendir(\"/sys/module/zfs\");\n  if (!zfs_dir) {\n    // No ZFS, so no bug\n    is_broken = false;\n    return false;\n  }\n  ScopedFd version_file_fd =\n      ScopedFd(openat(dirfd(zfs_dir), \"version\", O_RDONLY));\n  closedir(zfs_dir);\n  char version[50];\n  memset(version, 0, sizeof(version));\n  read(version_file_fd, version, sizeof(version) - 1);\n  int zfs_major = 0, zfs_minor = 0, zfs_patch = 0;\n  if (3 != sscanf(version, \"%d.%d.%d\", &zfs_major, &zfs_minor, &zfs_patch)) {\n    LOG(warn)\n        << \"Failed to parse /sys/module/zfs/version; assuming ZFS is broken\";\n    return true;\n  }\n  is_broken = !(zfs_major > 2 || (zfs_major == 2 && zfs_minor > 2));\n  return is_broken;\n}\n\n// On some versions of ZFS, SEEK_HOLE/SEEK_DATA is known to not be reliable\n// and potentially return spurious holes. Such holes would cause trace\n// corruption, so we must skip this optimizations on such ZFS versions.\nstatic bool may_have_zfs_seek_bug(ScopedFd& fd) {\n  static bool did_warn = false;\n  if (!os_has_broken_zfs())\n    return false;\n  // Check if this file is on ZFS.\n  struct statfs buf;\n  if (0 != fstatfs(fd, &buf)) {\n    // This really shouldn't fail, but let's be conservative\n    LOG(warn) << \"Failed to determine file system type for fd\";\n    return true;\n  }\n  int bad_file = (buf.f_type == ZFS_SUPER_MAGIC);\n  if (bad_file && !did_warn) {\n    LOG(warn)\n        << \"Detected access to file on ZFS < 2.3.0 which has known bugs.\\n\"\n        << \"Sparse file optimizations will be disabled.\";\n    did_warn = true;\n  }\n  return bad_file;\n}\n\n// The returned hole offsets are relative to 'offset'\nstatic vector<WriteHole> find_holes(RecordTask* t, int desc, uint64_t offset, uint64_t size) {\n  vector<WriteHole> ret;\n  ScopedFd fd = t->open_fd(desc, O_RDONLY);\n  if (!fd.is_open()) {\n    return ret;\n  }\n  if (may_have_zfs_seek_bug(fd)) {\n    return ret;\n  }\n  uint64_t file_start = offset;\n  uint64_t file_end = offset + size;\n  while (offset < file_end) {\n    off_t r = lseek(fd, offset, SEEK_HOLE);\n    if (r < 0) {\n      // SEEK_HOLE not supported?\n      return ret;\n    }\n    uint64_t hole = (uint64_t)r;\n    ASSERT(t, hole >= offset) << \"Found hole at \" << hole << \" which is before \" << offset;\n    if (hole >= file_end) {\n      return ret;\n    }\n    r = lseek(fd, hole, SEEK_DATA);\n    if (r < 0) {\n      if (errno == ENXIO) {\n        r = file_end;\n      } else {\n        return ret;\n      }\n    } else if (r == 0) {\n      // The file has no data.\n      r = file_end;\n    }\n    uint64_t data = min((uint64_t)r, file_end);\n    ASSERT(t, data > hole) << \"Found data at \" << data << \" which should be after hole \" << hole\n      << \"; file end \" << file_end << \", data offset \" << r;\n    ret.push_back({ hole - file_start, data - hole });\n    offset = data;\n  }\n  return ret;\n}\n\nstatic void check_outside_mappings(const KernelMapping& tracee_km, const RecordSession& session) {\n#if defined(__i386__)\n  struct utsname buf;\n  if (uname(&buf) != 0) {\n    FATAL() << \"Failed to read /proc\";\n  }\n  if (sizeof(void*) == 4 && strcmp(buf.machine, \"x86_64\") == 0) {\n      /* Running 32-bit rr at a 64-bit kernel is not going to work because\n       * the KernelMapIterator currently does not handle this combination. */\n      FATAL() << \"Cannot use --check_outside_mmaps with 32-bit rr at 64-bit kernel.\";\n  }\n#endif\n  DIR* proc = opendir(\"/proc\");\n  if (!proc) {\n    FATAL() << \"Failed to read /proc\";\n  }\n  while (true) {\n    struct dirent* f = readdir(proc);\n    if (!f) {\n      break;\n    }\n    pid_t pid = atoi(f->d_name);\n    if (pid) {\n      auto task = session.find_task(pid);\n      if (task) {\n        continue;\n      }\n      bool ok = false;\n      for (KernelMapIterator it(pid, &ok); ok && !it.at_end(); ++it) {\n        auto km = it.current();\n        if (km.device() == tracee_km.device() &&\n            km.inode() == tracee_km.inode() &&\n            km.prot() & PROT_WRITE)\n        {\n          printf(\"rr: Warning: Mapping of file %s could cause diversion when replaying, \"\n                 \"because pid=%d has mapped it outside of the recording.\\n\",\n                 km.fsname().c_str(), pid);\n          return;\n        }\n      }\n    }\n  }\n  closedir(proc);\n}\n\nstatic void process_mmap(RecordTask* t, size_t length, int prot, int flags,\n                         int fd, off_t offset) {\n  if (t->regs().syscall_failed()) {\n    // We purely emulate failed mmaps.\n    return;\n  }\n\n  size_t size = ceil_page_size(length);\n  remote_ptr<void> addr = t->regs().syscall_result();\n  if (flags & MAP_ANONYMOUS) {\n    KernelMapping km;\n    if (!(flags & MAP_SHARED)) {\n      // Anonymous mappings are by definition not backed by any file-like\n      // object, and are initialized to zero, so there's no nondeterminism to\n      // record.\n      km = t->vm()->map(t, addr, size, prot, flags, 0, string());\n    } else {\n      ASSERT(t, !(flags & MAP_GROWSDOWN));\n      // Read the kernel's mapping. There doesn't seem to be any other way to\n      // get the correct device/inode numbers. Fortunately anonymous shared\n      // mappings are rare.\n      KernelMapping kernel_info = t->vm()->read_kernel_mapping(t, addr);\n      km = t->vm()->map(t, addr, size, prot, flags, 0, kernel_info.fsname(),\n                        kernel_info.device(), kernel_info.inode());\n    }\n    auto d = t->trace_writer().write_mapped_region(t, km, km.fake_stat(), km.fsname(), vector<TraceRemoteFd>());\n    ASSERT(t, d == TraceWriter::DONT_RECORD_IN_TRACE);\n    return;\n  }\n\n  ASSERT(t, fd >= 0) << \"Valid fd required for file mapping\";\n  ASSERT(t, !(flags & MAP_GROWSDOWN));\n\n  bool effectively_anonymous = false;\n  auto st = t->stat_fd(fd);\n  string our_file_name =t->proc_fd_path(fd);\n  string tracee_file_name = t->file_name_of_fd(fd);\n  if (MAJOR(st.st_rdev) == 1 &&\n      MINOR(st.st_rdev) == 5) {\n    // mmapping /dev/zero is equivalent to MAP_ANONYMOUS, just more annoying.\n    // grab the device/inode from the kernel mapping so that it will be unique.\n    KernelMapping kernel_synthetic_info = t->vm()->read_kernel_mapping(t, addr);\n    st.st_dev = kernel_synthetic_info.device();\n    st.st_ino = kernel_synthetic_info.inode();\n    our_file_name = tracee_file_name = kernel_synthetic_info.fsname();\n    effectively_anonymous = true;\n  }\n\n  KernelMapping km =\n      t->vm()->map(t, addr, size, prot, flags, offset, tracee_file_name, st.st_dev,\n                   st.st_ino, unique_ptr<struct stat>(new struct stat(st)));\n\n  bool adjusted_size = false;\n  if (!st.st_size && !S_ISREG(st.st_mode)) {\n    // Some device files are mmappable but have zero size. Increasing the\n    // size here is safe even if the mapped size is greater than the real size.\n    st.st_size = offset + size;\n    adjusted_size = true;\n  }\n\n  vector<TraceRemoteFd> extra_fds;\n  bool monitor_this_fd = false;\n  if ((flags & MAP_SHARED) && !effectively_anonymous) {\n    monitor_this_fd = monitor_fd_for_mapping(t, fd, st, extra_fds);\n  }\n  if (t->trace_writer().write_mapped_region(t, km, st, our_file_name, extra_fds,\n                                            TraceWriter::SYSCALL_MAPPING,\n                                            !monitor_this_fd) ==\n      TraceWriter::RECORD_IN_TRACE) {\n    off_t end = (off_t)st.st_size - km.file_offset_bytes();\n    off_t nbytes = min(end, (off_t)km.size());\n    vector<WriteHole> holes = find_holes(t, fd, km.file_offset_bytes(), (uint64_t)nbytes);\n    ssize_t nread = t->record_remote_fallible(addr, nbytes, holes);\n    if (!adjusted_size && nread != nbytes) {\n      // If we adjusted the size, we're not guaranteed that the bytes we're\n      // reading are actually valid (it could actually have been a zero-sized\n      // file).\n      auto st2 = t->stat_fd(fd);\n      AddressSpace::print_process_maps(t);\n      if (system(\"df -h\")) {\n        // Couldn't run 'df'...\n      }\n      ASSERT(t, false) << \"Failed to read expected mapped data at \" << km\n          << \"; expected \" << nbytes << \" bytes, got \" << nread << \" bytes,\"\n          << \" got file size \" << st.st_size << \" before and \" << st2.st_size\n          << \" after; is filesystem full?\";\n    }\n  }\n  if ((flags & MAP_SHARED) && !effectively_anonymous) {\n    // Setting up MmappedFileMonitor may trigger updates to syscallbuf_fds_disabled\n    // in the tracee, recording memory records. Those should be recorded now, after the\n    // memory region data itself. Needs to be consistent with replay_syscall.\n    if (monitor_this_fd) {\n      extra_fds.push_back({ t->tid, fd});\n    }\n    for (auto& f : extra_fds) {\n      auto rt = t->session().find_task(f.tid);\n      if (rt->fd_table()->is_monitoring(f.fd)) {\n        auto type = rt->fd_table()->get_monitor(f.fd)->type();\n        if (type == FileMonitor::Type::Mmapped) {\n          ((MmappedFileMonitor*)rt->fd_table()->get_monitor(f.fd))->revive();\n        } else if (type == FileMonitor::Type::ODirect) {\n          rt->fd_table()->replace_monitor(rt, f.fd, new MmappedFileMonitor(rt, f.fd));\n        } else {\n          ASSERT(rt, false)\n              << \"Expected monitor type Mmapped | ODirect for fd \" << f.fd << \", got monitor type \"\n              << file_monitor_type_name(type);\n        }\n      } else {\n        rt->fd_table()->add_monitor(rt, f.fd, new MmappedFileMonitor(rt, f.fd));\n      }\n    }\n\n    if ((prot & PROT_WRITE)) {\n      LOG(debug) << tracee_file_name <<\n        \" is SHARED|writable; that's not handled \"\n        \"correctly yet. Optimistically hoping it's not \"\n        \"written by programs outside the rr tracee \"\n        \"tree.\";\n    }\n\n    if (t->session().check_outside_mmaps()) {\n      check_outside_mappings(km, t->session());\n    }\n  }\n\n  // We don't want to patch MAP_SHARED files. In the best case we'd end crashing\n  // at an assertion, in the worst case, we'd end up modifying the underlying\n  // file.\n  if (!(flags & MAP_SHARED)) {\n    t->vm()->monkeypatcher().patch_after_mmap(t, addr, size, offset, prot, fd,\n                                              Monkeypatcher::MMAP_SYSCALL);\n  }\n\n  if ((prot & (PROT_WRITE | PROT_READ)) == PROT_READ && (flags & MAP_SHARED) &&\n      !effectively_anonymous) {\n    MonitoredSharedMemory::maybe_monitor(t, tracee_file_name,\n                                         t->vm()->mapping_of(addr), fd, offset);\n  }\n}\n\nstatic void process_mremap(RecordTask* t, remote_ptr<void> old_addr,\n                           size_t old_length, size_t new_length, int flags) {\n  if (t->regs().syscall_failed()) {\n    // We purely emulate failed mremaps.\n    return;\n  }\n\n  size_t old_size = ceil_page_size(old_length);\n  size_t new_size = ceil_page_size(new_length);\n  remote_ptr<void> new_addr = t->regs().syscall_result();\n\n  t->vm()->remap(t, old_addr, old_size, new_addr, new_size, flags);\n  AddressSpace::Mapping m = t->vm()->mapping_of(new_addr);\n  KernelMapping km =\n      m.map.subrange(new_addr, new_addr + min(new_size, old_size));\n  struct stat st = m.mapped_file_stat ? *m.mapped_file_stat : km.fake_stat();\n\n  // Make sure that the trace records the mapping at the new location, even\n  // if the mapping didn't grow.\n  auto r = t->trace_writer().write_mapped_region(t, km, st, km.fsname(),\n                                                 vector<TraceRemoteFd>(),\n                                                 TraceWriter::REMAP_MAPPING);\n  ASSERT(t, r == TraceWriter::DONT_RECORD_IN_TRACE);\n  if (old_size >= new_size) {\n    return;\n  }\n\n  // Now record the new part of the mapping.\n  km = m.map.subrange(new_addr + old_size, new_addr + new_size);\n  if (!st.st_size) {\n    // Some device files are mmappable but have zero size. Increasing the\n    // size here is safe even if the mapped size is greater than the real size.\n    st.st_size = m.map.file_offset_bytes() + new_size;\n  }\n\n  if (t->trace_writer().write_mapped_region(t, km, st, km.fsname(),\n                                            vector<TraceRemoteFd>()) ==\n      TraceWriter::RECORD_IN_TRACE) {\n    off_t end = max<off_t>(st.st_size - km.file_offset_bytes(), 0);\n    // Allow failure; the underlying file may have true zero size, in which\n    // case this may try to record unmapped memory.\n    t->record_remote_fallible(km.start(), min(end, (off_t)km.size()));\n  }\n\n  // If the original mapping was monitored, we'll continue monitoring it\n  // automatically.\n}\n\nstatic void process_shmat(RecordTask* t, int shmid, int shm_flags,\n                          remote_ptr<void> addr) {\n  if (t->regs().syscall_failed()) {\n    // We purely emulate failed shmats.\n    return;\n  }\n\n  struct shmid64_ds ds;\n  int ret = _shmctl(shmid, IPC_STAT, &ds);\n  msan_unpoison(&ds, sizeof(semid64_ds));\n  ASSERT(t, !ret) << \"shmid should be readable by rr since rr has the same \"\n                     \"UID as tracees\";\n  size_t size = ceil_page_size(ds.shm_segsz);\n\n  int prot = shm_flags_to_mmap_prot(shm_flags);\n  int flags = MAP_SHARED;\n\n  // Read the kernel's mapping for the shm segment. There doesn't seem to be\n  // any other way to get the correct device number. (The inode number seems to\n  // be the shm key.) This should be OK since SysV shmem is not used very much\n  // and reading /proc/<pid>/maps should be reasonably cheap.\n  KernelMapping kernel_info = t->vm()->read_kernel_mapping(t, addr);\n  KernelMapping km =\n      t->vm()->map(t, addr, size, prot, flags, 0, kernel_info.fsname(),\n                   kernel_info.device(), kernel_info.inode());\n  t->vm()->set_shm_size(km.start(), km.size());\n  auto disposition =\n      t->trace_writer().write_mapped_region(t, km, km.fake_stat(), km.fsname(), vector<TraceRemoteFd>());\n  ASSERT(t, disposition == TraceWriter::RECORD_IN_TRACE);\n  t->record_remote(addr, size);\n\n  LOG(debug) << \"Optimistically hoping that SysV segment is not used outside \"\n                \"of tracees\";\n}\n\nstatic void maybe_process_new_socket(RecordTask* t, int fd) {\n  if (t->regs().syscall_failed()) {\n    return;\n  }\n\n  std::array<typename NativeArch::sockaddr_storage, 2> socket_addresses;\n  if (!read_proc_net_socket_addresses(t, fd, socket_addresses)) {\n    return;\n  }\n\n  auto& syscall = t->ev().Syscall();\n  syscall.socket_addrs = make_shared<std::array<typename NativeArch::sockaddr_storage, 2>>(std::move(socket_addresses));\n}\n\ntemplate <typename Arch>\nstatic string extra_expected_errno_info(RecordTask* t,\n                                        TaskSyscallState& syscall_state) {\n  stringstream ss;\n  switch (syscall_state.expect_errno) {\n    case ENOSYS:\n      ss << \"; execution of syscall unsupported by rr\";\n      break;\n    case EINVAL:\n      switch (t->regs().original_syscallno()) {\n        case Arch::ioctl: {\n          int request = (int)t->regs().arg2_signed();\n          if (request == SIOCETHTOOL) {\n            auto ifreq_ptr = remote_ptr<typename Arch::ifreq>(t->regs().arg3());\n            auto ifreq = t->read_mem(ifreq_ptr);\n            remote_ptr<void> cmd_ptr = ifreq.ifr_ifru.ifru_data.rptr();\n            auto cmd = t->read_mem(cmd_ptr.cast<uint32_t>());\n            ss << \"; unknown ETHTOOL command \" << cmd;\n          } else {\n            int type = _IOC_TYPE(request);\n            int nr = _IOC_NR(request);\n            int dir = _IOC_DIR(request);\n            int size = _IOC_SIZE(request);\n            ss << \"; Unknown ioctl(\" << HEX(request) << \"): type:\" << HEX(type)\n               << \" nr:\" << HEX(nr) << \" dir:\" << HEX(dir) << \" size:\" << size\n               << \" addr:\" << HEX(t->regs().arg3());\n          }\n          break;\n        }\n        case Arch::fcntl:\n        case Arch::fcntl64:\n          ss << \"; unknown fcntl(\" << HEX((int)t->regs().arg2_signed()) << \")\";\n          break;\n        case Arch::prctl: {\n          int request = (int)t->regs().orig_arg1_signed();\n          if (request == PR_SET_MM) {\n            ss << \"; unknown prctl(PR_SET_MM, \" << HEX((int)t->regs().arg2_signed()) << \")\";\n          } else {\n            ss << \"; unknown prctl(\" << HEX(request) << \")\";\n          }\n          break;\n        }\n        case Arch::arch_prctl:\n          ss << \"; unknown arch_prctl(\" << HEX((int)t->regs().orig_arg1_signed())\n             << \")\";\n          break;\n        case Arch::keyctl:\n          ss << \"; unknown keyctl(\" << HEX((int)t->regs().orig_arg1_signed()) << \")\";\n          break;\n        case Arch::socketcall:\n          ss << \"; unknown socketcall(\" << HEX((int)t->regs().orig_arg1_signed())\n             << \")\";\n          break;\n        case Arch::ipc:\n          ss << \"; unknown ipc(\" << HEX((int)t->regs().orig_arg1_signed()) << \")\";\n          break;\n        case Arch::futex_time64:\n        case Arch::futex:\n          ss << \"; unknown futex(\"\n             << HEX((int)t->regs().arg2_signed() & FUTEX_CMD_MASK) << \")\";\n          break;\n        case Arch::waitid:\n          ss << \"; unknown waitid(\" << HEX((idtype_t)t->regs().orig_arg1()) << \")\";\n          break;\n        case Arch::seccomp:\n          ss << \"; unknown seccomp(\" << HEX((unsigned int)t->regs().orig_arg1())\n             << \")\";\n          break;\n        case Arch::madvise:\n          ss << \"; unknown madvise(\" << (int)t->regs().arg3() << \")\";\n          break;\n        case Arch::bpf:\n          ss << \"; unknown bpf(cmd=\" << (int)t->regs().orig_arg1_signed() << \")\";\n          break;\n      }\n      break;\n    case EIO:\n      switch (t->regs().original_syscallno()) {\n        case Arch::ptrace:\n          ss << \"; unsupported ptrace(\" << HEX((int)t->regs().orig_arg1_signed()) << \" [\"\n             << ptrace_req_name<Arch>((int)t->regs().orig_arg1_signed()) << \"])\";\n          break;\n      }\n      break;\n  }\n  return ss.str();\n}\n\nstatic bool is_rr_fd_terminal(int fd, const string& pathname) {\n  char buf[PATH_MAX];\n  if (ttyname_r(fd, buf, sizeof(buf))) {\n    return false;\n  }\n  buf[sizeof(buf) - 1] = 0;\n  return pathname == buf;\n}\n\nstatic bool is_rr_terminal(const string& pathname) {\n  if (pathname == \"/dev/tty\") {\n    // XXX the tracee's /dev/tty could refer to a tty other than\n    // the recording tty, in which case output should not be\n    // redirected. That's not too bad, replay will still work, just\n    // with some spurious echoes.\n    return true;\n  }\n\n  return is_rr_fd_terminal(STDIN_FILENO, pathname) ||\n         is_rr_fd_terminal(STDOUT_FILENO, pathname) ||\n         is_rr_fd_terminal(STDERR_FILENO, pathname);\n}\n\nstatic int dev_tty_fd() {\n  static int fd = -1;\n  if (fd < 0) {\n    fd = open(\"/dev/tty\", O_WRONLY | O_CLOEXEC);\n  }\n  return fd;\n}\n\ntemplate <typename Arch>\nstatic void record_iovec_output(RecordTask* t, RecordTask* dest,\n                                remote_ptr<typename Arch::iovec> piov,\n                                uint32_t iov_cnt) {\n  // Ignore the syscall result, the kernel may have written more data than that.\n  // See https://bugzilla.kernel.org/show_bug.cgi?id=113541\n  auto iovs = t->read_mem(piov, iov_cnt);\n  for (auto& iov : iovs) {\n    dest->record_remote_writable(iov.iov_base, iov.iov_len);\n  }\n}\n\nstatic bool all_tasks_exited(AddressSpace* vm) {\n  for (Task* t : vm->task_set()) {\n    if (!t->already_exited()) {\n      return false;\n    }\n  }\n  return true;\n}\n\nstatic bool is_mapped_shared(RecordTask* t, const struct stat& st) {\n  for (AddressSpace* vm : t->session().vms()) {\n    if (all_tasks_exited(vm)) {\n      continue;\n    }\n    for (auto& m : vm->maps()) {\n      if ((m.map.flags() & MAP_SHARED) &&\n          m.mapped_file_stat && m.mapped_file_stat->st_dev == st.st_dev &&\n          m.mapped_file_stat->st_ino == st.st_ino) {\n        LOG(debug) << \"is_mapped_shared is shared: \"\n          << st.st_dev << \" \" << st.st_ino;\n        return true;\n      }\n    }\n  }\n  return false;\n}\n\n// Returns the file path. This could be a blacklisted file so don't\n// do anything for blacklisted files.\nstatic string handle_opened_file(RecordTask* t, int fd, int flags) {\n  string pathname = t->file_name_of_fd(fd);\n  struct stat st = t->stat_fd(fd);\n\n  // This must be kept in sync with replay_syscall's handle_opened_files.\n  FileMonitor* file_monitor = nullptr;\n  if (is_writable(t, fd) && is_mapped_shared(t, st)) {\n    // This is quite subtle. Because open(2) is ALLOW_SWITCH, we could have been\n    // descheduled after entering the syscall we're now exiting. If that happened,\n    // and another task did a shared mapping of this file while we were suspended,\n    // it would have trawled the proc filesystem looking for other open fds for\n    // the same file. If this syscall had been completed in the kernel by then,\n    // it will have already installed this monitor for us. So we must allow this\n    // benign race.\n    if (t->fd_table()->is_monitoring(fd)) {\n      LOG(debug) << \"Already monitoring \" << fd;\n        ASSERT(t,\n               t->fd_table()->get_monitor(fd)->type() ==\n               FileMonitor::Type::Mmapped);\n    } else {\n      // The normal case, we are unmonitored because we are a new file.\n      LOG(info) << \"Installing MmappedFileMonitor for \" << fd;\n      file_monitor = new MmappedFileMonitor(t, fd);\n    }\n  } else if (is_rr_terminal(pathname)) {\n    // This will let rr event annotations echo to the terminal. It will also\n    // ensure writes to this fd are not syscall-buffered.\n    LOG(info) << \"Installing StdioMonitor for \" << fd;\n    file_monitor = new StdioMonitor(dev_tty_fd());\n    pathname = \"terminal\";\n  } else if (is_proc_mem_file(pathname.c_str())) {\n    LOG(info) << \"Installing ProcMemMonitor for \" << fd;\n    file_monitor = new ProcMemMonitor(t, pathname);\n  } else if (is_proc_fd_dir(pathname.c_str())) {\n    LOG(info) << \"Installing ProcFdDirMonitor for \" << fd;\n    file_monitor = new ProcFdDirMonitor(t, pathname);\n  } else if (is_sys_cpu_online_file(pathname.c_str())) {\n    LOG(info) << \"Installing SysCpuMonitor for \" << fd;\n    file_monitor = new SysCpuMonitor(t, pathname);\n  } else if (is_proc_stat_file(pathname.c_str())) {\n    LOG(info) << \"Installing ProcStatMonitor for \" << fd;\n    file_monitor = new ProcStatMonitor(t, pathname);\n  } else if (is_rr_page_lib(pathname.c_str())) {\n    LOG(info) << \"Installing RRPageMonitor for \" << fd;\n    file_monitor = new RRPageMonitor();\n  } else if (flags & O_DIRECT) {\n    // O_DIRECT can impose unknown alignment requirements, in which case\n    // syscallbuf records will not be properly aligned and will cause I/O\n    // to fail. Disable syscall buffering for O_DIRECT files.\n    LOG(info) << \"Installing ODirectFileMonitor for O_DIRECT \" << fd;\n    file_monitor = new ODirectFileMonitor();\n  }\n\n  if (file_monitor) {\n    // Write absolute file name\n    auto& syscall = t->ev().Syscall();\n    syscall.opened.push_back({ pathname, fd, st.st_dev, st.st_ino });\n    t->fd_table()->add_monitor(t, fd, file_monitor);\n  }\n  return pathname;\n}\n\ntemplate <typename Arch>\nstatic void check_scm_rights_fd(RecordTask* t, typename Arch::msghdr& msg) {\n  if (msg.msg_controllen < sizeof(typename Arch::cmsghdr)) {\n    return;\n  }\n  auto data = t->read_mem(msg.msg_control.rptr().template cast<uint8_t>(),\n                          msg.msg_controllen);\n  size_t index = 0;\n  while (true) {\n    auto cmsg = reinterpret_cast<typename Arch::cmsghdr*>(data.data() + index);\n    if (cmsg->cmsg_len < sizeof(*cmsg) ||\n        index + Arch::cmsg_align(cmsg->cmsg_len) > data.size()) {\n      break;\n    }\n    if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {\n      int* fds = static_cast<int*>(Arch::cmsg_data(cmsg));\n      int fd_count = (cmsg->cmsg_len - sizeof(*cmsg)) / sizeof(int);\n      for (int i = 0; i < fd_count; ++i) {\n        handle_opened_file(t, fds[i], 0);\n      }\n    }\n    index += Arch::cmsg_align(cmsg->cmsg_len);\n    if (index + sizeof(*cmsg) > data.size()) {\n      break;\n    }\n  }\n}\n\nstatic void fake_gcrypt_file(RecordTask* t, Registers* r) {\n  // We hijacked this call to deal with /etc/gcrypt/hwf.deny.\n  char fname[255];\n  snprintf(fname, sizeof(fname), \"rr-gcrypt-hwf-deny-%d\", getpid());\n  ScopedFd fd(open_memory_file(fname));\n\n  struct stat dummy;\n  if (!stat(\"/etc/gcrypt/hwf.deny\", &dummy)) {\n    // Copy the contents into our temporary file\n    ScopedFd existing(\"/etc/gcrypt/hwf.deny\", O_RDONLY);\n    if (!copy_file(fd, existing)) {\n      FATAL() << \"Can't copy file\";\n    }\n  }\n\n  static const char disable_rdrand[] = \"\\nintel-rdrand\\n\";\n  write_all(fd, disable_rdrand, sizeof(disable_rdrand) - 1);\n\n  // Now open the file in the child.\n  int child_fd;\n  {\n    AutoRemoteSyscalls remote(t);\n    lseek(fd, 0, SEEK_SET);\n    child_fd = remote.infallible_send_fd_if_alive(fd);\n    if (child_fd < 0) {\n      // Tracee died.\n      return;\n    }\n  }\n\n  // And hand out our fake file\n  r->set_syscall_result(child_fd);\n}\n\nstatic void record_madvise(RecordTask* t) {\n  Registers regs = t->regs();\n  remote_ptr<void> start = floor_page_size(remote_ptr<void>(regs.orig_arg1()));\n  remote_ptr<void> end = ceil_page_size(start + regs.arg2());\n  int advice = regs.arg3();\n  int result = regs.syscall_result_signed();\n  if (end <= start || !result || start != regs.orig_arg1()) {\n    // Everything was affected according to the madvise\n    // parameters, so we don't need to record anything special.\n    return;\n  }\n  switch (advice) {\n    case MADV_DONTNEED:\n    case MADV_DONTNEED_LOCKED:\n      for (const auto& m : t->vm()->maps_containing_or_after(start)) {\n        MemoryRange r = m.map.intersect(MemoryRange(start, end));\n        if (!r.size()) {\n          break;\n        }\n        vector<MemoryRange> pages_present = find_pages(t, r,\n                                                       PageState::NOT_PRESENT);\n        auto& ranges = t->ev().Syscall().madvise_ranges;\n        ranges.insert(ranges.end(), pages_present.begin(), pages_present.end());\n      }\n      break;\n    case MADV_REMOVE: {\n      for (const auto& m : t->vm()->maps_containing_or_after(start)) {\n        if (m.map.start() >= end) {\n          break;\n        }\n        if (m.map.flags() & MAP_PRIVATE) {\n          // Private mappings fail cleanly with MADV_REMOVE so we\n          // don't need to worry about any effects on them.\n          continue;\n        }\n        // We don't handle this yet...\n        ASSERT(t, false) << \"Possibly-partial MADV_REMOVEs not handled yet\";\n      }\n      break;\n    }\n    default:\n      break;\n  }\n}\n\ntemplate <typename Arch>\nstatic void rec_process_syscall_arch(RecordTask* t,\n                                     TaskSyscallState& syscall_state) {\n  int syscallno = t->ev().Syscall().number;\n\n  if (t->regs().original_syscallno() == SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO) {\n    // rr vetoed this syscall. Don't do any post-processing.\n    return;\n  }\n\n  LOG(debug) << t->tid << \": processing: \" << t->ev()\n             << \" -- time: \" << t->trace_time();\n\n  if (remote_ptr<const struct syscallbuf_record> rec = t->desched_rec()) {\n    // If the syscallbuf has already been unmapped, there's no need to record\n    // the entry.\n    if (t->syscallbuf_child) {\n      t->record_remote(REMOTE_PTR_FIELD(rec, extra_data),\n                       t->read_mem(REMOTE_PTR_FIELD(rec, size)) -\n                           sizeof(struct syscallbuf_record));\n    }\n    return;\n  }\n\n  if (syscall_state.expect_errno) {\n    if (syscall_state.expect_errno == EINVAL && syscallno == Arch::ioctl &&\n        t->regs().syscall_result_signed() == -ENOTTY) {\n      // Unsupported ioctl was called, but is not supported for this device,\n      // so we can safely ignore it.\n      return;\n    }\n    ASSERT(t, t->regs().syscall_result_signed() == -syscall_state.expect_errno)\n        << \"Expected \" << errno_name(syscall_state.expect_errno) << \" for '\"\n        << syscall_name(syscallno, Arch::arch()) << \"' but got result \"\n        << t->regs().syscall_result_signed() << \" (errno \"\n        << errno_name(-t->regs().syscall_result_signed()) << \")\"\n        << extra_expected_errno_info<Arch>(t, syscall_state);\n    if (syscallno == Arch::execve || syscallno == Arch::execveat) {\n      t->session().scheduler().did_exit_execve(t);\n    }\n    return;\n  }\n\n  // Here we handle syscalls that need work that can only happen after the\n  // syscall completes --- and that our TaskSyscallState infrastructure can't\n  // handle.\n  switch (syscallno) {\n    case Arch::vfork:\n    case Arch::fork:\n    case Arch::clone:\n      if ((syscallno == Arch::vfork ||\n           (syscallno == Arch::clone && (t->regs().orig_arg1() & CLONE_VFORK))) &&\n          (t->emulated_ptrace_options & PTRACE_O_TRACEVFORKDONE)) {\n        t->emulate_ptrace_stop(\n            WaitStatus::for_ptrace_event(PTRACE_EVENT_VFORK_DONE));\n      }\n      if (Arch::is_x86ish()) {\n        // On a 3.19.0-39-generic #44-Ubuntu kernel we have observed clone()\n        // clearing the parity flag internally.\n        Registers r = t->regs();\n        r.set_flags(syscall_state.syscall_entry_registers.flags());\n        t->set_regs(r);\n      }\n      break;\n\n    case Arch::execve:\n    case Arch::execveat:\n      process_execve(t, syscall_state);\n      break;\n\n    case Arch::brk: {\n      remote_ptr<void> old_brk = ceil_page_size(t->vm()->current_brk());\n      remote_ptr<void> new_brk = ceil_page_size(t->regs().syscall_result());\n      KernelMapping km;\n      // This should be a nop.\n      // Otherwise we end up writing a redundant (though seemingly benign) zero length mapped region in the trace.\n      if (old_brk == new_brk) {\n        LOG(debug) << \"brk(\" << new_brk << \"). Unchanged from old brk, so doing nothing\";\n        break;\n      }\n      if (old_brk < new_brk) {\n        // Read the kernel's mapping. There doesn't seem to be any other way to\n        // get the correct prot bits for heaps. Usually it's READ|WRITE but\n        // there seem to be exceptions depending on system settings.\n        KernelMapping kernel_info = t->vm()->read_kernel_mapping(t, old_brk);\n        ASSERT(t, kernel_info.device() == KernelMapping::NO_DEVICE);\n        ASSERT(t, kernel_info.inode() == KernelMapping::NO_INODE);\n        km = kernel_info.subrange(old_brk, new_brk);\n      } else {\n        // Write a dummy KernelMapping that indicates an unmap\n        km = KernelMapping(new_brk, old_brk, string(), KernelMapping::NO_DEVICE,\n                           KernelMapping::NO_INODE, 0, 0, 0);\n      }\n      auto d = t->trace_writer().write_mapped_region(t, km, km.fake_stat(), km.fsname(), vector<TraceRemoteFd>());\n      ASSERT(t, d == TraceWriter::DONT_RECORD_IN_TRACE);\n      t->vm()->brk(t, t->regs().syscall_result(), km.prot());\n      break;\n    }\n\n    case Arch::mmap:\n      switch (Arch::mmap_semantics) {\n        case Arch::StructArguments: {\n          auto args = t->read_mem(\n              remote_ptr<typename Arch::mmap_args>(t->regs().orig_arg1()));\n          process_mmap(t, args.len, args.prot, args.flags, args.fd,\n                       args.offset);\n          break;\n        }\n        case Arch::RegisterArguments: {\n          Registers r = t->regs();\n          r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n          r.set_arg4(syscall_state.syscall_entry_registers.arg4_signed());\n          process_mmap(t, (size_t)r.arg2(), (int)r.arg3_signed(),\n                       (int)r.arg4_signed(), (int)r.arg5_signed(),\n                       ((off_t)r.arg6_signed()));\n          r.set_arg2(syscall_state.syscall_entry_registers.arg2_signed());\n          r.set_arg3(syscall_state.syscall_entry_registers.arg3_signed());\n          r.set_arg5(syscall_state.syscall_entry_registers.arg5_signed());\n          t->set_regs(r);\n          break;\n        }\n      }\n      break;\n\n    case Arch::mmap2: {\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      r.set_arg4(syscall_state.syscall_entry_registers.arg4_signed());\n      process_mmap(t, (size_t)r.arg2(), (int)r.arg3_signed(),\n                   (int)r.arg4_signed(), (int)r.arg5_signed(),\n                   (off_t)r.arg6_signed() * 4096);\n      r.set_arg2(syscall_state.syscall_entry_registers.arg2_signed());\n      r.set_arg3(syscall_state.syscall_entry_registers.arg3_signed());\n      r.set_arg5(syscall_state.syscall_entry_registers.arg5_signed());\n      t->set_regs(r);\n      break;\n    }\n\n    case Arch::mremap:\n      process_mremap(t, t->regs().orig_arg1(), t->regs().arg2(), t->regs().arg3(),\n                     (int)t->regs().arg4_signed());\n      break;\n\n    case Arch::shmat:\n      process_shmat(t, (int)t->regs().orig_arg1_signed(),\n                    (int)t->regs().arg3_signed(), t->regs().syscall_result());\n      break;\n\n    case Arch::ipc:\n      switch ((int)t->regs().orig_arg1_signed()) {\n        case SHMAT: {\n          auto out_ptr = t->read_mem(\n              remote_ptr<typename Arch::unsigned_long>(t->regs().arg4()));\n          process_shmat(t, (int)t->regs().arg2_signed(),\n                        (int)t->regs().arg3_signed(), out_ptr);\n          break;\n        }\n        default:\n          break;\n      }\n      break;\n\n    case Arch::bpf:\n      if (!t->regs().syscall_failed()) {\n        switch ((int)t->regs().orig_arg1()) {\n          case RR_BPF_MAP_CREATE: {\n            int fd = t->regs().syscall_result_signed();\n            auto attr = t->read_mem(remote_ptr<typename Arch::bpf_attr>(t->regs().arg2()));\n            t->fd_table()->add_monitor(t, fd, new BpfMapMonitor(attr.key_size, attr.value_size));\n            break;\n          }\n          default:\n            break;\n        }\n      }\n      break;\n\n    case Arch::clock_nanosleep:\n    case Arch::nanosleep: {\n      /* If the sleep completes, the kernel doesn't\n       * write back to the remaining-time\n       * argument. */\n      if (!(int)t->regs().syscall_result_signed()) {\n        syscall_state.write_back = TaskSyscallState::NO_WRITE_BACK;\n      }\n      break;\n    }\n\n    case Arch::perf_event_open:\n      if (!t->regs().syscall_failed()) {\n        int fd = t->regs().syscall_result_signed();\n        if (t->regs().original_syscallno() == Arch::inotify_init1) {\n          Registers r = t->regs();\n          r.set_original_syscallno(\n              syscall_state.syscall_entry_registers.original_syscallno());\n          r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n          t->set_regs(r);\n          auto attr =\n              t->read_mem(remote_ptr<struct perf_event_attr>(t->regs().orig_arg1()));\n          t->fd_table()->add_monitor(t,\n              fd, new VirtualPerfCounterMonitor(\n                      t, t->session().find_task((pid_t)t->regs().arg2_signed()),\n                      attr));\n        } else if (t->ip() != t->vm()->privileged_traced_syscall_ip().increment_by_syscall_insn_length(t->arch())) {\n          // Ignoring perf_event_open from syscallbuf; we'll attach a PreserveFileMonitor to it if it stays open\n          t->fd_table()->add_monitor(t, fd, new NonvirtualPerfCounterMonitor());\n        }\n      }\n      break;\n\n    case Arch::connect: {\n      // Restore the registers that we may have altered.\n      Registers r = t->regs();\n      if (r.original_syscallno() == Arch::gettid) {\n        // We hijacked this call to deal with blacklisted sockets\n        r.set_original_syscallno(Arch::connect);\n        r.set_syscall_result(-EACCES);\n        t->set_regs(r);\n      }\n      maybe_process_new_socket(t, r.orig_arg1());\n      break;\n    }\n\n    case Arch::accept:\n    case Arch::accept4: {\n      Registers r = t->regs();\n      maybe_process_new_socket(t, r.syscall_result());\n      break;\n    }\n\n    case Arch::open:\n    case Arch::openat:\n    case Arch::openat2: {\n      Registers r = t->regs();\n      if (r.syscall_failed()) {\n        uintptr_t path = syscallno == Arch::open ? r.orig_arg1() : r.arg2();\n        bool ok = true;\n        string pathname = t->read_c_str(remote_ptr<char>(path), &ok);\n        if (ok && is_gcrypt_deny_file(pathname.c_str())) {\n          fake_gcrypt_file(t, &r);\n          t->set_regs(r);\n        }\n      } else {\n        int fd = r.syscall_result_signed();\n\n        int flags;\n        switch (syscallno) {\n        case Arch::open:\n          flags = r.arg2();\n          break;\n        case Arch::openat:\n          flags = r.arg3();\n          break;\n        case Arch::openat2:\n          flags = t->read_mem(remote_ptr<int64_t>(r.arg3()));\n          break;\n        default:\n          DEBUG_ASSERT(0 && \"Unknown syscallno\");\n          __builtin_unreachable();\n        }\n\n        string pathname = handle_opened_file(t, fd, flags);\n        bool gcrypt = is_gcrypt_deny_file(pathname.c_str());\n        if (gcrypt || is_blacklisted_filename(pathname.c_str())) {\n          {\n            AutoRemoteSyscalls remote(t);\n            remote.infallible_close_syscall_if_alive(fd);\n          }\n          if (gcrypt) {\n            fake_gcrypt_file(t, &r);\n          } else {\n            LOG(warn) << \"Cowardly refusing to open \" << pathname;\n            r.set_syscall_result(-ENOENT);\n          }\n          t->set_regs(r);\n        }\n      }\n      break;\n    }\n\n    case SYS_rrcall_notify_control_msg: {\n      auto msg =\n          t->read_mem(remote_ptr<typename Arch::msghdr>(t->regs().orig_arg1()));\n      check_scm_rights_fd<Arch>(t, msg);\n      break;\n    }\n\n    case Arch::recvmsg:\n      if (!t->regs().syscall_failed()) {\n        auto msg =\n            t->read_mem(remote_ptr<typename Arch::msghdr>(t->regs().arg2()));\n        check_scm_rights_fd<Arch>(t, msg);\n      }\n      break;\n\n    case Arch::recvmmsg_time64:\n    case Arch::recvmmsg:\n      if (!t->regs().syscall_failed()) {\n        int msg_count = (int)t->regs().syscall_result_signed();\n        auto msgs = t->read_mem(\n            remote_ptr<typename Arch::mmsghdr>(t->regs().arg2()), msg_count);\n        for (auto& m : msgs) {\n          check_scm_rights_fd<Arch>(t, m.msg_hdr);\n        }\n      }\n      break;\n\n    case Arch::sched_getaffinity: {\n      pid_t pid = (pid_t)t->regs().orig_arg1();\n      if (!t->regs().syscall_failed() && (pid == 0 || pid == t->rec_tid)) {\n        if (t->regs().syscall_result() > sizeof(cpu_set_t)) {\n          LOG(warn) << \"Don't understand kernel's sched_getaffinity result\";\n        } else {\n          t->write_bytes_helper(t->regs().arg3(), t->regs().syscall_result(),\n              &t->session().scheduler().pretend_affinity_mask());\n        }\n      }\n      break;\n    }\n\n    case Arch::setsockopt: {\n      // restore possibly-modified regs\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      t->set_regs(r);\n      break;\n    }\n\n    case Arch::socketcall: {\n      // restore possibly-modified regs\n      Registers r = t->regs();\n      if (r.original_syscallno() == Arch::gettid) {\n        // `connect` was suppressed\n        r.set_syscall_result(-EACCES);\n      }\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      r.set_original_syscallno(\n          syscall_state.syscall_entry_registers.original_syscallno());\n      t->set_regs(r);\n\n      if (!t->regs().syscall_failed()) {\n        switch ((int)t->regs().orig_arg1_signed()) {\n          case SYS_RECVMSG: {\n            auto args = t->read_mem(\n                remote_ptr<typename Arch::recvmsg_args>(t->regs().arg2()));\n            auto msg = t->read_mem(args.msg.rptr());\n            check_scm_rights_fd<Arch>(t, msg);\n            break;\n          }\n          case SYS_RECVMMSG: {\n            auto args = t->read_mem(\n                remote_ptr<typename Arch::recvmmsg_args>(t->regs().arg2()));\n            int msg_count = (int)t->regs().syscall_result_signed();\n            auto msgs = t->read_mem(args.msgvec.rptr(), msg_count);\n            for (auto& m : msgs) {\n              check_scm_rights_fd<Arch>(t, m.msg_hdr);\n            }\n            break;\n          }\n          case SYS_CONNECT: {\n            auto args = t->read_mem(\n                remote_ptr<typename Arch::connect_args>(t->regs().arg2()));\n            maybe_process_new_socket(t, args.sockfd);\n            break;\n          }\n          case SYS_ACCEPT:\n          case SYS_ACCEPT4: {\n            Registers r = t->regs();\n            maybe_process_new_socket(t, r.syscall_result());\n            break;\n          }\n        }\n      }\n      break;\n    }\n\n    case Arch::process_vm_readv:\n      record_iovec_output<Arch>(t, t, t->regs().arg2(), t->regs().arg3());\n      break;\n\n    case Arch::process_vm_writev: {\n      RecordTask* dest = t->session().find_task(t->regs().orig_arg1());\n      if (dest) {\n        record_iovec_output<Arch>(t, dest, t->regs().arg4(), t->regs().arg5());\n      }\n      break;\n    }\n\n    case Arch::fcntl:\n    case Arch::fcntl64: {\n      // Restore the registers that we may have altered.\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      r.set_arg2(syscall_state.syscall_entry_registers.arg2());\n      r.set_arg3(syscall_state.syscall_entry_registers.arg3());\n      t->set_regs(r);\n\n      if (!r.syscall_failed() && r.arg3() == O_DIRECT) {\n        int fd = r.orig_arg1();\n        // O_DIRECT can impose unknown alignment requirements, in which case\n        // syscallbuf records will not be properly aligned and will cause I/O\n        // to fail. Disable syscall buffering for O_DIRECT files.\n        // If it already has a monitor (e.g. somebody tries to O_DIRECT\n        // /proc/pid/mem or something) then we don't need to do anything.\n        // since syscall buffering is already disabled.\n        if (!t->fd_table()->get_monitor(fd)) {\n          LOG(info) << \"Installing ODirectFileMonitor for O_DIRECT \" << fd;\n          FileMonitor* file_monitor = new ODirectFileMonitor();\n          t->fd_table()->add_monitor(t, fd, file_monitor);\n        }\n      }\n      break;\n    }\n\n    case Arch::madvise: {\n      Registers r = t->regs();\n      r.set_arg3(syscall_state.syscall_entry_registers.arg3());\n      t->set_regs(r);\n      record_madvise(t);\n      break;\n    }\n\n    case Arch::clone3:\n    case Arch::close_range:\n    case Arch::close:\n    case Arch::dup2:\n    case Arch::dup3:\n    case Arch::futex_time64:\n    case Arch::futex:\n    case Arch::ioctl:\n    case Arch::io_setup:\n    case Arch::io_uring_setup:\n    case Arch::memfd_create:\n    case Arch::mprotect:\n    case Arch::pkey_mprotect:\n    case Arch::pread64:\n    case Arch::preadv:\n    case Arch::ptrace:\n    case Arch::read:\n    case Arch::readv:\n    case Arch::rseq:\n    case Arch::sched_setaffinity:\n    case Arch::userfaultfd: {\n      // Restore the registers that we may have altered.\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      r.set_arg2(syscall_state.syscall_entry_registers.arg2());\n      r.set_arg3(syscall_state.syscall_entry_registers.arg3());\n      t->set_regs(r);\n      break;\n    }\n\n    case Arch::getdents:\n    case Arch::getdents64: {\n      Registers r = t->regs();\n      int fd = r.orig_arg1();\n      t->fd_table()->filter_getdents(fd, t);\n      break;\n    }\n\n    case Arch::waitpid:\n    case Arch::wait4:\n    case Arch::waitid: {\n      t->in_wait_type = WAIT_TYPE_NONE;\n      t->in_wait_options = 0;\n      // Restore possibly-modified registers\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      r.set_arg2(syscall_state.syscall_entry_registers.arg2());\n      r.set_arg3(syscall_state.syscall_entry_registers.arg3());\n      r.set_arg4(syscall_state.syscall_entry_registers.arg4());\n      r.set_original_syscallno(\n          syscall_state.syscall_entry_registers.original_syscallno());\n      t->set_regs(r);\n\n      RecordTask* tracee = syscall_state.emulate_wait_for_child;\n      if (tracee) {\n        // Finish emulation of ptrace result or stop-signal\n        Registers r = t->regs();\n        r.set_syscall_result(syscallno == Arch::waitid ? 0 : tracee->tid);\n        t->set_regs(r);\n        if (syscallno == Arch::waitid) {\n          remote_ptr<typename Arch::siginfo_t> sip = r.arg3();\n          if (!sip.is_null()) {\n            typename Arch::siginfo_t si;\n            memset(&si, 0, sizeof(si));\n            si.si_signo = SIGCHLD;\n            tracee->set_siginfo_for_waited_task<Arch>(&si);\n            t->write_mem(sip, si);\n          }\n        } else {\n          remote_ptr<int> statusp = r.arg2();\n          if (!statusp.is_null()) {\n            t->write_mem(statusp, tracee->emulated_stop_code.get());\n          }\n        }\n        if (syscallno == Arch::waitid && (r.arg4() & WNOWAIT)) {\n          // Leave the child in a waitable state\n        } else {\n          if (tracee->emulated_ptracer == t) {\n            tracee->emulated_stop_pending = false;\n          } else {\n            for (Task* thread : tracee->thread_group()->task_set()) {\n              auto rt = static_cast<RecordTask*>(thread);\n              rt->emulated_stop_pending = false;\n            }\n          }\n          if (tracee->detached_proxy &&\n              (tracee->emulated_stop_code.type() == WaitStatus::EXIT ||\n               tracee->emulated_stop_code.type() == WaitStatus::FATAL_SIGNAL)) {\n            // parent has reaped the proxy, so we're done with this task.\n            // This kills the proxy.\n            delete tracee;\n            tracee = nullptr;\n          }\n        }\n        if (tracee && tracee->already_exited()) {\n          // Have another go at reaping the task\n          tracee->did_reach_zombie();\n        }\n      }\n      break;\n    }\n\n    case Arch::prctl: {\n      // Restore arg1 in case we modified it to disable the syscall\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      t->set_regs(r);\n      switch ((int)t->regs().orig_arg1()) {\n        case PR_SET_SECCOMP:\n          if (t->session().done_initial_exec()) {\n            t->session()\n                .as_record()\n                ->seccomp_filter_rewriter()\n                .install_patched_seccomp_filter(t);\n          }\n          break;\n      }\n      break;\n    }\n\n    case Arch::arch_prctl: {\n      // Restore arg1 in case we modified it to disable the syscall\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      t->set_regs(r);\n      break;\n    }\n\n    case Arch::quotactl:\n      switch (t->regs().orig_arg1() >> SUBCMDSHIFT) {\n        case Q_GETQUOTA:\n        case Q_GETINFO:\n        case Q_GETFMT:\n        case Q_SETQUOTA:\n        case Q_QUOTAON:\n        case Q_QUOTAOFF:\n        case Q_SETINFO:\n        case Q_SYNC:\n          break;\n        default: {\n          auto ret = t->regs().syscall_result_signed();\n          ASSERT(t,\n                 ret == -ENOENT || ret == -ENODEV || ret == -ENOTBLK ||\n                     ret == -EINVAL)\n              << \" unknown quotactl(\" << HEX(t->regs().orig_arg1() >> SUBCMDSHIFT)\n              << \")\";\n          break;\n        }\n      }\n      break;\n\n    case Arch::seccomp: {\n      // Restore arg1 in case we modified it to disable the syscall\n      Registers r = t->regs();\n      r.set_orig_arg1(syscall_state.syscall_entry_registers.arg1());\n      t->set_regs(r);\n      if (t->regs().orig_arg1() == SECCOMP_SET_MODE_FILTER) {\n        ASSERT(t, t->session().done_initial_exec())\n            << \"no seccomp calls during spawn\";\n        t->session()\n            .as_record()\n            ->seccomp_filter_rewriter()\n            .install_patched_seccomp_filter(t);\n      }\n      break;\n    }\n\n    case SYS_rrcall_init_buffers:\n      t->init_buffers();\n      break;\n\n    case SYS_rrcall_init_preload: {\n      t->at_preload_init();\n      break;\n    }\n\n    case SYS_rrcall_notify_syscall_hook_exit: {\n      remote_ptr<uint8_t> child_addr =\n          REMOTE_PTR_FIELD(t->syscallbuf_child, notify_on_syscall_hook_exit);\n      t->write_mem(child_addr, (uint8_t)0);\n      t->record_remote(child_addr);\n\n      struct rrcall_params {\n        typename Arch::unsigned_word result;\n        typename Arch::unsigned_word original_syscallno;\n      };\n      Registers r = t->regs();\n      auto params_ptr = r.sp() + sizeof(typename Arch::unsigned_word);\n      auto params = t->read_mem(params_ptr.cast<rrcall_params>());\n      r.set_syscall_result((uintptr_t)params.result);\n      r.set_original_syscallno((intptr_t)params.original_syscallno);\n      t->set_regs(r);\n      break;\n    }\n  }\n}\n\n/* N.B.: `arch` is the architecture of the syscall, which may be different\n         from the architecture of the call (e.g. x86_64 may invoke x86 syscalls)\n*/\nstatic void rec_process_syscall_internal(RecordTask* t, SupportedArch arch,\n                                         TaskSyscallState& syscall_state) {\n  RR_ARCH_FUNCTION(rec_process_syscall_arch, arch, t, syscall_state)\n}\n\nvoid rec_did_sigreturn(RecordTask *t) {\n  auto& syscall_state = TaskSyscallState::get(t);\n  aarch64_kernel_bug_workaround(t, syscall_state);\n  t->syscall_state = nullptr;\n}\n\nvoid rec_process_syscall(RecordTask* t) {\n  auto& syscall_state = TaskSyscallState::get(t);\n  const SyscallEvent& sys_ev = t->ev().Syscall();\n  if (sys_ev.arch() != t->arch()) {\n    static bool did_warn = false;\n    if (!did_warn) {\n      LOG(warn)\n          << \"Cross architecture syscall detected. Support is best effort\";\n      did_warn = true;\n    }\n  }\n  rec_process_syscall_internal(t, sys_ev.arch(), syscall_state);\n  syscall_state.process_syscall_results();\n\n  aarch64_kernel_bug_workaround(t, syscall_state);\n\n  t->on_syscall_exit(sys_ev.number, sys_ev.arch(), t->regs());\n  t->syscall_state = nullptr;\n\n  MonitoredSharedMemory::check_all(t);\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/record_syscall.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_PROCESS_SYSCALL_H_\n#define RR_PROCESS_SYSCALL_H_\n\n#include \"util.h\"\n\nnamespace rr {\n\nclass RecordTask;\n\n/**\n * Prepare |t| to enter its current syscall event.  Return ALLOW_SWITCH if\n * a context-switch is allowed for |t|, PREVENT_SWITCH if not.\n */\nSwitchable rec_prepare_syscall(RecordTask* t);\n\n/**\n * Any prepared syscall is not going to happen (because it was aborted by\n * tracee seccomp filter). Cancel any preparation work.\n */\nvoid rec_abort_prepared_syscall(RecordTask* t);\n\n/**\n * Prepare |t| for its current syscall event to be interrupted and\n * possibly restarted.\n */\nvoid rec_prepare_restart_syscall(RecordTask* t);\n\n/**\n * Restore any argument registers fudged for |t|'s current syscall and\n * store any nondeterministic outparam data.\n */\nvoid rec_process_syscall(RecordTask* t);\n\n/**\n * Apply any necessary processing for an executed sigreturn.\n */\nvoid rec_did_sigreturn(RecordTask* t);\n\n/**\n * Return true if we're in a wait-like syscall that should\n * return a status from an emulated stop instead of being interrupted\n * by a signal. Sets the waited-for task as a side effect.\n */\nbool rec_return_normally_from_wait(RecordTask* t);\n\n} // namespace rr\n\n#endif /* RR_PROCESS_SYSCALL_H_ */\n"
  },
  {
    "path": "src/remote_code_ptr.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"remote_code_ptr.h\"\n\nusing namespace std;\n\nnamespace rr {\n\nostream& operator<<(ostream& stream, remote_code_ptr p) {\n  stream << (void*)p.register_value();\n  return stream;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/remote_code_ptr.h",
    "content": "#ifndef RR_REMOTE_CODE_PTR_H_\n#define RR_REMOTE_CODE_PTR_H_\n\n#include <cstddef>\n#include <iostream>\n\n#include \"kernel_abi.h\"\n\nnamespace rr {\n\n/*\n * A pointer to code in the tracee address space.  Convertible to a\n * remote_ptr<void>.\n */\nclass remote_code_ptr {\npublic:\n  remote_code_ptr() : ptr(0) {}\n  remote_code_ptr(uintptr_t ptr) : ptr(ptr) {}\n  remote_code_ptr(std::nullptr_t) : ptr(0) {}\n\n  bool operator==(const remote_code_ptr& other) const {\n    return ptr == other.ptr;\n  }\n  bool operator!=(const remote_code_ptr& other) const {\n    return ptr != other.ptr;\n  }\n  bool operator<=(const remote_code_ptr& other) const {\n    return ptr <= other.ptr;\n  }\n  bool operator>=(const remote_code_ptr& other) const {\n    return ptr >= other.ptr;\n  }\n  bool operator<(const remote_code_ptr& other) const { return ptr < other.ptr; }\n  bool operator>(const remote_code_ptr& other) const { return ptr > other.ptr; }\n  // XXXkhuey this will have to get smarter once we have ARM.\n  remote_code_ptr operator+(intptr_t delta) const {\n    return remote_code_ptr(ptr + delta);\n  }\n  remote_code_ptr operator-(intptr_t delta) const {\n    return remote_code_ptr(ptr - delta);\n  }\n  intptr_t operator-(remote_code_ptr other) const { return ptr - other.ptr; }\n\n  remote_code_ptr decrement_by_syscall_insn_length(SupportedArch arch) const {\n    return remote_code_ptr(ptr - rr::syscall_instruction_length(arch));\n  }\n  remote_code_ptr increment_by_syscall_insn_length(SupportedArch arch) const {\n    return remote_code_ptr(ptr + rr::syscall_instruction_length(arch));\n  }\n  remote_code_ptr undo_executed_bkpt(SupportedArch arch) {\n    switch (arch) {\n      case x86:\n      case x86_64:\n        return decrement_by_bkpt_insn_length_private(arch);\n      case aarch64:\n        // On aarch64 executed breakpoint instructions do not increment the pc\n        return *this;\n      default:\n        DEBUG_ASSERT(0 && \"Unknown architecture\");\n        __builtin_unreachable();\n    }\n  }\n  remote_code_ptr advance_past_executed_bkpt(SupportedArch arch) {\n    switch (arch) {\n      case x86:\n      case x86_64:\n        return *this;\n      case aarch64:\n        // On aarch64 executed breakpoint instructions do not increment the pc\n        return increment_by_bkpt_insn_length(arch);\n      default:\n        DEBUG_ASSERT(0 && \"Unknown architecture\");\n        __builtin_unreachable();\n    }\n  }\n  remote_code_ptr increment_by_bkpt_insn_length(SupportedArch arch) const {\n    return remote_code_ptr(ptr + rr::bkpt_instruction_length(arch));\n  }\n  remote_code_ptr increment_by_movrm_insn_length(SupportedArch arch) const {\n    return remote_code_ptr(ptr + rr::movrm_instruction_length(arch));\n  }\n  remote_code_ptr decrement_by_vsyscall_entry_length(SupportedArch arch) const {\n    return remote_code_ptr(ptr - rr::vsyscall_entry_length(arch));\n  }\n\n  template <typename T> remote_ptr<T> to_data_ptr() const {\n    return remote_ptr<T>(to_data_ptr_value());\n  }\n\n  // Return the pointer in a form suitable for storing in a register. Only\n  // intended for use by Registers and the operator <<\n  uintptr_t register_value() const { return ptr; }\n\n  bool is_null() const { return !ptr; }\n  explicit operator bool() const { return ptr != 0; }\n\nprivate:\n  // Private to avoid accidentally using this instead of undo_executed_bkpt.\n  // You probably want that one.\n  remote_code_ptr decrement_by_bkpt_insn_length_private(SupportedArch arch) const {\n    return remote_code_ptr(ptr - rr::bkpt_instruction_length(arch));\n  }\n\n  // Return the integer value for this pointer viewed as a data pointer.\n  // A no-op on Intel architectures, will mask off the thumb bit on ARM.\n  uintptr_t to_data_ptr_value() const { return ptr; }\n\n  uintptr_t ptr;\n};\n\nstd::ostream& operator<<(std::ostream& stream, remote_code_ptr p);\n\n} // namespace rr\n\nnamespace std {\n\ntemplate <> struct hash<rr::remote_code_ptr> {\n  size_t operator()(const rr::remote_code_ptr& ptr) const {\n    return hash<uintptr_t>()(ptr.register_value());\n  }\n};\n\n} // namespace std\n\n#endif // RR_REMOTE_CODE_PTR_H_\n"
  },
  {
    "path": "src/remote_ptr.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REMOTE_PTR_H_\n#define RR_REMOTE_PTR_H_\n\n#include <cstddef>\n#include <iostream>\n#include <cstdint>\n\nnamespace rr {\n\n/**\n * Number of bytes to use as the element size when doing pointer arithmetic\n * on this type. We specialize 'void' to use 1 byte to make a lot of our\n * calculations easier.\n */\ntemplate <typename T> size_t pointer_arithmetic_size() { return sizeof(T); }\ntemplate <> inline size_t pointer_arithmetic_size<void>() { return 1; }\n\n/**\n * A pointer to data in some tracee address space.\n * This lets us distinguish between real, usable pointers in rr's address space\n * and pointers that only make sense in a tracee address space.\n */\ntemplate <typename T> class remote_ptr {\npublic:\n  remote_ptr() : ptr(0) {}\n  remote_ptr(uintptr_t ptr) : ptr(ptr) {}\n  remote_ptr(std::nullptr_t) : ptr(0) {}\n  template <typename U> remote_ptr(remote_ptr<U> p) : ptr(p.as_int()) {\n    consume_dummy(static_cast<typename std::remove_cv<U>::type*>(nullptr));\n  }\n\n  uintptr_t as_int() const { return ptr; }\n\n  remote_ptr<T> operator+(intptr_t delta) const {\n    return remote_ptr<T>(ptr + delta * arith_size());\n  }\n  remote_ptr<T> operator-(intptr_t delta) const {\n    return remote_ptr<T>(ptr - delta * arith_size());\n  }\n  remote_ptr<T>& operator+=(intptr_t delta) {\n    ptr += delta * arith_size();\n    return *this;\n  }\n  remote_ptr<T>& operator-=(intptr_t delta) {\n    ptr -= delta * arith_size();\n    return *this;\n  }\n  intptr_t operator-(remote_ptr<T> other) const {\n    return (ptr - other.ptr) / arith_size();\n  }\n  remote_ptr<T>& operator++() {\n    ptr += arith_size();\n    return *this;\n  }\n  remote_ptr<T> operator++(int) {\n    uintptr_t p = ptr;\n    ptr += arith_size();\n    return p;\n  }\n  remote_ptr<T>& operator--() {\n    ptr -= arith_size();\n    return *this;\n  }\n  remote_ptr<T> operator--(int) {\n    uintptr_t p = ptr;\n    ptr -= arith_size();\n    return p;\n  }\n\n  template <typename U> remote_ptr<U> cast() const {\n    return remote_ptr<U>(ptr);\n  }\n\n  explicit operator bool() const { return ptr != 0; }\n  bool operator!() const { return !ptr; }\n  bool operator<(const remote_ptr<T>& other) const { return ptr < other.ptr; }\n  bool operator<=(const remote_ptr<T>& other) const { return ptr <= other.ptr; }\n  bool operator==(const remote_ptr<T>& other) const { return ptr == other.ptr; }\n  bool operator!=(const remote_ptr<T>& other) const { return ptr != other.ptr; }\n  bool operator>(const remote_ptr<T>& other) const { return ptr > other.ptr; }\n  bool operator>=(const remote_ptr<T>& other) const { return ptr >= other.ptr; }\n\n  bool is_null() const { return !ptr; }\n\n  template <typename U>\n  remote_ptr<typename std::remove_cv<U>::type> field(U*,\n                                                     uintptr_t offset) const {\n    return remote_ptr<typename std::remove_cv<U>::type>(ptr + offset);\n  }\n  T* dummy() { return nullptr; }\n  const T* dummy() const { return nullptr; }\n\n  size_t referent_size() { return sizeof(T); }\n\nprivate:\n  static void consume_dummy(T*) {}\n  static size_t arith_size() { return pointer_arithmetic_size<T>(); }\n\n  uintptr_t ptr;\n};\n\n/**\n * returns a remote_ptr pointing to field f of the struct pointed to by\n * remote_ptr p, with an additional value subtracted\n */\n#define REMOTE_PTR_FIELD_MINUS_OFFSET(p, f, o)                                 \\\n  ((p).field(                                                                  \\\n      ((typename std::remove_reference<decltype(                               \\\n            (p).dummy()->f)>::type*)nullptr),                                  \\\n      offsetof(typename std::remove_reference<decltype(*(p).dummy())>::type,   \\\n               f) - (o)))\n/**\n * returns a remote_ptr pointing to field f of the struct pointed to by\n * remote_ptr p\n */\n#define REMOTE_PTR_FIELD(p, f) REMOTE_PTR_FIELD_MINUS_OFFSET(p, f, 0)\n\ntemplate <typename T>\nstd::ostream& operator<<(std::ostream& stream, remote_ptr<T> p) {\n  stream << (void*)p.as_int();\n  return stream;\n}\n\n} // namespace rr\n\n#endif /* RR_REMOTE_PTR_H_ */\n"
  },
  {
    "path": "src/replay_syscall.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <errno.h>\n#include <fcntl.h>\n#include <linux/futex.h>\n#include <linux/perf_event.h>\n#include <linux/shm.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/prctl.h>\n#include <sys/wait.h>\n#include <syscall.h>\n\n#include <array>\n#include <initializer_list>\n#include <map>\n#include <memory>\n#include <sstream>\n#include <string>\n\n#include \"replay_syscall.h\"\n\n#include \"preload/preload_interface.h\"\n\n#include \"rr/rr.h\"\n\n#include \"AutoRemoteSyscalls.h\"\n#include \"EmuFs.h\"\n#include \"MmappedFileMonitor.h\"\n#include \"NonvirtualPerfCounterMonitor.h\"\n#include \"ODirectFileMonitor.h\"\n#include \"ProcFdDirMonitor.h\"\n#include \"ProcMemMonitor.h\"\n#include \"ProcStatMonitor.h\"\n#include \"RRPageMonitor.h\"\n#include \"ReplaySession.h\"\n#include \"ReplayTask.h\"\n#include \"SeccompFilterRewriter.h\"\n#include \"StdioMonitor.h\"\n#include \"SysCpuMonitor.h\"\n#include \"ThreadGroup.h\"\n#include \"TraceStream.h\"\n#include \"VirtualPerfCounterMonitor.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"kernel_supplement.h\"\n#include \"log.h\"\n#include \"util.h\"\n\n/* Uncomment this to check syscall names and numbers defined in syscalls.py\n   against the definitions in unistd.h. This may cause the build to fail\n   if unistd.h is slightly out of date, so it's not turned on by default. */\n//#define CHECK_SYSCALL_NUMBERS\n\nusing namespace std;\n\nnamespace rr {\n\n// XXX: x86-only currently.\n#ifdef CHECK_SYSCALL_NUMBERS\n\n// Hack because our 'break' syscall is called '_break'\n#define SYS__break SYS_break\n\n#include \"CheckSyscallNumbers.generated\"\n\n#endif // CHECK_SYSCALL_NUMBERS\n\nstatic void init_scratch_memory(ReplayTask* t, const KernelMapping& km,\n                                const TraceReader::MappedData& data) {\n  ASSERT(t, data.source == TraceReader::SOURCE_ZERO);\n\n  t->scratch_ptr = km.start();\n  t->scratch_size = km.size();\n  size_t sz = t->scratch_size;\n  // Make the scratch buffer read/write during replay so that\n  // preload's sys_read can use it to buffer cloned data.\n  ASSERT(t, (km.prot() & (PROT_READ | PROT_WRITE)) == (PROT_READ | PROT_WRITE));\n  ASSERT(t,\n         (km.flags() & (MAP_PRIVATE | MAP_ANONYMOUS)) ==\n             (MAP_PRIVATE | MAP_ANONYMOUS));\n\n  {\n    AutoRemoteSyscalls remote(t);\n    remote.infallible_mmap_syscall_if_alive(t->scratch_ptr, sz, km.prot(),\n                                            km.flags() | MAP_FIXED, -1, 0);\n    t->vm()->map(t, t->scratch_ptr, sz, km.prot(), km.flags(), 0, string(),\n                 KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,\n                 &km);\n  }\n  t->setup_preload_thread_locals();\n}\n\n/**\n * If scratch data was incidentally recorded for the current desched'd\n * but write-only syscall, then do a no-op restore of that saved data\n * to keep the trace in sync.\n *\n * Syscalls like |write()| that may-block and are wrapped in the\n * preload library can be desched'd.  When this happens, we save the\n * syscall record's \"extra data\" as if it were normal scratch space,\n * since it's used that way in effect.  But syscalls like |write()|\n * that don't actually use scratch space don't ever try to restore\n * saved scratch memory during replay.  So, this helper can be used\n * for that class of syscalls.\n */\nstatic void maybe_noop_restore_syscallbuf_scratch(ReplayTask* t) {\n  if (t->is_in_untraced_syscall()) {\n    // Untraced syscalls always have t's arch\n    LOG(debug) << \"  noop-restoring scratch for write-only desched'd \"\n               << syscall_name(t->regs().original_syscallno(), t->arch());\n    t->apply_data_record_from_trace();\n  }\n}\n\nstatic TraceTaskEvent read_task_trace_event(ReplayTask* t,\n                                            TraceTaskEvent::Type type) {\n  TraceTaskEvent tte;\n  FrameTime time;\n  do {\n    tte = t->trace_reader().read_task_event(&time);\n    ASSERT(t, tte.type() != TraceTaskEvent::NONE)\n        << \"Unable to find TraceTaskEvent; \"\n           \"trace is corrupt (did you kill -9 \"\n           \"rr?)\";\n  } while (tte.type() != type || time < t->current_frame_time());\n  ASSERT(t, time == t->current_frame_time());\n  return tte;\n}\n\n\ntemplate <typename Arch>\nstatic bool syscall_shares_vm(Registers r)\n{\n  switch (r.original_syscallno()) {\n    case Arch::clone:\n      return (CLONE_VM & r.orig_arg1());\n    case Arch::vfork:\n      return true;\n    case Arch::fork:\n      return false;\n    default:\n      FATAL() << \"Unknown clone syscall\";\n      __builtin_unreachable();\n  }\n}\n\ntemplate <typename Arch> static void prepare_clone(ReplayTask* t) {\n  const TraceFrame& trace_frame = t->current_trace_frame();\n\n  // We're being called with the syscall entry event, so we can't inspect the result\n  // of the syscall exit to see whether the clone succeeded (that event can happen\n  // much later, even after the spawned task has run).\n  if (trace_frame.event().Syscall().failed_during_preparation) {\n    /* creation failed, nothing special to do */\n    return;\n  }\n\n  Registers r = t->regs();\n  int sys = r.original_syscallno();\n  int flags = 0;\n  if (Arch::clone == sys) {\n    // BLOCKED clone flags:\n    // If we allow CLONE_UNTRACED then the child would escape from rr control\n    // and we can't allow that.\n    // Block CLONE_CHILD_CLEARTID because we'll emulate that ourselves.\n    // Block CLONE_VFORK for the reasons below.\n    // Block CLONE_NEW* from replay, any effects it had were dealt with during\n    // recording.\n    // Block CLONE_THREAD/CLONE_FILES - during replay each task is its own\n    // thread group/has its own fd table. We track what the membership was during\n    // record, but it's hard (and unnecessary) to replicate this kernel state during\n    // replay.\n    // Block CLONE_PIDFD/CLONE_CHILD_SETTID/CLONE_PARENT_SETTID because we record these.\n    //\n    // ALLOWED clone flags:\n    // We allow CLONE_VM because address space sharing must not be broken.\n    // We allow CLONE_SETTLS because we must set %fs correctly if requested.\n    //\n    // IRRELEVANT clone flags:\n    // CLONE_SIGHAND/CLONE_SYSVSEM/CLONE_FS/CLONE_IO are irrelevant because we don't set signal handlers\n    // or use SYSV-semaphore objects during replay, or let it use the filesystem, or do I/O.\n    //\n    // CLONE_PARENT/CLONE_PTRACE ... they probably need work to work under rr.\n    uintptr_t disallowed_clone_flags =\n        CLONE_UNTRACED |\n        CLONE_CHILD_CLEARTID |\n        CLONE_VFORK |\n        CLONE_NEWIPC | CLONE_NEWNET | CLONE_NEWNS | CLONE_NEWPID | CLONE_NEWUSER |\n        CLONE_NEWUTS | CLONE_NEWCGROUP |\n        CLONE_THREAD | CLONE_FILES |\n        CLONE_PIDFD | CLONE_CHILD_SETTID | CLONE_PARENT_SETTID;\n    flags = r.arg1();\n    r.set_arg1(flags & ~disallowed_clone_flags);\n  } else if (Arch::vfork == sys) {\n    // We can't perform a real vfork, because the kernel won't let the vfork\n    // parent return from the syscall until the vfork child has execed or\n    // exited, and it is an invariant of replay that tasks are not in the kernel\n    // except when we need them to execute a specific syscall on rr's behalf.\n    // So instead we do a regular fork but use the CLONE_VM flag to share\n    // address spaces between the parent and child. That's just like a vfork\n    // except the parent is immediately runnable. This is no problem for replay\n    // since we follow the recorded schedule in which the vfork parent did not\n    // run until the vfork child exited.\n    sys = Arch::clone;\n    flags = CLONE_VM;\n    r.set_arg1(flags);\n    r.set_arg2(0);\n  }\n  r.set_syscallno(sys);\n  r.set_ip(r.ip().decrement_by_syscall_insn_length(r.arch()));\n  t->set_regs(r);\n  Registers entry_regs = r;\n\n  // Run; we will be interrupted by PTRACE_EVENT_CLONE/FORK/VFORK.\n  bool ok = t->resume_execution(RESUME_CONT, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS);\n  ASSERT(t, ok) << \"Tracee was killed\";\n\n  pid_t new_tid;\n  while (!t->clone_syscall_is_complete(&new_tid, Arch::arch())) {\n    // clone() calls sometimes fail with -EAGAIN due to load issues or\n    // whatever. We need to retry the system call until it succeeds. Reset\n    // state to try the syscall again.\n    ASSERT(t, t->regs().syscall_result_signed() == -EAGAIN);\n    t->set_regs(entry_regs);\n    bool ok = t->resume_execution(RESUME_CONT, RESUME_WAIT_NO_EXIT, RESUME_NO_TICKS);\n    ASSERT(t, ok) << \"Tracee was killed\";\n  }\n\n  // Get out of the syscall\n  t->exit_syscall(Arch::arch());\n\n  ASSERT(t, !t->ptrace_event())\n      << \"Unexpected ptrace event while waiting for syscall exit; got \"\n      << ptrace_event_name(t->ptrace_event());\n\n  r = t->regs();\n  // Restore the saved flags, to hide the fact that we may have\n  // masked out CLONE_UNTRACED/CLONE_CHILD_CLEARTID or changed from vfork to\n  // clone.\n  r.set_arg1(trace_frame.regs().arg1());\n  r.set_arg2(trace_frame.regs().arg2());\n  // Pretend we're still in the system call\n  r.set_syscall_result(-ENOSYS);\n  r.set_original_syscallno(trace_frame.regs().original_syscallno());\n  t->set_regs(r);\n  t->canonicalize_regs(trace_frame.event().Syscall().arch());\n\n  // Dig the recorded tid out of the trace. The tid value returned in\n  // the recorded registers could be in a different pid namespace from rr's,\n  // so we can't use it directly.\n  TraceTaskEvent tte = read_task_trace_event(t, TraceTaskEvent::CLONE);\n  ASSERT(t, tte.parent_tid() == t->rec_tid)\n      << \"Expected tid \" << t->rec_tid << \", got \" << tte.parent_tid();\n  long rec_tid = tte.tid();\n\n  CloneParameters params;\n  if (Arch::clone == t->regs().original_syscallno()) {\n    params = extract_clone_parameters(t);\n  }\n  ReplayTask* new_task = static_cast<ReplayTask*>(\n      t->session().clone(t, clone_flags_to_task_flags(flags), params.stack,\n                         params.tls, params.ctid, new_tid, rec_tid));\n  new_task->own_namespace_rec_tid = tte.own_ns_tid();\n\n  if (Arch::clone == t->regs().original_syscallno()) {\n    /* FIXME: what if registers are non-null and contain an\n     * invalid address? */\n    t->apply_data_record_from_trace();\n\n    if (Arch::clone_tls_type == Arch::UserDescPointer) {\n      t->apply_data_record_from_trace();\n      new_task->apply_data_record_from_trace();\n    } else {\n      DEBUG_ASSERT(Arch::clone_tls_type == Arch::PthreadStructurePointer);\n    }\n    new_task->apply_data_record_from_trace();\n    new_task->apply_data_record_from_trace();\n  }\n\n  // Fix registers in new task\n  Registers new_r = new_task->regs();\n  new_r.set_original_syscallno(trace_frame.regs().original_syscallno());\n  new_r.set_orig_arg1(trace_frame.regs().arg1());\n  new_r.set_arg2(trace_frame.regs().arg2());\n  new_task->set_regs(new_r);\n  new_task->canonicalize_regs(new_task->arch());\n\n  if (!syscall_shares_vm<Arch>(r)) {\n    // It's hard to imagine a scenario in which it would\n    // be useful to inherit breakpoints (along with their\n    // refcounts) across a non-VM-sharing clone, but for\n    // now we never want to do this.\n    new_task->vm()->remove_all_breakpoints();\n    new_task->vm()->remove_all_watchpoints();\n\n    AutoRemoteSyscalls remote(new_task);\n    for (const auto& m : t->vm()->maps()) {\n      // Recreate any tracee-shared mappings\n      if (m.local_addr &&\n          !(m.flags & (AddressSpace::Mapping::IS_THREAD_LOCALS |\n                       AddressSpace::Mapping::IS_SYSCALLBUF))) {\n        Session::recreate_shared_mmap(remote, m, Session::PRESERVE_CONTENTS);\n      }\n    }\n  }\n\n  TraceReader::MappedData data;\n  KernelMapping km = t->trace_reader().read_mapped_region(&data);\n  init_scratch_memory(new_task, km, data);\n}\n\nstatic void restore_mapped_region(ReplayTask* t, AutoRemoteSyscalls& remote,\n                                  const KernelMapping& km,\n                                  const TraceReader::MappedData& data) {\n  ASSERT(t, !(km.flags() & MAP_SHARED))\n      << \"Shared mappings after exec not supported\";\n\n  string real_file_name;\n  dev_t device = KernelMapping::NO_DEVICE;\n  ino_t inode = KernelMapping::NO_INODE;\n  int flags = km.flags();\n  uint64_t offset_bytes = 0;\n  switch (data.source) {\n    case TraceReader::SOURCE_FILE: {\n      struct stat real_file;\n      offset_bytes = km.file_offset_bytes();\n      // Private mapping, so O_RDONLY is always OK.\n      remote.finish_direct_mmap(km.start(), km.size(), km.prot(),\n                         km.flags(), data.file_name, O_RDONLY,\n                         data.data_offset_bytes, real_file,\n                         real_file_name);\n      device = real_file.st_dev;\n      inode = real_file.st_ino;\n      break;\n    }\n    case TraceReader::SOURCE_TRACE:\n    case TraceReader::SOURCE_ZERO:\n      flags |= MAP_ANONYMOUS;\n      remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),\n                                              (flags & ~MAP_GROWSDOWN) | MAP_FIXED, -1,\n                                              0);\n      // The data, if any, will be written back by\n      // ReplayTask::apply_all_data_records_from_trace\n      break;\n    default:\n      ASSERT(t, false) << \"Unknown data source\";\n      break;\n  }\n\n  t->vm()->map(t, km.start(), km.size(), km.prot(), flags, offset_bytes,\n               real_file_name, device, inode, nullptr, &km);\n}\n\nstatic void process_execve(ReplayTask* t, const TraceFrame& trace_frame,\n                           ReplayTraceStep* step) {\n  step->action = TSTEP_RETIRE;\n\n  /* First, exec a stub program */\n  pid_t new_tid = t->real_tgid();\n  pid_t old_tid = t->tid;\n  t->os_exec_stub(trace_frame.regs().arch());\n  if (new_tid != old_tid) {\n    t->set_real_tid_and_update_serial(new_tid);\n  }\n\n  vector<KernelMapping> kms;\n  vector<TraceReader::MappedData> datas;\n\n  TraceTaskEvent tte = read_task_trace_event(t, TraceTaskEvent::EXEC);\n\n  // Find the text mapping of the main executable. This is complicated by the\n  // fact that the kernel also loads the dynamic linker (if the main\n  // executable specifies an interpreter).\n  ssize_t exe_km_option1 = -1, exe_km_option2 = -1, rip_km = -1;\n  while (true) {\n    TraceReader::MappedData data;\n    bool found;\n    KernelMapping km = t->trace_reader().read_mapped_region(&data, &found);\n    if (!found) {\n      break;\n    }\n    if (km.start() == AddressSpace::rr_page_start() ||\n        km.start() == AddressSpace::preload_thread_locals_start()) {\n      // Skip rr-page mapping record, that gets mapped automatically\n      continue;\n    }\n\n    if (tte.exe_base()) {\n      // We recorded the executable's start address so we can just use that\n      if (tte.exe_base() == km.start()) {\n        exe_km_option1 = kms.size();\n      }\n    } else {\n      // To disambiguate, we use the following criterion: The dynamic linker\n      // (if it exists) is a different file (identified via fsname) that has\n      // an executable segment that contains the ip. To compute this, we find\n      // (up to) two kms that have different fsnames but do each have an\n      // executable segment, as well as the km that contains the ip. This is\n      // slightly complicated, but should handle the case where either file has\n      // more than one executable segment.\n      const string& file_name = km.fsname();\n      if ((km.prot() & PROT_EXEC) && file_name.size() > 0 &&\n          // Make sure to exclude [vdso] (and similar) and executable stacks.\n          file_name[0] != '[') {\n        if (exe_km_option1 == -1) {\n          exe_km_option1 = kms.size();\n        } else if (exe_km_option2 == -1 &&\n                   kms[exe_km_option1].fsname() != file_name) {\n          exe_km_option2 = kms.size();\n        } else {\n          ASSERT(t,\n                 kms[exe_km_option1].fsname() == file_name ||\n                     kms[exe_km_option2].fsname() == file_name);\n        }\n      }\n      if (km.contains(trace_frame.regs().ip().to_data_ptr<void>())) {\n        rip_km = kms.size();\n      }\n    }\n    kms.push_back(km);\n    datas.push_back(data);\n  }\n\n  ASSERT(t, exe_km_option1 >= 0) << \"No executable mapping?\";\n\n  ssize_t exe_km = exe_km_option1;\n  if (exe_km_option2 >= 0) {\n    // Ok, we have two options. We choose the one that doesn't have the ip.\n    if (kms[exe_km_option2].fsname() != kms[rip_km].fsname()) {\n      ASSERT(t, kms[exe_km_option1].fsname() == kms[rip_km].fsname());\n      exe_km = exe_km_option2;\n    }\n  }\n\n  ASSERT(t, kms[0].is_stack()) << \"Can't find stack\";\n\n  // The exe name we pass in here will be passed to gdb. Pass the backing file\n  // name if there is one, otherwise pass the original file name (which means\n  // we declined to copy it to the trace file during recording for whatever\n  // reason).\n  const string& exe_name = datas[exe_km].file_name.empty()\n                               ? kms[exe_km].fsname()\n                               : datas[exe_km].file_name;\n  t->post_exec_syscall(exe_name, kms[exe_km].fsname());\n  t->vm()->set_interp_base(tte.interp_base());\n  t->vm()->set_interp_name(tte.interp_name());\n  if (!t->set_pac_keys(tte.pac_data())) {\n    LOG(warn) << \"Failed to restore PAC keys. Replay may fail.\";\n  }\n\n  t->fd_table()->close_after_exec(\n      t, t->current_trace_frame().event().Syscall().exec_fds_to_close);\n\n  {\n    // Tell AutoRemoteSyscalls that we don't need memory parameters. This will\n    // stop it from having trouble if our current stack pointer (the value\n    // from the replay) isn't in the [stack] mapping created for our stub.\n    AutoRemoteSyscalls remote(t, AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS);\n\n    // Now fix up the address space. First unmap all the mappings other than\n    // our rr page.\n    t->vm()->unmap_all_but_rr_mappings(remote);\n    // We will have unmapped the stack memory that |remote| would have used for\n    // memory parameters. Fortunately process_mapped_region below doesn't\n    // need any memory parameters for its remote syscalls.\n\n    // Process the [stack] mapping.\n    restore_mapped_region(t, remote, kms[0], datas[0]);\n  }\n\n  {\n    // Now that [stack] is mapped, reinitialize AutoRemoteSyscalls with\n    // memory parameters enabled.\n    AutoRemoteSyscalls remote(t);\n\n    // Now map in all the mappings that we recorded from the real exec.\n    for (ssize_t i = 1; i < ssize_t(kms.size()) - 1; ++i) {\n      restore_mapped_region(t, remote, kms[i], datas[i]);\n    }\n  }\n\n  init_scratch_memory(t, kms.back(), datas.back());\n\n  // Apply final data records --- fixing up the last page in each data segment\n  // for zeroing applied by the kernel, and applying monkeypatches.\n  t->apply_all_data_records_from_trace();\n\n  // Now it's safe to save the auxv data\n  t->vm()->save_auxv(t);\n\n  // Notify outer rr if there is one. We're assuming here that our\n  // rr is the same version as the outer rr, or at least is using\n  // the same syscall numbers. The inner rr could be replaying\n  // a trace with different rr syscall numbers.\n  syscall(SYS_rrcall_reload_auxv, t->tid);\n}\n\nstatic void process_brk(ReplayTask* t) {\n  TraceReader::MappedData data;\n  KernelMapping km = t->trace_reader().read_mapped_region(&data);\n  // Zero flags means it's an unmap, or no change.\n  if (km.flags()) {\n    AutoRemoteSyscalls remote(t);\n    ASSERT(t, data.source == TraceReader::SOURCE_ZERO);\n    remote.infallible_mmap_syscall_if_alive(km.start(), km.size(), km.prot(),\n                                            MAP_ANONYMOUS | MAP_FIXED | km.flags(), -1,\n                                            0);\n    t->vm()->map(t, km.start(), km.size(), km.prot(),\n                 MAP_ANONYMOUS | km.flags(), 0, \"[heap]\",\n                 KernelMapping::NO_DEVICE, KernelMapping::NO_INODE, nullptr,\n                 &km);\n  } else if (km.size() > 0) {\n    AutoRemoteSyscalls remote(t);\n    remote.infallible_syscall(syscall_number_for_munmap(t->arch()), km.start(),\n                              km.size());\n    t->vm()->unmap(t, km.start(), km.size());\n  }\n}\n\nstatic void finish_anonymous_mmap(ReplayTask* t, AutoRemoteSyscalls& remote,\n                                  remote_ptr<void> rec_addr, size_t length,\n                                  int prot, int flags) {\n  string file_name;\n  dev_t device = KernelMapping::NO_DEVICE;\n  ino_t inode = KernelMapping::NO_INODE;\n  TraceReader::MappedData data;\n  KernelMapping recorded_km = t->trace_reader().read_mapped_region(&data);\n  EmuFile::shr_ptr emu_file;\n  if (!(flags & MAP_SHARED)) {\n    remote.infallible_mmap_syscall_if_alive(rec_addr, length, prot,\n                                            // Tell the kernel to take |rec_addr|\n                                            // seriously.\n                                            (flags & ~MAP_GROWSDOWN) | MAP_FIXED, -1, 0);\n  } else {\n    ASSERT(remote.task(), data.source == TraceReader::SOURCE_ZERO);\n    emu_file = t->session().emufs().get_or_create(recorded_km);\n    struct stat real_file;\n    // Emufs file, so open it read-write in case we need to write to it\n    // through the task's memfd.\n    remote.finish_direct_mmap(rec_addr, length, prot,\n                       flags & ~MAP_ANONYMOUS, emu_file->proc_path(), O_RDWR, 0,\n                       real_file, file_name);\n    device = real_file.st_dev;\n    inode = real_file.st_ino;\n  }\n\n  remote.task()->vm()->map(t, rec_addr, length, prot, flags, 0, file_name,\n                           device, inode, nullptr, &recorded_km, emu_file);\n}\n\nstatic void write_mapped_data(ReplayTask* t,\n                              remote_ptr<void> rec_addr,\n                              size_t size,\n                              TraceReader::MappedData& data) {\n  switch (data.source) {\n  case TraceReader::SOURCE_TRACE: {\n    // Note that this gets called for remaps and shared maps that refer to the same pages\n    // as previous maps and so the data we're recording might not be the initial data\n    // for those pages, but it is the inital data *for this mapping*.\n    t->apply_data_record_from_trace();\n    break;\n  }\n  case TraceReader::SOURCE_FILE: {\n    ScopedFd file(data.file_name.c_str(), O_RDONLY);\n    ASSERT(t, file.is_open()) << \"Can't open \" << data.file_name;\n    off_t offset = lseek(file, data.data_offset_bytes, SEEK_SET);\n    ASSERT(t, offset == (off_t)data.data_offset_bytes)\n      << \"Couldn't seek to \" << data.data_offset_bytes << \", got \" << offset;\n    vector<uint8_t> buf;\n    buf.resize(page_size()*16);\n    while (size > 0) {\n      ssize_t ret = read(file, buf.data(), min(size, buf.size()));\n      if (ret < 0) {\n        FATAL() << \"Can't read from trace file \" << data.file_name;\n      }\n      if (ret == 0) {\n        break;\n      }\n      t->write_bytes_helper(rec_addr, ret, buf.data());\n      rec_addr += ret;\n      size -= ret;\n    }\n    break;\n  }\n  case TraceReader::SOURCE_ZERO:\n    break;\n  default:\n    FATAL() << \"Unknown data source\";\n    break;\n  }\n}\n\nstatic void finish_private_mmap(ReplayTask* t, AutoRemoteSyscalls& remote,\n                                remote_ptr<void> rec_addr, size_t length,\n                                int prot, int flags, off_t offset_bytes,\n                                const KernelMapping& km,\n                                TraceReader::MappedData& data) {\n  LOG(debug) << \"  finishing private mmap of \" << km.fsname();\n\n  remote.infallible_mmap_syscall_if_alive(\n      rec_addr, length, prot,\n      // Tell the kernel to take |rec_addr| seriously.\n      (flags & ~MAP_GROWSDOWN) | MAP_FIXED | MAP_ANONYMOUS, -1, 0);\n\n  // Update AddressSpace before loading data from the trace. This ensures our\n  // kernel-bug-workarounds when writing to tracee memory see the up-to-date\n  // virtual map.\n  t->vm()->map(t, rec_addr, length, prot, flags | MAP_ANONYMOUS,\n               offset_bytes, string(), KernelMapping::NO_DEVICE,\n               KernelMapping::NO_INODE, nullptr, &km);\n\n  /* Restore the map region we copied. */\n  write_mapped_data(t, rec_addr, km.size(), data);\n}\n\nstatic void finish_shared_mmap(ReplayTask* t, AutoRemoteSyscalls& remote,\n                               remote_ptr<void> rec_addr, size_t length,\n                               int prot, int flags, const vector<TraceRemoteFd>& fds,\n                               off_t offset_bytes,\n                               const KernelMapping& km,\n                               TraceReader::MappedData& data) {\n  // Ensure there's a virtual file for the file that was mapped\n  // during recording.\n  auto emufile = t->session().emufs().get_or_create(km);\n  // Re-use the direct_map() machinery to map the virtual file.\n  //\n  // NB: the tracee will map the procfs link to our fd; there's\n  // no \"real\" name for the file anywhere, to ensure that when\n  // we exit/crash the kernel will clean up for us.\n  struct stat real_file;\n  string real_file_name;\n  // Emufs file, so open it read-write in case we want to write to it through\n  // the task's mem fd.\n  remote.finish_direct_mmap(rec_addr, km.size(), prot, flags,\n                     emufile->proc_path(), O_RDWR, offset_bytes, real_file,\n                     real_file_name);\n  // Write back the snapshot of the segment that we recorded.\n  //\n  // TODO: this is a poor man's shared segment synchronization.\n  // For full generality, we also need to emulate direct file\n  // modifications through write/splice/etc.\n  //\n  // Update AddressSpace before loading data from the trace. This ensures our\n  // kernel-bug-workarounds when writing to tracee memory see the up-to-date\n  // virtual map.\n  t->vm()->map(t, rec_addr, km.size(), prot, flags, offset_bytes,\n               real_file_name, real_file.st_dev, real_file.st_ino, nullptr, &km,\n               emufile);\n\n  write_mapped_data(t, rec_addr, km.size(), data);\n\n  LOG(debug) << \"  restored \" << length << \" bytes at \"\n             << HEX(offset_bytes) << \" to \" << emufile->real_path() << \" for \"\n             << emufile->emu_path();\n  for (auto fd : fds) {\n    auto rt = t->session().find_task(fd.tid);\n    ASSERT(t, rt) << \"Can't find task \" << fd.tid;\n    if (rt->fd_table()->is_monitoring(fd.fd)) {\n      auto type = rt->fd_table()->get_monitor(fd.fd)->type();\n      if (type == FileMonitor::Type::Mmapped) {\n        ((MmappedFileMonitor*)rt->fd_table()->get_monitor(fd.fd))->revive();\n      } else if (type == FileMonitor::Type::ODirect) {\n        rt->fd_table()->replace_monitor(rt, fd.fd, new MmappedFileMonitor(rt, emufile));\n      } else {\n        ASSERT(rt, false)\n            << \"Expected monitor type Mmapped | ODirect for fd \" << fd.fd << \", got monitor type \"\n            << type;\n      }\n    } else {\n      rt->fd_table()->add_monitor(rt, fd.fd, new MmappedFileMonitor(rt, emufile));\n    }\n  }\n}\n\nstatic void process_mmap(ReplayTask* t, const TraceFrame& trace_frame,\n                         size_t length, int prot, int flags, int fd,\n                         off_t offset_bytes, ReplayTraceStep* step) {\n  step->action = TSTEP_RETIRE;\n\n  {\n    remote_ptr<void> addr = trace_frame.regs().syscall_result();\n    // Hand off actual execution of the mapping to the appropriate helper.\n    AutoRemoteSyscalls remote(t,\n                              !(flags & MAP_SHARED) && (flags & MAP_ANONYMOUS)\n                                  ? AutoRemoteSyscalls::DISABLE_MEMORY_PARAMS\n                                  : AutoRemoteSyscalls::ENABLE_MEMORY_PARAMS);\n    if (flags & MAP_ANONYMOUS) {\n      finish_anonymous_mmap(t, remote, trace_frame.regs().syscall_result(),\n                            length, prot, flags);\n    } else {\n      TraceReader::MappedData data;\n      vector<TraceRemoteFd> extra_fds;\n      bool skip_monitoring_mapped_fd;\n      KernelMapping km = t->trace_reader().read_mapped_region(&data, nullptr,\n        TraceReader::VALIDATE, TraceReader::CURRENT_TIME_ONLY, &extra_fds,\n        &skip_monitoring_mapped_fd);\n\n      if (t->session().has_trace_quirk(TraceReader::SpecialLibRRpage)) {\n        FileMonitor *fd_monitor = t->fd_table()->get_monitor(fd);\n        if (fd_monitor && fd_monitor->type() == FileMonitor::RRPage) {\n          if (offset_bytes == 0 && !(flags & MAP_FIXED) &&\n              length <= 2 * PRELOAD_LIBRARY_PAGE_SIZE &&\n              addr == (RR_PAGE_ADDR - PRELOAD_LIBRARY_PAGE_SIZE)) {\n            // We only mapped the first page during record. Do the same here\n            length = PRELOAD_LIBRARY_PAGE_SIZE;\n          }\n          if (offset_bytes == PRELOAD_LIBRARY_PAGE_SIZE && length == PRELOAD_LIBRARY_PAGE_SIZE &&\n              addr == RR_PAGE_ADDR && t->vm()->has_rr_page()) {\n            // We skipped this during recording. Setting length to zero here\n            // will have the same effect.\n            length = 0;\n          }\n        }\n      }\n\n      if (data.source == TraceReader::SOURCE_FILE &&\n          data.file_size_bytes > data.data_offset_bytes) {\n        struct stat real_file;\n        string real_file_name;\n        uint64_t map_bytes = min(ceil_page_size(data.file_size_bytes) - data.data_offset_bytes, length);\n        remote.finish_direct_mmap(addr, map_bytes, prot, flags,\n                           data.file_name, O_RDONLY,\n                           data.data_offset_bytes, real_file,\n                           real_file_name);\n        KernelMapping km_sub = km.subrange(km.start(), km.start() + ceil_page_size(map_bytes));\n        t->vm()->map(t, km.start(), map_bytes, prot, flags,\n                     offset_bytes, real_file_name,\n                     real_file.st_dev, real_file.st_ino, nullptr, &km_sub);\n        addr += map_bytes;\n        length -= map_bytes;\n        offset_bytes += ceil_page_size(map_bytes);\n        data.source = TraceReader::SOURCE_ZERO;\n        km = km.subrange(km_sub.end(), km.end());\n      }\n      if (length > 0) {\n        if (MAP_SHARED & flags) {\n          if (!skip_monitoring_mapped_fd) {\n            extra_fds.push_back({ t->rec_tid, fd });\n          }\n          finish_shared_mmap(t, remote, addr, length, prot, flags, extra_fds,\n                              offset_bytes, km, data);\n        } else {\n          ASSERT(t, extra_fds.empty());\n          finish_private_mmap(t, remote, addr, length, prot, flags,\n                              offset_bytes, km, data);\n        }\n      }\n    }\n\n    // This code is used to test the sharing functionality. It is in\n    // general a bad idea to indiscriminately share mappings between the\n    // tracer and the tracee. Instead, only mappings that have\n    // sufficiently many memory access from the tracer to require\n    // acceleration should be shared.\n    if (length > 0 && !(MAP_SHARED & flags) && t->session().flags().share_private_mappings) {\n      Session::make_private_shared(remote, t->vm()->mapping_of(addr));\n    }\n\n    // Finally, we finish by emulating the return value.\n    remote.regs().set_syscall_result(trace_frame.regs().syscall_result());\n  }\n  // Monkeypatcher can emit data records that need to be applied now\n  t->apply_all_data_records_from_trace();\n  t->validate_regs();\n}\n\nstatic void process_mremap(ReplayTask* t, const TraceFrame& trace_frame,\n                           ReplayTraceStep* step) {\n  step->action = TSTEP_RETIRE;\n\n  auto& trace_regs = trace_frame.regs();\n  remote_ptr<void> old_addr = trace_frame.regs().orig_arg1();\n  size_t old_size = ceil_page_size(trace_regs.arg2());\n  remote_ptr<void> new_addr = trace_frame.regs().syscall_result();\n  size_t new_size = ceil_page_size(trace_regs.arg3());\n  int flags = trace_regs.arg4_signed();\n\n  // The recorded mremap call succeeded, so we know the original mapping can be\n  // treated as a single mapping.\n  t->vm()->ensure_replay_matches_single_recorded_mapping(t, MemoryRange(old_addr, old_size));\n\n  TraceReader::MappedData data;\n  t->trace_reader().read_mapped_region(&data);\n  ASSERT(t, data.source == TraceReader::SOURCE_ZERO);\n  // We don't need to do anything; this is the mapping record for the moved\n  // data.\n\n  // Try reading a mapping record for new data.\n  bool found;\n  t->trace_reader().read_mapped_region(&data, &found);\n\n  {\n    // We must emulate mremap because the kernel's choice for the remap\n    // destination can vary (in particular, when we emulate exec it makes\n    // different decisions).\n    AutoRemoteSyscalls remote(t);\n    if (new_addr == old_addr) {\n      // Non-moving mremap. Don't pass MREMAP_FIXED or MREMAP_MAYMOVE\n      // since that triggers EINVAL when the new map overlaps the old map.\n      remote.infallible_syscall_if_alive(trace_regs.original_syscallno(), new_addr,\n                                         old_size, new_size, 0);\n    } else {\n      // Force the mremap to use the destination address from recording.\n      // XXX could the new mapping overlap the old, with different start\n      // addresses? Hopefully the kernel doesn't do that to us!!!\n      remote.infallible_syscall_if_alive(trace_regs.original_syscallno(), old_addr,\n                                         old_size, new_size,\n                                         flags | MREMAP_MAYMOVE | MREMAP_FIXED, new_addr);\n    }\n\n    remote.regs().set_syscall_result(new_addr);\n  }\n\n  t->vm()->remap(t, old_addr, old_size, new_addr, new_size, flags);\n\n  AddressSpace::Mapping mapping = t->vm()->mapping_of(new_addr);\n  auto f = mapping.emu_file;\n  if (f) {\n    f->ensure_size(mapping.map.file_offset_bytes() + new_size);\n  } else if (new_size > old_size && mapping.map.fsname().size() > 0 &&\n             !mapping.map.is_named_anonymous()) {\n    struct stat st;\n    int ret = stat(mapping.map.fsname().c_str(), &st);\n    if (ret != 0) {\n      FATAL() << \"Can't stat \" << mapping.map.fsname();\n    }\n    if (ceil_page_size(st.st_size) <\n        mapping.map.file_offset_bytes() + new_size) {\n      // Replace mapping with anonymous mapping to cover full mapped region.\n      // Don't just read the file data, since this could be a private mapping\n      // with some data changed.\n      vector<uint8_t> buf;\n      buf.resize(old_size);\n      t->read_bytes_helper(new_addr, buf.size(), buf.data());\n      AutoRemoteSyscalls remote(t);\n      // Shared non-EmuFs mappings must be of immutable files so it's OK to\n      // just copy the file data into a private mapping here.\n      int map_flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED;\n      remote.infallible_mmap_syscall_if_alive(new_addr, new_size, mapping.map.prot(),\n                                              map_flags, -1, 0);\n      t->vm()->unmap(t, new_addr, new_size);\n      t->vm()->map(t, new_addr, new_size, mapping.map.prot(), map_flags,\n                   mapping.map.file_offset_bytes(), string(),\n                   KernelMapping::NO_DEVICE,\n                   KernelMapping::NO_INODE, nullptr, &mapping.recorded_map);\n      t->write_bytes_helper(new_addr, buf.size(), buf.data());\n      mapping = t->vm()->mapping_of(new_addr);\n    }\n  }\n\n  // SOURCE_FILE for mapped files should be handled automatically by the mremap\n  // above.\n  // (If we started storing partial files, we'd have to careful to ensure this\n  // is still the case.)\n  if (found &&\n      (data.source != TraceReader::SOURCE_FILE || f ||\n       mapping.map.fsname().empty())) {\n    write_mapped_data(t, new_addr + old_size, new_size - old_size, data);\n  }\n\n  t->validate_regs();\n}\n\nvoid process_grow_map(ReplayTask* t) {\n  AutoRemoteSyscalls remote(t);\n  TraceReader::MappedData data;\n  KernelMapping km = t->trace_reader().read_mapped_region(&data);\n  ASSERT(t, km.size());\n  restore_mapped_region(t, remote, km, data);\n}\n\nstatic void process_shmat(ReplayTask* t, const TraceFrame& trace_frame,\n                          int shm_flags, ReplayTraceStep* step) {\n  step->action = TSTEP_RETIRE;\n\n  {\n    AutoRemoteSyscalls remote(t);\n    TraceReader::MappedData data;\n    KernelMapping km = t->trace_reader().read_mapped_region(&data);\n    int prot = shm_flags_to_mmap_prot(shm_flags);\n    int flags = MAP_SHARED;\n    finish_shared_mmap(t, remote, km.start(), km.size(), prot, flags,\n                       vector<TraceRemoteFd>(), 0, km, data);\n    t->vm()->set_shm_size(km.start(), km.size());\n\n    // Finally, we finish by emulating the return value.\n    // On x86-32 this is not the shm address...\n    remote.regs().set_syscall_result(trace_frame.regs().syscall_result());\n  }\n  // on x86-32 we have an extra data record that we need to apply ---\n  // the ipc syscall's klugy out-parameter.\n  t->apply_all_data_records_from_trace();\n  t->validate_regs();\n}\n\nstatic void process_shmdt(ReplayTask* t, const TraceFrame& trace_frame,\n                          remote_ptr<void> addr, ReplayTraceStep* step) {\n  step->action = TSTEP_RETIRE;\n\n  {\n    AutoRemoteSyscalls remote(t);\n    size_t size = t->vm()->get_shm_size(addr);\n    remote.infallible_syscall(syscall_number_for_munmap(t->arch()), addr, size);\n    remote.regs().set_syscall_result(trace_frame.regs().syscall_result());\n  }\n  t->validate_regs();\n}\n\n// Return true if this madvise() call should be passed through and\n// executed by the tracee.\nstatic bool process_madvise(ReplayTask* t, const TraceFrame& trace_frame,\n                            int advice, int result) {\n  switch (advice) {\n    case MADV_DONTNEED:\n    case MADV_REMOVE:\n    case MADV_DONTNEED_LOCKED: {\n      const SyscallEvent& ev = trace_frame.event().Syscall();\n      if (result == 0) {\n        ASSERT(t, ev.madvise_ranges.empty());\n        return true;\n      }\n      if (!ev.madvise_ranges.empty()) {\n        AutoRemoteSyscalls remote(t);\n        for (const auto& r : ev.madvise_ranges) {\n          remote.infallible_syscall(syscall_number_for_madvise(t->arch()),\n              r.start(), r.size(), advice);\n        }\n      }\n      return false;\n    }\n    /* These are not technically required to be passed through, but the\n       syscallbuf code does, so if we don't here, we risk fracturing\n       otherwise coalescable memory regions. Asan in particular triggers\n       a pathological case here that quickly exhausts the total mapping\n       limit by fracturing its shadow region */\n    case MADV_NORMAL:\n    case MADV_RANDOM:\n    case MADV_SEQUENTIAL:\n    case MADV_WILLNEED:\n    case MADV_MERGEABLE:\n    case MADV_UNMERGEABLE:\n    case MADV_HUGEPAGE:\n    case MADV_NOHUGEPAGE:\n    case MADV_DONTDUMP:\n    case MADV_DODUMP:\n      return true;\n    default:\n      return false;\n  }\n}\n\nstatic void process_init_buffers(ReplayTask* t, ReplayTraceStep* step) {\n  step->action = TSTEP_RETIRE;\n\n  /* We don't want the desched event fd during replay, because\n   * we already know where they were.  (The perf_event fd is\n   * emulated anyway.) */\n  t->init_buffers();\n  t->validate_regs();\n}\n\nstatic int non_negative_syscall(int sys) { return sys < 0 ? INT32_MAX : sys; }\n\ntemplate <typename Arch>\nstatic void rep_after_enter_syscall_arch(ReplayTask* t) {\n  switch (non_negative_syscall(t->regs().original_syscallno())) {\n    case Arch::write:\n    case Arch::writev: {\n      int fd = (int)t->regs().arg1_signed();\n      t->fd_table()->will_write(t, fd);\n      break;\n    }\n    case Arch::clone:\n    case Arch::vfork:\n    case Arch::fork:\n      // Create the new task now. It needs to exist before clone/fork/vfork\n      // returns so that a ptracer can touch it during PTRACE_EVENT handling.\n      prepare_clone<Arch>(t);\n      break;\n\n    case Arch::ptrace: {\n      ReplayTask* target =\n          t->session().find_task((pid_t)t->regs().arg2_signed());\n      if (!target) {\n        break;\n      }\n      switch ((int)t->regs().arg1_signed()) {\n        case Arch::PTRACE_POKETEXT:\n        case Arch::PTRACE_POKEDATA:\n          target->apply_all_data_records_from_trace();\n          break;\n        case PTRACE_SYSCALL:\n        case PTRACE_SINGLESTEP:\n        case Arch::PTRACE_SYSEMU:\n        case Arch::PTRACE_SYSEMU_SINGLESTEP:\n        case PTRACE_CONT:\n        case PTRACE_DETACH: {\n          int command = (int)t->regs().arg1_signed();\n          target->set_syscallbuf_locked(command != PTRACE_CONT &&\n                                        command != PTRACE_DETACH);\n          break;\n        }\n        case Arch::PTRACE_SET_THREAD_AREA: {\n          bool ok = true;\n          X86Arch::user_desc desc = t->read_mem(\n              remote_ptr<X86Arch::user_desc>(t->regs().arg4()), &ok);\n          if (ok) {\n            target->emulate_set_thread_area((int)t->regs().arg3(), desc);\n          }\n          break;\n        }\n      }\n      break;\n    }\n\n    case Arch::exit:\n      /* Destroy buffers now to match when we destroyed them during recording.\n         It's possible for another mapping to be created overlapping our\n         buffers before this task truly exits, and we don't want to trash\n         that mapping by destroying our buffers then. */\n      t->destroy_buffers();\n      break;\n    case Arch::exit_group:\n      if (t->thread_group()->task_set().size() == 1) {\n        /* See above. */\n        t->destroy_buffers();\n      }\n      break;\n  }\n  t->apply_all_data_records_from_trace();\n}\n\nvoid rep_after_enter_syscall(ReplayTask* t) {\n  RR_ARCH_FUNCTION(rep_after_enter_syscall_arch, t->arch(), t)\n}\n\nvoid rep_prepare_run_to_syscall(ReplayTask* t, ReplayTraceStep* step) {\n  const SyscallEvent& sys_ev = t->current_trace_frame().event().Syscall();\n  int sys = sys_ev.number;\n\n  LOG(debug) << \"processing \" << sys_ev.syscall_name() << \" (entry)\";\n\n  if (is_restart_syscall_syscall(sys, sys_ev.arch())) {\n    ASSERT(t, t->tick_count() == t->current_trace_frame().ticks());\n    t->set_regs(t->current_trace_frame().regs());\n    t->apply_all_data_records_from_trace();\n    step->action = TSTEP_RETIRE;\n    return;\n  }\n\n  step->syscall.number = sys;\n  step->action = TSTEP_ENTER_SYSCALL;\n\n  if (sys == t->session().syscall_number_for_rrcall_notify_syscall_hook_exit()) {\n    ASSERT(t, t->syscallbuf_child != nullptr);\n    t->write_mem(\n        REMOTE_PTR_FIELD(t->syscallbuf_child, notify_on_syscall_hook_exit),\n        (uint8_t)1);\n  }\n}\n\nstatic void handle_opened_files(ReplayTask* t, int flags) {\n  const auto& opened = t->current_trace_frame().event().Syscall().opened;\n  for (const auto& o : opened) {\n    // This must be kept in sync with record_syscall's handle_opened_file.\n    EmuFile::shr_ptr emu_file = t->session().emufs().find(o.device, o.inode);\n    FileMonitor* file_monitor = nullptr;\n    if (emu_file) {\n      file_monitor = new MmappedFileMonitor(t, emu_file);\n    } else if (o.path == \"terminal\") {\n      file_monitor = new StdioMonitor(t->session().tracee_output_fd(STDERR_FILENO));\n    } else if (is_proc_mem_file(o.path.c_str())) {\n      file_monitor = new ProcMemMonitor(t, o.path);\n    } else if (is_proc_fd_dir(o.path.c_str())) {\n      file_monitor = new ProcFdDirMonitor(t, o.path);\n    } else if (is_sys_cpu_online_file(o.path.c_str())) {\n      file_monitor = new SysCpuMonitor(t, o.path);\n    } else if (is_proc_stat_file(o.path.c_str())) {\n      file_monitor = new ProcStatMonitor(t, o.path);\n    } else if (is_rr_page_lib(o.path.c_str())) {\n      file_monitor = new RRPageMonitor();\n    } else if (flags & O_DIRECT) {\n      file_monitor = new ODirectFileMonitor();\n    } else {\n      ASSERT(t, false) << \"Why did we write filename \" << o.path;\n    }\n    t->fd_table()->add_monitor(t, o.fd, file_monitor);\n  }\n}\n\ntemplate <typename Arch>\nstatic void rep_process_syscall_arch(ReplayTask* t, ReplayTraceStep* step,\n                                     const Registers& trace_regs) {\n  int sys = t->current_trace_frame().event().Syscall().number;\n  const TraceFrame& trace_frame = t->session().current_trace_frame();\n\n  LOG(debug) << \"processing \" << syscall_name(sys, Arch::arch()) << \" (exit)\";\n\n  // sigreturns are never restartable, and the value of the\n  // syscall-result register after a sigreturn is not actually the\n  // syscall result.\n  if (trace_regs.syscall_may_restart() && !is_sigreturn(sys, Arch::arch())) {\n    // During recording, when a sys exits with a\n    // restart \"error\", the kernel sometimes restarts the\n    // tracee by resetting its $ip to the syscall entry\n    // point, but other times restarts the syscall without\n    // changing the $ip.\n    t->apply_all_data_records_from_trace();\n    t->set_return_value_from_trace();\n    step->action = TSTEP_RETIRE;\n    LOG(debug) << \"  \" << syscall_name(sys, Arch::arch()) << \" interrupted by \"\n               << trace_regs.syscall_result() << \" at \" << trace_regs.ip()\n               << \", may restart\";\n    return;\n  }\n\n  if (sys == Arch::restart_syscall) {\n    sys = t->regs().original_syscallno();\n  }\n\n  step->syscall.number = sys;\n  step->action = TSTEP_EXIT_SYSCALL;\n\n  if (trace_regs.original_syscallno() ==\n      SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO) {\n    // rr vetoed this syscall. Don't do any post-processing. Do set registers\n    // to match any registers rr modified to fool the signal handler.\n    t->set_regs(trace_regs);\n    return;\n  }\n\n  if (trace_regs.syscall_failed()) {\n    switch (non_negative_syscall(sys)) {\n      case Arch::madvise:\n      case Arch::mprotect:\n      case Arch::pkey_mprotect:\n      case Arch::sigreturn:\n      case Arch::rt_sigreturn:\n      case Arch::prctl:\n        break;\n      default:\n        return;\n    }\n  }\n\n  /* Manual implementations of irregular syscalls that need to do more during\n   * replay than just modify registenter_syscaller and memory state.\n   * Don't let a negative incoming syscall number be treated as a real\n   * system call that we assigned a negative number because it doesn't\n   * exist in this architecture.\n   * All invalid/unsupported syscalls get the default emulation treatment.\n   */\n  /* Don't let a negative incoming syscall number be treated as a real\n   * system call that we assigned a negative number because it doesn't\n   * exist in this architecture.\n   */\n  switch (non_negative_syscall(sys)) {\n    case Arch::execve:\n    case Arch::execveat:\n      return process_execve(t, trace_frame, step);\n\n    case Arch::brk:\n      return process_brk(t);\n\n    case Arch::mmap: {\n      switch (Arch::mmap_semantics) {\n        case Arch::StructArguments: {\n          auto args = t->read_mem(\n              remote_ptr<typename Arch::mmap_args>(trace_regs.orig_arg1()));\n          return process_mmap(t, trace_frame, args.len, args.prot, args.flags,\n                              args.fd, args.offset, step);\n        }\n        case Arch::RegisterArguments:\n          return process_mmap(t, trace_frame, trace_regs.arg2(),\n                              trace_regs.arg3(), trace_regs.arg4(),\n                              trace_regs.arg5(),\n                              trace_regs.arg6(), step);\n      }\n      break;\n    }\n    case Arch::mmap2:\n      return process_mmap(t, trace_frame, trace_regs.arg2(), trace_regs.arg3(),\n                          trace_regs.arg4(), trace_regs.arg5(),\n                          trace_regs.arg6() * 4096, step);\n\n    case Arch::shmat:\n      return process_shmat(t, trace_frame, trace_regs.arg3(), step);\n\n    case Arch::shmdt:\n      return process_shmdt(t, trace_frame, trace_regs.orig_arg1(), step);\n\n    case Arch::mremap:\n      return process_mremap(t, trace_frame, step);\n\n    case Arch::madvise:\n      if (!process_madvise(t, trace_frame, trace_regs.arg3(),\n                           trace_regs.syscall_result_signed())) {\n        return;\n      }\n      RR_FALLTHROUGH;\n    case Arch::arch_prctl: {\n      auto arg1 = t->regs().arg1();\n      if (sys == Arch::arch_prctl &&\n          (arg1 == ARCH_GET_CPUID || arg1 == ARCH_SET_CPUID)) {\n        return;\n      }\n    }\n      RR_FALLTHROUGH;\n    case Arch::prctl: {\n      auto arg1 = t->regs().arg1();\n      if (sys == Arch::prctl &&\n          (Arch::arch() != aarch64 || arg1 != PR_SET_SPECULATION_CTRL) &&\n          ((unsigned long)t->regs().arg1() != PR_SET_VMA || trace_regs.syscall_result_signed() == -EINVAL)) {\n        // On aarch64 PR_SET_SPECULATION_CTRL affects the pstate\n        // register during the system call, so we need to replay\n        // it, otherwise we'll get a mismatch there.\n        // We want to replay PR_SET_VMA as well, but not if it originally failed\n        // with EINVAL because the recording kernel may not have supported it.\n        return;\n      }\n    }\n      RR_FALLTHROUGH;\n    case Arch::munmap:\n    case Arch::mprotect:\n    case Arch::modify_ldt:\n    case Arch::pkey_mprotect:\n    case Arch::set_thread_area: {\n      // Using AutoRemoteSyscalls here fails for arch_prctl, not sure why.\n      Registers r = t->regs();\n      int modified_sys = sys == Arch::pkey_mprotect ? Arch::mprotect : sys;\n      r.set_syscallno(modified_sys);\n      r.set_ip(r.ip().decrement_by_syscall_insn_length(r.arch()));\n      t->set_regs(r);\n      if (modified_sys == Arch::mprotect) {\n        t->vm()->fixup_mprotect_growsdown_parameters(t);\n      }\n      t->enter_syscall(Arch::arch());\n      t->exit_syscall(Arch::arch());\n      ASSERT(t, t->regs().syscall_result() == trace_regs.syscall_result());\n      if (modified_sys == Arch::mprotect) {\n        Registers r2 = t->regs();\n        r2.set_arg1(r.arg1());\n        r2.set_arg2(r.arg2());\n        r2.set_arg3(r.arg3());\n        t->set_regs(r2);\n      }\n      // The syscall modified registers. Re-emulate the syscall entry.\n      t->canonicalize_regs(step->syscall.arch);\n      return;\n    }\n\n    case Arch::ipc:\n      switch ((int)trace_regs.orig_arg1_signed()) {\n        case SHMAT:\n          return process_shmat(t, trace_frame, trace_regs.arg3(), step);\n        case SHMDT:\n          return process_shmdt(t, trace_frame, trace_regs.arg5(), step);\n        default:\n          break;\n      }\n      break;\n\n    case Arch::sigreturn:\n    case Arch::rt_sigreturn:\n      if (Arch::arch() == aarch64) {\n        // The aarch64 kernel has a bug where it refuses to apply updates\n        // to x7 during any syscall stops. Make sure to move to a signal\n        // stop if we reached here using sysemu.\n        t->move_to_signal_stop();\n      }\n      t->set_regs(trace_regs);\n      t->set_extra_regs(trace_frame.extra_regs());\n      step->action = TSTEP_RETIRE;\n      return;\n\n    case Arch::pkey_alloc:\n      // Older versions of rr (incorrectly) did not record the extra regs here.\n      if (t->session().has_trace_quirk(TraceReader::PkeyAllocRecordedExtraRegs)) {\n        t->set_extra_regs(trace_frame.extra_regs());\n      }\n      return;\n\n    case Arch::rseq: {\n      Registers r = t->regs();\n      auto rseq = remote_ptr<typename Arch::rseq_t>(r.arg1());\n      int flags = r.arg3();\n      uint32_t sig = r.arg4();\n      if (flags & RR_RSEQ_FLAG_UNREGISTER) {\n        t->rseq_state = nullptr;\n      } else {\n        t->rseq_state = make_unique<RseqState>(rseq, sig);\n      }\n      return;\n    }\n\n    case Arch::perf_event_open: {\n      Task* target = t->session().find_task((pid_t)trace_regs.arg2_signed());\n      int cpu = trace_regs.arg3_signed();\n      unsigned long flags = trace_regs.arg5();\n      int fd = trace_regs.syscall_result_signed();\n      int allowed_perf_flags = PERF_FLAG_FD_CLOEXEC;\n      bool virtualize = false;\n      if (target && cpu == -1 && !(flags & ~allowed_perf_flags)) {\n        auto attr =\n            t->read_mem(remote_ptr<struct perf_event_attr>(trace_regs.orig_arg1()));\n        virtualize = VirtualPerfCounterMonitor::should_virtualize(attr);\n        if (virtualize) {\n          t->fd_table()->add_monitor(t,\n              fd, new VirtualPerfCounterMonitor(t, target, attr));\n        }\n      }\n      // Ignoring perf_event_open from syscallbuf; we'll attach a PreserveFileMonitor to it if it stays open\n      if (!virtualize &&\n          t->ip() != t->vm()->privileged_traced_syscall_ip().increment_by_syscall_insn_length(t->arch())) {\n        t->fd_table()->add_monitor(t, fd, new NonvirtualPerfCounterMonitor());\n      }\n    }\n      RR_FALLTHROUGH;\n\n    case Arch::recvmsg:\n    case Arch::recvmmsg:\n    case Arch::recvmmsg_time64:\n    case Arch::socketcall:\n      handle_opened_files(t, 0);\n      break;\n\n    case Arch::openat:\n      handle_opened_files(t, t->regs().arg3());\n      break;\n    case Arch::openat2:\n      handle_opened_files(t, t->read_mem(remote_ptr<int64_t>(t->regs().arg3())));\n      break;\n    case Arch::open:\n      handle_opened_files(t, t->regs().arg2());\n      break;\n\n    case Arch::write:\n    case Arch::writev:\n      /* write*() can be desched'd, but don't use scratch,\n       * so we might have saved 0 bytes of scratch after a\n       * desched. */\n      maybe_noop_restore_syscallbuf_scratch(t);\n      return;\n\n    case Arch::process_vm_writev: {\n      // Recorded data records may be for another process.\n      ReplayTask* dest = t->session().find_task(t->regs().arg1());\n      if (dest) {\n        uint32_t iov_cnt = t->regs().arg5();\n        for (uint32_t i = 0; i < iov_cnt; ++i) {\n          dest->apply_data_record_from_trace();\n        }\n      }\n      return;\n    }\n\n    case Arch::read: {\n      if (t->cloned_file_data_fd_child >= 0) {\n        int fd = (int)t->regs().arg1();\n        string file_name = t->file_name_of_fd(fd);\n        if (!file_name.empty() &&\n            file_name == t->file_name_of_fd(t->cloned_file_data_fd_child)) {\n          // This is a read of the cloned-data file. Replay logic depends on\n          // this file's offset actually advancing.\n          AutoRemoteSyscalls remote(t);\n          remote.infallible_lseek_syscall(fd, trace_regs.syscall_result(),\n                                          SEEK_CUR);\n        }\n      }\n      return;\n    }\n  }\n\n  if (sys == t->session().syscall_number_for_rrcall_notify_control_msg()) {\n    handle_opened_files(t, 0);\n  } else if (sys == t->session().syscall_number_for_rrcall_init_buffers()) {\n    process_init_buffers(t, step);\n  } else if (sys == t->session().syscall_number_for_rrcall_init_preload()) {\n    t->at_preload_init();\n  } else if (sys == t->session().syscall_number_for_rrcall_reload_auxv()) {\n    // Inner rr has finished emulating execve for a tracee. Reload auxv\n    // vectors now so that if gdb gets attached to the inner tracee, it will\n    // get useful symbols.\n    Task* target = t->session().find_task((pid_t)t->regs().arg1());\n    ASSERT(t, target) << \"SYS_rrcall_reload_auxv misused\";\n    target->vm()->save_auxv(target);\n  } else if (sys == t->session().syscall_number_for_rrcall_notify_stap_semaphore_added()) {\n    remote_ptr<uint16_t> range_start(t->regs().arg1()),\n                         range_end(t->regs().arg2());\n    MemoryRange semaphore_range(range_start, range_end);\n    t->vm()->add_stap_semaphore_range(t, semaphore_range);\n  } else if (sys == t->session().syscall_number_for_rrcall_notify_stap_semaphore_removed()) {\n    remote_ptr<uint16_t> range_start(t->regs().arg1()),\n                         range_end(t->regs().arg2());\n    MemoryRange semaphore_range(range_start, range_end);\n    t->vm()->remove_stap_semaphore_range(t, semaphore_range);\n  }\n}\n\nvoid rep_process_syscall(ReplayTask* t, ReplayTraceStep* step) {\n  const TraceFrame& trace_frame = t->current_trace_frame();\n  step->syscall.arch = trace_frame.event().Syscall().arch();\n  const Registers& trace_regs = trace_frame.regs();\n  with_converted_registers<void>(\n      trace_regs, step->syscall.arch, [&](const Registers& trace_regs) {\n        RR_ARCH_FUNCTION(rep_process_syscall_arch, step->syscall.arch, t, step,\n                         trace_regs)\n      });\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/replay_syscall.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_REP_PROCESS_EVENT_H_\n#define RR_REP_PROCESS_EVENT_H_\n\n#include \"TraceStream.h\"\n\nnamespace rr {\n\nclass ReplayTask;\nstruct ReplayTraceStep;\n\n/**\n * Prepare for a pending syscall. Call this when |t| is going to run towards\n * a syscall.\n */\nvoid rep_prepare_run_to_syscall(ReplayTask* t, ReplayTraceStep* step);\n\n/**\n * Call this when |t| has just entered a syscall.\n */\nvoid rep_after_enter_syscall(ReplayTask* t);\n\n/**\n * Process pending syscall. Call this when |t| is about to exit a syscall.\n */\nvoid rep_process_syscall(ReplayTask* t, ReplayTraceStep* step);\n\n/**\n * Process an EV_GROW_MAP event. These are like mmap syscalls, so handled\n * in replay_syscall.\n */\nvoid process_grow_map(ReplayTask* t);\n\n} // namespace rr\n\n#endif /* RR_REP_PROCESS_EVENT_H_ */\n"
  },
  {
    "path": "src/rr_trace.capnp",
    "content": "# rr trace file schema\n\n@0xcaa0b1486c12c629;\n\nusing Cxx = import \"/capnp/c++.capnp\";\n$Cxx.namespace(\"rr::trace\");\n\n# We generally use Data instead of Text because for e.g. files there is no\n# guarantee the data are valid UTF-8.\n# We use the natural system types whenever possible. For example, even though\n# negative fds are not possible, we use Int32 for fds to match kernel/library\n# APIs. This avoids potential problems where the trace value doesn't fit into\n# the range of the type where it is actually used.\n# \"Must\" constraints noted below should be checked by consumers.\n\n# A path that could be used during replay.\n# Must not contain any null bytes\nusing Path = Data;\n\n# Must not contain any null bytes\nusing CString = Data;\n\nusing Device = UInt64;\nusing Inode = UInt64;\nusing RemotePtr = UInt64;\n\n# Must be > 0\nusing FrameTime = Int64;\n# Must be > 0\nusing Tid = Int32;\n# Must be >= 0\nusing Ticks = Int64;\n# Must be >= 0\nusing Fd = Int32;\n\n# Describes what \"ticks\" mean in this trace\nenum TicksSemantics {\n  retiredConditionalBranches @0;\n  # Excludes interrupts, far branches, and rets\n  takenBranches @1;\n}\n\nenum CpuTriState {\n  unknown @0;\n  knownTrue @1;\n  knownFalse @2;\n}\n\nenum ChaosMode {\n  unknown @0;\n  knownTrue @1;\n  knownFalse @2;\n}\n\nstruct UtsName {\n  sysname @0 :CString;\n  nodename @1 :CString;\n  release @2 :CString;\n  version @3 :CString;\n  machine @4 :CString;\n  domainname @5 :CString;\n}\n\n# The 'version' file contains an ASCII version number followed by a newline.\n# The version number is currently 85 and increments only when there's a\n# backwards-incompatible change. See TRACE_VERSION.\n# After that, there is a Capnproto Header message.\n\nstruct Header {\n  # A random, unique ID for the trace\n  # Always 16 bytes\n  uuid @0 :Data;\n  # The CPU number the trace was bound to during recording, or -1 if it\n  # wasn't bound.\n  bindToCpu @1 :Int32;\n  # Semantics of \"ticks\" in this trace\n  ticksSemantics @6 :TicksSemantics;\n  # The syscallbuf protocol version. See SYSCALLBUF_PROTOCOL_VERSION.\n  syscallbufProtocolVersion @4 :UInt16;\n  # Trace recorded OK. False if rr crashed out due to an fatal assertion etc.\n  ok @7 :Bool = true;\n  # Do the mappings of preload_thread_locals always appear in the trace?\n  preloadThreadLocalsRecorded @8 :Bool = false;\n  # Base rr syscall number (rrcall_init_preload). Before this was variable,\n  # it was 442.\n  rrcallBase @9 :Int32 = 442;\n  nativeArch @10 :Arch = x8664;\n  # Architecture specific data, determined by nativeArch\n  x86 :group {\n    # True if the trace used CPUID faulting during recording (so CPUIDs\n    # were recorded as InstructionTraps).\n    hasCpuidFaulting @2 :Bool;\n    # A list of captured CPUID values.\n    # A series of 24-byte records. See CPUIDRecord in util.h.\n    cpuidRecords @3 :Data;\n    # Captured XCR0 value defining XSAVE features enabled by OS.\n    # 0 means \"unknown\"; default to everything supported by CPUID EAX=0xd ECX=0\n    xcr0 @5 :UInt64;\n    # Whether XSAVE instructions write FIP/FDP when there is no pending x87 exception\n    # rr itself doesn't use this yet.\n    xsaveFipFdpQuirk @12 :CpuTriState = unknown;\n    # Whether FDP is written only when an x87 instruction raises an unmasked exception\n    # rr itself doesn't use this yet.\n    fdpExceptionOnlyQuirk @13 :CpuTriState = unknown;\n    # rr sets FIP/FDP to zero at each recorded event.\n    clearFipFdp @14 :Bool = false;\n  }\n  # These flags guard rr behavior differences that ensure old rr traces can\n  # be successfully replayed on newer replayers\n  quirks :group {\n    # Whether the version of rr that recorded this, explicitly recorded\n    # modifications made through /proc/<pid>/<mem>\n    explicitProcMem @11 :Bool = true;\n\n    # Whether the version of rr that recorded this (may have) had special\n    # record behavior for librrpage.so\n    specialLibrrpage @15 :Bool = true;\n\n    # Whether the version of rr that recorded this saved the extra registers\n    # for the pkey_alloc syscall.\n    pkeyAllocRecordedExtraRegs @20 :Bool = false;\n\n    # Whether the version of rr that recorded this forced a tick after each\n    # buffered syscall.\n    bufferedSyscallForcedTick @21 :Bool = false;\n\n    # Whether the version of rr that recorded this was using the globals.in_replay\n    # flag rather than the rr page in_replay flag.\n    usesGlobalsInReplay @24 :Bool = true;\n  }\n  # Are we known to be in chaos mode? Useful for debugging.\n  chaosMode @16 :ChaosMode = unknown;\n  # If in chaos mode, what was the global exclusion range. Useful for debugging.\n  exclusionRangeStart @17 :RemotePtr;\n  exclusionRangeEnd @18 :RemotePtr;\n  # Replaying this trace requires at least this forward-compatibility-version\n  requiredForwardCompatibilityVersion @19 :Int32;\n  # real page size of the recorded process\n  runtimePageSize @22 :UInt32 = 4096;\n  # rr page size, i.e. the one used to build the librr_page.so\n  preloadLibraryPageSize @23 :UInt32 = 4096;\n  # SYSCALLBUF_FDS_DISABLED_SIZE during recording\n  syscallbufFdsDisabledSize @25 :UInt32 = 1024;\n  # sizeof(syscallbuf_hdr) during recording\n  syscallbufHdrSize @26 :UInt32 = 30;\n  # Result of uname(2). Possibly useful for diagnostics or LLDB qHostInfo.\n  uname @27 :UtsName;\n  # The highest virtual address size (in bits) needed to replay this trace. Some\n  # platforms (e.g. x86-64) have multiple possible virtual address sizes, and\n  # trace portability requires that traces that require a higher virtual address\n  # size are not replayed on systems that only support a lower virtual address\n  # size. A value of 0, only present for traces recorded before this was added,\n  # means the default value for the relevant arch.\n  maxVirtualAddressSize @28 :UInt8 = 0;\n  # One of our pre-flight checks found the CPU has issues (e.g. the Zen SpecLockMap\n  # optimization is not disabled) but the user chose to force recording to\n  # continue regardless.\n  cpuImproperlyConfigured @29 :CpuTriState = unknown;\n}\n\n# A file descriptor belonging to a task\nstruct RemoteFd {\n  tid @0 :Tid;\n  fd @1 :Int32;\n}\n\n# The 'mmaps', 'tasks' and 'events' files consist of a series of chunks.\n# Each chunk starts with a header of two 32-bit words: the size of the\n# uncompressed data, and the size of the Brotli-compressed data. The\n# compressed data follows.\n\n# The 'mmaps' file is a sequence of these.\nstruct MMap {\n  frameTime @0 :FrameTime;\n  # kernel memory mapping data\n  start @1 :RemotePtr;\n  end @2 :RemotePtr;\n  # Not a Path because it is only meaningful during recording\n  # Must not contain any null bytes\n  fsname @3 :CString;\n  device @4 :Device;\n  inode @5 :Inode;\n  prot @6 :Int32;\n  flags @7 :Int32;\n  fileOffsetBytes @8 :Int64;\n  # data about the original mapped file\n  # (or all-zero if the data has been erased by `rr pack` because we don't\n  # expect the original file to be available)\n  statMode @9 :UInt32;\n  statUid @10 :UInt32;\n  statGid @11 :UInt32;\n  # must be >= 0\n  statSize @12 :Int64;\n  statMTime @13 :Int64;\n  # how to get the data during replay\n  source :union {\n    zero @14 :Void;\n    trace @15 :Void;\n    file :group {\n      # Either an absolute path, or relative to the trace directory\n      backingFileName @16 :Path;\n    }\n  }\n  # File descriptors pointing to this mapping, other than the one\n  # that was mapped (for non-anonymous mappings).\n  extraFds @17 :List(RemoteFd);\n  # True if the mapped fd was read-only and should not be monitored\n  skipMonitoringMappedFd @18 :Bool;\n}\n\n# The 'tasks' file is a sequence of these.\nstruct TaskEvent {\n  frameTime @0 :FrameTime;\n  tid @1 :Tid;\n  union {\n    clone :group {\n      parentTid @2 :Tid;\n      flags @3 :Int32;    # Kernel's CLONE_ flags\n      ownNsTid @4 :Tid;\n    }\n    exec :group {\n      # Not a Path since it is only meaningful during recording\n      fileName @5 :CString;\n      cmdLine @6 :List(CString);\n      # Start address of executable mapping from /proc/.../exe\n      # Never null (in traces that support the field)\n      # Added after 5.0.0\n      exeBase @8 :RemotePtr;\n      interpBase @10 :RemotePtr;\n      # Not a Path since it is only meaningful during recording\n      interpName @11 :CString;\n      pacData @12 :PACData;\n    }\n    # Most frame 'exit' events generate one of these, but these are not\n    # generated if rr ends abnormally so the tasks did not in fact exit during\n    # recording.\n    exit :group {\n      exitStatus @7 :Int32;\n    }\n    detach :group {\n      none @9 :Void;\n    }\n  }\n}\n\nstruct WriteHole {\n  offset @0 :UInt64;\n  size @1 :UInt64;\n}\n\nstruct MemWrite {\n  tid @0 :Tid;\n  addr @1 :RemotePtr;\n  size @2 :UInt64;\n  # A list of regions where zeroes are written. These are not\n  # present in the compressed data.\n  holes @3 :List(WriteHole);\n  # This is set for writes where we don't actually know that the write\n  # will apply in full in the replayee (e.g. for conservative sigframe\n  # captures when handling EV_SIGNAL).\n  sizeIsConservative @4 :Bool;\n}\n\nenum Arch {\n  x86 @0;\n  x8664 @1;\n  aarch64 @2;\n}\n\nstruct Registers {\n  # May be empty. Format determined by Frame::arch\n  raw @0 :Data;\n}\n\nstruct ExtraRegisters {\n  # May be empty. Format determined by Frame::arch\n  raw @0 :Data;\n}\n\nstruct PACData {\n  # Formay determined by Frame::arch\n  raw @0 :Data;\n}\n\nenum SyscallState {\n  enteringPtrace @0;\n  entering @1;\n  exiting @2;\n}\n\nenum SignalDisposition {\n  fatal @0;\n  userHandler @1;\n  ignored @2;\n}\n\nstruct Signal {\n  # May differ from the Frame's arch, e.g. on x86-64 we always save\n  # siginfo in x86-64 format even for x86-32 Frames.\n  siginfoArch @0 :Arch;\n  # Native 'siginfo_t' for the given siginfoArch.\n  siginfo @1 :Data;\n  deterministic @2 :Bool;\n  disposition @3 :SignalDisposition;\n}\n\n# Some file opens are \"special\" (e.g. opening /dev/tty, or /proc/.../mem)\n# and get recorded in the trace as such\nstruct OpenedFd {\n  fd @0 :Fd;\n  # Absolute pathname, or \"terminal\" if we opened the terminal in some way\n  # Not a Path since it is only meaningful during recording\n  path @1 :CString;\n  # These are used to associate an opened fd with the right mapped file.\n  # May be zero for legacy recordings!\n  device @2 :Device;\n  inode @3 :Inode;\n}\n\nstruct MemRange {\n  start @0 :RemotePtr;\n  end @1 :RemotePtr;\n}\n\n# The 'events' file is a sequence of these.\nstruct Frame {\n  tid @0 :Tid;\n  # Per-task total tick count.\n  ticks @1 :Ticks;\n  # The baseline is unspecified, so only the differences between frames'\n  # values are meaningful.\n  # The time is the time this record was written, i.e. after the execution\n  # of this frame completed.\n  monotonicSec @2 :Float64;\n  # Userspace writes performed by this event\n  memWrites @3 :List(MemWrite);\n  # Architecture of this task at this event\n  # Determines the format of 'registers' and 'extraRegisters'\n  arch @4 :Arch;\n  registers @5 :Registers;\n  extraRegisters @6 :ExtraRegisters;\n  # If the event ends in the syscallbuf, then the address of the 'syscall_hook'\n  # function, otherwise zero.\n  # For legacy reasons this lives here but it only applies to sched events.\n  inSyscallbufSyscallHook @30 :UInt64;\n  event :union {\n    instructionTrap @7 :Void;\n    patchSyscall @8 :Void;\n    syscallbufAbortCommit @9 :Void;\n    syscallbufReset @10 :Void;\n    sched @11 :Void;\n    growMap @12 :Void;\n    signal @13 :Signal;\n    signalDelivery @14 :Signal;\n    signalHandler @15 :Signal;\n    exit @16 :Void;\n    syscallbufFlush :group {\n      # Not used during replay, but affects virtual memory layout so\n      # useful for some tools\n      # An array of 'mprotect_record's (see preload_interface.h)\n      mprotectRecords @17 :Data;\n    }\n    syscall :group {\n      # Linux supports system calls that are of a different architecture to\n      # the task's actual architecture (in particular, x86-32 syscalls via\n      # int $0x80 in an x86-64 process)\n      arch @18 :Arch;\n      number @19 :Int32;\n      state @20 :SyscallState;\n      failedDuringPreparation @21 :Bool;\n      extra :union {\n        none @22 :Void;\n        # Must be >= 0\n        writeOffset @23 :Int64;\n        execFdsToClose @24 :List(Fd);\n        openedFds @25 :List(OpenedFd);\n        socketAddrs :group {\n          localAddr @28 :Data;\n          remoteAddr @29 :Data;\n        }\n        # The list of all memory ranges affected by an madvise(). If empty,\n        # a successful madvise affected the range indicated by its parameters,\n        # and an unsuccessful madvise affected nothing.\n        # Currently, if an madvise was fully successful (returned 0),\n        # this list is always empty.\n        # Only populated for replay-relevant madvises, i.e. DONTNEED(_LOCKED)\n        # and REMOVE.\n        madviseRanges @32 :List(MemRange);\n      }\n    }\n    patchAfterSyscall @26: Void;\n    patchVsyscall @27: Void;\n    patchTrappingInstruction @31: Void;\n  }\n}\n"
  },
  {
    "path": "src/seccomp-bpf.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n/*\n * seccomp example for x86 (32-bit and 64-bit) with BPF macros\n *\n * Copyright (c) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>\n * Authors:\n *  Will Drewry <wad@chromium.org>\n *  Kees Cook <keescook@chromium.org>\n *\n * The code may be used by anyone for any purpose, and can serve as a\n * starting point for developing applications using mode 2 seccomp.\n */\n#ifndef RR_SECCOMP_BPF_H_\n#define RR_SECCOMP_BPF_H_\n\n#define _GNU_SOURCE 1\n#include <errno.h>\n#include <signal.h>\n#include <stddef.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <unistd.h>\n\n#include <asm/unistd.h>\n\n#include <vector>\n\n#include \"core.h\"\n#include \"remote_code_ptr.h\"\n\n#include <sys/prctl.h>\n#include <sys/user.h>\n#ifndef PR_SET_NO_NEW_PRIVS\n#define PR_SET_NO_NEW_PRIVS 38\n#endif\n\n#include <linux/audit.h>\n#include <linux/filter.h>\n#include <linux/unistd.h>\n#ifdef HAVE_LINUX_SECCOMP_H\n#include <linux/seccomp.h>\n#endif\n#ifndef SECCOMP_MODE_FILTER\n#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */\n\n#define SECCOMP_RET_KILL 0x00000000U\n#define SECCOMP_RET_TRAP 0x00030000U\n#define SECCOMP_RET_ERRNO 0x00050000U\n#define SECCOMP_RET_TRACE 0x7ff00000U\n#define SECCOMP_RET_ALLOW 0x7fff0000U\n\n#define SECCOMP_RET_ACTION 0x7fff0000U\n#define SECCOMP_RET_DATA 0x0000ffffU\n\nstruct seccomp_data {\n  int nr;\n  __u32 arch;\n  __u64 instruction_pointer;\n  __u64 args[6];\n};\n#endif\n\nnamespace rr {\n\n#define inst_ptr (offsetof(struct seccomp_data, instruction_pointer))\n\ntemplate <typename T> class SeccompFilter {\npublic:\n  void allow() {\n    filters.push_back(BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_ALLOW));\n  }\n  void trace() {\n    filters.push_back(\n        BPF_STMT(BPF_RET + BPF_K, SECCOMP_RET_TRACE | SECCOMP_RET_DATA));\n  }\n  void allow_syscalls_from_callsite(remote_code_ptr ip) {\n    uint32_t v(ip.register_value());\n    DEBUG_ASSERT(ip.register_value() == v);\n    filters.push_back(BPF_STMT(BPF_LD + BPF_W + BPF_ABS, inst_ptr));\n    filters.push_back(BPF_JUMP(BPF_JMP + BPF_JEQ + BPF_K, v, 0, 1));\n    allow();\n  }\n  std::vector<T> filters;\n};\n}\n\n#endif /* RR_SECCOMP_BPF_H_ */\n"
  },
  {
    "path": "src/syscalls.py",
    "content": "class BaseSyscall(object):\n    \"\"\"A base class for syscalls.\n\n    The constructor accepts specifications for the x86 and x86-64 syscall\n    numbers; if one of them does not exist, then the associated syscall is\n    assumed to not exist on the corresponding architecture.\n    \"\"\"\n\n    # Take **kwargs and ignore to make life easier on RegularSyscall.\n    def __init__(self, all=None, x86=None, x64=None, generic=None, **kwargs):\n        if all:\n            x86 = all\n            x64 = all\n            generic = all\n        assert x86 or x64       # Must exist on one architecture.\n        self.x86 = x86\n        self.x64 = x64\n        self.generic = generic\n        assert len(kwargs) == 0\n\nclass RestartSyscall(BaseSyscall):\n    \"\"\"A special class for the restart_syscall syscall.\"\"\"\n    def __init__(self, **kwargs):\n        BaseSyscall.__init__(self, **kwargs)\n\nclass UnsupportedSyscall(BaseSyscall):\n    \"\"\"A syscall that is unsupported by rr.\n\n    It is useful to expose these syscalls to the system, so that proper names\n    can be displayed in error messages, if nothing else.  They also serve as\n    useful documentation.\n    \"\"\"\n    def __init__(self, **kwargs):\n        BaseSyscall.__init__(self, **kwargs)\n\nclass InvalidSyscall(UnsupportedSyscall):\n    \"\"\"A syscall that is unsupported by rr and unimplemented by Linux.\n\n    We distinguish syscalls unimplemented by any version of Linux supported\n    by rr from other UnsupportedSyscalls, to help us track the completeness\n    of rr's syscall support.\n    \"\"\"\n    def __init__(self, **kwargs):\n        UnsupportedSyscall.__init__(self, **kwargs)\n\nclass RegularSyscall(BaseSyscall):\n    \"\"\"A syscall for which replay information may be recorded automatically.\n\n    The arguments required for rr to record may be specified directly\n    through the arg1...arg6 keyword arguments.  The values for these\n    arguments determine the size of the associated arguments to the syscall.\n    The only allowed type for a given argument is a Python string, in which\n    case the size of the argument is sizeof(arg).\n\n    To ensure correct handling for mixed-arch process groups (e.g. a mix of 32\n    and 64-bit processes), types should be specified using Arch instead of\n    referring directly to the host system types.\n    \"\"\"\n    def __init__(self, **kwargs):\n        for a in range(1,6):\n            arg = 'arg' + str(a)\n            if arg in kwargs:\n                self.__setattr__(arg, kwargs[arg])\n                kwargs.pop(arg)\n        BaseSyscall.__init__(self, **kwargs)\n\nclass EmulatedSyscall(RegularSyscall):\n    \"\"\"A wrapper for regular syscalls.\n    \"\"\"\n    def __init__(self, **kwargs):\n        RegularSyscall.__init__(self, **kwargs)\n\nclass IrregularEmulatedSyscall(BaseSyscall):\n    \"\"\"A wrapper for irregular syscalls.\n    \"\"\"\n    def __init__(self, **kwargs):\n        BaseSyscall.__init__(self, **kwargs)\n\n#  void exit(int status)\n#\n# The exit() function causes normal process termination and the value\n# of status & 0377 is returned to the parent (see wait(2)).\nexit = IrregularEmulatedSyscall(x86=1, x64=60, generic=93)\n\n# Obsolete, glibc calls clone() instead.\n# But Google Breakpad uses it!\nfork = IrregularEmulatedSyscall(x86=2, x64=57)\n\n#  ssize_t read(int fd, void *buf, size_t count);\n#\n# read() attempts to read up to count bytes from file descriptor fd\n# into the buffer starting at buf.\n#\n# CHECKED: (trace->recorded_regs.eax > 0)\nread = IrregularEmulatedSyscall(x86=3, x64=0, generic=63)\n\n#  ssize_t write(int fd, const void *buf, size_t count);\n#\n# write() writes up to count bytes to the file referenced by the file\n# descriptor fd from the buffer starting at buf. POSIX requires that\n# a read() which can be proved to occur after a write() has returned\n# returns the new data. Note that not all file systems are POSIX\n# conforming.\n#\n# Note: write isn't irregular per se; we hook it to redirect output\n# to stdout/stderr during replay.\nwrite = IrregularEmulatedSyscall(x86=4, x64=1, generic=64)\n\n#  int open(const char *pathname, int flags)\n#  int open(const char *pathname, int flags, mode_t mode)\n#\n# Given a pathname for a file, open() returns a file descriptor, a\n# small, nonnegative integer for use in subsequent system calls\n# (read(2), write(2), lseek(2), fcntl(2), etc.).  The file descriptor\n# returned by a successful call will be the lowest-numbered file\n# descriptor not currently open for the process.\nopen = IrregularEmulatedSyscall(x86=5, x64=2)\n\n#  int close(int fd)\n#\n# close() closes a file descriptor, so that it no longer refers to\n# any file and may be reused.  Any record locks (see fcntl(2)) held\n# on the file it was associated with, and owned by the process, are\n# removed (regardless of the file descriptor that was used to obtain\n# the lock).\nclose = IrregularEmulatedSyscall(x86=6, x64=3, generic=57)\n\n#  int close_range(unsigned int first, unsigned int last, unsigned int flags);\n#\n# The close_range() system call closes all open file descriptors\n# from first to last (included).\n#\n# Errors closing a given file descriptor are currently ignored.\nclose_range = IrregularEmulatedSyscall(all=436)\n\n#  pid_t waitpid(pid_t pid, int *status, int options);\n#\n# The waitpid() system call suspends execution of the calling process\n# until a child specified by pid argument has changed state.  By\n# default, waitpid() waits only for terminated children, but this\n# behavior is modifiable via the options argument, as described\n# below....\nwaitpid = IrregularEmulatedSyscall(x86=7)\n\n#  int creat(const char *pathname, mode_t mode);\n#\n# creat() is equivalent to open() with flags equal to\n# O_CREAT|O_WRONLY|O_TRUNC.\ncreat = EmulatedSyscall(x86=8, x64=85)\n\n#  int link(const char *oldpath, const char *newpath);\n#\n# link() creates a new link (also known as a hard link) to an\n# existing file.\nlink = EmulatedSyscall(x86=9, x64=86)\n\n#  int unlink(const char *path);\n#\n# The unlink() function shall remove a link to a file. If path names\n# a symbolic link, unlink() shall remove the symbolic link named by\n# path and shall not affect any file or directory named by the\n# contents of the symbolic link. Otherwise, unlink() shall remove the\n# link named by the pathname pointed to by path and shall decrement\n# the link count of the file referenced by the link.\nunlink = EmulatedSyscall(x86=10, x64=87)\n\n#  int execve(const char *filename, char *const argv[], char *const envp[]);\n#\n# execve() executes the program pointed to by filename.\nexecve = IrregularEmulatedSyscall(x86=11, x64=59, generic=221)\n\n#  int chdir(const char *path);\n#\n# chdir() changes the current working directory of the calling\n# process to the directory specified in path.\nchdir = EmulatedSyscall(x86=12, x64=80, generic=49)\n\n#  time_t time(time_t *t);\n#\n# time() returns the time since the Epoch (00:00:00 UTC, January 1,\n# 1970), measured in seconds. If t is non-NULL, the return value is\n# also stored in the memory pointed to by t.\ntime = EmulatedSyscall(x86=13, x64=201, arg1=\"typename Arch::time_t\")\n\nmknod = EmulatedSyscall(x86=14, x64=133)\n\n#  int chmod(const char *path, mode_t mode)\n#\n# The mode of the file given by path or referenced by fildes is\n# changed.\nchmod = EmulatedSyscall(x86=15, x64=90)\nlchown = EmulatedSyscall(x86=16, x64=94)\n_break = InvalidSyscall(x86=17)\noldstat = UnsupportedSyscall(x86=18)\n\n#  off_t lseek(int fd, off_t offset, int whence)\n#\n# The lseek() function repositions the offset of the open file\n# associated with the file descriptor fd to the argument offset\n# according to the directive whence as follows:\nlseek = EmulatedSyscall(x86=19, x64=8, generic=62)\n\n#  pid_t getpid(void);\n#\n# getpid() returns the process ID of the calling process.  (This is\n# often used by routines that generate unique temporary\n# filenames.)\ngetpid = EmulatedSyscall(x86=20, x64=39, generic=172)\n\nmount = EmulatedSyscall(x86=21, x64=165, generic=40)\numount = EmulatedSyscall(x86=22)\nsetuid = EmulatedSyscall(x86=23, x64=105, generic=146)\ngetuid = EmulatedSyscall(x86=24, x64=102, generic=174)\nstime = UnsupportedSyscall(x86=25)\n\n#  long ptrace(enum __ptrace_request request, pid_t pid,\n#              void *addr, void *data);\n#\n# The ptrace() system call provides a means by which one process (the\n# \"tracer\") may observe and control the execution of another process\n# (the \"tracee\"), and examine and change the tracee's memory and\n# registers.  It is primarily used to implement breakpoint debugging\n# and system call tracing.\nptrace = IrregularEmulatedSyscall(x86=26, x64=101, generic=117)\n\n#  unsigned int alarm(unsigned int seconds)\n#\n# The alarm() system call schedules an alarm. The process will get a\n# SIGALRM after the requested amount of seconds.\nalarm = EmulatedSyscall(x86=27, x64=37)\noldfstat = UnsupportedSyscall(x86=28)\n\n#  int pause(void);\n#\n# pause() causes the calling process (or thread) to sleep until a\n# signal is delivered that either terminates the process or causes\n# the invocation of a signal-catching function.\npause = IrregularEmulatedSyscall(x86=29, x64=34)\n\n#  int utime(const char *filename, const struct utimbuf *times)\n#\n# The utime() system call changes the access and modification times\n# of the inode specified by filename to the actime and modtime fields\n# of times respectively.\n#\n# If times is NULL, then the access and modification times of the\n# file are set to the current time.\n#\n# Changing timestamps is permitted when: either the process has\n# appropriate privileges, or the effective user ID equals the user ID\n# of the file, or times is NULL and the process has write permission\n# for the file.\n#\n# FIXME: is mod_time set by the kernel?\nutime = EmulatedSyscall(x86=30, x64=132)\n\nstty = InvalidSyscall(x86=31)\ngtty = InvalidSyscall(x86=32)\n\n#  int access(const char *pathname, int mode);\n#\n# access() checks whether the calling process can access the file\n# pathname.  If pathname is a symbolic link, it is dereferenced.\naccess = EmulatedSyscall(x86=33, x64=21)\n\nnice = UnsupportedSyscall(x86=34)\nftime = InvalidSyscall(x86=35)\nsync = IrregularEmulatedSyscall(x86=36, x64=162, generic=81)\n\n#  int kill(pid_t pid, int sig)\n#\n# The kill() system call can be used to send any signal to any\n# process group or process.\nkill = EmulatedSyscall(x86=37, x64=62, generic=129)\n\n#  int rename(const char *oldpath, const char *newpath)\n#\n# rename() renames a file, moving it between directories if required.\nrename = EmulatedSyscall(x86=38, x64=82)\n\n#  int mkdir(const char *pathname, mode_t mode);\n#\n# mkdir() attempts to create a directory named pathname.\nmkdir = EmulatedSyscall(x86=39, x64=83)\n\n#  int rmdir(const char *pathname)\n#\n# rmdir() deletes a directory, which must be empty.\nrmdir = EmulatedSyscall(x86=40, x64=84)\n\n#  int dup(int oldfd)\n#\n# dup() uses the lowest-numbered unused descriptor for the new\n# descriptor.\ndup = EmulatedSyscall(x86=41, x64=32, generic=23)\n\n#  int pipe(int pipefd[2]);\n#\n# pipe() creates a pipe, a unidirectional data channel that can be\n# used for interprocess communication.  The array pipefd is used to\n# return two file descriptors referring to the ends of the pipe.\n# pipefd[0] refers to the read end of the pipe.  pipefd[1] refers to\n# the write end of the pipe.  Data written to the write end of the\n# pipe is buffered by the kernel until it is read from the read end\n# of the pipe.  For further details, see pipe(7).\npipe = EmulatedSyscall(x86=42, x64=22, arg1=\"int[2]\")\n\n#  clock_t times(struct tms *buf)\n#\n# times() stores the current process times in the struct tms that buf\n#  points to.  The struct tms is as defined in <sys/times.h>:\ntimes = EmulatedSyscall(x86=43, x64=100, generic=153, arg1=\"typename Arch::tms\")\n\nprof = InvalidSyscall(x86=44)\n\n#  int brk(void *addr)\n#\n# brk() and sbrk() change the location of the program break, which\n# defines the end of the process's data segment (i.e., the program\n# break is the first location after the end of the uninitialized data\n# segment).  Increasing the program break has the effect of\n# allocating memory to the process; decreasing the break deallocates\n# memory.\n#\n# brk() sets the end of the data segment to the value specified by\n# addr, when that value is reasonable, the system has enough memory,\n# and the process does not exceed its maximum data size (see\n# setrlimit(2)).\nbrk = IrregularEmulatedSyscall(x86=45, x64=12, generic=214)\n\n#  int setgid(gid_t gid)\n#\n# setgid() sets the effective group ID of the calling process.\n# If the caller is the superuser, the real GID and saved set-group-ID\n# are also set.\n#\n# Under Linux, setgid() is implemented like the POSIX version with the\n# _POSIX_SAVED_IDS feature.  This allows a set-group-ID program that\n# is not set-user-ID-root to drop all of its group privileges, do some\n# un-privileged work, and then reengage the original effective group\n# ID in a secure manner.\n#\n# setgid will return 0 on success, or if the process already runs\n# under the given gid.\nsetgid = EmulatedSyscall(x86=46, x64=106, generic=144)\n\ngetgid = EmulatedSyscall(x86=47, x64=104, generic=176)\nsignal = UnsupportedSyscall(x86=48)\ngeteuid = EmulatedSyscall(x86=49, x64=107, generic=175)\ngetegid = EmulatedSyscall(x86=50, x64=108, generic=177)\nacct = EmulatedSyscall(x86=51, x64=163, generic=89)\numount2 = EmulatedSyscall(x86=52, x64=166, generic=39)\nlock = InvalidSyscall(x86=53)\n\n#  int ioctl(int d, int request, ...)\n#\n# The ioctl() function manipulates the underlying device parameters\n# of special files.  In particular, many operating characteristics of\n# character special files (e.g., terminals) may be controlled with\n# ioctl() requests.  The argument d must be an open file descriptor.\n#\nioctl = IrregularEmulatedSyscall(x86=54, x64=16, generic=29)\n\nfcntl = IrregularEmulatedSyscall(x86=55, x64=72, generic=25)\nmpx = InvalidSyscall(x86=56)\n\n#  int setpgid(pid_t pid, pid_t pgid);\n#\n# setpgid() sets the PGID of the process specified by pid to pgid.\n# If pid is zero, then the process ID of the calling process is used.\n# If pgid is zero, then the PGID of the process specified by pid is\n# made the same as its process ID.  If setpgid() is used to move a\n# process from one process group to another (as is done by some\n# shells when creating pipelines), both process groups must be part\n# of the same session (see setsid(2) and credentials(7)).  In this\n# case, the pgid specifies an existing process group to be joined and\n# the session ID of that group must match the session ID of the\n# joining process.\nsetpgid = EmulatedSyscall(x86=57, x64=109, generic=154)\n\nulimit = InvalidSyscall(x86=58)\noldolduname = UnsupportedSyscall(x86=59)\n\n#  mode_t umask(mode_t mask);\n#\n# umask() sets the calling process's file mode creation mask (umask)\n# to mask & 0777 (i.e., only the file permission bits of mask are\n# used), and returns the previous value of the mask.\numask = EmulatedSyscall(x86=60, x64=95, generic=166)\n\nchroot = EmulatedSyscall(x86=61, x64=161, generic=51)\nustat = UnsupportedSyscall(x86=62, x64=136)\n\n#  int dup2(int oldfd, int newfd)\n#\n# dup2() makes newfd be the copy of oldfd, closing newfd first if\n#  necessary, but note the following..\ndup2 = IrregularEmulatedSyscall(x86=63, x64=33)\n\n#  pid_t getppid(void);\n#\n# getppid() returns the process ID of the parent of the calling\n# process.\ngetppid = EmulatedSyscall(x86=64, x64=110, generic=173)\n\n#  pid_t getpgrp(void)\n#\n# The POSIX.1 getpgrp() always returns the PGID of the caller.\ngetpgrp = EmulatedSyscall(x86=65, x64=111)\n\n#  pid_t setsid(void)\n#\n# setsid() is used to start a new session and set the new process\n# group ID.\nsetsid = EmulatedSyscall(x86=66, x64=112, generic=157)\n\n#  int sigaction(int signum, const struct sigaction *act, struct sigaction\n#*oldact);\n#\n# The sigaction() system call is used to change the action taken by a\n# process on receipt of a specific signal.  (See signal(7) for an\n# overview of signals.)\n#\n# signum specifies the signal and can be any valid signal except\n# SIGKILL and SIGSTOP.\n#\n# If act is non-NULL, the new action for signal signum is installed\n# from act.  If oldact is non-NULL, the previous action is saved in\n# oldact.\nsigaction = IrregularEmulatedSyscall(x86=67)\n\nsgetmask = UnsupportedSyscall(x86=68)\nssetmask = UnsupportedSyscall(x86=69)\nsetreuid = EmulatedSyscall(x86=70, x64=113, generic=145)\nsetregid = EmulatedSyscall(x86=71, x64=114, generic=143)\nsigsuspend = IrregularEmulatedSyscall(x86=72)\nsigpending = UnsupportedSyscall(x86=73)\nsethostname = EmulatedSyscall(x86=74, x64=170, generic=161)\n\n#  int setrlimit(int resource, const struct rlimit *rlim)\n#\n# getrlimit() and setrlimit() get and set resource limits\n# respectively.  Each resource has an associated soft and hard limit,\n# as defined by the rlimit structure (the rlim argument to both\n# getrlimit() and setrlimit()):\n#\n# NOTE: This syscall is emulated so the limit does not apply during\n# replay. Any signals triggered due to exceeded limits are emulated\n# by other means.\nsetrlimit = EmulatedSyscall(x86=75, x64=160, generic=164)\n\ngetrlimit = EmulatedSyscall(x86=76, x64=97, generic=163, arg2=\"typename Arch::rlimit\")\n\n#  int getrusage(int who, struct rusage *usage)\n#\n# getrusage() returns resource usage measures for who, which can be\n# one of the following..\ngetrusage = EmulatedSyscall(x86=77, x64=98, generic=165, arg2=\"typename Arch::rusage\")\n\n#  int gettimeofday(struct timeval *tv, struct timezone *tz);\n#\n# The functions gettimeofday() and settimeofday() can get and set the\n# time as well as a timezone.  The tv argument is a struct timeval\n# (as specified in <sys/time.h>):\ngettimeofday = EmulatedSyscall(x86=78, x64=96, generic=169, arg1=\"typename Arch::timeval\", arg2=\"typename Arch::timezone\")\n\nsettimeofday = UnsupportedSyscall(x86=79, x64=164, generic=170)\ngetgroups = IrregularEmulatedSyscall(x86=80, x64=115, generic=158)\nsetgroups = EmulatedSyscall(x86=81, x64=116, generic=159)\nselect = IrregularEmulatedSyscall(x86=82, x64=23)\n\n#  int symlink(const char *oldpath, const char *newpath)\n#\n# symlink() creates a symbolic link named newpath which contains the\n# string oldpath.\nsymlink = EmulatedSyscall(x86=83, x64=88)\n\noldlstat = UnsupportedSyscall(x86=84)\n\n#  ssize_t readlink(const char *path, char *buf, size_t bufsiz);\n#\n# readlink() places the contents of the symbolic link path in the\n# buffer buf, which has size bufsiz. readlink() does not append a\n# null byte to buf.  It will truncate the contents (to a length of\n# bufsiz characters), in case the buffer is too small to hold all of\n# the contents.\nreadlink = IrregularEmulatedSyscall(x86=85, x64=89)\n\nuselib = UnsupportedSyscall(x86=86, x64=134)\nswapon = UnsupportedSyscall(x86=87, x64=167, generic=224)\nreboot = UnsupportedSyscall(x86=88, x64=169, generic=142)\nreaddir = UnsupportedSyscall(x86=89)\n\n#  void *mmap2(void *addr, size_t length, int prot,int flags, int fd, off_t\n#pgoffset);\n#\n# The mmap2() system call operates in exactly the same way as\n# mmap(2), except that the final argument specifies the offset into\n# the file in 4096-byte units (instead of bytes, as is done by\n# mmap(2)).  This enables applications that use a 32-bit off_t to map\n# large files (up to 2^44 bytes).\nmmap = IrregularEmulatedSyscall(x86=90, x64=9, generic=222)\n\n#  int munmap(void *addr, size_t length)\n#\n# The munmap() system call deletes the mappings for the specified\n# address range, and causes further references to addresses within\n# the range to generate invalid memory references.  The region is\n# also automatically unmapped when the process is terminated.  On the\n# other hand, closing the file descriptor does not unmap the region.\nmunmap = IrregularEmulatedSyscall(x86=91, x64=11, generic=215)\n\n#  int truncate(const char *path, off_t length);\n#  int ftruncate(int fd, off_t length)\n#\n# The truncate() and ftruncate() functions cause the regular file\n# named by path or referenced by fd to be truncated to a size of\n# precisely length bytes.\ntruncate = EmulatedSyscall(x86=92, x64=76, generic=45)\nftruncate = EmulatedSyscall(x86=93, x64=77, generic=46)\n\n#  int fchmod(int fd, mode_t mode);\n#\n# fchmod() changes the permissions of the file referred to by the\n# open file descriptor fd\nfchmod = EmulatedSyscall(x86=94, x64=91, generic=52)\n\nfchown = EmulatedSyscall(x86=95, x64=93, generic=55)\n\n#  int getpriority(int which, int who);\n#\n# The scheduling priority of the process, process group, or user, as\n# indicated by which and who is obtained with the getpriority() call.\ngetpriority = EmulatedSyscall(x86=96, x64=140, generic=141)\n\n#  int setpriority(int which, int who, int prio);\n#\n# The scheduling priority of the process, process group, or user, as\n# indicated by which and who is obtained with the getpriority() call\n# and set with the setpriority() call.\nsetpriority = IrregularEmulatedSyscall(x86=97, x64=141, generic=140)\n\nprofil = InvalidSyscall(x86=98)\n\n#  int statfs(const char *path, struct statfs *buf)\n#\n# The function statfs() returns information about a mounted file\n# system.  path is the pathname of any file within the mounted file\n# system.  buf is a pointer to a statfs structure defined\n# approximately as follows:\nstatfs = EmulatedSyscall(x86=99, x64=137, generic=43, arg2=\"struct Arch::statfs_t\")\n\n#  int fstatfs(int fd, struct statfs *buf)\n#\n# The function statfs() returns information about a mounted file\n# system.  path is the pathname of any file within the\n# get_time(GET_TID(thread_id));mounted file system.  buf is a pointer\n# to a statfs structure defined approximately as follows:\nfstatfs = EmulatedSyscall(x86=100, x64=138, generic=44, arg2=\"struct Arch::statfs_t\")\n\nioperm = EmulatedSyscall(x86=101, x64=173)\n\n#  int socketcall(int call, unsigned long *args)\n#\n# socketcall() is a common kernel entry point for the socket system\n# calls.  call determines which socket function to invoke.  args\n# points to a block containing the actual arguments, which are passed\n# through to the appropriate call.\nsocketcall = IrregularEmulatedSyscall(x86=102)\n\nsyslog = IrregularEmulatedSyscall(x86=103, x64=103, generic=116)\n\n#  int setitimer(int which, const struct itimerval *new_value, struct itimerval\n#*old_value);\n#\n# The function setitimer() sets the specified timer to the value in\n# new_value.  If old_value is non-NULL, the old value of the timer is\n# stored there.\nsetitimer = EmulatedSyscall(x86=104, x64=38, generic=103, arg3=\"typename Arch::itimerval\")\ngetitimer = EmulatedSyscall(x86=105, x64=36, generic=102, arg2=\"typename Arch::itimerval\")\nstat = EmulatedSyscall(x86=106, x64=4, arg2=\"struct Arch::stat_t\")\nlstat = EmulatedSyscall(x86=107, x64=6, arg2=\"struct Arch::stat_t\")\nfstat = EmulatedSyscall(x86=108, x64=5, generic=80, arg2=\"struct Arch::stat_t\")\nolduname = UnsupportedSyscall(x86=109)\niopl = EmulatedSyscall(x86=110, x64=172)\nvhangup = UnsupportedSyscall(x86=111, x64=153, generic=58)\nidle = UnsupportedSyscall(x86=112)\nvm86old = UnsupportedSyscall(x86=113)\n\n#  pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);\n#\n# The wait3() and wait4() system calls are similar to waitpid(2), but\n# additionally return resource usage information about the child in\n# the structure pointed to by rusage.\nwait4 = IrregularEmulatedSyscall(x86=114, x64=61, generic=260)\n\nswapoff = UnsupportedSyscall(x86=115, x64=168, generic=225)\n\n#  int sysinfo(struct sysinfo *info)\n#\n# sysinfo() provides a simple way of getting overall system\n# statistics.\nsysinfo = EmulatedSyscall(x86=116, x64=99, generic=179, arg1=\"struct Arch::sysinfo_t\")\n#  int ipc(unsigned int call, int first, int second, int third, void *ptr, long\n#fifth);\n#\n# ipc() is a common kernel entry point for the System V IPC calls for\n# messages, semaphores, and shared memory.  call determines which IPC\n# function to invoke; the other arguments are passed through to the\n# appropriate call.\nipc = IrregularEmulatedSyscall(x86=117)\n\n#  int fsync(int fd)\n#\n# fsync() transfers (\"flushes\") all modified in-core data of (i.e.,\n# modified buffer cache pages for) the file referred to by the file\n# descriptor fd to the disk device (or other permanent storage\n# device) where that file resides.  The call blocks until the device\n# reports that the transfer has completed.  It also flushes metadata\n# information associated with the file (see stat(2))\nfsync = IrregularEmulatedSyscall(x86=118, x64=74, generic=82)\n\n#  int sigreturn(unsigned long __unused)\n#\n# When the Linux kernel creates the stack frame for a signal handler,\n# a call to sigreturn() is inserted into the stack frame so that upon\n# return from the signal handler, sigreturn() will be called.\nsigreturn = IrregularEmulatedSyscall(x86=119)\n\n#  int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, (pid_t\n#*ptid, struct user_desc *tls, pid_t *ctid));\n#\n# clone() creates a new process, in a manner similar to fork(2).  It\n# is actually a library function layered ontrace top of the\n# underlying clone() system call, hereinafter referred to tidas\n# sys_clone.  A description of sys_clone is given towards the end of\n# this page.\n#\n# NOTE: clone is actually implemented by sys_clone which has the\n# following signature:\n#\n#  long sys_clone(unsigned long clone_flags, unsigned long newsp, void __user\n#*parent_tid, void __user *child_tid, struct pt_regs *regs)\nclone = IrregularEmulatedSyscall(x86=120, x64=56, generic=220)\n\nsetdomainname = EmulatedSyscall(x86=121, x64=171, generic=162)\n\n#  int uname(struct utsname *buf)\n#\n# uname() returns system information in the structure pointed to by\n# buf. The utsname struct is defined in <sys/utsname.h>:\nuname = EmulatedSyscall(x86=122, x64=63, generic=160, arg1=\"typename Arch::utsname\")\n\nmodify_ldt = IrregularEmulatedSyscall(x86=123, x64=154)\n\n#  int adjtimex(struct timex *buf);\n#\n# adjtimex() takes a pointer to a timex structure, reads it, and returns\n# the same structure updated with the current kernel values.\nadjtimex = EmulatedSyscall(x86=124, x64=159, generic=171, arg1=\"typename Arch::timex\")\n\n#  int mprotect(const void *addr, size_t len, int prot)\n#\n# mprotect() changes protection for the calling process's memory\n# page(s) containing any part of the address range in the interval\n# [addr, addr+len-1].  addr must be aligned to a page boundary.\n#\n# If the calling process tries to access memory in a manner that\n# violates the protection, then the kernel generates a SIGSEGV signal\n# for the process.\nmprotect = IrregularEmulatedSyscall(x86=125, x64=10, generic=226)\n\n#  int sigprocmask(int how, const sigset_t *set, sigset_t *oldset);\n#\n# sigprocmask() is used to fetch and/or change the signal mask of the\n# calling thread.  The signal mask is the set of signals whose\n# delivery is currently blocked for the caller (see also signal(7)\n# for more details).\nsigprocmask = IrregularEmulatedSyscall(x86=126)\n\ncreate_module = UnsupportedSyscall(x86=127, x64=174)\ninit_module = UnsupportedSyscall(x86=128, x64=175, generic=105)\ndelete_module = UnsupportedSyscall(x86=129, x64=176, generic=106)\nget_kernel_syms = InvalidSyscall(x86=130, x64=177)\n\n#  int quotactl(int cmd, const char *special, int id, caddr_t addr);\n#\n# The quotactl() call manipulates disk quotas.  The cmd argument\n# indicates a command to be applied to the user or group ID\n# specified in id.  To initialize the cmd argument, use the\n# QCMD(subcmd, type) macro.  The type value is either USRQUOTA, for\n# user quotas, or GRPQUOTA, for group quotas.  The subcmd value is\n# described below.\nquotactl = IrregularEmulatedSyscall(x86=131, x64=179, generic=60)\n\n#  pid_t getpgid(pid_t pid);\n#\n# getpgid() returns the PGID of the process specified by pid.  If pid\n# is zero, getpgid() the process ID of the calling process is\n# used.int getrusage(int who, struct rusage *usage);\ngetpgid = EmulatedSyscall(x86=132, x64=121, generic=155)\n\n#  int fchdir(int fd);\n#\n# fchdir() is identical to chdir(); the only difference is that the\n# directory is given as an open file descriptor.\nfchdir = EmulatedSyscall(x86=133, x64=81, generic=50)\n\nbdflush = UnsupportedSyscall(x86=134)\nsysfs = IrregularEmulatedSyscall(x86=135, x64=139)\npersonality = IrregularEmulatedSyscall(x86=136, x64=135, generic=92)\nafs_syscall = InvalidSyscall(x86=137, x64=183)\nsetfsuid = EmulatedSyscall(x86=138, x64=122, generic=151)\nsetfsgid = EmulatedSyscall(x86=139, x64=123, generic=152)\n\n#  int _llseek(unsigned int fd, unsigned long offset_high, unsigned long\n#offset_low, loff_t *result, unsigned int whence);\n#\n# The _llseek() function repositions the offset of the open file\n# associated with the file descriptor fd to (offset_high<<32) |\n# offset_low bytes relative to the beginning of the file, the current\n# position in the file, or the end of the file, depending on whether\n# whence is SEEK_SET, SEEK_CUR, or SEEK_END, respectively.  It\n# returns the resulting file position in the argument result.\n_llseek = EmulatedSyscall(x86=140, arg4=\"typename Arch::__kernel_loff_t\")\n\n#  int getdents(unsigned int fd, struct linux_dirent *dirp, unsigned int\n#count);\n#\n# The system call getdents() reads several linux_dirent structures\n# from the directory referred to by the open file descriptor fd into\n# the buffer pointed to by dirp.  The argument count specifies the\n# size of that buffer.\ngetdents = IrregularEmulatedSyscall(x86=141, x64=78)\n\n#  int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,\n#struct timeval *timeout);\n#\n# select() and pselect() allow a program to monitor multiple file\n# descriptors, waiting until one or more of the file descriptors\n# become \"ready\" for some class of I/O operation (e.g., input\n# possible).  A file descriptor is considered ready if it is possible\n# to perform the corresponding I/O operation (e.g., read(2)) without\n# blocking.\n_newselect = IrregularEmulatedSyscall(x86=142)\n\nflock = EmulatedSyscall(x86=143, x64=73, generic=32)\n\n#  int msync(void *addr, size_t length, int flags);\n#\n# msync() flushes changes made to the in-core copy of a file that was\n# mapped into memory using mmap(2) back to disk.  Without use of this\n# call there is no guarantee that changes are written back before\n# munmap(2) is called.  To be more precise, the part of the file that\n# corresponds to the memory area starting at addr and having length\n# length is updated.\nmsync = IrregularEmulatedSyscall(x86=144, x64=26, generic=227)\n\n#  ssize_t readv(int fd, const struct iovec *iov, int iovcnt);\n#\n# The readv() system call reads iovcnt buffers from the file associated\n# with the file descriptor fd into the buffers described by iov (\"scatter\n# input\").\nreadv = IrregularEmulatedSyscall(x86=145, x64=19, generic=65)\n\n#  ssize_t writev(int fd, const struct iovec *iov, int iovcnt)\n#\n# The writev() function writes iovcnt buffers of data described by\n# iov to the file associated with the file descriptor fd (\"gather\n# output\").\nwritev = IrregularEmulatedSyscall(x86=146, x64=20, generic=66)\n\n# pid_t getsid(pid_t pid);\n#\n# getsid(0) returns the session ID of the calling process.  getsid(p)\n# returns the session ID of the process with process ID p.  (The session\n# ID of a process is the process group ID of the session leader.)\ngetsid = EmulatedSyscall(x86=147, x64=124, generic=156)\n\n#  int fdatasync(int fd)\n#\n# fdatasync() is similar to fsync(), but does not flush modified\n# metadata unless that metadata is needed in order to allow a\n# subsequent data retrieval to be correctly handled.  For example,\n# changes to st_atime or st_mtime (respectively, time of last access\n# and time of last modification; see stat(2)) do not require flushing\n# because they are not necessary for a subsequent data read to be\n# handled correctly.  On the other hand, a change to the file size\n# (st_size, as made by say ftruncate(2)), would require a metadata\n# flush\nfdatasync = IrregularEmulatedSyscall(x86=148, x64=75, generic=83)\n\n#  int _sysctl(struct __syscall_args* args);\n#\n# The _sysctl() call reads and/or writes kernel parameters.  For example,\n# the hostname, or the maximum number of open files.\n#\n# Often not supported in modern kernels, so can return ENOSYS.\n_sysctl = IrregularEmulatedSyscall(x86=149, x64=156)\n\nmlock = EmulatedSyscall(x86=150, x64=149, generic=228)\nmunlock = EmulatedSyscall(x86=151, x64=150, generic=229)\nmlockall = EmulatedSyscall(x86=152, x64=151, generic=230)\nmunlockall = EmulatedSyscall(x86=153, x64=152, generic=231)\nsched_setparam = EmulatedSyscall(x86=154, x64=142, generic=118)\n\n#  int sched_getparam(pid_t pid, struct sched_param *param)\n#\n# sched_getparam() retrieves the scheduling parameters for the\n# process i dentified by pid.  If pid is zero, then the parameters of\n# the calling process are retrieved.\nsched_getparam = EmulatedSyscall(x86=155, x64=143, generic=121, arg2=\"typename Arch::sched_param\")\n\n#  int sched_setscheduler(pid_t pid, int policy, const struct sched_param\n#*param);\n#\n# sched_setscheduler() sets both the scheduling policy and the\n# associated parameters for the process whose ID is specified in pid.\n# If pid equals zero, the scheduling policy and parameters of the\n# calling process will be set.  The interpretation of the argument\n# param depends on the selected policy.\nsched_setscheduler = EmulatedSyscall(x86=156, x64=144, generic=119)\n\n#  int sched_getscheduler(pid_t pid);\n#\n# sched_getscheduler() queries the scheduling policy currently\n# applied to the process identified by pid.  If pid equals zero, the\n# policy of the calling process will be retrieved.\nsched_getscheduler = EmulatedSyscall(x86=157, x64=145, generic=120)\n\n#  int sched_yield(void)\n#\n# sched_yield() causes the calling thread to relinquish the CPU.  The\n# thread is moved to the end of the queue for its static priority and\n# a new thread gets to run.\nsched_yield = IrregularEmulatedSyscall(x86=158, x64=24, generic=124)\n\n#  int sched_get_priority_max(int policy)\n#\n# sched_get_priority_max() returns the maximum priority value that\n# can be used with the scheduling algorithm identified by policy.\nsched_get_priority_max = EmulatedSyscall(x86=159, x64=146, generic=125)\n\n#  int sched_get_priority_min(int policy)\n#\n# sched_get_priority_min() returns the minimum priority value that\n# can be used with the scheduling algorithm identified by policy.\nsched_get_priority_min = EmulatedSyscall(x86=160, x64=147, generic=126)\n\nsched_rr_get_interval = UnsupportedSyscall(x86=161, x64=148, generic=127)\n\n#  int nanosleep(const struct timespec *req, struct timespec *rem)\n#\n# nanosleep() suspends the execution of the calling thread until\n# either at least the time specified in *req has elapsed, or the\n# delivery of a signal that triggers the invocation of a handler in\n# the calling thread or that ter- minates the process.\n#\n# CHECKED: trace->recorded_regs.ecx != NULL\nnanosleep = IrregularEmulatedSyscall(x86=162, x64=35, generic=101)\n\n#  void *mremap(void *old_address, size_t old_size, size_t new_size, int flags,\n#... ( void *new_address ));\n#\n# mremap() expands (or shrinks) an existing memory mapping,\n# potentially moving it at the same time (controlled by the flags\n# argument and the available virtual address space).\nmremap = IrregularEmulatedSyscall(x86=163, x64=25, generic=216)\n\n#  int setresuid(uid_t ruid, uid_t euid, uid_t suid);\n#\n# setresuid() sets the real user ID, the effective user ID, and the\n# saved set-user-ID of the calling process.\nsetresuid = EmulatedSyscall(x86=164, x64=117, generic=147)\n\ngetresuid = EmulatedSyscall(x86=165, x64=118, generic=148, arg1=\"typename Arch::legacy_uid_t\", arg2=\"typename Arch::legacy_uid_t\", arg3=\"typename Arch::legacy_uid_t\")\nvm86 = UnsupportedSyscall(x86=166)\nquery_module = UnsupportedSyscall(x86=167, x64=178)\n\n#  int poll(struct pollfd *fds, nfds_t nfds, int timeout)\n#  int ppoll(struct pollfd *fds, nfds_t nfds,\n#            const struct timespec *timeout_ts,\n#            const sigset_t *sigmask);\n#\n# poll() performs a similar task to select(2): it waits for one of a\n# set of file descriptors to become ready to perform I/O.\n#\n# The relationship between poll() and ppoll() is analogous to the\n# relationship between select(2) and pselect(2): like pselect(2),\n# ppoll() allows an application to safely wait until either a file\n# descriptor becomes ready or until a signal is caught.\n#\n# XXX is this irregular?  CHECKED: (trace->recorded_regs.eax > 0)\npoll = IrregularEmulatedSyscall(x86=168, x64=7)\n\nnfsservctl = UnsupportedSyscall(x86=169, x64=180, generic=42)\n\n#  int setresgid(gid_t rgid, gid_t egid, gid_t sgid);\n#\n# setresgid() sets the real GID, effective GID, and saved\n# set-group-ID of the calling process.\nsetresgid = EmulatedSyscall(x86=170, x64=119, generic=149)\n\ngetresgid = EmulatedSyscall(x86=171, x64=120, generic=150, arg1=\"typename Arch::legacy_gid_t\", arg2=\"typename Arch::legacy_gid_t\", arg3=\"typename Arch::legacy_gid_t\")\n\n#  int prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long\n#arg4, unsigned long arg5);\n#\n# prctl() is called with a first argument describing what to do (with\n# values defined in <linux/prctl.h>), and further arguments with a\n# significance depending on the first one.\n#\nprctl = IrregularEmulatedSyscall(x86=172, x64=157, generic=167)\n\nrt_sigreturn = IrregularEmulatedSyscall(x86=173, x64=15, generic=139)\nrt_sigaction = IrregularEmulatedSyscall(x86=174, x64=13, generic=134)\nrt_sigprocmask = IrregularEmulatedSyscall(x86=175, x64=14, generic=135)\n\n#  int sigpending(sigset_t *set);\n#\n# sigpending() returns the set of signals that are pending for\n# delivery to the calling thread (i.e., the signals which have been\n# raised while blocked).  The mask of pending signals is returned in\n# set.\nrt_sigpending = IrregularEmulatedSyscall(x86=176, x64=127, generic=136)\n\n#  int sigtimedwait(const sigset_t *set, siginfo_t *info,\n#                   const struct timespec *timeout);\n#\n# sigwaitinfo() suspends execution of the calling thread until one of\n# the signals in set is pending (If one of the signals in set is\n# already pending for the calling thread, sigwaitinfo() will return\n# immedi ately.)\n#\n# sigtimedwait() operates in exactly the same way as sigwaitinfo()\n# except that it has an additional argument, timeout, which specifies\n# a minimum interval for which the thread is suspended waiting for a\n# signal.\nrt_sigtimedwait = IrregularEmulatedSyscall(x86=177, x64=128, generic=137)\n\n#  int sigsuspend(const sigset_t *mask);\n#\n# sigsuspend() temporarily replaces the signal mask of the calling\n# process with the mask given by mask and then suspends the process\n# until delivery of a signal whose action is to invoke a signal\n# handler or to terminate a process.\nrt_sigsuspend = IrregularEmulatedSyscall(x86=179, x64=130, generic=133)\n\n#  ssize_t pread(int fd, void *buf, size_t count, off_t offset);\n#\n# pread, pwrite - read from or write to a file descriptor at a given\n# offset\npread64 = IrregularEmulatedSyscall(x86=180, x64=17, generic=67)\npwrite64 = EmulatedSyscall(x86=181, x64=18, generic=68)\n\nchown = EmulatedSyscall(x86=182, x64=92)\n\n#  char *getwd(char *buf);\n#\n# These functions return a null-terminated string containing an\n# absolute pathname that is the current working directory of the\n# calling process.  The pathname is returned as the function result\n# and via the argument buf, if present.\ngetcwd = IrregularEmulatedSyscall(x86=183, x64=79, generic=17)\n\ncapget = IrregularEmulatedSyscall(x86=184, x64=125, generic=90)\ncapset = EmulatedSyscall(x86=185, x64=126, generic=91)\n\n#  int sigaltstack(const stack_t *ss, stack_t *oss)\n#\n# sigaltstack() allows a process to define a new alternate signal\n# stack and/or retrieve the state of an existing alternate signal\n# stack.  An alternate signal stack is used during the execution of a\n# signal handler if the establishment of that handler (see\n# sigaction(2)) requested it.\nsigaltstack = EmulatedSyscall(x86=186, x64=131, generic=132, arg2=\"typename Arch::stack_t\")\n\nsendfile = IrregularEmulatedSyscall(x86=187, x64=40, generic=71)\ngetpmsg = InvalidSyscall(x86=188, x64=181)\nputpmsg = InvalidSyscall(x86=189, x64=182)\nvfork = IrregularEmulatedSyscall(x86=190, x64=58)\n\n#  int getrlimit(int resource, struct rlimit *rlim)\n#\n# getrlimit() and setrlimit() get and set resource limits\n# respectively.  Each resource has an associated soft and hard limit,\n# as defined by the rlimit structure (the rlim argument to both\n# getrlimit() and setrlimit()):\nugetrlimit = EmulatedSyscall(x86=191, arg2=\"typename Arch::rlimit\")\n\nmmap2 = IrregularEmulatedSyscall(x86=192)\n\ntruncate64 = EmulatedSyscall(x86=193)\nftruncate64 = EmulatedSyscall(x86=194)\n\n# int stat(const char *path, struct stat *buf);\n#\n# stat() stats the file pointed to by path and fills in buf.\nstat64 = EmulatedSyscall(x86=195, arg2=\"struct Arch::stat64_t\")\n\n#  int lstat(const char *path, struct stat *buf);\n#\n# lstat() is identical to stat(), except that if path is a symbolic\n# link, then the link itself is stat-ed, not the file that it refers\n# to.\nlstat64 = EmulatedSyscall(x86=196, arg2=\"struct Arch::stat64_t\")\n\n#  int fstat(int fd, struct stat *buf)\n#\n# fstat() is identical to stat(), except that the file to be stat-ed\n# is specified by the file descriptor fd.\nfstat64 = EmulatedSyscall(x86=197, arg2=\"struct Arch::stat64_t\")\n\nlchown32 = EmulatedSyscall(x86=198)\n\n#  uid_t getuid(void);\n#\n# getuid() returns the real user ID of the calling process\ngetuid32 = EmulatedSyscall(x86=199)\n\n#  gid_t getgid(void);\n#\n# getgid() returns the real group ID of the calling process.\ngetgid32 = EmulatedSyscall(x86=200)\n\n#  uid_t geteuid(void);\n#\n# geteuid() returns the effective user ID of the calling process.\ngeteuid32 = EmulatedSyscall(x86=201)\n\n#  gid_t getegid(void);\n#\n# getegid() returns the effective group ID of the calling process.\ngetegid32 = EmulatedSyscall(x86=202)\n\nsetreuid32 = EmulatedSyscall(x86=203)\n\n#  int setregid(gid_t rgid, gid_t egid)\n#\n# setreuid() sets real and effective user IDs of the calling process\nsetregid32 = EmulatedSyscall(x86=204)\n\n#  int getgroups(int size, gid_t list[]);\n#\n# getgroups() returns the supplementary group IDs of the calling\n# process in list.  The argument size should be set to the maximum\n# number of items that can be stored in the buffer pointed to by\n# list. If the calling process is a member of more than size\n# supplementary groups, then an error results.  It is unspecified\n# whether the effective group ID of the calling process is included\n# in the returned list. (Thus, an application should also call\n# getegid(2) and add or remove the resulting value.)\n#\n# If size is zero, list is not modified, but the total number of\n# supplementary group IDs for the process is returned.  This allows\n# the caller to determine the size of a dynamically allocated list to\n# be used in a further call to getgroups().\ngetgroups32 = IrregularEmulatedSyscall(x86=205)\n\nsetgroups32 = EmulatedSyscall(x86=206)\nfchown32 = EmulatedSyscall(x86=207)\n\n#  int setresuid32(uid_t ruid, uid_t euid, uid_t suid);\n#\n# setresuid() sets the real user ID, the effective user ID, and the\n# saved set-user-ID of the calling process.\nsetresuid32 = EmulatedSyscall(x86=208)\n\n#  int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)\n#\n# getresuid() returns the real UID, the effective UID, and the saved\n# set- user-ID of the calling process, in the arguments ruid, euid,\n# and suid, respectively.  getresgid() performs the analogous task\n# for the process's group IDs.\ngetresuid32 = EmulatedSyscall(x86=209, arg1=\"typename Arch::uid_t\", arg2=\"typename Arch::uid_t\", arg3=\"typename Arch::uid_t\")\n\n#  int setresgid32(gid_t rgid, gid_t egid, gid_t sgid);\n#\n# setresgid() sets the real GID, effective GID, and saved\n# set-group-ID of the calling process.\nsetresgid32 = EmulatedSyscall(x86=210)\n\n#  int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid);\n#\n# getresuid() returns the real UID, the effective UID, and the saved\n# set-user-ID of the calling process, in the arguments ruid, euid,\n# and suid, respectively.  getresgid() performs the analogous task\n# for the process's group IDs.  @return: On success, zero is\n# returned.  On error, -1 is returned, and errno is set\n# appropriately.\ngetresgid32 = EmulatedSyscall(x86=211, arg1=\"typename Arch::gid_t\", arg2=\"typename Arch::gid_t\", arg3=\"typename Arch::gid_t\")\n\nchown32 = EmulatedSyscall(x86=212)\nsetuid32 = EmulatedSyscall(x86=213)\nsetgid32 = EmulatedSyscall(x86=214)\nsetfsuid32 = EmulatedSyscall(x86=215)\nsetfsgid32 = EmulatedSyscall(x86=216)\npivot_root = EmulatedSyscall(x86=217, x64=155, generic=41)\nmincore = IrregularEmulatedSyscall(x86=218, x64=27, generic=232)\n\n#  int madvise(void *addr, size_t length, int advice);\n#\n# The madvise() system call advises the kernel about how to handle\n# paging input/output in the address range beginning at address addr\n# and with size length bytes.  It allows an application to tell the\n# kernel how it expects to use some mapped or shared memory areas, so\n# that the kernel can choose appropriate read-ahead and caching\n# techniques.\n# The man page says \"This call does not influence the semantics of the\n# application (except in the case of MADV_DONTNEED)\", but that is a lie.\nmadvise = IrregularEmulatedSyscall(x86=219, x64=28, generic=233)\n\ngetdents64 = IrregularEmulatedSyscall(x86=220, x64=217, generic=61)\n\n#  int fcntl(int fd, int cmd, ... ( arg ));\n#\n# fcntl() performs one of the operations described below on the open\n# file descriptor fd.  The operation is determined by cmd. fcntl()\n# can take an optional third argument.  Whether or not this argument\n# is required is determined by cmd. The required argument type is\n# indicated in parentheses after each cmd name (in most cases, the\n# required type is long, and we identify the argument using the name\n# arg), or void is specified if the argument is not required.\nfcntl64 = IrregularEmulatedSyscall(x86=221)\n\n#  pid_t gettid(void);\n#\n# gettid() returns the caller's thread ID (TID).\ngettid = EmulatedSyscall(x86=224, x64=186, generic=178)\n\n#  ssize_t readahead(int fd, off_t offset, size_t count);\n#\n# readahead() populates the page cache with data from a file so that\n# subsequent reads from that file will not block on disk I/O.  The fd\n# argument is a file descriptor identifying the file which is to be\n# read.  The offset argu- ment specifies the starting point from\n# which data is to be read and count specifies the number of bytes to\n# be read.  I/O is performed in whole pages, so that offset is\n# effectively rounded down to a page boundary and bytes are read up\n# to the next page boundary greater than or equal to (offset+count).\n# readahead() does not read beyond the end of the file.  readahead()\n# blocks until the specified data has been read.  The current file\n# offset of the open file referred to by fd is left unchanged.\nreadahead = EmulatedSyscall(x86=225, x64=187, generic=213)\n\nsetxattr = EmulatedSyscall(x86=226, x64=188, generic=5)\nlsetxattr = EmulatedSyscall(x86=227, x64=189, generic=6)\nfsetxattr = EmulatedSyscall(x86=228, x64=190, generic=7)\n\n#  ssize_t getxattr(const char *path, const char *name,\n#                   void *value, size_t size);\n#  ssize_t lgetxattr(const char *path, const char *name,\n#                    void *value, size_t size);\n#  ssize_t fgetxattr(int fd, const char *name,\n#                    void *value, size_t size);\n#\n# getxattr() retrieves the value of the extended attribute identified\n# by name and associated with the given path in the file system. The\n# length of the attribute value is returned.\ngetxattr = IrregularEmulatedSyscall(x86=229, x64=191, generic=8)\nlgetxattr = IrregularEmulatedSyscall(x86=230, x64=192, generic=9)\nfgetxattr = IrregularEmulatedSyscall(x86=231, x64=193, generic=10)\n\nlistxattr = IrregularEmulatedSyscall(x86=232, x64=194, generic=11)\nllistxattr = IrregularEmulatedSyscall(x86=233, x64=195, generic=12)\nflistxattr = IrregularEmulatedSyscall(x86=234, x64=196, generic=13)\nremovexattr = EmulatedSyscall(x86=235, x64=197, generic=14)\nlremovexattr = EmulatedSyscall(x86=236, x64=198, generic=15)\nfremovexattr = EmulatedSyscall(x86=237, x64=199, generic=16)\ntkill = EmulatedSyscall(x86=238, x64=200, generic=130)\n\n# ssize_t sendfile64 (int __out_fd, int __in_fd, __off_t *__offset, size_t\n#__count);\n#\n# Send up to COUNT bytes from file associated with IN_FD starting at\n# *OFFSET to descriptor OUT_FD.  Set *OFFSET to the IN_FD's file position\n# following the read bytes.  If OFFSET is a null pointer, use the normal\n# file position instead.  Return the number of written bytes, or -1 in\n# case of error.\nsendfile64 = IrregularEmulatedSyscall(x86=239)\n\n#  int futex(int *uaddr, int op, int val, const struct timespec *timeout, int\n#*uaddr2, int val3);\n#\n# The futex() system call provides a method for a program to wait for\n# a value at a given address to change, and a method to wake up\n# anyone waiting on a particular address (while the addresses for the\n# same memory in separate processes may not be equal, the kernel\n# maps them internally so the same memory mapped in different\n# locations will correspond for futex() calls).  This system call is\n# typically used to implement the contended case of a lock in shared\n# memory, as described in futex(7).\nfutex = IrregularEmulatedSyscall(x86=240, x64=202, generic=98)\n\n#  int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);\n#\n# sched_setaffinity() sets the CPU affinity mask of the process whose\n# ID is pid to the value specified by mask.  If pid is zero, then the\n# calling process is used.  The argument cpusetsize is the length\n# (in bytes) of the data pointed to by mask.  Normally this argument\n# would be specified as sizeof(cpu_set_t).\nsched_setaffinity = IrregularEmulatedSyscall(x86=241, x64=203, generic=122)\n\n#  int sched_getaffinity(pid_t pid, size_t cpusetsize, cpu_set_t *mask);\n#\n# sched_getaffinity() writes the affinity mask of the process whose\n# ID is pid into the cpu_set_t structure pointed to by mask.  The\n# cpusetsize argument specifies the size (in bytes) of mask.  If pid\n# is zero, then the mask of the calling process is returned.\nsched_getaffinity = IrregularEmulatedSyscall(x86=242, x64=204, generic=123)\n\n# int sched_setattr(pid_t pid, struct sched_attr *attr,\n#                   unsigned int flags);\n#\n# The sched_setattr() system call sets the scheduling policy and\n# associated attributes for the thread whose ID is specified in pid.\n# If pid equals zero, the scheduling policy and attributes of the\n# calling thread will be set.\n#\n# XXX Do we want to restrict somehow how this plays with rr's\n# scheduling?\nsched_setattr = EmulatedSyscall(x86=351, x64=314, generic=274)\n\n# int sched_getattr(pid_t pid, struct sched_attr *attr,\n#                   unsigned int size, unsigned int flags);\n#\n# The sched_getattr() system call fetches the scheduling policy and the\n# associated attributes for the thread whose ID is specified in pid.\n# If pid equals zero, the scheduling policy and attributes of the call‐\n# ing thread will be retrieved.\nsched_getattr = IrregularEmulatedSyscall(x86=352, x64=315, generic=275)\n\n#  int set_thread_area(struct user_desc *u_info)\n#\n# set_thread_area() sets an entry in the current thread's Thread Local\n# Storage (TLS) array.  The TLS array entry set by set_thread_area()\n# corresponds to the value of u_info->entry_number passed in by the\n# user.  If this value is in bounds, set_thread_area() copies the TLS\n# descriptor pointed to by u_info into the thread's TLS array.\n#\n# When  set_thread_area() is passed an entry_number of -1, it uses a free\n# TLS entry.  If set_thread_area() finds a free TLS entry, the  value  of\n# u_info->entry_number  is  set  upon  return  to  show  which  entry was\n# changed.\nset_thread_area = IrregularEmulatedSyscall(x86=243, x64=205)\n\nget_thread_area = IrregularEmulatedSyscall(x86=244, x64=211)\nio_setup = IrregularEmulatedSyscall(x86=245, x64=206, generic=0)\nio_destroy = UnsupportedSyscall(x86=246, x64=207, generic=1)\nio_getevents = UnsupportedSyscall(x86=247, x64=208, generic=4)\nio_submit = UnsupportedSyscall(x86=248, x64=209, generic=2)\nio_cancel = UnsupportedSyscall(x86=249, x64=210, generic=3)\n\n#  int posix_fadvise(int fd, off_t offset, off_t len, int advice);\n#\n# Programs can use posix_fadvise() to announce an intention to access\n# file data in a specific pattern in the future, thus allowing the\n# kernel to perform appropriate optimizations.\nfadvise64 = EmulatedSyscall(x86=250, x64=221, generic=223)\n\n#  void exit_group(int status)\n#\n# This system call is equivalent to exit(2) except that it terminates\n# not only the calling thread, but all threads in the calling\n# process's thread group.\nexit_group = IrregularEmulatedSyscall(x86=252, x64=231, generic=94)\n\nlookup_dcookie = UnsupportedSyscall(x86=253, x64=212)\n\n#  int epoll_create(int size);\n#\n# epoll_create() creates an epoll \"instance\", requesting the kernel\n# to allocate an event backing store dimensioned for size\n# descriptors.  The size is not the maximum size of the backing store\n# but just a hint to the kernel about how to dimension internal\n# structures.  When no longer required, the file descriptor returned\n# by epoll_create() should be closed by using close(2).\nepoll_create = EmulatedSyscall(x86=254, x64=213)\n\n#  int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)\n#\n# This system call performs control operations on the epoll instance\n# referred to by the file descriptor epfd.  It requests that the\n# operation op be performed for the target file descriptor, fd.\nepoll_ctl = EmulatedSyscall(x86=255, x64=233, generic=21)\n\n#  int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int\n#timeout);\n#\n# The epoll_wait() system call waits for events on the epoll instance\n# referred to by the file descriptor epfd.  The memory area pointed\n# to by events will contain the events that will be available for the\n# caller.  Up to maxevents are returned by epoll_wait().  The\n# maxevents argument must be greater than zero.\n#\n# XXX is this irregular?  CHECKED: (trace->recorded_regs.eax >= 0)\nepoll_wait = IrregularEmulatedSyscall(x86=256, x64=232)\n\nremap_file_pages = UnsupportedSyscall(x86=257, x64=216, generic=234)\n\n#  long set_tid_address(int *tidptr);\n#\n# The kernel keeps for each process two values called set_child_tid\n# and clear_child_tid that are NULL by default.\n#\n# If a process is started using clone(2) with the CLONE_CHILD_SETTID\n# flag, set_child_tid is set to child_tidptr, the fifth argument of\n# that system call.\n#\n# When set_child_tid is set, the very first thing the new process\n# does is writing its PID at this address.\nset_tid_address = EmulatedSyscall(x86=258, x64=218, generic=96)\n\ntimer_create = EmulatedSyscall(x86=259, x64=222, generic=107, arg3=\"typename Arch::__kernel_timer_t\")\ntimer_settime = EmulatedSyscall(x86=260, x64=223, generic=110, arg4=\"typename Arch::itimerspec\")\ntimer_gettime = EmulatedSyscall(x86=261, x64=224, generic=108, arg2=\"typename Arch::itimerspec\")\ntimer_getoverrun = EmulatedSyscall(x86=262, x64=225, generic=109)\ntimer_delete = EmulatedSyscall(x86=263, x64=226, generic=111)\nclock_settime = EmulatedSyscall(x86=264, x64=227, generic=112, arg2=\"typename Arch::timespec\")\n\n#  int clock_gettime(clockid_t clk_id, struct timespec *tp);\n#\n# The functions clock_gettime() and clock_settime() retrieve and set\n# the time of the specified clock clk_id.\nclock_gettime = EmulatedSyscall(x86=265, x64=228, generic=113, arg2=\"typename Arch::timespec\")\n\n#  int clock_getres(clockid_t clk_id, struct timespec *res)\n#\n# The function clock_getres() finds the resolution (precision) of the\n# specified clock clk_id, and, if res is non-NULL, stores it in the\n# struct timespec pointed to by res.  The resolution of clocks\n# depends on the implementation and cannot be configured by a\n# particular process.  If the time value pointed to by the argument\n# tp of clock_settime() is not a multiple of res, then it is\n# truncated to a multiple of res.\nclock_getres = EmulatedSyscall(x86=266, x64=229, generic=114, arg2=\"typename Arch::timespec\")\n\nclock_nanosleep = IrregularEmulatedSyscall(x86=267, x64=230, generic=115)\n\n#  int statfs(const char *path, struct statfs *buf)\n#\n# The function statfs() returns information about a mounted file\n# system.  path is the pathname of any file within the mounted file\n# system.  buf is a pointer to a statfs structure defined\n# approximately as follows...\n#\n# FIXME: we use arg3() here, although according to man pages this system\n# call has only 2 parameters. However, strace tells another story...\nstatfs64 = EmulatedSyscall(x86=268, arg3=\"struct Arch::statfs64_t\")\nfstatfs64 = EmulatedSyscall(x86=269, arg3=\"struct Arch::statfs64_t\")\n\n#  int tgkill(int tgid, int tid, int sig)\n#\n# tgkill() sends the signal sig to the thread with the thread ID tid\n# in the thread group tgid.  (By contrast, kill(2) can only be used\n# to send a signal to a process (i.e., thread group) as a whole, and\n# the signal will be delivered to an arbitrary thread within that\n# process.)\ntgkill = EmulatedSyscall(x86=270, x64=234, generic=131)\n\n#  int utimes(const char *filename, const struct timeval times[2])\n#\n# The utime() system call changes the access and modification times\n# of the inode specified by filename to the actime and modtime fields\n# of times respectively.\n#\nutimes = EmulatedSyscall(x86=271, x64=235)\n\nfadvise64_64 = EmulatedSyscall(x86=272)\n\nvserver = InvalidSyscall(x86=273, x64=236)\nmbind = EmulatedSyscall(x86=274, x64=237, generic=235)\nget_mempolicy = IrregularEmulatedSyscall(x86=275, x64=239, generic=236)\nset_mempolicy = EmulatedSyscall(x86=276, x64=238, generic=237)\n\nmq_open = EmulatedSyscall(x86=277, x64=240, generic=180)\nmq_unlink = EmulatedSyscall(x86=278, x64=241, generic=181)\nmq_timedsend = EmulatedSyscall(x86=279, x64=242, generic=182)\nmq_timedreceive = IrregularEmulatedSyscall(x86=280, x64=243, generic=183)\nmq_notify = EmulatedSyscall(x86=281, x64=244, generic=184)\nmq_getsetattr = EmulatedSyscall(x86=282, x64=245, generic=185, arg3=\"struct Arch::mq_attr\")\n\nkexec_load = UnsupportedSyscall(x86=283, x64=246, generic=104)\n\n#  int waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);\n#\n# If WNOHANG was specified in options and there were no children in a\n# waitable state, then waitid() returns 0 immediately and the state\n# of the siginfo_t structure pointed to by infop is unspecified.  To\n# distinguish this case from that where a child was in a waitable\n# state, zero out the si_pid field before the call and check for a\n# nonzero value in this field after the call returns.\nwaitid = IrregularEmulatedSyscall(x86=284, x64=247, generic=95)\n\nadd_key = EmulatedSyscall(x86=286, x64=248, generic=217)\nrequest_key = UnsupportedSyscall(x86=287, x64=249, generic=218)\nkeyctl = IrregularEmulatedSyscall(x86=288, x64=250, generic=219)\nioprio_set = EmulatedSyscall(x86=289, x64=251, generic=30)\nioprio_get = EmulatedSyscall(x86=290, x64=252, generic=31)\n\n#  int inotify_init(void)\n#\n# inotify_init() initializes a new inotify instance and returns a\n# file descriptor associated with a new inotify event queue.\ninotify_init = EmulatedSyscall(x86=291, x64=253)\n\n#  int inotify_add_watch(int fd, const char *pathname, uint32_t mask)\n#\n# inotify_add_watch() adds a new watch, or modifies an existing\n# watch, for the file whose location is specified in pathname; the\n# caller must have read permission for this file.  The fd argument is\n# a file descrip tor referring to the inotify instance whose watch\n# list is to be modified.  The events to be monitored for pathname\n# are specified in the mask bit-mask argument.  See inotify(7) for a\n# description of the bits that can be set in mask.\ninotify_add_watch = EmulatedSyscall(x86=292, x64=254, generic=27)\n\n#  int inotify_rm_watch(int fd, uint32_t wd)\n#\n# inotify_rm_watch() removes the watch associated with the watch\n# descriptor wd from the inotify instance associated with the file\n# descriptor fd.\ninotify_rm_watch = EmulatedSyscall(x86=293, x64=255, generic=28)\n\nmigrate_pages = UnsupportedSyscall(x86=294, x64=256, generic=238)\n\n#  int openat(int dirfd, const char *pathname, int flags);\n#  int openat(int dirfd, const char *pathname, int flags, mode_t mode);\n#\n# The openat() system call operates in exactly the same way as\n# open(2), except for the differences described in this manual page.\nopenat = IrregularEmulatedSyscall(x86=295, x64=257, generic=56)\n\n#  int mkdirat(int dirfd, const char *pathname, mode_t mode);\n#\n# The mkdirat() system call operates in exactly the same way as\n# mkdir(2), except for the differences described in this manual\n# page....\nmkdirat = EmulatedSyscall(x86=296, x64=258, generic=34)\n\nmknodat = EmulatedSyscall(x86=297, x64=259, generic=33)\nfchownat = EmulatedSyscall(x86=298, x64=260, generic=54)\nfutimesat = UnsupportedSyscall(x86=299, x64=261)\n\n#  int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags);\n#\n# The fstatat() system call operates in exactly the same way as\n# stat(2), except for the differences described in this manual\n# page....\nfstatat = EmulatedSyscall(x64=262, generic=79, arg3=\"struct Arch::stat_t\")\nfstatat64 = EmulatedSyscall(x86=300, arg3=\"struct Arch::stat64_t\")\n\n#  int unlinkat(int dirfd, const char *pathname, int flags)\n#\n# The unlinkat() system call operates in exactly the same way as\n# either unlink(2) or rmdir(2) (depending on whether or not flags\n# includes the AT_REMOVEDIR flag) except for the differences\n# described in this manual page.\nunlinkat = EmulatedSyscall(x86=301, x64=263, generic=35)\n\nrenameat = EmulatedSyscall(x86=302, x64=264, generic=38)\nlinkat = EmulatedSyscall(x86=303, x64=265, generic=37)\nsymlinkat = EmulatedSyscall(x86=304, x64=266, generic=36)\nreadlinkat = IrregularEmulatedSyscall(x86=305, x64=267, generic=78)\nfchmodat = EmulatedSyscall(x86=306, x64=268, generic=53)\n\n#  int faccessat(int dirfd, const char *pathname, int mode, int flags)\n#\n# The faccessat() system call operates in exactly the same way as\n# access(2), except for the differences described in this manual\n# page....\nfaccessat = EmulatedSyscall(x86=307, x64=269, generic=48)\n\n#  int faccessat2(int dirfd, const char *pathname, int mode, int flags)\n#\n# The faccessat2() system call operates in exactly the same way as\n# access(2), except for the differences described in this manual\n# page...\nfaccessat2 = EmulatedSyscall(x86=439, x64=439, generic=439)\n\npselect6 = IrregularEmulatedSyscall(x86=308, x64=270, generic=72)\n\nppoll = IrregularEmulatedSyscall(x86=309, x64=271, generic=73)\n\nunshare = EmulatedSyscall(x86=310, x64=272, generic=97)\n\n#  long set_robust_list(struct robust_list_head *head, size_t len)\n#\n# The robust futex implementation needs to maintain per-thread lists\n# of robust futexes which are unlocked when the thread exits. These\n# lists are managed in user space, the kernel is only notified about\n# the location of the head of the list.\n#\n# set_robust_list sets the head of the list of robust futexes owned\n# by the current thread to head.  len is the size of *head.\nset_robust_list = EmulatedSyscall(x86=311, x64=273, generic=99)\n\nget_robust_list = EmulatedSyscall(x86=312, x64=274, generic=100, arg2=\"typename Arch::unsigned_word\", arg3=\"typename Arch::size_t\")\n\n#  ssize_t splice(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out,\n#size_t len, unsigned int flags);\n#\n# splice() moves data between two file descriptors without copying\n# between kernel address space and user address space.  It transfers\n# up to len bytes of data from the file descriptor fd_in to the file\n# descriptor fd_out, where one of the descriptors must refer to a\n# pipe.\n#\n# NB: the documentation doesn't mention it explicitly, but the |off|\n# params are actually inout params, and are updated with the new file\n# offset on return.\n#\n# NOTE: Technically, the following implementation is unsound for\n# programs that splice with stdin/stdout/stderr and have output\n# redirected during replay.  But, *crickets*.\nsplice = IrregularEmulatedSyscall(x86=313, x64=275, generic=76)\n\nsync_file_range = IrregularEmulatedSyscall(x86=314, x64=277, generic=84)\ntee = UnsupportedSyscall(x86=315, x64=276, generic=77)\nvmsplice = UnsupportedSyscall(x86=316, x64=278, generic=75)\nmove_pages = UnsupportedSyscall(x86=317, x64=279, generic=239)\ngetcpu = EmulatedSyscall(x86=318, x64=309, generic=168, arg1=\"unsigned int\", arg2=\"unsigned int\")\nepoll_pwait = IrregularEmulatedSyscall(x86=319, x64=281, generic=22)\n\n#  int utimensat(int dirfd, const char *pathname, const struct timespec\n#times[2], int flags);\n#\n# utimensat() and futimens() update the timestamps of a file with\n# nanosecond precision.  This contrasts with the historical utime(2)\n# and utimes(2), which permit only second and microsecond precision,\n# respectively, when setting file timestamps.\nutimensat = EmulatedSyscall(x86=320, x64=280, generic=88)\n\n#  int signalfd(int fd, const sigset_t *mask, int flags);\n# There are two underlying Linux system calls: signalfd() and the more\n# recent signalfd4(). The former system call does not implement a flags\n# argument. The latter system call implements the flags values described\n# above. Starting with glibc 2.9, the signalfd() wrapper function will\n# use signalfd4() where it is available.\nsignalfd = EmulatedSyscall(x86=321, x64=282)\n\n#  int timerfd_create(int clockid, int flags);\n#\n# timerfd_create() creates a new timer object, and returns a file\n# descriptor that refers to that timer.\ntimerfd_create = EmulatedSyscall(x86=322, x64=283, generic=85)\n\neventfd = EmulatedSyscall(x86=323, x64=284)\n\n# int fallocate(int fd, int mode, off_t offset, off_t len);\n#\n# fallocate() allows the caller to directly manipulate the allocated\n# disk space for the file referred to by fd for the byte range\n# starting at offset and continuing for len bytes\nfallocate = EmulatedSyscall(x86=324, x64=285, generic=47)\n\n#  int timerfd_settime(int fd, int flags,\n#                      const struct itimerspec *new_value,\n#                      struct itimerspec *old_value);\n#\n# timerfd_settime() arms (starts) or disarms (stops) the timer\n# referred to by the file descriptor fd.\ntimerfd_settime = EmulatedSyscall(x86=325, x64=286, generic=86, arg4=\"typename Arch::itimerspec\")\n\n#  int timerfd_gettime(int fd, struct itimerspec *curr_value);\n#\n# timerfd_gettime() returns, in curr_value, an itimerspec structure\n# that contains the current setting of the timer referred to by the\n# file descriptor fd.\ntimerfd_gettime = EmulatedSyscall(x86=326, x64=287, generic=87, arg2=\"typename Arch::itimerspec\")\n\n#  int signalfd(int fd, const sigset_t *mask, int flags);\n# There are two underlying Linux system calls: signalfd() and the more\n# recent signalfd4(). The former system call does not implement a flags\n# argument. The latter system call implements the flags values described\n# above. Starting with glibc 2.9, the signalfd() wrapper function will\n# use signalfd4() where it is available.\nsignalfd4 = EmulatedSyscall(x86=327, x64=289, generic=74)\n\n#  int eventfd(unsigned int initval, int flags);\n#\n# eventfd() creates an \"eventfd object\" that can be used as an event\n# wait/notify mechanism by userspace applications, and by the kernel\n# to notify userspace applications of events.  The object contains an\n# unsigned 64-bit integer (uint64_t) counter that is maintained by\n# the kernel.  This counter is initialized with the value specified\n# in the argument initval.\neventfd2 = EmulatedSyscall(x86=328, x64=290, generic=19)\n\n#  int epoll_create1(int flags);\n#\n# epoll_create1() is very similar to epoll_create.  They are identical\n# if the passed flag value is 0, they are completely identical.  The\n# flag argument can be used to set the close-on-exec flag on the new\n# file descriptor.\nepoll_create1 = EmulatedSyscall(x86=329, x64=291, generic=20)\n\ndup3 = IrregularEmulatedSyscall(x86=330, x64=292, generic=24)\n\n#  int pipe2(int pipefd[2], int flags)\n#\n# If flags is 0, then pipe2() is the same as pipe().  The following\n# values can be bitwise ORed in flags to obtain different behavior...\npipe2 = EmulatedSyscall(x86=331, x64=293, generic=59, arg1=\"int[2]\")\n\ninotify_init1 = EmulatedSyscall(x86=332, x64=294, generic=26)\n\npreadv = IrregularEmulatedSyscall(x86=333, x64=295, generic=69)\npwritev = EmulatedSyscall(x86=334, x64=296, generic=70)\n\n#  int rt_sigqueueinfo(pid_t tgid, int sig, siginfo_t *uinfo);\n#  int rt_tgsigqueueinfo(pid_t tgid, pid_t tid, int sig,\n#                        siginfo_t *uinfo);\n#\n# The rt_sigqueueinfo() and rt_tgsigqueueinfo() system calls are the\n# low-level interfaces used to send a signal plus data to a process\n# or thread.  The receiver of the signal can obtain the accompanying\n# data by establishing a signal handler with the sigaction(2)\n# SA_SIGINFO flag.\nrt_sigqueueinfo = EmulatedSyscall(x86=178, x64=129, generic=138)\nrt_tgsigqueueinfo = EmulatedSyscall(x86=335, x64=297, generic=240)\n\n#  int perf_event_open(struct perf_event_attr *attr,\n#                      pid_t pid, int cpu, int group_fd,\n#                      unsigned long flags);\n#\n# Given a list of parameters, perf_event_open() returns a file\n# descriptor, for use in subsequent system calls (read(2), mmap(2),\n# prctl(2), fcntl(2), etc.).\nperf_event_open = IrregularEmulatedSyscall(x86=336, x64=298, generic=241)\n\n#  int recvmmsg(int sockfd, struct mmsghdr *msgvec,\n#               unsigned int vlen, unsigned int flags,\n#               struct timespec *timeout);\n#\n# The recvmmsg() system call is an extension of recvmsg(2) that\n# allows the caller to receive multiple messages from a socket using\n# a single system call.  (This has performance benefits for some\n# applications.)  A further extension over recvmsg(2) is support for\n# a timeout on the receive operation.\nrecvmmsg = IrregularEmulatedSyscall(x86=337, x64=299, generic=243)\n\nfanotify_init = EmulatedSyscall(x86=338, x64=300, generic=262)\nfanotify_mark = EmulatedSyscall(x86=339, x64=301, generic=263)\n\n#  int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct\n#rlimit *old_limit);\n#\n# The Linux-specific prlimit() system call combines and extends the\n# functionality of setrlimit() and getrlimit().  It can be used to\n# both set and get the resource limits of an arbitrary process.\n#\n# NOTE: We should execute this system call, since this system call\n# can set a limit on the stack size that will trigger a synchronous SIGSEGV,\n# and we expect synchronous SIGSEGVs to be triggered by the kernel\n# during replay.\nprlimit64 = EmulatedSyscall(x86=340, x64=302, generic=261, arg4=\"typename Arch::rlimit64\")\n\nname_to_handle_at = IrregularEmulatedSyscall(x86=341, x64=303, generic=264)\nopen_by_handle_at = EmulatedSyscall(x86=342, x64=304, generic=265)\nclock_adjtime = EmulatedSyscall(x86=343, x64=305, generic=266, arg2=\"typename Arch::timex\")\nsyncfs = IrregularEmulatedSyscall(x86=344, x64=306, generic=267)\n\n#  int sendmmsg(int sockfd, struct mmsghdr *msgvec, unsigned int vlen,\n#               unsigned int flags);\n#\n# The sendmmsg() system call is an extension of sendmsg(2) that\n# allows the caller to transmit multiple messages on a socket using a\n# single system call.  (This has performance benefits for some\n# applications.)\nsendmmsg = IrregularEmulatedSyscall(x86=345, x64=307, generic=269)\n\nsetns = EmulatedSyscall(x86=346, x64=308, generic=268)\nprocess_vm_readv = IrregularEmulatedSyscall(x86=347, x64=310, generic=270)\nprocess_vm_writev = IrregularEmulatedSyscall(x86=348, x64=311, generic=271)\nkcmp = EmulatedSyscall(x86=349, x64=312, generic=272)\nfinit_module = UnsupportedSyscall(x86=350, x64=313, generic=273)\nrenameat2 = EmulatedSyscall(x86=353, x64=316, generic=276)\nseccomp = IrregularEmulatedSyscall(x86=354, x64=317, generic=277)\ngetrandom = IrregularEmulatedSyscall(x86=355, x64=318, generic=278)\nmemfd_create = IrregularEmulatedSyscall(x86=356, x64=319, generic=279)\narch_prctl = IrregularEmulatedSyscall(x86=384, x64=158)\n\nbpf = IrregularEmulatedSyscall(x86=357, x64=321, generic=280)\nexecveat = IrregularEmulatedSyscall(x86=358, x64=322, generic=281)\nuserfaultfd = IrregularEmulatedSyscall(x86=374, x64=323, generic=282)\nmembarrier = EmulatedSyscall(x86=375, x64=324, generic=283)\nmlock2 = UnsupportedSyscall(x86=376, x64=325, generic=284)\ncopy_file_range = IrregularEmulatedSyscall(x86=377, x64=326, generic=285)\npreadv2 = UnsupportedSyscall(x86=378, x64=327, generic=286)\npwritev2 = UnsupportedSyscall(x86=379, x64=328, generic=287)\npkey_mprotect = IrregularEmulatedSyscall(x86=380, x64=329, generic=288)\npkey_alloc = EmulatedSyscall(x86=381, x64=330, generic=289)\npkey_free = EmulatedSyscall(x86=382, x64=331, generic=290)\nstatx = EmulatedSyscall(x86=383, x64=332, generic=291, arg5=\"typename Arch::statx_struct\")\nio_pgetevents = UnsupportedSyscall(x86=385, x64=333, generic=292)\nrseq = IrregularEmulatedSyscall(x86=386, x64=334, generic=293)\n\nclock_gettime64 = EmulatedSyscall(x86=403, arg2=\"typename Arch::Arch64::timespec\")\nclock_settime64 = EmulatedSyscall(x86=404, arg2=\"typename Arch::Arch64::timespec\")\nclock_adjtime64 = EmulatedSyscall(x86=405, arg2=\"typename Arch::Arch64::timex\")\nclock_getres_time64 = EmulatedSyscall(x86=406, arg2=\"typename Arch::Arch64::timespec\")\nclock_nanosleep_time64 = IrregularEmulatedSyscall(x86=407)\ntimer_gettime64 = EmulatedSyscall(x86=408, arg2=\"typename Arch::Arch64::itimerspec\")\ntimer_settime64 = EmulatedSyscall(x86=409, arg4=\"typename Arch::Arch64::itimerspec\")\ntimerfd_gettime64 = EmulatedSyscall(x86=410, arg2=\"typename Arch::Arch64::itimerspec\")\ntimerfd_settime64 = EmulatedSyscall(x86=411, arg4=\"typename Arch::Arch64::itimerspec\")\nutimensat_time64 = EmulatedSyscall(x86=412)\npselect6_time64 = IrregularEmulatedSyscall(x86=413)\nppoll_time64 = IrregularEmulatedSyscall(x86=414)\nio_pgetevents_time64 = UnsupportedSyscall(x86=416)\nrecvmmsg_time64 = IrregularEmulatedSyscall(x86=417)\nmq_timedsend_time64 = EmulatedSyscall(x86=418)\nmq_timedreceive_time64 = IrregularEmulatedSyscall(x86=419)\nsemtimedop_time64 = IrregularEmulatedSyscall(x86=420)\nrt_sigtimedwait_time64 = IrregularEmulatedSyscall(x86=421)\nfutex_time64 = IrregularEmulatedSyscall(x86=422)\nsched_rr_get_interval_time64 = UnsupportedSyscall(x86=423)\n\n# x86-64 decided to skip ahead here to catchup\npidfd_send_signal = EmulatedSyscall(all=424)\nio_uring_setup = IrregularEmulatedSyscall(all=425)\nio_uring_enter = UnsupportedSyscall(all=426)\nio_uring_register = UnsupportedSyscall(all=427)\nopen_tree = EmulatedSyscall(all=428)\nmove_mount = EmulatedSyscall(all=429)\nfsopen = EmulatedSyscall(all=430)\nfsconfig = EmulatedSyscall(all=431)\nfsmount = EmulatedSyscall(all=432)\nfspick = UnsupportedSyscall(all=433)\npidfd_open = EmulatedSyscall(all=434)\nclone3 = IrregularEmulatedSyscall(all=435)\nopenat2 = IrregularEmulatedSyscall(all=437)\npidfd_getfd = EmulatedSyscall(all=438)\nprocess_madvise = UnsupportedSyscall(all=440)\nepoll_pwait2 = IrregularEmulatedSyscall(all=441)\nmount_setattr = EmulatedSyscall(all=442)\nquotactl_fd = UnsupportedSyscall(all=443)\nlandlock_create_ruleset = EmulatedSyscall(all=444)\nlandlock_add_rule = EmulatedSyscall(all=445)\nlandlock_restrict_self = EmulatedSyscall(all=446)\nmemfd_secret = UnsupportedSyscall(all=447)\nprocess_mrelease = UnsupportedSyscall(all=448)\nfutex_waitv = UnsupportedSyscall(all=449)\nset_mempolicy_home_node = UnsupportedSyscall(all=450)\ncachestat = UnsupportedSyscall(all=451)\nfchmodat2 = EmulatedSyscall(all=452)\nmap_shadow_stack = UnsupportedSyscall(all=453)\nfutex_wake = UnsupportedSyscall(all=454)\nfutex_wait = UnsupportedSyscall(all=455)\nfutex_requeue = UnsupportedSyscall(all=456)\nstatmount = UnsupportedSyscall(all=457)\nlistmount = UnsupportedSyscall(all=458)\nlsm_get_self_attr = UnsupportedSyscall(all=459)\nlsm_set_self_attr = UnsupportedSyscall(all=460)\nlsm_list_modules = UnsupportedSyscall(all=461)\nmseal = UnsupportedSyscall(all=462)\nsetxattrat = UnsupportedSyscall(all=463)\ngetxattrat = UnsupportedSyscall(all=464)\nlistxattrat = UnsupportedSyscall(all=465)\nremovexattrat = UnsupportedSyscall(all=466)\n\n# restart_syscall is a little special.\nrestart_syscall = RestartSyscall(x86=0, x64=219, generic=128)\n\n# Internal rr syscall numbers.\n# These syscall numbers must be the same across all architectures.\nrrcall_init_preload = IrregularEmulatedSyscall(all=1000)\nrrcall_init_buffers = IrregularEmulatedSyscall(all=1001)\nrrcall_notify_syscall_hook_exit = IrregularEmulatedSyscall(all=1002)\nrrcall_notify_control_msg = IrregularEmulatedSyscall(all=1003)\nrrcall_reload_auxv = IrregularEmulatedSyscall(all=1004)\nrrcall_mprotect_record = IrregularEmulatedSyscall(all=1005)\nrrcall_notify_stap_semaphore_added = IrregularEmulatedSyscall(all=1006)\nrrcall_notify_stap_semaphore_removed = IrregularEmulatedSyscall(all=1007)\nrrcall_check_presence = IrregularEmulatedSyscall(all=1008)\nrrcall_detach_teleport = IrregularEmulatedSyscall(all=1009)\nrrcall_arm_time_slice = IrregularEmulatedSyscall(all=1010)\nrrcall_freeze_tid = IrregularEmulatedSyscall(all=1011)\nrrcall_rdtsc = IrregularEmulatedSyscall(all=1012)\n\n# These syscalls also appear under `socketcall` on x86.\nsocket = EmulatedSyscall(x86=359, x64=41, generic=198)\nconnect = IrregularEmulatedSyscall(x86=362, x64=42, generic=203)\naccept = IrregularEmulatedSyscall(x64=43, generic=202)\nsendto = IrregularEmulatedSyscall(x86=369, x64=44, generic=206)\nrecvfrom = IrregularEmulatedSyscall(x86=371, x64=45, generic=207)\nsendmsg = IrregularEmulatedSyscall(x86=370, x64=46, generic=211)\nrecvmsg = IrregularEmulatedSyscall(x86=372, x64=47, generic=212)\nshutdown = EmulatedSyscall(x86=373, x64=48, generic=210)\nbind = EmulatedSyscall(x86=361, x64=49, generic=200)\nlisten = EmulatedSyscall(x86=363, x64=50, generic=201)\ngetsockname = IrregularEmulatedSyscall(x86=367, x64=51, generic=204)\ngetpeername = IrregularEmulatedSyscall(x86=368, x64=52, generic=205)\nsocketpair = EmulatedSyscall(x86=360, x64=53, generic=199, arg4=\"int[2]\")\nsetsockopt = IrregularEmulatedSyscall(x86=366, x64=54, generic=208)\ngetsockopt = IrregularEmulatedSyscall(x86=365, x64=55, generic=209)\naccept4 = IrregularEmulatedSyscall(x86=364, x64=288, generic=242)\n\n# These syscalls also appear under `ipc` on x86.\nshmget = EmulatedSyscall(x64=29, x86=395, generic=194)\nshmat = IrregularEmulatedSyscall(x64=30, x86=397, generic=196)\nshmctl = IrregularEmulatedSyscall(x64=31, x86=396, generic=195)\nsemget = EmulatedSyscall(x64=64, x86=393, generic=190)\nsemop = IrregularEmulatedSyscall(x64=65, generic=193)\nsemctl = IrregularEmulatedSyscall(x64=66, x86=394, generic=191)\nshmdt = IrregularEmulatedSyscall(x64=67, x86=398, generic=197)\nmsgget = EmulatedSyscall(x64=68, x86=399, generic=186)\nmsgsnd = IrregularEmulatedSyscall(x64=69, x86=400, generic=189)\nmsgrcv = IrregularEmulatedSyscall(x64=70, x86=401, generic=188)\nmsgctl = IrregularEmulatedSyscall(x64=71, x86=402, generic=187)\nsemtimedop = IrregularEmulatedSyscall(x64=220, generic=192)\n\n# These syscalls simply don't exist on x86.\ntuxcall = InvalidSyscall(x64=184)\nsecurity = InvalidSyscall(x64=185)\nepoll_ctl_old = UnsupportedSyscall(x64=214)\nepoll_wait_old = UnsupportedSyscall(x64=215)\n\ndef _syscalls():\n    for name, obj in globals().items():\n        if isinstance(obj, BaseSyscall):\n            yield name, obj\n\ndef all():\n    return list(_syscalls())\n\ndef for_arch(arch):\n    for name, obj in all():\n        if getattr(obj, arch) is not None:\n            yield name, obj\n"
  },
  {
    "path": "src/test/64bit_child.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid callback(uint64_t env, char *name, __attribute__((unused)) map_properties_t* props) {\n  const char search[] = \"librrpreload.so\";\n  if (strlen(name) > strlen(search)) {\n    if (sizeof(void*) == 4 &&\n        strcmp(name + strlen(name) - strlen(search), search) == 0)\n    {\n      int* rr_is_32bit = (int*)(uintptr_t)env;\n      *rr_is_32bit = 1;\n    }\n  }\n}\n\nstatic void skip_if_rr_32_bit_under_kernel_64_bit(void) {\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  int rr_is_32bit = 0;\n  iterate_maps((uintptr_t)&rr_is_32bit, callback, maps_file);\n\n  struct utsname buf;\n  if (uname(&buf) != 0)\n    return;\n\n  if (rr_is_32bit && // we are inside a 32bit rr process\n      strcmp(buf.machine, \"x86_64\") == 0) // running at a 64bit kernel\n  {\n    atomic_puts(\"NOTE: Skipping 32-bit test because of 32-bit rr with 64-bit kernel.\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n  }\n}\n\nint main(void) {\n\n  skip_if_rr_32_bit_under_kernel_64_bit();\n\n  /* Fork-and-exec 'echo'.\n     The exec may fail if 'bash' is 64-bit and rr doesn't support\n     64-bit processes. That's fine; the test should still pass. We're\n     testing that rr doesn't abort.\n   */\n  FILE* f = popen(\"echo -n\", \"r\");\n  while (1) {\n    int ch = fgetc(f);\n    if (ch < 0) {\n      break;\n    }\n    putchar(ch);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/_llseek.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(__attribute__((unused)) int argc, char* argv[]) {\n  int fd = open(argv[0], O_RDONLY);\n#ifdef SYS__llseek\n  loff_t result = -1234;\n#endif\n  test_assert(fd >= 0);\n#ifdef SYS__llseek\n  test_assert(syscall(SYS__llseek, fd, 0L, 0, &result, SEEK_SET) == 0);\n  test_assert(result == 0);\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/abort.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(0, SIGABRT);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/abort_nonmain.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* kill_thread(__attribute__((unused)) void* dontcare) {\n  atomic_puts(\"killing ...\");\n  abort();\n  atomic_puts(\"FAILED: abort() didn't work\");\n  return NULL; /* not reached */\n}\n\nint main(void) {\n  pthread_t t;\n\n  pthread_create(&t, NULL, kill_thread, NULL);\n  pthread_join(t, NULL);\n  atomic_puts(\"FAILED: joined thread that should have died\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/abort_nonmain.run",
    "content": "source `dirname $0`/util.sh\ncompare_test 'killing...'\n"
  },
  {
    "path": "src/test/accept.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void client(const struct sockaddr_un* addr) {\n  int clientfd;\n  struct sockaddr_un a;\n  socklen_t len = sizeof(a);\n  char c;\n\n  clientfd = socket(AF_UNIX, SOCK_STREAM, 0);\n  test_assert(clientfd >= 0);\n  test_assert(0 == connect(clientfd, (struct sockaddr*)addr, sizeof(*addr)));\n\n  memset(&a, 0, sizeof(a));\n  test_assert(1 == recvfrom(clientfd, &c, 1, 0, (struct sockaddr*)&a, &len));\n  atomic_printf(\"recvfrom() -> %c from (%d,%s) len %d\\n\", c, a.sun_family,\n                a.sun_path, len);\n  test_assert(c == '!');\n  test_assert(len > 0);\n  test_assert(addr->sun_family == a.sun_family);\n  test_assert(!strcmp(addr->sun_path, a.sun_path));\n\n  exit(0);\n}\n\nstatic void server(int use_accept4, int pass_addr) {\n  struct sockaddr_un addr;\n  int listenfd;\n  pid_t child;\n  int servefd;\n  struct sockaddr_un peer_addr;\n  socklen_t len = sizeof(peer_addr);\n  int status;\n  struct sockaddr* peer_addr_ptr =\n      pass_addr ? (struct sockaddr*)&peer_addr : NULL;\n  socklen_t* len_ptr = pass_addr ? &len : NULL;\n\n  memset(&addr, 0, sizeof(addr));\n  addr.sun_family = AF_UNIX;\n  strncpy(addr.sun_path, \"socket.unix\", sizeof(addr.sun_path) - 1);\n\n  test_assert(0 <= (listenfd = socket(AF_UNIX, SOCK_STREAM, 0)));\n  test_assert(0 == bind(listenfd, (struct sockaddr*)&addr, sizeof(addr)));\n  test_assert(0 == listen(listenfd, 1));\n\n  if (0 == (child = fork())) {\n    client(&addr);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  if (use_accept4) {\n    test_assert(0 <= (servefd = accept4(listenfd, peer_addr_ptr, len_ptr, 0)));\n  } else {\n    test_assert(0 <= (servefd = accept(listenfd, peer_addr_ptr, len_ptr)));\n  }\n  if (pass_addr) {\n    test_assert(AF_UNIX == peer_addr.sun_family);\n  }\n\n  test_assert(1 == send(servefd, \"!\", 1, 0));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  unlink(addr.sun_path);\n  close(servefd);\n  close(listenfd);\n}\n\nint main(void) {\n  int use_accept4, pass_addr;\n  for (use_accept4 = 0; use_accept4 <= 1; ++use_accept4) {\n    for (pass_addr = 0; pass_addr <= 1; ++pass_addr) {\n      server(use_accept4, pass_addr);\n    }\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/acct.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = acct(\"this_file_does_not_exist.1903901\");\n  test_assert(ret < 0 && (errno == EPERM || errno == ENOENT));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/adjtimex.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <sys/timex.h>\n#include <time.h>\n\nint main(void) {\n  struct timex tx;\n  memset(&tx, 0, sizeof(tx));\n  test_assert(-1 != adjtimex(&tx));\n\n  struct timespec ts;\n  memset(&ts, 0, sizeof(ts));\n\n  test_assert(0 == clock_gettime(CLOCK_REALTIME, &ts));\n\n  // Verify that adjtimex() and clock_gettime() return roughly the same time.\n  test_assert(labs(tx.time.tv_sec - ts.tv_sec) <= 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/aio.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  aio_context_t ctx;\n  int ret = syscall(__NR_io_setup, 1, &ctx);\n  test_assert(ret < 0 && errno == ENOSYS);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/alarm.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic volatile int caught_sig = 0;\n\nvoid catcher(__attribute__((unused)) int signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             __attribute__((unused)) void* ucontext_ptr) {\n  caught_sig = signum;\n}\n\nint main(void) {\n  struct sigaction sact;\n  int counter;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = catcher;\n  sigaction(SIGALRM, &sact, NULL);\n\n  alarm(1); /* timer will pop in 1 second */\n\n  for (counter = 0; counter >= 0 && !caught_sig; counter++) {\n    if (counter % 100000 == 0) {\n      write(STDOUT_FILENO, \".\", 1);\n    }\n  }\n\n  atomic_printf(\"\\nSignal %d caught, Counter is %d\\n\", caught_sig, counter);\n  test_assert(SIGALRM == caught_sig);\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/alarm2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid catcher(__attribute__((unused)) int signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             __attribute__((unused)) void* ucontext_ptr) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nint main(void) {\n  struct sigaction sact;\n  int r = 0;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = catcher;\n  sigaction(SIGALRM, &sact, NULL);\n\n  alarm(1); /* timer will pop in 1 second */\n\n  sleep(10);\n\n  return r;\n}\n"
  },
  {
    "path": "src/test/alsa_ioctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef ALSA_DEVICE_DIRECTORY\n#define ALSA_DEVICE_DIRECTORY \"/dev/snd/\"\n#endif\n\nint main(void) {\n  int fd = open(ALSA_DEVICE_DIRECTORY \"control0\", O_NONBLOCK | O_RDONLY);\n  if (fd < 0) {\n    test_assert(errno == EACCES || errno == ENOENT);\n  } else {\n    int* pversion;\n    struct snd_ctl_card_info* info;\n\n    ALLOCATE_GUARD(pversion, 'x');\n    *pversion = -1;\n    test_assert(0 == ioctl(fd, SNDRV_CTL_IOCTL_PVERSION, pversion));\n    VERIFY_GUARD(pversion);\n    test_assert(*pversion >= 0);\n\n    ALLOCATE_GUARD(info, 1);\n    test_assert(0 == ioctl(fd, SNDRV_CTL_IOCTL_CARD_INFO, info));\n    VERIFY_GUARD(info);\n    test_assert(info->id[0] > 1);\n    test_assert(info->driver[0] > 1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/alternate_thread_diversion.c",
    "content": "#include \"util.h\"\n\nstatic volatile int value = 0;\n\n__attribute__((used)) static int get_value(void) { return value; }\n\n__attribute__((noinline)) static void break_here(void) { __asm__(\"\"); }\n\nstatic void* thread_func(void* arg) {\n  (void)arg;\n\n  value = 1;\n  break_here();\n\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread_info;\n  pthread_create(&thread_info, NULL, &thread_func, NULL);\n  pthread_join(thread_info, NULL);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/alternate_thread_diversion.py",
    "content": "from util import *\n\nbp = breakpoint_at_function('break_here')\ncont()\nexpect_breakpoint_stop(bp)\n\nexpect_threads(num_threads=2, selected_thread=2)\n\nselect_thread(1)\nscheduler_locking_on()\nexpect_expression('get_value()', 1)\nscheduler_locking_off()\ncont()\nexpect_signal_stop('SIGKILL')\n\nok()\n"
  },
  {
    "path": "src/test/alternate_thread_diversion.run",
    "content": "source `dirname $0`/util.sh\ndebug_test\n"
  },
  {
    "path": "src/test/args.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  test_assert(6 == argc);\n  test_assert(!strcmp(\"-no\", argv[1]));\n  test_assert(!strcmp(\"--force-syscall-buffer=foo\", argv[2]));\n  test_assert(!strcmp(\"-c\", argv[3]));\n  test_assert(!strcmp(\"1000\", argv[4]));\n  test_assert(!strcmp(\"hello\", argv[5]));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/args.run",
    "content": "source `dirname $0`/util.sh\nrecord args$bitness \"-no --force-syscall-buffer=foo -c 1000 hello\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/arm/arch_timer.c",
    "content": "#include \"util.h\"\n\n#include <sys/auxv.h>\n#include <sys/prctl.h>\n#include <stdio.h>\n\n// For compatibility with pre-2.38 versions of binutils.\n#define cntvctss_el0 \"s3_3_c14_c0_6\"\n\n#ifndef HWCAP2_ECV\n#define HWCAP2_ECV (1 << 19)\n#endif\n\nlong cntfrq(void) {\n  long c;\n  __asm__ __volatile__(\"mrs %0, cntfrq_el0\" : \"=r\"(c));\n  return c;\n}\n\nlong cntvct(void) {\n  long c;\n  __asm__ __volatile__(\"mrs %0, cntvct_el0\" : \"=r\"(c));\n  return c;\n}\n\nlong cntvctss(void) {\n  long c;\n  if (getauxval(AT_HWCAP2) & HWCAP2_ECV) {\n    __asm__ __volatile__(\".arch armv8.6-a\\nmrs %0, \" cntvctss_el0 : \"=r\"(c));\n  } else {\n    __asm__ __volatile__(\"mrs %0, cntvct_el0\" : \"=r\"(c));\n  }\n  return c;\n}\n\nlong initial_cntfrq;\nlong initial_cntvct;\n\nvoid arch_timer_nops(void) {\n  __asm__ __volatile__(\"mrs xzr, cntfrq_el0\");\n  __asm__ __volatile__(\"mrs xzr, cntvct_el0\");\n  if (getauxval(AT_HWCAP2) & HWCAP2_ECV) {\n    __asm__ __volatile__(\"mrs xzr, \" cntvctss_el0);\n  }\n}\n\nvoid diversion_check(void) {\n  arch_timer_nops();\n  test_assert(initial_cntfrq == cntfrq());\n  test_assert(initial_cntvct < cntvct());\n  test_assert(initial_cntvct < cntvctss());\n  atomic_puts(\"diversion_check passed\");\n}\n\nvoid breakpoint(void) {}\n\nint main(void) {\n  initial_cntfrq = cntfrq();\n  initial_cntvct = cntvct();\n  breakpoint();\n\n  atomic_printf(\"%ld\\n\", cntvct());\n  atomic_printf(\"%ld\\n\", cntvctss());\n  atomic_printf(\"%ld\\n\", cntfrq());\n\n  arch_timer_nops();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/arm/arch_timer.run",
    "content": "source `dirname $0`/util.sh\nif ! prctl_tsc_supported; then\n  exit 77\nfi\ncompare_test EXIT-SUCCESS\ndebug_gdb_only arm/diversion_arch_timer\n"
  },
  {
    "path": "src/test/arm/brk_nonzero.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  __asm__ __volatile__(\"brk #12345\");\n}\n\nstatic void handle_sigtrap(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nint main(void) {\n  signal(SIGTRAP, handle_sigtrap);\n\n  atomic_puts(\"raising SIGTRAP ...\");\n\n  breakpoint();\n\n  test_assert(\"didn't catch trap!\" && 0);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/arm/diversion_arch_timer.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('call diversion_check()')\nexpect_gdb('diversion_check passed')\n\nok()\n"
  },
  {
    "path": "src/test/arm/tagged_addr_ctrl.c",
    "content": "#include \"util.h\"\n\n#include <linux/prctl.h>\n#include <sys/prctl.h>\n#include <errno.h>\n\nint main(void) {\n  int ret = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);\n  // Skip the test on pre-5.4 kernels which predate the prctl.\n  if (ret == -1 && errno == EINVAL) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n\n  ret = prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0);\n  test_assert(ret == 0);\n\n  ret = prctl(PR_GET_TAGGED_ADDR_CTRL, 0, 0, 0, 0);\n  test_assert(ret == PR_TAGGED_ADDR_ENABLE);\n\n  // We don't support MTE yet.\n  ret = prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE | PR_MTE_TCF_ASYNC,\n              0, 0, 0);\n  test_assert(ret == -1 && errno == EINVAL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/arm/util.h",
    "content": "#include \"../util.h\"\n"
  },
  {
    "path": "src/test/arm/util.sh",
    "content": "TEST_PREFIX=arm/\nsource `dirname $0`/../util.sh\n"
  },
  {
    "path": "src/test/async_kill_with_syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int pipe_fds[2];\n  int iteration = 0;\n  char chars[100];\n  pipe(pipe_fds);\n  memset(chars, 0, sizeof(chars));\n\n  atomic_puts(\"ready\");\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  while (1) {\n    int n = (iteration % 100) + 1;\n    test_assert(n == write(pipe_fds[1], chars, n));\n    test_assert(n == read(pipe_fds[0], chars, n));\n    iteration += 1;\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_kill_with_syscallbuf.run",
    "content": "source `dirname $0`/util.sh\n# SIGKILL, wait 2.0s\nrecord_async_signal 9 2.0 $TESTNAME\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_kill_with_syscallbuf2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  uint64_t iteration = 0;\n  int pipe_fds[2];\n  pipe(pipe_fds);\n\n  // Write once to get the syscallbuf primed.\n  write(pipe_fds[1], \"hi\\n\", 3);\n\n  atomic_puts(\"ready\");\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  // Write again.\n  write(pipe_fds[1], \"hi\\n\", 3);\n\n  while (iteration < UINT64_MAX) {\n    iteration += 1;\n    // Don't let the compiler delete this loop.\n    asm(\"\" : : : \"memory\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_kill_with_syscallbuf2.run",
    "content": "source `dirname $0`/util.sh\n# SIGKILL, wait 1.0s\nrecord_async_signal 9 1.0 $TESTNAME\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_kill_with_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  atomic_puts(\"ready\");\n  sleep(1000);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  sleep(1000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_kill_with_threads.run",
    "content": "source `dirname $0`/util.sh\n# SIGKILL, wait 2.0s\nrecord_async_signal 9 2.0 $TESTNAME\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_kill_with_threads_main_running.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  sleep(1000);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  atomic_puts(\"ready\");\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  while (1) {\n    asm(\"\" : : : \"memory\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_kill_with_threads_main_running.run",
    "content": "source `dirname $0`/util.sh\n# SIGKILL, wait 2.0s\nrecord_async_signal 9 2.0 $TESTNAME\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_kill_with_threads_thread_running.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  atomic_puts(\"ready\");\n  while (1) {\n    asm(\"\" : : : \"memory\");\n  }\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  sleep(1000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_kill_with_threads_thread_running.run",
    "content": "source `dirname $0`/util.sh\n# SIGKILL, wait 6.0s\n# The timeout must be greater than rr's alarm threshold of 3s, because\n# the spinning-thread may not do any conditional branches so we rely\n# on the alarm fallback to ensure there's a context switch to the main\n# thread to print EXIT-SUCCESS.\nrecord_async_signal 9 6.0 $TESTNAME\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_segv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_segv(int sig) {\n  test_assert(SIGSEGV == sig);\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nint main(void) {\n  int dummy = 0, i;\n\n  signal(SIGSEGV, handle_segv);\n\n  atomic_puts(\"ready\");\n\n  /* No syscalls after here!  (Up to the assert.) */\n  for (i = 1; i < (1 << 30); ++i) {\n    dummy += (dummy + i) % 9735;\n  }\n\n  /* It's possible for SEGV to be delivered too late, so succeed anyway */\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_segv.run",
    "content": "source `dirname $0`/util.sh\n# SIGSEGV, wait 2.0s\nrecord_async_signal 11 2.0 $TESTNAME\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/async_segv_ignored.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  signal(SIGSEGV, SIG_IGN);\n\n  kill(getpid(), SIGSEGV);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_signal_syscalls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic sig_atomic_t caught_usr1;\n\nstatic void handle_usr1(int sig) {\n  test_assert(SIGUSR1 == sig);\n  atomic_puts(\"caught usr1\");\n  caught_usr1 = 1;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n  }\n  return NULL;\n}\n\nint main(int argc, char* argv[]) {\n  struct timespec ts;\n  struct timeval tv;\n  int num_its;\n  int i;\n  pthread_t thread;\n\n  /* Create an extra thread so context switches can happen\n     and SCHED events will be recorded. */\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  test_assert(argc == 2);\n  num_its = atoi(argv[1]);\n  test_assert(num_its > 0);\n\n  atomic_printf(\"Running 2^%d iterations\\n\", num_its);\n\n  signal(SIGUSR1, handle_usr1);\n\n  atomic_puts(\"ready\\n\");\n\n  /* Driver scripts choose the number of iterations based on\n   * their needs. */\n  for (i = 0; i < 1 << num_its; ++i) {\n    /* The odds of the signal being caught in the library\n     * implementing these syscalls is very high.  But even\n     * if it's not caught there, this test will pass. */\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    if (caught_usr1) {\n      break;\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_signal_syscalls.run",
    "content": "source `dirname $0`/util.sh\n\n# Without the syscallbuf, trying to record the large number of\n# syscalls in this test is impractical.\nskip_if_no_syscall_buf\n\n# 2^17 iterations is arbitrarily chosen to take ~3s on a fast machine\nrecord $TESTNAME 17\n\nreplay\ncheck 'EXIT-SUCCESS'\npassed\n"
  },
  {
    "path": "src/test/async_signal_syscalls2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define ITERATION_COUNT 10\n\nstatic int usr1_count = 0;\nstatic int usr2_count = 0;\nstatic int alrm_count = 0;\nstatic volatile int done;\n\nstatic int ready_fds[2];\n\nstatic void handle_signal(int sig) {\n  switch (sig) {\n    case SIGUSR1:\n      usr1_count++;\n      break;\n    case SIGUSR2:\n      usr2_count++;\n      break;\n    case SIGALRM:\n      alrm_count++;\n      break;\n    default:\n      test_assert(0);\n      break;\n  }\n  test_assert(1 == write(ready_fds[1], \"K\", 1));\n}\n\nstatic void* thread_start(__attribute__((unused)) void* p) {\n  struct timespec ts = { 0, 1000 };\n  sigset_t mask;\n  int i;\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGUSR1);\n  sigaddset(&mask, SIGUSR2);\n  sigaddset(&mask, SIGALRM);\n  test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, NULL));\n\n  for (i = 0; i < ITERATION_COUNT; ++i) {\n    char buf[3];\n    int count = 3;\n\n    nanosleep(&ts, NULL);\n\n    if (i > 0) {\n      while (count > 0) {\n        int n = read(ready_fds[0], buf, count);\n        test_assert(n > 0);\n        count -= n;\n      }\n    }\n\n    kill(getpid(), SIGUSR1);\n    kill(getpid(), SIGUSR2);\n    kill(getpid(), SIGALRM);\n  }\n\n  done = 1;\n\n  return NULL;\n}\n\nint main(void) {\n  struct timespec ts;\n  pthread_t thread;\n  int fd;\n  char buf[10];\n\n  test_assert(0 == pipe(ready_fds));\n\n  fd = open(\"/dev/zero\", O_RDONLY);\n\n  signal(SIGUSR1, handle_signal);\n  signal(SIGUSR2, handle_signal);\n  signal(SIGALRM, handle_signal);\n\n  pthread_create(&thread, NULL, thread_start, NULL);\n\n  while (!done) {\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    read(fd, buf, sizeof(buf));\n  }\n\n  test_assert(usr1_count == ITERATION_COUNT);\n  test_assert(usr2_count == ITERATION_COUNT);\n  test_assert(alrm_count == ITERATION_COUNT);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_signal_syscalls2.run",
    "content": "source `dirname $0`/util.sh\n\n# Without the syscallbuf, trying to record the large number of\n# syscalls in this test is impractical.\nskip_if_no_syscall_buf\n\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/async_signal_syscalls_100.run",
    "content": "source `dirname $0`/util.sh\n\n# Ensure that the test records some SCHED interrupt events.\ntimeslice=100\nRECORD_ARGS=\"-c$timeslice\"\n\n# 2^9 iterations is arbitrarily chosen to record and replay < 15s,\n# both with and without the syscallbuf, on a fast machine.\nrecord async_signal_syscalls$bitness 9\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_signal_syscalls_1000.run",
    "content": "source `dirname $0`/util.sh\n\n# Ensure that the test records some USR_SCHED interrupt events.\ntimeslice=1000\nRECORD_ARGS=\"-c$timeslice\"\n\n# 2^9 iterations is arbitrarily chosen to record and replay < 15s,\n# both with and without the syscallbuf, on a fast machine.\nrecord async_signal_syscalls$bitness 9\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/async_signal_syscalls_siginfo.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic sig_atomic_t caught_usr1;\nstatic siginfo_t siginfo;\n\n#define MAGIC_NUMBER 0x7654321 /* positive */\n\nstatic void handle_usr1(int sig, siginfo_t* si,\n                        __attribute__((unused)) void* context) {\n  test_assert(SIGUSR1 == sig);\n  test_assert(si->si_code == siginfo.si_code);\n  test_assert(si->si_pid == siginfo.si_pid);\n  test_assert(si->si_uid == siginfo.si_uid);\n  test_assert(si->si_value.sival_int == siginfo.si_value.sival_int);\n\n  caught_usr1 = 1;\n  atomic_puts(\"caught usr1\");\n}\n\nstatic void* thread_start(__attribute__((unused)) void* p) {\n  usleep(1000);\n\n  siginfo.si_code = SI_QUEUE;\n  siginfo.si_pid = getpid();\n  siginfo.si_uid = geteuid();\n  siginfo.si_value.sival_int = MAGIC_NUMBER;\n  syscall(SYS_rt_tgsigqueueinfo, getpid(), getpid(), SIGUSR1, &siginfo);\n\n  return NULL;\n}\n\nint main(int argc, char* argv[]) {\n  struct timespec ts;\n  struct timeval tv;\n  int num_its;\n  int i;\n  struct sigaction sa;\n  pthread_t thread;\n\n  test_assert(argc == 2);\n  num_its = atoi(argv[1]);\n  test_assert(num_its > 0);\n\n  atomic_printf(\"Running 2^%d iterations\\n\", num_its);\n\n  sa.sa_flags = SA_SIGINFO;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_sigaction = handle_usr1;\n  sigaction(SIGUSR1, &sa, NULL);\n\n  pthread_create(&thread, NULL, thread_start, NULL);\n\n  /* Driver scripts choose the number of iterations based on\n   * their needs. */\n  for (i = 0; i < 1 << num_its; ++i) {\n    /* The odds of the signal being caught in the library\n     * implementing these syscalls is very high.  But even\n     * if it's not caught there, this test will pass. */\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n  }\n\n  pthread_join(thread, NULL);\n\n  test_assert(caught_usr1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_signal_syscalls_siginfo.run",
    "content": "source `dirname $0`/util.sh\n\n# Without the syscallbuf, trying to record the large number of\n# syscalls in this test is impractical.\nskip_if_no_syscall_buf\n\n# 2^17 iterations is arbitrarily chosen to take ~3s on a fast machine\nrecord $TESTNAME 17\n\nreplay\ncheck 'EXIT-SUCCESS'\npassed\n"
  },
  {
    "path": "src/test/async_usr1.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic sig_atomic_t caught_usr1;\n\nstatic void handle_usr1(int sig) {\n  test_assert(SIGUSR1 == sig);\n  caught_usr1 = 1;\n  atomic_puts(\"caught usr1\");\n}\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  int dummy = 0, i;\n\n  signal(SIGUSR1, handle_usr1);\n\n  atomic_puts(\"ready\");\n\n  breakpoint();\n  /* NO SYSCALLS AFTER HERE!  (Up to the assert.) */\n  for (i = 1; !caught_usr1 && i < (1 << 30); ++i) {\n    dummy += (dummy + i) % 9735;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/async_usr1.run",
    "content": "source `dirname $0`/util.sh\n# SIGUSR1, wait 2.0s\nrecord_async_signal 10 2.0 $TESTNAME\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/at_threadexit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pthread_key_t exit_key;\nstatic uint64_t exit_key_value;\n\nstatic void thread_exit(__attribute__((unused)) void* data) {\n  atomic_puts(\"thread exit\");\n}\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  pthread_key_create(&exit_key, thread_exit);\n  pthread_setspecific(exit_key, (void*)&exit_key_value);\n  pthread_exit(NULL);\n}\n\nint main(void) {\n  pthread_t t;\n\n  pthread_create(&t, NULL, thread, NULL);\n  pthread_join(t, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/bad_breakpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\nfor i in $(seq 15 25); do\n    echo Replaying to event $i ...\n    debug_gdb_only restart_finish \"-g $i\"\n    if [[ \"$leave_data\" == \"y\" ]]; then\n        break\n    fi\ndone\n"
  },
  {
    "path": "src/test/bad_good_break.py",
    "content": "from util import *\n\nsend_gdb('b bad_breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b good_breakpoint')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\n# If we hit bad_breakpoint, then we never continue and never reach\n# good_breakpoint.\nexpect_gdb('Breakpoint 2, good_breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/bad_ip.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(int sig, siginfo_t* si,\n                       __attribute__((unused)) void* utp) {\n  test_assert(SIGSEGV == sig && si->si_addr == (void*)0x44);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nint main(void) {\n  struct sigaction act;\n\n  act.sa_sigaction = sighandler;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = SA_SIGINFO;\n  sigaction(SIGSEGV, &act, NULL);\n\n  ((void (*)(void))(0x44))();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/bad_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = syscall(-10);\n  test_assert(-1 == ret && ENOSYS == errno);\n  ret = syscall(9999);\n  test_assert(-1 == ret && ENOSYS == errno);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return ret;\n}\n"
  },
  {
    "path": "src/test/barrier.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void hit_barrier(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void joined_threads(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void set_thread_name(int id) {\n  char name_buf[16];\n  snprintf(name_buf, sizeof(name_buf), \"BP-THREAD-%d\", id);\n  prctl(PR_SET_NAME, name_buf);\n}\n\nstruct thread_data {\n  int threadno;\n  pthread_barrier_t* bar;\n};\n\nstatic void* thread(void* datap) {\n  struct thread_data* data = datap;\n  pthread_barrier_t* bar = data->bar;\n\n  set_thread_name(data->threadno);\n\n  atomic_printf(\"thread %d launched with data %p\\n\", data->threadno, data);\n  breakpoint();\n  pthread_barrier_wait(bar);\n  pthread_barrier_wait(bar);\n\n  atomic_printf(\"thread %d done\\n\", data->threadno);\n  free(data);\n  return NULL;\n}\n\nint main(void) {\n  struct timeval tv;\n  pthread_barrier_t bar;\n  pthread_t threads[10];\n  size_t i;\n\n  /* (Kick on the syscallbuf lib.) */\n  gettimeofday(&tv, NULL);\n\n  pthread_barrier_init(&bar, NULL, 1 + ALEN(threads));\n\n  set_thread_name(1);\n\n  for (i = 0; i < ALEN(threads); ++i) {\n    struct thread_data* data = calloc(1, sizeof(*data));\n    data->threadno = i + 2;\n    data->bar = &bar;\n    pthread_create(&threads[i], NULL, thread, data);\n  }\n\n  pthread_barrier_wait(&bar);\n\n  hit_barrier();\n\n  pthread_barrier_wait(&bar);\n  atomic_puts(\"main done\");\n\n  for (i = 0; i < ALEN(threads); ++i) {\n    pthread_join(threads[i], NULL);\n  }\n\n  joined_threads();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n  return -1;\n}\n"
  },
  {
    "path": "src/test/basic_test.run",
    "content": "source `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/big_buffers.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DUMMY_FILE \"dummy.txt\"\n#define BUF_SIZE (1 << 24)\n\nint main(void) {\n  struct timeval ts;\n  char* buf;\n  int fd;\n  int sockfds[2];\n  ssize_t nread;\n\n  gettimeofday(&ts, NULL);\n\n  buf = xmalloc(BUF_SIZE);\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n\n  /* Big read() buffer. */\n  fd = creat(DUMMY_FILE, 0600);\n  write(fd, \"foo\", 3);\n  close(fd);\n  fd = open(DUMMY_FILE, O_RDONLY);\n  unlink(DUMMY_FILE);\n\n  nread = read(fd, buf, BUF_SIZE);\n  atomic_printf(\"read %zu bytes: %s\\n\", nread, buf);\n  test_assert(3 == nread && !strcmp(buf, \"foo\"));\n\n  /* Big recv() buffer. */\n  write(sockfds[0], \"bar\", 3);\n  nread = recv(sockfds[1], buf, BUF_SIZE, 0);\n  atomic_printf(\"recv'd %zu bytes: %s\\n\", nread, buf);\n  test_assert(3 == nread && !strcmp(buf, \"bar\"));\n\n  /* Big recvfrom() buffer. */\n  write(sockfds[0], \"baz\", 3);\n  nread = recvfrom(sockfds[1], buf, BUF_SIZE, 0, NULL, NULL);\n  atomic_printf(\"recvfrom'd %zu bytes: %s\\n\", nread, buf);\n  test_assert(3 == nread && !strcmp(buf, \"baz\"));\n\n  {\n    struct mmsghdr mmsg;\n    struct iovec data;\n\n    memset(&mmsg, 0, sizeof(mmsg));\n    memset(&data, 0, sizeof(data));\n    mmsg.msg_hdr.msg_iov = &data;\n    mmsg.msg_hdr.msg_iovlen = 1;\n\n    /* Big recvmsg() buffer. */\n    data.iov_base = \"foo\";\n    data.iov_len = 3;\n    test_assert(3 <= sendmsg(sockfds[0], &mmsg.msg_hdr, 0));\n\n    data.iov_base = buf;\n    data.iov_len = BUF_SIZE;\n    nread = recvmsg(sockfds[1], &mmsg.msg_hdr, 0);\n    atomic_printf(\"recvmsg'd %zu bytes: %s\\n\", nread, buf);\n    test_assert(3 <= nread && !strcmp(buf, \"foo\"));\n\n    /* Big recvmmsg() buffer. */\n    data.iov_base = \"bar\";\n    data.iov_len = 3;\n    test_assert(1 == sendmmsg(sockfds[0], &mmsg, 1, 0));\n\n    data.iov_base = buf;\n    data.iov_len = BUF_SIZE;\n    test_assert(1 == recvmmsg(sockfds[1], &mmsg, 1, 0, NULL));\n    nread = mmsg.msg_len;\n    atomic_printf(\"recvmmsg'd %zu bytes: %s\\n\", nread, buf);\n    test_assert(3 <= nread && !strcmp(buf, \"bar\"));\n  }\n\n  /* TODO: tests for epoll_wait() / poll() / select() (/\n   * prctl()?), which are much less likely to have buffers big\n   * enough to overflow scratch. */\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/big_select.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_LONGS (FD_SETSIZE/(8 * sizeof(long)) + 1)\n\nint main(void) {\n  struct {\n    long longs[NUM_LONGS];\n  } *fdset;\n  int ret;\n  int pipe_fds[2];\n  struct timeval timeout = { 0, 0 };\n  struct rlimit rlim = { FD_SETSIZE + 1, FD_SETSIZE + 1 };\n  if (setrlimit(RLIMIT_NOFILE, &rlim)) {\n    atomic_puts(\"Can't set necessary rlimit, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  ret = pipe(pipe_fds);\n  test_assert(ret == 0);\n  ret = dup2(pipe_fds[0], FD_SETSIZE);\n  test_assert(ret == FD_SETSIZE);\n\n  ALLOCATE_GUARD(fdset, 'a');\n  memset(fdset->longs, 0, sizeof(fdset->longs));\n  fdset->longs[NUM_LONGS - 1] = -1;\n  ret = select(FD_SETSIZE + 1, (fd_set*)fdset, NULL, NULL, &timeout);\n  test_assert(ret == 0);\n  VERIFY_GUARD(fdset);\n\n  test_assert(fdset->longs[NUM_LONGS - 1] == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/blacklist.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char file_name[] = \"rr-test-blacklist-file_name\";\n\nint main(void) {\n  int fd;\n  int dirfd;\n  char buf[PATH_MAX];\n\n  open(file_name, O_CREAT | O_WRONLY, 0700);\n\n#ifdef SYS_open\n  fd = syscall(SYS_open, file_name, O_RDONLY);\n  test_assert(fd < 0);\n  test_assert(errno == ENOENT);\n#endif\n\n  fd = syscall(SYS_openat, AT_FDCWD, file_name, O_RDONLY);\n  test_assert(fd < 0);\n  test_assert(errno == ENOENT);\n\n  getcwd(buf, PATH_MAX);\n  dirfd = syscall(SYS_openat, -1, buf, O_PATH);\n  test_assert(dirfd >= 0);\n  fd = syscall(SYS_openat, dirfd, \"rr-test-blacklist-file_name\", O_RDONLY);\n  test_assert(fd < 0);\n  test_assert(errno == ENOENT);\n\n  unlink(file_name);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/blacklist.run",
    "content": "source `dirname $0`/util.sh\ntouch rr-test-blacklist-file_name\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/block.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <linux/net.h>\n\n#define CTRLMSG_LEN CMSG_LEN(sizeof(int))\n\nstruct sendmmsg_arg {\n  int sockfd;\n  struct mmsghdr* msgvec;\n  unsigned int vlen;\n  unsigned int flags;\n};\n\nstruct recvmmsg_arg {\n  int sockfd;\n  struct mmsghdr* msgvec;\n  unsigned int vlen;\n  unsigned int flags;\n  struct timespec* timeout;\n};\n\nstruct select_arg {\n  int n_fds;\n  fd_set* read;\n  fd_set* write;\n  fd_set* except;\n  struct timeval* timeout;\n};\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\nstatic int sockfds[2];\n\nstatic const int msg_magic = 0x1337beef;\nconst ssize_t num_sockbuf_bytes = 1 << 20;\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  char token = '!';\n  int sock = sockfds[1];\n  struct timeval ts;\n  char c = '\\0';\n  int i;\n\n  gettimeofday(&ts, NULL);\n\n  atomic_puts(\"r: acquiring mutex ...\");\n  pthread_mutex_lock(&lock);\n  atomic_puts(\"r:   ... releasing mutex\");\n  pthread_mutex_unlock(&lock);\n\n  for (i = 0; i < 2; ++i) {\n    atomic_puts(\"r: reading socket ...\");\n    gettimeofday(&ts, NULL);\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"r:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n  }\n  /* TODO: readv() support */\n\n  atomic_puts(\"r: recv'ing socket ...\");\n  gettimeofday(&ts, NULL);\n  test_assert(1 == recv(sock, &c, sizeof(c), 0));\n  atomic_printf(\"r:   ... recv'd '%c'\\n\", c);\n  test_assert(c == token);\n  ++token;\n\n  atomic_puts(\"r: recvfrom'ing socket ...\");\n  test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, NULL, NULL));\n  atomic_printf(\"r:   ... recvfrom'd '%c'\\n\", c);\n  test_assert(c == token);\n  ++token;\n  {\n    struct sockaddr_un addr;\n    socklen_t addrlen = sizeof(addr);\n\n    atomic_puts(\"r: recvfrom(&sock)'ing socket ...\");\n    test_assert(1 == recvfrom(sock, &c, sizeof(c), 0, (struct sockaddr*)&addr, &addrlen));\n    atomic_printf(\"r:   ... recvfrom'd '%c' from sock len:%d\\n\", c, addrlen);\n    test_assert(c == token);\n    /* socketpair() AF_LOCAL sockets don't identify\n     * themselves. */\n    test_assert(addrlen == 0);\n    ++token;\n  }\n  {\n    struct mmsghdr mmsg;\n    struct iovec data;\n    int magic = ~msg_magic;\n    int err, ret;\n#if defined(SYS_socketcall)\n    struct recvmmsg_arg arg;\n#endif\n\n    memset(&mmsg, 0, sizeof(mmsg));\n    memset(&data, 0, sizeof(data));\n    data.iov_base = &magic;\n    data.iov_len = sizeof(magic);\n    mmsg.msg_hdr.msg_iov = &data;\n    mmsg.msg_hdr.msg_iovlen = 1;\n\n    struct cmsghdr* cmptr = (struct cmsghdr*)xmalloc(CTRLMSG_LEN);\n    mmsg.msg_hdr.msg_control = cmptr;\n    mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN;\n\n    atomic_puts(\"r: recvmsg with DONTWAIT ...\");\n    ret = recvmsg(sock, &mmsg.msg_hdr, MSG_DONTWAIT);\n    err = errno;\n    atomic_printf(\"r:  ... returned %d (%s/%d)\\n\", ret, strerror(err), err);\n    test_assert(-1 == ret);\n    test_assert(EWOULDBLOCK == err);\n    test_assert(mmsg.msg_hdr.msg_iov == &data);\n\n    atomic_puts(\"r: recmsg'ing socket ...\");\n\n    test_assert(0 < recvmsg(sock, &mmsg.msg_hdr, 0));\n    atomic_printf(\"r:   ... recvmsg'd 0x%x\\n\", magic);\n    test_assert(msg_magic == magic);\n    test_assert(mmsg.msg_hdr.msg_iov == &data);\n\n    int fd;\n    memcpy(&fd, CMSG_DATA(cmptr), sizeof(fd));\n    struct stat fs_new, fs_old;\n    fstat(fd, &fs_new);\n    fstat(STDERR_FILENO, &fs_old);\n    // check if control msg was send successfully\n    test_assert(\n        fs_old.st_dev == fs_new.st_dev && fs_old.st_ino == fs_new.st_ino &&\n        fs_old.st_uid == fs_new.st_uid && fs_old.st_gid == fs_new.st_gid &&\n        fs_old.st_rdev == fs_new.st_rdev && fs_old.st_size == fs_new.st_size);\n\n    magic = ~msg_magic;\n    atomic_puts(\"r: recmmsg'ing socket ...\");\n\n    breakpoint();\n    test_assert(1 == recvmmsg(sock, &mmsg, 1, 0, NULL));\n    atomic_printf(\"r:   ... recvmmsg'd 0x%x (%u bytes)\\n\", magic, mmsg.msg_len);\n    test_assert(msg_magic == magic);\n    test_assert(mmsg.msg_hdr.msg_iov == &data);\n\n    magic = ~msg_magic;\n#if defined(SYS_socketcall)\n    memset(&arg, 0, sizeof(arg));\n    arg.sockfd = sock;\n    arg.msgvec = &mmsg;\n    arg.vlen = 1;\n    test_assert(1 == syscall(SYS_socketcall, SYS_RECVMMSG, (void*)&arg));\n#elif defined(SYS_recvmmsg)\n    test_assert(1 == syscall(SYS_recvmmsg, sock, &mmsg, 1, 0, (void*)0));\n#else\n#error unable to call recvmmsg\n#endif\n    atomic_printf(\"r:   ... recvmmsg'd(by socketcall) 0x%x (%u bytes)\\n\", magic,\n                  mmsg.msg_len);\n    test_assert(msg_magic == magic);\n\n    free(cmptr);\n  }\n  {\n    struct msghdr msg;\n    struct iovec iovs[2];\n    char c1 = '\\0', c2 = '\\0';\n    memset(&msg, 0, sizeof(msg));\n\n    iovs[0].iov_base = &c1;\n    iovs[0].iov_len = sizeof(c1);\n    iovs[1].iov_base = &c2;\n    iovs[1].iov_len = sizeof(c2);\n\n    msg.msg_iov = iovs;\n    msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);\n\n    atomic_puts(\"r: recmsg'ing socket with two iovs ...\");\n    test_assert(2 == recvmsg(sock, &msg, 0));\n    atomic_printf(\"r:   ... recvmsg'd '%c' and '%c'\\n\", c1, c2);\n\n    test_assert(c1 == token);\n    token++;\n    test_assert(c2 == token);\n    token++;\n  }\n  {\n    struct pollfd pfd;\n\n    atomic_puts(\"r: polling socket ...\");\n    pfd.fd = sock;\n    pfd.events = POLLIN;\n    gettimeofday(&ts, NULL);\n    poll(&pfd, 1, -1);\n    atomic_puts(\"r:   ... done, doing nonblocking read ...\");\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"r:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n  }\n  {\n    struct pollfd pfd;\n\n    atomic_puts(\"r: polling socket ...\");\n    pfd.fd = sock;\n    pfd.events = POLLIN;\n    gettimeofday(&ts, NULL);\n    ppoll(&pfd, 1, NULL, NULL);\n    atomic_puts(\"r:   ... done, doing nonblocking read ...\");\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"r:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n  }\n  {\n    fd_set fds;\n    const struct timeval infinity = { 1 << 30, 0 };\n    struct timeval tv = infinity;\n    int ret;\n#if defined(__i386__)\n    struct select_arg arg;\n#endif\n\n    atomic_puts(\"r: select()ing socket ...\");\n    FD_ZERO(&fds);\n    FD_SET(sock, &fds);\n#if defined(__i386__)\n    memset(&arg, 0, sizeof(arg));\n    arg.n_fds = sock + 1;\n    arg.read = &fds;\n    arg.write = NULL;\n    arg.except = NULL;\n    arg.timeout = &tv;\n    ret = syscall(SYS_select, &arg);\n#elif defined(SYS_select)\n    ret = syscall(SYS_select, sock + 1, &fds, (void*)0, (void*)0, &tv);\n#else\n    ret = syscall(SYS_pselect6, sock + 1, &fds, (void*)0, (void*)0, &tv, (void*)0);\n#endif\n    atomic_printf(\"r:   ... returned %d; tv { %ld, %ld }\\n\", ret, tv.tv_sec,\n                  tv.tv_usec);\n    test_assert(1 == ret);\n    test_assert(FD_ISSET(sock, &fds));\n    test_assert(0 < tv.tv_sec && tv.tv_sec < infinity.tv_sec);\n\n    atomic_puts(\"r:   ... done, doing nonblocking read ...\");\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"r:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n  }\n  {\n    fd_set fds;\n    const struct timeval infinity = { 1 << 30, 0 };\n    struct timeval tv = infinity;\n    int ret;\n\n    atomic_puts(\"r: select()ing socket ...\");\n    FD_ZERO(&fds);\n    FD_SET(sock, &fds);\n    ret = select(sock + 1, &fds, NULL, NULL, &tv);\n    atomic_printf(\"r:   ... returned %d; tv { %ld, %ld }\\n\", ret, tv.tv_sec,\n                  tv.tv_usec);\n    test_assert(1 == ret);\n    test_assert(FD_ISSET(sock, &fds));\n    test_assert(0 < tv.tv_sec && tv.tv_sec <= infinity.tv_sec);\n\n    atomic_puts(\"r:   ... done, doing nonblocking read ...\");\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"r:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n  }\n  {\n    int epfd;\n    struct epoll_event ev;\n    sigset_t all_sigs;\n    sigfillset(&all_sigs);\n\n    atomic_puts(\"r: epolling socket ...\");\n    test_assert(0 <= (epfd = epoll_create(1 /*num events*/)));\n    ev.events = EPOLLIN;\n    ev.data.fd = sock;\n    gettimeofday(&ts, NULL);\n    test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev));\n    test_assert(1 == epoll_wait(epfd, &ev, 1, -1));\n    atomic_puts(\"r:   ... done, doing nonblocking read ...\");\n    test_assert(sock == ev.data.fd);\n    test_assert(1 == epoll_pwait(epfd, &ev, 1, -1, &all_sigs));\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"r:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n\n    close(epfd);\n  }\n  {\n    char* buf = (char*)xmalloc(num_sockbuf_bytes);\n    ssize_t nwritten = 0;\n    struct iovec iov;\n\n    ++token;\n    memset(buf, token, num_sockbuf_bytes);\n\n    atomic_printf(\"r: writing outbuf of size %zd ...\\n\", num_sockbuf_bytes);\n    while (nwritten < num_sockbuf_bytes) {\n      ssize_t this_write = write(sock, buf, num_sockbuf_bytes - nwritten);\n      atomic_printf(\"r:   wrote %zd bytes this time\\n\", this_write);\n      nwritten += this_write;\n    }\n\n    ++token;\n    memset(buf, token, num_sockbuf_bytes);\n    iov.iov_base = buf;\n    iov.iov_len = num_sockbuf_bytes;\n    atomic_printf(\"r: writev()ing outbuf of size %zd ...\\n\", num_sockbuf_bytes);\n    while (iov.iov_len > 0) {\n      ssize_t this_write = writev(sock, &iov, 1);\n      atomic_printf(\"r:   wrote %zd bytes this time\\n\", this_write);\n      iov.iov_len -= this_write;\n    }\n\n    free(buf);\n  }\n\n  atomic_puts(\"r: reading socket with masked signals ...\");\n  {\n    sigset_t old_mask, mask;\n    sigfillset(&mask);\n    test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, &old_mask));\n\n    test_assert(1 == read(sock, &c, sizeof(c)));\n\n    test_assert(0 == pthread_sigmask(SIG_SETMASK, &old_mask, NULL));\n  }\n  ++token;\n  atomic_printf(\"r:   ... read '%c'\\n\", c);\n  test_assert(c == token);\n\n  /* Make the main thread wait on our join() */\n  atomic_puts(\"r: sleeping ...\");\n  usleep(500000);\n\n  return NULL;\n}\n\nstatic void read_all_chunks(int sock, char* buf, ssize_t num_sockbuf_bytes,\n                            char token) {\n  ssize_t nread = 0;\n  while (nread < num_sockbuf_bytes) {\n    char* this_buf = buf + nread;\n    ssize_t this_read = read(sock, this_buf, num_sockbuf_bytes - nread);\n    int i;\n\n    atomic_printf(\"M:   read %zd bytes this time,\\n\", this_read);\n    test_assert(this_read > 0);\n    /* XXX: we would like to assert that the written data\n     * was read in more than one chunk, which should imply\n     * that at least one write() from the other thread\n     * blocked, but it's possible for multiple write()s to\n     * complete and fill the read buffer here before the\n     * reader returns. */\n    /*test_assert(this_read < num_sockbuf_bytes);*/\n\n    for (i = nread; i < nread + this_read; ++i) {\n      if (token != buf[i]) {\n        atomic_printf(\"M:   byte %d should be '%c', but is '%c'\\n\", i, token,\n                      buf[i]);\n      }\n    }\n    nread += this_read;\n    atomic_printf(\"M:      %zd total so far\\n\", nread);\n  }\n}\n\nint main(void) {\n  char token = '!';\n  struct timeval ts;\n  pthread_t reader;\n  int sock;\n\n  gettimeofday(&ts, NULL);\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n  sock = sockfds[0];\n\n  pthread_mutex_lock(&lock);\n\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  /* Make the reader thread wait on its pthread_mutex_lock() */\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n  atomic_puts(\"M: unlocking mutex ...\");\n  pthread_mutex_unlock(&lock);\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on read() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  test_assert(1 == write(sock, &token, sizeof(token)));\n  ++token;\n  atomic_puts(\"M:   ... done\");\n  /* Force a wait on readv() */\n  {\n    struct iovec v = {.iov_base = &token, .iov_len = sizeof(token) };\n\n    atomic_puts(\"M: sleeping again ...\");\n    usleep(500000);\n    atomic_printf(\"r: writev('%c')'ing socket ...\\n\", token);\n    test_assert(1 == writev(sock, &v, 1));\n    ++token;\n    atomic_puts(\"M:   ... done\");\n  }\n  /* Force a wait on recv() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: sending '%c' to socket ...\\n\", token);\n  send(sock, &token, sizeof(token), 0);\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on recvfrom() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: sending '%c' to socket ...\\n\", token);\n  send(sock, &token, sizeof(token), 0);\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on recvfrom(&sock) */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: sending '%c' to socket ...\\n\", token);\n  send(sock, &token, sizeof(token), 0);\n  ++token;\n  atomic_puts(\"M:   ... done\");\n  {\n    struct mmsghdr mmsg;\n    struct iovec data;\n    int magic = msg_magic;\n#if defined(SYS_socketcall)\n    struct sendmmsg_arg arg;\n#endif\n\n    memset(&mmsg, 0, sizeof(mmsg));\n    memset(&data, 0, sizeof(data));\n    data.iov_base = &magic;\n    data.iov_len = sizeof(magic);\n    mmsg.msg_hdr.msg_iov = &data;\n    mmsg.msg_hdr.msg_iovlen = 1;\n\n    struct cmsghdr* cmptr = (struct cmsghdr*)xmalloc(CTRLMSG_LEN); // send a fd\n    cmptr->cmsg_level = SOL_SOCKET;\n    cmptr->cmsg_type = SCM_RIGHTS;\n    cmptr->cmsg_len = CTRLMSG_LEN;\n    mmsg.msg_hdr.msg_control = cmptr;\n    mmsg.msg_hdr.msg_controllen = CTRLMSG_LEN;\n    {\n      const int fd = STDERR_FILENO;\n      memcpy(CMSG_DATA(cmptr), &fd, sizeof(fd)); // send stderr as fd\n    }\n\n    /* Force a wait on recvmsg() */\n    atomic_puts(\"M: sleeping again ...\");\n    usleep(500000);\n    atomic_printf(\"M: sendmsg'ing 0x%x to socket ...\\n\", msg_magic);\n    sendmsg(sock, &mmsg.msg_hdr, 0);\n    atomic_puts(\"M:   ... done\");\n\n    /* Force a wait on recvmmsg() */\n    atomic_puts(\"M: sleeping again ...\");\n    usleep(500000);\n    atomic_printf(\"M: sendmmsg'ing 0x%x to socket ...\\n\", msg_magic);\n\n    breakpoint();\n\n    sendmmsg(sock, &mmsg, 1, 0);\n    atomic_printf(\"M:   ... sent %u bytes\\n\", mmsg.msg_len);\n\n    /* Force a wait on recvmmsg() */\n    atomic_puts(\"M: sleeping again ...\");\n    usleep(500000);\n    atomic_printf(\"M: sendmmsg'ing(by socketcall) 0x%x to socket ...\\n\",\n                  msg_magic);\n\n#if defined(SYS_socketcall)\n    memset(&arg, 0, sizeof(arg));\n    arg.sockfd = sock;\n    arg.msgvec = &mmsg;\n    arg.vlen = 1;\n    syscall(SYS_socketcall, SYS_SENDMMSG, (void*)&arg);\n#elif defined(SYS_sendmmsg)\n    syscall(SYS_sendmmsg, sock, &mmsg, 1, 0);\n#else\n#error unable to call sendmmsg\n#endif\n\n    free(cmptr);\n  }\n  {\n    struct msghdr msg;\n    struct iovec iovs[2];\n    char c1 = token++;\n    char c2 = token++;\n    memset(&msg, 0, sizeof(msg));\n\n    iovs[0].iov_base = &c1;\n    iovs[0].iov_len = sizeof(c1);\n    iovs[1].iov_base = &c2;\n    iovs[1].iov_len = sizeof(c2);\n\n    msg.msg_iov = iovs;\n    msg.msg_iovlen = sizeof(iovs) / sizeof(iovs[0]);\n\n    /* Force a wait on recvmsg(). */\n    atomic_puts(\"M: sleeping again ...\");\n    usleep(500000);\n    atomic_printf(\"M: writing { '%c', '%c' } to socket ...\\n\", c1, c2);\n    test_assert(2 == sendmsg(sock, &msg, 0));\n    atomic_puts(\"M:   ... done\");\n  }\n  /* Force a wait on poll() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  write(sock, &token, sizeof(token));\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on ppoll() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  write(sock, &token, sizeof(token));\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on select(), raw syscall */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  write(sock, &token, sizeof(token));\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on select(), library call */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  write(sock, &token, sizeof(token));\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on epoll_wait() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  write(sock, &token, sizeof(token));\n  ++token;\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on write() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: reading socket ...\\n\");\n  ++token;\n  {\n    char* buf = (char*)xmalloc(num_sockbuf_bytes);\n    int i;\n    for (i = 0; i < 2; ++i) {\n      read_all_chunks(sock, buf, num_sockbuf_bytes, token);\n      ++token;\n    }\n    free(buf);\n  }\n  atomic_puts(\"M:   ... done\");\n\n  /* Force a wait on read() */\n  atomic_puts(\"M: sleeping again ...\");\n  usleep(500000);\n  atomic_printf(\"M: writing '%c' to socket ...\\n\", token);\n  write(sock, &token, sizeof(token));\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/block_clone_checkpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_SIZE 0x20000\n\nstatic void breakpoint(void) { event_syscall(); }\n\nint main(void) {\n  int i;\n  int fd = open(\"tmp.txt\", O_RDWR | O_CREAT | O_EXCL, 0600);\n  char buf[BUF_SIZE];\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(\"tmp.txt\"));\n  for (i = 1; i <= 10; ++i) {\n    memset(buf, i, sizeof(buf));\n    test_assert(sizeof(buf) == write(fd, buf, sizeof(buf)));\n  }\n\n  test_assert(0 == lseek(fd, 0, SEEK_SET));\n  memset(buf, 0, sizeof(buf));\n  for (i = 1; i <= 10; ++i) {\n    test_assert(sizeof(buf) == read(fd, buf, sizeof(buf)));\n    test_assert(buf[0] == i);\n    test_assert(buf[sizeof(buf) - 1] == i);\n    breakpoint();\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/block_clone_checkpoint.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('restart 1')\nexpect_gdb('breakpoint')\n\nsend_gdb('disable')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/block_clone_checkpoint.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n\n"
  },
  {
    "path": "src/test/block_clone_interrupted.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_COUNT (int)(0x20000 / sizeof(int))\n#define FILE_BUFS 10\n#define ITERATIONS 100\n\nint main(void) {\n  int i, j, count;\n  int fd = open(\"tmp.txt\", O_RDWR | O_CREAT | O_EXCL, 0600);\n  int buf[BUF_COUNT];\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(\"tmp.txt\"));\n  count = 0;\n  for (i = 0; i < FILE_BUFS; ++i) {\n    for (j = 0; j < BUF_COUNT; ++j) {\n      buf[j] = count++;\n    }\n    test_assert(sizeof(buf) == write(fd, buf, sizeof(buf)));\n  }\n\n  for (i = 0; i < ITERATIONS; ++i) {\n    count = 0;\n    test_assert(0 == lseek(fd, 0, SEEK_SET));\n    for (j = 0; j < FILE_BUFS; ++j) {\n      memset(buf, 0, sizeof(buf));\n      test_assert(sizeof(buf) == read(fd, buf, sizeof(buf)));\n      test_assert(buf[0] == count);\n      test_assert(buf[BUF_COUNT - 1] == count + BUF_COUNT - 1);\n      count += BUF_COUNT;\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/block_clone_interrupted.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c100\"\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/block_clone_syscallbuf_overflow.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_COUNT (int)(0x20000 / sizeof(int))\n#define FILE_BUFS 10\n#define ITERATIONS 100\n\nint main(void) {\n  int i, j, count;\n  int fd = open(\"tmp.txt\", O_RDWR | O_CREAT | O_EXCL, 0600);\n  int buf[BUF_COUNT];\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(\"tmp.txt\"));\n  count = 0;\n  for (i = 0; i < FILE_BUFS; ++i) {\n    for (j = 0; j < BUF_COUNT; ++j) {\n      buf[j] = count++;\n    }\n    test_assert(sizeof(buf) == write(fd, buf, sizeof(buf)));\n  }\n\n  for (i = 0; i < ITERATIONS; ++i) {\n    count = BUF_COUNT;\n    test_assert(sizeof(buf) == lseek(fd, sizeof(buf), SEEK_SET));\n    for (j = 1; j < FILE_BUFS; ++j) {\n      memset(buf, 0, sizeof(buf));\n      test_assert(sizeof(buf) == read(fd, buf, sizeof(buf)));\n      test_assert(buf[0] == count);\n      test_assert(buf[BUF_COUNT - 1] == count + BUF_COUNT - 1);\n      count += BUF_COUNT;\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/block_clone_syscallbuf_overflow.run",
    "content": "source `dirname $0`/util.sh\n\n# Use 4K syscallbuf size to force frequent overflows\nRECORD_ARGS=--syscall-buffer-size=4\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/block_intr_sigchld.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS 10\n#define NUM_PROCS_PER_ITERATION 10\n#define MAGIC_EXIT_CODE 42\n\nstatic int sockfds[2];\n\nconst ssize_t num_sockbuf_bytes = 1 << 20;\n\nstatic void child_proc(void) { exit(MAGIC_EXIT_CODE); }\n\nstatic void* writer_thread(__attribute__((unused)) void* dontcare) {\n  char token = '!';\n  int sock = sockfds[1];\n  int i;\n\n  for (i = 0; i < NUM_ITERATIONS; ++i) {\n    /* Force a wait on read() */\n    atomic_printf(\"w: iteration %d: sleeping ...\\n\", i);\n    usleep(500000);\n    atomic_printf(\"w: writing '%c' to socket ...\\n\", token);\n    write(sock, &token, sizeof(token));\n    ++token;\n    atomic_puts(\"w:   ... done\");\n  }\n  atomic_puts(\"w:   ... done\");\n  return NULL;\n}\n\nint main(void) {\n  char token = '!';\n  char c = '\\0';\n  pthread_t t;\n  int sock;\n  int i;\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n  sock = sockfds[0];\n\n  pthread_create(&t, NULL, writer_thread, NULL);\n\n  for (i = 0; i < NUM_ITERATIONS; ++i) {\n    pid_t procs[NUM_PROCS_PER_ITERATION];\n    int j;\n\n    atomic_printf(\"M: iteration %d: forking processes before read ...\\n\", i);\n    for (j = 0; j < NUM_PROCS_PER_ITERATION; ++j) {\n      if (0 == (procs[j] = fork())) {\n        child_proc();\n        test_assert(\"Not reached\" && 0);\n      }\n    }\n\n    atomic_printf(\"M: sleeping for a bit ...\");\n    usleep(10000);\n\n    atomic_printf(\"M: reading socket ...\\n\");\n    test_assert(1 == read(sock, &c, sizeof(c)));\n    atomic_printf(\"M:   ... read '%c'\\n\", c);\n    test_assert(c == token);\n    ++token;\n\n    for (j = 0; j < NUM_PROCS_PER_ITERATION; ++j) {\n      int status;\n      int child = procs[j];\n      int pid = waitpid(child, &status, 0);\n      int err = errno;\n      atomic_printf(\"M:  waitpid(%d) returns %d(%s) and status %#x\\n\", child,\n                    pid, strerror(err), status);\n      test_assert(child == pid);\n      test_assert(WIFEXITED(status) && MAGIC_EXIT_CODE == WEXITSTATUS(status));\n    }\n  }\n  atomic_printf(\"M: ... done\\n\");\n\n  pthread_join(t, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/block_intr_sigchld.run",
    "content": "source `dirname $0`/util.sh\n\n# The underlying failure here is difficult to reproduce without a lot\n# of tracee concurrency.\nRECORD_ARGS=\"-s\"\n\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/block_open.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int try_open(int flags) { return open(\"fifo\", flags); }\n\nstatic int try_openat(int flags) { return openat(AT_FDCWD, \"fifo\", flags); }\n\nstatic void do_test(int (*func)(int)) {\n  pid_t child;\n  int fd;\n  int status;\n  int ret = mkfifo(\"fifo\", 0600);\n  test_assert(ret == 0);\n\n  child = fork();\n  if (!child) {\n    fd = func(O_WRONLY);\n    test_assert(fd >= 0);\n    test_assert(0 == close(fd));\n    exit(77);\n  }\n\n  fd = func(O_RDONLY);\n  test_assert(fd >= 0);\n  test_assert(0 == close(fd));\n  unlink(\"fifo\");\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n}\n\nint main(void) {\n  do_test(try_open);\n  do_test(try_openat);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/blocked_bad_ip.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void fault_handler(__attribute__((unused)) int sig,\n                          __attribute__((unused)) siginfo_t* si,\n                          __attribute__((unused)) void* context) {\n  atomic_puts(\"FAILED: handler should not have been called for blocked signal\");\n}\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  sigset_t s;\n\n  syscall(SYS_write, STDOUT_FILENO, \"EXIT-\", (size_t)5);\n\n  sigemptyset(&s);\n  sigaddset(&s, SIGSEGV);\n  sigprocmask(SIG_BLOCK, &s, NULL);\n\n  syscall(SYS_write, STDOUT_FILENO, \"SUCCESS\\n\", (size_t)8, 9, 10, 11);\n\n  ((void (*)(void))(0x44))();\n\n  return NULL;\n}\n\nint main(void) {\n  struct sigaction act;\n  pthread_t thread;\n\n  act.sa_sigaction = fault_handler;\n  act.sa_flags = SA_SIGINFO | SA_NODEFER;\n  sigemptyset(&act.sa_mask);\n  sigaction(SIGSEGV, &act, NULL);\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  pthread_join(thread, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/blocked_bad_ip.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('SIGSEGV')\n\nsend_gdb('reverse-stepi')\nexpect_gdb('SIGSEGV')\n\nsend_gdb('reverse-stepi')\nexpect_gdb('start_thread')\n\nok()\n"
  },
  {
    "path": "src/test/blocked_bad_ip.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/blocked_sigill.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void fault_handler(__attribute__((unused)) int sig,\n                          __attribute__((unused)) siginfo_t* si,\n                          __attribute__((unused)) void* context) {\n  atomic_puts(\"FAILED: handler should not have been called for blocked signal\");\n}\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  sigset_t s;\n\n  sigemptyset(&s);\n  sigaddset(&s, SIGILL);\n  sigprocmask(SIG_BLOCK, &s, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  undefined_instr();\n\n  return NULL;\n}\n\nint main(void) {\n  struct sigaction act;\n  pthread_t thread;\n\n  act.sa_sigaction = fault_handler;\n  act.sa_flags = SA_SIGINFO | SA_NODEFER;\n  sigemptyset(&act.sa_mask);\n  sigaction(SIGILL, &act, NULL);\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  pthread_join(thread, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/blocked_sigill.run",
    "content": "source `dirname $0`/util.sh\n( record $TESTNAME ) >& /dev/null\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/bpf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n\n#include <linux/bpf.h>\n\nint bpf(int cmd, union bpf_attr *attr, unsigned int size)\n{\n  return syscall(__NR_bpf, cmd, attr, size);\n}\n\nint main(void) {\n  union bpf_attr attr;\n\n  {\n    const char* filename = \"foo\";\n    memset(&attr, 0, sizeof(attr));\n    attr.pathname = (__u64)(uintptr_t)filename;\n    bpf(RR_BPF_OBJ_GET, &attr, 1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/bpf_map.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n\n#include <linux/bpf.h>\n\nint bpf(int cmd, union bpf_attr *attr, unsigned int size)\n{\n  return syscall(__NR_bpf, cmd, attr, size);\n}\n\nint main(void) {\n  union bpf_attr attr;\n  int map_fd;\n  uint32_t key = 99;\n  uint32_t unknown_key = 0;\n  uint32_t* next_key;\n  uint64_t value = 1234567;\n  uint64_t* value_out;\n  int ret;\n  memset(&attr, 0, sizeof(attr));\n\n  attr.map_type = BPF_MAP_TYPE_HASH;\n  attr.key_size = sizeof(key);\n  attr.value_size = sizeof(value);\n  attr.max_entries = 10;\n  map_fd = bpf(RR_BPF_MAP_CREATE, &attr, sizeof(attr));\n  if (map_fd < 0) {\n    if (errno == ENOSYS) {\n      atomic_puts(\"bpf syscall not supported\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    if (errno == EPERM) {\n      atomic_puts(\"Skipping test because it requires CAP_SYS_ADMIN\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n  }\n  test_assert(map_fd >= 0);\n\n  attr.map_fd = map_fd;\n  attr.key = (uintptr_t)&key;\n  attr.value = (uintptr_t)&value;\n  attr.flags = BPF_ANY;\n  ret = bpf(RR_BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));\n\n  ALLOCATE_GUARD(value_out, 'a');\n  attr.value = (uintptr_t)value_out;\n  ret = bpf(RR_BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));\n  test_assert(0 == ret);\n  VERIFY_GUARD(value_out);\n  test_assert(value == *value_out);\n\n  ALLOCATE_GUARD(next_key, 'b');\n  attr.key = (uintptr_t)&unknown_key;\n  attr.next_key = (uintptr_t)next_key;\n  ret = bpf(RR_BPF_MAP_GET_NEXT_KEY, &attr, sizeof(attr));\n  test_assert(0 == ret);\n  VERIFY_GUARD(next_key);\n  test_assert(key == *next_key);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/bpf_prog_map.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n#include \"nsutils.h\"\n\n#include <stdint.h>\n#include <sched.h>\n#include <linux/bpf.h>\n\n#define MAX_PROG_CNT 1\n#define ATTACH_TYPE 17 // BPF_FLOW_DISSECTOR\n#define PROG_TYPE 22 // BPF_PROG_TYPE_FLOW_DISSECTOR\n\nint bpf(int cmd, union bpf_attr *attr, unsigned int size) {\n  return syscall(__NR_bpf, cmd, attr, size);\n}\n\nconst struct bpf_insn bpf_program[] = {\n  // mov r0, 0\n  { .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 0, .imm = 0 },\n  // exit\n  { .code = BPF_JMP | BPF_EXIT },\n};\n\nint main(void) {\n  if (try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"Skipping test because try_setup_ns failed\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int netns_fd = open(\"/proc/self/ns/net\", O_RDONLY);\n  test_assert(netns_fd > 0);\n\n  // load and add a program to the cgroup\n  static char log_buf[4096] = {};\n  union bpf_attr prog_attr = {\n    .insn_cnt = 2,\n    .insns = (uintptr_t)bpf_program,\n    .license = (uintptr_t)\"MIT\",\n    .prog_type = PROG_TYPE,\n    .log_size = sizeof(log_buf),\n    .log_buf = (uintptr_t)log_buf,\n    .log_level = 1,\n  };\n  const int offset_of_attach_prog_fd = 112;\n  size_t prog_attr_size = offset_of_attach_prog_fd + sizeof(__u32);\n  int prog = bpf(RR_BPF_PROG_LOAD, &prog_attr, prog_attr_size);\n  if (prog < 0) {\n    if (errno == ENOSYS) {\n      atomic_puts(\"bpf syscall not supported\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    if (errno == EPERM) {\n      atomic_puts(\"Skipping test because it requires CAP_SYS_ADMIN\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    atomic_puts(log_buf);\n    test_assert(0 && \"failed to load program\");\n  }\n  test_assert(prog > 0);\n\n  union bpf_attr* map_attr;\n  ALLOCATE_GUARD(map_attr, 'a');\n  memset(map_attr, 0, sizeof(*map_attr));\n  uint32_t key = 99;\n  uint64_t value = 1234567;\n  map_attr->map_type = BPF_MAP_TYPE_HASH;\n  map_attr->key_size = sizeof(key);\n  map_attr->value_size = sizeof(value);\n  map_attr->max_entries = 10;\n  int map_fd = bpf(RR_BPF_MAP_CREATE, map_attr, sizeof(*map_attr));\n  test_assert(map_fd >= 0);\n  VERIFY_GUARD(map_attr);\n\n  memset(map_attr, 0, sizeof(*map_attr));\n  struct {\n    uint32_t prog_fd;\n    uint32_t map_fd;\n    uint32_t flags;\n  } prog_bind_map;\n  prog_bind_map.map_fd = map_fd;\n  prog_bind_map.prog_fd = prog;\n  memcpy(map_attr, &prog_bind_map, sizeof(prog_bind_map));\n  int ret = bpf(RR_BPF_PROG_BIND_MAP, map_attr, sizeof(*map_attr));\n  test_assert(ret == 0 || errno == EINVAL);\n  VERIFY_GUARD(map_attr);\n\n  memset(map_attr, 0, sizeof(*map_attr));\n  map_attr->map_fd = map_fd;\n  ret = bpf(RR_BPF_MAP_FREEZE, map_attr, sizeof(*map_attr));\n  test_assert(ret == 0 || errno == EINVAL);\n  VERIFY_GUARD(map_attr);\n\n  struct bpf_prog_info* prog_info;\n  ALLOCATE_GUARD(prog_info, 'b');\n  memset(prog_info, 0, sizeof(*prog_info));\n  memset(map_attr, 0, sizeof(*map_attr));\n  map_attr->info.bpf_fd = prog;\n  map_attr->info.info_len = sizeof(*prog_info);\n  map_attr->info.info = (uintptr_t)prog_info;\n  ret = bpf(RR_BPF_OBJ_GET_INFO_BY_FD, map_attr, sizeof(*map_attr));\n  if (ret == 0) {\n    test_assert(prog_info->created_by_uid == getuid());\n  } else {\n    test_assert(errno == EINVAL);\n  }\n  VERIFY_GUARD(prog_info);\n\n  struct bpf_map_info* map_info;\n  ALLOCATE_GUARD(map_info, 'c');\n  memset(map_info, 0, sizeof(*map_info));\n  memset(map_attr, 0, sizeof(*map_attr));\n  map_attr->info.bpf_fd = map_fd;\n  map_attr->info.info_len = sizeof(*map_info);\n  map_attr->info.info = (uintptr_t)map_info;\n  ret = bpf(RR_BPF_OBJ_GET_INFO_BY_FD, map_attr, sizeof(*map_attr));\n  if (ret == 0) {\n    test_assert(map_info->type == BPF_MAP_TYPE_HASH);\n    atomic_printf(\"Map: %s key_size %d value_size %d\\n\",\n                  map_info->name, map_info->key_size, map_info->value_size);\n  } else {\n    test_assert(errno == EINVAL);\n  }\n  VERIFY_GUARD(map_info);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/bpf_query.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n#include \"nsutils.h\"\n\n#include <stdint.h>\n#include <sched.h>\n#include <linux/bpf.h>\n\n\n#define MAX_PROG_CNT 1\n#define ATTACH_TYPE 17 // BPF_FLOW_DISSECTOR\n#define PROG_TYPE 22 // BPF_PROG_TYPE_FLOW_DISSECTOR\n\n\nint bpf(int cmd, union bpf_attr *attr, unsigned int size) {\n  return syscall(__NR_bpf, cmd, attr, size);\n}\n\nconst struct bpf_insn bpf_program[] = {\n  // mov r0, 0\n  { .code = BPF_ALU | BPF_MOV | BPF_K, .dst_reg = 0, .imm = 0 },\n  // exit\n  { .code = BPF_JMP | BPF_EXIT },\n};\n\nint main(void) {\n  __u32 prog_ids[MAX_PROG_CNT];\n\n  if (try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int netns_fd = open(\"/proc/self/ns/net\", O_RDONLY);\n  test_assert(netns_fd > 0);\n\n  union bpf_attr query_attr = {\n    .query = {\n      .prog_ids = (uintptr_t)&prog_ids,\n      .target_fd = netns_fd,\n    },\n  };\n\n\n  // query cgroups bpf programs. at first, no programs are attached\n  query_attr.query.prog_cnt = 2;\n  query_attr.query.attach_type = ATTACH_TYPE;\n  if (bpf(RR_BPF_PROG_QUERY, &query_attr, sizeof(query_attr.query)) != 0) {\n    if (errno == ENOSYS) {\n      atomic_puts(\"Skipping test because bpf is not supported\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    if (errno == EPERM) {\n      // we have to check for EPERM again as a kernel can be built with\n      // user namespaces, so unshare can succeed regardless of CAP_SYS_ADMIN\n      atomic_puts(\"Skipping test because it requires CAP_SYS_ADMIN\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    test_assert(0 && \"bpf(RR_BPF_PROG_QUERY) failed\");\n  }\n  test_assert(query_attr.query.prog_cnt == 0);\n\n  // load and add a program to the cgroup\n  static char log_buf[4096] = {};\n  union bpf_attr prog_attr = {\n    .insn_cnt = 2,\n    .insns = (uintptr_t)bpf_program,\n    .license = (uintptr_t)\"MIT\",\n    .prog_type = PROG_TYPE,\n    .log_size = sizeof(log_buf),\n    .log_buf = (uintptr_t)log_buf,\n    .log_level = 1,\n  };\n  const int offset_of_attach_prog_fd = 112;\n  size_t prog_attr_size = offset_of_attach_prog_fd + sizeof(__u32);\n  int prog = bpf(RR_BPF_PROG_LOAD, &prog_attr, prog_attr_size);\n  if (prog < 0) {\n    atomic_puts(log_buf);\n    test_assert(0 && \"failed to load program\");\n  }\n  test_assert(prog > 0);\n\n  union bpf_attr attach_attr = {\n    .attach_type = ATTACH_TYPE,\n  };\n  const int offset_of_replace_bpf_fd = 112;\n  size_t attach_attr_size = offset_of_replace_bpf_fd + sizeof(__u32);\n  attach_attr.attach_bpf_fd = prog;\n  test_assert(bpf(RR_BPF_PROG_ATTACH, &attach_attr, attach_attr_size) == 0);\n\n  // query again\n  query_attr.query.prog_cnt = 1;\n  query_attr.query.attach_type = ATTACH_TYPE;\n  test_assert(bpf(RR_BPF_PROG_QUERY, &query_attr, sizeof(query_attr.query)) == 0);\n  test_assert(query_attr.query.prog_cnt == 1); // the kernel sets this field\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/break_block.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nfor i in range(2):\n    send_gdb('c')\n    expect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/break_block.run",
    "content": "source `dirname $0`/util.sh\nrecord block$bitness\ndebug_gdb_only break_block\n"
  },
  {
    "path": "src/test/break_clock.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nfor i in range(3):\n    send_gdb('c')\n    expect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/break_clock.run",
    "content": "source `dirname $0`/util.sh\nrecord clock$bitness\ndebug_gdb_only break_clock\n"
  },
  {
    "path": "src/test/break_clone.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nfor i in range(3):\n    send_gdb('c')\n    expect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/break_clone.run",
    "content": "source `dirname $0`/util.sh\nrecord clone$bitness\ndebug_gdb_only break_clone\n"
  },
  {
    "path": "src/test/break_exec.run",
    "content": "source `dirname $0`/util.sh\nrecord exec_self$bitness\ndebug_gdb_only generic_break\n"
  },
  {
    "path": "src/test/break_int3.py",
    "content": "from util import *\n\nsend_gdb('b int3.c:6')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/break_int3.run",
    "content": "source `dirname $0`/util.sh\n\nrecord int3$bitness\ndebug_gdb_only break_int3\n"
  },
  {
    "path": "src/test/break_mmap_private.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nfor i in range(3):\n    send_gdb('c')\n    expect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/break_mmap_private.run",
    "content": "source `dirname $0`/util.sh\nrecord mmap_private$bitness\ndebug_gdb_only break_mmap_private\ndebug_gdb_only break_mmap_private --share-private-mappings\n"
  },
  {
    "path": "src/test/break_msg.run",
    "content": "source `dirname $0`/util.sh\nrecord msg$bitness\ndebug_gdb_only generic_break\n"
  },
  {
    "path": "src/test/break_sigreturn.run",
    "content": "source `dirname $0`/util.sh\nrecord intr_sleep$bitness\ndebug_gdb_only generic_break\n"
  },
  {
    "path": "src/test/break_sync_signal.run",
    "content": "source `dirname $0`/util.sh\nrecord segfault$bitness\ndebug_gdb_only generic_break\n"
  },
  {
    "path": "src/test/break_thread.run",
    "content": "source `dirname $0`/util.sh\nrecord barrier$bitness\ndebug_gdb_only generic_break\n"
  },
  {
    "path": "src/test/break_time_slice.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('c')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/break_time_slice.run",
    "content": "source `dirname $0`/util.sh\nrecord chew_cpu$bitness\ndebug_gdb_only break_time_slice\n"
  },
  {
    "path": "src/test/breakpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void C(void) { atomic_puts(\"in C\"); }\n\n// In our test driver, we rely on the debugger stopping\n// on the first call inside the function. However, different\n// versions of gdb/gcc are inconsistent about whether the breakpoint\n// for the function is on the same line as the opening brace or the\n// first statement in the function, so make sure they're on the same\n// line irrespective of our usual style guide.\nstatic void B(void)\n{ atomic_puts(\"calling C\");\n  C();\n  atomic_puts(\"finished C\");\n}\n\nstatic void A(void)\n{ atomic_puts(\"calling B\");\n  B();\n  atomic_puts(\"finished B\");\n}\n\nint main(void) {\n  atomic_puts(\"calling A\");\n  A();\n  atomic_puts(\"finished A\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/breakpoint.py",
    "content": "from util import *\n\nbreakpoint = breakpoint_at_function('C')\ncont()\n\nexpect_rr('calling C')\nexpect_breakpoint_stop(breakpoint)\n\nbacktrace()\nexpect_debugger('#0[^C]+C[^#]+#1[^B]+B[^#]+#2[^A]+A[^#]+#3.+main')\n\nok()\n"
  },
  {
    "path": "src/test/breakpoint.run",
    "content": "source `dirname $0`/util.sh\ndebug_test\n"
  },
  {
    "path": "src/test/breakpoint_conditions.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpointA(__attribute__((unused)) int v4) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void breakpointB(__attribute__((unused)) int v4) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint v0 = 0;\nint v1 = 1;\nint v2 = 2;\nint v3 = 3;\nint vm1 = -1;\nint vm2 = -2;\nuint64_t u64max = (uint64_t)(int64_t)-1;\nint* p = (int*)&u64max;\n\nint main(void) {\n  int i;\n  for (i = 0; i < 10000; ++i) {\n    breakpointA(4);\n    breakpointB(4);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/breakpoint_conditions.py",
    "content": "from util import *\n\ndef test_cond(c):\n    send_gdb('python gdb.execute(\"cond 1 %s\"); gdb.execute(\"cond 2 !(%s)\"); gdb.execute(\"c\")' % (c, c))\n    expect_gdb('Breakpoint 1')\n\nsend_gdb('b breakpointA')\nexpect_gdb('Breakpoint 1')\nsend_gdb('b breakpointB')\nexpect_gdb('Breakpoint 2')\n\ntest_cond('v1==1')\ntest_cond('v1!=2')\ntest_cond('v4==4')\ntest_cond('v1+v2==3')\ntest_cond('v2-1==v1')\ntest_cond('v3-v2==1')\ntest_cond('v4>>2==v1')\ntest_cond('v1<<2==v4')\ntest_cond('(unsigned char)u64max==255')\ntest_cond('v2*v2==4')\ntest_cond('v4/v2==2')\ntest_cond('v4/vm2==-2')\ntest_cond('v3%v2==1')\ntest_cond('v3%vm2==1')\ntest_cond('!v1==v0')\ntest_cond('v1|v2==3')\ntest_cond('v3&v2==2')\ntest_cond('v3^v2==1')\ntest_cond('~v0==(int)u64max')\ntest_cond('v0?v1:v2==2')\ntest_cond('*p==(int)u64max')\ntest_cond('*(unsigned char*)p==255')\ntest_cond('*(short int*)p==-1')\ntest_cond('*(long long*)p==(long long)u64max')\n\nok()\n"
  },
  {
    "path": "src/test/breakpoint_conditions.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/breakpoint_consistent.py",
    "content": "from util import *\n\nsend_gdb('b C')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2, main')\n\nsend_gdb('cond 1 rand()&1 < 10')\n\nsend_gdb('c')\n\nexpect_rr('calling C')\n\nexpect_gdb('Breakpoint 1(.*) C')\n\nsend_gdb('check')\nsend_gdb('c')\nexpect_rr('finished C')\n\nok()\n"
  },
  {
    "path": "src/test/breakpoint_consistent.run",
    "content": "source `dirname $0`/util.sh\nrecord breakpoint$bitness\ndebug_gdb_only breakpoint_consistent\n"
  },
  {
    "path": "src/test/breakpoint_overlap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* This is a difficult bug to trigger because we need to set a breakpoint\n   where a SCHED event will stop, and the breakpoint has to fire exactly at the\n   moment the SCHED event fires. So we need a SCHED event to fire at a location\n   when it's the first time we've executed that location.\n   Setting the context switch time to something small-ish like -c100 should\n   help.\n   Then we generate a lot of conditional branches.\n*/\n\n#define STATEMENT(i)                                                           \\\n  if (a * (i) < b) {                                                           \\\n    ++a;                                                                       \\\n  } else {                                                                     \\\n    ++b;                                                                       \\\n  }\n#define STATEMENT2(i) STATEMENT(i) STATEMENT(i + 1)\n#define STATEMENT4(i) STATEMENT2(i) STATEMENT2(i + 2)\n#define STATEMENT8(i) STATEMENT4(i) STATEMENT4(i + 4)\n#define STATEMENT16(i) STATEMENT8(i) STATEMENT8(i + 8)\n#define STATEMENT32(i) STATEMENT16(i) STATEMENT16(i + 16)\n#define STATEMENT64(i) STATEMENT32(i) STATEMENT32(i + 32)\n#define STATEMENT128(i) STATEMENT64(i) STATEMENT64(i + 64)\n#define STATEMENT256(i) STATEMENT128(i) STATEMENT128(i + 128)\n#define STATEMENT512(i) STATEMENT256(i) STATEMENT256(i + 256)\n#define STATEMENT1024(i) STATEMENT512(i) STATEMENT512(i + 512)\n#define STATEMENT2048(i) STATEMENT1024(i) STATEMENT1024(i + 1024)\n#define STATEMENT4096(i) STATEMENT2048(i) STATEMENT2048(i + 2048)\n\nstatic volatile int blah = 0;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (blah < 1000000) {\n    ++blah;\n  }\n  return NULL;\n}\n\nint main(__attribute__((unused)) int argc, char* argv[]) {\n  int a = atoi(argv[1]);\n  int b = atoi(argv[2]);\n  pthread_t thread;\n\n  /* Create an extra thread so context switches can happen\n     and SCHED events will be recorded. */\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  /* This syscall signals the test that we're in the test body proper */\n  event_syscall();\n  STATEMENT4096(0)\n  return a + b;\n}\n"
  },
  {
    "path": "src/test/breakpoint_overlap.py",
    "content": "import collections\nimport sys\nimport re\nfrom util import *\n\narch = get_exe_arch()\n\nArchInfo = collections.namedtuple('ArchInfo', ['ip_name'])\nregex_info = {\n    'i386': ArchInfo('eip'),\n    'i386:x86-64': ArchInfo('rip'),\n    'aarch64': ArchInfo('pc'),\n}\n\nsyscall_re = re.compile(r'''`SYSCALL: <unknown-syscall--1>' \\(state:EXITING_SYSCALL\\)''')\nsched_re = re.compile(r'`SCHED')\neip_re = re.compile(r'%s:(0x[a-f0-9]+)' % regex_info[arch].ip_name)\n\nsched_enabled = False\neip_enabled = False\neip = None\nwhile True:\n    line = sys.stdin.readline()\n    if not line:\n        break\n    if syscall_re.search(line):\n        sched_enabled = True\n    if sched_enabled and sched_re.search(line):\n        eip_enabled = True\n    if eip_enabled:\n        m = eip_re.search(line)\n        if m:\n            eip = m.group(1)\n            break\n\nif eip is None:\n    failed('%s not found' % regex_info[arch].ip_name)\n\n# The SCHED after getgid may land in libc, which might not be loaded yet, in\n# which case setting a breakpoint there will cause gdb to barf. So run to\n# 'main' at which point libc is definitely loaded.\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b *%s'%eip)\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\nexpect_gdb('(rr)')\n\nif arch == 'aarch64':\n    send_gdb('p/x *(uint32_t*)$pc')\n    expect_gdb('0x([a-f0-9]+)')\n    if last_match().group(1) == 'd4200000':\n        failed('saw breakpoint at current instruction')\nelif arch == 'i386' or arch == 'i386:x86-64':\n    send_gdb('p/x *(char*)$pc')\n    expect_gdb('0x([a-f0-9]+)')\n    if last_match().group(1) == 'cc':\n        failed('saw breakpoint at current instruction')\nelse:\n    failed('Add check for this architecture')\n\nok()\n"
  },
  {
    "path": "src/test/breakpoint_overlap.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c100\"\nrecord breakpoint_overlap$bitness 3 4\n# Don't use pipes here since we need 'debug' to run in the same bash process\nrr --suppress-environment-warnings dump $workdir/latest-trace > $workdir/plaintext-trace\ndebug_gdb_only breakpoint_overlap < $workdir/plaintext-trace\n"
  },
  {
    "path": "src/test/breakpoint_print.py",
    "content": "from util import *\nimport re\n\nbp = breakpoint_at_function('main')\nset_breakpoint_commands(bp, ['print 123 + 456'])\ncont()\nexpect_debugger('579')\n\nok()\n"
  },
  {
    "path": "src/test/breakpoint_print.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug breakpoint_print\n"
  },
  {
    "path": "src/test/breakpoint_print_command.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('commands 1')\nsend_gdb('p 1234')\nsend_gdb('end')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nexpect_gdb('1234')\n\nok()\n"
  },
  {
    "path": "src/test/breakpoint_print_command.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only breakpoint_print_command\n"
  },
  {
    "path": "src/test/brk.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  void* prev;\n  void* start = sbrk(0);\n  test_assert((intptr_t)start != -1);\n  void* start_after_allocation = sbrk(111);\n  if (start_after_allocation == (void*)-1) {\n    // We have seen an intermittent failure here on 32-bit :-(\n    test_assert(errno == ENOMEM);\n    test_assert(sizeof(void*) == 4);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(start == start_after_allocation);\n  memset(start, 0xaa, 111);\n\n  prev = sbrk(1000000);\n  if (prev == (void*)-1) {\n    test_assert(errno == ENOMEM);\n    test_assert(sizeof(void*) == 4);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0 == brk(prev));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/brk2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  long pagesize = sysconf(_SC_PAGESIZE);\n  long pagemask = pagesize - 1;\n  long offset = pagesize + 1000;\n  void* start = (void*)syscall(SYS_brk, (void*)0);\n  void* p = (void*)syscall(SYS_brk, start + offset);\n  int res;\n  void* pp;\n  void* q;\n  void* r;\n\n  res = mprotect((void*)(((long)start + pagesize - 1) & ~pagemask), pagesize, PROT_READ);\n  test_assert(res == 0);\n\n  pp = (void*)syscall(SYS_brk, (void*)0);\n  test_assert(pp == p);\n\n  *(char*)p = 77;\n  q = (void*)syscall(SYS_brk, p + offset);\n  test_assert(p + offset == q);\n  test_assert(*(char*)p == 77);\n\n  r = (void*)syscall(SYS_brk, start + 1);\n  test_assert(start < r);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/call_exit.py",
    "content": "import sys\nfrom util import *\n\ngdb_version = get_gdb_version()\nif gdb_version < 10:\n    # On gdb 9.2 after calling exit(0)\n    # gdb's internal state is confused\n    # about which thread we're on, and\n    # the 'finish' command fails.\n    send_gdb('c')\n    expect_gdb('EXIT-SUCCESS')\n    ok()\n    sys.exit(0)\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, main')\n\n# Step over the breakpoint and into `atomic_puts' to make sure it\n# doesn't influence the test.\nsend_gdb('step')\nexpect_gdb('atomic_puts \\\\(str=')\n\nsend_gdb('call (int)exit(0)')\nexpect_gdb('while in a function called from GDB')\n\n# Check sure we're still in the frame of `atomic_puts' and can still\n# continue the replay.\nsend_gdb('finish')\nexpect_gdb('EXIT-SUCCESS')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1, main')\n\nok()\n"
  },
  {
    "path": "src/test/call_exit.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only call_exit\n"
  },
  {
    "path": "src/test/call_function.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int var;\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nvoid mutate_var(void) {\n  var = 22;\n  atomic_printf(\"var is %d\\n\", var);\n}\n\nvoid print_nums(void) {\n  int i;\n  for (i = 1; i <= 5; ++i) {\n    atomic_printf(\"%d \", i);\n  }\n  atomic_puts(\"\");\n}\n\nvoid alloc_and_print(void) {\n  static const int num_bytes = 4096;\n  char* str = mmap(NULL, num_bytes, PROT_WRITE | PROT_READ,\n                   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  snprintf(str, num_bytes, \"Hello %d\", var);\n  atomic_puts(str);\n\n  munmap(str, num_bytes);\n}\n\nvoid make_unhandled_syscall(void) {\n  ssize_t ret = kill(getpid(), SIGKILL);\n  /* XXX the error return is somewhat arbitrary here, but as\n   * long as |splice()| remains unimplemented in experiment\n   * mode, it's reasonable to assume that the libc wrapper will\n   * return -1 back to us. */\n  atomic_printf(\"return from kill: %zd\\n\", ret);\n}\n\nvoid print_time(void) {\n  struct timespec ts = { -1, -1 };\n  double now_sec;\n\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n  now_sec = (double)ts.tv_sec + (double)ts.tv_nsec / 1e9;\n  atomic_printf(\"now is %g sec\\n\", now_sec);\n}\n\nstatic void make_stack_executable(void) {\n  int v = 0;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p = (void*)((uintptr_t)&v & ~((uintptr_t)page_size - 1));\n  int ret = mprotect(p, page_size, PROT_READ | PROT_WRITE | PROT_EXEC);\n  test_assert(ret == 0 || errno == EACCES);\n}\n\ndouble xmm_arg(double d) {\n  return d * 2;\n}\n\nint main(void) {\n  var = -42;\n\n  breakpoint();\n\n  atomic_printf(\"var is %d\\n\", var);\n  test_assert(var == -42);\n\n  make_stack_executable();\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n\n  /* not reached */\n  mutate_var();\n  print_nums();\n  alloc_and_print();\n  make_unhandled_syscall();\n  print_time();\n  xmm_arg(0);\n}\n"
  },
  {
    "path": "src/test/call_function.py",
    "content": "from util import *\n\ndef do_tests():\n    expect_gdb('Breakpoint 1, breakpoint')\n\n    send_gdb('call mutate_var()')\n    expect_gdb('var is 22')\n\n    send_gdb('call print_nums()')\n    expect_gdb('1 2 3 4 5')\n\n    send_gdb('call alloc_and_print()')\n    expect_gdb('Hello 22')\n\n    send_gdb('call make_unhandled_syscall()')\n    expect_gdb('return from kill: -1')\n\n    send_gdb('call print_time()')\n    expect_gdb(r'now is \\d+(\\.\\d+(e\\+\\d\\d)?)? sec')\n\n    send_gdb('call xmm_arg(3.14159)')\n    expect_gdb('6.28317')\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\n\n# first set of tests use regular (hopefully not-executable) stack\ndo_tests()\n\nsend_gdb('c')\nexpect_rr('var is -42')\n# repeat the tests with executable stack\ndo_tests()\n\n# make sure we didn't crash\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/call_function.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/call_gettid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pid_t pid;\nstatic pid_t tid;\n\nvoid check_pid(void) {\n  assert(pid == getpid());\n  atomic_puts(\"SUCCESS\");\n}\n\nvoid check_tid(void) {\n  assert(tid == sys_gettid());\n  atomic_puts(\"SUCCESS\");\n}\n\nvoid breakpoint(void) {}\n\nstatic void* thread(__attribute__((unused)) void* dontcare) {\n  pid = getpid();\n  tid = sys_gettid();\n\n  breakpoint();\n  breakpoint();\n\n  return NULL;\n}\n\nint main(void) {\n  pthread_t t;\n  /* Switch to another thread so we can have distinct pid/tids. */\n  pthread_create(&t, NULL, thread, NULL);\n  pthread_join(t, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n\n  /* Not reached */\n  check_pid();\n  check_tid();\n}\n"
  },
  {
    "path": "src/test/call_gettid.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\n\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('call check_pid()')\nexpect_gdb('SUCCESS')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('call check_tid()')\nexpect_gdb('SUCCESS')\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/call_gettid.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/capget.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nextern int capget(cap_user_header_t header, cap_user_data_t data);\n\nint main(void) {\n  struct __user_cap_header_struct* hdr;\n  struct __user_cap_data_struct* data;\n\n  ALLOCATE_GUARD(hdr, 'a');\n  hdr->version = 0;\n  hdr->pid = 0;\n  test_assert(0 == capget(hdr, NULL));\n  test_assert(hdr->version > 0);\n  VERIFY_GUARD(hdr);\n\n  ALLOCATE_GUARD(hdr, 'a');\n  hdr->version = _LINUX_CAPABILITY_VERSION_1;\n  hdr->pid = 0;\n  ALLOCATE_GUARD(data, 'b');\n  test_assert(0 == capget(hdr, data));\n  VERIFY_GUARD(hdr);\n  VERIFY_GUARD(data);\n\n  ALLOCATE_GUARD(hdr, 'c');\n  hdr->version = _LINUX_CAPABILITY_VERSION_3;\n  hdr->pid = 0;\n  data = allocate_guard(sizeof(*data) * 2, 'd');\n  test_assert(0 == capget(hdr, data));\n  VERIFY_GUARD(hdr);\n  verify_guard(sizeof(*data) * 2, data);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/chaos_oom.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int compare(const void* a, const void* b) {\n  if (*(uint64_t*)a < *(uint64_t*)b) {\n    return -1;\n  }\n  if (*(uint64_t*)a > *(uint64_t*)b) {\n    return 1;\n  }\n  return 0;\n}\n\nstatic int addr_bits(void) {\n#if defined(__i386__)\n  return 32;\n#elif defined(__x86_64__)\n  return 47;\n#elif defined(__aarch64__)\n  return 48;\n#else\n#error Define your architecture here\n#endif\n}\n\nint check_range_available(uint64_t* ptrs, size_t num_ptrs, uint64_t map_size, uint64_t range_size) {\n  if (!num_ptrs) {\n    return 1;\n  }\n  qsort(ptrs, num_ptrs, sizeof(uint64_t), compare);\n  uint64_t last = 0;\n  for (size_t i = 0; i < num_ptrs; ++i) {\n    if (ptrs[i] - last >= range_size) {\n      return 1;\n    }\n    last = ptrs[i] + map_size;\n  }\n  uint64_t addr_max = ((uint64_t)1) << addr_bits();\n  if (addr_max - last >= range_size) {\n    return 1;\n  }\n\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  while (!feof(maps_file)) {\n    char maps_line[1024];\n    fgets(maps_line, sizeof(maps_line), maps_file);\n    fputs(maps_line, stdout);\n  }\n  fflush(stdout);\n\n  return 0;\n}\n\nint main(void) {\n  int i;\n  if (sizeof(void*) == 4) {\n    for (i = 0; i < 10; ++i) {\n      void* p = mmap(NULL, 512*1024*1024, PROT_NONE,\n                     MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n      if (p == MAP_FAILED) {\n        test_assert(errno == ENOMEM);\n        break;\n      }\n    }\n  } else {\n    uint64_t ptrs[1024];\n    uint64_t map_size = ((uint64_t)512)*1024*1024*1024;\n    for (i = 0; i < 1024; ++i) {\n      void* p = mmap(NULL, map_size, PROT_NONE,\n                     MAP_NORESERVE | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n      if (p == MAP_FAILED) {\n        test_assert(errno == ENOMEM);\n        break;\n      }\n      ptrs[i] = (uintptr_t)p;\n    }\n    test_assert(check_range_available(ptrs, i, map_size,\n                                      ((uint64_t)4)*1024*1024*1024*1024));\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/chaos_oom.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"--chaos\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/check_lost_interrupts.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int dummy;\n\nstatic void do_some_ticks(void) {\n  int i;\n  for (i = 0; i < 1000; ++i) {\n    dummy += i % 99;\n  }\n}\n\nint main(void) {\n  int i;\n\n  for (i = 0; i < 100000; ++i) {\n    do_some_ticks();\n    int fd = open(\"/dev/null\", O_RDONLY);\n    close(fd);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/check_lost_interrupts.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_no_syscall_buf\n\nRECORD_ARGS=\"-c10000\"\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/check_patched_pthread.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p ((int*)&__elision_aconf)[2]')\nexpect_gdb(re.compile(r'= 0|No symbol'))\nsend_gdb('p/x *(char*)elision_init')\nexpect_gdb(re.compile(r'= 0xc3|No symbol'))\n\nok()\n"
  },
  {
    "path": "src/test/check_patched_pthread.run",
    "content": "source `dirname $0`/util.sh\nrecord threads$bitness\ndebug_gdb_only check_patched_pthread\n"
  },
  {
    "path": "src/test/check_session_leaks.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_THREADS 100\n\nstatic int pipe_fds[2];\n\nstatic void read_all(int fd, char* buf, size_t size) {\n  while (size > 0) {\n    ssize_t ret = read(fd, buf, size);\n    test_assert(ret > 0);\n    size -= ret;\n    buf += ret;\n  }\n}\n\nstatic void* thread(__attribute__((unused)) void* p) {\n  int fd = open(\"/dev/zero\", O_RDONLY);\n  char buf[1000000];\n  test_assert(fd >= 0);\n  read_all(fd, buf, sizeof(buf));\n  read(pipe_fds[0], buf, 1);\n  test_assert(0);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t threads[NUM_THREADS];\n  int i;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  for (i = 0; i < NUM_THREADS; ++i) {\n    test_assert(0 == pthread_create(&threads[i], NULL, thread, NULL));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/check_session_leaks.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b atomic_puts')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nfor i in range(1,100):\n    send_gdb('checkpoint')\n    expect_gdb('Checkpoint %d '%i)\n    send_gdb('stepi')\n    send_gdb('restart %d'%i)\n    expect_gdb('stopped')\n    send_gdb('delete checkpoint %d'%i)\n    send_gdb('stepi')\n    send_gdb('stepi')\n\nok()\n"
  },
  {
    "path": "src/test/check_session_leaks.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/check_syscall_perf_interval.py",
    "content": "import sys\nimport re\n\nif len(sys.argv) < 4:\n    print('''Usage: %s <syscall-name> <perf-counter-name> <expected-perf-events-between-syscalls>\nExits with status 0 if exactly the expected number of perf events occur between\nevery pair of consecutive system calls of the given type.''' % sys.argv[0])\n    sys.exit(2)\n\nsyscall = sys.argv[1]\ncounter = sys.argv[2]\nexpected_count = int(sys.argv[3])\n\nlast_perfctr_value = -1\nsyscall_re = re.compile(r'''`SYSCALL: (\\\\w+)' \\\\(state:0\\\\)''')\nperfctr_re = re.compile(counter + ':(\\\\d+)')\n\nwhile True:\n    line = sys.stdin.readline()\n    if not line:\n        sys.exit(0)\n    m = syscall_re.search(line)\n    if m:\n        if m.group(1) == syscall:\n            line = sys.stdin.readline()\n            m = perfctr_re.search(line)\n            if m:\n                v = int(m.group(1))\n                if last_perfctr_value >= 0 and v - last_perfctr_value != expected_count:\n                    print('Mismatch: saw %d %ss between %ss (from %d to %d), expected %d' % \\\n                      (v - last_perfctr_value, counter, syscall, last_perfctr_value, v, expected_count))\n                    sys.exit(1)\n                last_perfctr_value = v\n        else:\n            # Ignore nonconsecutive syscalls. In the cpuid test, we have\n            # two batches of geteuid32s; one injected by rr itself to detect\n            # a buggy system, and a separate one for the test. We need to\n            # ignore the geteuid32 pair that spans the gap between the batches.\n            last_perfctr_value = -1\n"
  },
  {
    "path": "src/test/checkpoint_async_signal_syscalls_1000.run",
    "content": "source `dirname $0`/util.sh\n\n# async_signal_syscalls is really about the syscallbuf and is horribly slow\n# with the syscallbuf, so don't bother with this test in no-syscallbuf.\nskip_if_no_syscall_buf\n\ntimeslice=1000\nRECORD_ARGS=\"-c$timeslice\"\n\nrecord async_signal_syscalls$bitness 9\n\nnum_events=$(count_events)\n# This recording has a large number of events, and it's impractical to\n# run the debugger for each one.  The original bug reproduces when the\n# debugger attaches to pretty much any event past event 350, so we\n# somewhat arbitrarily choose a stride that reduces the number of\n# debug_gdb_only sessions by about 10x.\nstride=80\nfor i in $(seq 1 $stride $num_events); do\n    echo Checkpointing at event $i ...\n    debug_gdb_only restart_finish \"-g $i\"\n    if [[ \"$leave_data\" == \"y\" ]]; then\n        break\n    fi\ndone\n"
  },
  {
    "path": "src/test/checkpoint_dying_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic int thread_to_main_fds[2];\nstatic int main_to_child_fds[2];\nstatic int wait_forever_fds[2];\n\nstatic char ch = 'X';\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  /* Lower our priority so we won't get scheduled until everything\n     else is blocked */\n  setpriority(PRIO_PROCESS, 0, 4);\n  test_assert(1 == write(thread_to_main_fds[1], &ch, 1));\n  read(wait_forever_fds[0], &ch, 1);\n  test_assert(0);\n  return NULL;\n}\n\nstatic int run_child(void) {\n  test_assert(1 == read(main_to_child_fds[0], &ch, 1));\n  /* At this point, the parent's main thread should have exit_group()ed\n     and its extra thread should have died but not been scheduled yet.\n     Try to take a checkpoint in this state. */\n  breakpoint();\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\nstatic volatile int scratch = 0;\n\nint main(void) {\n  pthread_t thread;\n  pid_t child;\n  int i;\n\n  test_assert(0 == pipe(thread_to_main_fds));\n  test_assert(0 == pipe(main_to_child_fds));\n  test_assert(0 == pipe(wait_forever_fds));\n\n  child = fork();\n  if (!child) {\n    return run_child();\n  }\n  atomic_printf(\"child %d\\n\", child);\n  test_assert(0 == pthread_create(&thread, NULL, run_thread, NULL));\n\n  test_assert(1 == read(thread_to_main_fds[0], &ch, 1));\n  /* thread should have blocked on its wait-forever read. Tell the\n     child to proceed after we exit_group. */\n  test_assert(1 == write(main_to_child_fds[1], &ch, 1));\n\n  /* Spin for a while to give run_child time to reach a runnable state */\n  for (i = 0; i < 10000000; ++i) {\n    scratch += 1;\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/checkpoint_dying_threads.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('checkpoint')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/checkpoint_dying_threads.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only checkpoint_dying_threads \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/checkpoint_invalid.py",
    "content": "from util import *\n\nsend_gdb('delete checkpoint')\nexpect_gdb('requires an argument')\n\nsend_gdb('delete checkpoint x')\nexpect_gdb('Invalid checkpoint number')\n\nsend_gdb('delete checkpoint 0x1')\nexpect_gdb('Invalid checkpoint number')\n\nsend_gdb('delete checkpoint -1')\nexpect_gdb('No checkpoint number')\n\nsend_gdb('delete checkpoint 0')\nexpect_gdb('No checkpoint number')\n\nsend_gdb('delete checkpoint 99999999999999999999999999999999999999999')\nexpect_gdb('No checkpoint number')\n\nok()\n"
  },
  {
    "path": "src/test/checkpoint_invalid.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only checkpoint_invalid\n"
  },
  {
    "path": "src/test/checkpoint_mixed_mode.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int create_segment(size_t num_bytes) {\n  char filename[] = \"/dev/shm/rr-test-XXXXXX\";\n  int fd = mkstemp(filename);\n  unlink(filename);\n  test_assert(fd >= 0);\n  ftruncate(fd, num_bytes);\n  return fd;\n}\n\nstatic void breakpoint(void) {}\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = create_segment(num_bytes);\n  char* p = mmap(NULL, num_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n  char* shared_p;\n\n  p[0] = 77;\n\n  shared_p = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n\n  breakpoint();\n\n  test_assert(p[0] == 77);\n  test_assert(shared_p[0] == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/checkpoint_mixed_mode.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\n\nsend_gdb('n')\nsend_gdb('restart 1')\nexpect_gdb('breakpoint')\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('xited normally')\n"
  },
  {
    "path": "src/test/checkpoint_mixed_mode.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/checkpoint_mmap_shared.run",
    "content": "source `dirname $0`/util.sh\ncheckpoint_test mmap_shared$bitness 7 9\n"
  },
  {
    "path": "src/test/checkpoint_prctl_name.run",
    "content": "source `dirname $0`/util.sh\ncheckpoint_test prctl_name$bitness 11 13\n"
  },
  {
    "path": "src/test/checkpoint_simple.run",
    "content": "source `dirname $0`/util.sh\ncheckpoint_test simple$bitness 3 5\n"
  },
  {
    "path": "src/test/checksum_block_open.run",
    "content": "source `dirname $0`/util.sh\nGLOBAL_OPTIONS=\"$GLOBAL_OPTIONS --checksum=on-all-events\"\nrecord block_open$bitness\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/checksum_sanity.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) { return NULL; }\n\nstatic volatile int dummy;\n\nstatic void do_some_recursion(int depth) {\n  dummy = depth;\n  if (depth > 0) {\n    do_some_recursion(depth - 1);\n  }\n  dummy = 0;\n}\n\nint main(int argc, char** argv) {\n  pthread_t thread;\n  pid_t child;\n  int status;\n\n  if (argc > 1) {\n    return 77;\n  };\n\n  do_some_recursion(16000);\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  pthread_join(thread, NULL);\n\n  child = fork();\n  if (!child) {\n    char* args[] = { argv[0], \"dummy\", NULL };\n    execve(argv[0], args, environ);\n    test_assert(0 && \"exec failed\");\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  /* Test that checksumming doesn't care if we have a mmap\n   * that is not backed by a sufficiently long file */\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  static const char name[] = \"temp1\";\n  int fd = open(name, O_CREAT | O_RDWR | O_EXCL, 0600);\n  /* Have it extend a couple of bytes into the second page */\n  test_assert(0 == ftruncate(fd, page_size + 200));\n  void* map_addr =\n      mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n  test_assert(MAP_FAILED != map_addr);\n  /* Make the second and third page PROT_NONE */\n  test_assert(0 == mprotect(map_addr + page_size, 2 * page_size, PROT_NONE));\n  /* Just some syscall to get some additional checksums in */\n  event_syscall();\n  test_assert(0 == unlink(name));\n\n  /* The same again, but this time unmap the two pages in the middle */\n  static const char name2[] = \"temp2\";\n  fd = open(name2, O_CREAT | O_RDWR | O_EXCL, 0600);\n  /* Have it extend a couple of bytes into the second page */\n  test_assert(0 == ftruncate(fd, page_size + 200));\n  map_addr =\n      mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n  test_assert(MAP_FAILED != map_addr);\n  test_assert(0 == munmap(map_addr + page_size, 2 * page_size));\n  test_assert(0 == unlink(name2));\n\n  /* Now map two temporary files right next to each other to make sure they're\n     not getting coalesced, causing trouble for the checksumming */\n  static const char name3[] = \"temp3\";\n  fd = open(name3, O_CREAT | O_RDWR | O_EXCL, 0600);\n  static const char name4[] = \"temp4\";\n  int fd2 = open(name4, O_CREAT | O_RDWR | O_EXCL, 0600);\n  ftruncate(fd, page_size);\n  ftruncate(fd2, page_size);\n  // Alloc a 2 page region first, then overwrite it.\n  map_addr =\n      mmap(NULL, 2 * page_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);\n  test_assert(MAP_FAILED != map_addr);\n  test_assert(MAP_FAILED != mmap(map_addr, page_size, PROT_NONE,\n                                 MAP_PRIVATE | MAP_FIXED, fd, 0));\n  test_assert(MAP_FAILED != mmap(map_addr + page_size, page_size, PROT_NONE,\n                                 MAP_PRIVATE | MAP_FIXED, fd2, 0));\n  event_syscall();\n  test_assert(0 == unlink(name3));\n  test_assert(0 == unlink(name4));\n\n  /* Check mapping of file that's (probably) not in a tmpfs, and make sure\n     we can coalesce mappings that are/are not beyond the end of the file. */\n  fd = open(\"/bin/ls\", O_RDONLY);\n  long end = lseek(fd, 0, SEEK_END);\n  test_assert(end > 0);\n  map_addr = mmap(NULL, ceil_page_size(end) + page_size, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(MAP_FAILED != map_addr);\n  test_assert(MAP_FAILED != mmap(map_addr, page_size, PROT_READ,\n                                 MAP_PRIVATE | MAP_FIXED, fd, 0));\n  event_syscall();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/checksum_sanity.run",
    "content": "source `dirname $0`/util.sh\nGLOBAL_OPTIONS=\"$GLOBAL_OPTIONS --checksum=on-all-events\"\nrecord $TESTNAME\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/checksum_sanity_noclone.run",
    "content": "source `dirname $0`/util.sh\nGLOBAL_OPTIONS=\"$GLOBAL_OPTIONS --checksum=on-all-events\"\nRECORD_ARGS=\"--no-read-cloning --no-file-cloning\"\nrecord checksum_sanity$bitness\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/chew_cpu.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS 1000000000\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint spin(void) {\n  int i, dummy = 0;\n\n  atomic_puts(\"spinning\");\n  /* NO SYSCALLS AFTER HERE: the point of this test is to hit\n   * hpc interrupts to exercise the nonvoluntary interrupt\n   * scheduler. */\n  for (i = 1; i < NUM_ITERATIONS; ++i) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n    if (i == NUM_ITERATIONS / 2) {\n      breakpoint();\n    }\n  }\n  return dummy;\n}\n\nint main(void) {\n  atomic_printf(\"EXIT-SUCCESS dummy=%d\\n\", spin());\n  return 0;\n}\n"
  },
  {
    "path": "src/test/chmod.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  static const char file_path[] = \"rr-test-file\";\n  int fd = open(file_path, O_WRONLY | O_CREAT, 0);\n  test_assert(fd >= 0);\n\n  test_assert(0 == chmod(file_path, 0400));\n  test_assert(0 == access(file_path, R_OK));\n  test_assert(0 == fchmod(fd, 0200));\n  test_assert(0 == access(file_path, W_OK));\n  test_assert(0 == syscall(RR_fchmodat, AT_FDCWD, file_path, 0400));\n  test_assert(0 == syscall(RR_fchmodat2, AT_FDCWD, file_path, 0400, 0) || errno == ENOSYS);\n  test_assert(0 == access(file_path, R_OK));\n  test_assert(0 == faccessat(AT_FDCWD, file_path, R_OK, AT_SYMLINK_NOFOLLOW) || errno == ENOSYS);\n  test_assert(0 == syscall(RR_faccessat2, AT_FDCWD, file_path, R_OK, AT_SYMLINK_NOFOLLOW) || errno == ENOSYS);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/chown.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DUMMY_FILENAME \"foo.txt\"\n\nstatic gid_t get_gid(int fd) {\n  struct stat* st;\n  gid_t result;\n\n  ALLOCATE_GUARD(st, 'x');\n  test_assert(0 == fstat(fd, st));\n  result = st->st_gid;\n  FREE_GUARD(st);\n  return result;\n}\n\nstatic void change_group(const char* path, gid_t new_gid) {\n  test_assert(0 == chown(path, geteuid(), new_gid));\n}\n\nstatic void change_group_fd(int fd, gid_t new_gid) {\n  test_assert(0 == fchown(fd, geteuid(), new_gid));\n}\n\nstatic void change_group_at(const char* path, gid_t new_gid) {\n  test_assert(0 == fchownat(AT_FDCWD, path, geteuid(), new_gid, 0));\n}\n\nint main(void) {\n  long ngroups_max;\n  gid_t *groups;\n  int ngroups;\n  gid_t this_group, other_group;\n  int fd;\n\n  ngroups_max = sysconf(_SC_NGROUPS_MAX);\n  test_assert(ngroups_max != -1);\n  groups = alloca(sizeof(gid_t)*ngroups_max);\n\n  this_group = getegid();\n  atomic_printf(\"Current group is %d\\n\", this_group);\n\n  ngroups = getgroups(ngroups_max, groups);\n  test_assert(ngroups > 0);\n\n  other_group = this_group;\n  for (int i = 0; i < ngroups; i++) {\n    if (groups[i] != this_group && groups[i] != (uint16_t)-2) {\n      other_group = groups[i];\n      break;\n    }\n  }\n  if (other_group == this_group) {\n    atomic_puts(\"WARNING: unable to properly test chown()\");\n  }\n\n  fd = creat(DUMMY_FILENAME, 0600);\n  test_assert(fd >= 0);\n  atomic_printf(\"Group owner of %s is %d\\n\", DUMMY_FILENAME, get_gid(fd));\n  test_assert(this_group == get_gid(fd));\n\n  change_group(DUMMY_FILENAME, other_group);\n  atomic_printf(\"  ... now owner is %d\\n\", get_gid(fd));\n  test_assert(other_group == get_gid(fd));\n\n  change_group_fd(fd, this_group);\n  atomic_printf(\"  ... now back to original owner %d\\n\", get_gid(fd));\n  test_assert(this_group == get_gid(fd));\n\n  change_group_at(DUMMY_FILENAME, other_group);\n  atomic_printf(\"  ... now owner is %d\\n\", get_gid(fd));\n  test_assert(other_group == get_gid(fd));\n\n  unlink(DUMMY_FILENAME);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  struct timespec ts;\n  struct timeval tv;\n  int i, err;\n\n  err = clock_getres(CLOCK_MONOTONIC, &ts);\n  test_assert(err == 0);\n  atomic_printf(\"Clock resolution is >= %g us\\n\", ((double)ts.tv_nsec) / 1.0e3);\n\n  memset(&ts, 0, sizeof(ts));\n  memset(&tv, 0, sizeof(tv));\n\n  breakpoint();\n  for (i = 0; i < 100; ++i) {\n    struct timespec ts_now;\n    struct timeval tv_now;\n\n    err = clock_gettime(CLOCK_MONOTONIC, &ts_now);\n    test_assert(err == 0);\n    test_assert(ts.tv_sec < ts_now.tv_sec ||\n                (ts.tv_sec == ts_now.tv_sec && ts.tv_nsec <= ts_now.tv_nsec));\n    ts = ts_now;\n\n    if (i == 50) {\n      breakpoint();\n    }\n\n    /* technically gettimeofday() isn't monotonic, but the\n     * value of this check is higher than the remote\n     * possibility of a spurious failure */\n    err = gettimeofday(&tv_now, NULL);\n    test_assert(err == 0);\n    test_assert(tv.tv_sec < tv_now.tv_sec ||\n                (tv.tv_sec == tv_now.tv_sec && tv.tv_usec <= tv_now.tv_usec));\n    tv = tv_now;\n\n    atomic_printf(\"cg: %g %llu, gtod: %g %llu\\n\", (double)ts.tv_sec,\n                  (long long int)ts.tv_nsec, (double)tv.tv_sec,\n                  (long long int)tv.tv_usec);\n  }\n  breakpoint();\n\n  // Just make sure that rr has this system call. We don't actually try changing\n  // CLOCK_REALTIME, just in case we're root and actually have permissions to do\n  // that.\n  err = clock_settime(CLOCK_MONOTONIC, &ts);\n  test_assert(err == -1 && errno == EINVAL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clock_adjtime.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <sys/timex.h>\n#include <time.h>\n\nint main(void) {\n  struct timex tx;\n  memset(&tx, 0, sizeof(tx));\n  test_assert(-1 != clock_adjtime(CLOCK_REALTIME, &tx));\n\n  struct timespec ts;\n  memset(&ts, 0, sizeof(ts));\n\n  test_assert(-1 != clock_gettime(CLOCK_REALTIME, &ts));\n\n  // Verify that clock_adjtime() and clock_gettime() return roughly the same time.\n  test_assert(labs(tx.time.tv_sec - ts.tv_sec) <= 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clock_nanosleep.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Keep this roughly in sync with 'nanosleep' */\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  sigset_t sigs;\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGINT);\n  pthread_sigmask(SIG_BLOCK, &sigs, NULL);\n\n  while (1) {\n    sleep(1);\n    test_assert(0 == kill(getpid(), SIGINT));\n  }\n  return NULL;\n}\n\nstatic void handler(__attribute__((unused)) int sig) {}\n\nint main(void) {\n  struct timespec sleep = { 0, 1000000 };\n  struct timespec* remain;\n  pthread_t thread;\n\n  test_assert(0 == clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, NULL));\n\n  ALLOCATE_GUARD(remain, 'x');\n  remain->tv_sec = 9999;\n  remain->tv_nsec = 9998;\n  test_assert(0 == clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, remain));\n  VERIFY_GUARD(remain);\n  test_assert(remain->tv_sec == 9999 && remain->tv_nsec == 9998);\n\n  test_assert(0 == signal(SIGINT, handler));\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  sleep.tv_sec = 1000000;\n  test_assert(EINTR == clock_nanosleep(CLOCK_MONOTONIC, 0, &sleep, remain));\n  VERIFY_GUARD(remain);\n  test_assert(remain->tv_sec <= sleep.tv_sec);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clock_time64.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstruct rr_timespec64 {\n  int64_t tv_sec;\n  int64_t tv_nsec;\n};\n\nint main(void) {\n  struct rr_timespec64 ts;\n  struct rr_timespec64 duration = { 0, 1000000 };\n\n  if (sizeof(void*) != 4) {\n    atomic_puts(\"Ignoring non-32bit test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int ret = syscall(RR_clock_getres_time64, CLOCK_MONOTONIC, &ts);\n  if (ret == -1 && errno == ENOSYS) {\n    atomic_puts(\"Skipping tests, because 64 bit time syscalls are unavailable\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == ret);\n  atomic_printf(\"Clock resolution %lld %lld\\n\", (long long)ts.tv_sec, (long long)ts.tv_nsec);\n\n  test_assert(0 == syscall(RR_clock_gettime64, CLOCK_MONOTONIC, &ts));\n  atomic_printf(\"Clock now %lld %lld\\n\", (long long)ts.tv_sec, (long long)ts.tv_nsec);\n\n  test_assert(0 == syscall(RR_clock_nanosleep_time64, CLOCK_MONOTONIC, 0, &duration, &ts));\n\n  test_assert(0 == syscall(RR_clock_gettime64, CLOCK_MONOTONIC, &ts));\n  atomic_printf(\"Clock now %lld %lld\\n\", (long long)ts.tv_sec, (long long)ts.tv_nsec);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int futex(int* uaddr, int op, int val, const struct timespec* timeout,\n                 int* uaddr2, int val2) {\n  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val2);\n}\n\nstatic pid_t child_tid;\nstatic pid_t child_tid_copy;\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic int child(__attribute__((unused)) void* arg) {\n  sigset_t set;\n  int fd;\n  char byte = 'x';\n\n  /* Be careful in here. This thread was set up by a raw clone() call\n   * without TLS support so many things won't work, e.g. atomic_printf.\n   */\n\n  /* Do some syscall-bufferable syscalls to make sure that works.\n   * The syscallbuf will not have been set up, but the syscalls should\n   * still work by not buffering them. */\n  fd = open(\"/dev/zero\", O_RDONLY);\n  test_assert(fd >= 0);\n  test_assert(1 == read(fd, &byte, 1));\n  test_assert(0 == byte);\n  test_assert(0 == close(fd));\n\n  sigfillset(&set);\n  /* NB: we have to naughtily make the linux assumption that\n   * sigprocmask is per-task, because we're not a real\n   * pthread. */\n  test_assert(0 ==\n              syscall(SYS_rt_sigprocmask, SIG_UNBLOCK, &set, (void*)0, _NSIG / 8));\n\n  /* clone() should have set child_tid to our tid */\n  child_tid_copy = child_tid;\n  breakpoint();\n\n  /* We cannot return normally here.  Some clone() implementations call |_exit|\n     after the clone function returns; some call SYS_exit.  For consistency\n     and correctness's sake, we need to call SYS_exit here. */\n  syscall(SYS_exit, 0);\n\n  /* NOT REACHED */\n  return 0;\n}\n\nint main(void) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  int tid;\n  sigset_t set;\n  test_assert(stack != MAP_FAILED);\n\n  sys_gettid();\n  /* NB: no syscalls in between the sys_gettid() above and this\n   * clone(). */\n  breakpoint();\n\n  /* Warning: strace gets the parameter order wrong and will print\n     child_tidptr as 0 here. */\n  tid = clone(child, stack + stack_size,\n              CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND |\n                  CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,\n              NULL, &child_tid, NULL, &child_tid);\n\n  atomic_printf(\"clone()d pid: %d\\n\", tid);\n  test_assert(tid > 0);\n\n  futex(&child_tid, FUTEX_WAIT, tid, NULL, NULL, 0);\n  test_assert(child_tid_copy == tid);\n  /* clone() should have cleared child_tid now */\n  test_assert(child_tid == 0);\n\n  sys_gettid();\n\n  sigfillset(&set);\n  test_assert(0 == sigprocmask(SIG_BLOCK, &set, NULL));\n\n  /* NB: no syscalls in between the sys_gettid() above and this\n   * clone(). */\n  breakpoint();\n  tid = clone(child, stack + stack_size,\n              CLONE_SIGHAND /*must also have CLONE_VM*/, NULL, NULL, NULL);\n\n  atomic_printf(\"clone(CLONE_SIGHAND)'d tid: %d\\n\", tid);\n  test_assert(-1 == tid);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_bad_stack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int status = -1;\n\n  if (syscall(SYS_clone, SIGCHLD, (intptr_t)-1, (intptr_t)-1, (intptr_t)-1,\n              (intptr_t)-1) == 0) {\n    _exit(0);\n  }\n\n  test_assert(wait(&status) >= 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_bad_tls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int ret;\n  int status;\n\n  child = syscall(SYS_clone, CLONE_SETTLS | SIGCHLD, (void*)0, (void*)0, (void*)0, 0L);\n  if (child < 0) {\n    /* On x86-32 null TLS produces EFAULT */\n    test_assert(EFAULT == errno);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  if (!child) {\n    /* Use `syscall` here so we don't do any dl_runtime_resolve stuff that\n     * might use TLS. */\n    syscall(SYS_write, STDOUT_FILENO, \"EXIT-SUCCESS\\n\", 13);\n    syscall(SYS_exit_group, 77);\n  }\n  ret = wait(&status);\n  test_assert(child == ret);\n  test_assert(WIFEXITED(status) && 77 == WEXITSTATUS(status));\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_cleartid_coredump.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int futex(int* uaddr, int op, int val, const struct timespec* timeout,\n                 int* uaddr2, int val2) {\n  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val2);\n}\n\nstatic pid_t child_tid;\n\nstatic int child_SIGKILL(__attribute__((unused)) void* arg) {\n  kill(getpid(), SIGKILL);\n  return 0;\n}\n\nstatic int child_SIGSEGV(__attribute__((unused)) void* arg) {\n  kill(getpid(), SIGSEGV);\n  return 0;\n}\n\nint main(void) {\n  int status = 0;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void *shared_page = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                           MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  *(pid_t*)shared_page = (pid_t)-1;\n\n  if ((child_tid = fork()) == 0) {\n    const size_t stack_size = 1 << 20;\n    void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n    /* We spawn a thread in the same address space, but in a different\n     *  thread group. */\n    pid_t tid = clone(child_SIGKILL, stack + stack_size,\n                CLONE_VM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,\n                NULL, &child_tid, NULL, &child_tid);\n\n    test_assert(tid > 0);\n\n    futex(&child_tid, FUTEX_WAIT, tid, NULL, NULL, 0);\n    /* clone() should have cleared child_tid now */\n    test_assert(child_tid == 0);\n    test_assert(tid == waitpid(tid, &status, __WALL));\n    test_assert(WIFSIGNALED(status));\n\n    tid = clone(child_SIGSEGV, stack + stack_size,\n                CLONE_VM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID,\n                NULL, shared_page, NULL, shared_page);\n    test_assert(tid > 0);\n\n    test_assert(tid = waitpid(tid, &status, __WALL));\n    test_assert(WIFSIGNALED(status));\n    return 0;\n  }\n\n  test_assert(child_tid > 0);\n  test_assert(child_tid == waitpid(child_tid, &status, __WALL));\n  if (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) {\n    atomic_puts(\"Old (<5.16) kernel behavior\");\n    // In this case the value of *shared_page is nondeterministic.\n    // If the child_SIGKILL task exits first, it's sharding address space\n    // with the fork() child so the kernel will clear *shared_page.\n    // But the fork() child can exit first, in which case when the\n    // child_SIGKILL task exits, it's not sharing its address space with\n    // any other task, and the kernel doesn't clear *shared_page.\n    // This is observable if you run this test under `strace -f` on\n    // a < 5.16 kernel; for me, it causes the test to fail if we check\n    // *shared_page == 0 here.\n  } else if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {\n    atomic_puts(\"New (5.16+) kernel behavior\");\n    test_assert(*(pid_t*)shared_page == 0);\n  } else {\n    test_assert(0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_fail.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int child(__attribute__((unused)) void* arg) {\n  /* NOT REACHED */\n  syscall(SYS_exit, 77);\n  return 0;\n}\n\nint main(void) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n  /* This will fail due to invalid flags.\n     Setting CLONE_UNTRACED here to make sure we test the failure path\n     with CLONE_UNTRACED. */\n  pid_t ret = clone(child, stack + stack_size, 0xffffffff, NULL, NULL, NULL,\n                    NULL);\n  test_assert(ret == -1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_file_range.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef BTRFS_IOCTL_MAGIC\n#define BTRFS_IOCTL_MAGIC 0x94\n#endif\n#ifndef BTRFS_IOC_CLONE_RANGE\nstruct btrfs_ioctl_clone_range_args {\n  int64_t src_fd;\n  uint64_t src_offset;\n  uint64_t src_length;\n  uint64_t dest_offset;\n};\n#define BTRFS_IOC_CLONE_RANGE                                                  \\\n  _IOW(BTRFS_IOCTL_MAGIC, 13, struct btrfs_ioctl_clone_range_args)\n#endif\n\n#define BUF_SIZE 65536\n#define FILE_SIZE 10\n\nstatic const char file_name[] = \"tmp.bin\";\nstatic const char file_name2[] = \"tmp2.bin\";\n\nint main(void) {\n  char buf[BUF_SIZE];\n  int fd2;\n  int fd;\n  struct btrfs_ioctl_clone_range_args args;\n  int ret;\n\n  chdir_nontmp_workdir();\n\n  fd = open(file_name, O_RDWR | O_CREAT | O_EXCL, 0600);\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(file_name));\n  memset(buf, 1, sizeof(buf));\n  test_assert(write(fd, buf, FILE_SIZE) == FILE_SIZE);\n\n  fd2 = open(file_name2, O_RDWR | O_CREAT | O_EXCL, 0600);\n  test_assert(fd2 >= 0);\n  test_assert(0 == unlink(file_name2));\n  args.src_fd = fd;\n  args.src_offset = 0;\n  args.src_length = FILE_SIZE;\n  args.dest_offset = 0;\n  ret = ioctl(fd2, BTRFS_IOC_CLONE_RANGE, &args);\n  if (ret < 0 && (errno == EOPNOTSUPP || errno == ENOTTY)) {\n    atomic_puts(\"range cloning not supported\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n\n  memset(buf, 0, sizeof(buf));\n  test_assert(FILE_SIZE == read(fd2, buf, BUF_SIZE));\n  test_assert(buf[0] == 1);\n  test_assert(buf[9] == 1);\n  test_assert(buf[10] == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_file_range.run",
    "content": "source `dirname $0`/util.sh\nexport NONTMP_WORKDIR=$nontmp_workdir\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/clone_immediate_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, run_thread, NULL);\n  /* The signal will be delivered to the thread before\n     any code runs in the thread. */\n  pthread_kill(thread, SIGCHLD);\n\n  syscall(SYS_exit, 0);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_interruption.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void futex(int* uaddr, int op, int val) {\n/* Avoid using the rr-page syscall entrypoints, so we don't trigger any\n   special treatment that might hide bugs. */\n#ifdef __x86_64__\n  __asm__(\"mov $0,%%r10\\n\\t\"\n          \"syscall\\n\\t\" ::\"a\"(SYS_futex),\n          \"D\"(uaddr), \"S\"(op), \"d\"(val));\n#elif defined(__i386__)\n  __asm__(\"xchg %%ebx,%%edi\\n\\t\"\n          \"int $0x80\\n\\t\"\n          \"xchg %%ebx,%%edi\\n\\t\" ::\"a\"(SYS_futex),\n          \"c\"(op), \"d\"(val), \"S\"(NULL), \"D\"(uaddr));\n#else\n  syscall(SYS_futex, uaddr, op, val, (void*)0, (void*)0, 0);\n#endif\n}\n\nstatic int thread_to_main_fds[2];\n\nstatic void signal_handler(int sig) {\n  char ch = 'X';\n  test_assert(sig == SIGCHLD);\n  test_assert(1 == write(thread_to_main_fds[1], &ch, 1));\n}\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  char ch = 'X';\n  int futex_val = 0;\n  test_assert(SIG_ERR != signal(SIGCHLD, signal_handler));\n  test_assert(1 == write(thread_to_main_fds[1], &ch, 1));\n  futex(&futex_val, FUTEX_WAIT, 0);\n  test_assert(0);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  char ch;\n  int i;\n  sigset_t mask;\n\n  test_assert(0 == pipe(thread_to_main_fds));\n\n  pthread_create(&thread, NULL, run_thread, NULL);\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGCHLD);\n  pthread_sigmask(SIG_SETMASK, &mask, NULL);\n\n  test_assert(1 == read(thread_to_main_fds[0], &ch, 1));\n\n  for (i = 0; i < 1000; ++i) {\n    geteuid();\n  }\n\n  kill(getpid(), SIGCHLD);\n\n  test_assert(1 == read(thread_to_main_fds[0], &ch, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_interruption.py",
    "content": "import collections\nimport sys\nimport re\nfrom util import *\n\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\n\nsend_gdb('n')\nsend_gdb('restart 1')\nsend_gdb('c')\n\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/clone_interruption.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c100\"\nrecord $TESTNAME\n# Don't use pipes here since we need 'debug' to run in the same bash process\ndeclare -i stop_at_event=`rr --suppress-environment-warnings dump $workdir/latest-trace | \\\n    python3 $TESTDIR/clone_interruption_finder.py`\ndebug_gdb_only clone_interruption \"-g $stop_at_event\"\n"
  },
  {
    "path": "src/test/clone_interruption_finder.py",
    "content": "import sys\nimport re\n\nsyscall_re = re.compile('`SIGNAL: ')\ntime_re = re.compile(r'global_time:(\\d+)')\nfutex_time = 999999999\n\nwhile True:\n    line = sys.stdin.readline()\n    if not line:\n        break\n    if syscall_re.search(line):\n        m = time_re.search(line)\n        if m:\n            futex_time = m.group(1)\n\nprint(futex_time)\n"
  },
  {
    "path": "src/test/clone_newflags.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void overwrite_file(const char* path, ssize_t num_bytes) {\n  const int magic = 0x5a5a5a5a;\n  int fd = open(path, O_TRUNC | O_RDWR);\n  size_t i;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    write(fd, &magic, sizeof(magic));\n  }\n  close(fd);\n}\n\nint main(void) {\n  pid_t child;\n  int ret;\n  int status;\n\n  static const char name[] = \"temp\";\n  int fd = open(name, O_CREAT | O_RDWR | O_EXCL, 0600);\n\n  overwrite_file(name, 0x1000);\n\n  child = syscall(SYS_clone, CLONE_NEWUSER | SIGCHLD, 0, 0, 0, 0);\n  if (child == -1 && (errno == EINVAL || errno == EPERM)) {\n    atomic_puts(\"CLONE_NEWUSER not supported at this privilege level\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  if (!child) {\n    mmap(NULL, 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n  ret = wait(&status);\n  test_assert(0 == unlink(name));\n  test_assert(child == ret);\n  test_assert(WIFEXITED(status) && 77 == WEXITSTATUS(status));\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_parent.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  volatile pid_t* child_sibling = (pid_t*)malloc(sizeof(pid_t));\n\n  pid_t child = vfork();\n  test_assert(child != -1);\n  if (child == 0) {\n    *child_sibling = 0;\n    syscall(SYS_clone, CLONE_PARENT_SETTID | CLONE_PARENT | SIGCHLD, (void*)0,\n            child_sibling, (void*)0, 0L);\n    test_assert(*child_sibling != -1);\n    if (*child_sibling == 0) {\n      _exit(77);\n    }\n    test_assert(*child_sibling != 0);\n    _exit(76);\n    test_assert(0 && \"Should not reach here\");\n  }\n  test_assert(child != 0 && *child_sibling != 0);\n  int exit_code_sum = 0;\n  for (;;) {\n    int expected_exit_code = 0, status;\n    int ret = wait(&status);\n    if (ret == -1) {\n      test_assert(errno == ECHILD);\n      test_assert(exit_code_sum == 153);\n      atomic_puts(\"EXIT-SUCCESS\");\n      syscall(SYS_exit, 0);\n    } else if (ret == child) {\n      expected_exit_code = 76;\n    } else if (ret == *child_sibling) {\n      expected_exit_code = 77;\n    } else {\n      test_assert(0 && \"Unexpected child\");\n    }\n    test_assert(WIFEXITED(status) && expected_exit_code == WEXITSTATUS(status));\n    exit_code_sum += expected_exit_code;\n  }\n  test_assert(0 && \"Should not reach here\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/clone_share_vm.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void break_function(void) {}\n\nstatic int child(__attribute__((unused)) void* arg) {\n  sched_yield();\n\n  syscall(SYS_exit, 77);\n\n  /* NOT REACHED */\n  return 0;\n}\n\nint main(void) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  int tid;\n  int status;\n  test_assert(stack != MAP_FAILED);\n\n  /* Warning: strace gets the parameter order wrong and will print\n     child_tidptr as 0 here. */\n  tid = clone(child, stack + stack_size, CLONE_VM | SIGCHLD, NULL, NULL, NULL,\n              NULL);\n\n  break_function();\n\n  atomic_printf(\"clone()d pid: %d\\n\", tid);\n  test_assert(tid > 0);\n\n  test_assert(tid == waitpid(tid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_share_vm.py",
    "content": "from util import *\n\nsend_gdb('break break_function')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('check')\nexpect_gdb('Checkpoint 1')\nsend_gdb('next')\nsend_gdb('restart 1')\nexpect_gdb('break_function')\n\nsend_gdb('continue')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/clone_share_vm.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/clone_syscallbuf_cleanup_blocked.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipefds[2];\nstatic const char *CHILD_PROCESS_NAME = \"clone_syscallbuf_cleanup_child\";\n\nvoid assert_syscallbuf_count(int expected) {\n  FILE *f = fopen(\"/proc/self/maps\", \"r\");\n  test_assert(!!f);\n\n  int actual = 0;\n  for (;;) {\n      size_t len = 0;\n      char *line = NULL;\n      int ret = getline(&line, &len, f);\n      if (ret == -1) {\n        break;\n      }\n      if (strstr(line, \"rr-shared-syscallbuf\")) {\n        actual++;\n      }\n      free(line);\n  }\n  test_assert(expected == actual);\n}\n\nstatic int exec_proc(__attribute__((unused)) void* arg) {\n  // Close the reading end of the pipe in this process\n  close(pipefds[0]);\n\n  // Wait for the parent to be blocked in a read(2) syscall waiting on the pipe\n  char wchan_path[PATH_MAX];\n  snprintf(wchan_path, PATH_MAX, \"/proc/%d/wchan\", getppid());\n  char wchan[1024] = {0};\n  do {\n    FILE *f = fopen(wchan_path, \"r\");\n    size_t s = fread(wchan, 1, sizeof(wchan) - 1, f);\n    fclose(f);\n    wchan[s] = 0;\n  } while (strstr(wchan, \"pipe_read\") == 0);\n\n  sleep(1);\n\n  assert_syscallbuf_count(2);\n  // Now exec our child. The child will un-freeze the parent.\n  char wpipe_name[PATH_MAX];\n  snprintf(wpipe_name, sizeof(wpipe_name), \"/proc/self/fd/%d\", pipefds[1]);\n  execl(\"/proc/self/exe\", CHILD_PROCESS_NAME, wpipe_name, NULL);\n\n  test_assert(\"Not reached\" && 0);\n  return 0;\n}\n\nstatic void execd_child_proc(char *pipe_file) {\n  // Unblock the parent by writing a . to the shared pipe\n  pipefds[1] = open(pipe_file, O_WRONLY);\n  test_assert(pipefds[1] != -1);\n\n  char dummy[1] = { '.' };\n  int ret = write(pipefds[1], dummy, 1);\n  test_assert(ret == 1);\n\n  close(pipefds[1]);\n}\n\nint main(int argc, char **argv) {\n  // This is what get exec'd from exec_proc\n  if (argc == 2 && strcmp(argv[0], CHILD_PROCESS_NAME) == 0) {\n    execd_child_proc(argv[1]);\n    return 0;\n  }\n\n  int ret;\n\n  // Before forking, there should only be one syscallbuf\n  assert_syscallbuf_count(1);\n\n  ret = pipe2(pipefds, 0);\n  test_assert(ret != -1);\n\n  // Spawn a process which shares our address space, and will execve(2)\n  const size_t stack_size = 1 << 20;\n  void* exec_proc_stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  pid_t exec_proc_pid = clone(exec_proc, exec_proc_stack + stack_size, CLONE_VM | SIGCHLD,\n                              NULL, NULL, NULL, NULL);\n\n  // This proces needs the read end of the pipe, close the write end\n  close(pipefds[1]);\n\n  // Block ourselves attempting to read from the pipe.\n  char dummy[1] = { 0 };\n  ret = read(pipefds[0], dummy, 1);\n  // When we are woken up, we should have read a byte\n  test_assert(ret == 1);\n  test_assert(dummy[0] == '.');\n\n  // This means the child exec'd so we should have cleaned up the syscallbuf\n  assert_syscallbuf_count(1);\n\n  // Reap the exec'd child\n  test_assert(exec_proc_pid == waitpid(exec_proc_pid, NULL, 0));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/clone_syscallbuf_cleanup_blocked.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\nrecord $TESTNAME\nreplay\n"
  },
  {
    "path": "src/test/clone_syscallbuf_cleanup_cpu.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const size_t SHARED_MEMFD_SIZE = 4096;\nstatic int shared_memfd;\nstatic volatile char *shared_memfd_mapping;\nstatic const char *CHILD_PROCESS_NAME = \"clone_syscallbuf_cleanup_child\";\n\nvoid assert_syscallbuf_count(int expected) {\n  FILE *f = fopen(\"/proc/self/maps\", \"r\");\n  test_assert(!!f);\n\n  int actual = 0;\n  for (;;) {\n      size_t len = 0;\n      char *line = NULL;\n      int ret = getline(&line, &len, f);\n      if (ret == -1) {\n        break;\n      }\n      if (strstr(line, \"rr-shared-syscallbuf\")) {\n        actual++;\n      }\n      free(line);\n  }\n  test_assert(expected == actual);\n}\n\nstatic int exec_proc(__attribute__((unused)) void* arg) {\n  assert_syscallbuf_count(2);\n\n  char memfd_name[PATH_MAX];\n  snprintf(memfd_name, sizeof(memfd_name), \"/proc/self/fd/%d\", shared_memfd);\n  execl(\"/proc/self/exe\", CHILD_PROCESS_NAME, memfd_name, NULL);\n\n  test_assert(\"Not reached\" && 0);\n  return 0;\n}\n\nstatic void execd_child_proc(char *shared_memfd_mapping_path) {\n  // Need to re-map the shared memory we're going to use to poke the parent process\n  shared_memfd = open(shared_memfd_mapping_path, O_RDWR);\n  test_assert(shared_memfd != -1);\n  shared_memfd_mapping = mmap(NULL, SHARED_MEMFD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,\n                              shared_memfd, 0);\n  test_assert(shared_memfd_mapping != MAP_FAILED);\n\n  // And do said poking\n  shared_memfd_mapping[0] = 1;\n}\n\n\nint main(int argc, char **argv) {\n  // This is what get exec'd from exec_proc\n  if (argc == 2 && strcmp(argv[0], CHILD_PROCESS_NAME) == 0) {\n    execd_child_proc(argv[1]);\n    return 0;\n  }\n\n  int ret;\n\n  // Before forking, there should only be one syscallbuf\n  assert_syscallbuf_count(1);\n\n  // mmap some memory that can be shared across execve(2)\n  shared_memfd = memfd_create(\"shared_page\", 0);\n  test_assert(shared_memfd != -1);\n  ret = ftruncate(shared_memfd, SHARED_MEMFD_SIZE);\n  test_assert(ret != -1);\n  shared_memfd_mapping = mmap(NULL, SHARED_MEMFD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,\n                              shared_memfd, 0);\n  test_assert(shared_memfd_mapping != MAP_FAILED);\n  shared_memfd_mapping[0] = 0;\n\n  // Spawn a process which shares our address space, and will execve(2)\n  const size_t stack_size = 1 << 20;\n  void* exec_proc_stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(exec_proc_stack != MAP_FAILED);\n  pid_t exec_proc_pid = clone(exec_proc, exec_proc_stack + stack_size, CLONE_VM | SIGCHLD,\n                              NULL, NULL, NULL, NULL);\n  test_assert(exec_proc_pid != -1);\n\n  // Now spin waiting for the exec'd process to set a bit in the shard mapping\n  while (shared_memfd_mapping[0] != 1) { ; }\n\n  // This means the child exec'd so we should have cleaned up the syscallbuf\n  assert_syscallbuf_count(1);\n\n  // Reap the exec'd child\n  test_assert(exec_proc_pid == waitpid(exec_proc_pid, NULL, 0));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_syscallbuf_cleanup_cpu.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\nrecord $TESTNAME\nreplay\n"
  },
  {
    "path": "src/test/clone_untraced.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic int run_thread(__attribute__((unused)) void* p) {\n  test_assert(1 == write(pipe_fds[1], \".\", 1));\n  return 0;\n}\n\nint main(void) {\n  char* stack = (char*)xmalloc(65536) + 65536;\n  int ret;\n  char ch;\n\n  test_assert(0 == pipe(pipe_fds));\n  ret = clone(run_thread, stack, CLONE_UNTRACED, NULL);\n  test_assert(ret >= 0);\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_vfork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int not_shared;\nstatic int * volatile shared;\n\nint clonefunc(void* exe) {\n  not_shared = 1;\n  sched_yield();\n  *shared = 1;\n\n  execl(exe, exe, NULL);\n  test_assert(\"Not reached\" && 0);\n  return 0;\n}\n\nint main(int argc, char* argv[]) {\n  char child_stack[16384];\n  const char* exe;\n  pid_t child;\n  int status;\n\n  test_assert(2 == argc);\n  exe = argv[1];\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  shared = (int*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                      MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n\n  child = clone(clonefunc, (void*)(((uintptr_t)child_stack + sizeof(child_stack)) &\n                                   ~((uintptr_t)0x8-1)),\n                CLONE_VFORK | SIGCHLD, (void*)exe);\n  test_assert(child >= 0);\n\n  /* This should not execute until after the vfork child has execed */\n  test_assert(*shared == 1);\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  /* We didn't pass CLONE_VM so this should not have changed */\n  test_assert(not_shared == 0);\n\n  atomic_puts(\"clone-vfork-EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/clone_vfork.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe simple$bitness\nrecord $TESTNAME simple$bitness-$nonce\nreplay\ncheck clone-vfork-EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/clone_vfork_pidfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define RR_CLONE_PIDFD 0x1000\n\nint clonefunc(__attribute__((unused)) void* p) {\n  exit(77);\n  return 0;\n}\n\nint main(void) {\n  char child_stack[16384];\n  pid_t child;\n  int status;\n  int pidfd = 99;\n  int dummy_fds[2];\n  pipe(dummy_fds);\n\n  child = clone(clonefunc, (void*)(((uintptr_t)child_stack + sizeof(child_stack)) &\n                                   ~((uintptr_t)0x8-1)),\n                RR_CLONE_PIDFD | CLONE_VFORK | SIGCHLD, NULL, &pidfd);\n  /* CLONE_PIDFD has the same value as CLONE_PID which is silently ignored\n     by older kernels. So they only way to detect that it was ignored is to\n     check that `pidfd` has not been modified. */\n  if (pidfd == 99) {\n    atomic_puts(\"CLONE_PIDFD not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(child >= 0);\n  test_assert(pidfd == dummy_fds[1] + 1);\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && 77 == WEXITSTATUS(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/cloned_sigmask.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n  write(STDOUT_FILENO, \"FAILED!\\n\", 9);\n  exit(0);\n}\n\nint main(void) {\n  sigset_t sigs;\n  pid_t child;\n  int status;\n\n  signal(SIGSEGV, handler);\n\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGSEGV);\n  sigprocmask(SIG_BLOCK, &sigs, NULL);\n\n  child = fork();\n  if (!child) {\n    crash_null_deref();\n    return 77;\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/close_range.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = syscall(RR_close_range, 1, UINT32_MAX, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/comm.py",
    "content": "from util import *\nimport re\n\nsend_gdb('info threads')\nexpect_gdb(r'1\\s+Thread \\d+\\.\\d+ \\(simple(_32)?-[A-Za-z0-9]+\\)')\n\nok()\n"
  },
  {
    "path": "src/test/comm.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only comm\n"
  },
  {
    "path": "src/test/concurrent_signals.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int stop;\n\nstatic void handler(__attribute__((unused)) int sig) {}\n\nstatic void term_handler(__attribute__((unused)) int sig) { stop = 1; }\n\n#define STATEMENT(i)                                                           \\\n  if (a * (i) < b) {                                                           \\\n    ++a;                                                                       \\\n  } else {                                                                     \\\n    ++b;                                                                       \\\n  }\n#define STATEMENT2(i) STATEMENT(i) STATEMENT(i + 1)\n#define STATEMENT4(i) STATEMENT2(i) STATEMENT2(i + 2)\n#define STATEMENT8(i) STATEMENT4(i) STATEMENT4(i + 4)\n#define STATEMENT16(i) STATEMENT8(i) STATEMENT8(i + 8)\n#define STATEMENT32(i) STATEMENT16(i) STATEMENT16(i + 16)\n#define STATEMENT64(i) STATEMENT32(i) STATEMENT32(i + 32)\n#define STATEMENT128(i) STATEMENT64(i) STATEMENT64(i + 64)\n#define STATEMENT256(i) STATEMENT128(i) STATEMENT128(i + 128)\n#define STATEMENT512(i) STATEMENT256(i) STATEMENT256(i + 256)\n#define STATEMENT1024(i) STATEMENT512(i) STATEMENT512(i + 512)\n#define STATEMENT2048(i) STATEMENT1024(i) STATEMENT1024(i + 1024)\n#define STATEMENT4096(i) STATEMENT2048(i) STATEMENT2048(i + 2048)\n\nstatic volatile int a;\nstatic volatile int b;\nstatic volatile int i;\n\nint main(void) {\n  test_assert(0 == signal(SIGUSR1, handler));\n  test_assert(0 == signal(SIGUSR2, handler));\n  test_assert(0 == signal(SIGTERM, term_handler));\n\n  atomic_puts(\"ready\");\n\n  while (!stop) {\n    STATEMENT4096(i);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/concurrent_signals.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME &\n\nuntil grep -q ready record.out; do\n  sleep 0\ndone\n\npid=$(pidof $TESTNAME-$nonce)\n(for i in $(seq 1 1000); do sleep 0; kill -USR1 $pid; done) &\n(for i in $(seq 1 1000); do sleep 0; kill -USR2 $pid; done) &\nwait %2 || failed \"Failed to send all USR1s\"\nwait %3 || failed \"Failed to send all USR2s\"\nkill -TERM $pid\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait %1 || failed \"Abnormal record termination\"\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/conditional_breakpoint_calls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint counter;\nint dot_counter;\n\nint checker(void) {\n  ++counter;\n  return 0;\n}\n\nstatic void print_dot(void) {\n  atomic_printf(\".\");\n  ++dot_counter;\n}\n\nint main(void) {\n  int i;\n\n  for (i = 0; i < 10; ++i) {\n    print_dot();\n  }\n\n  atomic_puts(\"\\nEXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/conditional_breakpoint_calls.py",
    "content": "import re\nfrom util import *\n\nsend_gdb('b print_dot if checker()')\nexpect_gdb('Breakpoint 1')\nsend_gdb('watch dot_counter if checker()')\nexpect_gdb('Hardware watchpoint 2')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/conditional_breakpoint_calls.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/conditional_breakpoint_offload.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic int var;\n\nint main(void) {\n  int i;\n\n  for (i = 0; i < 5000; ++i) {\n    ++var;\n    breakpoint();\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/conditional_breakpoint_offload.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('cond 1 var==-1')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\n# This should complete in a reasonable amount of time!\nexpect_gdb('SIGKILL')\n\nsend_gdb('reverse-continue')\n# And so should this!\nexpect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/conditional_breakpoint_offload.run",
    "content": "source `dirname $0`/util.sh\nif [ $TIMEOUT -lt 300 ]; then TIMEOUT=300; fi\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/condvar_stress.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_THREADS 10\n#define NUM_TRIALS 1000\n\nstatic pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\nstatic pthread_cond_t cond = PTHREAD_COND_INITIALIZER;\nstatic int last_written;\nstatic int trial;\nstatic int write_locked;\nstatic int done;\n\nstatic void* thread(void* idp) {\n  int id = (intptr_t)idp;\n  int num_loops = 0;\n  int num_written = 0;\n\n  while (1) {\n    int this_write;\n\n    ++num_loops;\n    {\n      pthread_mutex_lock(&lock);\n\n      while (!done && (last_written == trial || write_locked)) {\n        pthread_cond_wait(&cond, &lock);\n      }\n      if (done) {\n        pthread_mutex_unlock(&lock);\n        break;\n      }\n\n      write_locked = 1;\n      this_write = trial;\n\n      pthread_mutex_unlock(&lock);\n    }\n\n    atomic_printf(\"%d:%d(%d)\\n\", id, this_write, num_loops);\n    ++num_written;\n\n    {\n      pthread_mutex_lock(&lock);\n\n      last_written = this_write;\n      write_locked = 0;\n      pthread_cond_broadcast(&cond);\n\n      pthread_mutex_unlock(&lock);\n    }\n  }\n\n  atomic_printf(\"  (%d wrote %d)\\n\", id, num_written);\n\n  pthread_exit((void*)(intptr_t)num_written);\n}\n\nint main(void) {\n  pthread_t threads[NUM_THREADS];\n  int i;\n  int threads_num_written = 0;\n\n  for (i = 0; i < NUM_THREADS; ++i) {\n    test_assert(0 ==\n                pthread_create(&threads[i], NULL, thread, (void*)(intptr_t)i));\n  }\n\n  for (i = 0; i < NUM_TRIALS; ++i) {\n    {\n      pthread_mutex_lock(&lock);\n\n      test_assert(i == trial);\n      test_assert(last_written == trial);\n      ++trial;\n      if (i % 2) {\n        pthread_cond_signal(&cond);\n      } else {\n        pthread_cond_broadcast(&cond);\n      }\n\n      pthread_mutex_unlock(&lock);\n    }\n\n    {\n      pthread_mutex_lock(&lock);\n\n      while (last_written < trial) {\n        pthread_cond_wait(&cond, &lock);\n      }\n\n      pthread_mutex_unlock(&lock);\n    }\n  }\n\n  {\n    pthread_mutex_lock(&lock);\n\n    done = 1;\n    pthread_cond_broadcast(&cond);\n\n    pthread_mutex_unlock(&lock);\n  }\n\n  for (i = 0; i < NUM_THREADS; ++i) {\n    void* ret = NULL;\n    test_assert(0 == pthread_join(threads[i], &ret));\n    threads_num_written += (intptr_t)ret;\n  }\n\n  atomic_printf(\" ...  %d threads completed %d out of %d trials\\n\", NUM_THREADS,\n                threads_num_written, NUM_TRIALS);\n  test_assert(threads_num_written == NUM_TRIALS);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/condvar_stress.run",
    "content": "source `dirname $0`/util.sh\n\n# Switch threads very eagerly on recorded events.\nRECORD_ARGS=\"-s\"\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/constructor.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid lib_exit_success(void);\n\nint main(void) {\n  struct timespec ts = { 1, 0 };\n  /* try patching clock_nanosleep, which a library thread is in */\n  clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);\n  nanosleep(&ts, NULL);\n\n  lib_exit_success();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/cont_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char fifo_name[] = \"fifo\";\n\nstatic volatile char ch;\n\nstatic void do_stuff(void) {\n  int i;\n  for (i = 0; i < 10000; ++i) {\n    ch = 7;\n  }\n}\n\n/* This runs outside of rr to send async SIGKILL signals on demand */\nstatic void do_killer(void) {\n  int fd;\n  char buf[4];\n  uint32_t pid;\n  fd = open(fifo_name, O_RDONLY);\n  test_assert(fd >= 0);\n  while (1) {\n    struct timespec ts = { 0, 500000 };\n    ssize_t s = read(fd, buf, 4);\n    if (s == 0) {\n      return;\n    }\n    test_assert(s == 4);\n    memcpy(&pid, buf, 4);\n    nanosleep(&ts, NULL);\n    kill(pid, SIGKILL);\n  }\n}\n\nint main(int argc, char** argv) {\n  pid_t child;\n  int i;\n  int fd;\n  mkfifo(fifo_name, 0600);\n\n  if (argc > 1 && strcmp(argv[1], \"killer\") == 0) {\n    do_killer();\n    return 0;\n  }\n\n  fd = open(fifo_name, O_WRONLY);\n  test_assert(fd >= 0);\n  for (i = 0; i < 1000; ++i) {\n    int ret;\n    int status;\n    char buf[4];\n    ssize_t s;\n    child = fork();\n    if (!child) {\n      while (1) {\n        sched_yield();\n        do_stuff();\n      }\n    }\n    memcpy(buf, &child, 4);\n    s = write(fd, buf, 4);\n    test_assert(s == 4);\n    ret = waitpid(child, &status, 0);\n    test_assert(ret == child);\n    test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/cont_race.run",
    "content": "source `dirname $0`/util.sh\nif [ $TIMEOUT -lt 300 ]; then TIMEOUT=300; fi\n${OBJDIR}/bin/cont_race$bitness killer &\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/cont_signal.py",
    "content": "from util import *\nimport re\n\nsend_gdb('c')\nindex = expect_list([re.compile(r'exited normally'), re.compile(r'Program received signal SIGUSR1')])\n\nif index == 1:\n    send_gdb('c')\n    expect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/cont_signal.run",
    "content": "source `dirname $0`/util.sh\n\nrecorded_exe=async_usr1$bitness\n\n# SIGUSR1, wait 2.0s\nrecord_async_signal 10 2.0 $recorded_exe\ndebug_gdb_only $TESTNAME_NO_BITNESS\n"
  },
  {
    "path": "src/test/context_switch_after_patch.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int counter;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  int pipe_fds[2];\n\n  ++counter;\n  int ret = getuid();\n  test_assert(ret >= 0);\n  ++counter;\n  ret = pipe2(pipe_fds, 0);\n  test_assert(ret < 0 && errno == ESRCH);\n  return NULL;\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_getgid */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_pipe2, 0, 1),\n    /* Error out with ESRCH */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (ESRCH & SECCOMP_RET_DATA)),\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  pthread_t thread;\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  install_filter();\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  for (int i = 0; i < 20; ++i) {\n    ++counter;\n    atomic_printf(\"counter = %d\\n\", counter);\n  }\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/context_switch_after_patch.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"--always-switch\"\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/copy_all.py",
    "content": "from util import *\n\nok()\n"
  },
  {
    "path": "src/test/copy_all.run",
    "content": "source `dirname $0`/util.sh\nRR_COPY_ALL_FILES=1 record simple$bitness\ndebug_gdb_only copy_all\n"
  },
  {
    "path": "src/test/copy_file_range.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n\n/* copy_file_range must be invoked using syscall() on versions of glibc\n * before 2.27.  */\nstatic loff_t\ncopy_file_range_syscall(int fd_in, loff_t *off_in, int fd_out,\n                        loff_t *off_out, size_t len, unsigned int flags)\n{\n    return syscall(RR_copy_file_range, fd_in, off_in, fd_out,\n                   off_out, len, flags);\n}\n\nint main(void) {\n  int in_fd = open(\"dummy.txt\", O_RDWR | O_CREAT | O_TRUNC, 0600);\n  int out_fd = open(\"dummy2.txt\", O_RDWR | O_CREAT | O_TRUNC, 0600);\n  int ret = write(in_fd, \"Hello\\n\", 6);\n  loff_t in_off = 0;\n  loff_t out_off = 0;\n  unlink(\"dummy.txt\");\n  unlink(\"dummy2.txt\");\n\n  test_assert(ret == 6);\n  ret = copy_file_range_syscall(in_fd, &in_off, out_fd, &out_off, 3, 0);\n  if (ret < 0) {\n    // Debian 9 4.9.0-11-amd64 returns EINVAL here for unknown reasons\n    test_assert(errno == ENOSYS || errno == EINVAL);\n    atomic_puts(\"copy_file_range not supported, aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 3);\n  test_assert(in_off == 3);\n  test_assert(out_off == 3);\n  ret = copy_file_range_syscall(in_fd, &in_off, out_fd, NULL, 10, 0);\n  test_assert(ret == 3);\n  test_assert(in_off == 6);\n  test_assert(out_off == 3);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/crash.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  volatile int* p = NULL;\n  *p = 42;\n  test_assert(\"Not reached\" && 0);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/crash.run",
    "content": "source `dirname $0`/util.sh\n\nrecord crash$bitness\nreplay\ncheck ''\n"
  },
  {
    "path": "src/test/crash_in_function.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid crash(void) { crash_null_deref(); }\n\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/crash_in_function.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\nsend_gdb('set unwindonsignal off')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('call crash()')\nexpect_gdb('SIGSEGV')\nsend_gdb('c')\nexpect_gdb('Program terminated with signal SIGKILL')\n# gdb forgets that we already stopped at this breakpoint so it'll stop us there again\nsend_gdb('next')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('next')\nexpect_rr('EXIT-SUCCESS')\nsend_gdb('call crash()')\nexpect_gdb('SIGSEGV')\nsend_gdb('c')\nexpect_gdb('SIGKILL')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1')\nsend_gdb('delete 1')\nsend_gdb('set unwindonsignal on')\nsend_gdb('call crash()')\nexpect_gdb('SIGSEGV')\n\nsend_gdb('next')\nexpect_rr('EXIT-SUCCESS')\nsend_gdb('call crash()')\nexpect_gdb('SIGSEGV')\nsend_gdb('c')\nexpect_gdb('SIGKILL')\n\nok()\n"
  },
  {
    "path": "src/test/crash_in_function.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/creat_address_not_truncated.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <limits.h>\n\nstatic const char dummy_filename[] = \"dummy.txt\";\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  // Request an address where casting to int could corrupt the address on 64-bit\n  // (i.e. not near the top or bottom of memory).\n  uint8_t* map = mmap((void*)(LONG_MAX / 2), page_size, PROT_READ | PROT_WRITE,\n                      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  // Copy the filename there, and try to use creat. If the address gets\n  // truncated, this can cause a segmentation fault.\n  memcpy(map, dummy_filename, sizeof(dummy_filename));\n\n  int fd = creat((const char*)map, 0600);\n  close(fd);\n\n  test_assert(access(dummy_filename, F_OK) == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/cwd_inaccessible.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <sys/types.h>\n#include <unistd.h>\n\nint main(void) {\n  struct passwd* p = getpwnam(\"nobody\");\n  pid_t child;\n  int ret;\n  int status;\n\n  if (!p || p->pw_uid == (uint16_t)-2) {\n    atomic_puts(\"User 'nobody' does not exist, can't run test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == mkdir(\"private\", 0700));\n\n  child = fork();\n  if (!child) {\n    pid_t grandchild;\n    test_assert(0 == chdir(\"private\"));\n    ret = setuid(p->pw_uid);\n    if (ret == -1 && errno == EPERM) {\n      atomic_puts(\"Don't have CAP_SETUID, can't run test\");\n      exit(78);\n    }\n\n    grandchild = fork();\n    if (!grandchild) {\n      ret = open(\".\", O_PATH);\n      test_assert(ret == -1 && errno == EACCES);\n      exit(77);\n    }\n    test_assert(grandchild == waitpid(grandchild, &status, 0));\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n    exit(78);\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(0 == rmdir(\"private\"));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 78);\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/daemon.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic int do_child(void) {\n  /* Daemonize */\n  if (fork()) {\n    return 0;\n  }\n  setsid();\n  write(pipe_fds[1], \"x\", 1);\n  sleep(1000000);\n  return 0;\n}\n\nint main(void) {\n  pid_t child;\n  char ch;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  child = fork();\n\n  if (!child) {\n    return do_child();\n  }\n\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/daemon_read.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic int do_child(void) {\n  char buf[100];\n  int fd = open(\"/dev/zero\", O_RDONLY);\n\n  test_assert(fd >= 0);\n\n  /* Daemonize */\n  if (fork()) {\n    return 0;\n  }\n  setsid();\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  sched_yield();\n  while (1) {\n    test_assert(sizeof(buf) == read(fd, buf, sizeof(buf)));\n  }\n  return 0;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  sleep(100000);\n  return NULL;\n}\n\n#define NUM_THREADS 5\n\nint main(void) {\n  pid_t child;\n  char ch;\n  pthread_t threads[NUM_THREADS];\n  int i;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  for (i = 0; i < NUM_THREADS; ++i) {\n    pthread_create(&threads[i], NULL, do_thread, NULL);\n  }\n\n  child = fork();\n\n  if (!child) {\n    return do_child();\n  }\n\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/daemon_read.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c1000\"\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/dconf_mock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, __attribute__((unused)) char* argv[]) {\n  int fd;\n  volatile char* p;\n  int count = 0;\n\n  if (argc == 1) {\n    test_assert(0 == mkdir(\"dconf\", 0700));\n  }\n  fd = open(\"dconf/user\", O_CREAT | O_RDWR, 0600);\n  test_assert(fd >= 0);\n  test_assert(0 == ftruncate(fd, 2));\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = (char*)mmap(NULL, page_size, PROT_READ | (argc == 2 ? PROT_WRITE : 0),\n                  MAP_SHARED, fd, 0);\n  test_assert(MAP_FAILED != p);\n\n  if (argc == 2) {\n    *p = 1;\n    test_assert(0 == unlink(\"dconf/user\"));\n    test_assert(0 == rmdir(\"dconf\"));\n    return 0;\n  }\n\n  atomic_puts(\"ready\");\n  while (*p == 0) {\n    ++count;\n    sched_yield();\n  }\n\n  atomic_printf(\"Count = %d\\n\", count);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/dconf_mock.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME &\n\nuntil grep -q ready record.out; do\n  sleep 0\ndone\n\n${OBJDIR}/bin/$TESTNAME mock_dconf_update\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait %1\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n\n"
  },
  {
    "path": "src/test/dead_thread_target.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b hit_barrier')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b joined_threads')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, hit_barrier')\n\nsend_gdb('info thr')\nexpect_gdb('2    Thread')\n\nsend_gdb('thr 2')\nexpect_gdb('Switching to thread 2')\n\nsend_gdb('c')\n# TODO: with the gdb in fedora 19, if a thread dies while it's the\n# resume target, then rr notifies gdb, but gdb doesn't ask for a new\n# thread list.  This seems like a gdb bug, because we don't have any\n# other way to notify gdb of thread death, and the same code works\n# just fine in concurrent ubuntu and older versions.\n#\n# So we work around that problem by returning this special error code\n# to the user.  Once gdb has made this mistake, the debugging session\n# is \"stuck\" because won't let any other threads continue.  But at\n# least this error code tells the user that they need to restart the\n# session.\nexpect_gdb(re.compile(\n    r'Breakpoint 2, joined_threads|Remote failure reply: E10'))\n\nok()\n"
  },
  {
    "path": "src/test/dead_thread_target.run",
    "content": "source `dirname $0`/util.sh\nrecord barrier$bitness\ndebug_gdb_only dead_thread_target\n"
  },
  {
    "path": "src/test/deliver_async_signal_during_syscalls.run",
    "content": "source `dirname $0`/util.sh\n\n# See async_signal_syscalls.run for an explanation.\nskip_if_no_syscall_buf\n\n# SIGUSR1, wait 0.5s; do 2^30 iterations to give us effectively unlimited time\n# (the test exits when SIGUSR1 has been handled)\nrecord_async_signal 10 0.5 async_signal_syscalls$bitness 30\n# Because of issue #184, replay takes longer than practical.  So for\n# now we'll skip it and hope other tests exercise the relevant code\n# well enough.\n#replay\n#check 'EXIT-SUCCESS'\npassed\n"
  },
  {
    "path": "src/test/desched_blocking_poll.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_PFDS 200\n\nint main(void) {\n  int fds[2];\n  struct pollfd pfds[NUM_PFDS];\n  char ch = 'x';\n  int i;\n\n  pipe(fds);\n\n  for (i = 0; i < NUM_PFDS; ++i) {\n    pfds[i].fd = fds[0];\n    pfds[i].events = POLLIN;\n  }\n\n  if (fork() == 0) {\n    usleep(1000);\n    write(fds[1], &ch, 1);\n    return 0;\n  }\n\n  /* This should block */\n  test_assert(NUM_PFDS == poll(pfds, NUM_PFDS, -1));\n  test_assert(POLLIN & pfds[0].revents);\n  test_assert(1 == read(pfds[0].fd, &ch, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/desched_sigkill.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#define NUM_READERS 10\n\nstatic int parent_to_child[2];\nstatic int child_to_parent[2];\n\nint main(void) {\n  int ret, status;\n  char ch;\n\n  // This test is a bit non-deterministic, because it relies on the kernel's\n  // scheduling behavior. The scheduling we're looking to test is:\n  //   1. The parent process releases the readers from `read` syscall.\n  //   2. The reader gets scheduled and advances to the syscall exit trap.\n  //   3. The parent gets scheduled and kills the reader.\n  //   4. `rr` gets scheduled and sees the exit trap.\n  //\n  // There are several ways this can go wrong. If the reader doesn't get scheduled\n  // before the parent's kill syscall, then rr will never see the syscall exit\n  // trap, which doesn't trigger the behavior we're interested in. Similarly,\n  // if the reader gets scheduled before `rr`, then it gets advanced to the\n  // exit trap again and rr will similarly never see it.\n  //\n  // To increase our chances of seeing this scheduling behavior, we lower the\n  // priority of the test executable here. The idea is to make rr more likely\n  // to run if it's runnable at all, in order to decrease the likelihood of\n  // the readers being scheduled again between points 3. and 4. above (while\n  // keeping the parent and the readers at the same priority to hopefully get\n  // the kernel to at least schedule one of the readers at point 2).\n  int prio = getpriority(PRIO_PROCESS, 0);\n  setpriority(PRIO_PROCESS, 0, prio >= 15 ? 20 : prio + 5);\n\n  test_assert(0 == pipe(parent_to_child));\n  test_assert(0 == pipe(child_to_parent));\n\n  pid_t pids[NUM_READERS];\n  for (int i = 0; i < NUM_READERS; ++i) {\n    pids[i] = fork();\n    if (pids[i] == 0) {\n        test_assert(1 == write(child_to_parent[1], \"x\", 1));\n        test_assert(1 == read(parent_to_child[0], &ch, 1) && ch == 'x');\n        pause();\n        return 77;\n    }\n  }\n\n  // Phase 1: Wait for all readers to become ready.\n  char chs[NUM_READERS];\n  int bytes_read = 0;\n  while (bytes_read < NUM_READERS) {\n    ret = read(child_to_parent[0], &chs[bytes_read], NUM_READERS - bytes_read);\n    test_assert(ret > 0);\n    for (int i = 0; i < ret; ++i) {\n      test_assert(chs[bytes_read + i] == 'x');\n    }\n    bytes_read += ret;\n  }\n\n  // Phase 2: Release readers from `read` syscall.\n  test_assert(NUM_READERS == write(parent_to_child[1], chs, NUM_READERS));\n\n  // Phase 3: Kill readers.\n  for (int i = 0; i < NUM_READERS; ++i) {\n    kill(pids[i], SIGKILL);\n  }\n\n  for (int i = 0; i < NUM_READERS; ++i) {\n    test_assert(waitpid(pids[i], &status, 0) == pids[i]);\n    test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/desched_ticks.py",
    "content": "from util import *\nimport re\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('b __before_poll_syscall_breakpoint')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nindex = expect_list([re.compile(r'Breakpoint 2'), re.compile(r'SIGKILL')])\nif index == 0:\n  # This is testing that we can reverse-step without crashing rr.\n  send_gdb('reverse-stepi')\n  send_gdb('c')\n  expect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/desched_ticks.run",
    "content": "source `dirname $0`/util.sh\n\n# Without the syscallbuf, this test makes no sense\n# and will fail since it sets a breakpoint in the preload code.\nskip_if_no_syscall_buf\n\nrecord desched_blocking_poll$bitness\ndebug_gdb_only desched_ticks\n"
  },
  {
    "path": "src/test/detach_huge_mmap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util_internal.h\"\n\nstatic const int magic = 0xab;\nstatic uint64_t size = 0x400000; /* 4 MB, at least the value in Task::dup_from */\nstatic size_t page_size;\nstatic void* pages[10];\nstatic unsigned int idx; /*next index of pages*/\n\nvoid test_alloc(char* mem, unsigned int count, off_t offset) {\n\n  test_assert(0 == munmap(mem + size, page_size));\n\n  /* one page near the start */\n  test_assert(idx < sizeof(pages)/sizeof(pages[0]));\n  pages[idx] = mem + page_size;\n  memset(pages[idx], magic, page_size);\n  idx++;\n\n  /* one or more pages near or at the end */\n  for (unsigned int i = 0; i < count; i++) {\n    test_assert(idx < sizeof(pages)/sizeof(pages[0]));\n    pages[idx] = mem + offset + i * page_size;\n    memset(pages[idx], magic, page_size);\n    idx++;\n  }\n}\n\nint main(void) {\n  page_size = sysconf(_SC_PAGESIZE);\n\n  /* Create one big mapping, then break it up by munmap\n   * into smaller ones, to better test the handling in\n   * the end of mappings. */\n\n  void* mem1 = mmap(NULL, 4 * (size + page_size), PROT_READ | PROT_WRITE,\n                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);\n  test_assert(mem1 != MAP_FAILED);\n\n  void* mem2 = mem1 + size + page_size;\n  void* mem3 = mem2 + size + page_size;\n  void* mem4 = mem3 + size + page_size;\n\n  test_alloc(mem1, 1, size - page_size);     /* one page used at last page */\n  test_alloc(mem2, 1, size - page_size * 2); /* one page used before last page */\n  test_alloc(mem3, 2, size - page_size * 2); /* two consecutive pages at last two pages */\n  test_alloc(mem4, 2, size - page_size * 3); /* two consecutive pages before last page */\n\n  pid_t pid = fork();\n  if (pid == 0) {\n    if (running_under_rr()) {\n      rr_detach_teleport();\n    }\n\n    /* create one page for easier comparison */\n    char* cmp = malloc(page_size * 3);\n    test_assert(cmp != NULL);\n    memset(cmp, magic, page_size * 3);\n\n    /* check if the saved pages have the expected value */\n    for (unsigned int i = 0; i < idx; i++) {\n      test_assert(memcmp(pages[i], cmp, page_size) == 0);\n    }\n\n    return 0;\n  }\n\n  int status;\n  wait(&status);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/detach_sigkill.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util_internal.h\"\n\nstatic int parent_to_child[2];\nstatic int child_to_parent[2];\n\nint main(__attribute__((unused)) int argc,\n         __attribute__((unused)) char **argv) {\n    int status;\n    char ch;\n    pid_t pid;\n\n    test_assert(0 == pipe(parent_to_child));\n    test_assert(0 == pipe(child_to_parent));\n\n    if (0 == (pid = fork())) {\n        if (running_under_rr()) {\n            rr_detach_teleport();\n        }\n        // Signal that we are ready\n        test_assert(1 == read(parent_to_child[0], &ch, 1) && ch == 'y');\n        test_assert(1 == write(child_to_parent[1], \"x\", 1));\n        pause();\n        test_assert(0);\n    }\n\n    test_assert(1 == write(parent_to_child[1], \"y\", 1));\n    test_assert(1 == read(child_to_parent[0], &ch, 1) && ch == 'x');\n\n    kill(pid, SIGKILL);\n\n    test_assert(pid == waitpid(pid, &status, 0));\n    test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n"
  },
  {
    "path": "src/test/detach_sigkill_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util_internal.h\"\n\nstatic int parent_to_child[2];\n\nint main(__attribute__((unused)) int argc,\n         __attribute__((unused)) char **argv) {\n    int status;\n    char ch;\n    pid_t pid;\n    siginfo_t sig;\n\n    test_assert(0 == pipe(parent_to_child));\n\n    if (0 == (pid = fork())) {\n        if (running_under_rr()) {\n            rr_detach_teleport();\n        }\n        // Signal that we are ready\n        test_assert(1 == read(parent_to_child[0], &ch, 1) && ch == 'y');\n        exit(24);\n    }\n\n    test_assert(1 == write(parent_to_child[1], \"y\", 1));\n\n    // Give the child a chance to finish exiting\n    test_assert(0 == waitid(P_PID, pid, &sig, WNOWAIT | WEXITED));\n    test_assert(sig.si_pid == pid && sig.si_code == CLD_EXITED && sig.si_status == 24);\n\n    // Now kill the detach proxy before reaping the child\n    kill(pid, SIGKILL);\n\n    // Let rr listen for the SIGKILL event\n    usleep(100);\n\n    test_assert(pid == waitpid(pid, &status, 0));\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 24);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n"
  },
  {
    "path": "src/test/detach_state.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util_internal.h\"\n\nchar path1[PATH_MAX];\nchar path2[PATH_MAX];\n\nvoid do_rdtsc(void) {\n#ifdef __x86_64__\n    asm volatile (\"rdtsc\\n\\t\"\n                  \"mov %%rax,%%rcx\\n\\t\" /* make it bufferable */\n                  ::: \"eax\", \"edx\");\n#endif\n    /* We don't buffer RDTSC on i386 so nothing to test there */\n}\n\nint main(int argc, char **argv) {\n    if (argc == 2) {\n        test_assert(strcmp(argv[1], \"--inner\") == 0);\n        return 0;\n    }\n    test_assert(argc == 1);\n\n    pid_t pid = fork();\n    if (pid == 0) {\n        readlink(\"/proc/self/exe\", path1, sizeof(path1));\n\n        // Check that MAP_GROWSDOWN doesn't get erased\n        size_t page_size = sysconf(_SC_PAGESIZE);\n\n        // Map a shared page\n        char filename[] = \"/dev/shm/rr-test-XXXXXX\";\n        int shmemfd = mkstemp(filename);\n        test_assert(shmemfd >= 0);\n        ftruncate(shmemfd, page_size);\n\n        int* wpage = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, shmemfd, 0);\n        int* rpage = mmap(NULL, page_size, PROT_READ, MAP_SHARED, shmemfd, 0);\n        *wpage = 1;\n        munmap(wpage, page_size);\n\n        // Let the kernel find us a 512 page gap that's free\n        char *pbase = mmap(NULL, page_size * 512, PROT_READ | PROT_WRITE,\n                MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n        test_assert(pbase != MAP_FAILED);\n        munmap(pbase, 512*page_size);\n\n        volatile char *p = (char *)mmap(pbase + 509 * page_size, page_size * 3, PROT_READ | PROT_WRITE,\n                MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_FIXED, -1, 0);\n        test_assert(p != MAP_FAILED);\n\n        // Check that /proc/self/mem gets remapped\n        uintptr_t newval = 1;\n        volatile uintptr_t stackval = 0;\n        int fd = open(\"/proc/self/mem\", O_RDWR);\n        test_assert(fd >= 0);\n        test_assert(sizeof(stackval) == pwrite64(fd, &newval, sizeof(stackval), (off_t)(uintptr_t)&stackval));\n        test_assert(stackval == 1);\n\n        // Check that rlimits survive\n        struct rlimit lim1, lim2;\n        test_assert(0 == getrlimit(RLIMIT_STACK, &lim1));\n        if (lim1.rlim_cur == RLIM_INFINITY) {\n            lim1.rlim_cur = 2 * 1024 * 1024; // 2 MiB\n        }\n        lim1.rlim_cur = 2 * lim1.rlim_cur;\n        if (lim1.rlim_max != RLIM_INFINITY && lim1.rlim_cur > lim1.rlim_max) {\n            lim1.rlim_cur = lim1.rlim_max;\n        }\n        test_assert(0 == setrlimit(RLIMIT_STACK, &lim1));\n\n        // Check that rdtsc gets unpatched\n        do_rdtsc();\n\n        if (running_under_rr()) {\n            rr_detach_teleport();\n        }\n\n        test_assert(0 == getrlimit(RLIMIT_STACK, &lim2));\n        test_assert(0 == memcmp(&lim1, &lim2, sizeof(struct rlimit)));\n\n        do_rdtsc();\n\n        newval = 2;\n        test_assert(sizeof(stackval) == pwrite64(fd, &newval, sizeof(stackval), (off_t)(uintptr_t)&stackval));\n        test_assert(stackval == 2);\n\n        // Validate that rr reset the scheduler affinity mask.\n        // Unfortunately, we can't just check that it matches that from\n        // before the detach, because rr does not yet emulate the correct\n        // scheduler mask after it changes it. XXX: Adjust this test when\n        // that is fixed.\n        cpu_set_t cpus;\n        test_assert(0 == sched_getaffinity(0, sizeof(cpu_set_t), &cpus));\n        if (CPU_COUNT(&cpus) == 1) {\n            // If only one CPU is set either rr messed with us, or only one\n            // cpu is available for environmental reasons (e.g. only one CPU\n            // is online). To see if that is the case, try resetting the\n            // affinity ourselves and if still only one CPU is allowed, let\n            // that through.\n            memset(&cpus, 0xFF, sizeof(cpu_set_t));\n            test_assert(0 == sched_setaffinity(0, sizeof(cpu_set_t), &cpus));\n            test_assert(0 == sched_getaffinity(0, sizeof(cpu_set_t), &cpus));\n            test_assert(CPU_COUNT(&cpus) == 1);\n        }\n\n        // The kernel is picky about MAP_GROWSDOWN. Whether our setup above\n        // works depends on the stack_guard_gap cmdline parameter as well as\n        // kernel versions (prior to 5.0 MAP_GROWSDOWN was disallowed for\n        // access more than 64k bytes beyond the kernel pointer), so check\n        // whether we can expect it to work by explicitly allocating a\n        // MAP_GROWSDOWN page in a subprocess.\n        if (0 == fork()) {\n            test_assert(MAP_FAILED !=\n                (char *)mmap(pbase + 509 * page_size, page_size * 3, PROT_READ | PROT_WRITE,\n                MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_FIXED, -1, 0));\n            *p = 1;\n            *(p - 1) = 1;\n            return 0;\n        }\n\n        int status;\n        wait(&status);\n        if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {\n            *p = 1;\n            *(p - 1) = 1;\n        }\n        // Don't print anything if this fails, because none of this is going to happen\n        // during replay and a printed message will cause the test to fail with apparent\n        // divergence.\n\n        readlink(\"/proc/self/exe\", path2, sizeof(path2));\n        test_assert(0 == strcmp(path1, path2));\n\n        // Check that we can exec without having to clear LD_PRELOAD\n        if (fork() == 0) {\n            // NULL here drops LD_PRELOAD\n            char* execv_argv[] = {\"/proc/self/exe\", \"--inner\", NULL};\n            execve(\"/proc/self/exe\", execv_argv, NULL);\n            test_assert(0 && \"Exec should not have failed\");\n        }\n\n        wait(&status);\n        test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n\n        test_assert(*rpage == 1);\n        unlink(filename);\n\n        return 0;\n    }\n\n    int status;\n    wait(&status);\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n"
  },
  {
    "path": "src/test/detach_terminal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char** argv, char** envp) {\n  struct sigaction sa;\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_handler = SIG_IGN;\n  sigaction(SIGTTIN, &sa, NULL);\n  sigaction(SIGTTOU, &sa, NULL);\n\n  if (argc >= 2 && strcmp(argv[1], \"--newtty\") == 0) {\n    int parent_to_child[2];\n    pipe(parent_to_child);\n    int child_to_parent[2];\n    pipe(child_to_parent);\n\n    // To call setsid() successfully this process must not be a\n    // process group leader. Create a child process, make it a process\n    // group leader, and move our process into that process group.\n    pid_t child = fork();\n    if (child == 0) {\n      test_assert(setpgid(0, 0) == 0);\n      test_assert(write(child_to_parent[1], \"x\", 1) == 1);\n      char ch;\n      test_assert(read(parent_to_child[0], &ch, 1) == 1);\n      return 0;\n    }\n    char ch;\n    test_assert(read(child_to_parent[0], &ch, 1) == 1);\n    test_assert(setpgid(getpid(), child) == 0);\n    test_assert(write(parent_to_child[1], \"x\", 1) == 1);\n\n    int status;\n    wait(&status);\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n\n    test_assert(setsid() >= 0);\n\n    // Create a new terminal, make it the controlling terminal\n    // for this process, and exec the rest of the command line.\n    int control_fd = posix_openpt(O_RDWR);\n    test_assert(control_fd >= 0);\n    test_assert(grantpt(control_fd) == 0);\n    test_assert(unlockpt(control_fd) == 0);\n\n    char buf[PATH_MAX];\n    ptsname_r(control_fd, buf, sizeof(buf));\n    int term_fd = open(buf, O_RDWR);\n    test_assert(term_fd >= 0);\n\n    test_assert(dup2(term_fd, STDIN_FILENO) == STDIN_FILENO);\n\n    execve(argv[2], argv + 2, envp);\n    return 65;\n  }\n\n  if (argc >= 2 && strcmp(argv[1], \"--newpgrp\") == 0) {\n    // Make this process the foreground process for our terminal\n    // and exec the rest of the command line.\n    test_assert(setpgrp() >= 0);\n    test_assert(tcsetpgrp(STDIN_FILENO, getpid()) >= 0);\n    execve(argv[2], argv + 2, envp);\n    return 66;\n  }\n\n  // Check that we are the foreground process for our terminal.\n  int pgrp = tcgetpgrp(STDIN_FILENO);\n  if (pgrp != getpid()) {\n    atomic_printf(\"tcgetpgrp() == %d, expected %d\\n\", pgrp, getpid());\n    return 67;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/detach_terminal.run",
    "content": "source `dirname $0`/util.sh\nskip_if_test_32_bit\nactual_rr=$(which $RR_EXE)\nRR_EXE=\"detach_terminal$bitness --newtty $actual_rr\"\njust_record detach_terminal$bitness \"--newpgrp $actual_rr record --nested=release detach_terminal$bitness\"\nreplay\ncheck_record EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/detach_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"util_internal.h\"\n\n#define NUM_THREADS 20\n\nstatic pid_t my_gettid(void) {\n\tpid_t pid = syscall(SYS_gettid);\n\ttest_assert(pid > 0);\n\treturn pid;\n}\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n\tpid_t tid = my_gettid();\n\tfor (int i = 0; i < 10000; ++i) {\n\t\ttest_assert(tid == my_gettid());\n\t\tif (i % 500 == 0) {\n\t\t\tsched_yield();\n\t\t}\n\t}\n  return NULL;\n}\n\nstatic pid_t my_tid;\n\nint main(__attribute__((unused)) int argc,\n         __attribute__((unused)) const char** argv) {\n\tif (fork() == 0) {\n\t\tpthread_t threads[NUM_THREADS];\n\t\t// Make sure this is patched before the detach\n\t\tmy_tid = my_gettid();\n\n\t\tif (running_under_rr()) {\n\t\t\trr_detach_teleport();\n\t\t\ttest_assert(my_gettid() != my_tid);\n\t\t}\n\n\t\tfor (int i = 0; i < NUM_THREADS; ++i) {\n\t\t\tpthread_create(&threads[i], NULL, run_thread, NULL);\n\t\t}\n\t\tfor (int i = 0; i < NUM_THREADS; ++i) {\n\t\t\tpthread_join(threads[i], NULL);\n\t\t}\n\t\treturn 0;\n\t}\n\n  int status;\n  wait(&status);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/deterministic_sigsys.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n}\n\nint main(void) {\n  struct sock_filter filter[] = {\n    { BPF_LD | BPF_W | BPF_ABS,  0, 0, offsetof(struct seccomp_data, nr) },\n    { BPF_JMP | BPF_JEQ | BPF_K, 0, 1, __NR_read },\n    { BPF_RET | BPF_K,          0, 0, SECCOMP_RET_TRAP },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_ALLOW }\n  };\n  struct sock_fprog fprog = { 4, filter };\n  sigset_t sigs;\n  int ret;\n  pid_t child = fork();\n  int status;\n\n  if (!child) {\n    signal(SIGSYS, handler);\n\n    sigemptyset(&sigs);\n    sigaddset(&sigs, SIGSYS);\n    sigprocmask(SIG_BLOCK, &sigs, NULL);\n\n    ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);\n    test_assert(ret == 0);\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (uintptr_t)&fprog, 0, 0);\n    test_assert(ret == 0);\n    syscall(__NR_read, 0, (void*)0, (size_t)0);\n  }\n  wait(&status);\n  test_assert(WIFSIGNALED(status));\n  test_assert(WTERMSIG(status) == SIGSYS);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/dev_tty.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"/dev/tty\", O_RDWR);\n  if (fd == -1 && errno == ENXIO) {\n    atomic_puts(\"/dev/tty does not exist, skipping test\");\n    fd = STDERR_FILENO;\n  } else {\n    test_assert(fd >= 0);\n  }\n  test_assert(13 == write(fd, \"EXIT-SUCCESS\\n\", 13));\n  return 0;\n}\n"
  },
  {
    "path": "src/test/dev_tty.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME\nreplay\ntoken=EXIT-SUCCESS\nif [[ \"replay.err\" != $(grep -l $token replay.err) ]]; then\n    failed \": token '$token' not in replay.err:\"\n    echo \"--------------------------------------------------\"\n    cat replay.err\n    echo \"--------------------------------------------------\"\n    cat replay.out\n    echo \"--------------------------------------------------\"\nelse\n    passed\nfi\n"
  },
  {
    "path": "src/test/dev_zero.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"/dev/zero\", O_RDONLY);\n  test_assert(fd >= 0);\n  void* ptr = mmap(NULL, 0x200000, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(ptr != NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/direct.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define SIZE 128*1024\n\nint main(void) {\n  int fd = open(\"test.out\", O_RDWR | O_DIRECT | O_CREAT | O_TRUNC, 0600);\n  void *p, *q;\n  int ret = posix_memalign(&p, SIZE, SIZE);\n  if (fd < 0 && errno == EINVAL) {\n    atomic_puts(\"Filesystem doesn't support O_DIRECT; skipping\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(fd >= 0);\n  test_assert(ret == 0);\n\n  ret = write(fd, p, SIZE);\n  test_assert(ret == SIZE);\n\n  ret = pread(fd, p, SIZE, 0);\n  test_assert(ret == SIZE);\n\n  q = mmap(NULL, SIZE, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(q != MAP_FAILED);\n  munmap(q, SIZE);\n\n  fd = open(\"test.out\", O_RDWR | O_CREAT | O_TRUNC, 0600);\n  test_assert(fd >= 0);\n  ret = fcntl(fd, F_SETFL, O_DIRECT);\n  test_assert(ret == 0);\n\n  ret = write(fd, p, SIZE);\n  test_assert(ret == SIZE);\n\n  ret = pread(fd, p, SIZE, 0);\n  test_assert(ret == SIZE);\n\n  q = mmap(NULL, SIZE, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(q != MAP_FAILED);\n  munmap(q, SIZE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/diversion_sigtrap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic __attribute__((noinline)) void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic __attribute__((noinline)) int hardware_breakpoint(void) {\n  debug_trap();\n  return 10;\n}\n\nint main(void) {\n  breakpoint();\n  hardware_breakpoint();\n}\n"
  },
  {
    "path": "src/test/diversion_sigtrap.py",
    "content": "from util import *\nimport re, sys\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p hardware_breakpoint()')\nexpect_gdb('received signal SIGTRAP')\n"
  },
  {
    "path": "src/test/diversion_sigtrap.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/diversion_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic __attribute__((noinline)) void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  // We will make use of the fact that fd 3 is closed. Just to be sure the\n  // parent didn't leak anything, close it (in the normal case, this'll fail,\n  // but that's ok).\n  close(3);\n\n  // Do a bunch of bufferable system calls\n  int fd = open(\"/dev/null\", O_WRONLY | O_CLOEXEC);\n  test_assert(fd == 3);\n\n  // At this breakpoint, we'll attempt to open a file during the diversion\n  breakpoint();\n\n  // More bufferable syscalls\n  for (int i = 1; i < 10; ++i) {\n    write(fd, \"Hello\", 5);\n  }\n}\n"
  },
  {
    "path": "src/test/diversion_syscall.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p (int)open(\"diversion_print.out\",0102,0600)')\nexpect_gdb(r'\\$1 = (\\d+)')\nfd = last_match().group(1)\n# This FD is confused with that during record. That's ok, just make sure\n# operations on this during the diversion actually go to our file.\n\nsend_gdb(f'p (int)write({fd}, \"DIVERSION-SUCCESS\", 17)')\nexpect_gdb(r'\\$2 = 17')\n\nok()\n"
  },
  {
    "path": "src/test/diversion_syscall.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME\ndebug_test_gdb_only\ntoken=DIVERSION-SUCCESS\nif [[ \"diversion_print.out\" != $(grep -l $token diversion_print.out) ]]; then\n  failed \": token '$token' not written to file by diversion\"\nelse\n  passed\nfi\n"
  },
  {
    "path": "src/test/dlchecksum.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <link.h>\n\n/* This test checksums all writable memory mappings of the process and writes it\n   to stdout. This might seem like an odd thing to do, but it's a reasonably close\n   match to memory-scanning infrastructure such as leak detectors and primitive\n   garbage collectors. We want to avoid any divergent memory contents from being\n   visible to such processes. */\n\nstatic uint32_t crc32c_sw(uint32_t crci, const char *buf, size_t len);\nstatic int dl_iterate_phdr_cb(struct dl_phdr_info *info, size_t size, void *crcptr) {\n  uint32_t *crc = (uint32_t*)crcptr;\n  for (size_t i = 0; i < info->dlpi_phnum; i++) {\n    const ElfW(Phdr) *phdr = &info->dlpi_phdr[i];\n    if ((phdr->p_type != PT_LOAD) || (phdr->p_memsz == 0))\n      continue;\n    /* This specifically excludes the rr_page code section, which differs between record and replay */\n    if (!(phdr->p_flags & PF_W))\n      continue;\n    *crc = crc32c_sw(*crc, (char *)(info->dlpi_addr + phdr->p_vaddr), phdr->p_memsz);\n  }\n  (void)size;\n  return 0;\n}\n\nint main(void) {\n  uint32_t crc;\n  dl_iterate_phdr(dl_iterate_phdr_cb, &crc);\n  atomic_printf(\"Checksum: 0x%08x\\n\", crc);\n  atomic_printf(\"EXIT-SUCCESS\\n\");\n  return 0;\n}\n\n/********************** crc32c Implementation **********************/\n\n/*\n  Copyright (C) The Julia contributors.\n  Copyright (C) 2013 Mark Adler\n\n  This software is provided 'as-is', without any express or implied\n  warranty.  In no event will the author be held liable for any damages\n  arising from the use of this software.\n  Permission is granted to anyone to use this software for any purpose,\n  including commercial applications, and to alter it and redistribute it\n  freely, subject to the following restrictions:\n  1. The origin of this software must not be misrepresented; you must not\n     claim that you wrote the original software. If you use this software\n     in a product, an acknowledgment in the product documentation would be\n     appreciated but is not required.\n  2. Altered source versions must be plainly marked as such, and must not be\n     misrepresented as being the original software.\n  3. This notice may not be removed or altered from any source distribution.\n  Mark Adler\n  madler@alumni.caltech.edu\n*/\nstatic const uint32_t crc32c_table[8][256] = {\n    { 0,4067132163,3778769143,324072436,3348797215,904991772,648144872,3570033899,2329499855,2024987596,1809983544,2575936315,1296289744,3207089363,2893594407,1578318884,274646895,3795141740,4049975192,51262619,3619967088,632279923,922689671,3298075524,2592579488,1760304291,2075979607,2312596564,1562183871,2943781820,3156637768,1313733451,549293790,3537243613,3246849577,871202090,3878099393,357341890,102525238,4101499445,2858735121,1477399826,1264559846,3107202533,1845379342,2677391885,2361733625,2125378298,820201905,3263744690,3520608582,598981189,4151959214,85089709,373468761,3827903834,3124367742,1213305469,1526817161,2842354314,2107672161,2412447074,2627466902,1861252501,1098587580,3004210879,2688576843,1378610760,2262928035,1955203488,1742404180,2511436119,3416409459,969524848,714683780,3639785095,205050476,4266873199,3976438427,526918040,1361435347,2739821008,2954799652,1114974503,2529119692,1691668175,2005155131,2247081528,3690758684,697762079,986182379,3366744552,476452099,3993867776,4250756596,255256311,1640403810,2477592673,2164122517,1922457750,2791048317,1412925310,1197962378,3037525897,3944729517,427051182,170179418,4165941337,746937522,3740196785,3451792453,1070968646,1905808397,2213795598,2426610938,1657317369,3053634322,1147748369,1463399397,2773627110,4215344322,153784257,444234805,3893493558,1021025245,3467647198,3722505002,797665321,2197175160,1889384571,1674398607,2443626636,1164749927,3070701412,2757221520,1446797203,137323447,4198817972,3910406976,461344835,3484808360,1037989803,781091935,3705997148,2460548119,1623424788,1939049696,2180517859,1429367560,2807687179,3020495871,1180866812,410100952,3927582683,4182430767,186734380,3756733383,763408580,1053836080,3434856499,2722870694,1344288421,1131464017,2971354706,1708204729,2545590714,2229949006,1988219213,680717673,3673779818,3383336350,1002577565,4010310262,493091189,238226049,4233660802,2987750089,1082061258,1395524158,2705686845,1972364758,2279892693,2494862625,1725896226,952904198,3399985413,3656866545,731699698,4283874585,222117402,510512622,3959836397,3280807620,837199303,582374963,3504198960,68661723,4135334616,3844915500,390545967,1230274059,3141532936,2825850620,1510247935,2395924756,2091215383,1878366691,2644384480,3553878443,565732008,854102364,3229815391,340358836,3861050807,4117890627,119113024,1493875044,2875275879,3090270611,1247431312,2660249211,1828433272,2141937292,2378227087,3811616794,291187481,34330861,4032846830,615137029,3603020806,3314634738,939183345,1776939221,2609017814,2295496738,2058945313,2926798794,1545135305,1330124605,3173225534,4084100981,17165430,307568514,3762199681,888469610,3332340585,3587147933,665062302,2042050490,2346497209,2559330125,1793573966,3190661285,1279665062,1595330642,2910671697 },\n    { 0,329422967,658845934,887597209,1317691868,1562966443,1775194418,2054015301,2635383736,2394315727,3125932886,2851302177,3550388836,3225172499,4108030602,3883469565,1069937025,744974838,411091311,186800408,1901039709,1659701290,1443537075,1168652484,2731618873,2977147470,2241069783,2520160928,3965408229,4294560658,3407766283,3636263804,2139874050,1814657909,1489949676,1265388443,822182622,581114537,373600816,98970183,3802079418,4047354061,3319402580,3598223395,2887074150,3216496913,2337304968,2566056447,1078858371,1408010996,1728782957,1957280282,247755615,493284136,696337329,975428550,3713716539,3472378188,4196393429,3921508770,2479927527,2154965136,3029696521,2805405822,4279748100,3971309171,3629315818,3421531805,2979899352,2722054063,2530776886,2239369025,1644365244,1906417099,1162229074,1457827109,747201632,1059847191,197940366,409914617,3235002245,3547377650,3885434731,4097154844,2388153945,2650459694,2837276343,3133144768,1573319741,1315204170,2055455955,1763794084,323786209,15601046,873047311,665533816,2157716742,2470362481,2816021992,3027996063,3457565914,3719617709,3914560564,4210158659,495511230,237665993,986568272,695160359,1392674658,1084235541,1950857100,1743073275,3210335367,2902150384,2552030313,2344516638,4057183579,3799067948,3600188853,3308527042,575477567,837783368,84420561,380288934,1825011427,2137386644,1266828813,1478549114,4223924985,3898696334,3699821079,3475264096,3041499941,2800419666,2450303947,2175677372,1725380929,1970643254,1100089775,1378914776,677206173,1006616810,253257843,482013188,3288730488,3617886991,3812834198,4041319393,2324458148,2569990867,2915654218,3194733117,1494403264,1253068983,2119694382,1844797529,395880732,70922603,819829234,595526021,2219317755,2548728204,2735548693,2964304226,3401742375,3647004752,3985066185,4263891134,425515587,184435252,1041885869,767259354,1473690527,1148462056,1888717681,1664160518,3146639482,2821681165,2630408340,2406105315,4110911910,3869577681,3527588168,3252691263,647572418,893105077,31202092,310281051,1746094622,2075251305,1331067632,1559552647,81018109,393651338,596708371,808686692,1247698209,1509737814,1830514127,2126116280,2579562309,2321704754,3196440491,2905036764,3611991705,3303540462,4027559543,3819779584,991022460,682841355,475331986,267806181,1973136544,1715025111,1390320718,1098646585,2785349316,3047659187,2168471082,2464327261,3901714200,4214093679,3486146550,3697854337,2069880831,1761429384,1545269009,1337489254,903200291,645342804,311463629,20059834,3863682119,4125721648,3238931625,3534533854,2831252891,3143886316,2407812469,2619790594,1150955134,1463334409,1675566736,1887274727,168841122,431151061,760577868,1056433979,3650022854,3391911345,4274773288,3983099231,2533657626,2225476717,2957098228,2749572227 },\n    { 0,2772537982,1332695565,3928932467,2665391130,1000289892,3518101015,1961911401,944848581,2635115707,2000579784,3531603638,2794429151,63834273,3923822802,1285642924,1889697162,3588485108,1070411655,2592914937,4001159568,1262308334,2702412701,72489443,1223902031,3987919153,127668546,2732426044,3593332565,1936487723,2571285848,1006839590,3779394324,1141205354,2922096921,191511399,2140823310,3671838064,821366019,2511642493,3642082769,2085902255,2524616668,859506082,1204511179,3800757173,144978886,2917507512,2447804062,883365088,3733574803,2076722925,255337092,2860101882,1079472265,3843482359,2847389787,217459237,3872975446,1134131240,929635393,2452131391,2013679180,3712474162,3345318105,1646531239,2282410708,759906474,1505436867,4244289213,383022798,3012945072,4281646620,1517628514,2958814225,354057839,1642732038,3299575928,780486667,2344934005,3083337043,310800173,4171804510,1575566624,689527113,2354629431,1719012164,3275200826,2409022358,718754280,3237581211,1706558437,289957772,3020551666,1579627905,4217808895,639728589,2204166579,1766730176,3423583166,3103776727,499010985,4153445850,1389436836,510674184,3140605814,1360992005,4099835259,2158944530,636449644,3485578015,1786782049,1451427399,4089615417,434918474,3165505076,3361579613,1830563875,2268262480,577987118,1859270786,3415452412,566061711,2231171313,4027358360,1431113446,3210989205,438459627,2334619459,778495293,3293062478,1628026672,368694105,2964865319,1519812948,4292285226,3010873734,372759544,4229503883,1498974709,766045596,2297004002,1657257873,3347459567,4219800265,1589942455,3035257028,296471226,1700507347,3222944941,708115678,2406837920,3285464076,1721083506,2361091585,704312447,1560973334,4165665384,308658715,3072610405,1784908887,3475119657,621600346,2152549412,4106037325,1375517235,3151133248,513009726,1379054226,4151517420,492691615,3088872161,3438024328,1772979446,2206418053,650303227,448917981,3212862371,1437508560,4042207662,2216646087,559859641,3413116874,1848743348,579915544,2278645094,1845468437,3367898987,3159255810,420477308,4079040783,1449175921,1279457178,3909314020,53323159,2792110057,3533460352,2011021822,2649948557,951227379,1947453791,3511835425,998021970,2654800172,3939331397,1334640443,2778873672,14921014,1021348368,2577471598,1938806813,3603843683,2721984010,125811828,3981540359,1209069177,78755029,2716870315,1272899288,4003427494,2590970063,1060012721,3573564098,1883361468,2902854798,138911472,3798556291,1193856253,869836948,2526624490,2092432025,3656804583,2505519691,806789173,3661127750,2138698296,193566289,2932343855,1155974236,3785840162,3718541572,2028331898,2462786313,931836279,1132123422,3862644576,202737427,2840860013,3858059201,1085595071,2862226892,266047410,2066475995,3731519909,876919254,2433035176 },\n    { 0,3712330424,3211207553,1646430521,2065838579,2791807819,3292861042,419477706,4131677158,721537374,1227047015,2489772767,2372293141,1344534701,838955412,4014267180,3915690301,874584965,1443074748,2336634884,2454094030,1325607542,757179215,4033087991,522244827,3261429859,2689069402,2097306594,1677910824,3108456848,3680878761,102787601,3609531531,174112307,1749169930,3037175218,2886149496,1900187584,325060345,3458575425,560035693,4230274517,2651215084,1128529492,1514358430,2265377830,3844367647,945934247,1044489654,3808694030,2166785591,1550003343,1164153925,2552643325,4194613188,658578812,3355821648,356543720,2002970065,2854702953,3005740963,1851940123,205575202,3506798234,2879807463,1994650975,348224614,3380926174,3498339860,230802604,1877167509,2997282605,1575107585,2158466745,3800375168,1069593912,650120690,4219840330,2577870451,1155695819,1120071386,2676442210,4255501659,551577571,971038505,3836048785,2257058984,1539462672,3028716860,1774397316,199339709,3601073157,3483679951,316741239,1891868494,2911254006,2088979308,2714165716,3286526189,513917525,128023199,3672428583,3100006686,1703146406,2328307850,1468170802,899681035,3907363251,4058323321,748729281,1317157624,2479329344,2515008081,1218597097,713087440,4156912488,4005940130,864051482,1369630755,2363966107,1671666103,3202757391,3703880246,25235598,411150404,3317957372,2816904133,2057511293,1386268991,2414175111,3989301950,813842438,696449228,4106703476,2531646285,1268806133,2766449369,2040594529,461605208,3334874080,3754335018,42152338,1621211307,3185840659,3150215170,1719784122,77814659,3655790907,3236317681,497279817,2139187824,2730803400,1300241380,2428875100,4075239525,799183581,916597271,3957817519,2311391638,1417716526,2240142772,1489008396,987954741,3886503053,4272417863,602031871,1103155142,2625987966,1942077010,2927891690,3433471443,300103531,149131169,3584435481,3078925344,1791035032,1826712713,2980365873,3548794632,247719344,398679418,3397842882,2829352699,1977734211,2594508655,1205904855,633482478,4169631318,3783736988,1019384868,1591745821,2208675749,4177958616,608386144,1180808537,2602835937,2183440171,1600195987,1027835050,3758501394,256046398,3523698566,2955269823,1835039751,1952498893,2837802613,3406292812,373444084,274868197,3441921373,2936341604,1916841692,1799362070,3053829294,3559339415,157458223,3861267459,996404923,1497458562,2214907194,2634315248,1078058824,576935537,4280745161,774079059,4083558635,2437194194,1275136874,1426174880,2286164248,3932590113,925055641,3630686645,86133517,1728102964,3125110924,2739261510,2113960702,472052679,3244775807,3343332206,436378070,2015367407,2774907479,3160736413,1629530149,50471196,3729230756,822300808,3964074544,2388947721,1394727345,1243701627,2539965379,4115022586,671344706 },\n    { 0,940666796,1881333592,1211347188,3762667184,3629437212,2422694376,2826309188,3311864721,4252394557,3041252553,2371140453,623031585,489937549,1426090617,1829832149,2401395155,3073576575,4278238859,3339833639,1869078371,1467396303,524615739,659845015,1246063170,1918109166,979875098,41343670,2852181234,2450635614,3659664298,3795018758,464041303,599382779,1804233231,1402668451,4226616295,3288097867,2345653439,3017718547,3738156742,3873362282,2934792606,2533101106,1049231478,110850010,1319690030,1991880834,2492126340,2895887144,3836218332,3703137392,1959750196,1289618840,82687340,1023204032,1374543637,1778167993,567214157,434008033,2980602277,2310606345,3247095549,4187738449,928082606,255853826,1198765558,2137184858,3608466462,4010130354,2805336902,2670159082,4063650111,3391557267,2182397543,3120943563,309583759,711110691,1649475799,1514172283,3094547325,2153931985,3360805925,4030774153,1479980493,1613224545,672426645,268764473,2098462956,1157984064,221700020,891793432,2639380060,2772488688,3983761668,3579973288,754573305,350793813,1557856417,1690988301,3434897737,4104982245,3164519953,2224017853,3919500392,3515857860,2579237680,2712495260,165374680,835323252,2046408064,1105779244,2749087274,2613760390,3556335986,3957853918,1134428314,2072997686,868016066,195932270,1723643323,1588451863,379480803,781124943,2264468235,3202901159,4141601875,3469392895,1856165212,1454619376,511707652,647062952,2397531116,3069576256,4274369716,3335838488,2881871565,2480189793,3689349525,3824578105,1266704509,1938886609,1000521509,62115977,3783308431,3650214691,2443340759,2847081595,29690431,970220947,1911018855,1240906443,619167518,485937330,1422221382,1825837034,3298951598,4239617538,3028344566,2358358362,1963614219,1293619111,86556499,1027199231,2505039547,2908664087,3849126371,3715919439,2959960986,2289828918,3226449090,4166966126,1344853290,1748613766,537528946,404448734,4196925912,3258543732,2315968128,2988159276,443400040,578605252,1783586864,1381896092,1062144585,123626981,1332598033,2004662973,3742020857,3877362517,2938661793,2537096205,1509146610,1642254430,701587626,297799430,3115712834,2175233774,3381976602,4052070838,2626991203,2760235983,3971377979,3567715479,2094074579,1153459583,217306507,887274023,3604078113,4005605773,2800943481,2665639637,915693713,243601213,1186381769,2124927077,330749360,732412444,1670646504,1535468868,4092816128,3420587180,2211558488,3149978612,1113262757,2051695881,846845437,174635601,2719921173,2584730553,3527174989,3928818913,2268856628,3207425688,4145995372,3473912256,1736032132,1600704552,391864540,793382768,3447286646,4117234906,3176903726,2236275586,758961606,355318378,1562249886,1695507762,136208615,806293323,2017247167,1076744211,3898334807,3494556155,2558066959,2691198627 },\n    { 0,4012927769,3683426499,884788186,3002414967,1573215342,1769576372,2252995757,1611012127,2402710278,3146430684,1421530053,3539152744,1036207217,159354795,3863995570,3222024254,792484647,461410557,4105239524,1928922953,2647223376,2843060106,1178979475,2685020193,1329218360,2072414434,2495013883,318709590,4258231375,3379806101,641979532,2247366285,1791262100,1584969294,2974342487,922821114,3627109091,3968696633,62777888,3857845906,180512139,1048489553,3511600456,1460091365,3090633468,2357958950,1673261631,1173890739,2865253802,2658436720,1900342633,4144828868,406682333,746696967,3283212830,637419180,3402519989,4268924527,289600886,2534083035,2017157826,1283959064,2746728961,235166699,3778294002,3582524200,985174065,3169938588,1405159301,1736297567,2286790470,1845642228,2167548141,3046040375,1522436142,3707204739,868687770,125555776,3897278297,3456658389,557318348,361024278,4206141455,2096979106,2479699899,2809265249,1212258168,2920182730,1094588627,1971507977,2595403792,486229181,4090179492,3346523262,675778407,2347781478,1690314367,1350364581,3209463484,956660241,3593801992,3800685266,230273483,3958789497,80100960,813364666,3746209443,1493393934,3056797975,2190459597,1841277396,1274838360,2764838465,2423315867,2134947458,4178135599,372842806,579201772,3451224565,737830215,3301576286,4034315652,524725917,2567918128,1983854889,1115943667,2914228714,470333398,4080590031,3347322645,682916876,2935849121,1104014264,1970348130,2587970427,2081337289,2470364368,2810318602,1219650579,3472595134,567014311,360134781,4198978404,3691284456,859106545,126363435,3904392242,1861333151,2176965510,3044872284,1515027269,3154288631,1395848430,1737375540,2294174765,251111552,3787965337,3581610051,978019162,2583470427,1993132610,1114636696,2906679937,722048556,3292134709,4035262191,531979766,4193958212,382390877,578165127,3443946142,1259310643,2755650858,2424516336,2142455273,1508938085,3066100348,2189177254,1833720511,3943015954,70634763,814286545,3753471432,972458362,3603358307,3799656889,222970528,2332278285,1681118484,1351556814,3216995799,302836797,4248602404,3380628734,649078759,2700729162,1338617939,2071296905,2487554192,1913320482,2637864763,2844153057,1186349048,3237987157,802138188,460546966,4098033807,3523271683,1026602778,160201920,3871086553,1626729332,2412085357,3145288631,1414078638,2986787868,1563864837,1770677471,2260340678,15987563,4022573170,3682554792,877607089,2549676720,2026410409,1282693747,2739155306,621661639,3393038046,4269894916,296814109,4160676527,416188854,745685612,3275893109,1158403544,2856042177,2659677467,1907826178,1475660430,3099894167,2356701773,1665663316,3842113017,171022048,1049451834,3518838307,938660497,3636640136,3967709778,55449931,2231887334,1782025983,1586185509,2981834300 },\n    { 0,1745038536,3490077072,3087365464,2782971345,3454265625,1978047553,501592201,1311636819,640602523,2653660355,4129851403,3956095106,2211320906,1003184402,1405636058,2623273638,4099462766,1281205046,610177022,968572791,1371018175,3921503975,2176731695,3530950645,3128240957,40918629,1785950893,2006368804,529919724,2811272116,3482564476,1029407677,1431875445,3982350893,2237593317,2562410092,4038617764,1220354044,549335860,1937145582,460673574,2742036350,3413314486,3600202559,3197474807,110158511,1855180391,2701162779,3372438995,1896226955,419761219,81837258,1826852866,3571901786,3169175954,4012737608,2267981952,1059839448,1462300944,1254965657,583953745,2597001225,4073206977,2058815354,313797554,2863750890,3266474530,3747070635,3075796579,257006395,1733474291,882571817,1553585889,3835470777,2359267185,2440708088,4185461552,1098671720,696208032,3874291164,2398081300,921347148,1592363140,1124874253,722408645,2466931101,4211690837,2831220879,3233950791,2026330399,281310679,220317022,1696786838,3710360782,3039080454,1206682823,804235279,2548751703,4293521823,3792453910,2316266974,839522438,1510552654,163674516,1640125788,3653705732,2982415564,2887892037,3290599565,2082989525,337955101,3686235745,3014939305,196159473,1672612665,2119678896,374642552,2924601888,3327315688,2509931314,4254707706,1167907490,765458026,813319907,1484352043,3766230899,2290037691,4117630708,2641175100,627595108,1298889644,1351535397,948824045,2156434101,3901472381,3141792679,3544244079,1799727671,54953727,514012790,1990204094,3466948582,2795914030,1765143634,20371610,3107171778,3509616906,3436523907,2765495627,483616787,1959806171,655886593,1327179209,4145959057,2669509721,2197343440,3942375448,1392416064,989706632,3358952777,2687934849,406050009,1882257425,1842694296,97936464,3184726280,3587194304,2249748506,3994770642,1444817290,1042089282,603502027,1274779907,4093570139,2617098387,1416525807,1013799719,2221420159,3966436023,4052660798,2576195318,562621358,1233897318,440634044,1916839540,3393573676,2722562020,3215150957,3617612709,1873090301,128334389,2413365646,3889833286,1608470558,937196758,708430943,1111154839,4198471119,2453453063,3254056157,2851592213,301116749,2045870469,1679044876,202841540,3021105308,3692119124,327349032,2072109024,3280251576,2877785712,3059889913,3730905649,1717858153,241648545,1571753595,900473523,2376685547,3853155107,4165979050,2420959074,675910202,1078640370,2994899507,3665929979,1652872099,176684907,392318946,2137088810,3345225330,2942778042,4239357792,2494323624,749285104,1151992376,1498395313,827104889,2303322913,3779774441,786002069,1188715613,4276037893,2531001805,2335814980,3812268428,1530916052,859619356,1626639814,150446350,2968704086,3639736478,3306440727,2903991519,353505671,2098281807 },\n    { 0,1228700967,2457401934,3678701417,555582061,1747058506,3009771555,4200137988,1111164122,185039357,3494117012,2575270835,1663469239,706411408,4049501433,3093430750,2222328244,3444208787,370078714,1597148893,2775288793,3965187838,924021143,2117012656,3326938478,2406576201,1412822816,487164423,3880816387,2926375460,1965585741,1007945834,218129817,1144789182,2675482583,3594838768,740157428,1696701139,3194297786,4149829789,1329291587,101129316,3712195341,2491409962,1848042286,656055817,4234025312,3043124295,2306239533,3226079498,453940835,1379068740,2825645632,3780612967,974328846,1932486953,3410847991,2188449232,1496683193,269086622,3931171482,2741802941,2015891668,823422451,436259634,1396487701,2289578364,3242478683,991775071,1914778744,2842014481,3763981878,1480314856,285717199,3393402278,2206156929,2032553349,807022754,3948853195,2724383468,2658583174,3612000161,202258632,1160922607,3211477227,4132912588,756267685,1680852866,3696084572,2507258747,1312111634,118047029,4249895985,3026991382,1864941183,638894936,385920683,1581044620,2239255781,3427019202,907881670,2132890081,2758137480,3982076847,1429973617,470275926,3343077439,2390699288,1948657692,1025135931,3864973906,2942480245,2474026783,3662338616,17718609,1211244662,2993366386,4216805461,538173244,1764729371,3511526341,2557599458,1127569803,168371372,4031783336,3110886543,1646844902,722773697,872519268,2101209923,2792975402,4014280973,354161673,1545627950,2271538759,3461911392,1983550142,1057419161,3829557488,2910721495,1462178003,505114100,3311397533,2355337146,2960629712,4182500087,571434398,1798510777,2439650749,3629539482,51570675,1244568276,4065106698,3144738349,1614045508,688397411,3545307495,2590860352,1093264169,135634446,956429309,1883082458,2876836275,3796202644,404517264,1361054903,2321845214,3277387513,2067461927,839289344,3913420137,2692640846,1512535370,320538733,3361705732,2170810915,3178756681,4098590574,789512199,1714650400,2624223268,3579184387,236094058,1194262349,4283235987,3060827060,1832125661,604535290,3729882366,2540503513,1277789872,85326743,771841366,1732059249,3162089240,4114995775,253550395,1176543772,2640586101,3562559570,1815763340,621159595,4265780162,3078545125,1294457825,68921030,3747553711,2523094152,2859947234,3813353925,940551852,1899221899,2339034767,3260459944,420621505,1345212902,3897315384,2708483359,2050271862,856217425,3377582677,2154671986,1529423899,303387964,587282639,1782400488,2977546881,4165320614,35437218,1260439429,2422489324,3646438859,1631206421,671498546,4081239643,3128867708,1076346488,152814431,3529458742,2606971153,2809606523,3997912156,890227509,2083763730,2255139606,3478572593,336742744,1563309183,3846976929,2893039750,1999949807,1040757448,3293689804,2372782827,1445547394,521482405 }\n};\n\nstatic uint32_t crc32c_sw(uint32_t crci, const char *buf, size_t len)\n{\n    uintptr_t crc = crci ^ 0xffffffff;\n    while (len && ((uintptr_t)buf & 7) != 0) {\n        crc = crc32c_table[0][(crc ^ *buf++) & 0xff] ^ (crc >> 8);\n        len--;\n    }\n    while (len >= 8) {\n#if defined(__x86_64__) || defined(__aarch64__)\n        crc ^= *(uint64_t*)buf;\n        crc = crc32c_table[7][crc & 0xff] ^\n            crc32c_table[6][(crc >> 8) & 0xff] ^\n            crc32c_table[5][(crc >> 16) & 0xff] ^\n            crc32c_table[4][(crc >> 24) & 0xff] ^\n            crc32c_table[3][(crc >> 32) & 0xff] ^\n            crc32c_table[2][(crc >> 40) & 0xff] ^\n            crc32c_table[1][(crc >> 48) & 0xff] ^\n            crc32c_table[0][crc >> 56];\n#else\n        uint32_t *p = (uint32_t*)buf;\n        crc ^= p[0];\n        uint32_t hi = p[1];\n        crc = crc32c_table[7][crc & 0xff] ^\n            crc32c_table[6][(crc >> 8) & 0xff] ^\n            crc32c_table[5][(crc >> 16) & 0xff] ^\n            crc32c_table[4][(crc >> 24) & 0xff] ^\n            crc32c_table[3][hi & 0xff] ^\n            crc32c_table[2][(hi >> 8) & 0xff] ^\n            crc32c_table[1][(hi >> 16) & 0xff] ^\n            crc32c_table[0][hi >> 24];\n#endif\n        buf += 8;\n        len -= 8;\n    }\n    while (len) {\n        crc = crc32c_table[0][(crc ^ *buf++) & 0xff] ^ (crc >> 8);\n        len--;\n    }\n    return (uint32_t)crc ^ 0xffffffff;\n}\n"
  },
  {
    "path": "src/test/dlopen.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  void* h = dlopen(\"libX11.so\", RTLD_LAZY);\n  if (h) {\n    dlclose(h);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/dlopen.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\nsend_gdb('c')\nexpect_gdb('EXIT-SUCCESS')\nexpect_gdb('SIGKILL')\nsend_gdb('reverse-continue')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/dlopen.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n\n"
  },
  {
    "path": "src/test/doublesegv.c",
    "content": "#include \"util.h\"\n\nint handler_pipe_fd;\n\nstatic void fault_handler(int sig, __attribute__((unused)) siginfo_t* si,\n                          __attribute__((unused)) void* context) {\n  sigset_t oldset;\n  sigprocmask(0, NULL, &oldset);\n  test_assert(sigismember(&oldset, SIGSEGV) &&\n              \"SIGSEGV should be blocked here\");\n  write(handler_pipe_fd, &sig, sizeof(int));\n  *((int*)1) = 0;\n  // raise(SIGSEGV);\n  test_assert(0 && \"Should not reach here\");\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  raise(SIGSEGV);\n  test_assert(0 && \"Should not reach here!\");\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  pthread_t thread;\n  int pipe_fds[2];\n  pipe(pipe_fds);\n  handler_pipe_fd = pipe_fds[1];\n\n  if ((child = fork()) == 0) {\n    struct sigaction act;\n    act.sa_sigaction = fault_handler;\n    act.sa_flags = SA_ONSTACK | SA_SIGINFO;\n    sigemptyset(&act.sa_mask);\n    sigaction(SIGSEGV, &act, NULL);\n\n    pthread_create(&thread, NULL, do_thread, NULL);\n    test_assert(0 == sched_yield());\n    sleep(1000);\n    test_assert(0 && \"Should not reach here\");\n    return 0;\n  }\n\n  int handler_sig;\n\n  test_assert(read(pipe_fds[0], &handler_sig, sizeof(int)) == sizeof(int));\n  test_assert(handler_sig == SIGSEGV);\n  test_assert(child == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/dup.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char buf[] = \"0123456789\";\n\nint main(void) {\n  int pipe_fds[2];\n  int fd;\n  char ch;\n\n  test_assert(0 == pipe(pipe_fds));\n  test_assert(10 == write(pipe_fds[1], buf, 10));\n\n  fd = dup(pipe_fds[0]);\n  test_assert(fd >= 0);\n  test_assert(fd != pipe_fds[0] && fd != pipe_fds[1]);\n  test_assert(1 == read(fd, &ch, 1));\n  test_assert(ch == '0');\n\n  fd = dup2(pipe_fds[0], 0);\n  test_assert(fd == 0);\n  test_assert(1 == read(fd, &ch, 1));\n  test_assert(ch == '1');\n\n  fd = dup3(pipe_fds[0], 49, O_CLOEXEC);\n  test_assert(fd == 49);\n  test_assert(1 == read(fd, &ch, 1));\n  test_assert(ch == '2');\n  test_assert(FD_CLOEXEC == fcntl(fd, F_GETFD));\n\n  test_assert(fd == dup2(0, fd));\n  test_assert(0 == fcntl(fd, F_GETFD));\n\n  fd = fcntl(pipe_fds[0], F_DUPFD, 49);\n  test_assert(fd == 50);\n  test_assert(1 == read(fd, &ch, 1));\n  test_assert(ch == '3');\n  test_assert(0 == fcntl(fd, F_GETFD));\n\n  fd = fcntl(pipe_fds[0], F_DUPFD_CLOEXEC, 49);\n  test_assert(fd == 51);\n  test_assert(1 == read(fd, &ch, 1));\n  test_assert(ch == '4');\n  test_assert(FD_CLOEXEC == fcntl(fd, F_GETFD));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/early_error.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char *argv[]) {\n  test_assert(argc >= 2);\n\n  struct sock_filter filter[] = {\n#if defined(__i386__) || defined(__x86_64__)\n    { BPF_LD | BPF_W | BPF_ABS,  0, 0, offsetof(struct seccomp_data, arch) },\n    { BPF_JMP | BPF_JEQ | BPF_K, 0, 4, AUDIT_ARCH_I386 },\n    // i386\n    { BPF_LD | BPF_W | BPF_ABS,  0, 0, offsetof(struct seccomp_data, nr) },\n    { BPF_JMP | BPF_JEQ | BPF_K, 0, 1, 37 /* __NR32_kill */ },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_TRAP },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_ALLOW },\n    // x86_64\n    { BPF_LD | BPF_W | BPF_ABS,  0, 0, offsetof(struct seccomp_data, nr) },\n    { BPF_JMP | BPF_JEQ | BPF_K, 0, 1, 62 /* __NR_kill */ },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_TRAP },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_ALLOW }\n#else\n    { BPF_LD | BPF_W | BPF_ABS,  0, 0, offsetof(struct seccomp_data, nr) },\n    { BPF_JMP | BPF_JEQ | BPF_K, 0, 1, SYS_kill },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_TRAP },\n    { BPF_RET | BPF_K,           0, 0, SECCOMP_RET_ALLOW }\n#endif\n  };\n  struct sock_fprog fprog = { sizeof(filter)/sizeof(struct sock_filter), filter };\n  int ret;\n  int status;\n\n  int fd_pair[2];\n  ret = pipe(fd_pair);\n\n  pid_t child = fork();\n\n  if (!child) {\n    ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);\n    test_assert(ret == 0);\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, (uintptr_t)&fprog, 0, 0);\n    test_assert(ret == 0);\n\n    ret = close(fd_pair[0]);\n    test_assert(ret == 0);\n    ret = dup2(fd_pair[1], 2);\n    test_assert(ret >= 0);\n\n    /* We want to probe the regular rr error path, not the test monitor path,\n       but we should still pass through things like LD_LIBRARY_PATH in case\n       they're required for rr running properly. */\n    unsetenv(\"RUNNING_UNDER_TEST_MONITOR\");\n    execve(argv[1], &argv[1], environ); // Should not return\n    test_assert(0);\n  }\n  ret = close(fd_pair[1]);\n\n  ret = wait(&status);\n  test_assert(ret >= 0);\n  atomic_printf(\"Got status 0x%x\\n\", status);\n  test_assert(WIFSIGNALED(status));\n\n  char buf[4096];\n  memset(buf, 0, sizeof(buf));\n  ssize_t nread = read(fd_pair[0], buf, sizeof(buf)-1);\n  test_assert(nread >= 0);\n  /* Three possibilities: */\n  if (WTERMSIG(status) == SIGSYS) {\n    /* The child got SIGSYS and exited before we PTRACE_SEIZEd it.\n       Then rr gets a SIGSYS when it tries to kill the tracee. */\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  if (strstr(buf, \"Tracee died before reaching SIGSTOP\") &&\n      WTERMSIG(status) == SIGABRT) {\n    /* The child got SIGSYS before we PTRACE_SEIZEd it, but we got it\n       in time to see the PTRACE_EVENT_EXIT */\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  if (strstr(buf, \"Unexpected stop\") && WTERMSIG(status) == SIGABRT) {\n    /* We ptrace-seized it in time to see the SIGSYS */\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  write(2, buf, nread);\n  test_assert(0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/early_error.run",
    "content": "source `dirname $0`/util.sh\nsave_exe \"$TESTNAME\"\n_RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT record.err \"./$TESTNAME-$nonce\" \\\n    $(which rr) $GLOBAL_OPTIONS record $LIB_ARG $RECORD_ARGS \"./$TESTNAME-$nonce\" \\\n    || failed \"didn't get expected startup error\"\n"
  },
  {
    "path": "src/test/elapsed_time.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void){\n    sleep(1);\n\n    breakpoint();\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n"
  },
  {
    "path": "src/test/elapsed_time.py",
    "content": "from util import *\nimport re\n\n# Test that the elapsed-time GDB command returns a time >= 1.0 at a breakpoint\n# after sleep(1);\n\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nsend_gdb('elapsed-time')\n\nexpect_gdb(re.compile(r'(?<=Elapsed Time \\(s\\): )[0-9.]+'))\nelapsed_time = float(last_match().group(0))\nsleep_time = 1.0\nif elapsed_time < sleep_time:\n    failed('ERROR ... The reported elapsed time after sleeping for ' +\n           f'{sleep_time} (s) was {elapsed_time}')\n\nok()\n"
  },
  {
    "path": "src/test/elapsed_time.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/env_newline.run",
    "content": "export BADENV='hello\nkitty'\nsource `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS \"\" simple$bitness\n"
  },
  {
    "path": "src/test/epoll_create.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n\n  fd = epoll_create(1);\n  atomic_printf(\"New epoll file descriptor: %d\\n\", fd);\n\n  if (fd >= 0) {\n    atomic_puts(\"EXIT-SUCCESS\");\n  }\n\n  close(fd);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/epoll_create1.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n\n  fd = epoll_create1(0);\n  atomic_printf(\"New epoll file descriptor: %d\\n\", fd);\n\n  if (fd >= 0) {\n    atomic_puts(\"EXIT-SUCCESS\");\n  }\n\n  close(fd);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/epoll_edge.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n  int pipe_fds[2];\n  struct epoll_event event = { EPOLLIN | EPOLLET, { 0 } };\n\n  fd = epoll_create(1);\n  test_assert(fd >= 0);\n  test_assert(0 == pipe(pipe_fds));\n  test_assert(0 == epoll_ctl(fd, EPOLL_CTL_ADD, pipe_fds[0], &event));\n\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  test_assert(1 == epoll_wait(fd, &event, 1, 1000));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/epoll_many.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUFFER_SIZE 1024*1024\n\nint main(void) {\n  int fd;\n  int pipe_fds[2];\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  struct epoll_event event = { EPOLLIN | EPOLLET, { 0 } };\n  char* p = (char*)mmap(NULL, BUFFER_SIZE,\n    PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p + page_size, page_size));\n\n  fd = epoll_create(1);\n  test_assert(fd >= 0);\n  test_assert(0 == pipe(pipe_fds));\n  test_assert(0 == epoll_ctl(fd, EPOLL_CTL_ADD, pipe_fds[0], &event));\n  test_assert(0 == epoll_wait(fd, (struct epoll_event*)p,\n      BUFFER_SIZE/sizeof(struct epoll_event), 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/epoll_pwait2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_sig(__attribute__((unused)) int sig) {\n  /* Don't do anything, just go through the signal handler motions */\n}\n\nint main(void) {\n  int pipe_fd[2];\n  int epfd = epoll_create(1 /*num events*/);\n  struct timespec ts = { 5, 0 };\n  struct epoll_event ev;\n  sigset_t sigmask;\n  sigemptyset(&sigmask);\n  sigaddset(&sigmask, SIGCHLD);\n\n  signal(SIGALRM, handle_sig);\n\n  test_assert(epfd >= 0);\n  test_assert(0 == pipe(pipe_fd));\n\n  ev.events = EPOLLIN;\n  ev.data.fd = pipe_fd[0];\n  test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev));\n\n  // Make sure something will wake us from the epoll_pwait2.\n  alarm(1);\n  // But also use the epoll_pwait to modify the signal mask.\n  syscall(RR_epoll_pwait2, epfd, &ev, 1, &ts, &sigmask, (long)8);\n  test_assert(errno == EINTR || errno == ENOSYS);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/epoll_pwait_eintr_sigmask.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_sig(__attribute__((unused)) int sig) {\n  /* Don't do anything, just go through the signal handler motions */\n}\n\nint main(void) {\n  int pipe_fd[2];\n  int epfd;\n  struct epoll_event ev;\n  sigset_t sigmask;\n  sigemptyset(&sigmask);\n  sigaddset(&sigmask, SIGCHLD);\n\n  signal(SIGALRM, handle_sig);\n\n  test_assert(0 == pipe(pipe_fd));\n  test_assert(0 <= (epfd = epoll_create(1 /*num events*/)));\n\n  ev.events = EPOLLIN;\n  ev.data.fd = pipe_fd[0];\n  test_assert(0 == epoll_ctl(epfd, EPOLL_CTL_ADD, ev.data.fd, &ev));\n\n  // Make sure something will wake us from the epoll_pwait.\n  alarm(1);\n  // But also use the epoll_pwait to modify the signal mask.\n  epoll_pwait(epfd, &ev, 1, 5000, &sigmask);\n  test_assert(errno == EINTR);\n  // We didn't die, yay!.\n  // The sigreturn will clean up the kernel's internal state.\n\n  // Now do it again, but don't rely on sigreturn to clean up\n  // the kernel state.\n  signal(SIGALRM, SIG_IGN);\n\n  // Make sure something will wake us from the epoll_pwait.\n  alarm(1);\n  // But also use the epoll_pwait to modify the signal mask.\n  epoll_pwait(epfd, &ev, 1, 5000, &sigmask);\n  test_assert(errno == EINTR);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/eventfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void do_test(int fd) {\n  uint64_t val = 7;\n  uint64_t out;\n\n  test_assert(fd >= 0);\n  test_assert(sizeof(val) == write(fd, &val, sizeof(val)));\n  test_assert(sizeof(out) == read(fd, &out, sizeof(out)));\n  test_assert(out == val);\n}\n\nint main(void) {\n#ifdef SYS_eventfd\n  do_test(syscall(SYS_eventfd, 0));\n#endif\n  do_test(eventfd(0, 0));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exclusion_region.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n#ifdef __x86_64__\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uintptr_t granularity = ((uintptr_t)2)*1024*1024*1024*1024;\n  char* addr = (char*)granularity;\n  int failed_to_allocate_in_some_region = 0;\n  while (addr < (char*)(((uintptr_t)1) << 47)) {\n    int succeeded = 0;\n    for (int i = 0; i < 16; ++i) {\n      char* addr2 = addr + i * page_size;\n      void* p = mmap(addr2, 4096, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n      if (p == addr2) {\n        succeeded = 1;\n      }\n      munmap(p, 4096);\n    }\n    if (!succeeded) {\n      atomic_printf(\"All allocations around %p failed\\n\", addr);\n      failed_to_allocate_in_some_region = 1;\n    }\n    addr += granularity;\n  }\n  test_assert(failed_to_allocate_in_some_region);\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exclusion_region.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=--chaos\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/exec_deleted.run",
    "content": "source `dirname $0`/util.sh\n\nfile=simple$bitness\ncp ${OBJDIR}/bin/$file $file-$nonce\njust_record ./$file-$nonce\nrm $file-$nonce\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/exec_failed.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  execlp(\"/asdjfklajdfkla\", \"\", NULL);\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_failed.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nok()\n\n"
  },
  {
    "path": "src/test/exec_failed.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/exec_flags.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void my_exec(const char* filename, const char** argv,\n                    const char** envp) {\n#ifdef __i386__\n  /* Use a special instruction after the syscall to make sure we don't patch\n     it */\n  int out_bx;\n  __asm__ __volatile__(\"xor %%ebx,%%ebx\\n\\t\"\n                       \"xchg %%ebx,%%edi\\n\\t\"\n                       \"int $0x80\\n\\t\"\n                       \"xchg %%ebx,%%edi\\n\\t\"\n                       : \"=b\"(out_bx)\n                       : \"a\"(SYS_execve), \"c\"(argv), \"d\"(envp), \"D\"(filename));\n#elif defined(__x86_64__)\n  int out_bx;\n  /* Use a special instruction after the syscall to make sure we don't patch\n     it */\n  __asm__ __volatile__(\"xor %%ebx,%%ebx\\n\\t\"\n                       \"syscall\\n\\t\"\n                       \"xchg %%rdx,%%rdx\\n\\t\"\n                       : \"=b\"(out_bx)\n                       : \"a\"(SYS_execve), \"D\"(filename), \"S\"(argv), \"d\"(envp));\n#elif defined(__aarch64__)\n  register long x8 __asm__(\"x8\") = SYS_execve;\n  register long x0 __asm__(\"x0\") = (long)filename;\n  register long x1 __asm__(\"x1\") = (long)argv;\n  register long x2 __asm__(\"x2\") = (long)envp;\n  __asm__ __volatile__(\"b 1f\\n\\t\"\n                       \"mov x8, 0xdc\\n\"\n                       \"1:\\n\\t\"\n                       \"svc #0\"\n                       : \"+r\"(x0)\n                       : \"r\"(x8), \"r\"(x1), \"r\"(x2));\n#else\n#error Unknown architecture\n#endif\n}\n\nint main(__attribute__((unused)) int argc, const char* argv[],\n         const char* envp[]) {\n  my_exec(\"/no-exist!\", argv, envp);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_from_main_thread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  sleep(1000);\n  test_assert(0 && \"Failed something!\");\n  return NULL;\n}\n\nint main(int argc, __attribute__((unused)) char** argv) {\n  pthread_t thread;\n  char* args[] = { \"/proc/self/exe\", \"dummy\", NULL };\n\n  if (argc > 1) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  test_assert(0 == sched_yield());\n\n  atomic_puts(\"About to exec\");\n  execve(\"/proc/self/exe\", args, environ);\n  test_assert(0 && \"Failed exec!\");\n\n  return 1;\n}\n"
  },
  {
    "path": "src/test/exec_from_other_thread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  char* argv[] = { \"/proc/self/exe\", \"dummy\", NULL };\n  write(STDOUT_FILENO, \".\", 1);\n  execve(\"/proc/self/exe\", argv, environ);\n  test_assert(0 && \"Failed exec!\");\n  return NULL;\n}\n\nint main(int argc, __attribute__((unused)) char** argv) {\n  pthread_t thread;\n  int i;\n  pid_t child;\n  int status;\n\n  if (argc > 1) {\n    return 77;\n  }\n\n  for (i = 0; i < 100; ++i) {\n    child = fork();\n    if (child == 0) {\n      pthread_create(&thread, NULL, do_thread, NULL);\n      sleep(1000);\n      test_assert(0 && \"Failed something!\");\n      return 1;\n    }\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  }\n\n  atomic_puts(\"\\nEXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_many.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  int count;\n  test_assert(argc <= 2);\n  count = argc == 1 ? 100 : atoi(argv[1]);\n\n  if (count > 0) {\n    char buf[1000];\n    sprintf(buf, \"%d\", count - 1);\n    execlp(argv[0], argv[0], buf, NULL);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_many.run",
    "content": "source `dirname $0`/util.sh\n\nulimit -n 1024\nRECORD_ARGS=\"--scarce-fds\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/exec_no_env.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char** argv) {\n  if (argc == 1) {\n    char* args[] = { argv[0], \"hello\", NULL };\n    char* envp[] = { NULL };\n    execve(argv[0], args, envp);\n    test_assert(0);\n    return 0;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_self.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(int argc, char* argv[]) {\n  test_assert(argc == 1 || (argc == 2 && !strcmp(\"self\", argv[1])));\n\n  if (argc != 2) {\n    atomic_printf(\"exec(%s, 'self') ...\\n\", argv[0]);\n\n    breakpoint();\n    /* No syscalls in between here. */\n    execlp(argv[0], argv[0], \"self\", NULL);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_shared_as.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pid_t child_tid;\nstatic char *exe;\n\nstatic int do_child(__attribute__((unused)) void* p) {\n  char* argv[] = { exe, NULL };\n  child_tid = sys_gettid(); // Force the syscallbuf to be allocated\n  execve(exe, argv, environ);\n  test_assert(0 && \"Failed exec!\");\n  return 0;\n}\n\nint main(int argc, char** argv) {\n  int i;\n  pid_t child;\n  int status;\n\n  test_assert(argc == 2);\n  exe = argv[1];\n\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n  // This test has a slight timing dependency. We want the SIGCHLD from the child process\n  // exiting to be delivered exactly when the parent process resumes for the first time.\n  // Our exit_fast executable makes this happen fairly reliably, but we run it a few times,\n  // just to make sure.\n  for (i = 0; i < 10; ++i) {\n    child = clone(do_child, stack + stack_size,\n                CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_VFORK |\n                CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD,\n            NULL, &child_tid, NULL, &child_tid);\n    test_assert(child != -1);\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exec_shared_as.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe exit_fast$bitness\nrecord $TESTNAME exit_fast$bitness-$nonce\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/exec_stop.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_gdb('stopped')\nsend_gdb('stepi')\nexpect_gdb('stopped')\nsend_gdb('stepi')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('stopped')\nsend_gdb('b execve')\nexpect_gdb('Breakpoint 1')\nsend_gdb('rc')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/exec_stop.run",
    "content": "source `dirname $0`/util.sh\nrecord exec_self$bitness\ndebug_gdb_only exec_stop\n"
  },
  {
    "path": "src/test/exec_stopsig.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  pid_t child;\n  int status;\n\n  test_assert(argc <= 2);\n  if (argc == 2) {\n    return 77;\n  }\n\n  if ((child = fork()) == 0) {\n    execlp(argv[0], argv[0], \"self\", NULL);\n    test_assert(\"Not reached\" && 0);\n  }\n  sched_yield();\n\n  /* Try sending SIGSTOP to the child while it is in exec */\n  kill(child, SIGSTOP);\n  kill(child, SIGCONT);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/execp.run",
    "content": "source `dirname $0`/util.sh\n\nexe=simple$bitness\ncp ${OBJDIR}/bin/$exe $exe-$nonce\nPATH=\"${PATH}:.\" just_record $exe-$nonce\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/execve_failed.run",
    "content": "source `dirname $0`/util.sh\n_RR_TRACE_DIR=\"$workdir\" $RR_EXE record program_that_does_not_exist\nexit_code=$?\nif [[ $exit_code != 69 ]]; then\n  failed \"Got exit code $exit_code, expected 69\"\nfi\n"
  },
  {
    "path": "src/test/execve_loop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* The runner script bombards us with SIGCHLDs. It's quite likely that one\n   of these will be received during an AutoRemoteSyscalls sycall, which is\n   what we want to test here. */\n\nint main(__attribute__((unused)) int argc, char* argv[], char* envp[]) {\n  int count = atoi(argv[1]);\n\n  if (count > 0) {\n    char buf[16];\n    sprintf(buf, \"%d\", count - 1);\n    argv[1] = buf;\n    execve(argv[0], argv, envp);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/execve_loop.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME 100 &\n\nfor i in $(seq 1 30); do\n  sleep 0.01\n  kill -CHLD $rrpid $(pidof $TESTNAME-$nonce) >& /dev/null\ndone\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/execveat.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  test_assert(argc == 1 || (argc == 2 && !strcmp(\"self\", argv[1])));\n\n  if (argc != 2) {\n    char* new_args[] = { argv[0], \"self\", NULL };\n    int ret = syscall(RR_execveat, AT_FDCWD, argv[0], new_args, environ, 0);\n    if (ret < 0 && errno == ENOSYS) {\n      atomic_puts(\"execveat not supported, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}"
  },
  {
    "path": "src/test/exit_codes.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  int cmd;\n  test_assert(argc == 2);\n  cmd = atoi(argv[1]);\n\n  if (cmd < 0) {\n    kill(getpid(), -cmd);\n    return 0;\n  }\n\n  return cmd;\n}\n"
  },
  {
    "path": "src/test/exit_codes.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME 3\nif [[ $? != 3 ]]; then\n    failed \"Expected exit code 3\"\nfi\n\n( record $TESTNAME -5 )\nif [[ $? != 133 ]]; then\n    failed \"Expected exit signal 5\"\nfi\n\n"
  },
  {
    "path": "src/test/exit_fast.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util_syscall.h\"\n\nvoid _start(void) {\n    unbufferable_syscall(RR_exit, 77, 0, 0);\n}\n"
  },
  {
    "path": "src/test/exit_group.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\npthread_barrier_t bar;\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  pthread_barrier_wait(&bar);\n\n  sleep(-1);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t t;\n\n  pthread_barrier_init(&bar, NULL, 2);\n\n  pthread_create(&t, NULL, thread, NULL);\n\n  pthread_barrier_wait(&bar);\n\n  atomic_puts(\"_exit()ing\");\n\n  _exit(0);\n  return 0; /* not reached */\n}\n"
  },
  {
    "path": "src/test/exit_group.run",
    "content": "source `dirname $0`/util.sh\ncompare_test '_exit()ing'\n"
  },
  {
    "path": "src/test/exit_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\ntypedef void* (* SyscallbufPtr)(void);\n\nstatic SyscallbufPtr syscallbuf_ptr;\n\nstatic void* syscallbuf;\n\nvoid* do_thread(__attribute__((unused)) void* p) {\n  struct timeval tv;\n  /* (Kick on the syscallbuf lib.) */\n  gettimeofday(&tv, NULL);\n  syscallbuf = syscallbuf_ptr();\n  return NULL;\n}\n\nint main(void) {\n  int i;\n  syscallbuf_ptr = (SyscallbufPtr)dlsym(RTLD_DEFAULT, \"syscallbuf_ptr\");\n  if (!syscallbuf_ptr) {\n    atomic_puts(\"Syscallbuf not enabled\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  for (i = 0; i < 100; ++i) {\n    pthread_t thread;\n    volatile char* p;\n    pthread_create(&thread, NULL, do_thread, NULL);\n    /* Try to make this mmap() happen between the thread calling exit()\n       and actually exiting */\n    p = (volatile char*)mmap(syscallbuf, 1, PROT_READ | PROT_WRITE,\n                             MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n    test_assert(p != MAP_FAILED);\n    pthread_join(thread, NULL);\n    *p = 1;\n    munmap((char*)p, 1);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/exit_race.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"--chaos -c100\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/exit_status.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) { return 7; }\n"
  },
  {
    "path": "src/test/exit_status.run",
    "content": "source `dirname $0`/util.sh\nrecord exit_status$bitness\nif [[ $? != 7 ]]; then\n    failed \"got exit status $?, expected 7\"\nelse\n    passed\nfi\n"
  },
  {
    "path": "src/test/exit_with_syscallbuf_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic SyscallWrapper delayed_syscall;\n\nstatic void* run_child(__attribute__((unused)) void* arg) {\n  /* context-switch events will happen during our long delay in the syscallbuf.\n     These will be queued and must be processed during exit.\n     In general these could be other signals that must not be dropped\n     so we want to handle them. */\n  struct syscall_info exit_syscall = { SYS_exit, { 0, 0, 0, 0, 0, 0 } };\n  delayed_syscall(&exit_syscall);\n  test_assert(0 && \"Should not reach here!\");\n  return 0;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  delayed_syscall = get_delayed_syscall();\n  if (delayed_syscall == default_syscall_wrapper) {\n    atomic_puts(\"syscallbuf not loaded\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  pthread_create(&thread, NULL, run_child, NULL);\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/expect_in_atomic_printf.py",
    "content": "from util import *\nimport re\n\nsend_gdb('bt')\nexpect_gdb('atomic_printf')\n\nok()\n"
  },
  {
    "path": "src/test/expect_in_exit.py",
    "content": "from util import *\nimport re\n\nsend_gdb('reverse-stepi')\nsend_gdb('bt')\nexpect_gdb('_exit')\n\nok()\n"
  },
  {
    "path": "src/test/explicit_checkpoint_clone.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n# Now we should be in the clone() thread. checkpoint here.\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('c')\nexpect_gdb('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/explicit_checkpoint_clone.run",
    "content": "source `dirname $0`/util.sh\nrecord clone$bitness\ndebug_gdb_only explicit_checkpoint_clone\n"
  },
  {
    "path": "src/test/fadvise.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  /* There's not a (simple) way to meaningfully test fadvise,\n   * since it only provides optimization hints, so this just\n   * checks that rr doesn't blow up when it sees one. */\n  posix_fadvise(-1, 0, 0, POSIX_FADV_NORMAL);\n  syscall(SYS_fadvise64, -1, (size_t)0, (size_t)0, POSIX_FADV_NORMAL);\n#if defined(SYS_fadvise64_64)\n  syscall(SYS_fadvise64_64, -1, POSIX_FADV_NORMAL, (size_t)0, (size_t)0);\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fanotify.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct fanotify_event_metadata* event;\n  int file_fd;\n  int fd = fanotify_init(0, O_RDONLY);\n\n  if (fd == -1 && errno == EPERM) {\n    atomic_puts(\"fanotify requires CAP_SYS_ADMIN (in the root namespace) but \"\n                \"we don't have those privileges; skipping tests\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  if (fd == -1 && errno == ENOSYS) {\n    atomic_puts(\"fanotify is not available in this kernel; skipping tests\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(fd >= 0);\n\n  file_fd = open(\"foo\", O_WRONLY | O_CREAT, 0777);\n  test_assert(file_fd >= 0);\n  test_assert(0 == close(file_fd));\n\n  test_assert(0 == fanotify_mark(fd, FAN_MARK_ADD, FAN_OPEN, AT_FDCWD, \"foo\"));\n\n  file_fd = open(\"foo\", O_WRONLY | O_CREAT, 0777);\n  test_assert(file_fd >= 0);\n  test_assert(0 == close(file_fd));\n\n  ALLOCATE_GUARD(event, 'x');\n  test_assert(sizeof(*event) == read(fd, event, sizeof(*event)));\n  VERIFY_GUARD(event);\n  test_assert(event->event_len == sizeof(*event));\n  test_assert(event->vers == FANOTIFY_METADATA_VERSION);\n  test_assert(event->mask == FAN_OPEN);\n  test_assert(event->fd >= 0);\n  test_assert(event->pid == getpid());\n\n  test_assert(0 == unlink(\"foo\"));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fatal_init_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"nsutils.h\"\n\nstatic char ch = 1;\n\nint main(void) {\n  pid_t pid;\n  int status;\n  int ret;\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    // We may not have permission to set up namespaces, so bail.\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  // This is the first child, therefore PID 1 in its PID namespace\n  pid = fork();\n  test_assert(pid >= 0);\n  if (pid == 0) {\n    test_assert(getpid() == 1);\n    // This will be nonfatal because we don't have a handler for it.\n    kill(getpid(), SIGQUIT);\n    // Ensure at least one tick\n    if (ch == 1) {\n      ch = 3;\n    }\n    return 55;\n  }\n\n  ret = waitpid(pid, &status, 0);\n  test_assert(ret == pid);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 55);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fatal_sigsegv_thread.c",
    "content": "#include \"util.h\"\n\nstatic void *run_thread(__attribute__((unused)) void* p) {\n    crash_null_deref();\n    return NULL;\n}\n\nstatic void* no_nothing_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n  }\n  return NULL;\n}\n\n#define NUSELESS 10\n\nint main(__attribute__((unused)) int argc,\n         __attribute__((unused)) const char** argv) {\n\n    pid_t child;\n    if ((child = fork()) == 0) {\n        pthread_t thread;\n        pthread_t useless_threads[NUSELESS];\n        for (int i = 0; i < NUSELESS; ++i) {\n            pthread_create(&useless_threads[i], NULL, no_nothing_thread, NULL);\n        }\n\n        pthread_create(&thread, NULL, run_thread, NULL);\n        pthread_join(thread, NULL);\n        test_assert(0 && \"Should not reach here\");\n    }\n\n    int status;\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n\n"
  },
  {
    "path": "src/test/fcntl_dupfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n\n  fd = fcntl(1, F_DUPFD, 3);\n  test_assert(fd >= 3);\n  close(1);\n\n  fd = dup2(fd, 1);\n  test_assert(fd == 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_lease.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"tmpfile\", O_RDWR | O_CREAT | O_TRUNC, 0600);\n  test_assert(fd >= 0);\n  int ret = fcntl(fd, F_SETLEASE, F_WRLCK);\n  test_assert(!ret);\n  ret = fcntl(fd, F_GETLEASE);\n  test_assert(ret == F_WRLCK);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_misc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fds[2];\n  int ret;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  ret = pipe(fds);\n  test_assert(ret == 0);\n  size_t new_size = 2 * page_size;\n  ret = fcntl(fds[0], F_SETPIPE_SZ, new_size);\n  if (ret == -EPERM) {\n    // Pipe resource buffer exhausted, e.g. due to\n    // /proc/sys/fs/pipe-max-size or /proc/sys/fs/pipe-user-pages-{hard, soft}.\n    atomic_puts(\"Pipe buffer exhausted during F_SETPIPE_SZ. Skipping.\");\n    new_size = page_size;\n  } else {\n    test_assert(ret == (int)(new_size));\n  }\n\n  ret = fcntl(fds[1], F_GETPIPE_SZ);\n  test_assert(ret == (int)(new_size));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_notify.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char tmp_name[] = \"tempXXXXXX\";\nstatic int saw_sigio = 0;\n\nvoid catcher(__attribute__((unused)) int signum) {\n  saw_sigio = 1;\n}\n\nint main(void) {\n  int fd, file_fd;\n  mkdtemp(tmp_name);\n  signal(SIGIO, catcher);\n\n  fd = open(tmp_name, O_RDONLY | O_DIRECTORY);\n  test_assert(fd >= 0);\n\n  fcntl(fd, F_NOTIFY, DN_CREATE);\n\n  file_fd = openat(fd, \"foo\", O_RDWR | O_CREAT, 0600);\n  test_assert(file_fd >= 0);\n  test_assert(saw_sigio);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_owner_ex.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void dump_owner(const char* tag, int fd) {\n  struct f_owner_ex own;\n\n  memset(&own, 0, sizeof(own));\n  test_assert(0 == fcntl(fd, F_GETOWN_EX, &own));\n  atomic_printf(\"%s: { type: %d, pid: %d }\\n\", tag, own.type, own.pid);\n}\n\nint main(void) {\n  int sockfds[2];\n  int fd;\n  struct f_owner_ex own;\n\n  test_assert(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds));\n  fd = sockfds[0]; /* doesn't matter */\n\n  test_assert(0 == fcntl(fd, F_SETFL, O_ASYNC));\n\n  dump_owner(\"initially\", fd);\n\n  own.type = F_OWNER_TID;\n  own.pid = getpid();\n  test_assert(0 == fcntl(fd, F_SETOWN_EX, &own));\n\n  dump_owner(\"after SETOWN_EX(TID, self)\", fd);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_rw_hints.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_MEMFD \"foo\"\n\n#ifndef MFD_CLOEXEC\n#define MFD_CLOEXEC 0x0001\n#define MFD_ALLOW_SEALING 0x0002\n#endif\n\n#ifndef F_ADD_SEALS\n#define F_ADD_SEALS 0x409\n#endif\n\n#ifndef F_SEAL_SEAL\n#define F_SEAL_SEAL 0x0001\n#define F_SEAL_SHRINK 0x0002\n#define F_SEAL_GROW 0x0004\n#define F_SEAL_WRITE 0x0008\n#endif\n\n#ifndef F_GET_RW_HINT\n#define F_GET_RW_HINT 1035\n#define F_SET_RW_HINT 1036\n#define F_GET_FILE_RW_HINT 1037\n#define F_SET_FILE_RW_HINT 1038\n#endif\n\n#ifndef RWF_WRITE_LIFE_NOT_SET\n#define RWF_WRITE_LIFE_NOT_SET 0\n#define RWH_WRITE_LIFE_NONE 1\n#define RWH_WRITE_LIFE_SHORT 2\n#define RWH_WRITE_LIFE_MEDIUM 3\n#define RWH_WRITE_LIFE_LONG 4\n#define RWH_WRITE_LIFE_EXTREME 5\n#endif\n\nint main(void) {\n  int fd = open(\"tempfile\", O_RDWR | O_CREAT, 0700);\n  int ret;\n  uint64_t hint;\n  test_assert(fd >= 0);\n\n  hint = RWH_WRITE_LIFE_MEDIUM;\n  ret = fcntl(fd, F_SET_RW_HINT, &hint);\n  if (ret < 0) {\n    test_assert(errno == EINVAL);\n    atomic_puts(\"F_SET_RW_HINT not supported\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  hint = 99;\n  ret = fcntl(fd, F_GET_RW_HINT, &hint);\n  test_assert(ret == 0);\n  test_assert(hint == RWH_WRITE_LIFE_MEDIUM);\n\n  hint = RWH_WRITE_LIFE_LONG;\n  ret = fcntl(fd, F_SET_FILE_RW_HINT, &hint);\n  if (ret < 0) {\n    test_assert(errno == EINVAL);\n    atomic_puts(\"F_SET_FILE_RW_HINT support removed\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  hint = 99;\n  ret = fcntl(fd, F_GET_FILE_RW_HINT, &hint);\n  test_assert(ret == 0);\n  test_assert(hint == RWH_WRITE_LIFE_LONG);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_seals.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_MEMFD \"foo\"\n\n#ifndef MFD_CLOEXEC\n#define MFD_CLOEXEC 0x0001\n#define MFD_ALLOW_SEALING 0x0002\n#endif\n\n#ifndef F_ADD_SEALS\n#define F_ADD_SEALS 0x409\n#endif\n#ifndef F_GET_SEALS\n#define F_GET_SEALS 0x40a\n#endif\n\n#ifndef F_SEAL_SEAL\n#define F_SEAL_SEAL 0x0001\n#define F_SEAL_SHRINK 0x0002\n#define F_SEAL_GROW 0x0004\n#define F_SEAL_WRITE 0x0008\n#endif\n\nint main(void) {\n  int fd;\n\n  /* There's no libc helper for this syscall. */\n  fd = syscall(RR_memfd_create, TEST_MEMFD, MFD_ALLOW_SEALING);\n  if (-1 == fd && ENOSYS == errno) {\n    atomic_puts(\"SYS_memfd_create not supported on this kernel\");\n  } else if (-1 == fd && EINVAL == errno) {\n    atomic_puts(\"MFD_ALLOW_SEALING not supported on this kernel\");\n  } else {\n    int seals;\n    test_assert(fd >= 0);\n    test_assert(\n        fcntl(fd, F_ADD_SEALS, F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW) == 0);\n    /* Seal after F_SEAL_SEAL should fail */\n    test_assert(fcntl(fd, F_ADD_SEALS,\n                      F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW) == -1);\n    seals = fcntl(fd, F_GET_SEALS, 0);\n    test_assert(seals == (F_SEAL_SEAL | F_SEAL_SHRINK | F_SEAL_GROW));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fcntl_sig.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  test_assert(0 == fcntl(1, F_SETSIG, SIGCHLD));\n  test_assert(SIGCHLD == fcntl(1, F_GETSIG, 0));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fd_cleanup.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  sleep(1000);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  pid_t child;\n  int status;\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  sched_yield();\n  child = fork();\n  if (child == 0) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n  wait(&status);\n  test_assert(WIFEXITED(status));\n  test_assert(WEXITSTATUS(status) == 77);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fd_leak.run",
    "content": "source `dirname $0`/util.sh\nnum_baseline=$(ls -la /proc/self/fd | wc -l)\njust_record $(which rr) \"record --nested=detach ls -la /proc/self/fd\"\nreplay\nnum_replay=$(cat replay.out | wc -l)\n# We allow for two extra fds in the recorded process,\n# one for the RR fd 999 and one for the perf_events\n# fd opened by the syscall buf (if present).\nexpected_extra_fds=2\nif [[ \"-n\" == \"$LIB_ARG\" ]]; then\nexpected_extra_fds=$((expected_extra_fds - 1))\nfi\nif [[ $num_replay -gt $((num_baseline + expected_extra_fds)) || $num_replay -lt $num_baseline ]]; then\n    failed\nelse\n    passed\nfi\n"
  },
  {
    "path": "src/test/fd_limit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  struct rlimit limit;\n  int ret = getrlimit(RLIMIT_NOFILE, &limit);\n  int new_fd;\n  rlim_t initial_limit = limit.rlim_cur;\n  test_assert(ret >= 0);\n\n  if (initial_limit + 10 > limit.rlim_max) {\n    atomic_puts(\"Current soft limit cannot be increased enough, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  /* Increase soft limit. */\n  limit.rlim_cur += 10;\n  ret = setrlimit(RLIMIT_NOFILE, &limit);\n  test_assert(ret >= 0);\n\n  /* Consume file descriptors until we've allocated all previously available descriptors (plus one). */\n  do {\n    new_fd = open(\"/dev/null\", O_RDONLY);\n    test_assert(new_fd >= 0);\n  } while (new_fd < (int)initial_limit);\n\n  /* This will allocate new fds for thread stack and syscallbuf stuff */\n  pthread_create(&thread, NULL, do_thread, NULL);\n  pthread_join(thread, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fd_limit.run",
    "content": "source `dirname $0`/util.sh\nulimit -S -n 1024\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/fd_tracking_across_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  test_assert(11 == dup2(STDOUT_FILENO, 11));\n  test_assert(14 == write(11, \"EXIT-SUCCESS\\n\", 14));\n\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  pthread_exit(NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fds_clean.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n\n  for (fd = 3; fd < 100; ++fd) {\n    /* Check that |fd| is available to us. */\n    test_assert(dup2(2, fd) == fd);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fexecve.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  test_assert(argc == 1 || (argc == 2 && !strcmp(\"self\", argv[1])));\n\n  if (argc != 2) {\n    int fd = open(\"/proc/self/exe\", O_RDONLY);\n    test_assert(fd >= 0);\n    char* new_args[] = { argv[0], \"self\", NULL };\n    int ret = syscall(RR_execveat, fd, \"\", new_args, environ, AT_EMPTY_PATH);\n    if (ret < 0 && errno == ENOSYS) {\n      atomic_puts(\"execveat not supported, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}"
  },
  {
    "path": "src/test/fexecve_memfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void copy_file(int from_fd, int to_fd) {\n  char buf[4096];\n  ssize_t ret;\n\n  while ((ret = read(from_fd, buf, sizeof(buf))) > 0) {\n    test_assert(write(to_fd, buf, ret) == ret);\n  }\n  test_assert(ret == 0);\n}\n\nint main(int argc, char* argv[]) {\n  test_assert(argc == 1 || (argc == 2 && !strcmp(\"self\", argv[1])));\n\n  if (argc != 2) {\n    int fd = open(\"/proc/self/exe\", O_RDONLY);\n    test_assert(fd >= 0);\n    int memfd = syscall(RR_memfd_create, \"test\", 0);\n    copy_file(fd, memfd);\n    char* new_args[] = { argv[0], \"self\", NULL };\n    int ret = syscall(RR_execveat, memfd, \"\", new_args, environ, AT_EMPTY_PATH);\n    if (ret < 0 && errno == ENOSYS) {\n      atomic_puts(\"execveat not supported, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}"
  },
  {
    "path": "src/test/file_name_newline.run",
    "content": "source `dirname $0`/util.sh\n\nexe=simple$bitness\ncp ${OBJDIR}/bin/$exe \"foo\nbar\"\njust_record \"foo\nbar\"\nreplay\ncheck 'EXIT-SUCCESS'\n(rr --suppress-environment-warnings dump -b -m -p ./latest-trace|grep -q ^bar) || failed \"Can't find proper name\"\n"
  },
  {
    "path": "src/test/final_sigkill.py",
    "content": "from util import *\nimport re\n\nsend_gdb('handle SIGKILL stop')\nsend_gdb('c')\nexpect_gdb('received signal SIGKILL')\n\nrestart_replay()\nexpect_gdb('received signal SIGKILL')\n\nsend_gdb('c')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/final_sigkill.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only final_sigkill\n"
  },
  {
    "path": "src/test/first_instruction.py",
    "content": "from util import *\n\nsend_gdb('disass')\nexpect_gdb('function _start')\n\nok()\n"
  },
  {
    "path": "src/test/first_instruction.run",
    "content": "source `dirname $0`/util.sh\nrecord rr_exec_stub$bitness\ndebug_gdb_only first_instruction\n"
  },
  {
    "path": "src/test/flock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define FILENAME \"foo.txt\"\n\nint main(void) {\n  ssize_t pagesize = sysconf(_SC_PAGESIZE);\n  int fd;\n  size_t i;\n  int err;\n  pid_t parent_pid = getpid();\n  pid_t pid;\n  int status;\n\n  fd = open(FILENAME, O_CREAT | O_EXCL | O_RDWR, 0600);\n  test_assert(fd >= 0);\n\n  unlink(FILENAME);\n\n  atomic_printf(\"parent pid is %d\\n\", parent_pid);\n\n  /* Write a page's worth of data. */\n  for (i = 0; i < pagesize / sizeof(i); ++i) {\n    ssize_t nwritten = write(fd, &i, sizeof(i));\n    test_assert(nwritten == sizeof(i));\n  }\n\n  {\n    struct flock lock = {.l_type = F_RDLCK,\n                         .l_whence = SEEK_SET,\n                         .l_start = pagesize,\n                         .l_len = -pagesize / 2 };\n\n    atomic_printf(\"sizeof(flock) = %zu\\n\", sizeof(lock));\n\n    /* It should currently be unlocked. */\n    err = fcntl(fd, F_GETLK, &lock);\n    test_assert(0 == err);\n\n    atomic_printf(\"before lock: type: %d, pid: %d\\n\", lock.l_type, lock.l_pid);\n    test_assert(F_UNLCK == lock.l_type);\n\n    lock.l_type = F_RDLCK;\n    fcntl(fd, F_SETLK, &lock);\n    test_assert(0 == err);\n\n    /* Make sure our lock \"took\". */\n    if (0 == (pid = fork())) {\n      lock.l_type = F_WRLCK;\n      err = fcntl(fd, F_GETLK, &lock);\n      test_assert(0 == err);\n\n      atomic_printf(\"  after lock: type: %d, pid: %d\\n\", lock.l_type,\n                    lock.l_pid);\n      test_assert(F_RDLCK == lock.l_type && pagesize / 2 == lock.l_start &&\n                  pagesize / 2 == lock.l_len && parent_pid == lock.l_pid);\n      exit(0);\n    }\n\n    waitpid(pid, &status, 0);\n    test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n  }\n\n  {\n    struct flock64 lock = {\n      .l_type = F_WRLCK, .l_whence = SEEK_SET, .l_start = 0, .l_len = pagesize\n    };\n\n    atomic_printf(\"sizeof(flock64) = %zu\\n\", sizeof(lock));\n\n    /* We should be able to take a write lock on the whole\n     * file.  The kernel will upgrade the readlock. */\n    err = fcntl(fd, F_GETLK64, &lock);\n    test_assert(0 == err);\n\n    atomic_printf(\"before lock: type: %d, pid: %d\\n\", lock.l_type, lock.l_pid);\n    test_assert(F_UNLCK == lock.l_type);\n\n    lock.l_type = F_WRLCK;\n    fcntl(fd, F_SETLK64, &lock);\n    test_assert(0 == err);\n\n    /* Make sure our lock \"took\". */\n    if (0 == (pid = fork())) {\n      lock.l_type = F_RDLCK;\n      err = fcntl(fd, F_GETLK64, &lock);\n      test_assert(0 == err);\n\n      atomic_printf(\"  after GETLK: type: %d, pid: %d\\n\", lock.l_type,\n                    lock.l_pid);\n      test_assert(F_WRLCK == lock.l_type && 0 == lock.l_start &&\n                  pagesize == lock.l_len && parent_pid == lock.l_pid);\n\n      lock.l_type = F_RDLCK;\n      lock.l_pid = 0;\n      err = fcntl(fd, F_SETLKW64, &lock);\n      test_assert(0 == err);\n\n      atomic_printf(\"  after SETLKW: type: %d, pid: %d\\n\", lock.l_type,\n                    lock.l_pid);\n      test_assert(F_RDLCK == lock.l_type && 0 == lock.l_start &&\n                  pagesize == lock.l_len && 0 == lock.l_pid);\n\n      atomic_puts(\"  releasing lock ...\");\n      lock.l_type = F_UNLCK;\n      fcntl(fd, F_SETLK64, &lock);\n      test_assert(0 == err);\n      return 0;\n    }\n\n    atomic_puts(\"P: forcing child to block on LK, sleeping ...\");\n    usleep(500000);\n    atomic_puts(\"P: ... awake, releasing lock\");\n    lock.l_type = F_UNLCK;\n    fcntl(fd, F_SETLK64, &lock);\n    test_assert(0 == err);\n\n    waitpid(pid, &status, 0);\n    test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/flock2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n/* Test for the 'flock' system call. */\n\n#include \"util.h\"\n\n#define FILENAME \"foo.txt\"\n\nint main(void) {\n  int fd;\n  int result;\n\n  fd = open(FILENAME, O_CREAT | O_EXCL | O_RDWR, 0600);\n  test_assert(fd >= 0);\n\n  result = flock(fd, LOCK_SH);\n  test_assert(result == 0);\n\n  result = flock(fd, LOCK_EX);\n  test_assert(result == 0);\n\n  result = flock(fd, LOCK_UN);\n  test_assert(result == 0);\n\n  result = close(fd);\n  test_assert(result == 0);\n\n  result = flock(fd, LOCK_EX);\n  test_assert(result < 0);\n  test_assert(errno == EBADF);\n\n  unlink(FILENAME);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/flock_ofd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define FILENAME \"foo.txt\"\n\nstatic void verify_lock(int fd, struct flock64* lock) {\n  ssize_t pagesize = sysconf(_SC_PAGESIZE);\n  lock->l_type = F_WRLCK;\n  test_assert(0 == fcntl(fd, F_OFD_GETLK, lock));\n\n  test_assert(F_RDLCK == lock->l_type && pagesize / 2 == lock->l_start &&\n              pagesize / 2 == lock->l_len);\n}\n\nint main(void) {\n  ssize_t pagesize = sysconf(_SC_PAGESIZE);\n  int fd, fd2;\n  size_t i;\n  int err;\n  pid_t pid;\n  int status;\n\n  fd = open(FILENAME, O_CREAT | O_EXCL | O_RDWR, 0600);\n  fd2 = open(FILENAME, O_EXCL | O_RDWR);\n  test_assert(fd >= 0 && fd2 >= 0);\n\n  unlink(FILENAME);\n\n  /* Write a page's worth of data. */\n  for (i = 0; i < pagesize / sizeof(i); ++i) {\n    ssize_t nwritten = write(fd, &i, sizeof(i));\n    test_assert(nwritten == sizeof(i));\n  }\n\n  struct flock64 lock = {.l_type = F_RDLCK,\n                         .l_whence = SEEK_SET,\n                         .l_start = pagesize,\n                         .l_len = -pagesize / 2 };\n\n  /* It should currently be unlocked. */\n  err = fcntl(fd2, F_OFD_GETLK, &lock);\n  if (err < 0 && errno == EINVAL) {\n    atomic_puts(\"F_OFD_GETLK not supported\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0 == err);\n\n  test_assert(F_UNLCK == lock.l_type);\n\n  if (0 == (pid = fork())) {\n    lock.l_type = F_RDLCK;\n    fcntl(fd, F_OFD_SETLK, &lock);\n    test_assert(0 == err);\n\n    /* Close a dup of the file descriptor. This should not release the lock */\n    test_assert(0 == close(dup(fd)));\n\n    /* Make sure our lock \"took\". */\n    if (0 == (pid = fork())) {\n      verify_lock(fd2, &lock);\n      exit(0);\n    }\n\n    waitpid(pid, &status, 0);\n    test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n    return 0;\n  }\n\n  waitpid(pid, &status, 0);\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  /* Should still be locked, since the lock is associated with the file\n     descriptor, not the process */\n  verify_lock(fd2, &lock);\n\n  /* This should release the lock */\n  close(fd);\n\n  lock.l_type = F_RDLCK;\n  lock.l_whence = SEEK_SET;\n  lock.l_start = pagesize;\n  lock.l_len = -pagesize / 2;\n  lock.l_pid = 0;\n  test_assert(0 == fcntl(fd2, F_OFD_GETLK, &lock));\n  test_assert(F_UNLCK == lock.l_type);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fork_brk.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child = fork();\n  int status;\n\n  if (!child) {\n    sbrk(100000);\n    return 77;\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fork_child_crash.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  pid_t child = fork();\n  int status;\n\n  if (0 == child) {\n    atomic_printf(\"child %d\\n\", getpid());\n\n    breakpoint();\n\n    atomic_puts(\"subprocess: crashing ...\");\n    *(volatile int*)NULL = 0;\n    exit(0); /* not reached */\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  atomic_printf(\"parent: subprocess %d exited with %#x\\n\", child, status);\n  test_assert(WIFSIGNALED(status) && SIGSEGV == WTERMSIG(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fork_exec_info_thr.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe barrier$bitness\nsaved_barrier=\"barrier$bitness-$nonce\"\n\nGLOBAL_OPTIONS=\"$GLOBAL_OPTIONS -M\"\nrecord target_process$bitness \"$saved_barrier\"\nTARGET_PID=$(grep 'child ' record.out | awk '{print $4}')\nTARGET_EVENT=$(grep 'thread 2 launched ' record.out | tr ']' ' ' | awk '{print $3}')\n\necho Targeting recorded pid $TARGET_PID at event $TARGET_EVENT ...\ndebug_gdb_only get_thread_list \"-p $TARGET_PID -g 1\"\ndebug_gdb_only expect_in_atomic_printf \"-p $TARGET_PID -g $TARGET_EVENT\"\ndebug_gdb_only expect_in_exit \"-p $TARGET_PID -e\"\n"
  },
  {
    "path": "src/test/fork_many.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  for (i = 0; i < 100; ++i) {\n    pid_t child = fork();\n    if (child < 0) {\n      test_assert(errno == EAGAIN);\n    } else if (child == 0) {\n      return 77;\n    } else {\n      int status;\n      test_assert(child == wait(&status));\n      test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n    }\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fork_stress.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS 250\n\nint main(void) {\n  int i;\n\n  for (i = 0; i < NUM_ITERATIONS; ++i) {\n    pid_t child = fork();\n    if (0 == child) {\n      return 0;\n    }\n    if (0 > child) {\n      atomic_printf(\"Fork failed with errno %d\\n\", errno);\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fork_stress.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/fork_syscalls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void syscalls(int num) {\n  struct timespec ts;\n  struct timeval tv;\n  int i;\n\n  for (i = 0; i < num; ++i) {\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n  }\n}\n\nint main(void) {\n  int child;\n\n  syscalls(10);\n\n  if (0 == (child = fork())) {\n    syscalls(10);\n    atomic_printf(\"CHILD-EXIT \");\n    exit(0);\n  }\n\n  syscalls(10);\n\n  waitpid(child, NULL, 0);\n\n  atomic_puts(\"PARENT-EXIT\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fork_syscalls.run",
    "content": "source `dirname $0`/util.sh\ncompare_test \"CHILD-EXIT PARENT-EXIT\"\n"
  },
  {
    "path": "src/test/fsmount.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#include <sys/mount.h>\n\nstruct rr_mount_attr {\n  uint64_t attr_set;\n  uint64_t attr_clr;\n  uint64_t propagation;\n  uint64_t userns_fd;\n};\n\nint main(void) {\n  if (try_setup_ns(CLONE_NEWNS) < 0) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int fs_fd = syscall(RR_fsopen, \"tmpfs\", 0);\n  test_assert(fs_fd >= 0);\n\n  int ret = syscall(RR_fsconfig, fs_fd, FSCONFIG_CMD_CREATE, NULL, NULL, 0);\n  test_assert(ret == 0);\n\n  int mnt_fd = syscall(RR_fsmount, fs_fd, 0, 0);\n  test_assert(mnt_fd >= 0);\n\n  ret = syscall(RR_move_mount, mnt_fd, \"\", AT_FDCWD, \"/tmp\", MOVE_MOUNT_F_EMPTY_PATH);\n  test_assert(ret == 0);\n\n  struct rr_mount_attr attr;\n  memset(&attr, 0, sizeof(attr));\n  ret = syscall(RR_mount_setattr, mnt_fd, \"\", AT_EMPTY_PATH, &attr, sizeof(attr));\n  if (ret < 0 && errno == ENOSYS) {\n    // This was added in kernel 5.12 so may not be available.\n    goto skip_mount_setattr;\n  }\n  test_assert(ret == 0);\n\nskip_mount_setattr:\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/fstatat.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct stat* buf;\n  int ret;\n\n  ALLOCATE_GUARD(buf, 0);\n  ret = fstatat(AT_FDCWD, \".\", buf, 0);\n  VERIFY_GUARD(buf);\n\n  if (ret < 0) {\n    test_assert(errno == ENOSYS);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  } else {\n    test_assert(buf->st_size != 0);\n  }\n\n  int dir_fd = open(\"/proc/self\", O_PATH);\n  test_assert(dir_fd >= 0);\n\n  ALLOCATE_GUARD(buf, 0);\n  ret = fstatat(dir_fd, \"exe\", buf, 0);\n  VERIFY_GUARD(buf);\n\n  test_assert(ret == 0);\n  test_assert(buf->st_size != 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/function_calls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int result = 0;\n\nstatic void funcallD(int n) { result = n; }\n\nstatic void funcallC(int n) {\n  funcallD(n);\n  funcallD(n);\n}\n\nstatic void funcallB(int n) {\n  funcallC(n);\n  funcallC(n);\n}\n\nstatic void funcallA(int n) {\n  funcallB(n);\n  funcallB(n);\n}\n\nstatic void funcall(int n) {\n  funcallA(n);\n  funcallA(n);\n}\n\nint main(void) {\n  funcall(1);\n  funcall(1);\n\n  atomic_printf(\"result=%d\\n\", result);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/function_calls.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('n');\nsend_gdb('n');\nsend_gdb('reverse-next');\nsend_gdb('c');\n\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/function_calls.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/futex_exit_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int futex(int* uaddr, int op, int val, const struct timespec* timeout,\n                 int* uaddr2, int val2) {\n  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val2);\n}\n\nstatic void* do_thread(void* futex_addr) {\n  futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n  return NULL;\n}\n\n#define NUM_THREADS 20\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int* futex_addr = (int*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                               MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  *futex_addr = 0;\n\n  if (fork() == 0) {\n    pthread_t threads[NUM_THREADS];\n    for (int i = 0; i < NUM_THREADS; ++i) {\n      pthread_create(&threads[i], NULL, do_thread, futex_addr);\n    }\n    // Give the threads a chance to run and block in the futex call\n    for (int i = 0; i < 2*NUM_THREADS; ++i) {\n      sched_yield();\n    }\n    futex(futex_addr, FUTEX_WAKE, NUM_THREADS + 1, NULL, NULL, 0);\n    syscall(SYS_exit_group, 10);\n    test_assert(0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  int ret = futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n  // Minimize the number of instructions/syscalls between the return of that\n  // futex call, to try to race the kernel to the cleanup of the child's\n  // threads. In that spirit,  we don't assert ret here.\n  // Rather, if the futex call failed, then `ret` will be non-zero, so we will\n  // see that in the exit code.\n  _exit(ret);\n  test_assert(0);\n}\n"
  },
  {
    "path": "src/test/futex_exit_race_sigsegv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int futex(int* uaddr, int op, int val, const struct timespec* timeout,\n                 int* uaddr2, int val2) {\n  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val2);\n}\n\nstatic void* do_thread(void* futex_addr) {\n  futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n  crash_null_deref();\n  return NULL;\n}\n\n#define NUM_THREADS 20\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int* futex_addr = (int*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                               MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  *futex_addr = 0;\n\n  if (fork() == 0) {\n    pthread_t threads[NUM_THREADS];\n    for (int i = 0; i < NUM_THREADS; ++i) {\n      pthread_create(&threads[i], NULL, do_thread, futex_addr);\n    }\n    // Give the threads a chance to run and block in the futex call\n    for (int i = 0; i < 2*NUM_THREADS; ++i) {\n      sched_yield();\n    }\n    futex(futex_addr, FUTEX_WAKE, NUM_THREADS + 1, NULL, NULL, 0);\n    // Never returns - let one of the threads crash\n    futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n    test_assert(0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  int ret = futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n  // Minimize the number of instructions/syscalls between the return of that\n  // futex call, to try to race the kernel to the cleanup of the child's\n  // threads. In that spirit,  we don't assert ret here.\n  // Rather, if the futex call failed, then `ret` will be non-zero, so we will\n  // see that in the exit code.\n  _exit(ret);\n  test_assert(0);\n}\n"
  },
  {
    "path": "src/test/futex_invalid_op.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  uint32_t ftx;\n  int ret = syscall(SYS_futex, &ftx, 0x70, 0, NULL, NULL, 0);\n  test_assert(ret < 0);\n  test_assert(errno == ENOSYS);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/futex_pi.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fut = 0;\n  int ret;\n\n  ret = syscall(SYS_futex, &fut, FUTEX_LOCK_PI, (void*)0, (void*)0, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n  ret = syscall(SYS_futex, &fut, FUTEX_TRYLOCK_PI, (void*)0, (void*)0, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n  ret = syscall(SYS_futex, &fut, FUTEX_UNLOCK_PI, (void*)0, (void*)0, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n  ret = syscall(SYS_futex, &fut, FUTEX_CMP_REQUEUE_PI, (void*)0, (void*)0, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n  ret = syscall(SYS_futex, &fut, FUTEX_WAIT_REQUEUE_PI, (void*)0, (void*)0, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/futex_priorities.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int v;\nstatic volatile int v2;\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  long ret;\n  struct timespec ts = { 0, 10000000 };\n  setpriority(PRIO_PROCESS, 0, 4);\n\n  /* Sleep briefly to ensure that the main thread actually starts waiting.\n   * Otherwise there is a race condition, manifesting especially in some older\n   * kernels, where the main thread enters its futex syscall and we detect it\n   * is not ready to run, but it hasn't actually started waiting in the kernel.\n   * We schedule this thread, which then does its WAKE_OP operation, which\n   * fails to wake up the main thread. Sleeping first ensures that the main\n   * thread really reaches its futex wait state before we try to wake it.\n   */\n  nanosleep(&ts, NULL);\n\n  ret = syscall(SYS_futex, &v, FUTEX_WAKE_OP, 1, (void*)0, &v2,\n                FUTEX_OP(FUTEX_OP_SET, 1, FUTEX_OP_CMP_EQ, 0));\n  test_assert(ret == 1);\n  /* We test that the side effects of this syscall on v2 (setting it to 1)\n     are performed before we context-switch to the main thread and run it. */\n  atomic_printf(\"thread: v2 = %d\\n\", v2);\n\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, run_thread, NULL);\n\n  atomic_printf(\"v2 = %d\\n\", v);\n\n  test_assert(0 == syscall(SYS_futex, &v, FUTEX_WAIT, 0, (void*)0, (void*)0, 0));\n  test_assert(1 == v2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/futex_requeue.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int v;\nstatic volatile int v2;\n\nstatic volatile int saw_v2_equals_1;\nstatic volatile int saw_v2_equals_2;\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  test_assert(0 == syscall(SYS_futex, &v, FUTEX_WAIT, 0, (void*)0, (void*)0, 0));\n  if (v2 == 1) {\n    ++saw_v2_equals_1;\n  } else if (v2 == 2) {\n    ++ saw_v2_equals_2;\n  }\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread1, thread2, thread3;\n\n  v = 0;\n  v2 = 1;\n  pthread_create(&thread1, NULL, run_thread, NULL);\n  pthread_create(&thread2, NULL, run_thread, NULL);\n  pthread_create(&thread3, NULL, run_thread, NULL);\n\n  // Give all the threads a chance to block.\n  usleep(500000);\n\n  // Wake one thread, and requeue one thread onto v2.\n  test_assert(2 == syscall(SYS_futex, &v, FUTEX_REQUEUE, 1, 1, &v2, 0));\n  usleep(250000);\n\n  test_assert(-1 == syscall(SYS_futex, &v, FUTEX_CMP_REQUEUE, 1, 1, &v2, 42));\n  test_assert(EAGAIN == errno);\n\n  // Requeue the remaining thread onto v2.\n  test_assert(1 == syscall(SYS_futex, &v, FUTEX_REQUEUE, 0, 1, &v2, 0));\n  usleep(250000);\n\n  ++v2;\n  // Wake both threads.\n  test_assert(2 == syscall(SYS_futex, &v2, FUTEX_CMP_REQUEUE, 2, INT_MAX, &v, 2));\n\n  pthread_join(thread1, NULL);\n  pthread_join(thread2, NULL);\n  pthread_join(thread3, NULL);\n\n  test_assert(saw_v2_equals_1 == 1);\n  test_assert(saw_v2_equals_2 == 2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/futex_restart_clone.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n// In this test we attempt to set up the following situation:\n// 1. The parent process gets kicked out of the futex wait by a signal.\n// 2. The child process execs and rr commandeers the parent process for cleanup.\n// 3. AutoRemoteSyscalls uses PTRACE_INTERRUPT to work around #3141\n// 4. rr attempts to inject the signal and sees a spurious group stop from the\n//    PTRACE_INTERRUPT.\n\npid_t parent_tid;\npid_t child_pid;\n\nstatic int futex(int* uaddr, int op, int val, const struct timespec* timeout,\n                 int* uaddr2, int val2) {\n  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val2);\n}\n\nstatic int child(__attribute__((unused)) void* arg) {\n  sched_yield();\n\n  tgkill(parent_tid, parent_tid, SIGUSR1);\n  char* execv_argv[] = {\"/proc/self/exe\", \"--inner\", NULL};\n  execve(\"/proc/self/exe\", execv_argv, NULL);\n  test_assert(0 && \"Exec should not have failed\");\n\n  /* NOT REACHED */\n  return 0;\n}\n\nstatic void usr1_handler(\n                    __attribute__((unused)) int sig,\n                    __attribute__((unused)) siginfo_t* si,\n                    __attribute__((unused)) void* p) {\n  atomic_printf(\"EXIT-SUCCESS\\n\");\n  kill(child_pid, SIGKILL);\n  exit(0);\n}\n\nint main(int argc, char *argv[]) {\n  if (argc == 2) {\n    test_assert(strcmp(argv[1], \"--inner\") == 0);\n    pause();\n    return 0;\n  }\n\n  parent_tid = sys_gettid();\n\n  struct sigaction sa;\n\n  sa.sa_sigaction = usr1_handler;\n  sa.sa_flags = SA_SIGINFO | SA_RESTART;\n  sigaction(SIGUSR1, &sa, NULL);\n\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(stack != MAP_FAILED);\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int* futex_addr = (int*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                               MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(futex_addr != MAP_FAILED);\n  *futex_addr = 0;\n\n  child_pid = clone(child, stack + stack_size, CLONE_VM | SIGCHLD, NULL, NULL, NULL,\n              NULL);\n\n  // Wait on the futex addr. This is a restartable syscall and we're expecting\n  // that the child's exec will kick us out of the syscall with register state\n  // indicating the potential for a restart.\n  futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n  test_assert(0 && \"Futex should not have returned\");\n}\n"
  },
  {
    "path": "src/test/futex_restart_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"util_internal.h\"\n\n// This test is extremely sensitive to scheduling differences.\n// Essentially the key ingredients that need to happen are:\n//\n// Condition 1. A futex system call gets interrupted by a signal\n// Condition 2. ... But the signal gets dequeued by another thread\n// Condition 3. ... and before rr schedules it again, yet another thread performs an execve\n// Condition 4. ... and rr notices that the signal-interrupted happened\n// Condition 5. ... and every other thread is blocked, so it is forced to use the signal-interrupted thread for execve-cleanup\n// Condition 6. ... And the AutoRemoteSyscall is forced through the non-singlestep path\n\nint pid_pipe[2];\npid_t parent_pid;\n\nstatic int futex(int* uaddr, int op, int val, const struct timespec* timeout,\n                 int* uaddr2, int val2) {\n  sigset_t set;\n  sigemptyset(&set);\n  // Block SIGTRAP to force non-singlestep path in AutoRemoteSyscall (Condition 6)\n  sigaddset(&set, SIGTRAP);\n  pthread_sigmask(SIG_BLOCK, &set, NULL);\n  return syscall(SYS_futex, uaddr, op, val, timeout, uaddr2, val2);\n}\n\nstatic void handle_usr1(__attribute__((unused)) int sig) {\n  test_assert(0 && \"Should have been dequeued in sigtimedwait\");\n}\n\nstatic void *do_thread(void* futex_addr) {\n  atomic_printf(\"Thread tid is %d\\n\", sys_gettid());\n  pid_t thread_tid = sys_gettid();\n  int ret = write(pid_pipe[1], &thread_tid, sizeof(pid_t));\n  test_assert(ret == sizeof(pid_t));\n  futex(futex_addr, FUTEX_WAIT, 0, NULL, NULL, 0);\n  test_assert(0); // Should not return. If the bug happens, futex returns with -512 (ERESTARTSYS)\n  return NULL;\n}\n\nchar* execv_argv[] = {\"/proc/self/exe\", \"--inner\", NULL};\nstatic int clone_child(void *unused) {\n  (void)unused;\n  // Give the parent a chance to enter wait4.\n  for (int i = 0; i < 5; ++i)\n    sched_yield();\n  kill(parent_pid, SIGUSR1);\n  execve(\"/proc/self/exe\", execv_argv, NULL);\n  test_assert(0 && \"Exec should not have failed\");\n  return 0;\n}\n\nint main(int argc, char *argv[]) {\n  if (argc == 2) {\n    test_assert(strcmp(argv[1], \"--inner\") == 0);\n    return 0;\n  }\n\n  if (!running_under_rr()) {\n    atomic_puts(\"WARNING: This test only works under rr.\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n  }\n\n  parent_pid = getpid();\n  int ret = pipe(pid_pipe);\n  test_assert(ret == 0);\n\n  // Make sure that SIGUSR1 is able to be sent to both threads.\n  signal(SIGUSR1, handle_usr1);\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int* futex_addr = (int*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                               MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(futex_addr != MAP_FAILED);\n  *futex_addr = 0;\n\n  char *child_stack = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(child_stack != MAP_FAILED);\n\n  pthread_t thread;\n  pthread_create(&thread, NULL, do_thread, futex_addr);\n\n  pid_t thread_tid;\n  ret = read(pid_pipe[0], &thread_tid, sizeof(pid_t));\n  test_assert(ret == sizeof(pid_t));\n\n  siginfo_t info;\n  sigset_t set;\n  sigemptyset(&set);\n  // Block all relevant signals on the main thread to make sure that\n  // the thread gets selected to receive the signal (Condition 1).\n  // Corner case: Because we do waitpid below, the kernel internally removes\n  // SIGCHLD from the blocked list for this thread and does not wake up\n  // the thread. To work around this, we send SIGUSR1 as well.\n  sigaddset(&set, SIGCHLD);\n  sigaddset(&set, SIGUSR1);\n  ret = pthread_sigmask(SIG_BLOCK, &set, NULL);\n  test_assert(ret == 0);\n\n  // Make sure the thread had a chance to enter the futex.\n  for (int i = 0; i < 10; ++i) {\n    sched_yield();\n  }\n\n  // Prevent rr from scheduling the thread until we've properly established all\n  // the required conditions for reproducing the bug.\n  rr_freeze_tid(thread_tid, 1);\n  // Like vfork, but without suspending the parent thread\n  pid_t child = clone(clone_child, child_stack + page_size, CLONE_VM | SIGCHLD, NULL);\n  test_assert(child != -1);\n  int status;\n  // Make sure that this thread is blocked while the child's execve\n  // happens, to make sure the thread is selected to perform execve\n  // cleanup (Condition 5).\n  // N.B.: vfork could work here also (and was used in the original bug report),\n  // but is racy, because vfork gets released before the ptrace exec notification happens.\n  pid_t waited = waitpid(-1, &status, 0);\n  test_assert(waited == child);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n  // Dequeue all signals before we allow the thread to run again (Condition 2).\n  for (int i = 0; i < 2; ++i) {\n    int sig = sigwaitinfo(&set, &info);\n    test_assert(sig == SIGCHLD || sig == SIGUSR1);\n  }\n  rr_freeze_tid(thread_tid, 0);\n  // Make sure the thread gets a chance to run before it's shot down.\n  sched_yield();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n"
  },
  {
    "path": "src/test/gcrypt_rdrand.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  FILE* file = fopen(\"/etc/gcrypt/hwf.deny\", \"r\");\n\n  test_assert(file != NULL);\n  while (1) {\n    char* buf = NULL;\n    size_t len = 0;\n    ssize_t bytes = getline(&buf, &len, file);\n    test_assert(bytes >= 0);\n    if (strcmp(buf, \"intel-rdrand\\n\") == 0) {\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    free(buf);\n  }\n}\n"
  },
  {
    "path": "src/test/gdb_bogus_breakpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char ch = 'E';\n\nstatic char my_write(int fd, void* buf, size_t size) {\n/* Do a write syscall where the address of the buffer\n   is at the top of stack during the syscall. This may trigger\n   gdb to try to set a breakpoint in that buffer. */\n#ifdef __x86_64__\n  long ret;\n  asm(\"push %5\\n\\t\"\n      \"syscall\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"pop %5\\n\\t\"\n      \"mov (%5),%0\\n\\t\"\n      : \"=a\"(ret)\n      : \"a\"(SYS_write), \"D\"(fd), \"S\"(buf), \"d\"(size), \"r\"(&ch));\n#elif __i386__\n  long ret;\n  asm(\"push %5\\n\\t\"\n      \"int $0x80\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"pop %5\\n\\t\"\n      \"mov (%5),%0\\n\\t\"\n      : \"=a\"(ret)\n      : \"a\"(SYS_write), \"b\"(fd), \"c\"(buf), \"d\"(size), \"r\"(&ch));\n#elif __aarch64__\n  register long x0 __asm(\"x0\") = fd;\n  register long x1 __asm(\"x1\") = (uintptr_t)buf;\n  register long x2 __asm(\"x2\") = size;\n  register long x7 __asm(\"x7\") = (uintptr_t)&ch;\n  register long x8 __asm(\"x8\") = SYS_write;\n  asm(\"stp x1, x7, [sp, #-16]!\\n\\t\"\n      \"svc #0\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"ldp x1, x7, [sp], #16\\n\\t\"\n      \"ldr x0, [x7]\\n\\t\"\n      : \"+r\"(x0)\n      : \"r\"(x1), \"r\"(x2), \"r\"(x8), \"r\"(x7));\n  long ret = x0;\n#else\n#error Unknown architecture\n#endif\n  return ret;\n}\n\nint main(void) {\n  test_assert('E' == my_write(STDOUT_FILENO, &ch, 1));\n  atomic_puts(\"XIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/gdb_bogus_breakpoint.py",
    "content": "from util import *\n\nsend_gdb('break my_write')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('s')\n\nsend_gdb('c')\n# First E may be printed by itself during 's'\nexpect_rr('XIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/gdb_bogus_breakpoint.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/gdb_qpasssignals.c",
    "content": "#include \"util.h\"\n\nstatic unsigned count = 0;\n\nvoid sig_handler(int sigNum) {\n    (void)sigNum;\n    ++count;\n}\n\nint main(void) {\n    atomic_puts(\"XIT-START\");\n    test_assert(signal(SIGURG, sig_handler) != SIG_ERR);\n\n    for (int i = 0; i < 10 * 1000; ++i) {\n        raise(SIGURG);\n    }\n\n    atomic_puts(\"XIT-END\");\n\n    return 0;\n}"
  },
  {
    "path": "src/test/gdb_qpasssignals.py",
    "content": "from util import *\n\nsend_gdb('handle SIGURG noprint nostop pass')\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('c')\n\n\nexpect_rr('XIT-END')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('reverse-continue')\n\nexpect_gdb('Breakpoint 1')\nok()"
  },
  {
    "path": "src/test/gdb_qpasssignals.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/generic_break.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/get_thread_list.py",
    "content": "from util import *\nimport re\n\nNUM_THREADS = 10\n\nsend_gdb('b hit_barrier')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, hit_barrier')\n\narch = get_exe_arch()\n\n# The locations the threads are stopped at depends on the architecture.\nstopped_locations = {\n    # on i386, we sometimes stop in the middle of nowhere\n    'i386': ['(0x[0-9a-f]+ in )?__kernel_vsyscall',\n             '(0x[0-9a-f]+ in )?_traced_raw_syscall',\n             '0x[0-9a-f]+ in \\?\\?',\n             '(0x[0-9a-f]+ in )?syscall_traced',\n             '(0x[0-9a-f]+ in )?rr_page_start',\n             '(0x[0-9a-f]+ in )?__lll_lock_wait',\n             '(0x[0-9a-f]+ in )?pthread_barrier_wait',\n             '(0x[0-9a-f]+ in )?futex_wait'],\n    'i386:x86-64': ['(0x[0-9a-f]+ in )?__lll_lock_wait',\n                    '(0x[0-9a-f]+ in )?pthread_barrier_wait',\n                    '(0x[0-9a-f]+ in )?futex_wait',\n                    '0x0*70000002 in \\?\\?',\n                    '(0x[0-9a-f]+ in )?syscall_traced',\n                    '(0x[0-9a-f]+ in )?rr_page_start'],\n    'aarch64': ['(0x[0-9a-f]+ in )?syscall_traced',\n                '(0x[0-9a-f]+ in )?pthread_barrier_wait',\n                '(0x[0-9a-f]+ in )?futex_wait']\n}\n\nfor i in range(NUM_THREADS + 1, 1, -1):\n    # The threads are at the kernel syscall entry, or either the\n    # traced/untraced entry reached through the rr monkeypatched one.\n    # Rarely, non-main threads have been observed to be reordered (i.e. gdb\n    # did not number them in order of creation). This does not seem to be a bug\n    # so tolerate it.\n    send_gdb('info threads')\n    expect_gdb(r'%d\\s+Thread[^(]+\\(BP-THREAD-[0-9]+\\)\\s+(?:%s)'%\n               (i, '|'.join(stopped_locations[arch])))\n    expect_gdb(r'\\(rr\\)')\n\nsend_gdb('info threads')\nexpect_gdb(r'1\\s+Thread[^h]+hit_barrier \\(\\)')\n\nok()\n"
  },
  {
    "path": "src/test/get_thread_list.run",
    "content": "source `dirname $0`/util.sh\nrecord barrier$bitness\ndebug_gdb_only get_thread_list\n"
  },
  {
    "path": "src/test/getcpu.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  unsigned int* cpu;\n  unsigned int* node;\n\n  ALLOCATE_GUARD(cpu, -1);\n  ALLOCATE_GUARD(node, -1);\n  /* The 'tcache' parameter is unused in all kernels rr works on */\n  test_assert(0 == sys_getcpu(cpu, node));\n  test_assert(*cpu <= 0xffffff);\n  test_assert(*node <= 0xffffff);\n  VERIFY_GUARD(cpu);\n  VERIFY_GUARD(node);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/getcwd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  ssize_t pagesize = sysconf(_SC_PAGESIZE);\n  ssize_t two_pages_size = 2 * pagesize;\n  void* two_pages = mmap(NULL, two_pages_size, PROT_READ | PROT_WRITE,\n                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  void* two_pages_end = two_pages + two_pages_size;\n  char* cwd;\n  char* expected_cwd;\n\n  test_assert(argc == 2);\n  expected_cwd = argv[1];\n\n  test_assert(two_pages != (void*)-1);\n  /* Make the value returned into |path| overlap two physical\n   * pages. */\n  cwd = two_pages + pagesize - 3;\n  /* Fill pages with non-zeroes to ensure the returned string is\n   * properly null-terminated */\n  memset(two_pages, 0xFF, two_pages_size);\n  test_assert(cwd == getcwd(cwd, two_pages_end - (void*)cwd));\n  atomic_printf(\"current working directory is %s; should be %s\\n\", cwd,\n                expected_cwd);\n  test_assert(!strcmp(cwd, expected_cwd));\n  /* Make sure we didn't write too many bytes */\n  test_assert((unsigned char)cwd[strlen(cwd) + 1] == 0xFF);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/getcwd.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME \"$PWD\"\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/getgroups.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  gid_t groups[1024];\n  int num_groups = getgroups(ALEN(groups), groups);\n  int i;\n\n  atomic_printf(\"User %d belongs to %d groups:\\n  \", geteuid(), num_groups);\n  for (i = 0; i < num_groups; ++i) {\n    atomic_printf(\"%d,\", groups[i]);\n  }\n  atomic_puts(\"\");\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/getpwnam.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct passwd* p = getpwnam(\"root\");\n  atomic_printf(\"%d\\n\", p ? p->pw_uid : 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/getrandom.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef GRND_NONBLOCK\n#define GRND_NONBLOCK 0x0001\n#define GRND_RANDOM 0x0002\n#endif\n\nint main(void) {\n  unsigned char buf[128];\n  int ret;\n\n  memset(buf, 0, sizeof(buf));\n\n  /* There's no libc helper for this syscall. */\n  ret = syscall(RR_getrandom, buf, sizeof(buf), GRND_NONBLOCK);\n  if (-1 == ret && ENOSYS == errno) {\n    atomic_puts(\"SYS_getrandom not supported on this kernel\");\n  } else {\n    uint i;\n\n    test_assert(sizeof(buf) == ret);\n    atomic_printf(\n        \"fetched %d random bytes (non-blockingly); first few bytes:\\n  \", ret);\n    for (i = 0; i < 10; ++i) {\n      atomic_printf(\"%02x\", buf[i]);\n    }\n    atomic_puts(\"\");\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/getsid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t sid = getsid(0);\n  atomic_printf(\"getsid(0) session ID: %d\\n\", sid);\n  test_assert(sid >= 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/gettimeofday.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct timeval* tv;\n  struct timezone* tz;\n\n  ALLOCATE_GUARD(tv, 0);\n  ALLOCATE_GUARD(tz, 'x');\n  test_assert(0 == gettimeofday(tv, tz));\n  test_assert(tv->tv_sec > 0);\n  test_assert(tz->tz_dsttime == 0); /* always zero on Linux */\n  VERIFY_GUARD(tv);\n  VERIFY_GUARD(tz);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/goto_event.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void first_breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void second_breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void* child_thread(void* num_syscallsp) {\n  int num_syscalls = (uintptr_t)num_syscallsp;\n  int i;\n\n  first_breakpoint();\n\n  atomic_printf(\"%d: running %d syscalls ...\\n\", getpid(), num_syscalls);\n  for (i = 0; i < num_syscalls; ++i) {\n    event_syscall();\n  }\n\n  second_breakpoint();\n\n  return NULL;\n}\n\nstatic void child(int num_syscalls) {\n  pthread_t t;\n\n  test_assert(0 == pthread_create(&t, NULL, child_thread,\n                                  (void*)(uintptr_t)num_syscalls));\n  pthread_join(t, NULL);\n\n  exit(0);\n}\n\nint main(int argc, char** argv) {\n  int num_syscalls;\n  pid_t c;\n  int status;\n\n  test_assert(argc == 2);\n  num_syscalls = atoi(argv[1]);\n\n  if (0 == (c = fork())) {\n    child(num_syscalls);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_printf(\"%d: waiting on %d ...\\n\", getpid(), c);\n  test_assert(c == waitpid(c, &status, 0));\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/goto_event.py",
    "content": "import os\nfrom util import *\n\nsend_gdb('when')\nexpect_gdb('Completed event: %s'%os.environ['EVENTS'])\n\nsend_gdb('b first_breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b second_breakpoint')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\n# If we hit first_breakpoint, then we never continue and never reach\n# second_breakpoint.\nexpect_gdb('Breakpoint 2, second_breakpoint')\n\nrestart_replay(1)\nexpect_gdb('Breakpoint 1, first_breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/goto_event.run",
    "content": "source `dirname $0`/util.sh\n\nexport EVENTS=1000\nrecord $TESTNAME $EVENTS\n\ndebug_gdb_only goto_event \"-g $EVENTS\"\n"
  },
  {
    "path": "src/test/grandchild_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  sleep(1000);\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  pthread_t thread;\n  int pipe_fds[2];\n  char ch;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (child > 0) {\n    read(pipe_fds[0], &ch, 1);\n    kill(child, 9);\n    /* try to exit before the child's exit */\n    return 0;\n  }\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  write(pipe_fds[1], &ch, 1);\n  sleep(1000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/grandchild_threads_main_running.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  char ch;\n\n  sleep(1);\n  atomic_puts(\"EXIT-SUCCESS\");\n  write(pipe_fds[1], &ch, 1);\n  sleep(1000);\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  pthread_t thread;\n  char ch;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (child > 0) {\n    read(pipe_fds[0], &ch, 1);\n    kill(child, 9);\n    /* try to exit before the child's exit */\n    return 0;\n  }\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  while (1) {\n    asm(\"\" : : : \"memory\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/grandchild_threads_parent_alive.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  sleep(1000);\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  pthread_t thread;\n  int pipe_fds[2];\n  char ch;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (child > 0) {\n    read(pipe_fds[0], &ch, 1);\n    kill(child, 9);\n    /* wait for the child to exit before we exit */\n    waitpid(child, NULL, 0);\n    return 0;\n  }\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  write(pipe_fds[1], &ch, 1);\n  sleep(1000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/grandchild_threads_thread_running.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    asm(\"\" : : : \"memory\");\n  }\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  pthread_t thread;\n  int pipe_fds[2];\n  char ch;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (child > 0) {\n    read(pipe_fds[0], &ch, 1);\n    kill(child, 9);\n    /* try to exit before the child's exit */\n    return 0;\n  }\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  sleep(1);\n  atomic_puts(\"EXIT-SUCCESS\");\n  write(pipe_fds[1], &ch, 1);\n  sleep(1000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/group_stop_thundering_herd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic void* do_thread(void* arg) {\n  int pipe_fd = *(int*)arg;\n  uint32_t tid = sys_gettid();\n\n  write(pipe_fd, &tid, 4);\n  /* Sleep long enough that it will be noticed if it's not interrupted. */\n  sleep(1000);\n\n  return NULL;\n}\n\nint main(void) {\n  pid_t child, grandchild;\n  int sock_fds[2];\n\n  test_assert(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sock_fds));\n\n  if (0 == (child = fork())) {\n    uint32_t tid;\n    int pipe_fds[2];\n    test_assert(0 == pipe(pipe_fds));\n\n    if (0 == (grandchild = fork())) {\n      pthread_t t;\n\n      pthread_create(&t, NULL, do_thread, &pipe_fds[1]);\n      pthread_join(t, NULL);\n\n      return 77;\n    }\n\n    test_assert(4 == read(pipe_fds[0], &tid, 4));\n\n    close(pipe_fds[0]);\n    sched_yield();\n\n    test_assert(sizeof(grandchild) == send(sock_fds[1], &grandchild, sizeof(grandchild), 0));\n    /* Nothing is ever sent the other way so this just blocks. */\n    recv(sock_fds[1], &grandchild, sizeof(grandchild), 0);\n\n    return 66;\n  }\n\n  /* Get the grandchild pid. */\n  recv(sock_fds[0], &grandchild, sizeof(grandchild), 0);\n\n  /* Hit the entire process group with a SIGSTOP. */\n  tgkill(grandchild, grandchild, SIGSTOP);\n\n  /* Force the rr scheduler to run. */\n  sched_yield();\n\n  kill(SIGKILL, grandchild);\n  kill(SIGKILL, child);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/hardlink_mmapped_files.run",
    "content": "source `dirname $0`/util.sh\n\ncp $OBJDIR/lib/rr/libtest_lib$bitness.so .\n\nRECORD_ARGS=\"--env=LD_PRELOAD=libtest_lib$bitness.so\"\nrecord constructor$bitness\nrm libtest_lib$bitness.so\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/hbreak.py",
    "content": "from util import *\nimport re\n\nsend_gdb('break atomic_puts')\nexpect_gdb('Breakpoint 1')\nsend_gdb('continue')\nexpect_gdb('Breakpoint 1')\nsend_gdb('hbreak main')\nexpect_gdb('breakpoint 2')\nsend_gdb('reverse-continue')\nexpect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/hbreak.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only hbreak\n"
  },
  {
    "path": "src/test/hello.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char *argv[]) {\n  if (argc <= 1) {\n    atomic_puts(\"Hi\");\n  } else {\n    atomic_puts(argv[1]);\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/hello.run",
    "content": "source `dirname $0`/util.sh\ncompare_test 'Hi'\n"
  },
  {
    "path": "src/test/history.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpointA(__attribute__((unused)) int i) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  int i;\n  for (i = 0; i < 5; ++i) {\n    breakpointA(i);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/history.py",
    "content": "from util import *\n\nsend_gdb('b breakpointA')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\n\nexpect_gdb('i=0')\nsend_gdb('c')\nexpect_gdb('i=1')\nsend_gdb('c')\nexpect_gdb('i=2')\nsend_gdb('c')\nexpect_gdb('i=3')\nsend_gdb('c')\nexpect_gdb('i=4')\n\nsend_gdb('forward')\nexpect_gdb('Can\\'t go forward. No more history entries.')\n\nsend_gdb('back')\nexpect_gdb('i=3')\nsend_gdb('back')\nexpect_gdb('i=2')\nsend_gdb('back')\nexpect_gdb('i=1')\n\n# A diversion should not interfere with the history\nsend_gdb('call strlen(\"abcd\")')\n\nsend_gdb('back')\nexpect_gdb('i=0')\n\n# Clear the forward stack by pushing a new entry\nsend_gdb('c')\nexpect_gdb('i=1')\nsend_gdb('forward')\nexpect_gdb('Can\\'t go forward. No more history entries.')\n\nsend_gdb('back')\nexpect_gdb('i=0')\n\nsend_gdb('d 1')\nexpect_gdb('c')\n\nok()\n"
  },
  {
    "path": "src/test/history.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/hooks.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint do_close(int fd);\n\nconst int sys_close = SYS_close;\n\n#ifdef __x86_64__\nasm (\".text\\n\"\n     \"do_close:\\n\\t\"\n     \"mov sys_close(%rip),%eax\\n\\t\"\n     \"syscall\\n\\t\"\n     \"ret\\n\\t\"\n     \".byte 0x0f, 0x1f, 0x44, 0, 0\");\n#else\nint do_close(int fd) {\n  return close(fd);\n}\n#endif\n\nint main(void) {\n  int i;\n  for (i = 0; i < 1000000; ++i) {\n    do_close(50000);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/hooks.run",
    "content": "source `dirname $0`/util.sh\n\n# This test requires syscallbuf syscall patching\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/ignore_nested.c",
    "content": "#include \"util.h\"\n\n// This simply execs the commands passed to it on\n// the command line without passing through the\n// environment. The runner uses this to test\n// --nested=ignore in the absence of RR_UNDER_RR\n// environment variable.\nint main(int argc, char *argv[]) {\n    if (argc > 1 && strcmp(argv[1], \"--inner\") == 0) {\n        atomic_puts(\"EXIT-SUCCESS\");\n        return 0;\n    }\n    char *newenv[] = { NULL };\n    return execve(argv[1], &argv[1], newenv);\n}\n"
  },
  {
    "path": "src/test/ignore_nested.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME \"$(which rr) record --nested=ignore $PWD/$TESTNAME-$nonce --inner\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/ignored_async_usr1.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int dummy = 0, i;\n\n  /* NB: since we're masking out the signal, there's no way for\n   * us to tell whether or not it was actually delivered.  This\n   * test can spuriously pass if it's never sent SIGUSR1. */\n\n  signal(SIGUSR1, SIG_IGN);\n\n  atomic_puts(\"SIGUSR1 disabled\");\n\n  for (i = 1; i < (1 << 27); ++i) {\n    dummy += (dummy + i) % 9735;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ignored_async_usr1.run",
    "content": "source `dirname $0`/util.sh\n\nSYNC_TOKEN=disabled\n\nrecord $TESTNAME &\nSUB_ID=$!\n\necho \"Waiting for token '$SYNC_TOKEN' from tracee ...\"\nuntil grep -q $SYNC_TOKEN record.out; do\n        sleep 0\n        if ! kill -0 \"$SUB_ID\" >/dev/null 2>&1; then failed \"subshell died, no need to longer wait for '$SYNC_TOKEN'\"; exit; fi\ndone\n\necho \"  done.  Delivering SIGUSR1 ...\"\nkill -USR1 $rrpid $(pidof $TESTNAME-$nonce)\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/ignored_sigsegv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  crash_null_deref();\n\n  return NULL;\n}\n\nint main(void) {\n  struct sigaction act;\n  pthread_t thread;\n\n  act.sa_handler = SIG_IGN;\n  act.sa_flags = SA_NODEFER;\n  sigemptyset(&act.sa_mask);\n  sigaction(SIGSEGV, &act, NULL);\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  pthread_join(thread, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ignored_sigsegv.run",
    "content": "source `dirname $0`/util.sh\n( record $TESTNAME ) >& /dev/null\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/immediate_restart.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int child;\n\n  atomic_printf(\"%d: forking...\\n\", getpid());\n  if (0 == (child = fork())) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n\n  waitpid(child, NULL, 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/immediate_restart.py",
    "content": "from util import *\n\nrestart_replay()\n# A single EXIT-SUCCESS is expected since the child process to which we have\n# attached only prints one, and it exits before the parent prints its\n# EXIT-SUCCESS.\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/immediate_restart.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only immediate_restart \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/inotify.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct inotify_event* event;\n  int desc;\n  int file_fd;\n  int fd = inotify_init();\n  test_assert(fd >= 0);\n  test_assert(0 == close(fd));\n  fd = inotify_init1(IN_CLOEXEC);\n  test_assert(fd >= 0);\n\n  file_fd = open(\"foo\", O_WRONLY | O_CREAT, 0777);\n  test_assert(file_fd >= 0);\n  test_assert(0 == close(file_fd));\n\n  desc = inotify_add_watch(fd, \"foo\", IN_ALL_EVENTS);\n  if (desc == -1 && errno == ENOSPC) {\n    atomic_puts(\"Hit inotify watch limit\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(desc >= 0);\n\n  test_assert(0 <= open(\"foo\", O_WRONLY | O_CREAT, 0777));\n  ALLOCATE_GUARD(event, 'x');\n  test_assert(sizeof(*event) == read(fd, event, sizeof(*event)));\n  VERIFY_GUARD(event);\n  test_assert(event->wd == desc);\n  test_assert(event->mask == IN_OPEN);\n\n  test_assert(0 == inotify_rm_watch(fd, desc));\n\n  test_assert(0 == unlink(\"foo\"));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/int3.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  debug_trap();\n  /* NB: the above instruction *must* be at line 6 in this file.\n   * Tests rely on that. */\n}\n\nstatic void handle_sigtrap(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nint main(void) {\n  signal(SIGTRAP, handle_sigtrap);\n\n  atomic_puts(\"raising SIGTRAP ...\");\n\n  breakpoint();\n\n  test_assert(\"didn't catch trap!\" && 0);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/interrupt.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid spin(void) {\n  int i;\n\n  atomic_puts(\"spinning\");\n  for (i = 1; i < (1 << 30); ++i) {\n    if (0 == i % (1 << 20)) {\n      write(STDOUT_FILENO, \".\", 1);\n    }\n    if (0 == i % (79 * (1 << 20))) {\n      write(STDOUT_FILENO, \"\\n\", 1);\n    }\n  }\n}\n\nint main(void) {\n  spin();\n  atomic_puts(\"done\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/interrupt.py",
    "content": "from util import *\n\n# XXX this test is racy, because we don't have a way to halt replay\n# until some condition is satisfied.  Maybe we should add that.\nsend_gdb('c')\nexpect_rr('spinning')\ninterrupt_gdb()\n\nok()\n"
  },
  {
    "path": "src/test/interrupt.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/intr_futex_wait_restart.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char start_token = '!';\nstatic const char sentinel_token = ' ';\n\nstatic pthread_t reader;\nstatic pthread_barrier_t barrier;\nstatic pid_t reader_tid;\nstatic int reader_caught_signal;\n\nstatic int sockfds[2];\n\npthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;\npthread_cond_t cond = PTHREAD_COND_INITIALIZER;\n\nstatic void cond_wait(int secs) {\n  struct timespec ts;\n\n  clock_gettime(CLOCK_REALTIME, &ts);\n  ts.tv_sec += secs;\n\n  test_assert(ETIMEDOUT == pthread_cond_timedwait(&cond, &lock, &ts));\n}\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 1 ...\");\n  cond_wait(1);\n  atomic_puts(\"r: ... wait done\");\n}\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  char token = start_token;\n  struct sigaction act;\n  int readsock = sockfds[1];\n  char c = sentinel_token;\n  int flags = 0;\n\n  pthread_mutex_lock(&lock);\n\n  reader_tid = sys_gettid();\n\n  flags = SA_RESTART;\n\n  act.sa_handler = sighandler;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR1, &act, NULL);\n\n  act.sa_handler = SIG_IGN;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR2, &act, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  atomic_puts(\"r: blocking on read, awaiting signal ...\");\n\n  test_assert(1 == read(readsock, &c, sizeof(c)));\n  test_assert(1 == reader_caught_signal);\n\n  atomic_printf(\"r: ... read level 0 '%c'\\n\", c);\n  test_assert(c == token);\n\n  return NULL;\n}\n\nint main(void) {\n  char token = start_token;\n  struct timeval ts;\n\n  /* (Kick on the syscallbuf if it's enabled.) */\n  gettimeofday(&ts, NULL);\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n\n  pthread_barrier_init(&barrier, NULL, 2);\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  /* Force a blocked read() that's interrupted by a SIGUSR1,\n   * which then itself blocks on read() and succeeds. */\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n\n  atomic_puts(\"M: killing reader ...\");\n  pthread_kill(reader, SIGUSR1);\n  atomic_puts(\"M:   (quick nap)\");\n  usleep(100000);\n\n  atomic_puts(\"M: killing reader again ...\");\n  pthread_kill(reader, SIGUSR2);\n\n  usleep(500000);\n  atomic_printf(\"M: finishing level 0 reader by writing '%c' to socket ...\\n\",\n                token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/intr_poll.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipefds[2];\nstatic int poll_pipe(int timeout_ms) {\n  struct pollfd pfd;\n  int ret;\n\n  pfd.fd = pipefds[0];\n  pfd.events = POLLIN;\n  errno = 0;\n  ret = poll(&pfd, 1, timeout_ms);\n  /* Verify that our input fields were not trashed */\n  test_assert(pfd.fd == pipefds[0]);\n  test_assert(pfd.events == POLLIN);\n  return ret;\n}\n\nstatic int caught_signal;\nstatic void handle_signal(__attribute__((unused)) int sig) { ++caught_signal; }\n\nint main(void) {\n  struct timespec dummy;\n\n  test_assert(0 == pipe(pipefds));\n\n  signal(SIGALRM, SIG_IGN);\n  alarm(1);\n  atomic_puts(\"ignoring SIGALRM, going into poll ...\");\n  test_assert(0 == poll_pipe(1500) && 0 == errno);\n\n  signal(SIGALRM, handle_signal);\n  alarm(1);\n  atomic_puts(\"handling SIGALRM, going into poll ...\");\n  clock_gettime(CLOCK_MONOTONIC, &dummy);\n  test_assert(-1 == poll_pipe(-1) && EINTR == errno);\n  test_assert(1 == caught_signal);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/intr_ppoll.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <poll.h>\n\n#define NUM_ITERATIONS 10\n\nint main(void) {\n  int fds[2];\n  struct pollfd pfd;\n  int i;\n\n  struct timespec t;\n  t.tv_sec = 2;\n  t.tv_nsec = 0;\n\n  sigset_t sigset;\n  test_assert(0 == sigemptyset(&sigset));\n  test_assert(0 == sigaddset(&sigset, SIGCHLD));\n\n  signal(SIGALRM, SIG_IGN);\n\n  pid_t pid = getpid();\n\n  pipe2(fds, O_NONBLOCK);\n\n  pfd.fd = fds[0];\n  pfd.events = POLLIN;\n  for (i = 0; i < NUM_ITERATIONS; ++i) {\n    int ret;\n\n    atomic_printf(\"iteration %d\\n\", i);\n    if (fork() == 0) {\n      usleep(100000);\n      // SIGCHLD will be unblocked once these signals are delivered.\n      // Half the time we send SIGALRM too, to verify that SIGCHLD only becomes\n      // unblocked after *all* of these are delivered.\n      kill(pid, SIGWINCH);\n      if (i % 2) {\n        kill(pid, SIGALRM);\n      }\n      return 0;\n    }\n\n    ret = ppoll(&pfd, 1, &t, &sigset);\n\n    sigset_t after_sigset;\n    ret = sigprocmask(SIG_BLOCK, NULL, &after_sigset);\n    test_assert(ret == 0);\n    test_assert(!sigismember(&after_sigset, SIGCHLD));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/intr_pselect.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipefds[2];\nstatic int pselect_pipe(int timeout, sigset_t* sigmask) {\n  fd_set set;\n\n  FD_ZERO(&set);\n  FD_SET(pipefds[0], &set);\n  struct timespec t;\n  t.tv_sec = timeout;\n  t.tv_nsec = 0;\n\n  errno = 0;\n  return pselect(pipefds[0] + 1, &set, NULL, NULL, timeout ? &t : NULL,\n                 sigmask);\n}\n\nstatic int caught_signal;\nstatic void handle_signal(__attribute__((unused)) int sig) { ++caught_signal; }\n\nint main(void) {\n  sigset_t sigmask;\n  sigemptyset(&sigmask);\n\n  pipe(pipefds);\n\n  signal(SIGALRM, SIG_IGN);\n  alarm(1);\n  atomic_puts(\"ignoring SIGALRM, going into pselect ...\");\n  test_assert(0 == pselect_pipe(2, &sigmask) && 0 == errno);\n\n  alarm(1);\n  atomic_puts(\"ignoring SIGALRM (sigmask=NULL), going into pselect ...\");\n  test_assert(0 == pselect_pipe(2, NULL) && 0 == errno);\n\n  /* Test that the signal mask is correct in rr when the SIGALRM is delivered */\n  sigaddset(&sigmask, SIGCHLD);\n\n  signal(SIGALRM, handle_signal);\n  alarm(1);\n  atomic_puts(\"handling SIGALRM, going into pselect ...\");\n  test_assert(-1 == pselect_pipe(0, &sigmask) && EINTR == errno);\n  test_assert(1 == caught_signal);\n\n  sigaddset(&sigmask, SIGALRM);\n  alarm(1);\n  atomic_puts(\"blocking SIGALRM, going into pselect ...\");\n  test_assert(0 == pselect_pipe(2, &sigmask) && 0 == errno);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/intr_ptrace_decline.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char start_token = '!';\nstatic const char sentinel_token = ' ';\n\nstatic pthread_t reader;\nstatic pthread_barrier_t barrier;\n\nstatic int sockfds[2];\n\npthread_mutex_t lock;\npthread_cond_t cond = PTHREAD_COND_INITIALIZER;\n\nstatic void fin_intr_sleep(int secs) {\n  struct timespec req = {.tv_sec = secs };\n  struct timespec rem = {.tv_sec = -1, .tv_nsec = -1 };\n\n  test_assert(0 == nanosleep(&req, &rem));\n  /* We would normally assert that the outparam wasn't touched\n   * for this successful sleep, but ptrace-declined signals are\n   * an odd case, the only way a nanosleep can restart.  The\n   * kernel has been observed to write back the outparam at\n   * interrupt time, so we track that semantics here.\n   *\n   *  test_assert(-1 == rem.tv_sec && -1 == rem.tv_nsec);\n   */\n}\n\nstatic void fin_poll(int secs) {\n  static int pipefds[2];\n  struct pollfd pfd;\n  int ret;\n\n  pipe(pipefds);\n\n  pfd.fd = pipefds[0];\n  pfd.events = POLLIN;\n  pfd.revents = -1;\n  errno = 0;\n\n  ret = poll(&pfd, 1, 1000 * secs);\n  atomic_printf(\"r: poll() returns %d; pfd.revents = 0x%x\\n\", ret, pfd.revents);\n  test_assert(0 == ret);\n  test_assert(0 == pfd.revents);\n}\n\nstatic void cond_wait(int secs) {\n  struct timespec ts;\n\n  clock_gettime(CLOCK_REALTIME, &ts);\n  ts.tv_sec += secs;\n\n  test_assert(ETIMEDOUT == pthread_cond_timedwait(&cond, &lock, &ts));\n}\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  char token = start_token;\n  int readsock = sockfds[1];\n  char c = sentinel_token;\n\n  pthread_mutex_lock(&lock);\n\n  pthread_barrier_wait(&barrier);\n\n  atomic_puts(\"r: blocking on sleep, awaiting signal ...\");\n  fin_intr_sleep(1);\n\n  atomic_puts(\"r: blocking on poll, awaiting signal ...\");\n  fin_poll(1);\n\n  atomic_puts(\"r: blocking on futex, awaiting signal ...\");\n  cond_wait(1);\n\n  atomic_puts(\"r: blocking on read, awaiting signal ...\");\n  test_assert(1 == read(readsock, &c, sizeof(c)));\n  atomic_printf(\"r: ... read '%c'\\n\", c);\n  test_assert(c == token);\n\n  return NULL;\n}\n\nint main(void) {\n  char token = start_token;\n  struct timeval ts;\n  int i;\n\n  /* (Kick on the syscallbuf if it's enabled.) */\n  gettimeofday(&ts, NULL);\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n\n  pthread_barrier_init(&barrier, NULL, 2);\n  pthread_mutex_init(&lock, NULL);\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n  for (i = 0; i < 4; ++i) {\n    atomic_puts(\"M: killing reader ...\");\n    pthread_kill(reader, SIGUSR1);\n    atomic_puts(\"M: sleeping ...\");\n    sleep(1);\n  }\n  atomic_printf(\"M: finishing original reader by writing '%c' to socket ...\\n\",\n                token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/intr_ptrace_decline.run",
    "content": "source `dirname $0`/util.sh\n\n# Ignore SIGUSR1; block its delivery to tracees.\nRECORD_ARGS=\"-i10\"\n\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/intr_read_no_restart.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char start_token = '!';\nstatic const char sentinel_token = ' ';\n\nstatic pthread_t reader;\nstatic pthread_barrier_t barrier;\nstatic pid_t reader_tid;\nstatic int reader_caught_signal;\n\nstatic int sockfds[2];\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  char c = sentinel_token;\n\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 1 ...\");\n\n  test_assert(-1 == read(sockfds[1], &c, sizeof(c)) && EINTR == errno);\n  atomic_printf(\"r: ... read level 1 '%c'\\n\", c);\n  test_assert(c == sentinel_token);\n}\n\nstatic void sighandler2(__attribute__((unused)) int sig) {\n  char c = sentinel_token;\n\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 2 ...\");\n\n  test_assert(1 == read(sockfds[1], &c, sizeof(c)));\n  atomic_printf(\"r: ... read level 2 '%c'\\n\", c);\n  test_assert(c == start_token);\n}\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  struct sigaction act;\n  struct timeval ts;\n  int readsock = sockfds[1];\n  char c = sentinel_token;\n  int flags = 0;\n\n  reader_tid = sys_gettid();\n\n  act.sa_handler = sighandler;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR1, &act, NULL);\n\n  act.sa_handler = sighandler2;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR2, &act, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  /* (Put another record in the syscallbuf.) */\n  gettimeofday(&ts, NULL);\n\n  atomic_puts(\"r: blocking on read, awaiting signal ...\");\n\n  test_assert(-1 == read(readsock, &c, sizeof(c)) && EINTR == errno);\n  test_assert(2 == reader_caught_signal);\n  atomic_printf(\"r: ... read level 0 '%c'\\n\", c);\n  test_assert(c == sentinel_token);\n\n  return NULL;\n}\n\nint main(void) {\n  char token = start_token;\n  struct timeval ts;\n\n  /* (Kick on the syscallbuf if it's enabled.) */\n  gettimeofday(&ts, NULL);\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n\n  pthread_barrier_init(&barrier, NULL, 2);\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  /* Force a blocked read() that's interrupted by a SIGUSR1,\n   * which then itself blocks on read() and succeeds. */\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n\n  atomic_puts(\"M: killing reader ...\");\n  pthread_kill(reader, SIGUSR1);\n  atomic_puts(\"M:   (quick nap)\");\n  usleep(100000);\n\n  atomic_puts(\"M: killing reader again ...\");\n  pthread_kill(reader, SIGUSR2);\n\n  atomic_puts(\"M:   (longer nap)\");\n\n  usleep(500000);\n  atomic_printf(\"M: finishing level 2 reader by writing '%c' to socket ...\\n\",\n                token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/intr_read_restart.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char start_token = '!';\nstatic const char sentinel_token = ' ';\n\nstatic pthread_t reader;\nstatic pthread_barrier_t barrier;\nstatic pid_t reader_tid;\nstatic int reader_caught_signal;\n\nstatic int sockfds[2];\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  char c = sentinel_token;\n\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 1 ...\");\n\n  test_assert(1 == read(sockfds[1], &c, sizeof(c)));\n  atomic_printf(\"r: ... read level 1 '%c'\\n\", c);\n  test_assert(c == start_token + 1);\n}\n\nstatic void sighandler2(__attribute__((unused)) int sig) {\n  char c = sentinel_token;\n\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 2 ...\");\n\n  test_assert(1 == read(sockfds[1], &c, sizeof(c)));\n  atomic_printf(\"r: ... read level 2 '%c'\\n\", c);\n  test_assert(c == start_token);\n}\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  char token = start_token;\n  struct sigaction act;\n  int readsock = sockfds[1];\n  char c = sentinel_token;\n  int flags = 0;\n\n  reader_tid = sys_gettid();\n\n  flags = SA_RESTART;\n\n  act.sa_handler = sighandler;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR1, &act, NULL);\n\n  act.sa_handler = sighandler2;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR2, &act, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  atomic_puts(\"r: blocking on read, awaiting signal ...\");\n\n  test_assert(1 == read(readsock, &c, sizeof(c)));\n  test_assert(2 == reader_caught_signal);\n  token += reader_caught_signal;\n\n  atomic_printf(\"r: ... read level 0 '%c'\\n\", c);\n  test_assert(c == token);\n\n  return NULL;\n}\n\nint main(void) {\n  char token = start_token;\n  struct timeval ts;\n\n  /* (Kick on the syscallbuf if it's enabled.) */\n  gettimeofday(&ts, NULL);\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n\n  pthread_barrier_init(&barrier, NULL, 2);\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  /* Force a blocked read() that's interrupted by a SIGUSR1,\n   * which then itself blocks on read() and succeeds. */\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n\n  atomic_puts(\"M: killing reader ...\");\n  pthread_kill(reader, SIGUSR1);\n  atomic_puts(\"M:   (quick nap)\");\n  usleep(100000);\n\n  atomic_puts(\"M: killing reader again ...\");\n  pthread_kill(reader, SIGUSR2);\n\n  atomic_puts(\"M:   (longer nap)\");\n\n  usleep(500000);\n  atomic_printf(\"M: finishing level 2 reader by writing '%c' to socket ...\\n\",\n                token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  usleep(500000);\n  atomic_printf(\"M: finishing level 1 reader by writing '%c' to socket ...\\n\",\n                token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  usleep(500000);\n  atomic_printf(\"M: finishing original reader by writing '%c' to socket ...\\n\",\n                token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/intr_sleep.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic int interrupted_sleep(void) {\n  struct timespec ts = {.tv_sec = 2 };\n\n  alarm(1);\n  errno = 0;\n  /* The implementation of sleep() is technically allowed to use\n   * SIGALRM, so we have to use nanosleep() for pedantry. */\n  nanosleep(&ts, NULL);\n  return errno;\n}\n\nstatic int caught_signal;\nstatic void handle_signal(__attribute__((unused)) int sig) {\n  ++caught_signal;\n\n  breakpoint();\n  /* No more syscalls after here. */\n}\n\nint main(void) {\n  int err;\n\n  signal(SIGALRM, SIG_IGN);\n  err = interrupted_sleep();\n  atomic_printf(\"No sighandler; sleep exits with errno %d\\n\", err);\n  test_assert(0 == err);\n\n  signal(SIGALRM, handle_signal);\n  err = interrupted_sleep();\n  atomic_printf(\"With sighandler; sleep exits with errno %d\\n\", err);\n  test_assert(1 == caught_signal);\n  test_assert(EINTR == err);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/intr_sleep_no_restart.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pthread_t reader;\nstatic pthread_barrier_t barrier;\nstatic pid_t reader_tid;\nstatic int reader_caught_signal;\n\nstatic void intr_sleep(int secs) {\n  struct timespec req = { secs, 0 };\n  struct timespec rem = { 0, 0 };\n\n  test_assert(-1 == nanosleep(&req, &rem) && EINTR == errno);\n  test_assert(rem.tv_sec > 0 || rem.tv_nsec > 0);\n}\n\nstatic void fin_sleep(int secs) {\n  struct timespec req = { secs, 0 };\n  struct timespec rem = { -1, -1 };\n\n  test_assert(0 == nanosleep(&req, &rem));\n  test_assert(-1 == rem.tv_sec && -1 == rem.tv_nsec);\n}\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 1 ...\");\n  intr_sleep(2);\n}\n\nstatic void sighandler2(__attribute__((unused)) int sig) {\n  test_assert(sys_gettid() == reader_tid);\n  ++reader_caught_signal;\n\n  atomic_puts(\"r: in sighandler level 2 ...\");\n  fin_sleep(1);\n}\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  struct sigaction act;\n  int flags = 0;\n\n  reader_tid = sys_gettid();\n\n  act.sa_handler = sighandler;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR1, &act, NULL);\n\n  act.sa_handler = sighandler2;\n  sigemptyset(&act.sa_mask);\n  act.sa_flags = flags;\n  sigaction(SIGUSR2, &act, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  atomic_puts(\"r: blocking on sleep, awaiting signal ...\");\n  intr_sleep(3);\n\n  return NULL;\n}\n\nint main(void) {\n  struct timeval ts;\n\n  /* (Kick on the syscallbuf if it's enabled.) */\n  gettimeofday(&ts, NULL);\n\n  pthread_barrier_init(&barrier, NULL, 2);\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  /* Force a blocked read() that's interrupted by a SIGUSR1,\n   * which then itself blocks on read() and succeeds. */\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n\n  atomic_puts(\"M: killing reader ...\");\n  pthread_kill(reader, SIGUSR1);\n  atomic_puts(\"M:   (quick nap)\");\n  usleep(100000);\n\n  atomic_puts(\"M: killing reader again ...\");\n  pthread_kill(reader, SIGUSR2);\n\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/invalid_exec.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  /* Do several variations of invalid execs */\n#pragma GCC diagnostic ignored \"-Wnonnull\"\n  test_assert(-1 == execve(NULL, NULL, NULL));\n  test_assert(errno == EFAULT);\n  test_assert(-1 == execve(\"/proc/self/exe\", (void*)0xdeadbeef, NULL));\n  test_assert(errno == EFAULT);\n  char *argv[] = { (char*)0xdeadbeef, NULL };\n  test_assert(-1 == execve(\"/proc/self/exe\", argv, NULL));\n  test_assert(errno == EFAULT);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/invalid_fcntl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  /* Do an invalid fcntl command on valid fd 0 */\n  test_assert(-1 == fcntl(0, 9999));\n  test_assert(errno == EINVAL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/invalid_interpreter.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nsize_t page_size;\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\n#define N_MAX_TO_UNMAP 1024\nstatic int n_to_unmap = 0;\nstatic map_properties_t to_unmap[N_MAX_TO_UNMAP];\n\nvoid callback(__attribute__((unused)) uint64_t env, char* name, map_properties_t* props) {\n  if (strstr(name, \"/ld-\") != 0) {\n    if (n_to_unmap >= N_MAX_TO_UNMAP)\n      return;\n    to_unmap[n_to_unmap++] = *props;\n  }\n}\n\nint main(void) {\n  page_size = sysconf(_SC_PAGESIZE);\n  /* Trigger dl_runtime_resolve etc for mmap */\n  mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS, -1, 0);\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  iterate_maps(0, callback, maps_file);\n  test_assert(n_to_unmap > 0);\n  for (int i = 0; i < n_to_unmap; i++) {\n    map_properties_t *props = &to_unmap[i];\n    test_assert(0 == munmap((void*)(uintptr_t)props->start, page_size));\n    void* p = (void*)mmap((void*)(uintptr_t)props->start, page_size, PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);\n    test_assert(p != MAP_FAILED);\n  }\n  breakpoint();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/invalid_interpreter.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\n\nok()\n"
  },
  {
    "path": "src/test/invalid_interpreter.run",
    "content": "source `dirname $0`/util.sh\nrecord invalid_interpreter$bitness\ndebug_gdb_only invalid_interpreter\n"
  },
  {
    "path": "src/test/invalid_ioctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  // Test invalid fd -1, to make sure that rr doesn't accidentally think\n  // this is it's desched fd (esp. when syscallbuf is disabled).\n  test_assert(-1 == ioctl(-1, PERF_EVENT_IOC_ENABLE));\n  test_assert(errno == EBADF);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/invalid_jump.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(int sig) {\n  atomic_printf(\"caught signal %d, exiting\\n\", sig);\n  _exit(0);\n}\n\nint main(void) {\n  char* invalid_jump_here;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  invalid_jump_here = (char*)mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(invalid_jump_here != MAP_FAILED);\n\n  // Just for clean exit to not worry people running the test manually ;).\n  signal(SIGSEGV, sighandler);\n  ((void (*)(void))invalid_jump_here)();\n  test_assert(0 && \"Shouldn't reach here\");\n}\n"
  },
  {
    "path": "src/test/invalid_jump.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_gdb('Program received signal SIGSEGV')\n\nsend_gdb('rsi')\nsend_gdb('rsi')\n\nexpect_gdb('main ()')\n\nok()\n"
  },
  {
    "path": "src/test/invalid_jump.run",
    "content": "source `dirname $0`/util.sh\nrecord invalid_jump$bitness\ndebug_gdb_only invalid_jump\n"
  },
  {
    "path": "src/test/io.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char buf[32];\n  int garbage_fd = 1 << 30;\n\n  read(garbage_fd, buf, sizeof(buf));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/io_uring.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstruct io_sqring_offsets {\n  uint32_t head;\n  uint32_t tail;\n  uint32_t ring_mask;\n  uint32_t ring_entries;\n  uint32_t flags;\n  uint32_t dropped;\n  uint32_t array;\n  uint32_t resv[3];\n};\n\nstruct io_cqring_offsets {\n  uint32_t head;\n  uint32_t tail;\n  uint32_t ring_mask;\n  uint32_t ring_entries;\n  uint32_t overflow;\n  uint32_t cqes;\n  uint32_t flags;\n  uint32_t resv[3];\n};\n\nstruct io_uring_params {\n  uint32_t sq_entries;\n  uint32_t cq_entries;\n  uint32_t flags;\n  uint32_t sq_thread_idle;\n  uint32_t features;\n  uint32_t resv[4];\n  struct io_sqring_offsets sq_off;\n  struct io_cqring_offsets cq_off;\n};\n\nint main(void) {\n  struct io_uring_params params;\n  int ret = syscall(RR_io_uring_setup, 32, &params);\n  test_assert(ret == -1 && errno == ENOSYS);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int pipe_fds[2];\n  int opt = 1;\n\n  test_assert(0 == pipe(pipe_fds));\n  test_assert(0 == ioctl(pipe_fds[0], FIOCLEX, NULL));\n  test_assert(FD_CLOEXEC == fcntl(pipe_fds[0], F_GETFD));\n  test_assert(0 == ioctl(pipe_fds[0], FIONCLEX, NULL));\n  test_assert(0 == ioctl(pipe_fds[0], FIOASYNC, &opt));\n  test_assert(0 == fcntl(pipe_fds[0], F_GETFD));\n  test_assert(0 == ioctl(pipe_fds[0], FIONBIO, &opt));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_blk.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int* int_val;\n  unsigned int* uint_val;\n  uint64_t* u64_val;\n  unsigned long* ulong_val;\n  unsigned short* ushort_val;\n  size_t* size_t_val;\n  char ch = 32;\n  int ret;\n\n  int fd = open(\"/dev/sda1\", O_NONBLOCK | O_RDONLY);\n  if (fd < 0) {\n    fd = open(\"/dev/dm-1\", O_NONBLOCK | O_RDONLY);\n  }\n\n  if (fd < 0) {\n    if (errno == EACCES) {\n      atomic_printf(\"Opening a block device usually needs root permission, skipping test\\n\");\n    } else if (errno == ENOENT) {\n      atomic_printf(\"Can't find block device to open, skipping test\\n\");\n    } else {\n      test_assert(0 && \"Unexpected error opening block device\");\n    }\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n#define CHECK_GETTER(name, val) \\\n    ALLOCATE_GUARD(val, ch++); \\\n    ret = ioctl(fd, name, val); \\\n    if (ret < 0) { \\\n      test_assert(errno == EINVAL || errno == ENOTTY || errno == EOPNOTSUPP); \\\n    } \\\n    VERIFY_GUARD(val); \\\n    atomic_printf(#name \" returned %llu\\n\", (unsigned long long)*val);\n\n  CHECK_GETTER(BLKROGET, uint_val);\n  CHECK_GETTER(BLKGETSIZE, ulong_val);\n  CHECK_GETTER(BLKRAGET, size_t_val);\n  CHECK_GETTER(BLKFRAGET, size_t_val);\n  CHECK_GETTER(BLKSECTGET, ushort_val);\n  CHECK_GETTER(BLKSSZGET, int_val);\n  CHECK_GETTER(BLKBSZGET, size_t_val);\n  CHECK_GETTER(BLKGETSIZE64, u64_val);\n  CHECK_GETTER(BLKIOMIN, uint_val);\n  CHECK_GETTER(BLKIOOPT, uint_val);\n  CHECK_GETTER(BLKALIGNOFF, int_val);\n  CHECK_GETTER(BLKPBSZGET, uint_val);\n  CHECK_GETTER(BLKDISCARDZEROES, uint_val);\n  CHECK_GETTER(BLKROTATIONAL, ushort_val);\n  CHECK_GETTER(BLKGETDISKSEQ, u64_val);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_br.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#include <linux/if_bridge.h>\n#include <stdio.h>\n#include <sys/ioctl.h>\n#include <sys/socket.h>\n#include <unistd.h>\n\nint main(void) {\n  if (try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int sk, ret;\n  unsigned long args[3];\n\n  sk = socket(AF_INET, SOCK_STREAM, 0);\n  if (sk < 0) {\n    return 0;\n  }\n\n  args[0] = BRCTL_GET_VERSION;\n  args[1] = args[2] = 0;\n  ret = ioctl(sk, SIOCGIFBR, &args);\n  if (ret < 0) {\n    test_assert(errno == EOPNOTSUPP);\n  } else {\n    atomic_printf(\"version=%d\\n\", ret);\n  }\n\n  if (sizeof (void *) == 4) {\n      // In 32 bit compatibility mode, the only operation supported is\n      // BRCTL_GET_VERSION; see old_bridge_ioctl in the kernel sources for\n      // details.\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n  }\n\n  // nonsense operation\n  args[0] = 0x13371337;\n  args[1] = args[2] = 0;\n  ret = ioctl(sk, SIOCGIFBR, &args);\n  test_assert(ret < 0 && errno == EOPNOTSUPP);\n\n  args[0] = BRCTL_ADD_BRIDGE;\n  args[1] = (unsigned long)\"mybridge\";\n  args[2] = 0;\n  ret = ioctl(sk, SIOCGIFBR, &args);\n  if (ret < 0) {\n    atomic_printf(\"error adding bridge: %d\\n\", errno);\n  }\n\n  int bridges[1024];\n  args[0] = BRCTL_GET_BRIDGES;\n  args[1] = (unsigned long)bridges;\n  args[2] = sizeof(bridges) / sizeof(int);\n  ret = ioctl(sk, SIOCGIFBR, &args);\n  if (ret < 0) {\n    atomic_printf(\"error BRCTL_GET_BRIDGES: %d\\n\", errno);\n  } else {\n    for (int i = 0; i < ret; ++i) {\n      atomic_printf(\"bridge: %d\\n\", bridges[i]);\n    }\n  }\n\n  args[0] = BRCTL_DEL_BRIDGE;\n  args[1] = (unsigned long)\"mybridge\";\n  args[2] = 0;\n  ret = ioctl(sk, SIOCGIFBR, &args);\n  if (ret < 0) {\n    atomic_printf(\"error BRCTL_DEL_BRIDGE: %d\\n\", errno);\n  }\n\n  close(sk);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_fb.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n  struct fb_fix_screeninfo finfo;\n  struct fb_var_screeninfo vinfo;\n\n  fd = open(\"/dev/fb0\", O_RDWR);\n  if (fd < 0) {\n    atomic_puts(\"Can't open framebuffer, aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == ioctl(fd, FBIOGET_FSCREENINFO, &finfo));\n  atomic_printf(\"FBIOGET_FSCREENINFO returned id=%s capabilities=%d\\n\", finfo.id, finfo.capabilities);\n\n  test_assert(0 == ioctl(fd, FBIOGET_VSCREENINFO, &vinfo));\n  atomic_printf(\"FBIOGET_VSCREENINFO returned xres=%d yres=%d colorspace=%d\\n\", vinfo.xres, vinfo.yres, vinfo.colorspace);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_fs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <linux/fs.h>\n\nint main(void) {\n  int fd = open(\"dummy.txt\", O_RDWR | O_CREAT, 0600);\n  long* version;\n  long* flags;\n  struct fsxattr* xattr;\n  char filebuf[4096] = {};\n  char fmbuf[4096] = {};\n  struct fiemap *fm;\n  int ret;\n\n  test_assert(fd >= 0);\n\n  ALLOCATE_GUARD(version, 'a');\n  ret = ioctl(fd, FS_IOC_GETVERSION, version);\n  VERIFY_GUARD(version);\n  if (ret < 0) {\n    test_assert(errno == ENOTTY || errno == EOPNOTSUPP);\n  } else {\n    atomic_printf(\"version=%ld\\n\", *version);\n  }\n\n  ALLOCATE_GUARD(flags, 'b');\n  ret = ioctl(fd, FS_IOC_GETFLAGS, flags);\n  VERIFY_GUARD(flags);\n  if (ret < 0) {\n    test_assert(errno == ENOTTY || errno == EOPNOTSUPP);\n  } else {\n    atomic_printf(\"flags=%lx\\n\", *flags);\n  }\n\n  ALLOCATE_GUARD(xattr, 'c');\n  ret = ioctl(fd, FS_IOC_FSGETXATTR, xattr);\n  VERIFY_GUARD(xattr);\n  if (ret < 0) {\n    test_assert(errno == ENOTTY || errno == EOPNOTSUPP);\n  } else {\n    atomic_printf(\"xflags=%d\\n\", xattr->fsx_xflags);\n  }\n\n  test_assert(sizeof(filebuf) == write(fd, &filebuf, sizeof(filebuf)));\n  fm = (struct fiemap*)fmbuf;\n  fm->fm_start = 0;\n  fm->fm_flags = 0;\n  fm->fm_extent_count = (sizeof(fmbuf) - offsetof(struct fiemap, fm_extents)) / sizeof(fm->fm_extents[0]);\n  fm->fm_length = FIEMAP_MAX_OFFSET - fm->fm_start;\n  ret = ioctl(fd, FS_IOC_FIEMAP, fm);\n  if (ret < 0) {\n    test_assert(errno == ENOTTY || errno == EOPNOTSUPP);\n  } else {\n    atomic_printf(\"fm->fm_mapped_extents=%d\\n\", fm->fm_mapped_extents);\n    for (unsigned int i=0; i < fm->fm_mapped_extents; i++) {\n      struct fiemap_extent* fe = fm->fm_extents + i;\n      atomic_printf(\"i=%d fe_logical=0x%llx fe_physical=0x%llx fe_length=0x%llx fe_flags=0x%x\\n\", i,\n                    fe->fe_logical, fe->fe_physical, fe->fe_length, fe->fe_flags);\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_hidraw.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include <linux/hidraw.h>\n#include \"util.h\"\n\ninline static int atomic_warn(int cond, const char *str,\n                              const char *file, const int line) {\n  if (!cond) {\n    atomic_printf(\"FAILED at %s:%d: !(%s) errno:%d (%s)\\n\", file, line, str,\n                  errno, strerror(errno));\n  }\n  return 1;\n}\n\n#define test_warn(cond) atomic_warn(cond, #cond, __FILE__, __LINE__)\n\n#define BUF_SIZE 256\n\nvoid test(int fd) {\n  char *buf = allocate_guard(BUF_SIZE, 0xFF);;\n  int size;\n  struct hidraw_report_descriptor *rpt_desc;\n\n  test_warn(0 <= ioctl(fd, HIDIOCGRAWNAME(256), buf));\n  atomic_printf(\" Device name: %s\\n\", buf);\n  verify_guard(BUF_SIZE, buf);\n\n  test_warn(0 == ioctl(fd, HIDIOCGRDESCSIZE, &size));\n  atomic_printf(\" Report Descriptor Size = %d bytes\\n\", size);\n\n  ALLOCATE_GUARD(rpt_desc, 0x00);\n  rpt_desc->size = size;\n  test_warn(0 == ioctl(fd, HIDIOCGRDESC, rpt_desc));\n  atomic_printf(\" Report Descriptor:\");\n  for (unsigned int i = 0; i < rpt_desc->size; i++) {\n    if (i % 16 == 0) {\n      atomic_printf(\"\\n \");\n    }\n    atomic_printf(\"0x%02hhX \", rpt_desc->value[i]);\n  }\n  atomic_puts(\"\");\n  FREE_GUARD(rpt_desc);\n}\n\nint main(void) {\n  int fd;\n\n  chdir(\"/dev\");\n  DIR* dev = opendir(\".\");\n  if (dev < 0) {\n    atomic_puts(\"Can't open dev directory, aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  struct dirent* e;\n  while ((e = readdir(dev))) {\n    if (0 != strncmp(\"hidraw\", e->d_name, 6)) {\n      continue;\n    }\n\n    fd = open(e->d_name, O_RDWR|O_NONBLOCK);\n    if (fd < 0) {\n      atomic_printf(\"Can’t open device /dev/%s; skipping\\n\", e->d_name);\n      continue;\n    }\n    atomic_printf(\"Poking device /dev/%s\\n\", e->d_name);\n    test(fd);\n    close(fd);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_pty.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <linux/tiocl.h>\n\nint main(void) {\n  int fd = open(\"/dev/ptmx\", O_RDWR);\n  pid_t child;\n  int ret;\n  int status;\n  int* arg;\n  test_assert(fd >= 0);\n\n  atomic_printf(\"pty ptsname = %s\\n\", ptsname(fd));\n\n  ALLOCATE_GUARD(arg, 'a');\n  test_assert(0 == ioctl(fd, TIOCGPKT, arg));\n  VERIFY_GUARD(arg);\n  test_assert(*arg == 0);\n\n  test_assert(0 == ioctl(fd, TIOCPKT, arg));\n\n  ALLOCATE_GUARD(arg, 'b');\n  test_assert(0 == ioctl(fd, TIOCGPTN, arg));\n  VERIFY_GUARD(arg);\n  atomic_printf(\"pty number = %d\\n\", *arg);\n\n  ALLOCATE_GUARD(arg, 'c');\n  test_assert(0 == ioctl(fd, TIOCGPTLCK, arg));\n  VERIFY_GUARD(arg);\n  test_assert(*arg == 1);\n\n  *arg = 0;\n  test_assert(0 == ioctl(fd, TIOCSPTLCK, arg));\n\n  ret = ioctl(fd, TIOCGPTPEER, 0);\n  if (ret < 0) {\n    test_assert(errno == ENOSYS || errno == ENOTTY);\n  }\n\n  test_assert(0 == ioctl(fd, TCXONC, TCOOFF));\n  test_assert(0 == ioctl(fd, TCFLSH, TCIFLUSH));\n  child = fork();\n  if (!child) {\n    test_assert(getpid() == setsid());\n\n    test_assert(0 == ioctl(fd, TIOCSCTTY, 0));\n    ioctl(fd, TIOCNOTTY, 0);\n    // The above ioctl can legitimately fail. If so, fake it.\n    kill(getpid(), SIGHUP);\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGHUP);\n\n  ret = ioctl(fd, TIOCSTI, \"x\");\n  test_assert(ret >= 0 || errno == EPERM || errno == EIO);\n\n  test_assert(0 == ioctl(fd, TIOCEXCL, 0));\n  ALLOCATE_GUARD(arg, 'd');\n  test_assert(0 == ioctl(fd, TIOCGEXCL, arg));\n  VERIFY_GUARD(arg);\n  test_assert(*arg == 1);\n  test_assert(0 == ioctl(fd, TIOCNXCL, 0));\n\n  ALLOCATE_GUARD(arg, 'e');\n  test_assert(0 == ioctl(fd, TIOCGETD, arg));\n  VERIFY_GUARD(arg);\n  atomic_printf(\"pty TIOCGETD = %d\\n\", *arg);\n  test_assert(0 == ioctl(fd, TIOCSETD, arg));\n\n  char* carg;\n  ALLOCATE_GUARD(carg, 'f');\n  *carg = TIOCL_GETSHIFTSTATE;\n  ret = ioctl(fd, TIOCLINUX, carg);\n  VERIFY_GUARD(carg);\n  test_assert(ret == 0 || errno == EIO || errno == ENOTTY);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_sg.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"/dev/sr0\", O_NONBLOCK | O_RDONLY);\n  if (fd < 0) {\n    test_assert(errno == EACCES || errno == ENOENT);\n  } else {\n\n    /* https://www.tldp.org/HOWTO/SCSI-Generic-HOWTO/pexample.html */\n\n    int k;\n    if ((ioctl(fd, SG_GET_VERSION_NUM, &k) < 0) || (k < 30000)) {\n      /* no usable sg device available */\n    } else {\n\n      #define INQ_REPLY_LEN 96\n      #define INQ_CMD_CODE 0x12\n      #define INQ_CMD_LEN 6\n\n      unsigned char inqCmdBlk[INQ_CMD_LEN] = {INQ_CMD_CODE, 0, 0, 0, INQ_REPLY_LEN, 0};\n      unsigned char inqBuff[INQ_REPLY_LEN];\n      unsigned char sense_buffer[32];\n      sg_io_hdr_t io_hdr;\n\n      memset(&io_hdr, 0, sizeof(sg_io_hdr_t));\n      io_hdr.interface_id = 'S';\n      io_hdr.cmd_len = sizeof(inqCmdBlk);\n      io_hdr.iovec_count = 0;\n      io_hdr.mx_sb_len = sizeof(sense_buffer);\n      io_hdr.dxfer_direction = SG_DXFER_FROM_DEV;\n      io_hdr.dxfer_len = INQ_REPLY_LEN;\n      io_hdr.dxferp = inqBuff;\n      io_hdr.cmdp = inqCmdBlk;\n      io_hdr.sbp = sense_buffer;\n      io_hdr.timeout = 20000;\n      io_hdr.flags = 0;\n      io_hdr.pack_id = 0;\n      io_hdr.usr_ptr = NULL;\n\n      test_assert(0 == ioctl(fd, SG_IO, &io_hdr));\n    }\n\n    int ret;\n    struct cdrom_tochdr tochdr;\n    memset(&tochdr, 0, sizeof(tochdr));\n    ret = ioctl(fd, CDROMREADTOCHDR, &tochdr);\n    atomic_printf(\"CDROMREADTOCHDR returned ret=%d cdth_trk0=%d cdth_trk1=%d\\n\",\n                  ret, tochdr.cdth_trk0, tochdr.cdth_trk1);\n\n    struct cdrom_tocentry tocentry;\n    memset(&tocentry, 0, sizeof(tocentry));\n    tocentry.cdte_track = tochdr.cdth_trk0;\n    tocentry.cdte_format = CDROM_LBA;\n    ret = ioctl(fd, CDROMREADTOCENTRY, &tocentry);\n    atomic_printf(\"CDROMREADTOCENTRY returned ret=%d cdte_format=%d lba=%d cdte_datamode=%d\\n\",\n                  ret, tocentry.cdte_format, tocentry.cdte_addr.lba, tocentry.cdte_datamode);\n\n    int atapi;\n    ret = ioctl(fd, SG_EMULATED_HOST, &atapi);\n    atomic_printf(\"SG_EMULATED_HOST returned ret=%d atapi=%d\\n\", ret, atapi);\n\n    int table_size;\n    ret = ioctl(fd, SG_GET_SG_TABLESIZE, &table_size);\n    atomic_printf(\"SG_GET_SG_TABLESIZE returned ret=%d table_size=%d\\n\", ret, table_size);\n\n    int reserved;\n    ret = ioctl(fd, SG_GET_RESERVED_SIZE, &reserved);\n    atomic_printf(\"SG_GET_RESERVED_SIZE returned ret=%d reserved=%d\\n\", ret, reserved);\n    ret = ioctl(fd, SG_SET_RESERVED_SIZE, &reserved);\n    atomic_printf(\"SG_SET_RESERVED_SIZE returned ret=%d\\n\", ret);\n\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_tty.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef HAVE_TERMIOS2\n/* We have to define termios2 ourselves with glibc. See\n * https://github.com/npat-efault/picocom/blob/1acf1ddabaf3576b4023c4f6f09c5a3e4b086fb8/termios2.txt\n * for the long explanation.\n */\nstruct termios2 {\n  tcflag_t c_iflag;\n  tcflag_t c_oflag;\n  tcflag_t c_cflag;\n  tcflag_t c_lflag;\n  cc_t c_line;\n  cc_t c_cc[19];\n  speed_t c_ispeed;\n  speed_t c_ospeed;\n};\n#endif\n\n/* glibc 2.42 removed termio:\n   https://sourceware.org/git/?p=glibc.git;a=commit;h=e04afb71771710cdc6025fe95908f5f17de7b72d\n*/\nstruct rr_termio {\n  unsigned short c_iflag;\n  unsigned short c_oflag;\n  unsigned short c_cflag;\n  unsigned short c_lflag;\n  unsigned char c_line;\n  unsigned char c_cc[8];\n};\n\nint main(void) {\n  int fd;\n  int ret;\n  struct termios* tc;\n  struct termios2* tc2;\n  struct rr_termio* tio;\n  pid_t* pgrp;\n  int* navail;\n  int* outq;\n  struct winsize* w;\n  pid_t* sid;\n  int* nread;\n  int sockets[2];\n\n  signal(SIGTTOU, SIG_IGN);\n\n  fd = open(\"/dev/tty\", O_RDWR);\n  if (fd < 0) {\n    atomic_puts(\"Can't open tty, aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  ALLOCATE_GUARD(tc, 'a');\n  test_assert(0 == ioctl(fd, TCGETS, tc));\n  VERIFY_GUARD(tc);\n  atomic_printf(\"TCGETS returned { iflag=0x%x, oflag=0x%x, cflag=0x%x, \"\n                \"lflag=0x%x }\\n\",\n                tc->c_iflag, tc->c_oflag, tc->c_cflag, tc->c_lflag);\n  test_assert(0 == ioctl(fd, TCSETS, tc));\n  test_assert(0 == ioctl(fd, TCSETSW, tc));\n  test_assert(0 == ioctl(fd, TCSETSF, tc));\n\n  ALLOCATE_GUARD(tio, 'b');\n  test_assert(0 == ioctl(fd, TCGETA, tio));\n  VERIFY_GUARD(tio);\n  atomic_printf(\"TCGETA returned { iflag=0x%x, oflag=0x%x, cflag=0x%x, \"\n                \"lflag=0x%x }\\n\",\n                tio->c_iflag, tio->c_oflag, tio->c_cflag, tio->c_lflag);\n  test_assert(0 == ioctl(fd, TCSETA, tio));\n  test_assert(0 == ioctl(fd, TCSETAW, tio));\n  test_assert(0 == ioctl(fd, TCSETAF, tio));\n\n  test_assert(0 == ioctl(fd, TIOCGLCKTRMIOS, tc));\n  VERIFY_GUARD(tc);\n  atomic_printf(\"TIOCGLCKTRMIOS returned { iflag=0x%x, oflag=0x%x, cflag=0x%x, \"\n                \"lflag=0x%x }\\n\",\n                tio->c_iflag, tio->c_oflag, tio->c_cflag, tio->c_lflag);\n  ret = ioctl(fd, TIOCSLCKTRMIOS, tc);\n  test_assert(ret >= 0 || errno == EPERM);\n\n  test_assert(0 == ioctl(fd, TCSBRK, 0));\n  test_assert(0 == ioctl(fd, TCSBRKP, 0));\n  test_assert(0 == ioctl(fd, TIOCSBRK, 0));\n  test_assert(0 == ioctl(fd, TIOCCBRK, 0));\n\n  ALLOCATE_GUARD(pgrp, 'c');\n  test_assert(0 == ioctl(fd, TIOCGPGRP, pgrp));\n  VERIFY_GUARD(pgrp);\n  if (*pgrp != 0) {\n    atomic_printf(\"TIOCGPGRP returned process group %d\\n\", *pgrp);\n    test_assert(0 == ioctl(fd, TIOCSPGRP, pgrp));\n  } else {\n    atomic_printf(\"Skipping TIOCSPGRP test - controlling tty outside PID ns.\");\n  }\n\n  ALLOCATE_GUARD(navail, 'd');\n  test_assert(0 == ioctl(fd, TIOCINQ, navail));\n  VERIFY_GUARD(navail);\n  atomic_printf(\"TIOCINQ returned navail=%d\\n\", *navail);\n\n  ALLOCATE_GUARD(outq, 'e');\n  test_assert(0 == ioctl(fd, TIOCOUTQ, outq));\n  VERIFY_GUARD(outq);\n  atomic_printf(\"TIOCOUTQ returned outq=%d\\n\", *outq);\n\n  ALLOCATE_GUARD(w, 'f');\n  test_assert(0 == ioctl(fd, TIOCGWINSZ, w));\n  VERIFY_GUARD(w);\n  atomic_printf(\"TIOCGWINSZ returned {row:%d col:%d}\\n\", w->ws_row, w->ws_col);\n  test_assert(0 == ioctl(fd, TIOCSWINSZ, w));\n\n  ALLOCATE_GUARD(sid, 'g');\n  test_assert(0 == ioctl(fd, TIOCGSID, sid));\n  VERIFY_GUARD(sid);\n  atomic_printf(\"TIOCGSID returned %d\\n\", *sid);\n\n  socketpair(AF_UNIX, SOCK_STREAM, 0, sockets);\n  ALLOCATE_GUARD(nread, 'h');\n  test_assert(0 == ioctl(sockets[0], FIONREAD, nread));\n  VERIFY_GUARD(nread);\n  atomic_printf(\"FIONREAD returned nread=%d\\n\", *nread);\n\n  ALLOCATE_GUARD(tc2, 'i');\n  test_assert(0 == ioctl(fd, TCGETS2, tc));\n  VERIFY_GUARD(tc2);\n  atomic_printf(\"TCGETS2 returned { iflag=0x%x, oflag=0x%x, cflag=0x%x, \"\n                \"lflag=0x%x, ispeed=%d, ospeed=%d }\\n\",\n                tc2->c_iflag, tc2->c_oflag, tc2->c_cflag, tc2->c_lflag,\n                tc2->c_ispeed, tc2->c_ospeed);\n  test_assert(0 == ioctl(fd, TCSETS2, tc2));\n  test_assert(0 == ioctl(fd, TCSETSW2, tc2));\n  test_assert(0 == ioctl(fd, TCSETSF2, tc2));\n\n  // NB: leaving the TCSETS2 as the last word seems to mess up the terminal,\n  // so fix it.\n  test_assert(0 == ioctl(fd, TCSETS, tc));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_ttyS.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <linux/serial.h>\n\nint main(void) {\n  int fd;\n  int* mbits;\n  struct serial_icounter_struct* sicnt;\n  int* lsr;\n\n  fd = open(\"/dev/ttyS0\", O_RDWR);\n  if (fd < 0) {\n    atomic_puts(\"Can't open ttyS0, aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  ALLOCATE_GUARD(mbits, 'a');\n  test_assert(0 == ioctl(fd, TIOCMGET, mbits));\n  VERIFY_GUARD(mbits);\n  atomic_printf(\"TIOCMGET returned mbits=0x%x\\n\", *mbits);\n  test_assert(0 == ioctl(fd, TIOCMSET, mbits));\n  atomic_printf(\"TIOCMSET mbits=0x%x afterwards\\n\", *mbits);\n\n  ALLOCATE_GUARD(sicnt, 'b');\n  test_assert(0 == ioctl(fd, TIOCGICOUNT, sicnt));\n  VERIFY_GUARD(sicnt);\n  atomic_printf(\"TIOCGICOUNT returned %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\\n\",\n                sicnt->cts, sicnt->dsr, sicnt->rng, sicnt->dcd, sicnt->rx, sicnt->tx,\n                sicnt->frame, sicnt->overrun, sicnt->parity, sicnt->brk, sicnt->buf_overrun);\n\n  ALLOCATE_GUARD(lsr, 'c');\n  test_assert(0 == ioctl(fd, TIOCSERGETLSR, lsr));\n  VERIFY_GUARD(lsr);\n  atomic_printf(\"TIOCSERGETLSR returned lsr=0x%x\\n\", *lsr);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioctl_vt.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n  int vt;\n  struct vt_stat vts;\n  int tty_mode;\n\n  fd = open(\"/dev/tty0\", O_RDWR);\n  if (fd < 0) {\n    atomic_puts(\"Can't open tty, aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == ioctl(fd, VT_OPENQRY, &vt));\n  atomic_printf(\"VT_OPENQRY returned %d\\n\", vt);\n\n  test_assert(0 == ioctl(fd, VT_GETSTATE, &vts));\n  atomic_printf(\"VT_GETSTATE returned v_active=%d\\n\", vts.v_active);\n\n  test_assert(0 == ioctl(fd, KDGKBMODE, &tty_mode));\n  atomic_printf(\"KDGKBMODE returned %d\\n\", tty_mode);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ioprio.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define RR_IOPRIO_WHO_PROCESS 1\n#define RR_IOPRIO_CLASS_IDLE 3\n#define RR_IOPRIO_CLASS_SHIFT 13\n\nint main(void) {\n  int ret;\n  ret = syscall(RR_ioprio_get, RR_IOPRIO_WHO_PROCESS, 0);\n  test_assert(ret >= 0);\n  ret = syscall(RR_ioprio_set, RR_IOPRIO_WHO_PROCESS, 0, RR_IOPRIO_CLASS_IDLE << RR_IOPRIO_CLASS_SHIFT);\n  test_assert(ret >= 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/jit_proc_mem.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#define _FILE_OFFSET_BITS 64\n\n#include \"util.h\"\n#include <stdlib.h>\n\ntypedef int (*puts_func)(const char* fmt);\n\n// It's surprisingly hard to know the size of a function from C,\n// even though the compiler is perfectly happy putting that information\n// in the symbol table. Here we use a trick to avoid having to write\n// this in assembly for every platform: We create two identical copies\n// of the same function and force them into the same section. Then by\n// construction, one must come after the other within a reasonable bound\n// so we're guaranteed that at least one correct copy ends up where we\n// want it.\n\n#if defined(__i386__)\nextern char template_function;\nextern char template_function2;\n// Some versions of GCC are bad at emitting calls to absolute arguments and\n// still try to call __x86.get_pc_thunk.ax which won't work if we just copy\n// it from the C version of the template function. Just hardcode it here.\nasm(\"template_function:\\n\\t\"\n    \"push 4(%esp)\\n\\t\"\n    \"call *12(%esp)\\n\\t\"\n    \"add $4,%esp\\n\\t\"\n    \"xor %eax,%eax\\n\\t\"\n    \"ret\\n\\t\"\n    \"template_function2:\\n\");\n#else\nstatic int __attribute__ ((section(\".text.template\"))) template_function(char* text, puts_func f) {\n  f(text);\n  return 0;\n}\n\nstatic int __attribute__ ((section(\".text.template\"))) template_function2(char* text, puts_func f) {\n  f(text);\n  return 0;\n}\n#endif\n\nstatic __attribute__((noinline)) void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  void* space = mmap(NULL, 4096, PROT_EXEC | PROT_READ,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  int memfd = open(\"/proc/self/mem\", O_RDWR);\n  breakpoint();\n\n  char *first = (char*)&template_function;\n  char *second = (char*)&template_function2;\n\n  if (first > second) {\n    char *tmp = second;\n    second = first;\n    first = tmp;\n  }\n\n  ssize_t to_write = second - first;\n  test_assert(to_write > 0);\n  int nwritten =\n      pwrite(memfd, first, to_write, (uintptr_t)space);\n  test_assert(to_write == nwritten);\n\n  int ret = ((int (*)(char*, puts_func))space)(\"EXIT-SUCCESS\", atomic_puts);\n  breakpoint();\n  return ret;\n}\n"
  },
  {
    "path": "src/test/jit_proc_mem.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('up')\nsend_gdb('b *space')\nexpect_gdb('Breakpoint 2')\n\n# Should hit breakpoint 2 here rather than making it all the way back to\n# the first instance of breakpoint 1.\nsend_gdb('rc')\nexpect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/jit_proc_mem.run",
    "content": "source `dirname $0`/util.sh\nrecord jit_proc_mem$bitness\ndebug_gdb_only jit_proc_mem\n"
  },
  {
    "path": "src/test/join_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  return NULL;\n}\n\nint main(void) {\n  int i;\n  pthread_t threads[100];\n\n  for (i = 0; i < 100; ++i) {\n    test_assert(0 == pthread_create(&threads[i], NULL, thread, NULL));\n  }\n  for (i = 0; i < 100; ++i) {\n    test_assert(0 == pthread_join(threads[i], NULL));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/joystick.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n// On bionic, scsi/sg.h's BUSY conflicts with a definition in linux/joystick.h\n#undef BUSY\n#include <linux/joystick.h>\n\nint main(void) {\n    int fd = open(\"/dev/input/js0\", O_RDONLY);\n    if (fd < 0) {\n        atomic_puts(\"Can't open joystick device, aborting test\");\n        atomic_puts(\"EXIT-SUCCESS\");\n        return 0;\n    }\n\n    int ret = 0;\n\n    // JSIOCGVERSION\n    uint32_t *version;\n    ALLOCATE_GUARD(version, 'a');\n    test_assert(0 == ioctl(fd, JSIOCGVERSION, version));\n    VERIFY_GUARD(version);\n\n    // JSIOCGAXES\n    uint8_t *number_of_axes;\n    ALLOCATE_GUARD(number_of_axes, 'b');\n    test_assert(0 == ioctl(fd, JSIOCGAXES, number_of_axes));\n    VERIFY_GUARD(number_of_axes);\n\n    // JSIOCGBUTTONS\n    uint8_t *number_of_buttons;\n    ALLOCATE_GUARD(number_of_buttons, 'c');\n    test_assert(0 == ioctl(fd, JSIOCGBUTTONS, number_of_buttons));\n    VERIFY_GUARD(number_of_buttons);\n\n    // This is not supported for now, since the size of the data returned\n    // depends on the number of axes, which can only be determined by querying\n    // the device.\n#if 0\n    // JSIOCGCORR\n    struct js_corr **corr;\n    size_t corr_size = *number_of_axes * sizeof(struct js_corr);\n    corr = allocate_guard(corr_size, 'd');\n    test_assert(0 == ioctl(fd, JSIOCGCORR, corr));\n    verify_guard(corr_size, corr);\n#endif\n\n    // JSIOCGAXMAP\n    uint8_t (*axis_mapping)[ABS_CNT];\n    ALLOCATE_GUARD(axis_mapping, 'e');\n    ret = ioctl(fd, JSIOCGAXMAP, axis_mapping);\n    test_assert(ret > 0 && (unsigned)ret <= sizeof(*axis_mapping));\n    VERIFY_GUARD(axis_mapping);\n\n    // JSIOCGBTNMAP\n    uint16_t (*button_mapping)[KEY_MAX - BTN_MISC + 1];\n    ALLOCATE_GUARD(button_mapping, 'f');\n    ret = ioctl(fd, JSIOCGBTNMAP, button_mapping);\n    test_assert(ret > 0 && (unsigned)ret <= sizeof(*button_mapping));\n    VERIFY_GUARD(button_mapping);\n\n    // JSIOCGNAME\n    // With zero size, this should always succeed\n    test_assert(0 == ioctl(fd, JSIOCGNAME(0), NULL));\n\n    uint8_t (*name)[1024];\n    ALLOCATE_GUARD(name, 'g');\n    ret = ioctl(fd, JSIOCGNAME(sizeof(*name)), *name);\n    test_assert((ret == -1 && errno == EFAULT) ||\n                (ret >= 0 && (unsigned)ret <= sizeof(*name)));\n    VERIFY_GUARD(name);\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n"
  },
  {
    "path": "src/test/kcmp.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t pid = getpid();\n  int ret;\n\n  ret = syscall(RR_kcmp, pid, pid, RR_KCMP_FILES, 0L, 0L);\n  if (ret < 0 && errno == ENOSYS) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  test_assert(0 < syscall(RR_kcmp, pid, getppid(), RR_KCMP_FILES, 0L, 0L));\n  test_assert(0 == syscall(RR_kcmp, pid, pid, RR_KCMP_FILE, STDIN_FILENO,\n                           STDIN_FILENO));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/keyctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <linux/keyctl.h>\n\ntypedef uint32_t key_serial_t;\n\n/* There was a breaking UAPI change so use this */\nstruct rr_keyctl_dh_params {\n        __s32 dh_private;\n        __s32 prime;\n        __s32 base;\n};\n\nint main(void) {\n  char buffer[256];\n\n  char* data = \"Test Data\";\n  key_serial_t key = syscall(SYS_add_key, \"user\", \"RR Test key\", data,\n                             strlen(data) + 1, KEY_SPEC_PROCESS_KEYRING);\n  test_assert(0 == syscall(SYS_keyctl, KEYCTL_SETPERM, key, 0x3f3f0000));\n  long result =\n      syscall(SYS_keyctl, KEYCTL_DESCRIBE, key, buffer, sizeof(buffer));\n  test_assert(-1 != result);\n  check_data(buffer, result);\n  result = syscall(SYS_keyctl, KEYCTL_READ, key, buffer, sizeof(buffer));\n  test_assert(-1 != result);\n  check_data(buffer, result);\n  test_assert(0 == memcmp(buffer, data, strlen(data) + 1));\n  result =\n      syscall(SYS_keyctl, KEYCTL_GET_SECURITY, key, buffer, sizeof(buffer));\n  test_assert(-1 != result);\n  check_data(buffer, result);\n\n  test_assert(0 == syscall(SYS_keyctl, KEYCTL_INVALIDATE, key));\n\n#ifdef KEYCTL_DH_COMPUTE\n  uint8_t base[256] = { 1 };\n  // 'prime' must be at least 1536 bits or we get EINVAL.\n  uint8_t prime[256] = { 7 }; // Not prime but we should be OK\n  uint8_t private = 1;        // The world's worst private key\n  base[191] = 'x';\n\n  key_serial_t base_key = syscall(SYS_add_key, \"user\", \"base\", base,\n                                  sizeof(base), KEY_SPEC_PROCESS_KEYRING);\n  key_serial_t prime_key = syscall(SYS_add_key, \"user\", \"prime\", prime,\n                                   sizeof(prime), KEY_SPEC_PROCESS_KEYRING);\n  key_serial_t private_key = syscall(SYS_add_key, \"user\", \"private\", &private,\n                                     sizeof(private), KEY_SPEC_PROCESS_KEYRING);\n\n  struct rr_keyctl_dh_params params = {.dh_private = private_key,\n                                       .prime = prime_key,\n                                       .base = base_key };\n\n  result = syscall(SYS_keyctl, KEYCTL_DH_COMPUTE, &params, buffer,\n                   sizeof(buffer), (void*)0);\n  if (-1 == result) {\n    // This one's rather new. May not be supported.\n    test_assert(errno == EOPNOTSUPP);\n  } else {\n    check_data(buffer, result);\n    test_assert(0 == memcmp(buffer, base, sizeof(base)));\n  }\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/kill_newborn.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n  int i;\n  /* These setpriority calls may appear to fail but rr will honor them */\n  setpriority(PRIO_PROCESS, 0, 1);\n  child = fork();\n  if (!child) {\n    /* Doesn't matter what we do here; we intend for the child to never run */\n    return 0;\n  }\n  setpriority(PRIO_PROCESS, 0, 0);\n  /* Hopefully we've raised our priority so the child doesn't run at all.\n   * However, it is possible for the scheduler to pick the child to run. */\n  kill(child, SIGKILL);\n  for (i = 0; i < 200; ++i) {\n    test_assert(1 == write(STDOUT_FILENO, \".\", 1));\n  }\n  test_assert(child == wait(&status));\n  /* See above ... we can't guarantee these assertions will succeed */\n  /* test_assert(WIFSIGNALED(status));\n     test_assert(WTERMSIG(status) == SIGKILL); */\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/kill_ptracee.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n\n  /* Just an always runnable task */\n  if (0 == fork()) {\n    for (;;) {\n      sched_yield();\n    }\n  }\n\n  if (0 == (child = fork())) {\n    ptrace(PTRACE_TRACEME, 0, 0, 0);\n    raise(SIGSTOP);\n    for (;;) {\n#if defined(__x86_64__) || defined(__i386__)\n      __asm__(\"pause\");\n#else\n      __asm__(\"nop\");\n#endif\n    }\n    test_assert(0 && \"Should have died\");\n  }\n\n  /* Wait until the tracee stops */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  /* Continue the tracee */\n  test_assert(0 == ptrace(PTRACE_CONT, child, 0, 0));\n\n  sched_yield();\n\n  /* One or more of these may fail (since the tracee may already be dead).\n   * That's ok, but nothing should assert in rr, etc.\n   */\n\n  ptrace(PTRACE_KILL, child, 0, 0);\n  kill(child, SIGKILL);\n  /* Not necessary for functionality, but some real applications do this, so\n   * make sure we handle it fine\n   */\n  ptrace(PTRACE_CONT, child, 0, 0);\n\n  /* Wait until the tracee exits */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n\n  /* Same thing again but will while the tracee is still in the ptrace stop */\n  if (0 == (child = fork())) {\n    ptrace(PTRACE_TRACEME, 0, 0, 0);\n    raise(SIGSTOP);\n    test_assert(0 && \"Should have died\");\n  }\n\n  /* Wait until the tracee stops */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  kill(child, SIGKILL);\n  ptrace(PTRACE_KILL, child, 0, 0);\n  ptrace(PTRACE_CONT, child, 0, 0);\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/landlock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define LANDLOCK_RULE_PATH_BENEATH 1\n\n#define LANDLOCK_ACCESS_FS_READ_DIR 8\n\nstruct landlock_ruleset_attr {\n  uint64_t handled_access_fs;\n};\n\nstruct landlock_path_beneath_attr {\n  uint64_t allowed_access;\n  int32_t parent_fd;\n} __attribute__((packed));\n\nint main(void) {\n  struct landlock_ruleset_attr ruleset = { LANDLOCK_ACCESS_FS_READ_DIR };\n  int ruleset_fd = syscall(RR_landlock_create_ruleset,\n    &ruleset, sizeof(struct landlock_ruleset_attr),\n    0);\n  if (ruleset_fd < 0 && errno == ENOSYS) {\n    atomic_puts(\"landlock not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ruleset_fd >= 0);\n\n  int root_fd = open(\"/\", O_PATH);\n  test_assert(root_fd >= 0);\n\n  struct landlock_path_beneath_attr rule =\n    { LANDLOCK_ACCESS_FS_READ_DIR, root_fd };\n  int ret = syscall(RR_landlock_add_rule, ruleset_fd,\n    LANDLOCK_RULE_PATH_BENEATH, &rule, 0);\n  test_assert(ret == 0);\n\n  ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);\n  test_assert(ret == 0);\n\n  ret = syscall(RR_landlock_restrict_self, ruleset_fd, 0);\n  test_assert(ret == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/large_file.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_rr_32_bit\nexe=simple$bitness\ncp ${OBJDIR}/bin/$exe $exe-$nonce\ntruncate -s 2G $exe-$nonce\nPATH=\"${PATH}:.\" just_record $exe-$nonce\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/large_hole.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n#ifdef __x86_64__\n  off_t size = ((off_t)100)*1024*1024*1024;\n  char* p;\n  int fd = open(\"big\", O_RDWR | O_TRUNC | O_CREAT, 0700);\n  test_assert(pwrite64(fd, \"x\", 1, size) == 1);\n  p = (char*)mmap(NULL, size + 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  p[size/2] = 1;\n  p[size/2 + 65536] = 1;\n  test_assert(0 == munmap(p, size + 1));\n\n  test_assert(fallocate64(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, size/2, 4096) == 0);\n  p = (char*)mmap(NULL, size + 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[size/2] == 0);\n  test_assert(p[size/2 + 65536] == 1);\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/large_write_deadlock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\nstatic volatile int big_size = 1024 * 1024 * 50;\n\nint main(void) {\n  pid_t child;\n  char buf[1024];\n  int status;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (!child) {\n    memset(buf, 1, sizeof(buf));\n    write(pipe_fds[1], buf, sizeof(buf));\n    return 77;\n  }\n\n  read(pipe_fds[0], buf, big_size);\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/legacy_ugid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* We use this structure to verify that, on architectures supporting UID16\n * syscalls, rr properly records and replays only 16-bit values.\n */\nunion legacy_id {\n  uint16_t u16[2];\n  uint32_t u32;\n};\n\n#define UID_COOKIE 0xd05e\n\nstatic void initialize_legacy_ids(size_t n, union legacy_id* ids) {\n  size_t i;\n\n  for (i = 0; i < n; ++i) {\n    ids[i].u16[0] = 0;\n    ids[i].u16[1] = UID_COOKIE;\n  }\n};\n\nstatic void verify_results(size_t n, union legacy_id* ids) {\n  size_t i;\n\n  for (i = 0; i < n; ++i) {\n#if defined(__i386__)\n    // For UID16 syscall-supporting archs, the cookie should be intact.\n    test_assert(ids[i].u16[1] == UID_COOKIE);\n#elif defined(__x86_64__) || defined(__aarch64__)\n    // For UID32 archs, assume that the user doesn't have a UID with the\n    // upper bits equivalent to our cookie.  This is not a great assumption,\n    // but we don't really have anything better.\n    test_assert(ids[i].u16[1] != UID_COOKIE);\n#else\n#error unknown architecture\n#endif\n  }\n}\n\nint main(void) {\n  union legacy_id resuid_results[3];\n  union legacy_id resgid_results[3];\n  int ret;\n\n  initialize_legacy_ids(ALEN(resuid_results), resuid_results);\n  ret = syscall(SYS_getresuid, &resuid_results[0],\n                &resuid_results[1], &resuid_results[2]);\n  if (ret < 0 && errno == ENOSYS) {\n    atomic_puts(\"Syscall not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n\n  verify_results(ALEN(resuid_results), resuid_results);\n\n  initialize_legacy_ids(ALEN(resgid_results), resgid_results);\n  ret = syscall(SYS_getresgid, &resgid_results[0],\n                &resgid_results[1], &resgid_results[2]);\n  if (ret < 0 && errno == ENOSYS) {\n    atomic_puts(\"Syscall not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  verify_results(ALEN(resgid_results), resgid_results);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/link.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  static const char token_file[] = \"rr-link-file.txt\";\n  static const char link_name[] = \"rr-link-file.link\";\n  int fd = open(token_file, O_RDWR | O_CREAT | O_TRUNC, 0600);\n  test_assert(fd >= 0);\n  test_assert(0 == close(fd));\n\n  test_assert(0 == link(token_file, link_name));\n  test_assert(0 == unlink(token_file));\n  test_assert(0 == linkat(AT_FDCWD, link_name, AT_FDCWD, token_file, 0));\n  test_assert(0 == unlink(token_file));\n  test_assert(0 == unlink(link_name));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/link.run",
    "content": "source `dirname $0`/util.sh\n# NB: this test creates garbage, but it will be cleaned up along with\n# the other files in the tmp dir.\ncompare_test 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/madvise.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nsize_t page_size = 0;\n#define PAGE_ZEROES (page_size / sizeof(int))\n\nstatic size_t count_page_zeroes(int* p) {\n  size_t zeroes = 0;\n  size_t i;\n  for (i = 0; i < page_size / sizeof(*p); ++i) {\n    if (!p[i]) {\n      ++zeroes;\n    }\n  }\n  return zeroes;\n}\n\nstatic void set_page_values_nonzero(int* p) {\n  size_t i;\n  for (i = 0; i < page_size / sizeof(*p); ++i) {\n    p[i] = i + 1;\n  }\n}\n\nint main(void) {\n  int* page;\n  void* fixed_area;\n  int ret;\n  page_size = sysconf(_SC_PAGESIZE);\n\n  fixed_area =\n      mmap(NULL, page_size * 5, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(fixed_area != MAP_FAILED);\n  test_assert(0 == munmap(fixed_area, page_size * 5));\n\n  page = mmap(fixed_area + page_size, page_size, PROT_READ | PROT_WRITE,\n              MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(page != MAP_FAILED);\n  test_assert(count_page_zeroes(page) == PAGE_ZEROES);\n\n  set_page_values_nonzero(page);\n  test_assert(0 == madvise(page, page_size, MADV_DONTNEED));\n  test_assert(count_page_zeroes(page) == PAGE_ZEROES);\n\n  set_page_values_nonzero(page);\n  test_assert(0 == madvise(page, 1, MADV_DONTNEED));\n  test_assert(count_page_zeroes(page) == PAGE_ZEROES);\n\n  set_page_values_nonzero(page);\n  test_assert(-1 == madvise(fixed_area - 1, page_size * 5, MADV_DONTNEED));\n  test_assert(EINVAL == errno);\n  /* check this madvise had no effect */\n  test_assert(count_page_zeroes(page) < PAGE_ZEROES);\n\n  test_assert(-1 == madvise(fixed_area, page_size * 5, MADV_DONTNEED));\n  test_assert(ENOMEM == errno);\n  /* check this madvise did take effect */\n  test_assert(count_page_zeroes(page) == PAGE_ZEROES);\n\n  set_page_values_nonzero(page);\n  ret = madvise(page, page_size, MADV_DONTNEED_LOCKED);\n  if (ret) {\n    test_assert(errno == EINVAL);\n  } else {\n    test_assert(count_page_zeroes(page) == PAGE_ZEROES);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_dontfork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nint main(void) {\n  char* page;\n  pid_t pid;\n  int status;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  page = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,\n              MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(page != MAP_FAILED);\n\n  test_assert(0 == madvise(page, page_size, MADV_DONTFORK));\n\n  breakpoint();\n\n  page[0] = 1;\n\n  pid = fork();\n  if (!pid) {\n    test_assert(-1 == madvise(page, page_size, MADV_NORMAL));\n    test_assert(ENOMEM == errno);\n\n    page[page_size] = 2;\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  test_assert(pid == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_dontfork.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('next')\n\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/madvise_dontfork.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/madvise_dontneed_private.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"/proc/self/exe\", O_RDONLY);\n  test_assert(fd >= 0);\n  char* p = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n      MAP_PRIVATE, fd, 0);\n  test_assert(p != MAP_FAILED);\n  char* backup = malloc(page_size);\n  memcpy(backup, p, page_size);\n\n  memset(p, 0, page_size);\n  int ret = madvise(p, page_size, MADV_DONTNEED);\n  test_assert(ret == 0);\n  test_assert(memcmp(p, backup, page_size) == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_fracture_flags.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define FILL_REGION_SIZE 2ULL*1024ULL*1024ULL*1024ULL // 2 GiB\n#define PROBE_REGION_SIZE 200*1024ULL*1024ULL // 200 MiB\n\nint main(__attribute__((unused)) int argc, __attribute__((unused)) char** argv) {\n    FILE *f = fopen(\"/proc/sys/vm/max_map_count\", \"r\");\n    test_assert(f != NULL);\n\n    size_t max_map_count;\n    int ret = fscanf(f, \"%zu\", &max_map_count);\n    test_assert(ret == 1);\n\n    if (max_map_count > 100000) {\n        atomic_puts(\"Skipping test: max_map_count is too high - test would take too long\");\n        atomic_puts(\"EXIT-SUCCESS\");\n        return 77;\n    }\n\n    // Prepare the fill region - we will fill this with a number of mappings close to the\n    // maximum. We allow about a 256 mapping gap for rr's and the executable's mappings.\n    size_t page_size = sysconf(_SC_PAGESIZE);\n    size_t target_fill_mappings = max_map_count - 256;\n    size_t fill_region_size = page_size * target_fill_mappings;\n    char *fill_map = mmap(NULL, fill_region_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);\n    test_assert(fill_map != MAP_FAILED);\n    for (size_t off = 0; off < fill_region_size; off += 2*page_size) {\n        // Fracture the fill region into individual page-sized mappings.\n        char *page = fill_map + off;\n        test_assert(mprotect(page, page_size, PROT_READ) == 0);\n    }\n\n    // Now allocate the probe region\n    char *probe_map = mmap(NULL, PROBE_REGION_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);\n    test_assert(probe_map != MAP_FAILED);\n    ret = madvise(probe_map, PROBE_REGION_SIZE, MADV_HUGEPAGE);\n    if (ret == -1 && errno == EINVAL) {\n        atomic_puts(\"Skipping test: CONFIG_TRANSPARENT_HUGEPAGE is disabled\");\n        atomic_puts(\"EXIT-SUCCESS\");\n        return 77;\n    }\n    test_assert(ret == 0);\n    ret = madvise(probe_map, PROBE_REGION_SIZE, MADV_DONTDUMP);\n    test_assert(ret == 0);\n\n    // Now go through and re-map this mapping one page at a time, re-applying\n    // the flags as we go. If rr is inconsistent about applying the flags\n    // during replay, we will exceed the limit on the total number of mappings\n    // and crash during replay.\n    for (size_t off = 0; off < PROBE_REGION_SIZE; off += page_size) {\n        char *map_target = probe_map + off;\n        char *new_map = mmap(map_target, page_size,\n            PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE | MAP_FIXED, -1, 0);\n        test_assert(map_target == new_map);\n        ret = madvise(new_map, page_size, MADV_HUGEPAGE);\n        test_assert(ret == 0);\n        if (off % (2*page_size) == 0) {\n            ret = madvise(new_map, page_size, MADV_DONTDUMP);\n            test_assert(ret == 0);\n        } else {\n            // Simulate a full syscallbuf - perform an unbuffered syscall\n            ret = unbufferable_syscall(SYS_madvise, (uintptr_t)map_target,\n                page_size, MADV_DONTDUMP);\n            test_assert(ret == 0);\n        }\n    }\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_fracture_flags.run",
    "content": "NO_CHECK_CACHED_MMAP=1\nsource `dirname $0`/util.sh\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/madvise_free.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p =\n      mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  test_assert(-1 == madvise(p, page_size, MADV_FREE));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_misc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void do_madvise(int advice, const char* advice_name) {\n  int page_size = sysconf(_SC_PAGE_SIZE);\n  char* page = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  int ret = madvise(page, page_size, advice);\n  atomic_printf(\"Testing %s\\n\", advice_name);\n  if (ret == -1) {\n    test_assert(errno == EINVAL);\n  }\n}\n\n#define DO_MADVISE(advice) do_madvise(advice, #advice)\n\nint main(void) {\n  DO_MADVISE(MADV_NORMAL);\n  DO_MADVISE(MADV_RANDOM);\n  DO_MADVISE(MADV_SEQUENTIAL);\n  DO_MADVISE(MADV_WILLNEED);\n  DO_MADVISE(MADV_MERGEABLE);\n  DO_MADVISE(MADV_HUGEPAGE);\n  DO_MADVISE(MADV_NOHUGEPAGE);\n  DO_MADVISE(MADV_DONTDUMP);\n  DO_MADVISE(MADV_DODUMP);\n  DO_MADVISE(MADV_COLD);\n  DO_MADVISE(MADV_PAGEOUT);\n  DO_MADVISE(MADV_POPULATE_READ);\n  DO_MADVISE(MADV_POPULATE_WRITE);\n  DO_MADVISE(MADV_COLLAPSE);\n  DO_MADVISE(MADV_GUARD_INSTALL);\n  DO_MADVISE(MADV_GUARD_REMOVE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_remove.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char* p =\n      mmap(NULL, page_size*3, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p + page_size, page_size));\n\n  test_assert(-1 == madvise(p, page_size, MADV_REMOVE));\n  test_assert(errno == EINVAL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/madvise_wipeonfork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef MADV_WIPEONFORK\n#define MADV_WIPEONFORK 18\n#endif\n\n#ifndef MADV_KEEPONFORK\n#define MADV_KEEPONFORK 19\n#endif\n\nint main(void) {\n  char* page;\n  pid_t pid;\n  int status;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  page = mmap(NULL, page_size * 4, PROT_READ | PROT_WRITE,\n              MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(page != MAP_FAILED);\n\n  if (0 != madvise(page, 4 * page_size, MADV_WIPEONFORK)) {\n    atomic_puts(\"MADV_WIPEONFORK not supported, skipping test.\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == madvise(page + page_size, page_size, MADV_KEEPONFORK));\n  test_assert(0 == madvise(page + 3 * page_size, page_size, MADV_KEEPONFORK));\n\n  page[0] = 1;\n  page[page_size] = 1;\n  page[2 * page_size] = 1;\n  page[3 * page_size] = 1;\n\n  pid = fork();\n  if (!pid) {\n    test_assert(page[0] == 0);\n    test_assert(page[page_size] == 1);\n    test_assert(page[2 * page_size] == 0);\n    test_assert(page[3 * page_size] == 1);\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  test_assert(pid == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  test_assert(0 == madvise(page, 4 * page_size, MADV_DONTFORK));\n  test_assert(0 == madvise(page, 2 * page_size, MADV_DOFORK));\n\n  pid = fork();\n  if (!pid) {\n    // This should still be zero, because DONTFORK and WIPEONFORK are tracked\n    // separately in the kernel.\n    test_assert(page[0] == 0);\n    test_assert(page[page_size] == 1);\n    test_assert(page[2 * page_size] == 1); // This should segfault.\n\n    atomic_puts(\"FAILED: the third page should have been removed.\");\n    return -4;\n  }\n\n  test_assert(pid == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/main_thread_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pthread_t main_thread;\n\nstatic void breakpoint(void) {}\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  test_assert(0 == pthread_join(main_thread, NULL));\n  breakpoint();\n  atomic_puts(\"EXIT-SUCCESS\");\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  main_thread = pthread_self();\n  test_assert(0 == pthread_create(&thread, NULL, start_thread, NULL));\n  pthread_exit(NULL);\n  test_assert(0);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/main_thread_exit.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('checkpoint')\nsend_gdb('n')\nsend_gdb('restart 1')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/main_thread_exit.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/many_yields.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int stop;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (!stop) {\n    sched_yield();\n  }\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  int count;\n  pthread_create(&thread, NULL, do_thread, NULL);\n  for (count = 0; count < 1000; ++count) {\n    sched_yield();\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/many_yields.run",
    "content": "source `dirname $0`/util.sh\n\nexe=many_yields$bitness\ncp ${OBJDIR}/bin/$exe $exe-$nonce\njust_record $exe-$nonce\nrr rerun --export-checkpoints=500,2,socket1 latest-trace &\nrr rerun --import-checkpoint=socket1 --export-checkpoints=601,1,socket2 latest-trace &\nrr rerun --import-checkpoint=socket2 latest-trace || failed \"rerun from 601 failed\"\nrr rerun --import-checkpoint=socket1 latest-trace || failed \"rerun from 500 failed\"\nwait %1 || failed \"First rerun failed\"\nwait %2 || failed \"Second rerun failed\"\necho EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/map_fixed.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* map1 = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,\n                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  uint8_t* map1_end = map1 + page_size;\n  uint8_t* map2;\n\n  test_assert(map1 != (void*)-1);\n\n  map2 = mmap(map1_end, page_size, PROT_READ | PROT_WRITE,\n              MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(map2 != (void*)-1);\n  test_assert(map2 == map1_end);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/map_shared_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Tests that we can do a syscall from a syscall instruction located on a\n   MAP_SHARED page */\n\nstatic uintptr_t my_syscall(uintptr_t syscall, uintptr_t arg1) {\n  uintptr_t ret;\n#ifdef __x86_64__\n  __asm__ volatile(\"syscall\\n\\t\" : \"=a\"(ret) : \"a\"(syscall), \"D\"(arg1));\n#elif defined(__i386__)\n  __asm__ volatile(\"int $0x80\\n\\t\" : \"=a\"(ret) : \"a\"(syscall), \"b\"(arg1));\n#elif defined(__aarch64__)\n  register long x8 __asm__(\"x8\") = syscall;\n  register long x0 __asm__(\"x0\") = (long)arg1;\n  __asm__ volatile(\"svc #0\\n\\t\" : \"+r\"(x0) : \"r\"(x8));\n  ret = x0;\n#else\n#error define syscall here\n#endif\n  return ret;\n}\n\nvoid my_brk(uintptr_t brk) { my_syscall(SYS_brk, brk); }\n\nstatic uint64_t my_brk_file_offset;\n\nstatic void callback(__attribute__((unused)) uint64_t env, __attribute__((unused)) char* name, map_properties_t* props) {\n  uint64_t addr = (uintptr_t)my_brk;\n  if (props->start <= addr && addr < props->end) {\n    my_brk_file_offset = addr - props->start + props->offset;\n  }\n}\n\nint main(void) {\n  FILE* maps_file;\n  /* map another copy of this executable (but MAP_SHARED this time) */\n  int fd = open(\"/proc/self/exe\", O_RDONLY);\n  test_assert(fd != -1);\n\n  /* Get the size of this executable */\n  struct stat stat_buf;\n  test_assert(fstat(fd, &stat_buf) == 0);\n\n  /* Map the executable */\n  void* map_addr =\n      mmap(NULL, stat_buf.st_size, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);\n  test_assert(map_addr != MAP_FAILED);\n\n  maps_file = fopen(\"/proc/self/maps\", \"r\");\n  iterate_maps(0, callback, maps_file);\n\n  /* Call my_sbrk in the new copy */\n  void (*fptr)(uintptr_t) = (void (*)(uintptr_t))(\n      (uintptr_t)map_addr + (uintptr_t)my_brk_file_offset);\n  fptr((uintptr_t)sbrk(0) + sysconf(_SC_PAGESIZE));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/membarrier.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define RR_MEMBARRIER_CMD_QUERY 0\n#define RR_MEMBARRIER_CMD_SHARED 1\n\nint main(void) {\n  int ret = syscall(RR_membarrier, RR_MEMBARRIER_CMD_QUERY, 0);\n  if (ret < 0 && errno == ENOSYS) {\n    atomic_puts(\"membarrier not supported, skipping test\");\n  } else {\n    test_assert(ret >= 0);\n    if (ret & RR_MEMBARRIER_CMD_SHARED) {\n      test_assert(0 == syscall(RR_membarrier, RR_MEMBARRIER_CMD_SHARED, 0));\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/memfd_create.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_MEMFD \"foo\"\n\nint main(void) {\n  int fd;\n\n  /* There's no libc helper for this syscall. */\n  fd = syscall(RR_memfd_create, TEST_MEMFD, 0);\n  if (-1 == fd && ENOSYS == errno) {\n    atomic_puts(\"SYS_memfd_create not supported on this kernel\");\n  } else {\n    test_assert(fd >= 0);\n    test_assert(0 == close(fd));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/memfd_create_dotnet_huge_mapping.c",
    "content": "#include \"util.h\"\n/*\nhttps://github.com/dotnet/runtime/blob/23aeecc9f91a9ae0a211702dbd849c90cdd81d36/src/coreclr/minipal/Unix/doublemapping.cpp#L85\n#ifdef TARGET_64BIT\nstatic const off_t MaxDoubleMappedSize = 2048ULL*1024*1024*1024;\n#else\nstatic const off_t MaxDoubleMappedSize = UINT_MAX;\n#endif\nTo prevent bugs that could result in writing a 2TB file, a 20GB limit is used instead.\n*/\n#define _1GB (1024 * 1024 * 1024ULL)\nunsigned long long MaxDoubleMappedSize = 20 * _1GB;\n#define PAGE_SIZE_4K 4096\n\nvoid test_ftruncate_huge_mapping(void) {\n  int fd = memfd_create(\"double_mapper_test\", MFD_CLOEXEC);\n  test_assert(fd >= 0);\n  test_assert(ftruncate(fd, MaxDoubleMappedSize) == 0);\n  void* executable_addr = mmap(NULL, PAGE_SIZE_4K, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);\n  test_assert(executable_addr != MAP_FAILED);\n  test_assert(0 == close(fd));\n}\n\nint main(void) {\n#if defined(__i386__)\n  atomic_puts(\"Skipping test on 32 bit\");\n#else\n  struct timespec start, end;\n  test_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &start));\n  test_ftruncate_huge_mapping();\n  test_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &end));\n  //check timeout\n  test_assert((end.tv_sec - start.tv_sec) <= 2);\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/memfd_create_efault.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n\n  /* There's no libc helper for this syscall. */\n  fd = syscall(RR_memfd_create, NULL, 0);\n  if (ENOSYS == errno) {\n    atomic_puts(\"SYS_memfd_create not supported on this kernel\");\n  } else {\n    test_assert(fd == -1);\n    test_assert(errno == EFAULT);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/memfd_create_shared.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_MEMFD \"foo\"\n\nint main(void) {\n  int fd;\n\n  /* There's no libc helper for this syscall. */\n  fd = syscall(RR_memfd_create, TEST_MEMFD, 0);\n  if (-1 == fd && ENOSYS == errno) {\n    atomic_puts(\"SYS_memfd_create not supported on this kernel\");\n  } else {\n    void* p1;\n    test_assert(fd >= 0);\n    ftruncate(fd, 4096);\n    /* Create a shared, executable mapping to make sure that works.\n       In the past, rr depended on /tmp being mounted exec for this to work. */\n    p1 = mmap(0, 4096, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0);\n    test_assert(p1 != MAP_FAILED);\n    test_assert(0 == close(fd));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/memfd_create_shared_huge.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_MEMFD \"bar\"\n/* On my system (5.4.0-67-generic) /proc/pid/mem can take 2GB - 1 page at once. */\n#define MEMFD_SIZE (2LL * 1024 * 1024 * 1024)\n\nint main(void) {\n#if defined(__i386__)\n  atomic_puts(\"Skipping test on 32 bit\");\n#else\n  int fd;\n\n  /* There's no libc helper for this syscall. */\n  fd = syscall(RR_memfd_create, TEST_MEMFD, 0);\n  if (-1 == fd && ENOSYS == errno) {\n    atomic_puts(\"SYS_memfd_create not supported on this kernel\");\n  } else {\n    test_assert(fd >= 0);\n    if (0 != ftruncate(fd, 2LL * 1024 * 1024 * 1024)) {\n      atomic_puts(\"Could not create 2GB memfd\");\n    } else {\n      void *p1, *p2;\n      /* Map it once */\n      p1 = mmap(0, MEMFD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n      test_assert(p1 != MAP_FAILED);\n      *(uint32_t*)p1 = 0xdeadbeef;\n      /* Map it again */\n      p2 = mmap(0, MEMFD_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n      test_assert(p2 != MAP_FAILED);\n      test_assert(*(uint32_t*)p2 == 0xdeadbeef);\n      test_assert(0 == close(fd));\n    }\n  }\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mincore.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_SIZE 10\n\nint main(int argc, __attribute__((unused)) char* argv[]) {\n  unsigned char* buf;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p = (void*)((long)&argc & ~(long)(page_size - 1));\n  ALLOCATE_GUARD(buf, 'q');\n  test_assert(0 == mincore(p, page_size, buf));\n  /* I guess we can't actually check mincore's results in any way */\n  VERIFY_GUARD(buf);\n\n  atomic_printf(\"In-core=%d\\n\", *buf & 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mknod.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define FILENAME \"foo\"\n#define MODE S_IFIFO\n\nint main(void) {\n  struct stat* st;\n\n  test_assert(mknod(FILENAME, MODE, 0) == 0);\n\n  ALLOCATE_GUARD(st, 'x');\n  test_assert(stat(FILENAME, st) == 0);\n  test_assert(st->st_mode == MODE);\n  VERIFY_GUARD(st);\n\n  test_assert(mknod(FILENAME, MODE, 0) < 0);\n  test_assert(errno == EEXIST);\n\n  test_assert(0 == unlink(FILENAME));\n\n  test_assert(mknodat(AT_FDCWD, FILENAME, MODE, 0) == 0);\n\n  test_assert(stat(FILENAME, st) == 0);\n  test_assert(st->st_mode == MODE);\n  VERIFY_GUARD(st);\n\n  test_assert(0 == unlink(FILENAME));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mlock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  test_assert(0 == mlock(p, page_size) || errno == ENOMEM || errno == EPERM);\n  test_assert(0 == munlock(p, page_size));\n  test_assert(0 == mlockall(MCL_CURRENT) || errno == ENOMEM || errno == EPERM);\n  test_assert(0 == munlockall());\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mlock_madvise.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char* p = mmap(NULL, page_size*2, PROT_READ | PROT_WRITE,\n      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  p[0] = 'a';\n  p[page_size] = 'b';\n  test_assert(mlock(p + page_size, page_size) == 0);\n  test_assert(madvise(p, page_size*2, MADV_DONTNEED) == -1);\n  test_assert(errno == EINVAL);\n  test_assert(p[0] == 0);\n  test_assert(p[page_size] == 'b');\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_adjacent_to_rr_usage.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define RR_PAGE_ADDR 0x70000000\n\nstatic void* map_addr;\nstatic uintptr_t page_size;\n\n/* Look for a mapping that looks like Monkeypatcher's stubs page,\n   and try allocating our own page next to it to see if that causes\n   problems for rr. */\nvoid callback(__attribute__((unused)) uint64_t env,\n              __attribute__((unused)) char* name, map_properties_t* props) {\n  if (!strcmp(props->flags, \"r-xp\") &&\n      (props->end - props->start) == page_size && props->start != 0x70000000 &&\n      (int64_t)props->start >= 0) {\n    map_addr = (void*)(uintptr_t)props->start;\n  }\n}\n\nint main(void) {\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  void* ret;\n\n  page_size = sysconf(_SC_PAGESIZE);\n  iterate_maps(0, callback, maps_file);\n  atomic_printf(\"Targeted map addr is %p\\n\", map_addr);\n  ret = mmap(map_addr + page_size, page_size, PROT_READ | PROT_EXEC,\n             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  if (ret == MAP_FAILED) {\n    /* The allocation might not work because there might already\n       be something there. If so, fail gracefully. */\n    test_assert(errno == EINVAL);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_fd_reuse_checkpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int fd;\n\nvoid do_checkpoint(void) {}\n\nstatic void* le_thread(__attribute__((unused)) void* p) {\n  do_checkpoint();\n  close(fd);\n  return NULL;\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  const char kFileName[] = \"file\";\n\n  fd = open(kFileName, O_CREAT | O_EXCL | O_RDWR, 0600);\n  assert(fd >= 0);\n\n  int old = fd;\n\n  char* wpage = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  assert(wpage != MAP_FAILED);\n\n  pthread_t thread;\n  pthread_create(&thread, NULL, le_thread, wpage);\n  pthread_join(thread, NULL);\n\n  fd = open(kFileName, O_EXCL | O_RDWR);\n  assert(fd == old && \"test expects fd reuse\");\n\n  munmap(wpage, 0);\n  unlink(kFileName);\n}\n"
  },
  {
    "path": "src/test/mmap_fd_reuse_checkpoint.py",
    "content": "from util import *\n\nsend_gdb('break do_checkpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1')\nsend_gdb('c')\nexpect_gdb('xited normally')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('xited normally')\nsend_gdb('c')\n\nok()\n"
  },
  {
    "path": "src/test/mmap_fd_reuse_checkpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord mmap_fd_reuse_checkpoint$bitness\ndebug_gdb_only mmap_fd_reuse_checkpoint\n"
  },
  {
    "path": "src/test/mmap_huge.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  if (sizeof(void*) == 4) {\n    atomic_puts(\"Skipping test on 32-bit\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int fd = memfd_create(\"rr_test\", 0);\n  test_assert(fd >= 0);\n  uint64_t len = 1LL << 40;\n  int ret = ftruncate(fd, len);\n  test_assert(ret == 0);\n  ret = write(fd, \"x\", 1);\n  test_assert(ret == 1);\n\n  int flags[] = { PROT_NONE, PROT_READ };\n  int mode[] = { MAP_PRIVATE, MAP_SHARED };\n  for (int i = 0; i < 2; ++i) {\n    for (int j = 0; j < 2; ++j) {\n      void* p = mmap(NULL, len, flags[i], mode[j], fd, 0);\n      test_assert(p != MAP_FAILED);\n      ret = munmap(p, len);\n      test_assert(ret == 0);\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_private.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(__attribute__((unused)) int argc, char* argv[]) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(argv[0], O_RDONLY);\n  int* wpage;\n  int* rpage;\n  size_t i;\n\n  test_assert(fd >= 0);\n\n  breakpoint();\n  wpage = mmap(NULL, num_bytes, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n\n  breakpoint();\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_PRIVATE, fd, 0);\n\n  test_assert(wpage != (void*)-1 && rpage != (void*)-1 && rpage != wpage);\n\n  breakpoint();\n  for (i = 0; i < num_bytes / sizeof(int); ++i) {\n    int magic;\n\n    test_assert(wpage[i] == rpage[i]);\n\n    magic = rpage[i] * 31 + 3;\n    wpage[i] = magic;\n\n    test_assert(rpage[i] != magic && wpage[i] == magic);\n    atomic_printf(\"%d:%d,\", rpage[i], wpage[i]);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_private_grow_under_map.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"file\", O_RDWR | O_CREAT | O_TRUNC, 0700);\n  char* p;\n  test_assert(fd >= 0);\n  unlink(\"file\");\n\n  p = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n  test_assert(p != MAP_FAILED);\n  ftruncate(fd, page_size);\n  p[0] = 'x';\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_recycle.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#define PREFIX \"./\"\n\nstatic int child_to_parent_pipe[2];\n\nstatic void do_child(void) {\n  struct stat st;\n  unlink(\"foobar\");\n  int fd = open(PREFIX \"foobar\", O_CREAT | O_RDWR, 0700);\n  test_assert(fd >= 0);\n  int ret = unlink(PREFIX \"foobar\");\n  test_assert(ret == 0);\n  ret = write(fd, \"x\", 1);\n  test_assert(ret == 1);\n  ret = fstat(fd, &st);\n  test_assert(ret == 0);\n  void* p = mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  ret = write(child_to_parent_pipe[1], &st.st_ino, sizeof(st.st_ino));\n  test_assert(ret == sizeof(st.st_ino));\n  kill(getpid(), SIGSTOP);\n}\n\nint main(void) {\n  int ret = pipe(child_to_parent_pipe);\n  pid_t child;\n  ino_t child_inode;\n  struct timespec ts = { 0, 1000000 };\n  test_assert(ret == 0);\n\n  for (int i = 0; i < 10; ++i) {\n    char buf[100];\n    sprintf(buf, PREFIX \"foobar%d\", i);\n    unlink(buf);\n  }\n\n  child = fork();\n  if (!child) {\n    do_child();\n    return 0;\n  }\n  ret = read(child_to_parent_pipe[0], &child_inode, sizeof(child_inode));\n  test_assert(ret == sizeof(child_inode));\n  ret = kill(child, SIGKILL);\n  nanosleep(&ts, NULL);\n  test_assert(ret == 0);\n  /* now try to reuse the dev/ino */\n  for (int i = 0; i < 10; ++i) {\n    char buf[100];\n    struct stat st;\n    sprintf(buf, PREFIX \"foobar%d\", i);\n    unlink(buf);\n    int fd = open(buf, O_CREAT | O_RDWR, 0700);\n    test_assert(fd >= 0);\n    ret = fstat(fd, &st);\n    test_assert(ret >= 0);\n    if (st.st_ino == child_inode) {\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    ret = close(fd);\n    test_assert(ret >= 0);\n  }\n  atomic_puts(\"Skipping test because inode was not recycled; try running the test with the working directory in ext4\");\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_replace_most_mappings.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define MAX_ERRNO 4095\n\n#define RR_PAGE_ADDR 0x70000000\n#ifdef __aarch64__\n#define RR_THREAD_LOCALS_PAGE_ADDR 0x70010000\n#else\n#define RR_THREAD_LOCALS_PAGE_ADDR 0x70001000\n#endif\n\nstruct Unmaps {\n  uintptr_t unmappings[1000];\n  ssize_t nunmappings;\n};\n\nint main(void);\nstatic int contains_symbol(map_properties_t* props, void* symbol) {\n  return (props->start <= (uintptr_t)symbol && (uintptr_t)symbol < props->end);\n}\nvoid callback(uint64_t env, char* name, map_properties_t* props) {\n  if (contains_symbol(props, &main) ||\n      /* env is on the stack - this prevents it from being unmapped if\n         the kernel gets confused by syscallbuf's stack switching */\n      contains_symbol(props, &env) ||\n      (props->start <= RR_PAGE_ADDR && RR_PAGE_ADDR < props->end) ||\n      strcmp(name, \"[stack]\") == 0) {\n    return;\n  }\n\n  struct Unmaps* u = (struct Unmaps*)(size_t)env;\n  u->unmappings[2 * u->nunmappings] = (uintptr_t)props->start;\n  u->unmappings[2 * u->nunmappings + 1] = (uintptr_t)(props->end - props->start);\n  ++u->nunmappings;\n}\n\nstatic __attribute__((noinline)) void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nintptr_t my_syscall(intptr_t syscallno, intptr_t arg1, intptr_t arg2,\n                    intptr_t arg3, intptr_t arg4, intptr_t arg5, intptr_t arg6);\n\n#ifdef __i386__\n__asm__(\"my_syscall:\\n\\t\"\n        \"push %ebp\\n\\t\"\n        \"push %esi\\n\\t\"\n        \"push %edi\\n\\t\"\n        \"push %ebx\\n\\t\"\n        \"mov 20(%esp),%eax\\n\\t\"\n        \"mov 24(%esp),%ebx\\n\\t\"\n        \"mov 28(%esp),%ecx\\n\\t\"\n        \"mov 32(%esp),%edx\\n\\t\"\n        \"mov 36(%esp),%esi\\n\\t\"\n        \"mov 40(%esp),%edi\\n\\t\"\n        \"mov 44(%esp),%ebp\\n\\t\"\n        \"int $0x80\\n\\t\"\n        \"pop %ebx\\n\\t\"\n        \"pop %edi\\n\\t\"\n        \"pop %esi\\n\\t\"\n        \"pop %ebp\\n\\t\"\n        \"ret\\n\\t\");\n#elif defined(__x86_64__)\n__asm__(\"my_syscall:\\n\\t\"\n        \"mov %rdi,%rax\\n\\t\"\n        \"mov %rsi,%rdi\\n\\t\"\n        \"mov %rdx,%rsi\\n\\t\"\n        \"mov %rcx,%rdx\\n\\t\"\n        \"mov %r8,%r10\\n\\t\"\n        \"mov %r9,%r8\\n\\t\"\n        \"mov 8(%rsp),%r9\\n\\t\"\n        \"syscall\\n\\t\"\n        \"ret\\n\\t\");\n#elif defined(__aarch64__)\n__asm__(\"my_syscall:\\n\\t\"\n        \"mov x8,x0\\n\\t\"\n        \"mov x0,x1\\n\\t\"\n        \"mov x1,x2\\n\\t\"\n        \"mov x2,x3\\n\\t\"\n        \"mov x3,x4\\n\\t\"\n        \"mov x4,x5\\n\\t\"\n        \"mov x5,x6\\n\\t\"\n        \"b 1f\\n\\t\"\n        \"mov x8, 0xdc\\n\"\n        \"1:\\n\\t\"\n        \"svc #0\\n\\t\"\n        \"ret\\n\\t\");\n#else\n#error Fill in syscall here\n#endif\n\nint main(void) {\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  int i = 0;\n  struct Unmaps u;\n  u.nunmappings = 0;\n  // Scan and record mappings - we can't mmap over them yet because libc will\n  // be gone at some point. After iterate_maps, no C library calls are allowed\n  iterate_maps((size_t)&u, callback, maps_file);\n  for (i = 0; i < u.nunmappings; ++i) {\n    const int mmap_syscall =\n#ifdef __i386__\n        RR_mmap2\n#elif defined(__x86_64__) || defined(__aarch64__)\n        RR_mmap\n#else\n#error Fill in syscall here\n#endif\n        ;\n    int ret =\n        my_syscall(mmap_syscall, u.unmappings[2 * i], u.unmappings[2 * i + 1],\n                   PROT_NONE, MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);\n    // We can't even use test_assert here, because it'll call strerror to printf\n    // the failure\n    // and we're unmapping libc).\n    // NB: Trying to mess with the highest pages on x86-64 gets us an ENOMEM\n    // error.\n    if (ret <= 0 && ret >= -MAX_ERRNO && ret != -ENOMEM) {\n      my_syscall(RR_exit, ret, 0, 0, 0, 0, 0);\n    }\n  }\n\n  my_syscall(RR_mprotect, RR_THREAD_LOCALS_PAGE_ADDR, 4096,\n             PROT_READ | PROT_WRITE, 0, 0, 0);\n  *((uint64_t*)RR_THREAD_LOCALS_PAGE_ADDR) = RR_PAGE_ADDR;\n  my_syscall(RR_mprotect, RR_THREAD_LOCALS_PAGE_ADDR, 4096, PROT_NONE, 0, 0, 0);\n\n  breakpoint();\n\n  my_syscall(RR_mprotect, RR_THREAD_LOCALS_PAGE_ADDR, 4096, PROT_READ, 0, 0, 0);\n  int ret =\n      (*((uint64_t*)RR_THREAD_LOCALS_PAGE_ADDR) == RR_PAGE_ADDR) ? 0 : -42;\n\n  my_syscall(RR_exit, ret, 0, 0, 0, 0, 0);\n  // Never reached, but make compiler happy.\n  return 1;\n}\n"
  },
  {
    "path": "src/test/mmap_replace_most_mappings.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('rc')\nexpect_history_end()\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('SIGKILL')\n\nok()\n"
  },
  {
    "path": "src/test/mmap_replace_most_mappings.run",
    "content": "source `dirname $0`/util.sh\nrecord mmap_replace_most_mappings$bitness\ndebug_gdb_only mmap_replace_most_mappings\n"
  },
  {
    "path": "src/test/mmap_ro.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DUMMY_FILE \"dummy.txt\"\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(DUMMY_FILE, O_CREAT | O_EXCL | O_RDWR, 0600);\n  int one = 1;\n  int* rpage;\n\n  test_assert(fd >= 0);\n\n  test_assert(sizeof(one) == write(fd, &one, sizeof(one)));\n\n  test_assert(0 == fchmod(fd, 0400));\n\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(rpage != (void*)-1);\n\n  unlink(DUMMY_FILE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_self_maps_shared.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid callback(uint64_t env, char* name, map_properties_t* props) {\n  (void)env;\n  if (name[0] != '/') {\n    return;\n  }\n  int fd = open(name, O_RDONLY);\n  void* addr =\n      mmap(NULL, props->end - props->start, PROT_READ, MAP_SHARED, fd, 0);\n  munmap(addr, props->end - props->start);\n  close(fd);\n}\n\nint main(void) {\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  iterate_maps(0, callback, maps_file);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int create_segment(size_t num_bytes) {\n  char filename[] = \"/dev/shm/rr-test-XXXXXX\";\n  int fd = mkstemp(filename);\n  unlink(filename);\n  test_assert(fd >= 0);\n  ftruncate(fd, num_bytes);\n  return fd;\n}\n\nstruct mmap_arg_struct {\n  unsigned long addr;\n  unsigned long len;\n  unsigned long prot;\n  unsigned long flags;\n  unsigned long fd;\n  unsigned long offset;\n};\n\nstatic void run_test(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = create_segment(num_bytes);\n  int* wpage = mmap(NULL, num_bytes, PROT_WRITE, MAP_SHARED, fd, 0);\n  size_t i;\n  int* rpage;\n\n  close(128);\n  munmap(NULL, 0);\n\n#if defined(__i386__)\n  struct mmap_arg_struct args;\n  args.addr = 0;\n  args.len = num_bytes;\n  args.prot = PROT_READ;\n  args.flags = MAP_SHARED;\n  args.fd = fd;\n  args.offset = 0;\n  rpage = (int*)syscall(SYS_mmap, &args, -1, -1, -1, -1, -1);\n#elif defined(__x86_64__) || defined(__aarch64__)\n  rpage = (int*)syscall(SYS_mmap, 0, num_bytes, PROT_READ, MAP_SHARED, fd,\n                        (off_t)0);\n#else\n#error unknown architecture\n#endif\n\n  test_assert(wpage != (void*)-1 && rpage != (void*)-1 && rpage != wpage);\n\n  close(128);\n\n  for (i = 0; i < num_bytes / sizeof(int); ++i) {\n    wpage[i] = i;\n    test_assert(rpage[i] == (ssize_t)i);\n  }\n}\n\nint main(void) {\n  pid_t c;\n  int status;\n\n  atomic_printf(\"%d: checking shared maps ...\\n\", getpid());\n  run_test();\n\n  if (0 == (c = fork())) {\n    atomic_printf(\"%d:   and in fork child ...\\n\", getpid());\n    run_test();\n    exit(0);\n  }\n  test_assert(c == waitpid(c, &status, 0) && WIFEXITED(status) &&\n              0 == WEXITSTATUS(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_dev_zero.c",
    "content": "#include \"util.h\"\n\n#include <assert.h>\n#include <fcntl.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGE_SIZE);\n  int fd = open(\"/dev/zero\", O_RDWR);\n  void* p1 = mmap(0, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  assert(p1 != MAP_FAILED);\n  void* p2 = mmap(0, page_size, PROT_READ, MAP_SHARED, fd, 0);\n  assert(p2 != MAP_FAILED);\n  assert(p1 != p2);\n\n  memset(p1, 0xdd, page_size);\n  // Verify that these mappings are not connected.\n  assert(*(long*)p2 == 0);\n  atomic_printf(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_extern.c",
    "content": "#include \"util.h\"\n\n#include <assert.h>\n#include <fcntl.h>\n#include <string.h>\n#include <sys/mman.h>\n#include <sys/stat.h>\n\nint main(__attribute__((unused)) int argc, char* argv[], char* argenv[]) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char last = 0;\n  char* p;\n  int proc_num = argv[2][0] - '0';\n  int timeout = 30000; // 30 seconds\n\n  if (argv[3][0] > '0') {\n    if (fork() == 0) {\n      char proc_num_arg[2] = {'0' + proc_num + 1, '\\0'};\n      char proc_to_start_arg[2] = {argv[3][0] - 1, '\\0'};\n      char* execv_argv[] = {argv[0], argv[1], proc_num_arg, proc_to_start_arg, NULL};\n      execve(\"/proc/self/exe\", execv_argv, argenv);\n    }\n  }\n\n  int fd = open(argv[1], O_RDWR|O_CREAT, 0600);\n  test_assert(fd >= 0);\n  ftruncate(fd, page_size);\n  p = (char*)mmap(0, page_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);\n  assert(p != MAP_FAILED);\n\n  while (1) {\n    if ((*p % 2) == proc_num) {\n      if ((*p)++ >= 6) {\n        atomic_printf(\"%d %d exiting.\\n\", getpid(), proc_num);\n        usleep(50000); /* first recorded process exiting kills all others, wait a little. */\n        return 0;\n      }\n    }\n    if (last != *p)\n      atomic_printf(\"%d\\n\", last = *p);\n    usleep(50000);\n    timeout -= 50;\n    if (timeout < 0) {\n        atomic_printf(\"timeout reached.\\n\");\n        return 0;\n    }\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_extern.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_rr_32_bit_with_shell_64_bit\n\nrm -rf $workdir/map_file\nRECORD_ARGS=\"--check-outside-mmaps\"\nrecord mmap_shared_extern$bitness $workdir/map_file 0 1\nmv record.out record.out.1\nmv record.err record.err.1\ngrep \"could cause diversion\" $workdir/record.out.1 > /dev/null\nif [[ $? != 1 ]]; then\n  failed \"\\\"could cause diversion\\\" was returned when all processes are inside the recording.\"\n  exit\nfi\n\nrm -rf $workdir/map_file\nmmap_shared_extern$bitness $workdir/map_file 0 0 > /dev/null&\nRECORD_ARGS=\"--check-outside-mmaps\"\nrecord mmap_shared_extern$bitness $workdir/map_file 1 0\nmv record.out record.out.2\nmv record.err record.err.2\ngrep \"could cause diversion\" $workdir/record.out.2 > /dev/null\nif [[ $? != 0 ]]; then\n  failed \"\\\"could cause diversion\\\" was not returned when some processes are outside the recording.\"\nfi\n"
  },
  {
    "path": "src/test/mmap_shared_grow.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int create_segment(size_t num_bytes) {\n  char filename[] = \"/dev/shm/rr-test-XXXXXX\";\n  int fd = mkstemp(filename);\n  unlink(filename);\n  test_assert(fd >= 0);\n  ftruncate(fd, num_bytes);\n  return fd;\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  size_t num_bytes = 120; /* Not a multiple of the page size */\n  int fd = create_segment(num_bytes);\n  int* page = mmap(NULL, 2 * page_size, PROT_READ, MAP_SHARED, fd, 0);\n  int* data_page = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,\n                        MAP_SHARED | MAP_ANONYMOUS, -1, 0);\n\n  int magic = 0xa5a5a5a5;\n  for (int* p = data_page; p < data_page + 2 * page_size / sizeof(magic); ++p) {\n    *p = magic;\n  }\n\n  pwrite64(fd, data_page, 2 * page_size - num_bytes, num_bytes);\n\n  test_assert(*(page + 2 * page_size / sizeof(magic) - 1) == magic);\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_grow_under_map.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"file\", O_RDWR | O_CREAT | O_TRUNC, 0700);\n  char* p;\n  test_assert(fd >= 0);\n  unlink(\"file\");\n\n  p = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  ftruncate(fd, page_size);\n  p[0] = 'x';\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_multiple.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char* p;\n  char* q;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,\n           -1, 0);\n  test_assert(p != MAP_FAILED);\n  q = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,\n           -1, 0);\n  test_assert(q != MAP_FAILED);\n\n  *p = 'a';\n  test_assert(*q == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_prot.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nint main(void) {\n  pid_t child;\n  int status;\n  char* p;\n\n  /* Do a dummy waitpid so the real one doesn't go through the linker,\n     patching etc */\n  waitpid(-2, NULL, 0);\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,\n           -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  *p = 'a';\n\n  if ((child = fork()) == 0) {\n    while (*(char*)p == 'a') {\n      sched_yield();\n    }\n    return 0;\n  }\n\n  test_assert(0 == mprotect(p, page_size, PROT_READ));\n\n  breakpoint();\n\n  test_assert(0 == mprotect(p, page_size, PROT_READ | PROT_WRITE));\n\n  *p = *p + 1;\n\n  test_assert(*p == 'b');\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(0 == status);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_prot.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('check')\nexpect_gdb('Checkpoint 1 at')\n\nsend_gdb('c')\nexpect_gdb('exited normally')\n\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/mmap_shared_prot.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/mmap_shared_subpage.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int create_segment(size_t num_bytes) {\n  char filename[] = \"/dev/shm/rr-test-XXXXXX\";\n  int fd = mkstemp(filename);\n  unlink(filename);\n  test_assert(fd >= 0);\n  ftruncate(fd, num_bytes);\n  return fd;\n}\n\nint main(void) {\n  size_t num_bytes = 120; /* Not a multiple of the page size */\n  int fd = create_segment(num_bytes);\n  int* wpage = mmap(NULL, num_bytes, PROT_WRITE, MAP_SHARED, fd, 0);\n  int* rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  size_t i;\n\n  test_assert(wpage != (void*)-1 && rpage != (void*)-1 && rpage != wpage);\n\n  close(128);\n\n  for (i = 0; i < num_bytes / sizeof(int); ++i) {\n    wpage[i] = i;\n    test_assert(rpage[i] == (ssize_t)i);\n    atomic_printf(\"%d,\", rpage[i]);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_write.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void check_mapping(int* page, int magic, ssize_t nr_ints) {\n  int i;\n  for (i = 0; i < nr_ints; ++i) {\n    test_assert(page[i] == magic);\n  }\n  atomic_printf(\"  %p has the correct values\\n\", page);\n}\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(\"temp\", O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* rpage;\n\n  unlink(\"temp\");\n\n  test_assert(fd >= 0);\n\n  int magic = 0x5a5a5a5a;\n  size_t i;\n  for (i = 0; i < 3 * num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"rpage:%p\\n\", rpage);\n  test_assert(rpage != MAP_FAILED);\n\n  magic = 0xa5a5a5a5;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n\n  check_mapping(rpage, 0xa5a5a5a5, num_bytes / sizeof(*rpage));\n\n  magic = 0x5a5a5a5a;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n\n  check_mapping(rpage, 0x5a5a5a5a, num_bytes / sizeof(*rpage));\n\n  magic = 0xa5a5a5a5;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), num_bytes + i * sizeof(magic));\n  }\n\n  check_mapping(rpage, 0x5a5a5a5a, num_bytes / sizeof(*rpage));\n\n  magic = 0xdeadbeef;\n  pwrite64(fd, &magic, sizeof(magic), num_bytes / 2);\n\n  test_assert(rpage[num_bytes / (sizeof(magic) * 2)] == magic);\n  test_assert(rpage[0] != magic);\n\n  pwrite64(fd, &magic, sizeof(magic), num_bytes - 2);\n  test_assert(rpage[num_bytes / sizeof(magic) - 1] == (int)0xbeef5a5a);\n\n  rpage = mremap(rpage, num_bytes, 5 * num_bytes, MREMAP_MAYMOVE);\n  for (i = 3 * num_bytes / sizeof(magic); i < 5 * num_bytes / sizeof(magic);\n       ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n  check_mapping(&rpage[(3 * num_bytes) / sizeof(magic)], 0xdeadbeef,\n                2 * num_bytes / sizeof(*rpage));\n\n  munmap(rpage, 5 * num_bytes);\n\n  // The case when all pages have been unmapped is special in the\n  // implementation - make sure it gets sufficient coverage\n  write(fd, &magic, sizeof(magic));\n  write(fd, &magic, sizeof(magic));\n\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"rpage:%p\\n\", rpage);\n  test_assert(rpage != MAP_FAILED);\n\n  // This tests both that the monitor gets activated again if the page is\n  // remapped and that `write` works on a monitored page.\n  lseek(fd, 0, SEEK_SET);\n  magic = 0xb6b6b6b6;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    write(fd, &magic, sizeof(magic));\n  }\n  check_mapping(rpage, magic, num_bytes / sizeof(*rpage));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_write_exec_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void check_mapping(int* page, int magic, ssize_t nr_ints) {\n  int i;\n  for (i = 0; i < nr_ints; ++i) {\n    test_assert(page[i] == magic);\n  }\n  atomic_printf(\"  %p has the correct values\\n\", page);\n}\n\nint main(int argc, char* argv[]) {\n  if (argc > 1 && strcmp(argv[1], \"exit\") == 0) {\n    return 0;\n  }\n\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(\"temp\", O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* rpage;\n\n  unlink(\"temp\");\n\n  test_assert(fd >= 0);\n\n  int magic = 0x5a5a5a5a;\n  size_t i;\n\n  for (i = 0; i < 3 * num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"rpage:%p\\n\", rpage);\n  test_assert(rpage != MAP_FAILED);\n\n  magic = 0xa5a5a5a5;\n\n  if (0 == fork()) {\n    execl(argv[0], argv[0], \"exit\", (char*)0);\n  }\n\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n\n  check_mapping(rpage, 0xa5a5a5a5, num_bytes / sizeof(*rpage));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_shared_write_exec_race.run",
    "content": "source `dirname $0`/util.sh\n\n# Switch threads very eagerly on recorded events.\nRECORD_ARGS=\"-s\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/mmap_shared_write_fork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void check_mapping(int* page, int magic, ssize_t nr_ints) {\n  int i;\n  for (i = 0; i < nr_ints; ++i) {\n    test_assert(page[i] == magic);\n  }\n  atomic_printf(\"  %p has the correct values\\n\", page);\n}\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(\"temp\", O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* rpage;\n  pid_t child;\n  int status;\n\n  unlink(\"temp\");\n\n  test_assert(fd >= 0);\n\n  int magic = 0x5a5a5a5a;\n  size_t i;\n  for (i = 0; i < 3 * num_bytes / sizeof(magic); ++i) {\n    pwrite64(fd, &magic, sizeof(magic), i * sizeof(magic));\n  }\n\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"rpage:%p\\n\", rpage);\n  test_assert(rpage != MAP_FAILED);\n\n  magic = 0x12341234;\n\n  child = fork();\n  if (!child) {\n    test_assert(0 == munmap(rpage, num_bytes));\n\n    /* Test that writing while our page is unmapped but another\n       process has a page mapped works */\n    pwrite64(fd, &magic, sizeof(magic), 0);\n\n    return 77;\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  check_mapping(rpage, magic, 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_short_file.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DUMMY_FILE \"dummy.txt\"\n\nstatic void sighandler(int sig) {\n  atomic_printf(\"caught signal %d, exiting\\n\", sig);\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(DUMMY_FILE, O_CREAT | O_EXCL | O_RDWR, 0600);\n  int one = 1;\n  int* rpage;\n\n  unlink(DUMMY_FILE);\n\n  test_assert(fd >= 0);\n  test_assert(sizeof(one) == write(fd, &one, sizeof(one)));\n\n  rpage = mmap(NULL, page_size * 2, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(rpage != (void*)-1);\n  test_assert(*rpage == 1);\n\n  signal(SIGSEGV, sighandler);\n  signal(SIGBUS, sighandler);\n  /* This should generate a SIGBUS, but the test will pass whether the\n     kernel generates SIGBUS or SIGSEGV.\n     rr checks that the same signal is produced during replay\n     as during recording. */\n  char ch = *((char*)rpage + page_size);\n\n  atomic_printf(\"FAILED: no segfault, read %d\", ch);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_tmpfs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_FILENAME \"foo.so\"\n#define TOKEN \"hello kitty\"\n\nint main(void) {\n  int fd = open(TEST_FILENAME, O_CREAT | O_EXCL | O_RDWR, 0700);\n  char* bytes;\n\n  write(fd, TOKEN, sizeof(TOKEN));\n  close(fd);\n\n  fd = open(TEST_FILENAME, O_RDONLY);\n  bytes = (char*)mmap(NULL, 4096, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);\n  test_assert(bytes != MAP_FAILED);\n  test_assert(!strcmp(bytes, TOKEN));\n  munmap(bytes, 4096);\n  close(fd);\n\n  unlink(TEST_FILENAME);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_tmpfs.run",
    "content": "source `dirname $0`/util.sh\nunset RR_TRUST_TEMP_FILES\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/mmap_write.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DUMMY_FILE \"dummy.txt\"\n\nstatic const int magic = 0x5a5a5a5a;\n\nstatic void overwrite_file(const char* path, size_t num_bytes) {\n  int fd = open(path, O_TRUNC | O_RDWR);\n  size_t i;\n\n  test_assert(fd >= 0);\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    write(fd, &magic, sizeof(magic));\n  }\n  close(fd);\n}\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(DUMMY_FILE, O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* rpage;\n  size_t i;\n\n  test_assert(fd >= 0);\n\n  overwrite_file(DUMMY_FILE, num_bytes);\n\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"rpage:%p\\n\", rpage);\n  test_assert(rpage != (void*)-1);\n\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    test_assert(rpage[i] == magic);\n  }\n\n  lseek(fd, 0, SEEK_SET);\n\n  for (i = 0; i < num_bytes / sizeof(i); ++i) {\n    int written;\n\n    write(fd, &i, sizeof(i));\n    written = rpage[i];\n    atomic_printf(\"(wrote %d, read %d)\", (int)i, written);\n    test_assert(written == (ssize_t)i);\n  }\n\n  atomic_puts(\" done\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_write.run",
    "content": "source `dirname $0`/util.sh\n\nfails \"write()s to SHARED mapped files aren't propagated to mapping during replay.\"\n\ncompare_test 'done'\n"
  },
  {
    "path": "src/test/mmap_write_complex.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"output\", O_RDWR | O_CREAT, 0777);\n  int fd2 = dup(fd);\n  /* create a new file description */\n  int fd3 = open(\"output\", O_RDWR);\n  int fd4;\n  int fd5 = open(\"output\", O_RDONLY);\n  int ret;\n  char* p = (char*)mmap(NULL, 10, PROT_READ | PROT_WRITE,\n                        MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n\n  ret = write(fd, \"x\", 1);\n  test_assert(ret == 1);\n  test_assert(p[0] == 'x');\n\n  ret = write(fd2, \"y\", 1);\n  test_assert(ret == 1);\n  test_assert(p[1] == 'y');  \n\n  ret = write(fd3, \"z\", 1);\n  test_assert(ret == 1);\n  test_assert(p[0] == 'z');  \n\n  /* Check that an open after the mmap works */\n  fd4 = open(\"output\", O_RDWR);\n  ret = write(fd4, \"a\", 1);\n  test_assert(ret == 1);\n  test_assert(p[0] == 'a');  \n\n  /* Unmap, write, remap and write again to make sure that works. */\n  munmap(p, 10);\n\n  ret = write(fd4, \"b\", 1);\n  test_assert(ret == 1);\n\n  p = (char*)mmap(NULL, 10, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n\n  ret = write(fd4, \"c\", 1);\n  test_assert(ret == 1);\n  test_assert(p[1] == 'b');\n  test_assert(p[2] == 'c');\n\n  /* Make sure a shared mapping from a read-only fd also works */\n  p = (char*)mmap(NULL, 10, PROT_READ, MAP_SHARED, fd5, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[1] == 'b');\n  test_assert(p[2] == 'c');\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_write_private.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"output\", O_RDWR | O_CREAT, 0777);\n  int fd2;\n  int fd3;\n  ssize_t ret;\n  char* p2;\n  char* p = (char*)mmap(NULL, 10, PROT_READ,\n                        MAP_PRIVATE, fd, 0);\n  test_assert(p != MAP_FAILED);\n\n  /* Opening a MAP_PRIVATE-mapped file writable is potentially\n     problematic, but it should at least be OK if we don't write to\n     it. */\n  fd2 = open(\"output\", O_RDWR);\n  test_assert(fd2 >= 0);\n\n  p2 = (char*)mmap(NULL, 10, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(p2 != MAP_FAILED);\n\n  /* Test what happens if the file is mapped private AND shared and\n     we write to it */\n  fd3 = open(\"output\", O_RDWR);\n  test_assert(fd3 >= 0);\n\n  ret = write(fd3, \"x\", 1);\n  test_assert(ret == 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mmap_write_private.run",
    "content": "source `dirname $0`/util.sh\nRR_COPY_ALL_FILES=1 compare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/mmap_zero_size_fd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  static const char name[] = \"temp\";\n  int fd = open(name, O_CREAT | O_RDWR | O_EXCL, 0600);\n  ftruncate(fd, 0);\n  void* mmap_addr =\n      mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);\n  test_assert(mmap_addr != MAP_FAILED);\n\n  test_assert(0 == unlink(name));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/mount_ns_exec.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  if ((argc > 1 && strcmp(argv[1], \"in_copy\") == 0) ||\n      -1 == try_setup_ns(CLONE_NEWNS)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == mkdir(\"mountpoint\", 0700));\n  test_assert(0 == mount(\"none\", \"mountpoint\", \"tmpfs\", 0, NULL));\n\n  struct stat buf;\n  int ret = stat(\"/proc/self/exe\", &buf);\n  test_assert(ret != -1);\n  int src_fd = open(\"/proc/self/exe\", O_RDONLY);\n  test_assert(src_fd != -1);\n  int dst_fd = open(\"mountpoint/the_copy\", O_WRONLY | O_CREAT, 0700);\n  test_assert(dst_fd != -1);\n  off_t offset = 0;\n  test_assert(sendfile(dst_fd, src_fd, &offset, buf.st_size) == buf.st_size);\n  close(src_fd);\n  fsync(dst_fd);\n  close(dst_fd);\n\n  char* const new_argv[] = { \"mountpoint/the_copy\", \"in_copy\", NULL };\n  execve(\"mountpoint/the_copy\", new_argv, environ);\n  test_assert(0);\n  return 1;\n}\n"
  },
  {
    "path": "src/test/mount_ns_exec2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  if (argc > 1 && strcmp(argv[1], \"in_copy\") == 0) {\n    // Try to do an mmap call, just to stress that code path\n    long pagesize = sysconf(_SC_PAGESIZE);\n    int selffd = open(\"/proc/self/exe\", O_RDONLY);\n    test_assert(selffd != -1);\n    void *addr = mmap(NULL, pagesize, PROT_READ, MAP_PRIVATE, selffd, pagesize);\n    test_assert(addr != MAP_FAILED);\n    check_data(addr, pagesize);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  if (-1 == try_setup_ns(CLONE_NEWNS)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  char exe_buf[PATH_MAX+1];\n  memset(exe_buf, 0, sizeof(exe_buf));\n  ssize_t nread = readlink(\"/proc/self/exe\", exe_buf, sizeof(exe_buf)-1);\n  test_assert(nread != -1);\n\n  char *exe_name = strrchr(exe_buf, '/');\n  *exe_name = '\\0';\n  exe_name += 1;\n\n  test_assert(0 == mkdir(\"mountpoint\", 0700));\n\n  int mountpoint_fd = open(\"mountpoint\", O_PATH);\n  test_assert(mountpoint_fd != -1);\n\n  // Copy the exe to the mountpoint as well to make sure rr doesn't\n  // accidentally pick up the wrong one to put in the trace\n  struct stat buf;\n  int ret = stat(\"/proc/self/exe\", &buf);\n  test_assert(ret != -1);\n  int src_fd = open(\"/proc/self/exe\", O_RDONLY);\n  test_assert(src_fd != -1);\n  int dst_fd = openat(mountpoint_fd, exe_name, O_WRONLY | O_CREAT, 0700);\n  test_assert(dst_fd != -1);\n  off_t offset = 0;\n  // Only send the first 4096 bytes, so we really crash if somebody tries to\n  // Use that file instead\n  test_assert(sendfile(dst_fd, src_fd, &offset, 4096) == 4096);\n  close(src_fd);\n  fsync(dst_fd);\n  close(dst_fd);\n  close(mountpoint_fd);\n\n  test_assert(0 == mount(exe_buf, \"mountpoint\", \"none\", MS_BIND, NULL));\n\n  char exe_path[PATH_MAX];\n  ssize_t n = snprintf(exe_path, sizeof(exe_path), \"mountpoint/%s\", exe_name);\n  test_assert(n > 0 && n < (ssize_t)sizeof(exe_path));\n\n  char* const new_argv[] = { exe_path, \"in_copy\", NULL };\n  execve(exe_path, new_argv, environ);\n  test_assert(0);\n  return 1;\n}\n"
  },
  {
    "path": "src/test/mount_ns_execveat.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  if ((argc > 1 && strcmp(argv[1], \"in_copy\") == 0) ||\n      -1 == try_setup_ns(CLONE_NEWNS)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == mkdir(\"mountpoint\", 0700));\n  test_assert(0 == mount(\"none\", \"mountpoint\", \"tmpfs\", 0, NULL));\n\n  int fd = open(\"mountpoint/the_copy\", O_RDWR | O_CREAT | O_EXCL, 0600);\n  test_assert(fd >= 0);\n  test_assert(0 == close(fd));\n  test_assert(0 == mount(argv[0], \"mountpoint/the_copy\",\n                         \"\", MS_BIND, NULL));\n  int dst_fd = open(\"mountpoint/the_copy\", O_RDONLY | O_PATH);\n  test_assert(dst_fd != -1);\n\n  test_assert(0 == umount2(\"mountpoint/the_copy\", MNT_DETACH));\n\n  char* const new_argv[] = { \"mountpoint/the_copy\", \"in_copy\", NULL };\n  int ret = syscall(RR_execveat, dst_fd, \"\", new_argv, environ, AT_EMPTY_PATH);\n  if (ret < 0 && errno == ENOSYS) {\n    atomic_puts(\"execveat not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0);\n  return 1;\n}\n"
  },
  {
    "path": "src/test/mprotect.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* map1 = mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE,\n                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  uint8_t* map1_end = map1 + 2 * page_size;\n  uint8_t* map2;\n  uint8_t* map2_end;\n\n  test_assert(map1 != MAP_FAILED);\n\n  atomic_printf(\"map1 = [%p, %p)\\n\", map1, map1_end);\n\n  mprotect(map1 + page_size, page_size, PROT_NONE);\n\n  map2 = mmap(map1_end, 2 * page_size, PROT_READ | PROT_WRITE,\n              MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  map2_end = map2 + page_size;\n  test_assert(map2 != (void*)-1);\n  test_assert(map2 == map1_end);\n\n  atomic_printf(\"map2 = [%p, %p)\\n\", map2, map2_end);\n\n  mprotect(map2, page_size, PROT_NONE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_checkpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\n#define NUM_PAGES 20\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGE_SIZE);\n  char* p = (char*)mmap(NULL, page_size*NUM_PAGES, PROT_NONE,\n      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  for (int i = 0; i < NUM_PAGES; ++i) {\n    test_assert(0 == mprotect(p + page_size*i, page_size, PROT_READ));\n    breakpoint();\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_checkpoint.py",
    "content": "from util import *\nimport re\n\nsend_gdb('handle SIGKILL stop')\nexpect_gdb('SIGKILL')\nsend_gdb('continue')\nexpect_gdb('Killed')\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('ignore 1 1000000')\nexpect_gdb('Will ignore')\nsend_gdb('reverse-continue')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/mprotect_checkpoint.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/mprotect_growsdown.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char* p;\n\n  /* map 3 pages since the first page will be made into a guard page by the\n     kernel */\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE,\n           MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  test_assert(\n      0 == mprotect(p + page_size * 2, page_size, PROT_NONE | PROT_GROWSDOWN));\n\n  test_assert(-1 == mprotect(p + 1, page_size, PROT_NONE | PROT_GROWSDOWN));\n  test_assert(EINVAL == errno);\n\n  p = (char*)(((uintptr_t)main) & ~((uintptr_t)page_size - 1));\n  test_assert(-1 ==\n              mprotect(p, page_size, PROT_READ | PROT_EXEC | PROT_GROWSDOWN));\n  test_assert(EINVAL == errno);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_growsdown.run",
    "content": "source `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS\ncompare_test EXIT-SUCCESS --share-private-mappings\n"
  },
  {
    "path": "src/test/mprotect_heterogenous.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_FILE \"foo.txt\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(TEST_FILE, O_CREAT | O_EXCL | O_RDWR, 0600);\n  uint8_t* pages;\n  int ret, err;\n\n  test_assert(fd >= 0);\n  test_assert(0 == ftruncate(fd, 8 * page_size));\n\n  unlink(TEST_FILE);\n\n  pages = mmap(NULL, 5 * page_size, PROT_WRITE, MAP_PRIVATE, fd, 0);\n  test_assert(pages != (void*)-1);\n\n  /* Protect second page. */\n  test_assert(0 == mprotect(pages + page_size, page_size, PROT_NONE));\n  /* Protect fourth page. */\n  test_assert(0 == mprotect(pages + 3 * page_size, page_size, PROT_NONE));\n  /* Protect all five pages. */\n  test_assert(0 == mprotect(pages, 5 * page_size, PROT_NONE));\n\n  /* Unmap second page. */\n  test_assert(0 == munmap(pages + page_size, page_size));\n  /* Fail to protect the entire region, because one page is\n   * unmapped. */\n  errno = 0;\n  ret = mprotect(pages, 5 * page_size, PROT_READ | PROT_WRITE);\n  err = errno;\n  test_assert(-1 == ret && ENOMEM == err);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_none.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* map_base;\n  uint8_t* map;\n\n  map_base =\n      mmap(NULL, 5 * page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(map_base != MAP_FAILED);\n  test_assert(0 == munmap(map_base, 4 * page_size));\n\n  map = mmap(map_base + page_size, page_size, PROT_READ,\n             MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0);\n  test_assert(map == map_base + page_size);\n  test_assert(-1 == mprotect(map_base, 4 * page_size, PROT_READ | PROT_WRITE));\n  test_assert(ENOMEM == errno);\n  test_assert(0 == munmap(map_base, 4 * page_size));\n\n  map = mmap(map_base + page_size, 2 * page_size, PROT_READ,\n             MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0);\n  test_assert(map == map_base + page_size);\n  test_assert(-1 == mprotect(map_base, 2 * page_size, PROT_READ | PROT_WRITE));\n  test_assert(ENOMEM == errno);\n  map = mmap(map_base + 4 * page_size, page_size, PROT_READ,\n             MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0);\n  /* The first mapped page will be mprotect'ed PROT_READ | PROT_WRITE and then\n     it will return ENOMEM. */\n  test_assert(-1 == mprotect(map_base + 2 * page_size, 3 * page_size,\n                             PROT_READ | PROT_WRITE));\n  test_assert(ENOMEM == errno);\n  map_base[2 * page_size] = 1;\n  test_assert(0 == munmap(map_base + page_size, 2 * page_size));\n\n  test_assert(-1 == mprotect(map_base, 4 * page_size, PROT_READ | PROT_WRITE));\n  test_assert(ENOMEM == errno);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_stack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* map1 = mmap(NULL, 4 * page_size, PROT_READ | PROT_WRITE,\n                       MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  uint8_t* map1_end = map1 + 2 * page_size;\n  uint8_t* map2;\n  uint8_t* map2_end;\n\n  test_assert(map1 != (void*)-1);\n\n  atomic_printf(\"map1 = [%p, %p)\\n\", map1, map1_end);\n\n  mprotect(map1 + page_size, page_size, PROT_NONE);\n\n  map2 = mmap(map1_end, 2 * page_size, PROT_READ | PROT_WRITE,\n              MAP_STACK | MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  map2_end = map2 + page_size;\n  test_assert(map2 != (void*)-1);\n  test_assert(map2 == map1_end);\n\n  atomic_printf(\"map2 = [%p, %p)\\n\", map2, map2_end);\n\n  mprotect(map2, page_size, PROT_NONE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_step.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b mprotect')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\n\n# step through mprotect() until we reach the system call that\n# gets performed during replay\nfor i in range(0,200):\n    send_gdb('stepi')\n    expect_gdb('(rr)')\n\nok()\n"
  },
  {
    "path": "src/test/mprotect_step.run",
    "content": "source `dirname $0`/util.sh\nrecord mprotect$bitness\ndebug_gdb_only mprotect_step\n\n"
  },
  {
    "path": "src/test/mprotect_syscallbuf_overflow.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p =\n      mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  for (i = 0; i < 10000; ++i) {\n    test_assert(0 == mprotect(p, page_size, PROT_READ | PROT_WRITE));\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mprotect_syscallbuf_overflow.run",
    "content": "source `dirname $0`/util.sh\n\n# Use 4K syscallbuf size to force frequent overflows\nRECORD_ARGS=--syscall-buffer-size=4\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/mq.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n\n  mqd_t mq_a;\n  mqd_t mq_b;\n  struct mq_attr mq_attr;\n  struct mq_attr mq_attr_test;\n  char msg[] = \"Hello\";\n  char buffer[1024] = { 0 }; /* 'C' fills in the rest of the array with 0s. */\n  unsigned prio;\n  struct timespec expiry;\n\n  mq_attr.mq_flags = 0;\n  mq_attr.mq_maxmsg = 10;\n  mq_attr.mq_msgsize = 1024;\n  mq_attr.mq_curmsgs = 0;\n  char mq_name[100];\n  snprintf(mq_name, 100, \"/rr-test-queue%d\", sys_gettid());\n  mq_a = mq_open(mq_name, O_WRONLY | O_CREAT, 0777, &mq_attr);\n  test_assert(mq_a != -1);\n\n  mq_b = mq_open(mq_name, O_RDONLY);\n  test_assert(mq_b != -1);\n\n  test_assert(mq_getattr(mq_a, &mq_attr_test) == 0);\n  test_assert(mq_attr_test.mq_flags == mq_attr.mq_flags);\n  test_assert(mq_attr_test.mq_maxmsg == mq_attr.mq_maxmsg);\n  test_assert(mq_attr_test.mq_msgsize == mq_attr.mq_msgsize);\n  test_assert(mq_attr_test.mq_curmsgs == 0);\n\n  test_assert(mq_getattr(mq_b, &mq_attr_test) == 0);\n  test_assert(mq_attr_test.mq_flags == mq_attr.mq_flags);\n  test_assert(mq_attr_test.mq_maxmsg == mq_attr.mq_maxmsg);\n  test_assert(mq_attr_test.mq_msgsize == mq_attr.mq_msgsize);\n  test_assert(mq_attr_test.mq_curmsgs == 0);\n\n  test_assert(sizeof(msg) == 6);\n  test_assert(mq_send(mq_a, msg, sizeof(msg), 100) == 0);\n  test_assert(mq_getattr(mq_b, &mq_attr_test) == 0);\n  test_assert(mq_attr_test.mq_curmsgs == 1);\n\n  prio = ~0;\n  test_assert(mq_receive(mq_b, buffer, sizeof(buffer), &prio) == sizeof(msg));\n  test_assert(memcmp(msg, buffer, sizeof(msg)) == 0);\n  test_assert(prio == 100);\n\n  clock_gettime(CLOCK_REALTIME, &expiry);\n  expiry.tv_sec += 2;\n  test_assert(mq_timedreceive(mq_b, buffer, sizeof(buffer), &prio, &expiry) ==\n              -1);\n\n  mq_unlink(mq_name);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void check_mapping(int* rpage, int* wpage, ssize_t nr_ints) {\n  int i;\n  for (i = 0; i < nr_ints; ++i) {\n    test_assert(wpage[i] == rpage[i]);\n\n    wpage[i] = i;\n\n    test_assert(rpage[i] == i && wpage[i] == rpage[i]);\n  }\n  atomic_printf(\"  %p and %p point at the same resource\\n\", rpage, wpage);\n}\n\nstatic void overwrite_file(const char* path, ssize_t num_bytes) {\n  const int magic = 0x5a5a5a5a;\n  int fd = open(path, O_TRUNC | O_RDWR);\n  test_assert(fd >= 0);\n  size_t i;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    write(fd, &magic, sizeof(magic));\n  }\n  close(fd);\n}\n\nstatic const char file_name[] = \"tmpfile\";\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  int fd = open(file_name, O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* wpage;\n  int* rpage;\n  int* old_wpage;\n\n  test_assert(fd >= 0);\n\n  overwrite_file(file_name, 2 * num_bytes);\n\n  wpage = mmap(NULL, num_bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"wpage:%p rpage:%p\\n\", wpage, rpage);\n  test_assert(wpage != (void*)-1 && rpage != (void*)-1 && rpage != wpage);\n\n  check_mapping(rpage, wpage, num_bytes / sizeof(*wpage));\n\n  overwrite_file(file_name, 2 * num_bytes);\n\n  old_wpage = wpage;\n\n  /* Test invalid mremap */\n  test_assert(MAP_FAILED ==\n              mremap(old_wpage, num_bytes, 2 * num_bytes - 1, 0xFFFFFFFF));\n  test_assert(EINVAL == errno);\n\n  /* Test remapping a non-page-sized range */\n  wpage = mremap(old_wpage, num_bytes, 2 * num_bytes - 1, MREMAP_MAYMOVE);\n  atomic_printf(\"remapped wpage:%p\\n\", wpage);\n  test_assert(wpage != (void*)-1);\n\n  check_mapping(rpage, wpage, num_bytes / sizeof(*wpage));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  unlink(file_name);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_after_coalesce.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd;\n  void* map_addr;\n  long end;\n\n  /* Map a file that's (probably) not in a tmpfs */\n  fd = open(\"/bin/ls\", O_RDONLY);\n  end = lseek(fd, 0, SEEK_END);\n  test_assert(end > 0);\n  map_addr = mmap(NULL, ceil_page_size(end) + page_size, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(MAP_FAILED != map_addr);\n  test_assert(MAP_FAILED != mmap(map_addr, page_size, PROT_READ,\n                                 MAP_PRIVATE | MAP_FIXED, fd, 0));\n  map_addr = mremap(map_addr, ceil_page_size(end) + page_size,\n                    ceil_page_size(end) + page_size*2, MREMAP_MAYMOVE);\n  if (map_addr == MAP_FAILED && errno == EFAULT) {\n    // This happens in a Debian 9 kernel (4.9.0-11-amd64)\n    atomic_puts(\"Kernel didn't coalesce the mapping; skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(MAP_FAILED != map_addr);\n\n  /* Try again, shrinking this time */\n  fd = open(\"/bin/ls\", O_RDONLY);\n  end = lseek(fd, 0, SEEK_END);\n  test_assert(end > 0);\n  map_addr = mmap(NULL, ceil_page_size(end) + page_size*3, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(MAP_FAILED != map_addr);\n  test_assert(MAP_FAILED != mmap(map_addr, page_size, PROT_READ,\n                                 MAP_PRIVATE | MAP_FIXED, fd, 0));\n  map_addr = mremap(map_addr, ceil_page_size(end) + page_size*2,\n                    ceil_page_size(end) + page_size, 0);\n  test_assert(MAP_FAILED != map_addr);\n\n  /* Try again, this time starting in the middle of a mapping */\n  fd = open(\"/bin/ls\", O_RDONLY);\n  end = lseek(fd, 0, SEEK_END);\n  test_assert(end > 0);\n  map_addr = mmap(NULL, ceil_page_size(end) + page_size*3, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(MAP_FAILED != map_addr);\n  test_assert(MAP_FAILED != mmap(map_addr, page_size*3, PROT_READ,\n                                 MAP_PRIVATE | MAP_FIXED, fd, 0));\n  map_addr = mremap(map_addr + page_size, page_size*3, page_size, 0);\n  test_assert(MAP_FAILED != map_addr);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_dontunmap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,\n                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  memset(p, 0xaa, 2 * page_size);\n  void* p2 = mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,\n                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  memset(p2, 0xbb, 2 * page_size);\n  void* p3 = mremap(p, 2 * page_size, 2 * page_size, MREMAP_MAYMOVE | MREMAP_DONTUNMAP, 0);\n  if (p3 == MAP_FAILED && errno == EINVAL) {\n    atomic_puts(\"MREMAP_DONTUNMAP not present on this kernel, quitting\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(((unsigned char*)p3)[page_size] == 0xaa);\n  test_assert(((unsigned char*)p)[page_size] == 0);\n  void* p4 = mremap(p3, 2 * page_size, 2 * page_size, MREMAP_FIXED | MREMAP_MAYMOVE | MREMAP_DONTUNMAP, p2);\n  test_assert(p4 == p2);\n  test_assert(((unsigned char*)p4)[page_size] == 0xaa);\n  test_assert(((unsigned char*)p3)[page_size] == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_grow.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"temp\", O_RDWR | O_CREAT, 0700);\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char buf[page_size * 2];\n  char* p;\n\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(\"temp\"));\n\n  memset(buf, 1, sizeof(buf));\n  test_assert((ssize_t)sizeof(buf) == write(fd, buf, sizeof(buf)));\n\n  p = (char*)mmap(NULL, page_size, PROT_READ, MAP_PRIVATE, fd, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[0] == 1);\n\n  p = (char*)mremap(p, page_size, page_size * 2, MREMAP_MAYMOVE);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[0] == 1);\n  test_assert(p[page_size] == 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_grow_shared.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(__attribute((unused)) int argc, char* argv[]) {\n  int fd = open(argv[0], O_RDONLY);\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char buf[page_size * 2];\n  char* p;\n\n  test_assert(fd >= 0);\n  test_assert((ssize_t)sizeof(buf) == read(fd, buf, sizeof(buf)));\n\n  p = (char*)mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[0] == buf[0]);\n\n  p = (char*)mremap(p, page_size, page_size * 2, MREMAP_MAYMOVE);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[0] == buf[0]);\n  test_assert(p[page_size] == buf[page_size]);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_non_page_size.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void check_mapping(int* rpage, int* wpage, ssize_t nr_ints) {\n  int i;\n  for (i = 0; i < nr_ints; ++i) {\n    test_assert(wpage[i] == rpage[i]);\n\n    wpage[i] = i;\n\n    test_assert(rpage[i] == i && wpage[i] == rpage[i]);\n  }\n  atomic_printf(\"  %p and %p point at the same resource\\n\", rpage, wpage);\n}\n\nstatic void overwrite_file(const char* path, ssize_t num_bytes) {\n  const int magic = 0x5a5a5a5a;\n  int fd = open(path, O_TRUNC | O_RDWR);\n  size_t i;\n  for (i = 0; i < num_bytes / sizeof(magic); ++i) {\n    write(fd, &magic, sizeof(magic));\n  }\n  close(fd);\n}\n\nint main(void) {\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  static const char file_name[] = \"temp\";\n  int fd = open(file_name, O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* wpage;\n  int* rpage;\n  int* old_wpage;\n\n  test_assert(fd >= 0);\n\n  overwrite_file(file_name, num_bytes - 4);\n\n  unlink(file_name);\n\n  wpage = mmap(NULL, num_bytes - 8, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  rpage = mmap(NULL, num_bytes, PROT_READ, MAP_SHARED, fd, 0);\n  atomic_printf(\"wpage:%p\\n\", wpage);\n  test_assert(wpage != (void*)-1 && rpage != (void*)-1 && rpage != wpage);\n\n  old_wpage = wpage;\n\n  /* Test a remapping that changes the number of pages */\n  wpage = mremap(old_wpage, num_bytes - 8, num_bytes + 8, MREMAP_MAYMOVE);\n  atomic_printf(\"remapped wpage:%p\\n\", wpage);\n  test_assert(wpage != (void*)-1);\n\n  check_mapping(rpage, wpage, (num_bytes - 4) / sizeof(*wpage));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_overwrite.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"file\", O_RDWR | O_CREAT | O_TRUNC, 0700);\n  void* block;\n  void* mapped_file;\n  void* dest;\n\n  test_assert(fd >= 0);\n  unlink(\"file\");\n  block = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n               MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(block != MAP_FAILED);\n  mapped_file = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                     MAP_SHARED, fd, 0);\n  test_assert(mapped_file != MAP_FAILED);\n  dest = mremap(mapped_file, page_size, page_size, MREMAP_FIXED | MREMAP_MAYMOVE,\n                block);\n  test_assert(dest == block);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_private_grow_under_map.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"file\", O_RDWR | O_CREAT | O_TRUNC, 0700);\n  char* p;\n  test_assert(fd >= 0);\n  unlink(\"file\");\n\n  p = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  p = (char*)mremap(p, page_size, page_size*2, MREMAP_MAYMOVE);\n  ftruncate(fd, page_size*2);\n  p[page_size] = 'x';\n\n  p = (char*)mmap(NULL, page_size*2, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  p = (char*)mremap(p, page_size*2, page_size*3, MREMAP_MAYMOVE);\n  ftruncate(fd, page_size*3);\n  p[page_size*2] = 'y';\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mremap_shrink.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p = mmap(NULL, 3 * page_size, PROT_READ | PROT_WRITE,\n                 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  void* p2 = mremap(p, 3 * page_size, 2 * page_size, 0);\n  void* p3 = mremap(p, 2 * page_size, page_size, MREMAP_MAYMOVE);\n\n  atomic_printf(\"%p %p %p\\n\", p, p2, p3);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/msg.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_MSGS 3\n\nstruct msg {\n  long mtype;\n  long msg;\n};\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic int msqid;\n\nstatic void child(void) {\n  const char* id = \"c\";\n  int i;\n  int ret;\n  int err;\n  struct msg msg;\n  memset(&msg, 0, sizeof(msg));\n\n  atomic_printf(\"%s: inherited msg id %d\\n\", id, msqid);\n  test_assert(msqid >= 0);\n\n  for (i = 1; i < NUM_MSGS; ++i) {\n    atomic_printf(\"%s: msgrcv() ...\\n\", id);\n    ret = msgrcv(msqid, &msg, sizeof(msg.msg), i, 0);\n    err = errno;\n    atomic_printf(\"%s: ... returned %d (%s/%d): (%ld, %ld)\\n\", id, ret,\n                  strerror(err), err, msg.mtype, msg.msg);\n    test_assert(sizeof(msg.msg) == ret);\n    test_assert(msg.mtype + 1 == msg.msg);\n  }\n\n  atomic_printf(\"%s: awaiting Q destruction ...\\n\", id);\n  ret = msgrcv(msqid, &msg, sizeof(msg.msg), i, 0);\n  err = errno;\n  atomic_printf(\"%s: ... returned %d (%s/%d)\\n\", id, ret, strerror(err), err);\n  test_assert(-1 == ret && EIDRM == err);\n  atomic_printf(\"%s: ... done\\n\", id);\n\n  exit(0);\n}\n\nint main(void) {\n  const char* id = \"P\";\n  int ret;\n  int err;\n  pid_t c;\n  struct msqid_ds buf;\n  struct msginfo info;\n  int i;\n  int status;\n  struct msg msg;\n  memset(&msg, 0, sizeof(msg));\n\n  breakpoint();\n  /* NB: no syscalls between here and |msgget()| below. */\n\n  /* NB: surprisingly, this test will leak Q's on failure, even\n   * though we're using IPC_PRIVATE.  There doesn't appear to be\n   * a way to avoid that. */\n  msqid = msgget(IPC_PRIVATE, 0600);\n  atomic_printf(\"%s: got id %d for key %d\\n\", id, msqid, IPC_PRIVATE);\n  test_assert(msqid >= 0);\n\n  memset(&buf, 0x5a, sizeof(buf));\n  test_assert(0 == msgctl(msqid, IPC_STAT, &buf));\n  atomic_printf(\"%s: Q stats in %p:\\n\"\n                \"    { perm:%#o qnum:%ld lspid:%d lrpid:%d }\\n\",\n                id, &buf, buf.msg_perm.mode, buf.msg_qnum, buf.msg_lspid,\n                buf.msg_lrpid);\n\n  memset(&info, 0x5a, sizeof(info));\n  ret = msgctl(msqid, IPC_INFO, (struct msqid_ds*)&info);\n  err = errno;\n  atomic_printf(\"%s: IPC_INFO returned %d (%s/%d):\\n\"\n                \"    { max:%d mnb:%d mni:%d }\\n\",\n                id, ret, strerror(err), err, info.msgmax, info.msgmnb,\n                info.msgmni);\n  test_assert(ret >= 0);\n\n  memset(&info, 0x5a, sizeof(info));\n  ret = msgctl(msqid, MSG_INFO, (struct msqid_ds*)&info);\n  err = errno;\n  atomic_printf(\"%s: MSG_INFO returned %d (%s/%d):\\n\"\n                \"    { pool:%d map:%d tql:%d }\\n\",\n                id, ret, strerror(err), err, info.msgpool, info.msgmap,\n                info.msgtql);\n  test_assert(ret >= 0);\n\n  if ((0 == (c = fork()))) {\n    child();\n    test_assert(\"Not reached\" && 0);\n  }\n\n  /* Make the child wait on msgrcv() a few times. */\n  for (i = 1; i < NUM_MSGS; ++i) {\n    atomic_printf(\"%s: sleeping ...\\n\", id);\n    usleep(500000);\n\n    msg.mtype = i;\n    msg.msg = msg.mtype + 1;\n    atomic_printf(\"%s: sending msg (%ld, %ld) ...\\n\", id, msg.mtype, msg.msg);\n    ret = msgsnd(msqid, &msg, sizeof(msg.msg), 0);\n    err = errno;\n    atomic_printf(\"%s: ... returned %d (%s/%d)\\n\", id, ret, strerror(err), err);\n    test_assert(0 == ret);\n    atomic_printf(\"%s:   ... done\\n\", id);\n  }\n\n  memset(&buf, 0x5a, sizeof(buf));\n  test_assert(0 == msgctl(msqid, IPC_STAT, &buf));\n  atomic_printf(\"%s: Q stats: { perm:%#o qnum:%ld lspid:%d lrpid:%d }\\n\", id,\n                buf.msg_perm.mode, buf.msg_qnum, buf.msg_lspid, buf.msg_lrpid);\n\n  /* Make the child wait on msgrcv() returning EIDRM. */\n  atomic_printf(\"%s: sleeping ...\\n\", id);\n  usleep(500000);\n  atomic_printf(\"%s: destroying msg Q ...\\n\", id);\n  test_assert(0 == msgctl(msqid, IPC_RMID, NULL));\n  atomic_printf(\"%s:   ... done\", id);\n\n  atomic_printf(\"%s: joining %d ...\\n\", id, c);\n  ret = waitpid(c, &status, 0);\n  atomic_printf(\"%s: ... joined %d with status %#x\\n\", id, ret, status);\n  test_assert(c == ret && WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/msg_trunc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int sockets[2];\n  char out[10];\n\n  test_assert(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == 0);\n  test_assert(send(sockets[0], \"0123456789\", 10, 0) == 10);\n  memset(out, 77, sizeof(out));\n  test_assert(recv(sockets[1], out, 1, MSG_TRUNC) == 10);\n  test_assert(out[1] == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/msync.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define FILENAME \"foo.txt\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(FILENAME, O_CREAT | O_EXCL | O_RDWR, 0600);\n  int* wpage;\n  size_t i;\n  int* rpage;\n\n  unlink(FILENAME);\n\n  test_assert(fd >= 0);\n  ftruncate(fd, page_size);\n\n  wpage = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(wpage != (void*)-1);\n  for (i = 0; i < page_size / sizeof(int); ++i) {\n    wpage[i] = i;\n  }\n\n  rpage = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(rpage != (void*)-1 && wpage != rpage);\n\n  msync(wpage, page_size, MS_INVALIDATE);\n\n  for (i = 0; i < page_size / sizeof(int); ++i) {\n    test_assert(rpage[i] == (ssize_t)i);\n    atomic_printf(\"%d,\", rpage[i]);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mtio.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct mtget out;\n  int ret = ioctl(STDOUT_FILENO, MTIOCGET, &out);\n  test_assert(ret == -1 && ENOTTY == errno);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/multiple_pending_signals.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* In this test, usually SIGUSR1 will be delivered,\n   and then as soon as we enter the SIGUSR1 handler,\n   SIGUSR2 will be delivered and run nested inside the\n   SIGUSR1 handler.\n   This doesn't usually exercise multiple pending signals within\n   rr itself, because the kernel doesn't notify rr of the second\n   signal until rr has injected the first signal.\n*/\n\nstatic int to_child[2];\nstatic int from_child[2];\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  char ch;\n  sigset_t s;\n\n  sigemptyset(&s);\n  sigaddset(&s, SIGUSR1);\n  sigaddset(&s, SIGUSR2);\n  sigprocmask(SIG_SETMASK, &s, NULL);\n\n  /* yield to the main thread to minimize the chance of\n     a context switch during the following two syscalls */\n  test_assert(1 == read(to_child[0], &ch, 1));\n  test_assert('J' == ch);\n\n  kill(getpid(), SIGUSR1);\n  kill(getpid(), SIGUSR2);\n\n  test_assert(1 == write(from_child[1], \"K\", 1));\n  return NULL;\n}\n\nstatic void handler(int sig, __attribute__((unused)) siginfo_t* si,\n                    __attribute__((unused)) void* p) {\n  atomic_printf(\"Handling signal %s\\n\", sig == SIGUSR1 ? \"SIGUSR1\" : \"SIGUSR2\");\n}\n\nint main(void) {\n  pthread_t t;\n  char ch;\n  struct sigaction sa;\n\n  test_assert(0 == pipe(to_child));\n  test_assert(0 == pipe(from_child));\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO | SA_RESTART;\n  sigaction(SIGUSR1, &sa, NULL);\n  sigaction(SIGUSR2, &sa, NULL);\n\n  pthread_create(&t, NULL, run_thread, NULL);\n\n  test_assert(1 == write(to_child[1], \"J\", 1));\n\n  test_assert(1 == read(from_child[0], &ch, 1));\n  test_assert('K' == ch);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/multiple_pending_signals_sequential.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* In this test, usually SIGUSR1 will be delivered,\n   the SIGUSR1 handler will run, and when the handler\n   returns, SIGUSR2 will be delivered and its handler will run.\n   This doesn't usually exercise multiple pending signals within\n   rr itself, because the kernel doesn't notify rr of the second\n   signal until rr has injected the first signal.\n*/\n\nstatic int to_child[2];\nstatic int from_child[2];\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  char ch;\n  sigset_t s;\n\n  sigemptyset(&s);\n  sigaddset(&s, SIGUSR1);\n  sigaddset(&s, SIGUSR2);\n  sigprocmask(SIG_SETMASK, &s, NULL);\n\n  /* yield to the main thread to minimize the chance of\n     a context switch during the following two syscalls */\n  test_assert(1 == read(to_child[0], &ch, 1));\n  test_assert('J' == ch);\n\n  kill(getpid(), SIGUSR1);\n  kill(getpid(), SIGUSR2);\n\n  return NULL;\n}\n\nstatic int handler_count;\n\nstatic void handler(int sig, __attribute__((unused)) siginfo_t* si,\n                    __attribute__((unused)) void* p) {\n  atomic_printf(\"Handling signal %s\\n\", sig == SIGUSR1 ? \"SIGUSR1\" : \"SIGUSR2\");\n  ++handler_count;\n  if (handler_count == 2) {\n    test_assert(1 == write(from_child[1], \"K\", 1));\n  }\n}\n\nint main(void) {\n  pthread_t t;\n  char ch;\n  struct sigaction sa;\n\n  test_assert(0 == pipe(to_child));\n  test_assert(0 == pipe(from_child));\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sigaddset(&sa.sa_mask, SIGUSR2);\n  sa.sa_flags = SA_SIGINFO | SA_RESTART;\n  sigaction(SIGUSR1, &sa, NULL);\n\n  sigemptyset(&sa.sa_mask);\n  sigaddset(&sa.sa_mask, SIGUSR1);\n  sigaction(SIGUSR2, &sa, NULL);\n\n  pthread_create(&t, NULL, run_thread, NULL);\n\n  test_assert(1 == write(to_child[1], \"J\", 1));\n\n  test_assert(1 == read(from_child[0], &ch, 1));\n  test_assert('K' == ch);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/munmap_discontinuous.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_FILE \"foo.txt\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(TEST_FILE, O_CREAT | O_EXCL | O_RDWR, 0600);\n  uint8_t* pages;\n\n  test_assert(fd >= 0);\n  test_assert(0 == ftruncate(fd, 8 * page_size));\n\n  unlink(TEST_FILE);\n\n  pages = mmap(NULL, 8 * page_size, PROT_WRITE, MAP_PRIVATE, fd, 0);\n  test_assert(pages != (void*)-1);\n\n  /* Unmap first page. */\n  munmap(pages, page_size);\n  /* Unmap third page. */\n  munmap(pages + 2 * page_size, page_size);\n  /* Unmap fifth page. */\n  munmap(pages + 4 * page_size, page_size);\n\n  /* Unmap first 6 page locations, leave last 2. */\n  munmap(pages, 6 * page_size);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/munmap_segv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char* p = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  signal(SIGSEGV, sighandler);\n\n  *p = 'a';\n\n  test_assert(0 == munmap(p, page_size));\n  *p = 'b';\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mutex_pi_stress.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_THREADS 10\n#define NUM_TRIALS 1000\n\nstatic pthread_mutex_t lock;\n\nstatic void* thread(void* idp) {\n  int tid = (intptr_t)idp;\n  int i;\n\n  atomic_printf(\"thread %d starting ...\\n\", tid);\n  for (i = 0; i < NUM_TRIALS; ++i) {\n    pthread_mutex_lock(&lock);\n    sched_yield();\n    pthread_mutex_unlock(&lock);\n  }\n  atomic_printf(\"  ... thread %d done.\\n\", tid);\n  return NULL;\n}\n\nint main(void) {\n  pthread_mutexattr_t attr;\n  pthread_t threads[NUM_THREADS];\n  int i, err;\n\n  pthread_mutexattr_init(&attr);\n  test_assert(0 == pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT));\n  if ((err = pthread_mutex_init(&lock, &attr))) {\n    test_assert(ENOTSUP == err);\n    test_assert(0 == pthread_mutex_init(&lock, NULL));\n  }\n\n  for (i = 0; i < NUM_THREADS; ++i) {\n    test_assert(0 ==\n                pthread_create(&threads[i], NULL, thread, (void*)(intptr_t)i));\n  }\n  for (i = 0; i < NUM_THREADS; ++i) {\n    test_assert(0 == pthread_join(threads[i], NULL));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/mutex_pi_stress.run",
    "content": "source `dirname $0`/util.sh\n\n# Switch threads very eagerly on recorded events.\nRECORD_ARGS=\"-s\"\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/nanosleep.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Keep this roughly in sync with 'clock_nanosleep' */\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  sigset_t sigs;\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGINT);\n  pthread_sigmask(SIG_BLOCK, &sigs, NULL);\n\n  while (1) {\n    sleep(1);\n    test_assert(0 == kill(getpid(), SIGINT));\n  }\n  return NULL;\n}\n\nstatic void handler(__attribute__((unused)) int sig) {}\n\nint main(void) {\n  struct timespec sleep = { 0, 1000000 };\n  struct timespec* remain;\n  pthread_t thread;\n\n  test_assert(0 == nanosleep(&sleep, NULL));\n\n  ALLOCATE_GUARD(remain, 'x');\n  remain->tv_sec = 9999;\n  remain->tv_nsec = 9998;\n  test_assert(0 == nanosleep(&sleep, remain));\n  VERIFY_GUARD(remain);\n  test_assert(remain->tv_sec == 9999 && remain->tv_nsec == 9998);\n\n  test_assert(0 == signal(SIGINT, handler));\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  sleep.tv_sec = 1000000;\n  test_assert(-1 == nanosleep(&sleep, remain));\n  test_assert(errno == EINTR);\n  VERIFY_GUARD(remain);\n  test_assert(remain->tv_sec <= sleep.tv_sec);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/nested_detach.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS=\"--env=_RR_TRACE_DIR=$workdir/inner\"\nsave_exe simple$bitness\nexport RR_TEST_DELAY_SEIZE=1\njust_record $(which rr) \"record --suppress-environment-warnings --nested=detach $PWD/simple$bitness-$nonce\"\n# Replay outer\nreplay\ncheck_record\n# Replay inner\ncd inner\nworkdir_orig=$workdir\nworkdir=$PWD\nwait_for_complete\nreplay\ncheck_replay_token EXIT-SUCCESS\nworkdir=$workdir_orig\n"
  },
  {
    "path": "src/test/nested_detach_kill.run",
    "content": "source `dirname $0`/util.sh\n\nNEST_EXE=nested_detach_wait\nSLEEP_EXE=term_trace_syscall\nSYNC_TOKEN=sleeping\nWAIT_SECS=1\n\nmkdir $workdir/inner\nRECORD_ARGS=\"--env=_RR_TRACE_DIR=$workdir/inner\"\nsave_exe \"$NEST_EXE\"\nsave_exe \"$SLEEP_EXE\"\ntouch record.out\njust_record $NEST_EXE-$nonce \"$(which rr) record --nested=detach $PWD/$SLEEP_EXE-$nonce\" &\nSUB_ID=$!\n\necho \"Waiting for token '$SYNC_TOKEN' from tracee ...\"\nuntil grep -q $SYNC_TOKEN record.out; do\n    sleep 0\n    if ! kill -0 \"$SUB_ID\" >/dev/null 2>&1; then failed \"subshell died, no need to longer wait for '$SYNC_TOKEN'\"; exit; fi\ndone\n\nrrpid=$(parent_pid_of $(pidof $NEST_EXE-$nonce))\necho \"  done.  Delivering SIGTERM to $rrpid ...\"\nkill -TERM $rrpid\n\necho \"  done.\"\n\n# Wait for 'record' to actually terminate.\nwait $SUB_ID\nEXIT_CODE=$?\nif [[ $EXIT_CODE != 143 ]]; then\n  failed \"Unexpected exit $EXIT_CODE\"\nfi\n\n# Replay outer\nreplay\n# Replay inner\ncd $workdir/inner\nworkdir_orig=$workdir\nworkdir=$PWD\nwait_for_complete\nreplay\ncheck_replay_token $SYNC_TOKEN\nworkdir=$workdir_orig\n"
  },
  {
    "path": "src/test/nested_detach_kill_stuck.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstruct timespec ts = { 10000, 0 };\n\nstatic void handle_sigterm(__attribute__((unused)) int sig,\n                           __attribute__((unused)) siginfo_t* info,\n                           __attribute__((unused)) void* mcontext) {\n  /* This simulates a process that takes a long time to exit on SIGTERM.\n     Maybe it's a database trying to flush or a process that's trying to\n     print backtraces or something. */\n  nanosleep(&ts, NULL);\n  exit(1);\n}\n\nint main(void) {\n  struct sigaction sa;\n\n  sa.sa_flags = SA_SIGINFO;\n  sa.sa_sigaction = handle_sigterm;\n  sigaction(SIGTERM, &sa, NULL);\n\n  atomic_puts(\"sleeping\");\n  nanosleep(&ts, NULL);\n\n  return 1;\n}\n"
  },
  {
    "path": "src/test/nested_detach_kill_stuck.run",
    "content": "source `dirname $0`/util.sh\n\nNEST_EXE=nested_detach_wait\nSLEEP_EXE=nested_detach_kill_stuck\nSYNC_TOKEN=sleeping\nWAIT_SECS=1\n\nmkdir $workdir/inner\nRECORD_ARGS=\"--wait --env=_RR_TRACE_DIR=$workdir/inner\"\nsave_exe \"$NEST_EXE\"\nsave_exe \"$SLEEP_EXE\"\ntouch record.out\njust_record $NEST_EXE-$nonce \"$(which rr) record --nested=detach $PWD/$SLEEP_EXE-$nonce\" &\nSUB_ID=$!\n\necho \"Waiting for token '$SYNC_TOKEN' from tracee ...\"\nuntil grep -q $SYNC_TOKEN record.out; do\n    sleep 0\n    if ! kill -0 \"$SUB_ID\" >/dev/null 2>&1; then failed \"subshell died, no need to longer wait for '$SYNC_TOKEN'\"; exit; fi\ndone\n\nrrpid=$(parent_pid_of $(pidof $NEST_EXE-$nonce))\necho \"  done.  Delivering SIGTERM to $rrpid ...\"\nkill -TERM $rrpid\n\necho \"  done.\"\n\n# Wait for 'record' to actually terminate.\nwait\n\n# Replay outer\nreplay\n# Replay inner\ncd $workdir/inner\nworkdir_orig=$workdir\nworkdir=$PWD\nwait_for_complete\nreplay\ncheck_replay_token $SYNC_TOKEN\nworkdir=$workdir_orig\n"
  },
  {
    "path": "src/test/nested_detach_stop.run",
    "content": "source `dirname $0`/util.sh\n\nNEST_EXE=nested_detach_wait\nSLEEP_EXE=term_trace_syscall\nSYNC_TOKEN=sleeping\nWAIT_SECS=1\n\nmkdir $workdir/inner\nRECORD_ARGS=\"--env=_RR_TRACE_DIR=$workdir/inner\"\nsave_exe \"$NEST_EXE\"\nsave_exe \"$SLEEP_EXE\"\ntouch record.out\njust_record $NEST_EXE-$nonce \"$(which rr) record --nested=detach $PWD/$SLEEP_EXE-$nonce\" &\nSUB_ID=$!\n\necho \"Waiting for token '$SYNC_TOKEN' from tracee ...\"\nuntil grep -q $SYNC_TOKEN record.out; do\n    sleep 0\n    if ! kill -0 \"$SUB_ID\" >/dev/null 2>&1; then failed \"subshell died, no need to longer wait for '$SYNC_TOKEN'\"; exit; fi\ndone\n\nsleep_pid=$(pidof $SLEEP_EXE-$nonce)\nnested_rr_pid=$(parent_pid_of $sleep_pid)\necho \"  done.  Delivering SIGSTOP to nested rr $nested_rr_pid ...\"\nkill -STOP $nested_rr_pid\n# Sleep a bit because if we issue the CONT immediately rr doesn't even notice\nsleep 1\necho \"  done.  Delivering SIGCONT to nested rr $nested_rr_pid ...\"\nkill -CONT $nested_rr_pid\n\necho \"  done.  Delivering SIGTERM to sleeping $sleep_pid ...\"\nkill -TERM $sleep_pid\n\n# Wait for 'record' to actually terminate.\nwait $SUB_ID || failed \"Recording failed: $?\"\n\n# Replay outer\nreplay\n# Replay inner\ncd $workdir/inner\nworkdir_orig=$workdir\nworkdir=$PWD\nwait_for_complete\nreplay\ncheck_replay_token $SYNC_TOKEN\nworkdir=$workdir_orig\n"
  },
  {
    "path": "src/test/nested_detach_wait.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char *argv[]) {\n  pid_t child = fork();\n  if (argc > 1 && strcmp(argv[1], \"--inner\") == 0) {\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n  }\n  test_assert(argc >= 2);\n\n  if (!child) {\n    execve(argv[1], &argv[1], environ); // Should not return\n    test_assert(0);\n  }\n\n  while (1) {\n    int status;\n    wait(&status);\n    if (WIFSTOPPED(status) &&\n        (WSTOPSIG(status) == SIGSTOP || WSTOPSIG(status) == SIGCONT)) {\n      continue;\n    }\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n    atomic_puts(\"EXIT-WAITED\");\n    return 0;\n  }\n}\n"
  },
  {
    "path": "src/test/nested_detach_wait.run",
    "content": "source `dirname $0`/util.sh\n\nmkdir $workdir/inner\nRECORD_ARGS=\"--env=_RR_TRACE_DIR=$workdir/inner\"\nrecord $TESTNAME \"$(which rr) record --suppress-environment-warnings --nested=detach $PWD/$TESTNAME-$nonce --inner\"\n# Replay outer\nreplay\ncheck_record EXIT-WAITED\n# Replay inner\ncd $workdir/inner\nworkdir_orig=$workdir\nworkdir=$PWD\nreplay\ncheck_replay_token EXIT-SUCCESS\nworkdir=$workdir_orig\n"
  },
  {
    "path": "src/test/nested_release.run",
    "content": "source `dirname $0`/util.sh\njust_record $(which rr) \"record --nested=release hello NOT-IN-REPLAY\"\n# Replay outer\nreplay\nif [[ $(grep -l NOT-IN-REPLAY replay.out) ]]; then\n    failed \": token NOT-IN-REPLAY in replay.out:\"\n        echo \"--------------------------------------------------\"\n        cat replay.out\n        echo \"--------------------------------------------------\"\nfi\ncheck_record\n\n"
  },
  {
    "path": "src/test/nested_release_exit_code.run",
    "content": "source `dirname $0`/util.sh\njust_record $RR_EXE \"record --nested=release false\" && failed \"error not propagated\"\npassed\n"
  },
  {
    "path": "src/test/nested_release_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  kill(getpid(), SIGABRT);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/nested_release_signal.run",
    "content": "source `dirname $0`/util.sh\njust_record $RR_EXE \"record --nested=detach nested_release_signal$bitness\" && failed \"error not propagated\"\npassed\n"
  },
  {
    "path": "src/test/netfilter.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <linux/netfilter_ipv4/ip_tables.h>\n\n#include \"nsutils.h\"\n\nint main(void) {\n  if (-1 == try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int sock_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);\n  test_assert(sock_fd >= 0);\n\n  struct ipt_getinfo* info;\n  ALLOCATE_GUARD(info, 'a');\n  strcpy(info->name, \"nat\");\n  uint32_t getinfo_size = sizeof(*info);\n\n  errno = 0;\n  int ret = getsockopt(sock_fd, SOL_IP, IPT_SO_GET_INFO, info, &getinfo_size);\n  if (ret < 0) {\n    switch (errno) {\n    case ENOPROTOOPT:\n      atomic_puts(\"IPT_SO_GET_INFO not available\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      break;\n    case ENOENT:\n      atomic_puts(\"'nat' table missing\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      break;\n    default:\n      test_assert(errno == 0);\n    }\n    return 0;\n  }\n  test_assert(getinfo_size == sizeof(*info));\n  VERIFY_GUARD(info);\n\n  atomic_printf(\"%d existing entries in nat table\\n\", info->num_entries);\n\n  uint32_t getentries_size = sizeof(struct ipt_get_entries) + info->size;\n  struct ipt_get_entries* entries = allocate_guard(getentries_size, 'b');\n  strcpy(entries->name, \"nat\");\n  entries->size = info->size;\n  ret = getsockopt(sock_fd, SOL_IP, IPT_SO_GET_ENTRIES, entries,\n                   &getentries_size);\n  if (ret < 0 && errno == EINVAL && sizeof(void*) == 4) {\n    atomic_puts(\"Kernel may have been built without CONFIG_NETFILTER_XTABLES_COMPAT\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  VERIFY_GUARD(entries);\n\n  size_t final_size = sizeof(struct ipt_replace) + info->size;\n  struct ipt_replace* final = allocate_guard(final_size, 'c');\n\n  strcpy(final->name, \"nat\");\n  final->valid_hooks = info->valid_hooks;\n  final->num_entries = info->num_entries;\n  final->size = info->size;\n  memcpy(final->hook_entry, info->hook_entry, sizeof(final->hook_entry));\n  memcpy(final->underflow, info->underflow, sizeof(final->underflow));\n  final->num_counters = info->num_entries;\n  // Allocate space to receive counters\n  // We will check for at least some of these bytes being replaced by the kernel\n  struct xt_counters* counters =\n      allocate_guard(sizeof(struct xt_counters) * info->num_entries, 0xff);\n  final->counters = counters;\n\n  char* src_ptr = (char*)entries->entrytable;\n  char* dest_ptr = (char*)final->entries;\n  for (size_t i = 0; i < info->num_entries; ++i) {\n    struct ipt_entry* cur_entry = (struct ipt_entry*)src_ptr;\n    memcpy(dest_ptr, src_ptr, cur_entry->next_offset);\n    dest_ptr += cur_entry->next_offset;\n    src_ptr += cur_entry->next_offset;\n  }\n  test_assert(dest_ptr == (char*)final + final_size);\n\n  // Finally pass this off to the kernel\n  ret = setsockopt(sock_fd, SOL_IP, IPT_SO_SET_REPLACE, final, final_size);\n  test_assert(ret == 0);\n  VERIFY_GUARD(final);\n  VERIFY_GUARD(final->counters);\n\n  // Verify that the counters array was overwritten. Since we don't know the\n  // exact value here, just make sure some bytes were written. After every byte\n  // comparison we also call getuid if they were not the same, which should\n  // catch any replay divergence, just from tick mismatch.\n  int any_changed = 0;\n  for (size_t i = 0; i < sizeof(struct xt_counters) * info->num_entries; ++i) {\n    if (((uint8_t*)counters)[i] != 0xff) {\n      any_changed = 1;\n      (void)getuid();\n    }\n  }\n\n  test_assert(any_changed);\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/netfilter_ipv6.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <linux/netfilter_ipv6/ip6_tables.h>\n\n#include \"nsutils.h\"\n\nint main(void) {\n  if (-1 == try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int sock_fd = socket(AF_INET6, SOCK_RAW, IPPROTO_RAW);\n  if (sock_fd < 0 && errno == EAFNOSUPPORT) {\n    atomic_puts(\"IPV6 not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(sock_fd >= 0);\n\n  struct ip6t_getinfo* info;\n  ALLOCATE_GUARD(info, 'a');\n  strcpy(info->name, \"nat\");\n  uint32_t getinfo_size = sizeof(*info);\n\n  errno = 0;\n  int ret = getsockopt(sock_fd, SOL_IPV6, IP6T_SO_GET_INFO, info, &getinfo_size);\n  if (ret < 0) {\n    switch (errno) {\n    case ENOPROTOOPT:\n      atomic_puts(\"IPV6T_SO_GET_INFO not available\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      break;\n    case ENOENT:\n      atomic_puts(\"'nat' table missing\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      break;\n    default:\n      test_assert(errno == 0);\n    }\n    return 0;\n  }\n  test_assert(getinfo_size == sizeof(*info));\n  VERIFY_GUARD(info);\n\n  atomic_printf(\"%d existing entries in nat table\\n\", info->num_entries);\n\n  uint32_t getentries_size = sizeof(struct ip6t_get_entries) + info->size;\n  struct ip6t_get_entries* entries = allocate_guard(getentries_size, 'b');\n  strcpy(entries->name, \"nat\");\n  entries->size = info->size;\n  ret = getsockopt(sock_fd, SOL_IPV6, IP6T_SO_GET_ENTRIES, entries,\n                   &getentries_size);\n  if (ret < 0 && errno == EINVAL && sizeof(void*) == 4) {\n    atomic_puts(\"Kernel may have been built without CONFIG_NETFILTER_XTABLES_COMPAT\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  VERIFY_GUARD(entries);\n\n  size_t final_size = sizeof(struct ip6t_replace) + info->size;\n  struct ip6t_replace* final = allocate_guard(final_size, 'c');\n\n  strcpy(final->name, \"nat\");\n  final->valid_hooks = info->valid_hooks;\n  final->num_entries = info->num_entries;\n  final->size = info->size;\n  memcpy(final->hook_entry, info->hook_entry, sizeof(final->hook_entry));\n  memcpy(final->underflow, info->underflow, sizeof(final->underflow));\n  final->num_counters = info->num_entries;\n  // Allocate space to receive counters\n  // We will check for at least some of these bytes being replaced by the kernel\n  struct xt_counters* counters =\n      allocate_guard(sizeof(struct xt_counters) * info->num_entries, 0xff);\n  final->counters = counters;\n\n  char* src_ptr = (char*)entries->entrytable;\n  char* dest_ptr = (char*)final->entries;\n  for (size_t i = 0; i < info->num_entries; ++i) {\n    struct ip6t_entry* cur_entry = (struct ip6t_entry*)src_ptr;\n    memcpy(dest_ptr, src_ptr, cur_entry->next_offset);\n    dest_ptr += cur_entry->next_offset;\n    src_ptr += cur_entry->next_offset;\n  }\n  test_assert(dest_ptr == (char*)final + final_size);\n\n  // Finally pass this off to the kernel\n  ret = setsockopt(sock_fd, SOL_IPV6, IP6T_SO_SET_REPLACE, final, final_size);\n  test_assert(ret == 0);\n  VERIFY_GUARD(final);\n  VERIFY_GUARD(final->counters);\n\n  // Verify that the counters array was overwritten. Since we don't know the\n  // exact value here, just make sure some bytes were written. After every byte\n  // comparison we also call getuid if they were not the same, which should\n  // catch any replay divergence, just from tick mismatch.\n  int any_changed = 0;\n  for (size_t i = 0; i < sizeof(struct xt_counters) * info->num_entries; ++i) {\n    if (((uint8_t*)counters)[i] != 0xff) {\n      any_changed = 1;\n      (void)getuid();\n    }\n  }\n\n  test_assert(any_changed);\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/netlink_mmap_disable.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);\n  int ret;\n  unsigned int block_size = 16 * getpagesize();\n  struct nl_mmap_req req = {\n    .nm_block_size = block_size,\n    .nm_block_nr = 64,\n    .nm_frame_size = 16384,\n    .nm_frame_nr = 64 * block_size / 16384,\n  };\n\n  if (sock < 0) {\n    atomic_puts(\"Can't create netlink socket\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  ret = setsockopt(sock, SOL_NETLINK, NETLINK_RX_RING, &req, sizeof(req));\n  test_assert(ret < 0 && errno == ENOPROTOOPT);\n  ret = setsockopt(sock, SOL_NETLINK, NETLINK_TX_RING, &req, sizeof(req));\n  test_assert(ret < 0 && errno == ENOPROTOOPT);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/no_mask_timeslice.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pseudospinlock;\nstatic pthread_barrier_t bar;\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  pthread_barrier_wait(&bar);\n\n  sched_yield();\n  pseudospinlock = 1;\n\n  return NULL;\n}\n\nint main(void) {\n  sigset_t old, mask;\n  pthread_t t;\n\n  pthread_barrier_init(&bar, NULL, 2);\n\n  test_assert(0 == pthread_create(&t, NULL, thread, NULL));\n\n  sigfillset(&mask);\n  pthread_sigmask(SIG_BLOCK, &mask, &old);\n\n  pthread_barrier_wait(&bar);\n  while (!pseudospinlock) {\n    ;\n  }\n\n  pthread_sigmask(SIG_SETMASK, &old, NULL);\n\n  pthread_join(t, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/nscd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = socket(AF_UNIX, SOCK_STREAM, 0);\n  struct sockaddr_un addr;\n  int ret;\n  test_assert(fd >= 0);\n  addr.sun_family = AF_UNIX;\n  strcpy(addr.sun_path, \"/var/run/nscd/socket\");\n  ret = connect(fd, (struct sockaddr*)&addr, sizeof(addr));\n  test_assert(ret < 0 && errno == EACCES);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/nsutils.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef NSUTILS_H\n#define NSUTILS_H\n\n#include \"util.h\"\n\nstatic int try_setup_ns_internal(int ns_kind, int expect_to_be_root);\nstatic inline int try_setup_ns_no_root(int ns_kind) {\n  return try_setup_ns_internal(ns_kind, 0);\n}\n\nstatic inline int try_setup_ns(int ns_kind) {\n  return try_setup_ns_internal(ns_kind, 1);\n}\n\nstatic int open_proc_file(pid_t pid, const char* file, int mode) {\n  char path[100];\n  ssize_t n = snprintf(path, sizeof(path), \"/proc/%d/%s\", pid, file);\n  test_assert(n >= 0 && n < (ssize_t)sizeof(path));\n  int fd = open(path, mode);\n  test_assert(fd != -1);\n  return fd;\n}\n\nstatic int try_setup_ns_internal(int ns_kind, int expect_to_be_root) {\n  int err = -1;\n  errno = 0;\n  if (ns_kind != CLONE_NEWUSER) {\n    err = unshare(ns_kind);\n  }\n  if (ns_kind == CLONE_NEWUSER || err == -1) {\n    // Try again using user namespace functionality\n    test_assert(errno == 0 || errno == EPERM);\n\n    int child_block[2];\n    pipe(child_block);\n\n    pid_t pid = getpid();\n    pid_t child = fork();\n    test_assert(child >= 0);\n    if (!child) {\n      char ch;\n\n      close(child_block[1]);\n\n      // This will block until the parent closes fds[1]\n      test_assert(0 == read(child_block[0], &ch, 1));\n      close(child_block[0]);\n\n      // Deny setgroups\n      int setgroups_fd = open_proc_file(pid, \"setgroups\", O_WRONLY);\n      char deny[] = \"deny\";\n      test_assert(write(setgroups_fd, deny, sizeof(deny)) == sizeof(deny));\n      close(setgroups_fd);\n\n      // Make us root\n      ssize_t nbytes;\n      int uidmap_fd = open_proc_file(pid, \"uid_map\", O_WRONLY);\n      test_assert(uidmap_fd != -1);\n      char uidmap[100];\n      if (expect_to_be_root) {\n        nbytes =\n            snprintf(uidmap, (ssize_t)sizeof(uidmap), \"0\\t%d\\t1\", getuid());\n      } else {\n        nbytes =\n            snprintf(uidmap, (ssize_t)sizeof(uidmap), \"1000\\t%d\\t1\", getuid());\n      }\n      test_assert(nbytes > 0 && nbytes <= (ssize_t)sizeof(uidmap));\n      test_assert(write(uidmap_fd, uidmap, nbytes) == nbytes);\n      test_assert(uidmap_fd);\n\n      int gidmap_fd = open_proc_file(pid, \"gid_map\", O_WRONLY);\n      test_assert(gidmap_fd != -1);\n      char gidmap[100];\n      if (expect_to_be_root) {\n        nbytes =\n            snprintf(gidmap, (ssize_t)sizeof(gidmap), \"0\\t%d\\t1\", getgid());\n      } else {\n        nbytes =\n            snprintf(gidmap, (ssize_t)sizeof(gidmap), \"1000\\t%d\\t1\", getgid());\n      }\n      test_assert(nbytes > 0 && nbytes <= (ssize_t)sizeof(gidmap));\n      test_assert(write(gidmap_fd, gidmap, nbytes) == nbytes);\n\n      _exit(0);\n    }\n    close(child_block[0]);\n\n    err = unshare(ns_kind | CLONE_NEWUSER);\n\n    if (err == -1) {\n      // `EINVAL` is returned if the namespace is not supported/enabled.\n      test_assert(errno == EPERM || errno == EINVAL);\n      atomic_puts(\"Skipping test because namespaces are\\n\"\n                  \"not available at this privilege level\");\n      return -1;\n    }\n\n    // Allow the child to configure this user namespace\n    close(child_block[1]);\n\n    // Wait until our child has configured this namespace and has exited\n    int status = 0;\n    waitpid(child, &status, 0);\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n  }\n\n  return 0;\n}\n\n#endif // NSUTILS_H\n"
  },
  {
    "path": "src/test/numa.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define MPOL_DEFAULT 0\n#define MPOL_PREFERRED 1\n#define MPOL_BIND 2\n#define MPOL_INTERLEAVE 3\n\n#define MPOL_MF_STRICT 0x1\n#define MPOL_MF_MOVE 0x2\n#define MPOL_MF_MOVE_ALL 0x4\n\n#define MPOL_F_STATIC_NODES (1 << 15)\n#define MPOL_F_RELATIVE_NODES (1 << 14)\n\nstatic long mbind(void* start, unsigned long len, int mode,\n                  const unsigned long* nmask, unsigned long maxnode,\n                  unsigned flags) {\n  return syscall(SYS_mbind, start, len, mode, nmask, maxnode, flags);\n}\n\nstatic long set_mempolicy(int mode, const unsigned long* nodemask,\n                          unsigned long maxnode) {\n  return syscall(SYS_set_mempolicy, mode, nodemask, maxnode);\n}\n\nstatic int get_mempolicy(int* mode, unsigned long* nodemask,\n                         unsigned long maxnode, void* addr,\n                         unsigned long flags) {\n  return syscall(SYS_get_mempolicy, mode, nodemask, maxnode, addr, flags);\n}\n\ntypedef struct { unsigned long m[64]; } Nodemask;\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p = mmap(NULL, 16 * page_size, PROT_READ | PROT_WRITE,\n                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  int ret;\n  Nodemask* nodemask;\n  unsigned long mask = 0x1;\n  int mode;\n\n  test_assert(p != MAP_FAILED);\n  ret = mbind(p, 16 * page_size, MPOL_PREFERRED, NULL, 0, MPOL_MF_MOVE);\n  test_assert(ret == 0 || (ret == -1 && errno == ENOSYS));\n\n  // sanity check\n  ret = set_mempolicy(0, NULL, 0);\n  test_assert(ret == 0 || (ret == -1 && errno == ENOSYS));\n  ret = get_mempolicy(NULL, NULL, 0, NULL, 0);\n  test_assert(ret == 0 || (ret == -1 && errno == ENOSYS));\n\n  // test in and out params\n  // Make `nodemask` big in case we run on a kernel that has MAX_NUMNODES set\n  // to a large value; we get EINVAL if we pass a maxnodes value that's too\n  // small. And there's no way to determine what MAX_NUMNODES is AFAIK. What\n  // a terrible API!\n  ret = set_mempolicy(MPOL_BIND, &mask, 8 * sizeof(mask));\n  test_assert(ret == 0 || (ret == -1 && errno == ENOSYS));\n  ALLOCATE_GUARD(nodemask, 'a');\n  ret = get_mempolicy(&mode, nodemask->m, 8 * sizeof(nodemask->m), NULL, 0);\n  if (ret < 0) {\n    test_assert(errno == EINVAL || errno == ENOSYS);\n  } else {\n    test_assert(mode == MPOL_BIND);\n    test_assert(nodemask->m[0] == 0x1);\n    test_assert(nodemask->m[1] == 0);\n  }\n  VERIFY_GUARD(nodemask);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/open_tree.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = syscall(RR_open_tree, AT_FDCWD, \"/mnt\", 0);\n  if (fd < 0) {\n    if (errno == ENOSYS) {\n      atomic_puts(\"open_tree not supported, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    if (errno == ENOENT) {\n      atomic_puts(\"/mnt not found, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n  }\n  test_assert(fd >= 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/openat2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TEST_DIR \"test_dir\"\n#define FILENAME \"foo\"\n#define REL_FILENAME \"../\" TEST_DIR \"/\" FILENAME\n\nint main(void) {\n  mkdir(TEST_DIR, 0700);\n  int dirfd = open(TEST_DIR, O_DIRECTORY, 0755);\n  test_assert(dirfd > 0);\n\n  int filefd = openat(dirfd, FILENAME, O_CREAT | O_RDWR, 0600);\n  test_assert(filefd > 0);\n  test_assert(close(filefd) == 0);\n\n  struct rr_open_how how = {0};\n  how.flags = O_CREAT | O_RDONLY;\n  how.mode = 0600;\n\n  how.resolve = RESOLVE_BENEATH;\n  filefd = syscall(RR_openat2, dirfd, REL_FILENAME, &how, sizeof(how));\n  test_assert(filefd == -1);\n\n  // openat2 was introduced by Linux 5.6\n  // if the syscall isn't supported, return immediately\n  if (errno == ENOSYS) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(errno == EXDEV);\n\n  how.resolve = 0;\n  filefd = syscall(RR_openat2, dirfd, REL_FILENAME, &how, sizeof(how));\n  test_assert(filefd > 0);\n  test_assert(close(filefd) == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/openat_null.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n#include <unistd.h>\n\nint main(void) {\n  // Use syscall(2) because the glibc prototype for openat(2) might enforce that\n  // it's nonnull.\n  int fd = syscall(SYS_openat, AT_FDCWD, NULL, O_RDONLY);\n  test_assert(fd == -1);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/orphan_process.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  /* Descendant process will write one byte to the pipe to signal that it's\n   * complete */\n  int pipe_fds[2];\n  int err = pipe(pipe_fds);\n  pid_t child_pid, grandchild_pid, greatgrandchild_pid, dyingchild_pid;\n  test_assert(err == 0);\n\n  child_pid = fork();\n  if (child_pid) {\n    char buf;\n    int n = read(pipe_fds[0], &buf, 1);\n    test_assert(n == 1);\n    return 0;\n  }\n\n  /* In child */\n  dyingchild_pid = getpid();\n  grandchild_pid = fork();\n  if (grandchild_pid) {\n    exit(0);\n  }\n\n  /* In grandchild */\n  /* Wait for parent to die */\n  while (getppid() == dyingchild_pid) {\n    sched_yield();\n  }\n\n  /* Now the rr supervisor process is no longer our ancestor in the process\n     tree.\n     Try forking again. */\n  greatgrandchild_pid = fork();\n  if (greatgrandchild_pid) {\n    exit(0);\n  }\n\n  /* In great-grandchild */\n  atomic_puts(\"EXIT-SUCCESS\");\n  write(pipe_fds[1], \"a\", 1);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/overflow_branch_counter.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic volatile int caught_sig = 0;\n\nvoid catcher(__attribute__((unused)) int signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             __attribute__((unused)) void* ucontext_ptr) {\n  caught_sig = signum;\n}\n\nint main(void) {\n  struct sigaction sact;\n  long counter = 0;\n  long counter2 = 0;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = catcher;\n  sigaction(SIGALRM, &sact, NULL);\n\n  /* Run loop for 1 second. On my laptop, 1 second is easily enough to\n     get over 2^31 conditional branches on x86-64 and x86-32, with\n     the optimized code below. */\n  alarm(1);\n\n#ifdef __x86_64__\n  asm(\"1: incq %0\\n\\t\"\n      \"cmpl $0,%1\\n\\t\"\n      \"je 1b\\n\\t\"\n      : \"+r\"(counter)\n      : \"m\"(caught_sig));\n#elif __i386__\n  asm(\"1: incl %0\\n\\t\"\n      \"adcl $0,%1\\n\\t\"\n      \"cmpl $0,%2\\n\\t\"\n      \"je 1b\\n\\t\"\n      : \"+r\"(counter), \"+r\"(counter2)\n      : \"m\"(caught_sig));\n#elif defined(__aarch64__)\n  register long tmp = 0;\n  asm(\"1: add %0, %0, #1\\n\\t\"\n      \"ldr %1, %2\\n\\t\"\n      \"cmp %w1, %w0\\n\\t\"\n      \"bne 1b\" : \"+r\"(counter) : \"r\"(tmp), \"m\"(caught_sig));\n#else\n#error Unknown architecture\n#endif\n\n  atomic_printf(\"Signal %d caught, Counter is %lld\\n\", caught_sig,\n                counter + (((long long)counter2) << 32));\n  test_assert(SIGALRM == caught_sig);\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/overflow_branch_counter.run",
    "content": "source `dirname $0`/util.sh\n\n# This test executes LOTS of conditional branches so speed things up by\n# not interrupting too often.\nRECORD_ARGS=\"-c20000000\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/pack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void map_file(const char* name) {\n  int fd = open(name, O_RDONLY);\n  void* p;\n\n  test_assert(fd >= 0);\n  p = mmap(NULL, 65536, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);\n  test_assert(p != MAP_FAILED);\n}\n\nint main(void) {\n  map_file(\"mapped_file\");\n  map_file(\"mapped_file2\");\n  map_file(\"mapped_file3\");\n  map_file(\"mapped_file4\");\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pack.run",
    "content": "source `dirname $0`/util.sh\n\nswitch_to_nontmp_workdir_if_possible\ndd bs=1 count=65539 if=/dev/urandom of=mapped_file >& /dev/null\ndd bs=1 count=65539 if=/dev/urandom of=mapped_file2 >& /dev/null\ndd bs=1 count=1800 if=/dev/urandom of=mapped_file3 >& /dev/null\ndd bs=1 count=1800 if=/dev/urandom of=mapped_file4 >& /dev/null\n/bin/chmod u+x mapped_file*\nrecord pack$bitness\n\npack || failed \"'rr pack' failed\"\nif [[ `ls latest-trace/*_pack$bitness-* | wc -l` != \"1\" ]]; then\n    failed \"Failed to coalesce all instances of 'pack'\"\nfi\n\ntouch does_fs_support_clone\n# Assumes your `cp` supports the --reflink flag\ncp --reflink=always does_fs_support_clone does_fs_support_clone1\nif [[ $? -ne 0 ]]; then\n  # Since fs does NOT support file cloning, this further check should now be done\n  # (without the outer `if` the pack test would fail on btrfs)\n  if [[ `ls latest-trace/mmap_pack_* | wc -l` == \"0\" ]]; then\n       failed \"Packing produced no files.\"\n  fi\nfi\n\n# If there are no copies of _mapped_file it was probably copied\n# into the trace data, for one of various reasons, so don't fail\n# the test in that case.\nif [[ `ls latest-trace/*_mapped_file | wc -l` != \"0\" ]]; then\n    if [[ `ls latest-trace/*_mapped_file | wc -l` != \"1\" ]]; then\n        failed \"Failed to pack 'mapped_file'\"\n    fi\n    if [[ `ls latest-trace/*_mapped_file2 | wc -l` != \"1\" ]]; then\n        failed \"Failed to pack 'mapped_file2'\"\n    fi\n    if [[ `ls latest-trace/*_mapped_file3 | wc -l` != \"1\" ]]; then\n        failed \"Failed to pack 'mapped_file3'\"\n    fi\n    if [[ `ls latest-trace/*_mapped_file4 | wc -l` != \"1\" ]]; then\n        failed \"Failed to pack 'mapped_file4'\"\n    fi\nfi\n\nreplay\ncheck EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/pack_dir.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe simple$bitness\njust_record simple$bitness-$nonce\njust_record simple$bitness-$nonce\n\nmkdir the_pack_dir\n\n# Pack both directories with a common pack directory\npack --pack-dir the_pack_dir simple$bitness-$nonce-0 simple$bitness-$nonce-1\n\n# Test that we can still replay both traces\nreplay simple$bitness-$nonce-0\ncheck EXIT-SUCCESS\nrm replay.err replay.out\n\nreplay simple$bitness-$nonce-1\ncheck EXIT-SUCCESS\nrm replay.err replay.out\n\n# Check that we can move all three directories somewhere else and replay\n# still works.\nmkdir a_subdirectory\nmv the_pack_dir simple$bitness-$nonce-0 simple$bitness-$nonce-1 a_subdirectory\n\nreplay a_subdirectory/simple$bitness-$nonce-0\ncheck EXIT-SUCCESS\nrm replay.err replay.out\n\nreplay a_subdirectory/simple$bitness-$nonce-1\ncheck EXIT-SUCCESS\nrm replay.err replay.out\n"
  },
  {
    "path": "src/test/packet_mmap_disable.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));\n  int ret;\n  char buf[1024];\n\n  if (sock < 0) {\n    atomic_puts(\"Can't create raw socket\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  memset(buf, 0, sizeof(buf));\n\n  ret = setsockopt(sock, SOL_PACKET, PACKET_RX_RING, buf, sizeof(buf));\n  test_assert(ret < 0 && errno == ENOPROTOOPT);\n  ret = setsockopt(sock, SOL_PACKET, PACKET_TX_RING, buf, sizeof(buf));\n  test_assert(ret < 0 && errno == ENOPROTOOPT);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/parent_no_break_child_bkpt.py",
    "content": "from util import *\n\ndef observe_normal_parent_exit():\n    expect_rr('EXIT-SUCCESS')\n    expect_gdb(r'Inferior 1 \\(process \\d+\\) exited normally')\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nobserve_normal_parent_exit()\n\nrestart_replay()\nobserve_normal_parent_exit()\n\nok()\n"
  },
  {
    "path": "src/test/parent_no_break_child_bkpt.run",
    "content": "source `dirname $0`/util.sh\nrecord fork_child_crash$bitness\ndebug_gdb_only parent_no_break_child_bkpt\n"
  },
  {
    "path": "src/test/parent_no_stop_child_crash.py",
    "content": "from util import *\n\ndef observe_normal_parent_exit():\n    expect_rr('EXIT-SUCCESS')\n    expect_gdb(r'Inferior 1 \\(process \\d+\\) exited normally')\n\nsend_gdb('c')\nobserve_normal_parent_exit()\n\nrestart_replay()\nobserve_normal_parent_exit()\n\nok()\n"
  },
  {
    "path": "src/test/parent_no_stop_child_crash.run",
    "content": "source `dirname $0`/util.sh\nrecord fork_child_crash$bitness\ndebug_gdb_only parent_no_stop_child_crash\n"
  },
  {
    "path": "src/test/patch_page_end.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __i386__\nstatic const uint8_t code[] = {\n    0xcd, 0x80, // int $80\n    0x90, // nop\n    0x90, // nop\n    0x90, // nop\n    0xc3  // ret\n};\n#elif defined(__x86_64__)\nstatic const uint8_t code[] = {\n    0x0f, 0x05, // syscall\n    0x90, // nop\n    0x90, // nop\n    0x90, // nop\n    0xc3  // ret\n};\n#elif defined(__aarch64__)\nstatic const uint8_t code[] = {\n    0x1, 0x0, 0x0, 0xd4,    // svc #0\n    0xc0, 0x03, 0x5f, 0xd6, // ret\n};\n#else\n  #error unsupported arch\n#endif\n\nstatic long do_call(uint8_t* p) {\n  long ret;\n#if defined (__i386__) || defined(__x86_64__)\n  __asm__ __volatile__(\"call *%2\\n\\t\" : \"=a\"(ret) : \"a\"(SYS_getpid), \"c\"(p));\n#elif defined(__aarch64__)\n  register long x8 __asm__(\"x8\") = SYS_getpid;\n  register long x0 __asm__(\"x0\") = 0;\n  __asm__ __volatile__(\"blr %2\" : \"=r\"(x0) : \"r\"(x8), \"r\"(p) : \"x30\"); // x30 = lr\n  ret = x0;\n#else\n  #error unsupported arch\n#endif\n  return ret;\n}\n\nstatic void check_patch(uint8_t* p)\n{\n#if defined (__i386__) || defined(__x86_64__)\n  test_assert(p[0] == 0xe9);\n#elif defined(__aarch64__)\n  uint32_t inst;\n  memcpy(&inst, p, sizeof(inst));\n  // b to immediate instruction\n  test_assert((inst & 0xfc000000) == 0x14000000);\n#else\n  #error unsupported arch\n#endif\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* p = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,\n                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  uint8_t* d = p + page_size - sizeof(code);\n  pid_t pid;\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p + page_size, page_size));\n  memcpy(d, code, sizeof(code));\n\n  test_assert(0 == mprotect(p, page_size, PROT_READ | PROT_EXEC));\n  pid = do_call(d);\n  do_call(d);\n  check_patch(d);\n  test_assert(pid == getpid());\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/patch_page_end.run",
    "content": "source `dirname $0`/util.sh\n\n# This test requires syscallbuf syscall patching\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/pause.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int caught_signal;\nstatic void handle_signal(__attribute__((unused)) int sig) { ++caught_signal; }\n\nint main(void) {\n  int err;\n\n  signal(SIGALRM, handle_signal);\n  alarm(1);\n  atomic_puts(\"set alarm for 1 sec from now; pausing ...\");\n  pause();\n  err = errno;\n\n  atomic_printf(\"  ... woke up with errno %s(%d)\\n\", strerror(err), err);\n  test_assert(1 == caught_signal);\n  test_assert(EINTR == err);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/perf_event.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int counter_fd;\n\nstatic int sys_perf_event_open(struct perf_event_attr* attr, pid_t pid, int cpu,\n                               int group_fd, unsigned long flags) {\n  return syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, flags);\n}\n\nstatic uint64_t get_desched(void) {\n  uint64_t nr_desched;\n\n  test_assert(sizeof(nr_desched) ==\n              read(counter_fd, &nr_desched, sizeof(nr_desched)));\n  return nr_desched;\n}\n\nint main(void) {\n  struct perf_event_attr attr;\n  int i;\n  int new_counter_fd;\n\n  memset(&attr, 0, sizeof(attr));\n  attr.size = sizeof(attr);\n  attr.type = PERF_TYPE_SOFTWARE;\n  attr.config = PERF_COUNT_SW_CONTEXT_SWITCHES;\n\n  counter_fd = sys_perf_event_open(&attr, 0 /*self*/, -1 /*any cpu*/, -1, 0);\n  if (counter_fd < 0) {\n    test_assert(errno == EACCES);\n    atomic_puts(\"Skipping test because counter is not available\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0 <= counter_fd);\n\n  atomic_printf(\"num descheds: %\" PRIu64 \"\\n\", get_desched());\n  for (i = 0; i < 5; ++i) {\n    sched_yield();\n    atomic_printf(\"after yield: %\" PRIu64 \"\\n\", get_desched());\n  }\n\n  close(counter_fd);\n  /* Reopen the counter to make sure that rr noticed the close(). */\n  new_counter_fd = sys_perf_event_open(&attr, 0 /*self*/, -1 /*any cpu*/, -1, 0);\n  test_assert(counter_fd == new_counter_fd);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/perf_event_ioctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n/* Test for performance monitoring ('perf') ioctls. */\n\n#include \"util.h\"\n\n/**\n * glibc doesn't provide a wrapper for perf_event_open syscall. Hence, we create our\n * own wrapper.\n */\nstatic int perf_event_open(struct perf_event_attr *hw_event,\n                           pid_t pid, int cpu, int group_fd,\n                           unsigned long flags) {\n  int ret;\n  ret = syscall(__NR_perf_event_open, hw_event, pid, cpu, group_fd, flags);\n  return ret;\n}\n\nint main(void) {\n  struct perf_event_attr pe_attr;\n  int ret;\n  int fd;\n  uint64_t* event_id;\n\n  memset(&pe_attr, 0, sizeof(pe_attr));\n  pe_attr.type = PERF_TYPE_SOFTWARE;\n  pe_attr.config = PERF_COUNT_SW_CPU_CLOCK;\n  pe_attr.size = sizeof(struct perf_event_attr);\n  pe_attr.disabled = 1;\n  pe_attr.exclude_kernel = 1;\n  pe_attr.exclude_hv = 1;\n  pe_attr.exclude_idle = 1;\n  pe_attr.read_format = PERF_FORMAT_GROUP | PERF_FORMAT_ID;\n\n  fd = perf_event_open(&pe_attr, 0, -1, -1, 0);\n  test_assert(fd >= 0);\n\n  ret = ioctl(fd, PERF_EVENT_IOC_ENABLE, PERF_IOC_FLAG_GROUP);\n  test_assert(ret >= 0);\n\n  ret = ioctl(fd, PERF_EVENT_IOC_DISABLE, PERF_IOC_FLAG_GROUP);\n  test_assert(ret >= 0);\n\n  ret = ioctl(fd, PERF_EVENT_IOC_RESET, PERF_IOC_FLAG_GROUP);\n  test_assert(ret >= 0);\n\n  ALLOCATE_GUARD(event_id, 'x');\n  ret = ioctl(fd, PERF_EVENT_IOC_ID, event_id);\n  test_assert(ret >= 0 || errno == EINVAL || errno == ENOTTY);\n  VERIFY_GUARD(event_id);\n\n  ret = close(fd);\n  test_assert(ret == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/perf_event_mmap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int sys_perf_event_open(struct perf_event_attr* attr, pid_t pid, int cpu,\n                               int group_fd, unsigned long flags) {\n  return syscall(SYS_perf_event_open, attr, pid, cpu, group_fd, flags);\n}\n\nint main(void) {\n  struct perf_event_attr attr;\n  void* p;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int counter_fd;\n\n  memset(&attr, 0, sizeof(attr));\n  attr.size = sizeof(attr);\n  attr.type = PERF_TYPE_SOFTWARE;\n  attr.config = PERF_COUNT_SW_CPU_CLOCK;\n  attr.exclude_kernel = 1;\n  attr.sample_period = 1000000;\n  attr.sample_type = PERF_SAMPLE_IP;\n\n  counter_fd = sys_perf_event_open(&attr, 0 /*self*/, -1 /*any cpu*/, -1, 0);\n  test_assert(0 <= counter_fd);\n\n  p = mmap(NULL, 3*page_size, PROT_READ | PROT_WRITE, MAP_SHARED, counter_fd, 0);\n  test_assert(p == MAP_FAILED);\n  test_assert(errno == ENODEV);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/personality.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int rr_personality(unsigned long persona) {\n  long ret = syscall(RR_personality, persona);\n  if (-4096 < ret && ret < 0) {\n    errno = -ret;\n    return -1;\n  }\n  return ret;\n}\n\nint main(void) {\n  rr_personality(PER_LINUX);\n  test_assert(rr_personality(0xffffffff) == PER_LINUX);\n\n  int ret = rr_personality(PER_LINUX32);\n#ifndef __aarch64__\n  test_assert(ret != -1);\n#endif\n  if (ret != -1)\n    test_assert(rr_personality(0xffffffff) == PER_LINUX32);\n\n  rr_personality(ADDR_NO_RANDOMIZE);\n  test_assert(rr_personality(0xffffffff) == ADDR_NO_RANDOMIZE);\n\n  rr_personality(ADDR_COMPAT_LAYOUT);\n  test_assert(rr_personality(0xffffffff) == ADDR_COMPAT_LAYOUT);\n\n  rr_personality(ADDR_LIMIT_32BIT);\n  test_assert(rr_personality(0xffffffff) == ADDR_LIMIT_32BIT);\n\n  rr_personality(ADDR_LIMIT_3GB);\n  test_assert(rr_personality(0xffffffff) == ADDR_LIMIT_3GB);\n\n  rr_personality(MMAP_PAGE_ZERO);\n  test_assert(rr_personality(0xffffffff) == MMAP_PAGE_ZERO);\n\n  /* Not tested yet: May need to update some checks in rr\n     rr_personality(READ_IMPLIES_EXEC);\n     test_assert(rr_personality(0xffffffff) == READ_IMPLIES_EXEC);\n  */\n\n  rr_personality(SHORT_INODE);\n  test_assert(rr_personality(0xffffffff) == SHORT_INODE);\n\n  rr_personality(STICKY_TIMEOUTS);\n  test_assert(rr_personality(0xffffffff) == STICKY_TIMEOUTS);\n\n  rr_personality(UNAME26);\n  test_assert(rr_personality(0xffffffff) == UNAME26);\n\n  rr_personality(WHOLE_SECONDS);\n  test_assert(rr_personality(0xffffffff) == WHOLE_SECONDS);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/personality_chaos.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=--chaos\ncompare_test EXIT-SUCCESS \"\" personality$bitness\n"
  },
  {
    "path": "src/test/pid_ns_kill_child.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(void) {\n  pid_t pid;\n  int pipe_fds[2];\n  char ch;\n  pipe(pipe_fds);\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  signal(SIGTERM, SIG_IGN);\n  /* Print this now because we will get killed */\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  /* This is the first child, therefore PID 1 in its PID namespace */\n  pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    int i;\n    for (i = 0; i < 20; ++i) {\n      pid = fork();\n      if (!pid) {\n        /* The grandchild just sleeps */\n        pause();\n      }\n      test_assert(pid == i + 2);\n    }\n    write(pipe_fds[1], \"x\", 1);\n    pause();\n  }\n\n  read(pipe_fds[0], &ch, 1);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_kill_child_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#define NUM_THREADS_PER_GRANDCHILD 5\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  pause();\n  return NULL;\n}\n\nstatic void do_grandchild(void) {\n  pthread_t thread;\n  /* Reduce thread priority so rr doesn't schedule these threads unless we want it to */\n  setpriority(PRIO_PROCESS, 0, 5);\n  for (int i = 0; i < NUM_THREADS_PER_GRANDCHILD; ++i) {\n    pthread_create(&thread, NULL, do_thread, NULL);\n  }\n  pause();\n}\n\nint main(void) {\n  pid_t pid;\n  int pipe_fds[2];\n  char ch;\n  pipe(pipe_fds);\n  struct timespec ts = { 0, 1000000 };\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  /* This is the first child, therefore PID 1 in its PID namespace.\n     Spawn some grandchildren that don't exit by themselves but spawn some threads.\n\n     The bug we're looking for here is:\n     * zap_pid_ns_processes tears down the pid-namespace children of our child\n     * we get the PTRACE_EVENT_EXIT for that grandchild's thread-group leader before we've seen the\n     exit event of all of its child threads\n     * The grandchild's thread-group leader reaches zombie state but we don't reap it\n     (because we can't safely do so until all its child threads have been reaped)\n     * So we just carry on leaving the thread-group leader unreaped. But later on\n     when we try to kill our child, the pid-namespace root, we're unable to observe\n     its exit because it is waiting to reap the thread-group leader zombie, and it can't.\n  */\n  pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    pid = fork();\n    test_assert(pid >= 0);\n    if (!pid) {\n      do_grandchild();\n    }\n    write(pipe_fds[1], \"x\", 1);\n    pause();\n  }\n\n  read(pipe_fds[0], &ch, 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(pid, SIGKILL);\n  nanosleep(&ts, NULL);\n  \n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_kill_child_zombie.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#define NUM_GRANDCHILDREN 5\n\nint main(void) {\n  pid_t pid;\n  int pipe_fds[2];\n  int i;\n  char ch;\n  pipe(pipe_fds);\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  /* This is the first child, therefore PID 1 in its PID namespace.\n     Spawn some grandchildren that just hang. */\n  pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    for (i = 0; i < NUM_GRANDCHILDREN; ++i) {\n      pid = fork();\n      test_assert(pid >= 0);\n      if (!pid) {\n        pause();\n        return 0;\n      }\n      test_assert(pid == i + 2);\n    }\n    write(pipe_fds[1], \"x\", 1);\n    pause();\n  }\n\n  read(pipe_fds[0], &ch, 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  /* Now kill the pid-ns init process. This will move it to its exit stop. */\n  kill(pid, SIGKILL);\n  /* When we exit, rr will do Task::kill() on the pid-ns init process.\n     This will reach zap_pid_ns_processes to kill the grandchildren.\n     rr needs to handle this without deadlocking. */\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_kill_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#define NUM_THREADS 3\n\nstatic int trigger_last_thread_pipe[2];\nstatic int trigger_pid_ns_init_exit_pipe[2];\n\nstatic void* do_thread(void* p) {\n  int index = (intptr_t)p;\n  /* Reduce thread priority so rr doesn't schedule these threads unless we want it to */\n  setpriority(PRIO_PROCESS, 0, 5);\n  if (index == NUM_THREADS - 1) {\n    char ch;\n    read(trigger_last_thread_pipe[0], &ch, 1);\n    /* Kick off the init process exit ...\n       after our exit_group has started. */\n    write(trigger_pid_ns_init_exit_pipe[1], \"x\", 1);\n    exit(1);\n  }\n  pause();\n  return NULL;\n}\n\n/**\n * 1) make the last thread of 'child' do an 'exit_group', initiating kill of all threads\n * in particular 'child's main thread, which advances to PTRACE_EVENT_EXIT\n * 2) then have the pid_ns_init process exit, triggering kernel's zap_pid_ns_processes\n * for 'child' and 'inner_child'\n * 3) this kicks 'child' out of PTRACE_EVENT_EXIT (without rr having seen it)\n * 4) 'child' then enters its own zap_pid_ns_processes and waits on the exit of\n * 'inner_child'\n * 5) rr sees that 'child' has been reaped, but it's not in STOPPED state nor\n * is it in EXITED state.\n */\nstatic int do_pid_ns_init(void) {\n  pid_t child;\n  char ch;\n  pipe(trigger_last_thread_pipe);\n  pipe(trigger_pid_ns_init_exit_pipe);\n\n  child = fork();\n  if (!child) {\n    pid_t inner_child;\n\n    for (int i = 0; i < NUM_THREADS; ++i) {\n      pthread_t thread;\n      pthread_create(&thread, NULL, do_thread, (void*)(intptr_t)i);\n    }\n\n    test_assert(0 == unshare(CLONE_NEWPID));\n    inner_child = fork();\n    if (!inner_child) {\n      pause();\n      return 0;\n    }\n\n    write(trigger_last_thread_pipe[1], \"y\", 1);\n    pause();\n    return 0;\n  }\n  read(trigger_pid_ns_init_exit_pipe[0], &ch, 1);\n  /* Trigger exit that will zap_pid_ns_processes for our child tasks */\n  return 77;\n}\n\nint main(void) {\n  pid_t pid;\n  int status;\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    return do_pid_ns_init();\n  }\n\n  test_assert(pid == waitpid(pid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_kill_threads_exit_wait.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#define NUM_THREADS 2\n\nstatic int trigger_last_thread_pipe[2];\nstatic int trigger_pid_ns_init_exit_pipe[2];\n\nstatic void* do_thread(void* p) {\n  int index = (intptr_t)p;\n  /* Reduce thread priority so rr doesn't schedule these threads unless we want it to */\n  setpriority(PRIO_PROCESS, 0, index + 1);\n  if (index == NUM_THREADS - 1) {\n    char ch;\n    read(trigger_last_thread_pipe[0], &ch, 1);\n    /* Kick off the init process exit ...\n       after our exit_group has started. */\n    write(trigger_pid_ns_init_exit_pipe[1], \"x\", 1);\n    exit(1);\n  }\n  pause();\n  return NULL;\n}\n\nstatic int do_pid_ns_init(void) {\n  pid_t child;\n  char ch;\n  pipe(trigger_last_thread_pipe);\n  pipe(trigger_pid_ns_init_exit_pipe);\n\n  test_assert(0 == unshare(CLONE_NEWPID));\n  child = fork();\n  if (!child) {\n    pid_t inner_child;\n    for (int i = 0; i < NUM_THREADS; ++i) {\n      pthread_t thread;\n      pthread_create(&thread, NULL, do_thread, (void*)(intptr_t)i);\n    }\n\n    inner_child = fork();\n    if (!inner_child) {\n      pause();\n      return 0;\n    }\n\n    write(trigger_last_thread_pipe[1], \"y\", 1);\n    pause();\n    return 0;\n  }\n  read(trigger_pid_ns_init_exit_pipe[0], &ch, 1);\n  /* Trigger exit that will zap_pid_ns_processes for our child tasks */\n  return 77;\n}\n\nstatic void do_detect_glibc_bug(void) {\n  pid_t child;\n  int status;\n  unshare(CLONE_NEWPID);\n  child = fork();\n  if (!child) {\n    exit(0);\n  }\n  wait(&status);\n  exit(WIFSIGNALED(status));\n}\n\nstatic int detect_glibc_bug_inner(void) {\n  int status;\n  pid_t pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    do_detect_glibc_bug();\n  }\n  wait(&status);\n  return WEXITSTATUS(status) != 0;\n}\n\n/* Detect https://sourceware.org/legacy-ml/libc-alpha/2017-05/msg00378.html */\nstatic int detect_glibc_bug(void) {\n  int status;\n  pid_t pid = fork();\n  if (!pid) {\n    close(STDERR_FILENO);\n    if (-1 == try_setup_ns(CLONE_NEWPID)) {\n      exit(0);\n    }\n    exit(detect_glibc_bug_inner());\n  }\n  wait(&status);\n  return WEXITSTATUS(status);\n}\n\nint main(void) {\n  pid_t pid;\n  int status;\n\n  if (detect_glibc_bug()) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    return do_pid_ns_init();\n  }\n\n  test_assert(pid == waitpid(pid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_reap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  /* This will try to exit_group while we have a child alive in our\n     pid namespace. The kernel will insist on killing and reaping the\n     child before this task can complete its exit. */\n  exit(66);\n}\n\nint main(void) {\n  pid_t pid;\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  /* This is the first child, therefore PID 1 in its PID namespace */\n  pid = fork();\n  test_assert(pid >= 0);\n  if (pid == 0) {\n    struct timespec ts = { 0, 10000000 };\n    pthread_t thread;\n    pid_t ns_child;\n    test_assert(getpid() == 1);\n\n    ns_child = fork();\n    test_assert(ns_child >= 0);\n    if (ns_child == 0) {\n      pid_t ns_grandchild = fork();\n      if (ns_grandchild == 0) {\n        sleep(10);\n      }\n      return 0;\n    }\n\n    /* Make time to allow grandchild to reparent to us */\n    nanosleep(&ts, NULL);\n\n    /* Test exiting from a non-main thread */\n    pthread_create(&thread, NULL, do_thread, NULL);\n    pthread_exit(NULL);\n  }\n\n  int status;\n  waitpid(pid, &status, 0);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 66);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_segv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(void) {\n  pid_t pid;\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    // We may not have permission to set up namespaces, so bail.\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  // This is the first child, therefore PID 1 in its PID namespace\n  pid = fork();\n  test_assert(pid >= 0);\n  if (pid == 0) {\n    test_assert(getpid() == 1);\n    crash_null_deref();\n    test_assert(0 && \"Shouldn't have gotten here\");\n  }\n\n  int status;\n  waitpid(pid, &status, __WALL);\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pid_ns_shutdown.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#define NUM_THREADS 10\n\nstatic int trigger_last_thread_pipe[2];\nstatic int trigger_pid_ns_init_exit_pipe[2];\nstatic int toplevel_exit_pipe[2];\n\nstatic void* do_thread(void* p) {\n  int index = (intptr_t)p;\n  /* Reduce thread priority so rr doesn't schedule these threads unless we want it to */\n  setpriority(PRIO_PROCESS, 0, 5);\n  if (index == NUM_THREADS - 1) {\n    char ch;\n    read(trigger_last_thread_pipe[0], &ch, 1);\n    /* Kick off the init process exit ...\n       after our exit_group has started. */\n    write(trigger_pid_ns_init_exit_pipe[1], \"x\", 1);\n    exit(1);\n  }\n  pause();\n  return NULL;\n}\n\n/**\n * 1) make the last thread of 'child' do an 'exit_group', initiating kill of all threads\n * in particular 'child's main thread, which advances to PTRACE_EVENT_EXIT\n * 2) then have the pid_ns_init process exit, triggering kernel's zap_pid_ns_processes\n * for 'child' and 'inner_child'\n * 3) this kicks 'child' out of PTRACE_EVENT_EXIT (without rr having seen it)\n * 4) 'child' then enters its own zap_pid_ns_processes and waits on the exit of\n * 'inner_child'\n * 5) rr sees that 'child' has been reaped, but it's not in STOPPED state nor\n * is it in EXITED state.\n */\nstatic int do_pid_ns_init(void) {\n  pid_t child;\n  char ch;\n  pipe(trigger_last_thread_pipe);\n\n  unshare(CLONE_NEWPID);\n  child = fork();\n  if (!child) {\n    pid_t inner_child;\n    for (int i = 0; i < NUM_THREADS; ++i) {\n      pthread_t thread;\n      pthread_create(&thread, NULL, do_thread, (void*)(intptr_t)i);\n    }\n\n    test_assert(0 == unshare(CLONE_NEWPID));\n    inner_child = fork();\n    if (!inner_child) {\n      pause();\n      return 0;\n    }\n\n    write(trigger_last_thread_pipe[1], \"y\", 1);\n    pause();\n    return 0;\n  }\n  read(trigger_pid_ns_init_exit_pipe[0], &ch, 1);\n  write(toplevel_exit_pipe[1], \"q\", 1);\n  return 77;\n}\n\nstatic void do_detect_glibc_bug(void) {\n  pid_t child;\n  int status;\n  unshare(CLONE_NEWPID);\n  child = fork();\n  if (!child) {\n    exit(0);\n  }\n  wait(&status);\n  exit(WIFSIGNALED(status));\n}\n\nstatic int detect_glibc_bug_inner(void) {\n  int status;\n  pid_t pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    do_detect_glibc_bug();\n  }\n  wait(&status);\n  return WEXITSTATUS(status) != 0;\n}\n\n/* Detect https://sourceware.org/legacy-ml/libc-alpha/2017-05/msg00378.html */\nstatic int detect_glibc_bug(void) {\n  int status;\n  pid_t pid = fork();\n  if (!pid) {\n    close(STDERR_FILENO);\n    if (-1 == try_setup_ns(CLONE_NEWPID)) {\n      exit(0);\n    }\n    exit(detect_glibc_bug_inner());\n  }\n  wait(&status);\n  return WEXITSTATUS(status);\n}\n\nint main(void) {\n  pid_t pid;\n  char ch;\n\n  if (detect_glibc_bug()) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"Insufficient permissions, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  pipe(trigger_pid_ns_init_exit_pipe);\n  pipe(toplevel_exit_pipe);\n  pid = fork();\n  test_assert(pid >= 0);\n  if (!pid) {\n    return do_pid_ns_init();\n  }\n\n  read(toplevel_exit_pipe[0], &ch, 1);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pidfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define RR_P_PIDFD 3\n\nint main(void) {\n  int child;\n  int pipe_fds[2];\n  int pidfd;\n  int status;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (!child) {\n    char ch;\n    read(pipe_fds[0], &ch, 1);\n    return 77;\n  }\n\n  pidfd = syscall(RR_pidfd_open, child, 0);\n  write(pipe_fds[1], \"x\", 1);\n  if (pidfd < 0 && errno == ENOSYS) {\n    atomic_puts(\"pidfd_open not supported, skipping test\");\n    write(pipe_fds[1], \"x\", 1);\n    test_assert(wait(&status) == child);\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  } else {\n    siginfo_t* info;\n    int ret;\n    test_assert(pidfd >= 0);\n\n    ret = syscall(RR_pidfd_send_signal, pidfd, SIGURG, NULL, 0);\n    if (ret < 0) {\n      test_assert(errno == ENOSYS);\n    } else {\n      test_assert(ret == 0);\n    }\n\n    write(pipe_fds[1], \"x\", 1);\n    ALLOCATE_GUARD(info, 'a');\n    ret = waitid(RR_P_PIDFD, pidfd, info, WEXITED);\n    VERIFY_GUARD(info);\n    if (ret < 0 && errno == EINVAL) {\n      atomic_puts(\"P_PIDFD not supported, skipping that part of the test\");\n      test_assert(wait(&status) == child);\n      test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n    } else {\n      test_assert(ret == 0);\n      test_assert(info->si_pid == child);\n      test_assert(info->si_code == CLD_EXITED);\n      test_assert(info->si_status == 77);\n\n      ret = waitid(RR_P_PIDFD, 0, info, WEXITED);\n      VERIFY_GUARD(info);\n      test_assert(ret < 0);\n      test_assert(errno == EBADF);\n\n      ret = waitid(RR_P_PIDFD, INT_MAX, info, WEXITED);\n      VERIFY_GUARD(info);\n      test_assert(ret < 0);\n      test_assert(errno == EBADF);\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pidfd_getfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define RR_P_PIDFD 3\n\nint main(void) {\n  int child;\n  int pipe_fds[2];\n  int pidfd, gotfd;\n  int status;\n  char ch;\n\n  pipe(pipe_fds);\n  child = fork();\n  if (!child) {\n    kill(sys_gettid(), SIGSTOP);\n    return 77;\n  }\n\n  test_assert(waitpid(child, &status, WUNTRACED) == child);\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  pidfd = syscall(RR_pidfd_open, child, 0);\n  write(pipe_fds[1], \"x\", 1);\n  if (pidfd < 0 && errno == ENOSYS) {\n    atomic_puts(\"pidfd_open not supported, skipping test\");\n    kill(child, SIGCONT);\n    test_assert(wait(&status) == child);\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(pidfd >= 0);\n\n  gotfd = syscall(RR_pidfd_getfd, pidfd, pipe_fds[0], 0);\n  if (gotfd < 0 && errno == ENOSYS) {\n    atomic_puts(\"pidfd_getfd not supported, skipping test\");\n    kill(child, SIGCONT);\n    test_assert(wait(&status) == child);\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(gotfd != pipe_fds[0]);\n  read(gotfd, &ch, 1);\n  test_assert(ch == 'x');\n\n  // Test FileMonitors.\n  gotfd = syscall(RR_pidfd_getfd, pidfd, 1, 0);\n  test_assert(gotfd > 0);\n  write(gotfd, \"Hi\\n\", 3);\n\n  kill(child, SIGCONT);\n  test_assert(wait(&status) == child);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pivot_root.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(void) {\n  if (-1 == try_setup_ns(CLONE_NEWNS)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  /* Set up a directory structure for testing */\n  test_assert(0 == mkdir(\"old_root\", 0700));\n  test_assert(0 == mount(\"none\", \"old_root\", \"tmpfs\", 0, NULL));\n\n  test_assert(0 == mkdir(\"old_root/new_root\", 0700));\n  test_assert(0 == mount(\"none\", \"old_root/new_root\", \"tmpfs\", 0, NULL));\n\n  test_assert(0 == mkdir(\"old_root/new_root/new_old_root\", 0700));\n\n  /* Write some files so we can identify directories */\n  int fd = open(\"old_root/old_root.txt\", O_WRONLY | O_CREAT, 0600);\n  test_assert(fd != -1);\n  test_assert(0 == close(fd));\n\n  fd = open(\"old_root/new_root/new_root.txt\", O_WRONLY | O_CREAT, 0600);\n  test_assert(fd != -1);\n  test_assert(0 == close(fd));\n\n  /* The actual test */\n  test_assert(0 == chdir(\"old_root\"));\n  test_assert(0 == chroot(\".\"));\n\n  test_assert(0 ==\n              syscall(SYS_pivot_root, \"new_root\", \"new_root/new_old_root\"));\n\n  /* Verify that directory structure looks as expected */\n  struct stat buf;\n  test_assert(0 == stat(\"new_root.txt\", &buf));\n  test_assert(0 == stat(\"new_old_root/old_root.txt\", &buf));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/poll_sig_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS 10\n\nint main(void) {\n  int fds[2];\n  struct pollfd pfd;\n  int i;\n\n  pipe2(fds, O_NONBLOCK);\n\n  pfd.fd = fds[0];\n  pfd.events = POLLIN;\n  for (i = 0; i < NUM_ITERATIONS; ++i) {\n    char c;\n    int ret;\n\n    atomic_printf(\"iteration %d\\n\", i);\n\n    if (0 == fork()) {\n      usleep(250000);\n      write(fds[1], \"x\", 1);\n      return 0;\n    }\n\n    /* wait for 1 second, which should be long enough for\n       the child to do its write. In extreme cases the\n       child might run to completion before this poll()\n       call is entered, in which case we will time out safely. */\n    ret = poll(&pfd, 1, 1000);\n    if (ret == 0) {\n      continue;\n    }\n    test_assert(1 == ret);\n    test_assert(POLLIN & pfd.revents);\n    test_assert(1 == read(pfd.fd, &c, 1));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/post_exec_fpu_regs.py",
    "content": "from util import *\nimport re\n\narch = get_exe_arch()\n\nif arch == 'aarch64':\n    send_gdb('p $v0.d.u')\n    expect_gdb('{0, 0}')\nelif arch == 'i386' or arch == 'i386:x86-64':\n    send_gdb('p $xmm0')\n    expect_gdb('v4_float = {0, 0, 0, 0}')\n\nok()\n"
  },
  {
    "path": "src/test/post_exec_fpu_regs.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only post_exec_fpu_regs\n"
  },
  {
    "path": "src/test/ppoll.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <poll.h>\n\n#define NUM_ITERATIONS 10\n\nstatic int our_ualarm(useconds_t value, useconds_t interval)\n{\n  struct itimerval timer;\n\n  timer.it_value.tv_sec = 0;\n  timer.it_value.tv_usec = value;\n  timer.it_interval.tv_sec = 0;\n  timer.it_interval.tv_usec = interval;\n\n  return setitimer(ITIMER_REAL, &timer, NULL);\n}\n\nstatic void handle_sig(__attribute__((unused)) int sig) {\n  sigset_t after_sigset;\n  int ret = sigprocmask(SIG_BLOCK, NULL, &after_sigset);\n  test_assert(ret == 0);\n  test_assert(sigismember(&after_sigset, SIGCHLD));\n}\n\nint main(void) {\n  int fds[2];\n  struct pollfd pfd;\n  int i;\n\n  struct timespec t;\n  t.tv_sec = 1;\n  t.tv_nsec = 0;\n\n  sigset_t sigset;\n  test_assert(0 == sigemptyset(&sigset));\n  test_assert(0 == sigaddset(&sigset, SIGCHLD));\n\n  uint64_t fake_sigset[10];\n  fake_sigset[0] =\n      (((uint64_t)1) << (SIGCHLD - 1)) | (((uint64_t)1) << (SIGPWR - 1));\n  memset(&fake_sigset[1], 0xab, 9 * sizeof(uint64_t));\n\n  signal(SIGALRM, &handle_sig);\n\n  pipe2(fds, O_NONBLOCK);\n\n  pfd.fd = fds[0];\n  pfd.events = POLLIN;\n  for (i = 0; i < NUM_ITERATIONS; i++) {\n    int ret;\n    sigset_t before_sigset;\n    sigset_t sigalrm_blocked_sigset;\n    sigemptyset(&sigalrm_blocked_sigset);\n    sigaddset(&sigalrm_blocked_sigset, SIGALRM);\n    /* Block SIGALRM before we call our_ualarm because we don't want it\n       to go off early. */\n    ret = sigprocmask(SIG_SETMASK, &sigalrm_blocked_sigset, &before_sigset);\n    test_assert(ret == 0);\n    test_assert(!sigismember(&before_sigset, SIGALRM));\n\n    atomic_printf(\"iteration %d\\n\", i);\n    if (i % 2 == 0) {\n      our_ualarm(100000, 0);\n    } else if (fork() == 0) {\n      usleep(100000);\n      return 0;\n    }\n\n    t.tv_sec = 1;\n    t.tv_nsec = 0;\n\n    ret = syscall(SYS_ppoll, &pfd, 1, &t, &fake_sigset[0], sizeof(uint64_t));\n    if (i % 2 == 0) {\n      test_assert(ret == -1 && errno == EINTR);\n    } else {\n      test_assert(ret == 0);\n    }\n\n    /* Validate that we did not clobber fake_sigset memory */\n    for (size_t i = 0; i < 9 * sizeof(uint64_t); ++i) {\n      test_assert(((uint8_t*)(&fake_sigset[1]))[i] == 0xab);\n    }\n\n    /* Validate that the signal mask got reset */\n    sigset_t after_sigset;\n    ret = sigprocmask(SIG_SETMASK, &before_sigset, &after_sigset);\n    test_assert(ret == 0);\n    test_assert(!sigismember(&after_sigset, SIGCHLD));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ppoll_deliver.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <poll.h>\n\nstatic volatile int sighandler_called;\n\nstatic void handle_signal(int sig) {\n  test_assert(sig == SIGCHLD);\n  sighandler_called = 1;\n}\n\nint main(void) {\n  pid_t child;\n  int ret;\n  struct sigaction sa;\n  sigset_t sigset;\n  int status;\n  struct timespec ten_ms = { 0, 10000000 };\n\n  test_assert(0 == sigemptyset(&sigset));\n  test_assert(0 == sigaddset(&sigset, SIGCHLD));\n  test_assert(0 == sigprocmask(SIG_BLOCK, &sigset, NULL));\n\n  child = fork();\n  if (!child) {\n    return 77;\n  }\n  /* Try to ensure the child has exited so the SIGCHLD is pending */\n  test_assert(0 == nanosleep(&ten_ms, NULL));\n\n  memset(&sa, 0, sizeof(sa));\n  sa.sa_handler = handle_signal;\n  test_assert(0 == sigaction(SIGCHLD, &sa, NULL));\n\n  test_assert(0 == sigemptyset(&sigset));\n  /* SIGCHLD should already be pending, so the syscallbuf ppoll will\n     only do the untraced ppoll and defer the signal until we're\n     exiting the syscallbuf. */\n  ret = ppoll(NULL, 0, NULL, &sigset);\n  test_assert(ret == -1 && errno == EINTR);\n\n  test_assert(sighandler_called);\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char setname[16] = \"prctl-test\";\n  char getname[16];\n  unsigned long slack = sizeof(unsigned long) == 4\n                            ? 1024 * 1024 * 1024\n                            : (unsigned long)(1024LL * 1024 * 1024 * 8);\n  int sig = 99;\n  int tsc = 99;\n  int dummy;\n\n  test_assert(0 == prctl(PR_SET_KEEPCAPS, 0));\n  test_assert(0 == prctl(PR_GET_KEEPCAPS));\n\n  test_assert(0 == prctl(PR_SET_KEEPCAPS, 1));\n  test_assert(1 == prctl(PR_GET_KEEPCAPS));\n\n  test_assert(0 == prctl(PR_SET_NAME, setname));\n  test_assert(0 == prctl(PR_GET_NAME, getname));\n  atomic_printf(\"set name `%s'; got name `%s'\\n\", setname, getname);\n  test_assert(!strcmp(getname, setname));\n\n  test_assert(0 == prctl(PR_SET_DUMPABLE, 0));\n  test_assert(0 == prctl(PR_GET_DUMPABLE));\n\n  test_assert(0 == prctl(PR_SET_DUMPABLE, 1));\n  test_assert(1 == prctl(PR_GET_DUMPABLE));\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n\n  test_assert(0 == prctl(PR_SET_TIMERSLACK, slack));\n  /* prctl coerces its result to int */\n  test_assert((int)slack == prctl(PR_GET_TIMERSLACK));\n\n  test_assert(0 ==\n              prctl(PR_MCE_KILL, PR_MCE_KILL_SET, PR_MCE_KILL_EARLY, 0, 0));\n  test_assert(PR_MCE_KILL_EARLY == prctl(PR_MCE_KILL_GET, 0, 0, 0, 0));\n\n  test_assert(-1 == prctl(PR_GET_ENDIAN, &dummy) && errno == EINVAL);\n  test_assert(-1 == prctl(PR_GET_FPEMU, &dummy) && errno == EINVAL);\n  test_assert(-1 == prctl(PR_GET_FPEXC, &dummy) && errno == EINVAL);\n  test_assert(-1 == prctl(PR_GET_UNALIGN, &dummy) && errno == EINVAL);\n\n  test_assert(0 == prctl(PR_GET_PDEATHSIG, (unsigned long)&sig));\n  test_assert(sig == 0);\n\n  test_assert(0 == prctl(PR_GET_TSC, (unsigned long)&tsc));\n  test_assert(tsc == PR_TSC_ENABLE);\n\n  test_assert(0 == prctl(PR_GET_SECCOMP));\n\n  int reaper;\n  test_assert(0 == prctl(PR_SET_CHILD_SUBREAPER, 1));\n  test_assert(0 == prctl(PR_GET_CHILD_SUBREAPER, &reaper));\n  test_assert(reaper == 1);\n\n  unsigned int size = 0;\n  test_assert(0 == prctl(PR_SET_MM, PR_SET_MM_MAP_SIZE, &size, 0, 0));\n  test_assert(size != 0);\n\n  // PR_SET_MM_ARG_START needs CAP_SYS_RESOURCE\n  int ret = prctl(PR_SET_MM, PR_SET_MM_ARG_START, setname, 0, 0);\n  test_assert(0 == ret || (-1 == ret && errno == EPERM));\n\n  // PR_SET_MM_ARG_END needs CAP_SYS_RESOURCE\n  ret = prctl(PR_SET_MM, PR_SET_MM_ARG_END, setname + sizeof(setname), 0, 0);\n  test_assert(0 == ret || (-1 == ret && errno == EPERM));\n\n  // On a kernel without PR_SET_VMA, this will return EINVAL.\n  // On a kernel with PR_SET_VMA but without CONFIG_ANON_VMA_NAME,\n  // it will return ENOMEM.\n  // On a kernel with it, it should return EBADF, because\n  // the rr page is not an anonymous mapping.\n  ssize_t page_size = sysconf(_SC_PAGE_SIZE);\n  test_assert(-1 == prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, 0x7000000, page_size, \"foo\") &&\n              (errno == EINVAL || errno == EBADF || errno == ENOMEM));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_anon_vma_name.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  for (int i = 0; i < 2; ++i) {\n    char* p = (char*)mmap(NULL, 5*page_size, PROT_READ | PROT_WRITE,\n        MAP_ANONYMOUS | (i ? MAP_SHARED : MAP_PRIVATE), -1, 0);\n    test_assert(p != MAP_FAILED);\n    munmap(p + 3*page_size, page_size);\n\n    int ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p + page_size, page_size, \"abc\");\n    if (ret < 0 && errno == EINVAL) {\n      atomic_puts(\"PR_SET_VMA_ANON_NAME not supported, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    test_assert(ret == 0);\n\n    ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p + page_size, page_size*3, \"def\");\n    test_assert(ret == -1 && errno == ENOMEM);\n\n    ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p + page_size, page_size*3, \"$$$\");\n    test_assert(ret == -1 && errno == EINVAL);\n\n    ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p + page_size, page_size*3, \"\");\n    test_assert(ret == -1 && errno == ENOMEM);\n\n    ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p + page_size, page_size*2, NULL);\n    test_assert(ret == 0);\n\n    int fd = open(\"/proc/self/exe\", O_RDONLY);\n    test_assert(fd >= 0);\n    char* p2 = mmap(p + 3*page_size, page_size, PROT_READ, MAP_FIXED | MAP_PRIVATE, fd, 0);\n    test_assert(p2 != MAP_FAILED);\n    ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p, page_size*4, \"ghi\");\n    test_assert(ret == -1 && errno == EBADF);\n\n    char* p3 = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n        MAP_ANONYMOUS | (i ? MAP_SHARED : MAP_PRIVATE), -1, 0);\n    test_assert(p != MAP_FAILED);\n\n    ret = prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, p3, page_size, \"don't blow up\");\n    test_assert(ret == 0);\n    p3 = mremap(p3, page_size, 2*page_size, MREMAP_MAYMOVE);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_auxv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret, ret2;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char* p = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n      MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  ret = prctl(PR_GET_AUXV, 0, 1, 0, 0);\n  test_assert(ret < 0);\n  if (errno == EINVAL) {\n    atomic_puts(\"PR_GET_AUXV not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  if (errno != EFAULT) {\n    atomic_puts(\"PR_GET_AUXV returned unexpected error\");\n    return 77;\n  }\n\n  ret = prctl(PR_GET_AUXV, p, 1, 0, 0);\n  test_assert(ret > 0);\n\n  ret2 = prctl(PR_GET_AUXV, p, page_size, 0, 0);\n  test_assert(ret == ret2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_caps.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#include <linux/securebits.h>\n\nstatic void verify_caps(uint32_t caps) {\n  struct __user_cap_header_struct* hdr;\n  struct __user_cap_data_struct* data;\n  hdr = malloc(sizeof(*hdr));\n  hdr->version = _LINUX_CAPABILITY_VERSION_3;\n  hdr->pid = 0;\n  data = malloc(sizeof(*data) * 2);\n  test_assert(0 == syscall(SYS_capget, hdr, data));\n  test_assert(data[0].permitted == caps);\n  test_assert(data[1].permitted == 0);\n  free(hdr);\n  free(data);\n}\n\nstatic void raise_in_inheritable_set(uint32_t caps) {\n  struct __user_cap_header_struct* hdr;\n  struct __user_cap_data_struct* data;\n  hdr = malloc(sizeof(*hdr));\n  hdr->version = _LINUX_CAPABILITY_VERSION_3;\n  hdr->pid = 0;\n  data = malloc(sizeof(*data) * 2);\n  test_assert(0 == syscall(SYS_capget, hdr, data));\n  data[0].inheritable |= caps;\n  test_assert(0 == syscall(SYS_capset, hdr, data));\n}\n\nstatic void fork_exec_self(char* op) {\n  pid_t child;\n  int status;\n  if ((child = fork()) == 0) {\n    char* const argv[] = { \"/proc/self/exe\", op, NULL };\n    execve(\"/proc/self/exe\", argv, environ);\n    _exit(1);\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n}\n\nint main(int argc, char* argv[]) {\n  if (argc > 1) {\n    if (strcmp(argv[1], \"verify_only_admin\") == 0) {\n      verify_caps(((uint32_t)1) << CAP_SYS_ADMIN);\n      return 0;\n    } else if (strcmp(argv[1], \"verify_no_caps\") == 0) {\n      verify_caps(0);\n      return 0;\n    } else {\n      return 1;\n    }\n  }\n\n  if (-1 == try_setup_ns_no_root(CLONE_NEWUSER)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(1 == prctl(PR_CAPBSET_READ, CAP_SYS_ADMIN));\n\n  int ret = prctl(PR_GET_SECUREBITS);\n  test_assert(ret >= 0);\n  int err = prctl(PR_SET_SECUREBITS, ret | SECBIT_KEEP_CAPS);\n  test_assert(prctl(PR_GET_SECUREBITS) == (ret | SECBIT_KEEP_CAPS));\n  test_assert(err == 0);\n\n  err = prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_CLEAR_ALL, 0, 0, 0);\n  if (err == -1) {\n    // This is a rather new option, may not be available in all kernels\n    // we want to run on\n    test_assert(errno == EINVAL);\n  } else {\n    fork_exec_self(\"verify_no_caps\");\n    test_assert(\n        0 == prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_SYS_ADMIN, 0, 0));\n    raise_in_inheritable_set((uint32_t)1 << CAP_SYS_ADMIN);\n    test_assert(\n        0 == prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_SYS_ADMIN, 0, 0));\n    test_assert(\n        1 == prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_IS_SET, CAP_SYS_ADMIN, 0, 0));\n    fork_exec_self(\"verify_only_admin\");\n    test_assert(\n        0 == prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_LOWER, CAP_SYS_ADMIN, 0, 0));\n    fork_exec_self(\"verify_no_caps\");\n  }\n\n  test_assert(0 == prctl(PR_CAPBSET_DROP, CAP_SYS_ADMIN));\n  test_assert(0 == prctl(PR_CAPBSET_READ, CAP_SYS_ADMIN));\n\n  test_assert(0 == try_setup_ns(CLONE_NEWUSER));\n\n  test_assert(1 == prctl(PR_CAPBSET_READ, CAP_SYS_ADMIN));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_deathsig.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int grandchild_to_child_fds[2];\nstatic int grandchild_to_main_fds[2];\n\nstatic void handle_signal(int sig) {\n  test_assert(sig == SIGILL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  /* Signal main to go ahead and exit */\n  test_assert(1 == write(grandchild_to_main_fds[1], \"x\", 1));\n  exit(0);\n}\n\nstatic int run_grandchild(void) {\n  int sig = 99;\n\n  signal(SIGILL, handle_signal);\n\n  test_assert(0 == prctl(PR_SET_PDEATHSIG, SIGILL));\n  test_assert(0 == prctl(PR_GET_PDEATHSIG, (unsigned long)&sig));\n  test_assert(sig == SIGILL);\n\n  /* Signal child to go ahead and exit.\n     This will trigger our SIGILL handler. */\n  test_assert(1 == write(grandchild_to_child_fds[1], \"y\", 1));\n\n  sleep(1000000);\n  test_assert(0);\n  return 0;\n}\n\nstatic int run_child(void) {\n  char ch;\n  if (!fork()) {\n    return run_grandchild();\n  }\n  test_assert(1 == read(grandchild_to_child_fds[0], &ch, 1));\n  return 0;\n}\n\nint main(void) {\n  char ch;\n\n  test_assert(0 == pipe(grandchild_to_child_fds));\n  test_assert(0 == pipe(grandchild_to_main_fds));\n\n  if (!fork()) {\n    return run_child();\n  }\n  test_assert(1 == read(grandchild_to_main_fds[0], &ch, 1));\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_mdwe.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = prctl(PR_GET_MDWE, 0, 0, 0, 0);\n  if (ret == -1 && errno == EINVAL) {\n    atomic_puts(\"PR_GET_MDWE not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret >= 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_name.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Max name length is 16 bytes, *without* null terminator. */\n#define PRNAME_NUM_BYTES 16\n\nconst char* exe_image;\n\nconst char main_name[] = \"main\";\nconst char thread_name[] = \"thread\";\nconst char fork_child_name[] = \"fchild\";\nconst char exec_child_name[] = \"echild\";\n\nstatic void assert_prname_is(const char* tag, const char* name) {\n  char prname[PRNAME_NUM_BYTES] = \"\";\n  test_assert(0 == prctl(PR_GET_NAME, prname));\n\n  atomic_printf(\"%s: prname is '%s'; expecting '%s'\\n\", tag, prname, name);\n  test_assert(!strcmp(prname, name));\n}\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  pid_t child;\n\n  assert_prname_is(\"thread\", main_name);\n\n  prctl(PR_SET_NAME, thread_name);\n  assert_prname_is(\"thread\", thread_name);\n\n  if ((child = fork())) {\n    int status;\n\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n    assert_prname_is(\"thread\", thread_name);\n\n    return NULL;\n  }\n\n  assert_prname_is(\"fork child\", thread_name);\n\n  prctl(PR_SET_NAME, fork_child_name);\n  assert_prname_is(\"fork child\", fork_child_name);\n\n  execl(exe_image, exe_image, \"exec child\", NULL);\n  test_assert(\"Not reached\" && 0);\n\n  return NULL;\n}\n\nchar initial_name[PRNAME_NUM_BYTES] = \"\";\nstatic void compute_initial_name(const char* exe_image) {\n  const char* basename = strrchr(exe_image, '/');\n  if (basename) {\n    /* Eat the '/' character. */\n    ++basename;\n  } else {\n    /* Image path is already a basename. */\n    basename = exe_image;\n  }\n\n  atomic_printf(\"  (basename of exe path '%s' is '%s')\\n\", exe_image, basename);\n\n  strncpy(initial_name, basename, sizeof(initial_name) - 1);\n}\n\nint main(int argc, char* argv[]) {\n  pthread_t t;\n\n  exe_image = argv[0];\n  compute_initial_name(exe_image);\n\n  if (2 == argc) {\n    assert_prname_is(\"exec child\", initial_name);\n\n    prctl(PR_SET_NAME, exec_child_name);\n    assert_prname_is(\"exec child\", exec_child_name);\n    return 0;\n  }\n\n  assert_prname_is(\"main\", initial_name);\n\n  test_assert(-1 == prctl(PR_SET_NAME, NULL));\n  test_assert(EFAULT == errno);\n  assert_prname_is(\"main\", initial_name);\n\n  prctl(PR_SET_NAME, main_name);\n  assert_prname_is(\"main\", main_name);\n\n  test_assert(0 == pthread_create(&t, NULL, thread, NULL));\n  pthread_join(t, NULL);\n\n  assert_prname_is(\"main\", main_name);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_short_name.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Max name length is 16 bytes, *without* null terminator. */\n#define PRNAME_NUM_BYTES 16\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char* p = (char*)mmap(NULL, 2 * page_size, PROT_READ | PROT_WRITE,\n                        MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  char prname[PRNAME_NUM_BYTES] = \"\";\n\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p + page_size, page_size));\n  strcpy(p + page_size - 5, \"name\");\n  test_assert(0 == prctl(PR_SET_NAME, p + page_size - 5));\n\n  test_assert(0 == prctl(PR_GET_NAME, prname));\n  test_assert(!strcmp(prname, \"name\"));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_speculation_ctrl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0);\n\n  /* which path is taken here is out of our control */\n  if (ret == -1) {\n    test_assert(errno == EINVAL || errno == ENODEV);\n    test_assert(-1 == prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,\n                            PR_SPEC_ENABLE, 0, 0) &&\n                (errno == ENXIO || errno == EINVAL));\n  } else if (ret != PR_SPEC_NOT_AFFECTED) {\n    if (ret & PR_SPEC_PRCTL) {\n      if (ret & PR_SPEC_ENABLE) {\n        test_assert(0 == prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,\n                               PR_SPEC_DISABLE, 0, 0));\n        test_assert(\n            prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0) &\n            PR_SPEC_DISABLE);\n      } else if (ret & PR_SPEC_DISABLE) {\n        test_assert(0 == prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,\n                               PR_SPEC_ENABLE, 0, 0));\n        test_assert(\n            prctl(PR_GET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS, 0, 0, 0) &\n            PR_SPEC_ENABLE);\n      } else {\n        test_assert(ret & PR_SPEC_FORCE_DISABLE);\n        test_assert(-1 == prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,\n                                PR_SPEC_ENABLE, 0, 0) &&\n                    errno == EPERM);\n      }\n    } else if (ret & PR_SPEC_ENABLE) {\n      test_assert(-1 == prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,\n                              PR_SPEC_DISABLE, 0, 0) &&\n                  (errno == ENXIO || errno == EPERM));\n    } else {\n      test_assert(-1 == prctl(PR_SET_SPECULATION_CTRL, PR_SPEC_STORE_BYPASS,\n                              PR_SPEC_ENABLE, 0, 0) &&\n                  errno == ENXIO);\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prctl_tsc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void skip_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si, void* user) {\n  ucontext_t* ctx = (ucontext_t*)user;\n#if defined(__i386__)\n  ctx->uc_mcontext.gregs[REG_EIP] += 2;\n#elif defined(__x86_64__)\n  ctx->uc_mcontext.gregs[REG_RIP] += 2;\n#elif defined(__aarch64__)\n  ctx->uc_mcontext.pc += 4;\n#else\n#error unknown architecture\n#endif\n}\n\nstatic void print_handler(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nstatic void exit_handler(__attribute__((unused)) int sig) { exit(77); }\n\nint main(void) {\n  int status;\n  pid_t child;\n  struct sigaction sa;\n\n  test_assert(0 == prctl(PR_SET_TSC, PR_TSC_SIGSEGV));\n\n  sa.sa_sigaction = skip_handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  test_assert(0 == sigaction(SIGSEGV, &sa, NULL));\n\n  child = fork();\n  if (!child) {\n    test_assert(0 == prctl(PR_GET_TSC, &status));\n    test_assert(PR_TSC_SIGSEGV == status);\n    signal(SIGSEGV, exit_handler);\n    trigger_timer_counter_trap();\n    return 77;\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  signal(SIGSEGV, print_handler);\n  test_assert(0 == prctl(PR_GET_TSC, &status));\n  test_assert(PR_TSC_SIGSEGV == status);\n  trigger_timer_counter_trap();\n  return 1;\n}\n"
  },
  {
    "path": "src/test/prctl_tsc.run",
    "content": "source `dirname $0`/util.sh\nif ! prctl_tsc_supported; then\n  exit 77\nfi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/prctl_tsc_supported.c",
    "content": "#include <stdlib.h>\n#include <sys/prctl.h>\n\nint main(void) {\n  return prctl(PR_SET_TSC, PR_TSC_ENABLE) == 0 ? EXIT_SUCCESS : EXIT_FAILURE;\n}\n"
  },
  {
    "path": "src/test/priority.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int prio1, prio2;\n\n  prio1 = getpriority(PRIO_PROCESS, 0);\n  atomic_printf(\"Current process priority: %d\\n\", prio1);\n  if (prio1 < 19) {\n    /* If it's less than 19, we can decrease the\n     * priority. */\n    ++prio1;\n  }\n\n  setpriority(PRIO_PROCESS, 0, prio1);\n\n  prio2 = getpriority(PRIO_PROCESS, 0);\n  test_assert(prio1 == prio2);\n  atomic_printf(\"Now priority is: %d\\n\", prio2);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/priority.run",
    "content": "source `dirname $0`/util.sh\n# note: we use a value that is below the regular \"nice\" value\n#       of 10, allowing to run `nice ctest` as well\nrenice -n 11 $$ && record $TESTNAME\nrenice -n 22 $$ && replay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/privileged_net_ioctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\n#include <linux/route.h>\n#include <linux/rtnetlink.h>\n#include <linux/veth.h>\n\n/* Utilities for assembling rtnetlink packages */\nvoid buf_put(char** cur_buf_pos, void* data, size_t size) {\n  memcpy(*cur_buf_pos, data, size);\n  *cur_buf_pos += size;\n}\n\nvoid buf_put_attr_header(char** cur_buf_pos, uint16_t opt, size_t size) {\n  struct rtattr attr = {.rta_type = opt,\n                        .rta_len = size + sizeof(struct rtattr) };\n  buf_put(cur_buf_pos, &attr, sizeof(struct rtattr));\n}\n\nvoid buf_put_attr(char** cur_buf_pos, uint16_t opt, void* data, size_t size) {\n  buf_put_attr_header(cur_buf_pos, opt, size);\n  buf_put(cur_buf_pos, data, size);\n  *cur_buf_pos += RTA_ALIGN(size) - size;\n}\n\n#ifdef __ANDROID__\n#define htonl(x) __bswap_32(x)\n#endif\n\nint main(void) {\n  if (-1 == try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  int fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_ROUTE);\n  int inetfd = socket(AF_INET, SOCK_DGRAM, 0);\n  struct iovec iov;\n  struct sockaddr_nl kernel_addr;\n  memset(&kernel_addr, 0, sizeof(struct sockaddr_nl));\n  kernel_addr.nl_family = AF_NETLINK;\n  struct msghdr hdr = {.msg_name = &kernel_addr,\n                       .msg_namelen = sizeof(struct sockaddr_nl),\n                       .msg_iov = &iov,\n                       .msg_iovlen = 1,\n                       .msg_control = 0,\n                       .msg_controllen = 0,\n                       .msg_flags = 0 };\n  char* cur_buf_p;\n  char** cur_buf_pos = &cur_buf_p;\n  char* bridge_name = \"rrbridge0\";\n  char* iface0_name = \"rreth0\";\n  char* iface1_name = \"rreth1\";\n\n  // Create some interfaces to play with. This is the equivalent of:\n  // sudo ip link add rreth0 type veth peer name rreth1\n  {\n    char* interface_kind = \"veth\";\n\n    ssize_t total_encoded_size =\n        5 * sizeof(struct rtattr) + sizeof(struct ifinfomsg) +\n        RTA_ALIGN(strlen(interface_kind)) + RTA_ALIGN(strlen(iface1_name) + 1);\n\n    ssize_t msg_len = sizeof(struct nlmsghdr) + sizeof(struct ifinfomsg) +\n                      sizeof(struct rtattr) +\n                      RTA_ALIGN(strlen(iface0_name) + 1) + total_encoded_size;\n\n    struct nlmsghdr nlhdr;\n    memset(&nlhdr, 0, sizeof(struct nlmsghdr));\n    nlhdr.nlmsg_type = RTM_NEWLINK;\n    nlhdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST | NLM_F_ACK | NLM_F_EXCL;\n    nlhdr.nlmsg_len = msg_len;\n    nlhdr.nlmsg_seq = 1;\n    // Reply here please\n    nlhdr.nlmsg_pid = getpid();\n    struct ifinfomsg msg;\n    memset(&msg, 0, sizeof(struct ifinfomsg));\n    char* buf = malloc(msg_len);\n    cur_buf_p = buf;\n    buf_put(cur_buf_pos, &nlhdr, sizeof(nlhdr));\n    buf_put(cur_buf_pos, &msg, sizeof(msg));\n    buf_put_attr(cur_buf_pos, IFLA_IFNAME, iface0_name,\n                 strlen(iface0_name) + 1);\n\n    buf_put_attr_header(cur_buf_pos, IFLA_LINKINFO, total_encoded_size - 4);\n    buf_put_attr(cur_buf_pos, IFLA_INFO_KIND, interface_kind,\n                 strlen(interface_kind));\n    buf_put_attr_header(cur_buf_pos, IFLA_INFO_DATA, total_encoded_size - 16);\n    buf_put_attr_header(cur_buf_pos, VETH_INFO_PEER, total_encoded_size - 20);\n    buf_put(cur_buf_pos, &msg, sizeof(msg));\n    buf_put_attr(cur_buf_pos, IFLA_IFNAME, iface1_name,\n                 strlen(iface1_name) + 1);\n    iov.iov_base = buf;\n    iov.iov_len = msg_len;\n    test_assert(msg_len == sendmsg(fd, &hdr, 0));\n    test_assert(-1 != recvmsg(fd, &hdr, 0));\n    errno = -((struct nlmsgerr*)&(((struct nlmsghdr*)buf)[1]))->error;\n    if (((struct nlmsghdr*)buf)->nlmsg_type == NLMSG_ERROR) {\n      if (errno == ENOTSUP) {\n        atomic_puts(\"Skipping test because veth device creation\\n\"\n                    \"is not supported by this kernel.\");\n        atomic_puts(\"EXIT-SUCCESS\");\n        return 0;\n      }\n      test_assert(errno == 0);\n    }\n    free(buf);\n  }\n\n  // sudo ifconfig rreth0 0.0.0.0\n  {\n    struct ifreq req;\n    memcpy(&req.ifr_name, iface0_name, strlen(iface0_name) + 1);\n    memset(&req.ifr_addr, 0, sizeof(req.ifr_addr));\n    req.ifr_addr.sa_family = AF_INET;\n    test_assert(0 == ioctl(inetfd, SIOCSIFADDR, &req));\n    test_assert(0 == ioctl(inetfd, SIOCGIFFLAGS, &req));\n    req.ifr_flags |= IFF_UP | IFF_RUNNING;\n    test_assert(0 == ioctl(inetfd, SIOCSIFFLAGS, &req));\n  }\n\n  // sudo brctl addbr rrbridge0\n  {\n    char buf[IFNAMSIZ];\n    strncpy(buf, bridge_name, sizeof(buf));\n    test_assert(0 == ioctl(inetfd, SIOCBRADDBR, buf));\n  }\n\n  // sudo brctl addif rrbridge0 rreth0\n  {\n    struct ifreq req;\n    // Get index by name\n    memcpy(&req.ifr_name, iface0_name, strlen(iface0_name) + 1);\n    test_assert(0 == ioctl(inetfd, SIOCGIFINDEX, &req));\n\n    // Add to bridge\n    memcpy(&req.ifr_name, bridge_name, strlen(bridge_name) + 1);\n    test_assert(0 == ioctl(inetfd, SIOCBRADDIF, &req));\n  }\n\n  // sudo ifconfig rreth0 10.0.0.2/24\n  {\n    uint32_t host = htonl((uint32_t)10 << 24 | 0x2);\n    uint32_t netmask = htonl(0xffffff00);\n\n    struct ifreq req;\n    memcpy(&req.ifr_name, iface1_name, strlen(iface1_name) + 1);\n    req.ifr_addr.sa_family = AF_INET;\n    memcpy(&((struct sockaddr_in*)&req.ifr_addr)->sin_addr, &host,\n           sizeof(uint32_t));\n    test_assert(0 == ioctl(inetfd, SIOCSIFADDR, &req));\n    memcpy(&((struct sockaddr_in*)&req.ifr_netmask)->sin_addr, &netmask,\n           sizeof(uint32_t));\n    test_assert(0 == ioctl(inetfd, SIOCSIFNETMASK, &req));\n    test_assert(0 == ioctl(inetfd, SIOCGIFFLAGS, &req));\n    req.ifr_flags |= IFF_UP | IFF_RUNNING;\n    test_assert(0 == ioctl(inetfd, SIOCSIFFLAGS, &req));\n  }\n\n  // That will be our default gateway:\n  // route add default gw 10.0.0.2\n  {\n    struct rtentry rm;\n    uint32_t gateway = htonl((uint32_t)10 << 24 | 0x2);\n    memset(&rm, 0, sizeof(struct rtentry));\n    rm.rt_dst.sa_family = rm.rt_genmask.sa_family = rm.rt_gateway.sa_family =\n        AF_INET;\n    rm.rt_flags |= RTF_GATEWAY;\n    memcpy(&((struct sockaddr_in*)&rm.rt_gateway)->sin_addr, &gateway,\n           sizeof(uint32_t));\n    test_assert(0 == ioctl(inetfd, SIOCADDRT, &rm));\n    /* Maybe try to delete it again */\n    test_assert(0 == ioctl(inetfd, SIOCDELRT, &rm));\n  }\n\n  // sudo brctl delif rrbridge0 rreth0\n  {\n    struct ifreq req;\n    // Get index by name\n    memcpy(&req.ifr_name, iface0_name, strlen(iface0_name) + 1);\n    test_assert(0 == ioctl(inetfd, SIOCGIFINDEX, &req));\n\n    // Remove from bridge\n    memcpy(&req.ifr_name, bridge_name, strlen(bridge_name) + 1);\n    test_assert(0 == ioctl(inetfd, SIOCBRDELIF, &req));\n  }\n\n  // sudo brctl delbr rrbridge0\n  {\n    char buf[IFNAMSIZ];\n    strncpy(buf, bridge_name, sizeof(buf));\n    test_assert(0 == ioctl(inetfd, SIOCBRDELBR, buf));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/proc_fds.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <dirent.h>\n#include <unistd.h>\n\nstatic pthread_barrier_t bar;\nstatic const char proc_fd_path[] = \"/proc/self/fd\";\n\nstatic void* thread_func(__attribute__((unused)) void* name) {\n  pthread_barrier_wait(&bar);\n  sleep(1);\n  return NULL;\n}\n\nstatic void close_upper_fds(void) {\n  DIR* dir = opendir(proc_fd_path);\n  struct dirent* ent;\n  int fd;\n\n  test_assert(dir != NULL);\n  while ((ent = readdir(dir)) != NULL) {\n    fd = atoi(ent->d_name);\n    if (fd > 2) {\n      close(fd);\n    }\n  }\n  closedir(dir);\n}\n\nint opener(void) {\n  const char proc_fd_path[] = \"/proc/self/fd\";\n  int fd = syscall(SYS_openat, -1, proc_fd_path, O_DIRECTORY);\n  test_assert(fd >= 0);\n  return fd;\n}\n\nint opener_task_tid(void) {\n  char buf[1024];\n  int dir_fd = open(\"/proc/self\", O_PATH);\n  test_assert(dir_fd >= 0);\n  sprintf(buf, \"task/%d/fd\", sys_gettid());\n  int fd = syscall(SYS_openat, dir_fd, buf, O_DIRECTORY);\n  test_assert(fd >= 0);\n  return fd;\n}\n\nvoid do_test(int (*opener)(void)) {\n  // Empirically tested to be enough to make ProcFdDirMonitor\n  // repeat the getdents call.\n  const int NUM_THREADS = 20;\n  int i;\n\n  // Close any non-stdio fds inherited from the environment\n  close_upper_fds();\n\n  for (i = 0; i < 15; i++) {\n    dup(2);\n  }\n\n  close(RR_MAGIC_SAVE_DATA_FD);\n\n  /* init barrier */\n  pthread_barrier_init(&bar, NULL, NUM_THREADS + 1);\n  /* Create independent threads each of which will execute\n   * function */\n  for (i = 0; i < NUM_THREADS; i++) {\n    pthread_t thread;\n    pthread_create(&thread, NULL, thread_func, NULL);\n  }\n\n  pthread_barrier_wait(&bar);\n\n  int fd = opener();\n\n  char buf[128];\n  char* current;\n  int bytes;\n  while ((bytes = syscall(SYS_getdents64, fd, &buf, sizeof(buf)))) {\n    current = buf;\n    while (current != buf + bytes) {\n      struct dirent64* ent = (struct dirent64*)current;\n      char* end;\n      int fd = strtol(ent->d_name, &end, 10);\n      if (!*end) {\n        test_assert(fd < 20); // Other fds should be cloaked!\n      }\n      current += ent->d_reclen;\n    }\n  }\n}\n\nint main(void) {\n  do_test(opener);\n  do_test(opener_task_tid);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/proc_maps.py",
    "content": "from util import *\nimport re\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('info proc mappings')\nexpect_gdb('\\[vdso\\]')\n\nok()\n"
  },
  {
    "path": "src/test/proc_maps.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only proc_maps\n"
  },
  {
    "path": "src/test/proc_mem.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int cookie1;\nstatic int cookie2;\nstatic int cookie3;\n\nstatic int COOKIE = 0x12345678;\n\nstatic int do_openat(int child) {\n  char buf[1024];\n  int fd;\n  int dir_fd = open(\"/proc\", O_PATH);\n  test_assert(dir_fd >= 0);\n  sprintf(buf, \"%d/mem\", child);\n  fd = openat(dir_fd, buf, O_RDWR);\n  close(dir_fd);\n  return fd;\n}\n\nstatic int do_openat_task_tid(int child) {\n  char buf[1024];\n  int fd;\n  int dir_fd = open(\"/proc\", O_PATH);\n  test_assert(dir_fd >= 0);\n  sprintf(buf, \"%d/task/%d/mem\", child, child);\n  fd = openat(dir_fd, buf, O_RDWR);\n  close(dir_fd);\n  return fd;\n}\n\nstatic int do_openat_task_tid2(int child) {\n  char buf[1024];\n  int fd;\n  sprintf(buf, \"/proc/%d/task\", child);\n  int dir_fd = open(buf, O_PATH);\n  test_assert(dir_fd >= 0);\n  sprintf(buf, \"%d/mem\", child);\n  fd = openat(dir_fd, buf, O_RDWR);\n  close(dir_fd);\n  return fd;\n}\n\nstatic int do_open(int child) {\n  char buf[1024];\n  sprintf(buf, \"/proc/%d/mem\", child);\n  return open(buf, O_RDWR);\n}\n\nstatic int do_open_task_tid(int child) {\n  char buf[1024];\n  sprintf(buf, \"/proc/%d/task/%d/mem\", child, child);\n  return open(buf, O_RDWR);\n}\n\nstatic int do_cmsg_generic(int (*opener)(int), int child, int use_recvmmsg) {\n  int fd = opener(child);\n  /* launder it through SCM_RIGHTS */\n  char ch = 0;\n  struct mmsghdr msgvec;\n  struct msghdr* msg = &msgvec.msg_hdr;\n  struct iovec iov;\n  uint8_t cbuf[CMSG_SPACE(sizeof(fd))];\n  struct cmsghdr* cmsg;\n  int sockfds[2];\n\n  test_assert(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds));\n\n  iov.iov_base = \"x\";\n  iov.iov_len = 1;\n  memset(msg, 0, sizeof(*msg));\n  msg->msg_iov = &iov;\n  msg->msg_iovlen = 1;\n  msg->msg_control = cbuf;\n  msg->msg_controllen = sizeof(cbuf);\n  cmsg = CMSG_FIRSTHDR(msg);\n  cmsg->cmsg_level = SOL_SOCKET;\n  cmsg->cmsg_type = SCM_RIGHTS;\n  cmsg->cmsg_len = CMSG_LEN(sizeof(fd));\n  memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));\n  test_assert(1 == sendmsg(sockfds[1], msg, 0));\n\n  iov.iov_base = &ch;\n  if (use_recvmmsg) {\n    test_assert(1 == recvmmsg(sockfds[0], &msgvec, 1, 0, NULL));\n    test_assert(1 == msgvec.msg_len);\n  } else {\n    test_assert(1 == recvmsg(sockfds[0], msg, 0));\n  }\n  test_assert('x' == ch);\n  cmsg = CMSG_FIRSTHDR(msg);\n  test_assert(SOL_SOCKET == cmsg->cmsg_level && SCM_RIGHTS == cmsg->cmsg_type);\n  memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));\n  close(sockfds[0]);\n  close(sockfds[1]);\n  return fd;\n}\n\nstatic int do_cmsg(int child) { return do_cmsg_generic(do_open, child, 0); }\nstatic int do_cmsg_open_task_tid(int child) { return do_cmsg_generic(do_open_task_tid, child, 0); }\nstatic int do_cmsg_openat(int child) { return do_cmsg_generic(do_openat, child, 0); }\nstatic int do_cmsg_openat_task_tid(int child) { return do_cmsg_generic(do_openat_task_tid, child, 0); }\nstatic int do_cmsg_openat_task_tid2(int child) { return do_cmsg_generic(do_openat_task_tid2, child, 0); }\n\nstatic int do_cmsg_recvmmsg(int child) { return do_cmsg_generic(do_open, child, 1); }\nstatic int do_cmsg_recvmmsg_open_task_tid(int child) { return do_cmsg_generic(do_open_task_tid, child, 1); }\nstatic int do_cmsg_recvmmsg_openat(int child) { return do_cmsg_generic(do_openat, child, 1); }\nstatic int do_cmsg_recvmmsg_openat_task_tid(int child) { return do_cmsg_generic(do_openat_task_tid, child, 1); }\nstatic int do_cmsg_recvmmsg_openat_task_tid2(int child) { return do_cmsg_generic(do_openat_task_tid2, child, 1); }\n\nstatic void do_test(int (*opener)(int)) {\n  pid_t child;\n  int fd;\n  int status;\n  int pipe_fds[2];\n  struct iovec iov[2];\n\n  test_assert(0 == pipe(pipe_fds));\n\n  child = fork();\n  if (!child) {\n    char ch;\n    test_assert(1 == read(pipe_fds[0], &ch, 1));\n    test_assert(COOKIE == cookie1);\n    test_assert(COOKIE == cookie2);\n    test_assert(COOKIE == cookie3);\n    exit(77);\n  }\n\n  fd = opener(child);\n  test_assert(fd >= 0);\n  test_assert(sizeof(COOKIE) ==\n              pwrite(fd, &COOKIE, sizeof(COOKIE), (uintptr_t)&cookie1));\n\n  iov[0].iov_base = (char*)&COOKIE;\n  iov[0].iov_len = 2;\n  iov[1].iov_base = (char*)&COOKIE + 2;\n  iov[1].iov_len = 2;\n  test_assert(sizeof(COOKIE) == pwritev(fd, iov, 2, (uintptr_t)&cookie2));\n\n  lseek(fd, (uintptr_t)&cookie3, SEEK_SET);\n  test_assert(sizeof(COOKIE) == write(fd, &COOKIE, sizeof(COOKIE)));\n\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n}\n\nint main(void) {\n  do_test(do_open);\n  do_test(do_open_task_tid);\n  do_test(do_openat);\n  do_test(do_openat_task_tid);\n  do_test(do_openat_task_tid2);\n  do_test(do_cmsg);\n  do_test(do_cmsg_open_task_tid);\n  do_test(do_cmsg_openat);\n  do_test(do_cmsg_openat_task_tid);\n  do_test(do_cmsg_openat_task_tid2);\n  do_test(do_cmsg_recvmmsg);\n  do_test(do_cmsg_recvmmsg_open_task_tid);\n  do_test(do_cmsg_recvmmsg_openat);\n  do_test(do_cmsg_recvmmsg_openat_task_tid);\n  do_test(do_cmsg_recvmmsg_openat_task_tid2);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/protect_rr_fds.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define MAX_FDS 2048\n\nint main(int argc, char* argv[]) {\n  pid_t child;\n  int status;\n  int ret;\n  int fd;\n  int pipe_fds[2];\n  struct rlimit nofile;\n  int fd_limit;\n\n  if (argc == 2) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  /* Various spawning APIs try to close all open file descriptors before\n     exec --- via direct close(), or by setting CLOEXEC. Check that\n     those don't interfere with rr by closing one of our essential\n     file descriptors. */\n  test_assert(0 == getrlimit(RLIMIT_NOFILE, &nofile));\n  if (nofile.rlim_cur == RLIM_INFINITY || nofile.rlim_cur > MAX_FDS) {\n    fd_limit = MAX_FDS;\n  } else {\n    fd_limit = nofile.rlim_cur;\n  }\n  for (fd = STDERR_FILENO + 1; fd < fd_limit; ++fd) {\n    ret = fcntl(fd, F_SETFD, FD_CLOEXEC);\n    test_assert(ret == 0 || (ret == -1 && errno == EBADF));\n    ret = dup2(STDERR_FILENO, fd);\n    test_assert(ret == fd || (ret == -1 && errno == EBADF));\n    ret = dup3(STDERR_FILENO, fd, O_CLOEXEC);\n    test_assert(ret == fd || (ret == -1 && errno == EBADF));\n    ret = close(fd);\n    test_assert(ret == 0 || (ret == -1 && errno == EBADF));\n  }\n\n  /* Check that syscall buffering still works */\n  test_assert(0 == pipe(pipe_fds));\n  test_assert(1 == write(pipe_fds[1], \"c\", 1));\n\n  if (0 == (child = fork())) {\n    execl(argv[0], argv[0], \"step2\", NULL);\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/prw.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"prw.txt\", O_CREAT | O_RDWR, 0600);\n  const char content[] = \"01234567890\\nhello there\\n\";\n  char buf[sizeof(content)];\n  ssize_t nr;\n\n  memset(buf, '?', sizeof(buf));\n  nr = write(fd, buf, sizeof(buf));\n  test_assert(nr == sizeof(buf));\n  nr = write(fd, buf, 10);\n  test_assert(nr == 10);\n\n  nr = pwrite(fd, content, sizeof(content), 10);\n  test_assert(nr == sizeof(content));\n  atomic_printf(\"Wrote ```%s'''\\n\", content);\n\n  nr = pread(fd, buf, sizeof(buf), 10);\n  test_assert(nr == sizeof(content));\n  atomic_printf(\"Read ```%s'''\\n\", buf);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pthread_condvar_locking.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pthread_cond_t condvar = PTHREAD_COND_INITIALIZER;\nstatic pthread_mutex_t mutex;\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n    pthread_mutex_lock(&mutex);\n    pthread_cond_signal(&condvar);\n    pthread_mutex_unlock(&mutex);\n  }\n  return NULL;\n}\n\nint main(void) {\n  pthread_mutexattr_t attr;\n  pthread_t thread;\n\n  pthread_mutexattr_init(&attr);\n  pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);\n  pthread_mutex_init(&mutex, &attr);\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n\n  pthread_mutex_lock(&mutex);\n  pthread_cond_wait(&condvar, &mutex);\n  pthread_cond_wait(&condvar, &mutex);\n  pthread_mutex_unlock(&mutex);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pthread_mutex_timedlock.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pthread_mutexattr_t attr;\n  pthread_mutex_t mutex;\n  struct timespec abstime = {0,0};\n\n  pthread_mutexattr_init(&attr);\n  pthread_mutex_init(&mutex, &attr);\n\n  pthread_mutex_timedlock(&mutex, &abstime);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pthread_pi_mutex.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pthread_mutexattr_t attr;\n  pthread_mutex_t mutex;\n\n  test_assert(pthread_mutexattr_init(&attr) == 0);\n  test_assert(pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT) == 0);\n  test_assert(pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) == 0);\n  test_assert(pthread_mutex_init(&mutex, &attr) == 0);\n  test_assert(pthread_mutex_destroy(&mutex) == 0);\n  test_assert(pthread_mutexattr_destroy(&attr) == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/pthread_rwlocks.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pthread_rwlock_t lock = PTHREAD_RWLOCK_INITIALIZER;\n\nstatic int pipe_fds[2];\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  pthread_rwlock_rdlock(&lock);\n  pthread_rwlock_unlock(&lock);\n\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n\n  pthread_rwlock_wrlock(&lock);\n  pthread_rwlock_unlock(&lock);\n\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  char ch;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  pthread_rwlock_rdlock(&lock);\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  pthread_rwlock_unlock(&lock);\n\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_attach_null_status.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  struct timespec ts = { 0, 50000000 };\n\n  if (0 == (child = fork())) {\n    sleep(1000000);\n    return 77;\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, NULL, 0));\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_attach_running.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct timespec ts = { 0, 50000000 };\n\n  if (0 == (child = fork())) {\n    while (1) {\n      asm(\"\" : : : \"memory\");\n    }\n    return 77;\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_attach_sleeping.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct timespec ts = { 0, 50000000 };\n\n  if (0 == (child = fork())) {\n    sleep(1000000);\n    return 77;\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_attach_stopped.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct timespec ts = { 0, 50000000 };\n\n  if (0 == (child = fork())) {\n    kill(getpid(), SIGSTOP);\n    return 77;\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_attach_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int parent_to_child_fds[2];\n\nint main(void) {\n  pid_t child;\n  int status;\n  int ret = pipe(parent_to_child_fds);\n  test_assert(ret == 0);\n\n  if (0 == (child = fork())) {\n    char ch;\n    read(parent_to_child_fds[0], &ch, 1);\n    return 77;\n  }\n\n  struct timespec ts = { 0, 50000000 };\n  nanosleep(&ts, NULL);\n\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  write(parent_to_child_fds[1], \"x\", 1);\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_attach_thread_running.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic void* child_thread(__attribute__((unused)) void* p) {\n  char ch;\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n  test_assert(ch == 'K');\n  exit(77);\n  return NULL;\n}\n\nstatic void* child_thread_running(__attribute__((unused)) void* p) {\n  while (1) {\n    asm(\"\" : : : \"memory\");\n  }\n  return NULL;\n}\n\nstatic void run_child(void) {\n  pthread_t t;\n\n  pthread_create(&t, NULL, child_thread, NULL);\n  /* try to get the kernel to deliver signals sent to our pid to some\n     other thread */\n  pthread_create(&t, NULL, child_thread_running, NULL);\n  pause();\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct timespec ts = { 0, 50000000 };\n\n  test_assert(0 == pipe(pipe_fds));\n\n  if (0 == (child = fork())) {\n    run_child();\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(1 == write(pipe_fds[1], \"K\", 1));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_breakpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic void breakpoint(void) {}\n\n#if defined(__i386__) || defined(__x86_64__)\nchar breakpoint_instruction[] = { 0xcc };\nint ip_after_breakpoint = 1;\n#elif defined(__aarch64__)\nchar breakpoint_instruction[] = { 0x0, 0x0, 0x20, 0xd4 };\nint ip_after_breakpoint = 0;\n#else\n#error Unknown architecture\n#endif\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct user_regs_struct regs;\n  int pipe_fds[2];\n  int mem_fd;\n  char buf[1024];\n  char saved_bytes[sizeof(breakpoint_instruction)];\n  ssize_t bkpt_size = sizeof(breakpoint_instruction);\n\n  test_assert(0 == pipe(pipe_fds));\n\n  if (0 == (child = fork())) {\n    char ch;\n    read(pipe_fds[0], &ch, 1);\n    breakpoint();\n    return 77;\n  }\n\n  sprintf(buf, \"/proc/%d/mem\", child);\n  mem_fd = open(buf, O_RDWR);\n  test_assert(mem_fd >= 0);\n\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(bkpt_size ==\n    pread(mem_fd, saved_bytes, bkpt_size, (uintptr_t)breakpoint));\n  test_assert(bkpt_size ==\n    pwrite(mem_fd, breakpoint_instruction, bkpt_size, (uintptr_t)breakpoint));\n\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  ptrace_getregs(child, &regs);\n  test_assert((char*)regs.IP == (char*)breakpoint + ip_after_breakpoint ? bkpt_size : 0);\n\n  test_assert(bkpt_size == pwrite(mem_fd, saved_bytes, bkpt_size, (uintptr_t)breakpoint));\n  if (ip_after_breakpoint) {\n    regs.IP -= bkpt_size;\n  }\n  ptrace_setregs(child, &regs);\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status));\n  test_assert(WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_change_patched_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic int parent_to_child_fds[2];\nstatic int child_to_parent_fds[2];\n\nint main(void) {\n  pid_t child;\n  char ch;\n  int status;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n  test_assert(0 == pipe(child_to_parent_fds));\n\n  if (0 == (child = fork())) {\n    // Give the Monkeypatcher a chance to patch both the\n    // read and write syscalls\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    test_assert(1 == write(child_to_parent_fds[1], \"x\", 1));\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    raise(SIGSTOP);\n    // We will change the following read to a write\n    ch = 'y';\n    test_assert(1 == read(child_to_parent_fds[1], &ch, 1));\n    return 0;\n  }\n  /* Make sure child is still running */\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n  test_assert(1 == read(child_to_parent_fds[0], &ch, 1));\n\n  test_assert(0 ==\n              ptrace(PTRACE_SEIZE, child, NULL, (void*)PTRACE_O_TRACESYSGOOD));\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  /* Wait until it's stopped */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  for (;;) {\n    /* Step to syscall entry */\n    test_assert(0 == ptrace(PTRACE_SYSCALL, child, 0, 0));\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WSTOPSIG(status) == (SIGTRAP | 0x80));\n\n    /* Change the system call number once we get to the right one */\n    struct user_regs_struct regs;\n    ptrace_getregs(child, &regs);\n    if (regs.ORIG_SYSCALLNO == SYS_read) {\n      ptrace_change_syscall(child, &regs, SYS_write);\n      break;\n    }\n\n    /* Step to syscall exit */\n    test_assert(0 == ptrace(PTRACE_SYSCALL, child, 0, 0));\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WSTOPSIG(status) == (SIGTRAP | 0x80));\n  }\n\n  /* Continue the tracee and check that we're receiving a write */\n  test_assert(0 == ptrace(PTRACE_CONT, child, 0, 0));\n  test_assert(1 == read(child_to_parent_fds[0], &ch, 1));\n  test_assert(ch == 'y');\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_exec.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic size_t read_all(int fd, char* buf, size_t size) {\n  size_t total = 0;\n  while (size > 0) {\n    ssize_t ret = read(fd, buf, size);\n    test_assert(ret >= 0);\n    if (ret == 0) {\n      return total;\n    }\n    size -= ret;\n    buf += ret;\n    total += ret;\n  }\n  return total;\n}\n\nstatic int proc_num_args(pid_t pid) {\n  char buf[4096];\n  int fd;\n  int i = 0;\n  int count = 0;\n\n  sprintf(buf, \"/proc/%d/cmdline\", pid);\n  fd = open(buf, O_RDONLY);\n  test_assert(fd >= 0);\n\n  size_t bytes = read_all(fd, buf, sizeof(buf));\n  // The kernel is supposed to append a zero-length string after all other\n  // command-line parameters, but it doesn't.\n  while ((size_t)i < bytes) {\n    ++count;\n    i += strlen(buf + i) + 1;\n  }\n  test_assert(0 == close(fd));\n  return count;\n}\n\nvoid run_test(char** argv, int use_traceexec, int syscall_step)\n{\n  pid_t child;\n  int status;\n  struct user_regs_struct regs;\n\n  if (0 == (child = fork())) {\n    char* args[] = { argv[0], \"hello\", NULL };\n    kill(getpid(), SIGSTOP);\n    execve(argv[0], args, environ);\n    /* should never reach here */\n    test_assert(0);\n    return;\n  }\n\n  test_assert(proc_num_args(child) == 1);\n  if (use_traceexec)\n    test_assert(0 == ptrace(PTRACE_SEIZE, child, NULL, (void*)PTRACE_O_TRACEEXEC));\n  else\n    test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL,\n      (void*)PTRACE_O_TRACEEXEC));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  if (syscall_step) {\n    while (1) {\n      test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n      test_assert(child == waitpid(child, &status, 0));\n      if (!(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP) &&\n          !(status == ((SIGTRAP << 8) | 0x7f)))\n        break;\n    }\n  } else {\n    while (1) {\n      test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n      test_assert(child == waitpid(child, &status, 0));\n      if (!(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP))\n        break;\n    }\n  }\n\n  if (use_traceexec)\n    test_assert(status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8)));\n  else\n    test_assert(status == ((SIGTRAP << 8) | 0x7f));\n\n  ptrace_getregs(child, &regs);\n#if !defined(__aarch64__)\n  // On aarch64, we may only ask this in a syscall-entry stop, which this is not\n  test_assert(SYS_execve == regs.ORIG_SYSCALLNO);\n#endif\n  if (!use_traceexec)\n    test_assert(0 == regs.SYSCALL_RESULT);\n  /* Check that we have actually transitioned */\n  test_assert(proc_num_args(child) == 2);\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n}\n\nint main(int argc, char** argv) {\n  test_assert(proc_num_args(getpid()) == argc);\n\n  if (argc == 2) {\n    return 77;\n  }\n\n  /* Test that PTRACE_ATTACH produces a raw SIGTRAP after exiting exec, when\n    PTRACE_O_TRACEEXEC is not used. */\n  run_test(argv, 0, 0);\n  /* Test that rr doesn't mind exec stops and syscall exit stops both happening */\n  run_test(argv, 1, 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_group_stop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic void* do_thread(void* arg) {\n  int pipe_fd = *(int*)arg;\n  uint32_t tid = sys_gettid();\n\n  write(pipe_fd, &tid, 4);\n  /* Sleep long enough that it will be noticed if it's not interrupted. */\n  sleep(1000);\n\n  return NULL;\n}\n\nint main(void) {\n  pid_t child, child2;\n  uint32_t msg;\n  int status;\n  int pipe_fds[2];\n  struct user_regs_struct regs;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  if (0 == (child = fork())) {\n    pthread_t t;\n\n    pthread_create(&t, NULL, do_thread, &pipe_fds[1]);\n    pthread_join(t, NULL);\n\n    return 77;\n  }\n\n  test_assert(4 == read(pipe_fds[0], &msg, 4));\n  child2 = (pid_t)msg;\n  close(pipe_fds[0]);\n  sched_yield();\n\n  /* Hit the entire process group with a SIGSTOP. */\n  tgkill(child, child, SIGSTOP);\n\n  /* Force the rr scheduler to run. */\n  sched_yield();\n\n  /* Now seize the stopped task. */\n  test_assert(0 == ptrace(PTRACE_SEIZE, child2, 0, 0));\n  test_assert(child2 == waitpid(child2, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  /* Do something that requires the task to be stopped. */\n  ptrace_getregs(child2, &regs);\n\n  /* Verify that we can resume from group stops. */\n  test_assert(0 == ptrace(PTRACE_CONT, child2, 0, 0));\n  /* Force the rr scheduler to run. */\n  sched_yield();\n  test_assert(0 == ptrace(PTRACE_INTERRUPT, child2, 0, 0));\n  test_assert(child2 == waitpid(child2, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_kill_grandtracee.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef PTRACE_EVENT_STOP\n#define PTRACE_EVENT_STOP 128\n#endif\n\nstatic int parent_to_child_fds[2];\n\nint main(void) {\n  pid_t child;\n  char ch;\n  int status;\n  unsigned long cloned_pid;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n\n  if (0 == (child = fork())) {\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n\n    if (fork()) {\n      return 77;\n    } else {\n      return 66;\n    }\n  }\n\n  test_assert(0 == ptrace(PTRACE_SEIZE, child, NULL,\n                          (void*)PTRACE_O_TRACEFORK));\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  test_assert(child == waitpid(child, &status, 0));\n  /* Test that PTRACE_EVENT_FORK is generated and that we are tracing the\n     grandchild. */\n  test_assert(status == ((PTRACE_EVENT_FORK << 16) | (SIGTRAP << 8) | 0x7f));\n  test_assert(0 == ptrace(PTRACE_GETEVENTMSG, child, NULL, &cloned_pid));\n  test_assert((pid_t)cloned_pid == waitpid(cloned_pid, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);\n  test_assert((status >> 16) == PTRACE_EVENT_STOP);\n  test_assert(0 == kill(cloned_pid, SIGKILL));\n\n  test_assert((pid_t)cloned_pid == waitpid(cloned_pid, &status, 0));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGKILL);\n\n  /* Test that the child observes a SIGCHLD from the grandchild's exit. */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGCHLD);\n\n  /* Test that the child exits OK. */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_remote_unmap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <ctype.h>\n\n#define RR_PAGE_ADDR 0x70000000\n\nlong checked_ptrace(int request, pid_t pid, void* addr,\n                    void* data) {\n  long ret = ptrace(request, pid, addr, data);\n  test_assert(ret != -1);\n  return ret;\n}\n\nextern char syscall_addr __attribute__ ((visibility (\"hidden\")));\nuintptr_t child_syscall_addr;\nstatic __attribute__((noinline, used)) void my_syscall(void) {\n#if defined(__i386)\n  __asm__ __volatile__(\"syscall_addr: int $0x80\\n\\t\");\n#elif defined(__x86_64__)\n  __asm__ __volatile__(\"syscall_addr: syscall\\n\\t\");\n#elif defined(__aarch64__)\n  __asm__ __volatile__(\"syscall_addr: svc #0\\n\\tbrk #0\\n\\t\");\n#endif\n}\n\nvoid munmap_remote(pid_t child, uintptr_t start, size_t size) {\n  struct user_regs_struct regs;\n  struct iovec iov;\n  int status;\n  pid_t wret;\n  iov.iov_base = &regs;\n  iov.iov_len = sizeof(regs);\n  checked_ptrace(PTRACE_GETREGSET, child, (void*)NT_PRSTATUS, &iov);\n#ifdef __i386__\n  regs.eip = child_syscall_addr;\n  regs.eax = __NR_munmap;\n  regs.ebx = start;\n  regs.ecx = size;\n#elif defined(__x86_64__)\n  regs.rip = child_syscall_addr;\n  regs.rax = __NR_munmap;\n  regs.rdi = start;\n  regs.rsi = size;\n  regs.rdx = 0;\n  regs.r10 = 0;\n  regs.r8 = 0;\n  regs.r9 = 0;\n#elif defined(__aarch64__)\n  regs.pc = child_syscall_addr;\n  regs.regs[8] = SYS_munmap;\n  regs.regs[0] = start;\n  regs.regs[1] = size;\n#else\n#error unsupported architecture\n#endif\n  checked_ptrace(PTRACE_SETREGSET, child, (void*)NT_PRSTATUS, &iov);\n  // Execute the syscall\n  checked_ptrace(PTRACE_SYSCALL, child, 0, 0);\n  // Wait until entry trap\n  wret = waitpid(child, &status, __WALL | WSTOPPED);\n  test_assert(wret == child);\n  test_assert(WSTOPSIG(status) == (SIGTRAP | 0x80));\n\n  checked_ptrace(PTRACE_SYSCALL, child, 0, 0);\n  // Wait until exit trap\n  wret = waitpid(child, &status, __WALL | WSTOPPED);\n  test_assert(wret == child);\n  test_assert(WSTOPSIG(status) == (SIGTRAP | 0x80));\n  // Verify that the syscall didn't fail\n  checked_ptrace(PTRACE_GETREGSET, child, (void*)NT_PRSTATUS, &iov);\n#ifdef __i386__\n  test_assert(regs.eax == 0);\n#elif defined(__x86_64__)\n  test_assert(regs.rax == 0);\n#elif defined(__aarch64__)\n  test_assert(regs.regs[0] == 0);\n#else\n#error unsupported architecture\n#endif\n}\n\nstatic void remote_unmap_callback(uint64_t child, char* name,\n                                  map_properties_t* props) {\n  if ((props->start <= child_syscall_addr && child_syscall_addr < props->end) ||\n      (props->start <= RR_PAGE_ADDR && props->end > RR_PAGE_ADDR) ||\n      strcmp(name, \"[vsyscall]\") == 0) {\n    return;\n  }\n\n  munmap_remote(child, props->start, props->end - props->start);\n}\n\nstatic __attribute__((noinline)) void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nchar exe_path[200];\nuintptr_t my_start = 0, their_start = 0;\nstatic void find_exe_mapping_start(uint64_t which, char* name,\n                                   map_properties_t* props) {\n  // Find an executable mapping with the given name\n  uintptr_t* start = (which ? &their_start : &my_start);\n  if (*start == 0 && memcmp(props->flags, \"r-xp\", 4) == 0 &&\n      strcmp(exe_path, name) == 0) {\n    *start = props->start;\n  }\n}\n\nstatic void handler(__attribute__((unused)) int sig) {}\n\nint main(void) {\n  sigset_t mask;\n  pid_t child;\n  if (0 == (child = fork())) {\n    raise(SIGSTOP);\n    char* args[] = { \"/proc/self/exe\", NULL };\n    execve(\"/proc/self/exe\", args, environ);\n  }\n\n  // Wait until stopped\n  int status;\n  pid_t wret = waitpid(child, &status, __WALL | WSTOPPED);\n  test_assert(wret == child);\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  // Now PTRACE_SEIZE the child\n  checked_ptrace(PTRACE_SEIZE, child, NULL,\n                 (void*)(PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEEXEC));\n\n  // That caused another stop\n  wret = waitpid(child, &status, __WALL | WSTOPPED);\n  test_assert(wret == child);\n\n  // Set procmask to block signals for now\n  test_assert(0 == sigemptyset(&mask));\n  test_assert(0 == sigaddset(&mask, SIGCHLD));\n  test_assert(0 == sigprocmask(SIG_BLOCK, &mask, NULL));\n\n  // Continue until the exec\n  checked_ptrace(PTRACE_CONT, child, 0, 0);\n  // This should be the exec stop.\n  // Test waiting for a ptrace signal with sigsuspend.\n  test_assert(0 == signal(SIGCHLD, handler));\n  test_assert(0 == sigemptyset(&mask));\n  test_assert(-1 == sigsuspend(&mask) && errno == EINTR);\n  wret = waitpid(child, &status, __WALL | WSTOPPED);\n  test_assert(wret == child);\n  test_assert(status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXEC << 8)));\n\n  // Continue to syscall exit event\n  checked_ptrace(PTRACE_SYSCALL, child, 0, 0);\n  wret = waitpid(child, &status, __WALL | WSTOPPED);\n  test_assert(wret == child);\n  test_assert(WSTOPSIG(status) == (SIGTRAP | 0x80));\n\n  // On kernels with aggressive ASLR, the executable mapping may\n  // not be in the same place that it is now. Find it again.\n  ssize_t path_size = readlink(\"/proc/self/exe\", exe_path, 200);\n  test_assert(path_size > 0);\n\n  // First find the correct mapping in our own address space.\n  FILE* own_maps = fopen(\"/proc/self/maps\", \"r\");\n  iterate_maps(0, find_exe_mapping_start, own_maps);\n  fclose(own_maps);\n\n  // Now find the same mapping in the new process\n  char path[200];\n  snprintf(path, 200, \"/proc/%d/maps\", child);\n  FILE* maps_file = fopen(path, \"r\");\n  iterate_maps(1, find_exe_mapping_start, maps_file);\n  fclose(maps_file);\n\n  // Adjust the syscall address by the slide\n  child_syscall_addr = (uintptr_t)&syscall_addr + (their_start - my_start);\n\n  // Ok, now start unmapping the remote mappings\n  maps_file = fopen(path, \"r\");\n\n  iterate_maps(child, remote_unmap_callback, maps_file);\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_remote_unmap.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('rc')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/ptrace_remote_unmap.run",
    "content": "source `dirname $0`/util.sh\nrecord ptrace_remote_unmap$bitness\ndebug_gdb_only ptrace_remote_unmap\n"
  },
  {
    "path": "src/test/ptrace_seize.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef PTRACE_EVENT_STOP\n#define PTRACE_EVENT_STOP 128\n#endif\n\nstatic int parent_to_child_fds[2];\nstatic int child_to_parent_fds[2];\n\nint main(void) {\n  pid_t child;\n  char ch;\n  int status;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n  test_assert(0 == pipe(child_to_parent_fds));\n\n  if (0 == (child = fork())) {\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    test_assert(1 == write(child_to_parent_fds[1], \"x\", 1));\n    sleep(10000);\n    return 77;\n  }\n\n  test_assert(0 ==\n              ptrace(PTRACE_SEIZE, child, NULL, (void*)PTRACE_O_TRACESYSGOOD));\n  /* Make sure child is still running */\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n  test_assert(1 == read(child_to_parent_fds[0], &ch, 1));\n\n  /* Stop it */\n  test_assert(0 == kill(child, SIGSTOP));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)SIGSTOP));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((PTRACE_EVENT_STOP << 16) | (SIGSTOP << 8) | 0x7f));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, 0));\n  /* Most likely there is no context switch between these two syscalls, rr does\n   * not actually restart the tracee, and this PTRACE_INTERRUPT sees the task\n   * is already stopped internally, and is emulated as a noop.\n   */\n  test_assert(0 == ptrace(PTRACE_INTERRUPT, child, NULL, 0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((PTRACE_EVENT_STOP << 16) | (SIGSTOP << 8) | 0x7f));\n\n  test_assert(WIFSTOPPED(status));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, 0));\n  /* Use a sched_yield() to force rr to context switch and restart the tracee,\n   * so when we PTRACE_INTERRUPT below rr is forced to PTRACE_INTERRUPT the\n   * tracee.\n   */\n  sched_yield();\n  test_assert(0 == ptrace(PTRACE_INTERRUPT, child, NULL, 0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((PTRACE_EVENT_STOP << 16) | (SIGSTOP << 8) | 0x7f));\n\n  test_assert(WIFSTOPPED(status));\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_sigchld.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int parent_to_child_fds[2];\nstatic pid_t child2;\n\nstatic void handle_sigchld(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(child2, SIGKILL);\n  exit(0);\n}\n\nint main(void) {\n  pid_t child1;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n\n  signal(SIGCHLD, handle_sigchld);\n\n  if (0 == (child1 = fork())) {\n    char ch;\n    read(parent_to_child_fds[0], &ch, 1);\n    kill(getpid(), SIGTERM);\n    return 77;\n  }\n\n  /* while we're waiting for child2, a SIGCHLD from child1\n     should still be deliverable (interrupting the wait) */\n  if (0 == (child2 = fork())) {\n    pause();\n    return 99;\n  }\n\n  test_assert(0 == ptrace(PTRACE_SEIZE, child1, NULL, NULL));\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  waitpid(child2, NULL, 0);\n  test_assert(0 && \"Should never return\");\n  return 33;\n}\n"
  },
  {
    "path": "src/test/ptrace_sigchld_blocked.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int parent_to_child_fds[2];\n\nint main(void) {\n  pid_t child;\n  char ch;\n  int status;\n  sigset_t sigs;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n\n  if (0 == (child = fork())) {\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    kill(getpid(), SIGSEGV);\n    return 77;\n  }\n\n  /* Try to block all signals. See if we can still get woken up. */\n  sigfillset(&sigs);\n  test_assert(0 == sigprocmask(SIG_SETMASK, &sigs, NULL));\n\n  test_assert(0 == ptrace(PTRACE_SEIZE, child, NULL, NULL));\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSEGV << 8) | 0x7f));\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_signals.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char* p;\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  p[1] = 78;\n  signal(SIGSEGV, SIG_DFL);\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  int pipe_fds[2];\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED,\n           -1, 0);\n  test_assert(MAP_FAILED != p);\n  p[0] = 0;\n  p[1] = 0;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  if (0 == (child = fork())) {\n    char ch;\n    read(pipe_fds[0], &ch, 1);\n    signal(SIGSEGV, sighandler);\n    p[0] = 77;\n    /* trigger SIGSEGV */\n    crash_null_deref();\n    return 77;\n  }\n\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSEGV << 8) | 0x7f));\n  /* Check that the child actually executed forwards to the SIGSEGV */\n  test_assert(p[0] == 77);\n  test_assert(p[1] == 0);\n\n  /* Progress to second (fatal) SIGSEGV */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)SIGSEGV));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSEGV << 8) | 0x7f));\n  test_assert(p[0] == 77);\n  /* Check that code actually ran */\n  test_assert(p[1] == 78);\n\n  /* Continue with the signal again. This should be fatal. */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)SIGSEGV));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSIGNALED(status));\n  test_assert(WTERMSIG(status) == SIGSEGV);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_singlestep.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\n#ifdef SYS_geteuid32\n#define SYSCALLNO SYS_geteuid32\n#else\n#define SYSCALLNO SYS_geteuid\n#endif\n\nextern char syscall_addr;\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct user_regs_struct regs;\n  uid_t uid = geteuid();\n\n  if (0 == (child = fork())) {\n    // Give the Monkeypatcher a chance to patch this\n    my_geteuid();\n    ptrace(PTRACE_TRACEME, 0, 0, 0);\n    kill(getpid(), SIGSTOP);\n    /* the ptracer changes this result */\n    unsigned int ret = my_geteuid();\n    test_assert(ret == uid + 1);\n    return 77;\n  }\n\n  /* Wait until the tracee stops */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  test_assert(0 == ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD));\n\n  /* Single step through everything, but change the result of the syscall when\n     we get to it */\n  for (;;) {\n    test_assert(0 == ptrace(PTRACE_SYSEMU_SINGLESTEP, child, 0, 0));\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(WIFSTOPPED(status));\n    if (WSTOPSIG(status) == (SIGTRAP | 0x80)) {\n      /* Syscall stop, change the return value */\n      ptrace_getregs(child, &regs);\n      regs.SYSCALL_RESULT = uid + 1;\n      ptrace_setregs(child, &regs);\n      break;\n    }\n    test_assert(WSTOPSIG(status) == SIGTRAP);\n  }\n  test_assert(0 == ptrace(PTRACE_CONT, child, 0, 0));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\n#include <linux/ptrace.h>\n\n#ifdef SYS_geteuid32\n#define SYSCALLNO SYS_geteuid32\n#else\n#define SYSCALLNO SYS_geteuid\n#endif\n\nextern char syscall_addr __attribute__ ((visibility (\"hidden\")));\n\nint main(void) {\n  pid_t child;\n  int status;\n  int ret = 0;\n  struct user_regs_struct regs;\n  uid_t uid = geteuid();\n\n  if (0 == (child = fork())) {\n    kill(getpid(), SIGSTOP);\n    /* the ptracer changes this to a gettid, and then fakes the result */\n    ret = my_geteuid();\n    test_assert(ret == (int)uid + 1);\n    return 77;\n  }\n\n  test_assert(0 ==\n              ptrace(PTRACE_SEIZE, child, NULL, (void*)PTRACE_O_TRACESYSGOOD));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == (((0x80 | SIGTRAP) << 8) | 0x7f));\n  ptrace_getregs(child, &regs);\n\n#ifdef PTRACE_GET_SYSCALL_INFO\n  struct ptrace_syscall_info *info;\n  ALLOCATE_GUARD(info, 'a');\n  ret = ptrace(PTRACE_GET_SYSCALL_INFO, child, sizeof(*info), info);\n  if (ret > 0) {\n    test_assert((offsetof(struct ptrace_syscall_info, entry) + sizeof(info->entry)) == ret);\n    test_assert(info->op == PTRACE_SYSCALL_INFO_ENTRY);\n    test_assert(info->instruction_pointer == (uintptr_t)regs.IP);\n    test_assert(info->stack_pointer == (uintptr_t)regs.SP);\n    test_assert(info->entry.nr == SYSCALLNO);\n    test_assert(info->entry.args[0] == (uintptr_t)regs.SYSCALL_ARG1);\n  } else {\n    test_assert(errno == EIO);\n  }\n  VERIFY_GUARD(info);\n\n  // Test truncation behavior\n  uint8_t *op;\n  ALLOCATE_GUARD(op, 'a');\n  ret = ptrace(PTRACE_GET_SYSCALL_INFO, child, sizeof(*op), op);\n  if (ret > 0) {\n    test_assert((offsetof(struct ptrace_syscall_info, entry) + sizeof(info->entry)) == ret);\n    test_assert(*op == PTRACE_SYSCALL_INFO_ENTRY);\n  } else {\n    test_assert(errno == EIO);\n  }\n  VERIFY_GUARD(op);\n#endif\n\n  /* This assert will fail if we patched the syscall for syscallbuf. */\n  test_assert(&syscall_addr + SYSCALL_SIZE == (char*)regs.IP);\n  test_assert(SYSCALLNO == regs.ORIG_SYSCALLNO);\n#if !defined(__aarch64__)\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n#endif\n  ptrace_change_syscall(child, &regs, SYS_gettid);\n\n  test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == (((0x80 | SIGTRAP) << 8) | 0x7f));\n  ptrace_getregs(child, &regs);\n#if !defined(__aarch64__)\n  // On aarch64 we're only allowed to ask this during a syscall-entry stop\n  test_assert(SYS_gettid == regs.ORIG_SYSCALLNO);\n#endif\n  test_assert(child == (int)regs.SYSCALL_RESULT);\n  test_assert(&syscall_addr + SYSCALL_SIZE == (char*)regs.IP);\n\n#ifdef PTRACE_GET_SYSCALL_INFO\n  ALLOCATE_GUARD(info, 'a');\n  ret = ptrace(PTRACE_GET_SYSCALL_INFO, child, sizeof(*info), info);\n  if (ret > 0) {\n    test_assert((offsetof(struct ptrace_syscall_info, exit) + sizeof(uint64_t) + sizeof(uint8_t)) == ret);\n    test_assert(info->op == PTRACE_SYSCALL_INFO_EXIT);\n    test_assert(info->instruction_pointer == (uintptr_t)regs.IP);\n    test_assert(info->stack_pointer == (uintptr_t)regs.SP);\n    test_assert(info->exit.rval == (intptr_t)regs.SYSCALL_RESULT);\n  } else {\n    test_assert(errno == EIO);\n  }\n  VERIFY_GUARD(info);\n#endif\n\n  regs.SYSCALL_RESULT = uid + 1;\n  ptrace_setregs(child, &regs);\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_syscall_clone_untraced.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) { return NULL; }\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct user_regs_struct regs;\n  struct user_regs_struct regs2;\n\n  if (0 == (child = fork())) {\n    pthread_t thread;\n    kill(getpid(), SIGSTOP);\n    pthread_create(&thread, NULL, do_thread, NULL);\n    pthread_join(thread, NULL);\n    return 77;\n  }\n\n  test_assert(0 ==\n              ptrace(PTRACE_SEIZE, child, NULL,\n                     (void*)(PTRACE_O_TRACECLONE | PTRACE_O_TRACESYSGOOD)));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  do {\n    test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n    test_assert(child == waitpid(child, &status, 0));\n    test_assert(status == (((0x80 | SIGTRAP) << 8) | 0x7f));\n    ptrace_getregs(child, &regs);\n  } while (SYS_clone != regs.ORIG_SYSCALLNO);\n\n  // Make sure CLONE_UNTRACED is honored.\n  regs.SYSCALL_ARG1 |= CLONE_UNTRACED;\n  ptrace_setregs(child, &regs);\n\n  test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == (((0x80 | SIGTRAP) << 8) | 0x7f));\n  ptrace_getregs(child, &regs2);\n#if !defined(__aarch64__)\n  test_assert(SYS_clone == regs2.ORIG_SYSCALLNO);\n#endif\n  test_assert(regs.IP == regs2.IP);\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_sysemu_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\n/* This test tests the interaction between PTRACE_SYSEMU and PTRACE_SYSCALL.\n * In addition, it also tests the behavior of PTRACE_SYSEMU when the entering\n * syscall number is invalid (it will be -ENOSYS for the second syscall).\n */\n\nextern char syscall1_addr __attribute__ ((visibility (\"hidden\")));\nint main(void) {\n  pid_t child;\n  int status;\n  struct user_regs_struct regs;\n\n  if (0 == (child = fork())) {\n    ptrace(PTRACE_TRACEME, 0, 0, 0);\n#ifdef __i386__\n    __asm__ __volatile__(\"int $3\\n\\t\"\n                         \"syscall1_addr: int $0x80\\n\\t\"\n                         \"nop\\n\\t\"\n                         \"int $0x80\\n\\t\"\n                         \"nop\\n\\t\"\n                         \"int $3\\n\\t\" ::\"a\"(SYS_geteuid32));\n#elif defined(__x86_64__)\n    __asm__ __volatile__(\"int $3\\n\\t\"\n                         \"syscall1_addr: syscall\\n\\t\"\n                         \"nop\\n\\t\"\n                         \"syscall\\n\\t\"\n                         \"nop\\n\\t\"\n                         \"int $3\\n\\t\" ::\"a\"(SYS_geteuid));\n#elif defined(__aarch64__)\n    register long x8 __asm__(\"x8\") = SYS_geteuid;\n    __asm__ __volatile__(\"brk #0\\n\\t\"\n                         \"syscall1_addr: svc #0\\n\\t\"\n                         \"nop\\n\\t\"\n                         \"svc #0\\n\\t\"\n                         \"nop\\n\\t\"\n                         \"brk #0\\n\\t\" :: \"r\"(x8));\n#else\n#error Add support for new architecture here\n#endif\n    test_assert(0 && \"Should not reach here\");\n  }\n\n  /* Wait until the tracee stops */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);\n  test_assert(0 == ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD));\n\n  skip_breakpoint(child);\n\n  /* Should step to syscall entry */\n  test_assert(0 == ptrace(PTRACE_SYSEMU, child, 0, 0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));\n\n  /* Should step to syscall exit, but have skipped the syscall */\n  test_assert(0 == ptrace(PTRACE_SYSCALL, child, 0, 0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));\n\n  /* If we hadn't skipped the syscall the register would now contain the result\n   */\n  ptrace_getregs(child, &regs);\n#if !defined(__aarch64__)\n  test_assert((uintptr_t)regs.SYSCALL_RESULT == (uintptr_t)-ENOSYS);\n#endif\n  test_assert((uintptr_t)regs.IP == (uintptr_t)&syscall1_addr + SYSCALL_SIZE);\n\n  /* Should step to syscall entry */\n  test_assert(0 == ptrace(PTRACE_SYSEMU, child, 0, 0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == (SIGTRAP | 0x80));\n\n  /* Should hit the interrupt (i.e. not step to syscall exit) */\n  test_assert(0 == ptrace(PTRACE_SYSEMU, child, 0, 0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);\n\n  kill(child, SIGKILL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_trace_clone.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\n#ifndef PTRACE_EVENT_STOP\n#define PTRACE_EVENT_STOP 128\n#endif\n\nstatic int parent_to_child_fds[2];\n\nstatic void* do_thread(__attribute__((unused)) void* p) { return NULL; }\n\nint main(void) {\n  pid_t child;\n  char ch;\n  int status;\n  unsigned long cloned_pid;\n  struct user_regs_struct regs;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n\n  if (0 == (child = fork())) {\n    pid_t grandchild;\n    pthread_t thread;\n\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n\n    grandchild = fork();\n    if (!grandchild) {\n      return 66;\n    }\n    test_assert(grandchild == waitpid(grandchild, &status, 0));\n    test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 66);\n\n    pthread_create(&thread, NULL, do_thread, NULL);\n    pthread_join(thread, NULL);\n\n    return 77;\n  }\n\n  test_assert(0 == ptrace(PTRACE_SEIZE, child, NULL,\n                          (void*)(PTRACE_O_TRACEFORK | PTRACE_O_TRACECLONE |\n                                  PTRACE_O_TRACESYSGOOD)));\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  test_assert(child == waitpid(child, &status, 0));\n  /* Test that PTRACE_EVENT_FORK is generated and that we are tracing the\n     grandchild. */\n  test_assert(status == ((PTRACE_EVENT_FORK << 16) | (SIGTRAP << 8) | 0x7f));\n  test_assert(0 == ptrace(PTRACE_GETEVENTMSG, child, NULL, &cloned_pid));\n  ptrace_getregs(child, &regs);\n  test_assert((pid_t)cloned_pid == waitpid(cloned_pid, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);\n  test_assert((status >> 16) == PTRACE_EVENT_STOP);\n  ptrace_getregs(cloned_pid, &regs);\n\n  /* Test that we observe the exit of the grandchild. We need to wait()\n     on the grandchild or our child won't ever see the exit. */\n  test_assert(0 == ptrace(PTRACE_CONT, cloned_pid, NULL, (void*)0));\n  test_assert((pid_t)cloned_pid == waitpid(cloned_pid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 66);\n\n  /* Test that the child observes a SIGCHLD from the grandchild's exit. */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGCHLD);\n\n  /* Test that PTRACE_EVENT_CLONE is generated and we are tracing the\n     grandchild. */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((PTRACE_EVENT_CLONE << 16) | (SIGTRAP << 8) | 0x7f));\n  ptrace_getregs(child, &regs);\n  test_assert(0 == ptrace(PTRACE_GETEVENTMSG, child, NULL, &cloned_pid));\n  test_assert((pid_t)cloned_pid == waitpid(cloned_pid, &status, __WCLONE));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);\n  test_assert((status >> 16) == PTRACE_EVENT_STOP);\n  ptrace_getregs(cloned_pid, &regs);\n\n  /* Test that we observe the exit of the grandchild. We need to wait()\n     on the grandchild or our child won't ever see the exit. */\n  test_assert(0 == ptrace(PTRACE_CONT, cloned_pid, NULL, (void*)0));\n  test_assert((pid_t)cloned_pid == waitpid(cloned_pid, &status, __WCLONE));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n\n  /* Test that we observe the exit of the child. */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_trace_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"ptrace_util.h\"\n\nstatic int parent_to_child_fds[2];\n\nint main(void) {\n  pid_t child;\n  char ch;\n  int status;\n  struct user_regs_struct regs;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n\n  if (0 == (child = fork())) {\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    return 77;\n  }\n\n  test_assert(0 == ptrace(PTRACE_SEIZE, child, NULL,\n                          (void*)(PTRACE_O_TRACEEXIT | PTRACE_O_TRACESYSGOOD)));\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((PTRACE_EVENT_EXIT << 16) | (SIGTRAP << 8) | 0x7f));\n  ptrace_getregs(child, &regs);\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_traceme.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int parent_to_child_fds[2];\nstatic int child_to_parent_fds[2];\n\nint main(void) {\n\n  pid_t child;\n  char ch;\n  int status;\n\n  test_assert(0 == pipe(parent_to_child_fds));\n  test_assert(0 == pipe(child_to_parent_fds));\n\n  if (0 == (child = fork())) {\n    test_assert(0 == ptrace(PTRACE_TRACEME, 0, 0, 0));\n    test_assert(-1 == ptrace(PTRACE_TRACEME, 0, 0, 0));\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    test_assert(1 == write(child_to_parent_fds[1], \"x\", 1));\n    raise(SIGSTOP);\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    return 0;\n  }\n\n  /* Make sure child is still running */\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n  test_assert(1 == read(child_to_parent_fds[0], &ch, 1));\n\n  /* Wait until the tracee stops */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  /* Ask for a ptrace notification on exit */\n  test_assert(0 == ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEEXIT));\n  test_assert(0 == ptrace(PTRACE_CONT, child, 0, 0));\n\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  /* Child is now exiting. Check for the PTRACE_EVENT_EXIT notification */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXIT << 8)));\n\n  ptrace(PTRACE_CONT, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_traceme_thread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int parent_to_child_fds[2];\nstatic int child_to_parent_fds[2];\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  pid_t child = fork();\n  char ch;\n  if (!child) {\n    test_assert(0 == ptrace(PTRACE_TRACEME, 0, 0, 0));\n    test_assert(1 == write(child_to_parent_fds[1], \"x\", 1));\n    raise(SIGSTOP);\n    test_assert(1 == read(parent_to_child_fds[0], &ch, 1));\n    return NULL;\n  }\n\n  test_assert(1 == read(child_to_parent_fds[0], &ch, 1));\n  /* Wait until the tracee stops */\n  int status;\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  /* Ask for a ptrace notification on exit */\n  test_assert(0 == ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEEXIT));\n  test_assert(0 == ptrace(PTRACE_CONT, child, 0, 0));\n\n  test_assert(1 == write(parent_to_child_fds[1], \"p\", 1));\n\n  /* Child is now exiting. Check for the PTRACE_EVENT_EXIT notification */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status >> 8 == (SIGTRAP | (PTRACE_EVENT_EXIT << 8)));\n  return NULL;\n}\n\nint main(void) {\n  test_assert(0 == pipe(parent_to_child_fds));\n  test_assert(0 == pipe(child_to_parent_fds));\n\n  pthread_t thread;\n  pthread_create(&thread, NULL, do_thread, NULL);\n  pthread_join(thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptrace_util.h",
    "content": "\n#if defined(__i386__)\n#define ORIG_SYSCALLNO orig_eax\n#elif defined(__x86_64__)\n#define ORIG_SYSCALLNO orig_rax\n#elif defined(__aarch64__)\n#define ORIG_SYSCALLNO regs[8]\n#else\n#error unknown architecture\n#endif\n\n#if defined(__i386__)\n#define SYSCALL_RESULT eax\n#elif defined(__x86_64__)\n#define SYSCALL_RESULT rax\n#elif defined(__aarch64__)\n#define SYSCALL_RESULT regs[0]\n#else\n#error unknown architecture\n#endif\n\n#if defined(__i386__)\n#define SYSCALL_ARG1 ebx\n#elif defined(__x86_64__)\n#define SYSCALL_ARG1 rdi\n#elif defined(__aarch64__)\n#define SYSCALL_ARG1 regs[0]\n#else\n#error unknown architecture\n#endif\n\n#if defined(__i386__)\n#define IP eip\n#elif defined(__x86_64__)\n#define IP rip\n#elif defined(__aarch64__)\n#define IP pc\n#else\n#error unknown architecture\n#endif\n\n#if defined(__i386__)\n#define SP esp\n#elif defined(__x86_64__)\n#define SP rsp\n#elif defined(__aarch64__)\n#define SP sp\n#else\n#error unknown architecture\n#endif\n\n#if defined(__i386__) || defined(__x86_64__)\n#define SYSCALL_SIZE 2\n#elif defined(__aarch64__)\n#define SYSCALL_SIZE 4\n#else\n#error unknown architecture\n#endif\n\n#ifndef PTRACE_SYSEMU\n#define PTRACE_SYSEMU 31\n#endif\n#ifndef PTRACE_SYSEMU_SINGLESTEP\n#define PTRACE_SYSEMU_SINGLESTEP 32\n#endif\n\nvoid ptrace_getregs(pid_t child, struct user_regs_struct *regs) {\n#ifdef PTRACE_GETREGS\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, regs));\n#else\n  struct iovec iov = { .iov_base=regs, .iov_len=sizeof(*regs) };\n  test_assert(0 == ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &iov));\n#endif\n}\n\nvoid ptrace_setregs(pid_t child, struct user_regs_struct *regs) {\n#ifdef PTRACE_SETREGS\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, regs));\n#else\n  struct iovec iov = { .iov_base=regs, .iov_len=sizeof(*regs) };\n  test_assert(0 == ptrace(PTRACE_SETREGSET, child, NT_PRSTATUS, &iov));\n#endif\n}\n\nvoid ptrace_change_syscall(pid_t child, struct user_regs_struct *regs, int new_syscall)\n{\n#if defined(__i386__) || defined(__x86_64__)\n  regs->ORIG_SYSCALLNO = new_syscall;\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, regs));\n#elif defined(__aarch64__)\n  (void)regs;\n  struct iovec iov = { .iov_base=&new_syscall, .iov_len=sizeof(new_syscall) };\n  test_assert(0 == ptrace(PTRACE_SETREGSET, child, NT_ARM_SYSTEM_CALL, &iov));\n#else\n#error \"Unknown architecture\"\n#endif\n}\n\n/* Make a syscallbuf-patchable syscall to check that syscallbuf patching\n   doesn't happen when we are emulating a ptracer --- which can be\n   potentially confused by it. */\nstatic uid_t __attribute__((noinline,unused)) my_geteuid(void) {\n  int r;\n#ifdef __i386__\n  __asm__ __volatile__(\"syscall_addr: int $0x80\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       : \"=a\"(r)\n                       : \"a\"(SYS_geteuid32));\n#elif defined(__x86_64__)\n  __asm__ __volatile__(\"syscall_addr: syscall\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       : \"=a\"(r)\n                       : \"a\"(SYS_geteuid));\n#elif defined(__aarch64__)\n  register long x8 __asm__(\"x8\") = SYS_geteuid;\n  register long x0 __asm__(\"x0\");\n  __asm__ __volatile__(\"syscall_addr: svc #0\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       \"nop\\n\\t\"\n                       : \"=r\"(x0)\n                       : \"r\"(x8));\n  r = x0;\n#else\n#error Unknown architecture\n#endif\n  return r;\n}\n\nvoid skip_breakpoint(pid_t child) {\n#if defined(__i386__) || defined(__x86_64__)\n  (void)child;\n  return;\n#elif defined(__aarch64__)\n  struct user_regs_struct regs;\n  ptrace_getregs(child, &regs);\n  regs.IP += 4;\n  ptrace_setregs(child, &regs);\n#else\n#error Unknown architecture\n#endif\n}\n"
  },
  {
    "path": "src/test/ptrace_waiter_thread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic pid_t child;\nstatic int parent_to_child[2];\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  int status;\n  /* Make sure this thread (which is not the ptracer thread)\n     can read the wait status from the ptracee. */\n  int ret = waitpid(-1, &status, 0);\n  test_assert(ret == child);\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  char ch;\n  test_assert(0 == pipe(parent_to_child));\n\n  if (0 == (child = fork())) {\n    test_assert(1 == write(parent_to_child[1], \"x\", 1));\n    sleep(1000000);\n    return 77;\n  }\n\n  test_assert(1 == read(parent_to_child[0], &ch, 1));\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  sleep(10000000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptracer_death.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int status_pipe[2];\n\nstatic int ptracer(void) {\n  pid_t child;\n  int status;\n  struct timespec ts = { 0, 50000000 };\n  int ready_pipe[2];\n  char ready = 'R';\n\n  test_assert(0 == pipe(ready_pipe));\n\n  if (0 == (child = fork())) {\n    char ch = 0;\n    char ok = 'K';\n\n    test_assert(1 == read(ready_pipe[0], &ch, 1));\n    test_assert(ch == 'R');\n    test_assert(1 == write(status_pipe[1], &ok, 1));\n    return 77;\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  test_assert(1 == write(ready_pipe[1], &ready, 1));\n  /* Now just exit, and the child should resume */\n  return 44;\n}\n\nint main(void) {\n  char ch = 0;\n  pid_t ptracer_pid;\n  int status;\n\n  test_assert(0 == pipe(status_pipe));\n\n  if (0 == (ptracer_pid = fork())) {\n    return ptracer();\n  }\n\n  test_assert(ptracer_pid == waitpid(ptracer_pid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 44);\n\n  test_assert(1 == read(status_pipe[0], &ch, 1));\n  test_assert(ch == 'K');\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptracer_death_multithread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* This test spawns a ptracer and a ptracee, where the ptracee has 10\n   sub-threads.\n   The pracer attaches to all the ptracee's threads, then exits.\n   We check that all ptracee threads are resumed. */\n\nstatic int status_pipe[2];\nstatic int tid_pipe[2];\nstatic int ready_pipe[2];\nstatic int thread_wait_pipe[2];\n\nstatic void write_tid(void) {\n  pid_t tid = sys_gettid();\n  test_assert(sizeof(tid) == write(tid_pipe[1], &tid, sizeof(tid)));\n}\n\nstatic pid_t read_tid(void) {\n  pid_t tid;\n  test_assert(sizeof(tid) == read(tid_pipe[0], &tid, sizeof(tid)));\n  return tid;\n}\n\nstatic void* child_thread(__attribute__((unused)) void* p) {\n  char ch = 0;\n  write_tid();\n  test_assert(1 == read(thread_wait_pipe[0], &ch, 1));\n  test_assert('W' == ch);\n  return NULL;\n}\n\nstatic int child_runner(void) {\n  char ch = 0;\n  pthread_t threads[10];\n  int i;\n\n  write_tid();\n  for (i = 0; i < 10; ++i) {\n    pthread_create(&threads[i], NULL, child_thread, NULL);\n  }\n\n  atomic_printf(\"Waiting on ready_pipe\\n\");\n  test_assert(1 == read(ready_pipe[0], &ch, 1));\n  test_assert(ch == 'R');\n\n  for (i = 0; i < 10; ++i) {\n    char ch2 = 'W';\n    test_assert(1 == write(thread_wait_pipe[1], &ch2, 1));\n  }\n  for (i = 0; i < 10; ++i) {\n    atomic_printf(\"Joining thread %d\\n\", i);\n    pthread_join(threads[i], NULL);\n  }\n\n  char ok = 'K';\n  test_assert(1 == write(status_pipe[1], &ok, 1));\n\n  return 77;\n}\n\nstatic int ptracer(void) {\n  pid_t child;\n  int status;\n  char ready = 'R';\n  int i;\n  pid_t child_tids[11];\n\n  if (0 == (child = fork())) {\n    return child_runner();\n  }\n\n  for (i = 0; i < 11; ++i) {\n    child_tids[i] = read_tid();\n  }\n  for (i = 0; i < 11; ++i) {\n    int ret;\n    test_assert(0 == ptrace(PTRACE_ATTACH, child_tids[i], NULL, NULL));\n    ret = waitpid(child_tids[i], &status, __WALL);\n    atomic_printf(\"waitpid on %d gives %d with errno=%d\\n\", child_tids[i], ret,\n                  errno);\n    test_assert(ret == child_tids[i]);\n    test_assert(status == ((SIGSTOP << 8) | 0x7f));\n  }\n\n  test_assert(1 == write(ready_pipe[1], &ready, 1));\n\n  /* Now just exit, and all child threads should resume */\n  return 44;\n}\n\nint main(void) {\n  char ch = 0;\n  pid_t ptracer_pid;\n  int status;\n\n  test_assert(0 == pipe(ready_pipe));\n  test_assert(0 == pipe(tid_pipe));\n  test_assert(0 == pipe(status_pipe));\n  test_assert(0 == pipe(thread_wait_pipe));\n\n  if (0 == (ptracer_pid = fork())) {\n    return ptracer();\n  }\n\n  test_assert(ptracer_pid == waitpid(ptracer_pid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 44);\n\n  test_assert(1 == read(status_pipe[0], &ch, 1));\n  test_assert(ch == 'K');\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ptracer_death_multithread_peer.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* This test spawns a ptracer and a ptracee, where the ptracee has 10\n   sub-threads.\n   The pracer attaches to all the ptracee's threads, then exits.\n   We check that all ptracee threads are resumed.\n   Similar to ptracer_detach_multithread, except the ptracer is\n   not a parent of the ptracee.\n*/\n\nstatic int status_pipe[2];\nstatic int tid_pipe[2];\nstatic int ready_pipe[2];\nstatic int thread_wait_pipe[2];\n\nstatic void write_tid(void) {\n  pid_t tid = sys_gettid();\n  test_assert(sizeof(tid) == write(tid_pipe[1], &tid, sizeof(tid)));\n}\n\nstatic pid_t read_tid(void) {\n  pid_t tid;\n  test_assert(sizeof(tid) == read(tid_pipe[0], &tid, sizeof(tid)));\n  return tid;\n}\n\nstatic void* child_thread(__attribute__((unused)) void* p) {\n  char ch = 0;\n  write_tid();\n  test_assert(1 == read(thread_wait_pipe[0], &ch, 1));\n  test_assert('W' == ch);\n  return NULL;\n}\n\nstatic int child_runner(void) {\n  char ch = 0;\n  pthread_t threads[10];\n  int i;\n\n  /* This fails on some kernels, so don't check its result */\n  prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);\n\n  write_tid();\n  for (i = 0; i < 10; ++i) {\n    pthread_create(&threads[i], NULL, child_thread, NULL);\n  }\n\n  atomic_printf(\"Waiting on ready_pipe\\n\");\n  test_assert(1 == read(ready_pipe[0], &ch, 1));\n  test_assert(ch == 'R');\n\n  for (i = 0; i < 10; ++i) {\n    char ch2 = 'W';\n    test_assert(1 == write(thread_wait_pipe[1], &ch2, 1));\n  }\n  for (i = 0; i < 10; ++i) {\n    atomic_printf(\"Joining thread %d\\n\", i);\n    pthread_join(threads[i], NULL);\n  }\n\n  char ok = 'K';\n  test_assert(1 == write(status_pipe[1], &ok, 1));\n\n  return 77;\n}\n\nstatic int ptracer(void) {\n  int status;\n  char ready = 'R';\n  int i;\n  pid_t child_tids[11];\n\n  for (i = 0; i < 11; ++i) {\n    child_tids[i] = read_tid();\n  }\n  for (i = 0; i < 11; ++i) {\n    int ret;\n    test_assert(0 == ptrace(PTRACE_ATTACH, child_tids[i], NULL, NULL));\n    ret = waitpid(child_tids[i], &status, __WALL);\n    atomic_printf(\"waitpid on %d gives %d with errno=%d\\n\", child_tids[i], ret,\n                  errno);\n    test_assert(ret == child_tids[i]);\n    test_assert(status == ((SIGSTOP << 8) | 0x7f));\n  }\n\n  test_assert(1 == write(ready_pipe[1], &ready, 1));\n\n  /* Now just exit, and all child threads should resume */\n  return 44;\n}\n\nint main(void) {\n  char ch = 0;\n  pid_t ptracer_pid, child;\n  int status;\n\n  test_assert(0 == pipe(ready_pipe));\n  test_assert(0 == pipe(tid_pipe));\n  test_assert(0 == pipe(status_pipe));\n  test_assert(0 == pipe(thread_wait_pipe));\n\n  if (0 == (child = fork())) {\n    return child_runner();\n  }\n\n  if (0 == (ptracer_pid = fork())) {\n    return ptracer();\n  }\n\n  test_assert(ptracer_pid == waitpid(ptracer_pid, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 44);\n\n  test_assert(1 == read(status_pipe[0], &ch, 1));\n  test_assert(ch == 'K');\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/quotactl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char home_device[1001];\n\nstatic void find_home_device(void) {\n  struct stat home_stat;\n  const char* home = getenv(\"HOME\");\n  FILE* f;\n  char mount_line[2000];\n\n  if (!home || stat(home, &home_stat)) {\n    atomic_printf(\"Can't stat %s; aborting test\\n\", home);\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n  }\n\n  f = fopen(\"/proc/self/mountinfo\", \"rt\");\n  test_assert(f != NULL);\n  while (fgets(mount_line, sizeof(mount_line), f)) {\n    int maj, min;\n    int ret;\n    ret = sscanf(mount_line, \"%*d %*d %d:%d %*s %*s %*s %*s - %*s %1000s %*s\",\n                 &maj, &min, home_device);\n    // optional field (7) missing?\n    if (ret != 3) {\n      sscanf(mount_line, \"%*d %*d %d:%d %*s %*s %*s - %*s %1000s %*s\", &maj,\n             &min, home_device);\n    }\n    if (maj == (int)major(home_stat.st_dev) &&\n        min == (int)minor(home_stat.st_dev) && maj != 0) {\n      atomic_printf(\"%s (%d:%d) is on device special file %s\\n\", home, maj, min,\n                    home_device);\n      return;\n    }\n  }\n\n  atomic_printf(\"Can't find filesystem containing %s (%d:%d); aborting test\\n\",\n                home, major(home_stat.st_dev), minor(home_stat.st_dev));\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nint main(void) {\n  struct dqblk dq;\n  int ret;\n\n  /* ENOTBLK may be returned before checking cmd */\n  ret = quotactl(0x12345678, \"/\", getuid(), (caddr_t)&dq);\n  test_assert(ret < 0 && (errno == ENOTBLK || errno == EINVAL));\n\n  /* ENOENT may be returned before checking cmd */\n  ret =\n      quotactl(0x12345678, \"/asdfjlafdlkk289892389pkj\", getuid(), (caddr_t)&dq);\n  test_assert(ret < 0 && (errno == ENOENT || errno == EINVAL));\n\n  /* ENODEV may be returned before checking cmd when the device is a Btrfs volume */\n  ret = quotactl(0x12345678, \"/dev/dm-0\", getuid(), (caddr_t)&dq);\n  test_assert(ret < 0 && (errno == ENOTBLK || errno == ENOENT ||\n                          errno == ENODEV || errno == EINVAL));\n\n  find_home_device();\n  ret =\n      quotactl(QCMD(Q_GETQUOTA, USRQUOTA), home_device, getuid(), (caddr_t)&dq);\n  if (ret < 0 && errno == ENOSYS) {\n    atomic_puts(\"Quotas not supported in this kernel; aborting test\");\n  } else if (ret < 0 && errno == ESRCH) {\n    atomic_puts(\"Quotas not enabled on this file system; aborting test\");\n  } else if (ret < 0 && errno == ENOTBLK) {\n    atomic_puts(\"Home directory device is not a block device; aborting test\");\n  } else if (ret < 0 && errno == ENOENT) {\n    /* On Ubuntu 16.06, at least, I'm getting a `/dev/root` which doesn't\n     * actually exist :-(\n     */\n    atomic_puts(\"Home directory device not found; aborting test\");\n  } else {\n    test_assert(0 == ret);\n    atomic_printf(\"QIF bits=%x\\n\", dq.dqb_valid);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/read_bad_mem.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, main')\n\nsend_gdb('p *0xf')\nexpect_gdb('Cannot access memory at address 0xf')\n\nsend_gdb('p *0xffffffff')\nexpect_gdb('Cannot access memory at address 0xffffffff')\n\nok()\n"
  },
  {
    "path": "src/test/read_bad_mem.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only read_bad_mem\n"
  },
  {
    "path": "src/test/read_big_struct.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\n/* FIXME: we should be able to send arbitrarily large structs over the\n * debugging socket.  This is a temporary hack. */\nstruct big {\n  char bytes[8192];\n};\n\nint main(void) {\n  struct big big;\n\n  memset(&big, 0x5a, sizeof(big));\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/read_big_struct.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('f 1')\nexpect_gdb('(rr)')\n\nsend_gdb('p big')\nexpect_gdb('bytes = \\'Z\\'')\n\nok()\n"
  },
  {
    "path": "src/test/read_big_struct.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/read_large.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_SIZE 65536\n#define EXTRA 10\n\nstatic const char file_name[] = \"tmp.bin\";\n\n/**\n * For benchmarking purposes you can run this with \"write\" parameter to\n * just generate a (much larger) file and \"read\" parameter to read it. The\n * normal test uses a much smaller file size.\n */\nint main(int argc, char** argv) {\n  char buf[BUF_SIZE];\n  char buf2[BUF_SIZE];\n  int i;\n  int fd;\n  int buf_count = argc < 2 ? 500 : 20000;\n\n  memset(buf, 1, sizeof(buf));\n\n  if (argc < 2 || !strcmp(argv[1], \"write\")) {\n    fd = open(file_name, O_WRONLY | O_CREAT | O_EXCL, 0600);\n    test_assert(fd >= 0);\n    for (i = 0; i < buf_count; ++i) {\n      test_assert(write(fd, buf, BUF_SIZE) == BUF_SIZE);\n    }\n    test_assert(write(fd, buf, EXTRA) == EXTRA);\n  }\n\n  if (argc < 2 || !strcmp(argv[1], \"read\")) {\n    fd = open(file_name, O_RDONLY);\n    test_assert(fd >= 0);\n    for (i = 0; i < buf_count; ++i) {\n      test_assert(read(fd, buf2, sizeof(buf2)) == sizeof(buf2));\n      test_assert(!memcmp(buf, buf2, sizeof(buf)));\n    }\n    test_assert(read(fd, buf2, sizeof(buf2)) == EXTRA);\n    test_assert(read(fd, buf2, sizeof(buf2)) == 0);\n  }\n\n  if (argc < 2) {\n    fd = open(file_name, O_WRONLY);\n    test_assert(fd >= 0);\n    memset(buf, 2, sizeof(buf));\n    test_assert(write(fd, buf, sizeof(buf)) == sizeof(buf));\n    test_assert(0 == close(fd));\n\n    test_assert(0 == unlink(file_name));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/read_nothing.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define SIZE 100000000\n\nint main(void) {\n  int pipe_fds[2];\n  int i;\n  char* buf = mmap(NULL, SIZE, PROT_READ | PROT_WRITE,\n                   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  test_assert(buf != MAP_FAILED);\n  test_assert(0 == pipe2(pipe_fds, O_NONBLOCK));\n  for (i = 0; i < 10000; ++i) {\n    test_assert(-1 == read(pipe_fds[0], buf, SIZE));\n    test_assert(errno == EAGAIN);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/read_oversize.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"tmp\", O_CREAT | O_RDWR, 0700);\n  char buf[100];\n  int ret;\n\n  test_assert(fd >= 0);\n  memset(buf, 1, sizeof(buf));\n  test_assert(sizeof(buf) == write(fd, buf, sizeof(buf)));\n\n  test_assert(0 == lseek(fd, 0, SEEK_SET));\n  ret = syscall(RR_read, fd, buf, UINTPTR_MAX - 0xfff);\n  if (ret < 0) {\n    /* x86-64 returns EFAULT here. I'm not sure why. */\n    test_assert(EFAULT == errno);\n  } else {\n    test_assert(100 == ret);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/readdir.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  DIR* dir = opendir(\".\");\n  struct dirent* ent;\n\n  test_assert(dir != NULL);\n\n  while ((ent = readdir(dir)) != NULL) {\n    test_assert(ent->d_reclen >= 8);\n    atomic_printf(\"%s %lld %lld\\n\", ent->d_name, (long long)ent->d_ino,\n                  (long long)ent->d_off);\n  }\n\n  test_assert(0 == closedir(dir));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/readlink.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_SIZE 10\n#define BUF2_SIZE 1000\n\nint main(void) {\n  char path[] = \"rr-test-file-XXXXXX\";\n  int fd = mkstemp(path);\n  int count;\n  char link[PATH_MAX];\n  char* buf = allocate_guard(BUF_SIZE, 'q');\n  char* buf2 = allocate_guard(BUF2_SIZE, 'r');\n\n  test_assert(0 <= fd);\n\n  for (count = 0;; ++count) {\n    sprintf(link, \"rr-test-link-%d\", count);\n    int ret = symlink(path, link);\n    if (ret == 0) {\n      break;\n    }\n    test_assert(errno == EEXIST);\n  }\n\n  test_assert(BUF_SIZE == readlink(link, buf, BUF_SIZE));\n  test_assert(0 == memcmp(path, buf, BUF_SIZE));\n  verify_guard(BUF_SIZE, buf);\n\n  test_assert((ssize_t)strlen(path) == readlink(link, buf2, BUF2_SIZE));\n  test_assert(0 == memcmp(path, buf2, strlen(path)));\n  verify_guard(BUF2_SIZE, buf2);\n\n  test_assert(0 == unlink(path));\n  test_assert(0 == unlink(link));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/readlinkat.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_SIZE 10\n#define BUF2_SIZE 1000\n\nint main(void) {\n  static const char file_path[] = \"rr-test-file\";\n  static const char link_path[] = \"rr-test-link\";\n  char* buf = allocate_guard(BUF_SIZE, 'q');\n  char* buf2 = allocate_guard(BUF2_SIZE, 'r');\n\n  test_assert(0 == symlink(file_path, link_path));\n  test_assert(BUF_SIZE == readlinkat(AT_FDCWD, link_path, buf, BUF_SIZE));\n  test_assert(0 == memcmp(file_path, buf, BUF_SIZE));\n  verify_guard(BUF_SIZE, buf);\n\n  test_assert((ssize_t)(sizeof(file_path) - 1) ==\n              readlinkat(AT_FDCWD, link_path, buf2, BUF2_SIZE));\n  test_assert(0 == memcmp(file_path, buf2, sizeof(file_path) - 1));\n  verify_guard(BUF2_SIZE, buf2);\n\n  test_assert(0 == unlink(link_path));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/readv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char data[11] = \"0123456789\";\n\nstatic void test(int use_preadv) {\n  static const char name[] = \"temp\";\n  int fd = open(name, O_CREAT | O_RDWR | O_EXCL, 0600);\n  struct {\n    char ch[7];\n  } * part1;\n  struct {\n    char ch[10];\n  } * part2;\n  struct iovec iovs[2];\n  ssize_t nread;\n\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(name));\n  test_assert(sizeof(data) == write(fd, data, sizeof(data)));\n\n  ALLOCATE_GUARD(part1, 'x');\n  ALLOCATE_GUARD(part2, 'y');\n  iovs[0].iov_base = part1;\n  iovs[0].iov_len = sizeof(*part1);\n  iovs[1].iov_base = part2;\n  iovs[1].iov_len = sizeof(*part2);\n  if (use_preadv) {\n    /* Work around busted preadv prototype in older libcs */\n    nread = syscall(SYS_preadv, fd, iovs, 2, (off_t)0, 0);\n  } else {\n    test_assert(0 == lseek(fd, 0, SEEK_SET));\n    nread = readv(fd, iovs, 2);\n  }\n  test_assert(sizeof(data) == nread);\n  test_assert(0 == memcmp(part1, data, sizeof(*part1)));\n  test_assert(\n      0 == memcmp(part2, data + sizeof(*part1), sizeof(data) - sizeof(*part1)));\n  test_assert(part2->ch[sizeof(data) - sizeof(*part1)] == 'y');\n  VERIFY_GUARD(part1);\n  VERIFY_GUARD(part2);\n}\n\nint main(void) {\n  test(0);\n  test(1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/record_replay.run",
    "content": "source `dirname $0`/util.sh\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\nrecord record_replay_subject$bitness\njust_record rr \"--suppress-environment-warnings replay -a $workdir/*-0\"\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/record_replay_subject.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int caught_sig = 0;\n\npthread_barrier_t bar;\nchar value[8];\nint fd;\n\nvoid catcher(__attribute__((unused)) int signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             __attribute__((unused)) void* ucontext_ptr) {\n  caught_sig = signum;\n  test_assert(sys_gettid() == getpid());\n}\n\nvoid* receiver(__attribute__((unused)) void* name) {\n  sigset_t sigs;\n\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGALRM);\n  test_assert(0 == pthread_sigmask(SIG_BLOCK, &sigs, NULL));\n  test_assert(value[0] == 0);\n  // Synchronize with the main thread to allow it to proceed.\n  pthread_barrier_wait(&bar);\n  // Immediately block again.\n  pthread_barrier_wait(&bar);\n\n  // Give the main thread a chance to exit.\n  // No non-racy way to do this afaict.\n  sleep(1);\n\n  test_assert(0 < read(fd, &value[0], 8));\n  close(fd);\n\n  // Assert that we wrote into value.\n  test_assert(value[0] == 0x7f);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n  return NULL;\n}\n\nint main(void) {\n  struct sigaction sact;\n  int counter;\n  pthread_t thread;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = catcher;\n  sigaction(SIGALRM, &sact, NULL);\n\n  pthread_barrier_init(&bar, NULL, 2);\n  pthread_create(&thread, NULL, receiver, NULL);\n  /* Synchronize with the child thread so we're sure it won't take the signal */\n  pthread_barrier_wait(&bar);\n\n  fd = open(\"/proc/self/exe\", O_RDONLY);\n  test_assert(fd >= 0);\n\n  alarm(1); /* timer will pop in 1 second */\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* p =\n      mmap(NULL, page_size, PROT_READ, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  test_assert(0 == mprotect(p, page_size, PROT_NONE));\n\n  for (counter = 0; counter >= 0 && !caught_sig; counter++) {\n    if (counter % 10000000 == 0) {\n      write(STDOUT_FILENO, \".\", 1);\n    }\n  }\n\n  /* Allow the child thread to proceed */\n  pthread_barrier_wait(&bar);\n  syscall(SYS_exit, 0);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/recvfrom.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char buf[] = \"0123456789abcdefghijklmnopqrstuvwxyz\";\n\n/* Make it longer than sizeof(struct sockaddr) */\nstatic const char sock_name[] = \"sock_sock_sock_sock\";\nstatic const char sock_name2[] = \"sock_sock_sock_sock_2\";\n\nint main(void) {\n  struct sockaddr_un addr;\n  struct sockaddr_un addr2;\n  struct sockaddr_un out_addr;\n  socklen_t out_addr_len;\n  char out[100];\n  int src;\n  int dest = socket(AF_UNIX, SOCK_DGRAM, 0);\n  test_assert(dest >= 0);\n\n  addr.sun_family = AF_UNIX;\n  strcpy(addr.sun_path, sock_name);\n  test_assert(0 == bind(dest, (struct sockaddr*)&addr, sizeof(addr)));\n\n  src = socket(AF_UNIX, SOCK_DGRAM, 0);\n  test_assert(src >= 0);\n\n  test_assert(36 == sendto(src, buf, 36, 0, (struct sockaddr*)&addr, sizeof(addr)));\n  out_addr_len = sizeof(out_addr);\n  test_assert(36 ==\n              recvfrom(dest, out, sizeof(out), 0, (struct sockaddr*)&out_addr, &out_addr_len));\n  test_assert(0 == memcmp(buf, out, 36));\n  test_assert(0 == out_addr_len);\n\n  addr2.sun_family = AF_UNIX;\n  strcpy(addr2.sun_path, sock_name2);\n  test_assert(0 == bind(src, (struct sockaddr*)&addr2, sizeof(addr2)));\n\n  test_assert(36 == sendto(src, buf, 36, 0, (struct sockaddr*)&addr, sizeof(addr)));\n  out_addr_len = sizeof(out_addr);\n  test_assert(36 ==\n              recvfrom(dest, out, sizeof(out), 0, (struct sockaddr*)&out_addr, &out_addr_len));\n  test_assert(0 == memcmp(buf, out, 36));\n  test_assert(out_addr_len == 2 + sizeof(sock_name2));\n  test_assert(0 == memcmp(out_addr.sun_path, sock_name2, sizeof(sock_name2)));\n\n  test_assert(36 == sendto(src, buf, 36, 0, (struct sockaddr*)&addr, sizeof(addr)));\n  out_addr_len = 8;\n  out_addr.sun_path[9] = 'x';\n  test_assert(36 ==\n              recvfrom(dest, out, sizeof(out), 0, (struct sockaddr*)&out_addr, &out_addr_len));\n  test_assert(0 == memcmp(buf, out, 36));\n  test_assert(out_addr_len == 2 + sizeof(sock_name2));\n  test_assert(0 == memcmp(out_addr.sun_path, sock_name2, 8));\n  test_assert(out_addr.sun_path[9] == 'x');\n\n  test_assert(0 == unlink(sock_name));\n  test_assert(0 == unlink(sock_name2));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/redzone_integrity.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nextern int perform_redzone_integrity_test(void);\n\n#if defined(__x86_64__)\n__asm__(\".text\\n\"\n        \".global perform_redzone_integrity_test\\n\"\n        \".type perform_redzone_integrity_test, @function\\n\"\n        \"perform_redzone_integrity_test:\\n\"\n        \"  leaq -128(%rsp), %rdi\\n\"\n        \"  movq $128, %rcx \\n\"\n        \"  movq $0xde, %rax # Arbitrary byte pattern we will verify after\\n\"\n        \"  rep stosb\\n\"\n        /* Note: This should be a patchable syscall */\n        \"  movq $186, %rax\\n\"\n        \"  syscall\\n\"\n        \"  nop\\n\"\n        \"  nop\\n\"\n        \"  nop\\n\"\n        \"  leaq    -128(%rsp), %rdi\\n\"\n        \"  leaq    128(%rdi), %rax\\n\"\n        \"  jmp exit_cond\\n\"\n        \"loop_start:\\n\"\n        \"  addq    $1, %rdi\\n\"\n        \"  cmpq    %rax, %rdi\\n\"\n        \"  je  exit_success\\n\"\n        \"exit_cond:\\n\"\n        \"  cmpb    $0xde, (%rdi)\\n\"\n        \"  je  loop_start\\n\"\n        \"exit_fail:\\n\"\n        \"  movq    $1, %rax\\n\"\n        \"  retq\\n\"\n        \"exit_success:\\n\"\n        \"  xorq %rax, %rax\\n\"\n        \"  retq\\n\"\n        \".previous\\n\");\n#else\n// x86-64 is the only architecture we currently support that mandates a redzone\nint perform_redzone_integrity_test(void) { return 0; }\n#endif\n\nstatic int did_sighandler_test = 0;\nvoid catcher(int __attribute__((unused)) signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             __attribute__((unused)) void* ucontext_ptr) {\n  test_assert(0 == perform_redzone_integrity_test());\n  did_sighandler_test = 1;\n}\n\nint main(void) {\n  test_assert(0 == perform_redzone_integrity_test());\n\n  if (0 == fork()) {\n    // Just a child to prevent waitpid failing with fork\n    sleep(1000);\n    test_assert(0 && \"Should not reach here\");\n  }\n\n  // Test redzone integrity in a signal handler during an interrupted blocking\n  // syscall.\n  struct sigaction sact;\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = catcher;\n  sigaction(SIGALRM, &sact, NULL);\n  alarm(1);\n\n  int status;\n  wait(&status);\n\n  test_assert(did_sighandler_test);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/remove_latest_trace.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, __attribute__((unused)) char** argv) {\n  char* args[] = { \"/proc/self/exe\", \"dummy\", NULL };\n\n  if (argc > 1) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  atomic_puts(\"ready\");\n\n  sleep(1);\n  execve(\"/proc/self/exe\", args, environ);\n  test_assert(0 && \"Failed exec!\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/remove_latest_trace.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME\n\nreplay &\n\nuntil grep -q ready replay.out; do\n  sleep 0\ndone\n\nrm -f latest-trace\n\nwait\ncheck 'EXIT-SUCCESS'\n\n"
  },
  {
    "path": "src/test/remove_watchpoint.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('watch -l var')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 42')\n\nsend_gdb('p atomic_printf(\"hello%s\", \"kitty\")')\nexpect_gdb('hellokitty')\n\nsend_gdb('delete 2')\n\nsend_gdb('break pthread_join')\nexpect_gdb('Breakpoint 3')\nsend_gdb('c')\nexpect_gdb('Breakpoint 3')\n\nsend_gdb('p atomic_printf(\"hello%s\", \"kitty\")')\nexpect_gdb('hellokitty')\n\nsend_gdb('c')\nexpect_gdb('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/remove_watchpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord watchpoint$bitness\ndebug_gdb_only remove_watchpoint\n"
  },
  {
    "path": "src/test/rename.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  static const char file_path[] = \"rr-test-file\";\n  static const char file2_path[] = \"rr-test-file2\";\n  int ret;\n  int fd = open(file_path, O_WRONLY | O_CREAT, 0700);\n  test_assert(0 == close(fd));\n\n  test_assert(0 == rename(file_path, file2_path));\n  test_assert(0 == renameat(AT_FDCWD, file2_path, AT_FDCWD, file_path));\n  ret = syscall(RR_renameat2, AT_FDCWD, file_path, AT_FDCWD, file2_path, 0);\n  if (-1 == ret && errno == ENOSYS) {\n    test_assert(0 == unlink(file_path));\n  } else {\n    test_assert(0 == ret);\n    test_assert(0 == unlink(file2_path));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/replay_overlarge_event_number.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\n_RR_TRACE_DIR=\"$workdir\" rr $GLOBAL_OPTIONS replay -s 9999 -g 3000 1> replay.out 2> replay.err\nif [[ $? != 0 ]]; then\n    failed \"should exit normally\"\nfi\npassed\n"
  },
  {
    "path": "src/test/replay_serve_files.py",
    "content": "from util import *\n\nsend_gdb('b constructor')\nexpect_gdb('Make breakpoint pending on future shared library load?')\n\nsend_gdb('y')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/replay_serve_files.run",
    "content": "source `dirname $0`/util.sh\n\n>&2 echo \"We're in $PWD\"\n\ncp $OBJDIR/lib/rr/libtest_lib$bitness.so .\n\nRECORD_ARGS=\"--env=LD_LIBRARY_PATH=$PWD --no-file-cloning\"\nrecord constructor$bitness\nrr pack $workdir/latest-trace || failed \"'rr pack' failed\"\n# Make sure rr pack really copied the file\ntruncate --size 0 libtest_lib$bitness.so\nrm libtest_lib$bitness.so\ndebug_gdb_only $TESTNAME_NO_BITNESS \"--serve-files\"\n"
  },
  {
    "path": "src/test/restart_abnormal_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(getppid(), SIGINT);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/restart_abnormal_exit.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 2 at')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited')\n\nok()\n"
  },
  {
    "path": "src/test/restart_abnormal_exit.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/restart_breakpoint.py",
    "content": "from util import *\n\nsend_gdb('b C')\nexpect_gdb('Breakpoint 1')\n\ndef check_breakpoint():\n    expect_rr('calling C')\n\n    expect_gdb('Breakpoint 1(.*) C')\n\n    send_gdb('bt')\n    expect_gdb('#0[^C]+C[^#]+#1[^B]+B[^#]+#2[^A]+A[^#]+#3[^m]+main')\n\nsend_gdb('c')\ncheck_breakpoint()\n\nrestart_replay()\ncheck_breakpoint()\n\nrestart_replay()\ncheck_breakpoint()\n\nok()\n"
  },
  {
    "path": "src/test/restart_diversion.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('check')\nexpect_gdb('Checkpoint 1 at')\n\nsend_gdb('p atomic_printf(\"hello%s\", \"kitty\")')\nexpect_gdb('hellokitty')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p atomic_printf(\"hello%s\", \"kitty\")')\nexpect_gdb('hellokitty')\n\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/restart_diversion.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only restart_diversion\n"
  },
  {
    "path": "src/test/restart_finish.py",
    "content": "from util import *\nimport re\n\nrestart_replay()\nsend_gdb('c')\n# A stop fires when we hit an exec\nexpect_rr([ re.compile(r'exited normally'),\n            re.compile(r'stopped') ])\n\nok()\n"
  },
  {
    "path": "src/test/restart_invalid_checkpoint.py",
    "content": "from util import *\n\nsend_gdb('c')\nsend_gdb('checkpoint')\nexpect_gdb('is not being run')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nrestart_replay()\nexpect_gdb('Breakpoint 1')\nsend_gdb('b atomic_puts')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('restart 8')\n\nsend_gdb('info threads')\n# Don't expect anything specific from 'info threads', but make sure gdb at least functions\nsend_gdb('p 987654321+1')\nexpect_gdb('987654322')\n\nsend_gdb('restart -1')\nsend_gdb('restart abc')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\n# If rr crashes, a 'restart' will re-run the program directly under gdb from\n# the beginning. If that happens, we'll stop at breakpoint 1, not exit normally.\nexpect_gdb('xited normally')\n\nok()\n"
  },
  {
    "path": "src/test/restart_invalid_checkpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only restart_invalid_checkpoint\n\n"
  },
  {
    "path": "src/test/restart_unstable.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_gdb('exited normally')\n\nrestart_replay()\n\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/restart_unstable.run",
    "content": "source `dirname $0`/util.sh\nrecord exit_group$bitness\ndebug_gdb_only restart_unstable\n"
  },
  {
    "path": "src/test/reverse_alarm.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_alarm.run",
    "content": "source `dirname $0`/util.sh\nrecord alarm$bitness\ndebug_gdb_only reverse_alarm\n"
  },
  {
    "path": "src/test/reverse_continue_breakpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int k = 2;\n\nstatic void breakpoint(void) {}\n\nstatic void breakpoint2(void) {}\n\nint main(void) {\n  int i;\n  int j;\n  int fd = open(\"/dev/null\", O_WRONLY);\n\n  test_assert(fd >= 0);\n\n  /* We need to test reverse-continue through\n     a bunch of breakpoints when the next event\n     is a syscallbuf-flush. So we need the next event to\n     be syscall-buffered. Do a write here so that the syscall\n     is patched now, not later. */\n  test_assert(1 == write(fd, \".\", 1));\n\n  for (i = 0; i < 2000000; ++i) {\n    breakpoint2();\n    for (j = 0; j < 10; ++j) {\n      k = k * 37;\n    }\n  }\n  breakpoint();\n\n  test_assert(1 == write(fd, \".\", 1));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_continue_breakpoint.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('break breakpoint2')\nexpect_gdb('Breakpoint 2')\nsend_gdb('reverse-cont')\nexpect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_breakpoint.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_continue_exec_subprocess.py",
    "content": "from util import *\nimport re\n\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_exec_subprocess.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe simple$bitness\nsaved_simple=\"simple$bitness-$nonce\"\nsave_exe target_process$bitness\n\nrecord \"target_process$bitness\" \"$saved_simple\"\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only reverse_continue_exec_subprocess \"-p $TARGET_PID\"\n"
  },
  {
    "path": "src/test/reverse_continue_fork_subprocess.py",
    "content": "from util import *\nimport re\n\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nsend_gdb('stepi')\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nsend_gdb('stepi')\nsend_gdb('reverse-stepi')\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_fork_subprocess.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe simple$bitness\nsaved_simple=\"simple$bitness-$nonce\"\nsave_exe target_process$bitness\n\nrecord \"target_process$bitness\" \"$saved_simple\"\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only reverse_continue_fork_subprocess \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/reverse_continue_int3.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_gdb('SIGTRAP')\n\nsend_gdb('rc')\nexpect_gdb('SIGTRAP')\n\nsend_gdb('rc')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_int3.run",
    "content": "source `dirname $0`/util.sh\n\nrecord int3$bitness\ndebug_gdb_only reverse_continue_int3\n"
  },
  {
    "path": "src/test/reverse_continue_multiprocess.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic int parent_to_child[2];\nstatic int child_to_parent[2];\n\nint main(void) {\n  pid_t pid;\n  int status;\n  int i;\n  char ch;\n\n  test_assert(0 == pipe(parent_to_child));\n  test_assert(0 == pipe(child_to_parent));\n\n  /* Force ping-ponging between parent and child. At each iteration the\n     child receives a signal. We debug the parent process; the signals\n     being received by the child while reverse-executing the parent\n     should be ignored at a low enough level they don't impact the\n     performance of reverse-continue. */\n  breakpoint();\n  pid = fork();\n  if (0 == pid) {\n    for (i = 0; i < 1000; ++i) {\n      char ch;\n      test_assert(1 == read(parent_to_child[0], &ch, 1) && ch == 'y');\n      kill(getpid(), SIGCHLD);\n      test_assert(1 == write(child_to_parent[1], \"x\", 1));\n    }\n    return 77;\n  }\n\n  for (i = 0; i < 1000; ++i) {\n    test_assert(1 == write(parent_to_child[1], \"y\", 1));\n    test_assert(1 == read(child_to_parent[0], &ch, 1) && ch == 'x');\n  }\n\n  test_assert(pid == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_continue_multiprocess.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('rc')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_multiprocess.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_continue_process_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS (1 << 26)\n\nint spin(void) {\n  int i, dummy = 0;\n\n  atomic_puts(\"spinning\");\n  for (i = 1; i < NUM_ITERATIONS; ++i) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n  }\n  return dummy;\n}\n\nint main(void) {\n  pid_t pid;\n  int status;\n\n  pid = fork();\n  if (0 == pid) {\n    signal(SIGINT, SIG_IGN);\n    spin();\n    kill(getpid(), SIGINT);\n    return 77;\n  }\n\n  test_assert(pid == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_continue_process_signal.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('c')\nexpect_gdb('SIGKILL')\nsend_gdb('reverse-continue')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_process_signal.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_continue_start.py",
    "content": "from util import *\nimport re\n\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('reverse-cont')\nexpect_history_end()\nsend_gdb('reverse-stepi')\nexpect_history_end()\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_continue_start.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only reverse_continue_start\n"
  },
  {
    "path": "src/test/reverse_finish.py",
    "content": "from util import *\n\nsend_gdb('break atomic_puts')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1') \n\nsend_gdb('reverse-finish')\nexpect_gdb('main')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_finish.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only reverse_finish\n"
  },
  {
    "path": "src/test/reverse_many_breakpoints.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic volatile int result;\n\nint main(void) {\n  int i;\n  for (i = 0; i < 100000; ++i) {\n    result += i * i;\n    breakpoint();\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_many_breakpoints.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\nsend_gdb('c')\nexpect_gdb('SIGKILL')\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('reverse-continue')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_many_breakpoints.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_step_breakpoint.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('n')\nsend_gdb('break')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('reverse-next')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('next')\nexpect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_step_breakpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only reverse_step_breakpoint\n"
  },
  {
    "path": "src/test/reverse_step_long.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS (1 << 27)\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic int spin(void) {\n  int i, dummy = 0;\n\n  atomic_puts(\"spinning\");\n  for (i = 1; i < 1 << 28; ++i) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n  }\n  return dummy;\n}\n\n/**\n * We'll break in do_thread, continue until SIGKILL, and\n * then try a reverse-stepi. This will have to search back through\n * several checkpoints to find the last completed singlestep for\n * the thread.\n */\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  char ch;\n  breakpoint();\n  /* Will never return */\n  read(STDIN_FILENO, &ch, 1);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  signal(SIGTTIN, SIG_IGN);\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  spin();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_step_long.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('SIGKILL')\n# This should not hang\nsend_gdb('reverse-stepi')\nsend_gdb('reverse-continue')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_step_long.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_step_signal.py",
    "content": "from util import *\nimport re\n\nsend_gdb('watch -l num_signals_caught')\nexpect_gdb('Hardware watchpoint 1')\n\nsend_gdb('c')\nexpect_gdb('received signal')\n\nsend_gdb('c')\nexpect_gdb('Hardware watchpoint 1')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 1')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Hardware watchpoint 1')\nexpect_gdb('Old value = 1')\nexpect_gdb('New value = 0')\n\nsend_gdb('reverse-finish')\nsend_gdb('bt')\nexpect_gdb('raise')\n\nsend_gdb('reverse-stepi')\nexpect_gdb('received signal')\n\nsend_gdb('reverse-continue')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_step_signal.run",
    "content": "source `dirname $0`/util.sh\nrecord sigrt$bitness\ndebug_gdb_only reverse_step_signal\n"
  },
  {
    "path": "src/test/reverse_step_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS (1 << 27)\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint spin(int iterations) {\n  int i, dummy = 0;\n\n  atomic_puts(\"spinning\");\n  for (i = 1; i < iterations; ++i) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n  }\n  return dummy;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  breakpoint();\n  return NULL;\n}\n\nint main(void) {\n  int s = spin(NUM_ITERATIONS);\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  pthread_join(thread, NULL);\n\n  s = spin(1000);\n  atomic_printf(\"EXIT-SUCCESS dummy=%d\\n\", s);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_step_threads.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('set scheduler-locking off')\nsend_gdb('reverse-step')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_step_threads.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_step_threads2.py",
    "content": "from util import *\n\nsend_gdb('b spin')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\n\nsend_gdb('set scheduler-locking off')\nsend_gdb('reverse-step')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_step_threads2.run",
    "content": "source `dirname $0`/util.sh\nrecord reverse_step_threads$bitness\ndebug_gdb_only reverse_step_threads2\n"
  },
  {
    "path": "src/test/reverse_step_threads_break.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int main_to_thread_fds[2];\nstatic int thread_to_main_fds[2];\n\nstatic void breakpoint(void) {}\n\nstatic void breakpoint_thread(void) {}\n\nstatic size_t my_read(int fd, void* buf, size_t size) {\n  size_t ret;\n#ifdef __x86_64__\n  __asm__(\"syscall\\n\\t\"\n          /* Make sure we don't patch this syscall for syscall buffering */\n          \"cmp $77,%%rax\\n\\t\"\n          : \"=a\"(ret)\n          : \"a\"(SYS_read), \"D\"(fd), \"S\"(buf), \"d\"(size)\n          : \"memory\", \"flags\");\n#elif defined(__i386__)\n  __asm__(\"xchg %%ebx,%%edi\\n\\t\"\n          \"int $0x80\\n\\t\"\n          \"xchg %%ebx,%%edi\\n\\t\"\n          : \"=a\"(ret)\n          : \"a\"(SYS_read), \"c\"(buf), \"d\"(size), \"D\"(fd)\n          : \"memory\");\n#elif defined(__aarch64__)\n  register uint64_t x0 __asm__ (\"x0\") = fd;\n  register void *x1 __asm__ (\"x1\") = buf;\n  register uint64_t x2 __asm__ (\"x2\") = size;\n  register uint64_t x8 __asm__ (\"x8\") = SYS_read;\n  __asm__(\"b 1f\\n\\t\"\n          \"mov x8, 0xdc\\n\"\n          \"1:\\n\\t\"\n          \"svc #0\\n\\t\"\n          : \"+r\"(x0)\n          : \"r\"(x1), \"r\"(x2), \"r\"(x8)\n          : \"memory\");\n  ret = x0;\n#else\n#error define syscall here\n#endif\n  return ret;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  char ch;\n  breakpoint_thread();\n  test_assert(1 == write(thread_to_main_fds[1], \"y\", 1));\n  test_assert(1 == read(main_to_thread_fds[0], &ch, 1));\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  char ch;\n\n  test_assert(0 == pipe(thread_to_main_fds));\n  test_assert(0 == pipe(main_to_thread_fds));\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  test_assert(1 == my_read(thread_to_main_fds[0], &ch, 1));\n  breakpoint();\n  test_assert(1 == write(main_to_thread_fds[1], \"x\", 1));\n\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/reverse_step_threads_break.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b breakpoint_thread')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('set scheduler-locking off')\nfor i in range(50):\n  send_gdb('reverse-step')\n\nexpect_gdb('Breakpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_step_threads_break.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/reverse_watchpoint.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('continue')\nexpect_gdb('Breakpoint 1')\nsend_gdb('delete 1')\nsend_gdb('watch -l var')\nexpect_gdb('Hardware watchpoint 2')\nsend_gdb('break atomic_puts')\nexpect_gdb('Breakpoint 3')\n\nsend_gdb('c')\nexpect_gdb('Hardware watchpoint 2')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 42')\n\nsend_gdb('c')\nexpect_gdb('Hardware watchpoint 2')\nexpect_gdb('Old value = 42')\nexpect_gdb('New value = 1337')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 3')\n\nsend_gdb('reverse-cont')\nexpect_gdb('Hardware watchpoint 2')\nexpect_gdb('Old value = 1337')\nexpect_gdb('New value = 42')\n\nsend_gdb('reverse-cont')\nexpect_gdb('Hardware watchpoint 2')\nexpect_gdb('Old value = 42')\nexpect_gdb('New value = 0')\n\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/reverse_watchpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord watchpoint$bitness\ndebug_gdb_only reverse_watchpoint\n"
  },
  {
    "path": "src/test/reverse_watchpoint_syscall.py",
    "content": "from util import *\n\nsend_gdb('break atomic_puts')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('watch -l *p')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = <unreadable>')\nexpect_gdb('New value = 0')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 98')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 98')\nexpect_gdb('New value = 0')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 97')\n\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 97')\nexpect_gdb('New value = 0')\n\nok()\n"
  },
  {
    "path": "src/test/reverse_watchpoint_syscall.run",
    "content": "source `dirname $0`/util.sh\nrecord watchpoint_syscall$bitness\ndebug_gdb_only reverse_watchpoint_syscall\n"
  },
  {
    "path": "src/test/rlimit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct rlimit* r;\n  struct rlimit* r2;\n\n  ALLOCATE_GUARD(r, 0);\n  ALLOCATE_GUARD(r2, 'x');\n\n  test_assert(0 == getrlimit(RLIMIT_FSIZE, r));\n  test_assert(r->rlim_cur > 0);\n  test_assert(r->rlim_max > 0);\n  VERIFY_GUARD(r);\n\n  r->rlim_cur /= 2;\n  test_assert(0 == setrlimit(RLIMIT_FSIZE, r));\n  VERIFY_GUARD(r);\n\n  test_assert(0 == getrlimit(RLIMIT_FSIZE, r2));\n  test_assert(r2->rlim_cur == r->rlim_cur);\n  VERIFY_GUARD(r2);\n\n  test_assert(0 == prlimit(0, RLIMIT_FSIZE, r, r2));\n  test_assert(r2->rlim_cur == r->rlim_cur);\n  VERIFY_GUARD(r);\n  VERIFY_GUARD(r2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/robust_futex.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\nstatic pthread_mutex_t* mutex;\n\nstatic void* run_thread(__attribute__((unused)) void* unused) {\n  void* p;\n  size_t len;\n  syscall(SYS_get_robust_list, 0, &p, &len);\n  atomic_printf(\"robust_list = %p, len = %d\\n\", p, (int)len);\n  test_assert(0 == pthread_mutex_lock(mutex));\n  return NULL;\n}\n\nint main(void) {\n  pthread_mutexattr_t attr;\n  pthread_t thread;\n  pid_t child;\n  int status;\n  char ch;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  mutex = (pthread_mutex_t*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                                 MAP_SHARED | MAP_ANONYMOUS, -1, 0);\n\n  pthread_mutexattr_init(&attr);\n  pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);\n  pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);\n  pthread_mutex_init(mutex, &attr);\n\n  pthread_create(&thread, NULL, run_thread, NULL);\n  pthread_join(thread, NULL);\n\n  test_assert(EOWNERDEAD == pthread_mutex_lock(mutex));\n  pthread_mutex_consistent(mutex);\n  test_assert(0 == pthread_mutex_unlock(mutex));\n  test_assert(0 == pthread_mutex_lock(mutex));\n  test_assert(0 == pthread_mutex_unlock(mutex));\n\n  child = fork();\n  if (!child) {\n    test_assert(0 == pthread_mutex_lock(mutex));\n    test_assert(1 == write(pipe_fds[1], \"x\", 1));\n    sleep(1000000);\n    return 1;\n  }\n\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n  kill(child, SIGKILL);\n  test_assert(child == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == 9);\n\n  test_assert(EOWNERDEAD == pthread_mutex_lock(mutex));\n  pthread_mutex_consistent(mutex);\n  test_assert(0 == pthread_mutex_unlock(mutex));\n  test_assert(0 == pthread_mutex_lock(mutex));\n  test_assert(0 == pthread_mutex_unlock(mutex));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/rr_ps.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, __attribute__((unused)) char* argv[]) {\n  pid_t child;\n  int status;\n\n  if (argc > 1) {\n    return 88;\n  }\n\n  child = fork();\n  if (!child) {\n    return 77;\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  child = fork();\n  if (!child) {\n    kill(getpid(), SIGSEGV);\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n  child = fork();\n  if (!child) {\n    char* args[] = { argv[0], \"token\", NULL };\n    execve(argv[0], args, environ);\n    test_assert(0 && \"execve failed\");\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 88);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/rr_ps.run",
    "content": "source `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS\n\nif !(do_ps | grep -q $'\\t77'); then\n    failed \"Can't find return value 77\"\nfi\n\nif !(do_ps | grep -q -- $'\\t-11'); then\n    failed \"Can't find return value -11\"\nfi\n\nif !(do_ps | grep $'\\t88' | grep -q token); then\n    failed \"Can't find exec parameter 'token'\"\nfi\n"
  },
  {
    "path": "src/test/rr_ps_ns.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nint main(void) {\n  pid_t pid;\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    // 77 will indicate to driver script that this test was skipped\n    return 77;\n  }\n\n  // This is the first child, therefore PID 1 in its PID namespace\n  pid = fork();\n  test_assert(pid >= 0);\n  if (pid == 0) {\n    // We will check that rr ps includes `(1)` here\n    return 78;\n  }\n\n  test_assert(pid == waitpid(pid, NULL, 0));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 79;\n}\n"
  },
  {
    "path": "src/test/rr_ps_ns.run",
    "content": "source `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS\n\nif !(do_ps | grep -q $'\\t77'); then\n    # If 77 shows up, the test was skipped. Since we're here, we should expect\n    # the parent exiting with 79, and the child (PID 1 in its namespace) exiting\n    # with 78\n    if !(do_ps | grep -q $'\\t79'); then\n      failed \"Can't find return value 79\"\n    fi\n    \n    if !(do_ps | grep $'\\t78' | cut -f 1 | grep -q $'(1)'); then\n      failed \"Can't find child namespace init\"\n    fi    \nfi\n"
  },
  {
    "path": "src/test/rseq.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic struct rseq* rs_ptr;\nstatic struct rseq_cs rs_cs;\n\nstatic const uint32_t RSEQ_SIG = 0x12345678;\n\n// Use hidden symbols to make sure we refer to the assembly symbol\n// rather than through GOT\n__attribute__((visibility(\"hidden\"))) extern char start_ip;\n__attribute__((visibility(\"hidden\"))) extern char end_ip;\n__attribute__((visibility(\"hidden\"))) extern char abort_ip;\n\nstatic uint64_t aborts;\nstatic uint64_t jump_aborts;\n\nstatic volatile uint32_t dummy;\n\nstatic void do_section(void) {\n  long did_abort = 0;\n\n  rs_ptr->rseq_cs = (uint64_t)(uintptr_t)&rs_cs;\n#if defined(__x86_64__) || defined(__i386__)\n  __asm__ __volatile__ (\n    \"start_ip:\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"jmp 1f\\n\\t\"\n    \"end_ip:\\n\\t\"\n    \".int 0x12345678\\n\\t\"\n    \"abort_ip:\\n\\t\"\n    \"movb $1,%1\\n\\t\"\n    \"1:\\n\\t\"\n    : : \"m\"(dummy), \"m\"(did_abort));\n#elif defined(__aarch64__)\n  long dummy2;\n  __asm__ __volatile__ (\n    \"start_ip:\\n\\t\"\n    \"mov %1, 1234\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"b 1f\\n\\t\"\n    \"end_ip:\\n\\t\"\n    \".int 0x12345678\\n\\t\"\n    \"abort_ip:\\n\\t\"\n    \"mov %0, 1\\n\\t\"\n    \"1:\\n\\t\"\n    : \"+r\"(did_abort), \"=&r\"(dummy2) : \"m\"(dummy));\n#endif\n  if (did_abort) {\n    ++jump_aborts;\n    test_assert(!rs_ptr->rseq_cs);\n  }\n  if (!rs_ptr->rseq_cs) {\n    ++aborts;\n  }\n  rs_ptr->rseq_cs = 0;\n}\n\nstatic int main_child_thread(__attribute__((unused)) void* arg) {\n  struct rseq rs;\n  memset(&rs, 0, sizeof(rs));\n  int ret = syscall(RR_rseq, &rs, sizeof(rs), 0, RSEQ_SIG);\n  test_assert(ret == 0);\n  return 0;\n}\n\nstatic int passed_argc;\nstatic char** passed_argv;\nstatic char** passed_envp;\n\nstatic int main_child(void) {\n  int i;\n  int status;\n  pid_t child;\n  int ret;\n  volatile char* stop_flag = (char*)mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  test_assert(stop_flag != MAP_FAILED);\n\n  ret = syscall(RR_rseq, rs_ptr, sizeof(*rs_ptr), 0, RSEQ_SIG);\n  if (ret == -1 && errno == ENOSYS) {\n    atomic_puts(\"rseq not supported; ignoring test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  test_assert(rs_ptr->cpu_id_start < 10000000);\n  test_assert(rs_ptr->cpu_id < 10000000);\n\n  rs_cs.start_ip = (uint64_t)(uintptr_t)&start_ip;\n  rs_cs.post_commit_offset = (uint64_t)(uintptr_t)&end_ip - rs_cs.start_ip;\n  rs_cs.abort_ip = (uint64_t)(uintptr_t)&abort_ip;\n\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(stack != MAP_FAILED);\n\n  clone(main_child_thread, stack + stack_size,\n        CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND,\n        NULL, NULL, NULL, NULL);\n\n  child = fork();\n  if (!child) {\n    char* exec_argv[] = { passed_argv[0], passed_argv[0], NULL };\n    while (!*stop_flag) {\n      do_section();\n    }\n\n    /* Test that it's OK to do system calls with rseq_cs set as long as we're\n       not in the section */\n    rs_ptr->rseq_cs = (uint64_t)(uintptr_t)&rs_cs;\n    atomic_printf(\"Detected %lld aborts, %lld jump aborts\\n\",\n                  (long long)aborts, (long long)jump_aborts);\n    /* Test that execve works */\n    execve(passed_argv[0], exec_argv, passed_envp);\n    /* Should never be reached */\n    abort();\n  }\n  atomic_printf(\"child %d\\n\", child);\n  /* Try to interrupt the child 50 times */\n  for (i = 0; i < 50; ++i) {\n    sched_yield();\n  }\n  *stop_flag = 1;\n  ret = waitpid(child, &status, 0);\n  test_assert(ret == child);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\nstatic int main_child_wrapper(__attribute__((unused)) void* arg) {\n  exit(main_child());\n}\n\nint main(int argc, char** argv, char** envp) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(stack != MAP_FAILED);\n\n  if (argc > 1) {\n    return 77;\n  }\n\n  passed_argc = argc;\n  passed_argv = argv;\n  passed_envp = envp;\n\n  rs_ptr = (struct rseq*)mmap(NULL, sizeof(*rs_ptr), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(rs_ptr != MAP_FAILED);\n  rs_ptr->cpu_id_start = 10000000;\n  rs_ptr->cpu_id = 10000001;\n\n  /* Do the real work in a thread that doesn't have glibc's rseq setup installed */\n  clone(main_child_wrapper, stack + stack_size,\n        CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND,\n        NULL, NULL, NULL, NULL);\n  pause();\n}\n"
  },
  {
    "path": "src/test/rseq.py",
    "content": "from util import *\n\nsend_gdb('break abort_ip')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('reverse-stepi')\nsend_gdb('stepi')\nsend_gdb('stepi')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('disable 1')\nsend_gdb('c')\nexpect_gdb('rogram stopped')\n\nok()\n"
  },
  {
    "path": "src/test/rseq.run",
    "content": "source `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS\n# Skip debug_gdb_only script test if there were no jumps to abort_ip\ngrep -q \", 0 jump aborts\" record.out\nif [[ $? != 0 ]]; then\n    TARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n    debug_gdb_only rseq \"-f $TARGET_PID\"\nfi\n"
  },
  {
    "path": "src/test/rseq_cpu_id_reset.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const uint32_t RSEQ_SIG = 0x12345678;\n\nstatic int to_main_fds[2];\nstatic int from_main_fds[2];\n\nstatic const int PING_PONG_ITERATIONS = 5;\n\nstatic const uint32_t CPU_INVALID = 10000000;\n\nstatic int main_child(void) {\n  struct rseq* rs_ptr =\n      (struct rseq*)mmap(NULL, sizeof(struct rseq), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(rs_ptr != MAP_FAILED);\n  rs_ptr->cpu_id_start = CPU_INVALID;\n  rs_ptr->cpu_id = CPU_INVALID;\n\n  int ret = syscall(RR_rseq, rs_ptr, sizeof(*rs_ptr), 0, RSEQ_SIG);\n  if (ret == -1 && errno == ENOSYS) {\n    atomic_puts(\"rseq not supported; ignoring test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  test_assert(rs_ptr->cpu_id_start < CPU_INVALID);\n  test_assert(rs_ptr->cpu_id < CPU_INVALID);\n\n  for (int i = 0; i < PING_PONG_ITERATIONS; ++i) {\n    char ch;\n    rs_ptr->cpu_id_start = CPU_INVALID;\n    rs_ptr->cpu_id = CPU_INVALID;\n    test_assert(1 == write(to_main_fds[1], \"y\", 1));\n    // Under rr (or taskset to a single core) there must be a\n    // context switch here. Some code exists that expects\n    // rseq::cpu_id(_start) to be reset to the current core index\n    // every time a task is scheduled onto a core.\n    test_assert(1 == read(from_main_fds[0], &ch, 1));\n    test_assert(rs_ptr->cpu_id_start < CPU_INVALID);\n    test_assert(rs_ptr->cpu_id < CPU_INVALID);\n  }\n\n  return 0;\n}\n\nstatic int main_child_wrapper(__attribute__((unused)) void* arg) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(main_child());\n}\n\nint main(void) {\n  test_assert(0 == pipe(to_main_fds));\n  test_assert(0 == pipe(from_main_fds));\n\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(stack != MAP_FAILED);\n\n  /* Do the real work in a thread that doesn't have glibc's rseq setup installed */\n  clone(main_child_wrapper, stack + stack_size,\n        CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND,\n        NULL, NULL, NULL, NULL);\n\n  for (int i = 0; i < PING_PONG_ITERATIONS; ++i) {\n    char ch;\n    test_assert(1 == read(to_main_fds[0], &ch, 1));\n    test_assert(1 == write(from_main_fds[1], \"x\", 1));\n  }\n\n  pause();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/rseq_cpu_id_reset_longrunning.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const uint32_t RSEQ_SIG = 0x12345678;\n\nstatic const uint32_t CPU_INVALID = 10000000;\n\nstatic int main_child(void) {\n  struct rseq* rs_ptr =\n      (struct rseq*)mmap(NULL, sizeof(struct rseq), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(rs_ptr != MAP_FAILED);\n  rs_ptr->cpu_id_start = CPU_INVALID;\n  rs_ptr->cpu_id = CPU_INVALID;\n\n  int ret = syscall(RR_rseq, rs_ptr, sizeof(*rs_ptr), 0, RSEQ_SIG);\n  if (ret == -1 && errno == ENOSYS) {\n    atomic_puts(\"rseq not supported; ignoring test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  test_assert(rs_ptr->cpu_id_start < CPU_INVALID);\n  test_assert(rs_ptr->cpu_id < CPU_INVALID);\n\n  rs_ptr->cpu_id_start = CPU_INVALID;\n  rs_ptr->cpu_id = CPU_INVALID;\n\n  for (int i = 0; i < 10000; ++i) {\n    event_syscall();\n  }\n\n  test_assert(rs_ptr->cpu_id_start == CPU_INVALID);\n  test_assert(rs_ptr->cpu_id == CPU_INVALID);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\nstatic int main_child_wrapper(__attribute__((unused)) void* arg) {\n  exit(main_child());\n}\n\nint main(void) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(stack != MAP_FAILED);\n\n  /* Do the real work in a thread that doesn't have glibc's rseq setup installed */\n  clone(main_child_wrapper, stack + stack_size,\n        CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND,\n        NULL, NULL, NULL, NULL);\n\n  pause();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/rseq_cpu_id_reset_longrunning.py",
    "content": "from util import *\nimport re\n\nsend_gdb('break atomic_puts')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('break event_syscall')\nexpect_gdb('Breakpoint 2')\nsend_gdb('rc')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/rseq_cpu_id_reset_longrunning.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/rseq_syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic struct rseq* rs_ptr;\nstatic struct rseq_cs rs_cs;\n\nstatic const uint32_t RSEQ_SIG = 0x12345678;\n\n// Use hidden symbols to make sure we refer to the assembly symbol\n// rather than through GOT\n__attribute__((visibility(\"hidden\"))) extern char start_ip;\n__attribute__((visibility(\"hidden\"))) extern char end_ip;\n__attribute__((visibility(\"hidden\"))) extern char abort_ip;\n\nstatic uint64_t aborts;\nstatic uint64_t jump_aborts;\n\nstatic volatile uint32_t dummy;\n\nstatic void do_section(void) {\n  long did_abort = 0;\n\n  rs_ptr->rseq_cs = (uint64_t)(uintptr_t)&rs_cs;\n#if defined(__x86_64__) || defined(__i386__)\n  __asm__ __volatile__ (\n    \"start_ip:\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"movl $1234,%0\\n\\t\"\n    \"jmp 1f\\n\\t\"\n    \"end_ip:\\n\\t\"\n    \".int 0x12345678\\n\\t\"\n    \"abort_ip:\\n\\t\"\n    \"movb $1,%1\\n\\t\"\n    \"1:\\n\\t\"\n    : : \"m\"(dummy), \"m\"(did_abort));\n#elif defined(__aarch64__)\n  long dummy2;\n  __asm__ __volatile__ (\n    \"start_ip:\\n\\t\"\n    \"mov %1, 1234\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"str %1, %2\\n\\t\"\n    \"b 1f\\n\\t\"\n    \"end_ip:\\n\\t\"\n    \".int 0x12345678\\n\\t\"\n    \"abort_ip:\\n\\t\"\n    \"mov %0, 1\\n\\t\"\n    \"1:\\n\\t\"\n    : \"+r\"(did_abort), \"=&r\"(dummy2) : \"m\"(dummy));\n#endif\n  if (did_abort) {\n    ++jump_aborts;\n    test_assert(!rs_ptr->rseq_cs);\n  }\n  if (!rs_ptr->rseq_cs) {\n    ++aborts;\n  }\n  rs_ptr->rseq_cs = 0;\n}\n\nstatic int passed_argc;\nstatic char** passed_argv;\nstatic char** passed_envp;\n\nstatic int main_child(void) {\n  int i;\n  int status;\n  pid_t child;\n  int ret;\n  volatile char* stop_flag = (char*)mmap(NULL, 1, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  test_assert(stop_flag != MAP_FAILED);\n\n  ret = syscall(RR_rseq, rs_ptr, sizeof(*rs_ptr), 0, RSEQ_SIG);\n  if (ret == -1 && errno == ENOSYS) {\n    atomic_puts(\"rseq not supported; ignoring test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n  test_assert(rs_ptr->cpu_id_start < 10000000);\n  test_assert(rs_ptr->cpu_id < 10000000);\n\n  rs_cs.start_ip = (uint64_t)(uintptr_t)&start_ip;\n  rs_cs.post_commit_offset = (uint64_t)(uintptr_t)&end_ip - rs_cs.start_ip;\n  rs_cs.abort_ip = (uint64_t)(uintptr_t)&abort_ip;\n\n  child = fork();\n  if (!child) {\n    /* Issue invalid rseq call to make sure that doesn't break syscall buffering */\n    ret = syscall(RR_rseq, rs_ptr, sizeof(*rs_ptr), 0xffffffff, RSEQ_SIG);\n    test_assert(ret == -1);\n    test_assert(errno == EINVAL);\n\n    struct timeval tv;\n    while (!*stop_flag) {\n      gettimeofday(&tv, NULL);\n      do_section();\n    }\n\n    atomic_printf(\"Detected %lld aborts, %lld jump aborts\\n\",\n                  (long long)aborts, (long long)jump_aborts);\n    return 77;\n  }\n  atomic_printf(\"child %d\\n\", child);\n  /* Try to interrupt the child 50 times */\n  for (i = 0; i < 50; ++i) {\n    sched_yield();\n  }\n  *stop_flag = 1;\n  ret = waitpid(child, &status, 0);\n  test_assert(ret == child);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\nstatic int main_child_wrapper(__attribute__((unused)) void* arg) {\n  exit(main_child());\n}\n\nint main(int argc, char** argv, char** envp) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(stack != MAP_FAILED);\n\n  passed_argc = argc;\n  passed_argv = argv;\n  passed_envp = envp;\n\n  rs_ptr = (struct rseq*)mmap(NULL, sizeof(*rs_ptr), PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(rs_ptr != MAP_FAILED);\n  rs_ptr->cpu_id_start = 10000000;\n  rs_ptr->cpu_id = 10000001;\n\n  /* Do the real work in a thread that doesn't have glibc's rseq setup installed */\n  clone(main_child_wrapper, stack + stack_size,\n        CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_THREAD | CLONE_SIGHAND,\n        NULL, NULL, NULL, NULL);\n  pause();\n}\n"
  },
  {
    "path": "src/test/rseq_syscallbuf.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_no_syscall_buf\n\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/run_end.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\n\n# Test that invalid syntax doesn't crash rr\nsend_gdb('run run 100')\nexpect_gdb('from the beginning')\nsend_gdb('y')\nexpect_gdb('(rr)')\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\n# Running with a big event number should reach the end of the recording\nsend_gdb('run 10000')\nexpect_gdb('from the beginning')\nsend_gdb('y')\nexpect_gdb('SIGKILL')\nsend_gdb('c')\nexpect_gdb('xited normally')\n\nsend_gdb('run 10000')\n# no need to confirm since the process already exited\nexpect_gdb('SIGKILL')\nsend_gdb('reverse-cont')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/run_end.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only run_end\n"
  },
  {
    "path": "src/test/run_in_function.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('call crash()')\nexpect_gdb('SIGSEGV')\nrestart_replay()\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/run_in_function.run",
    "content": "source `dirname $0`/util.sh\nrecord crash_in_function$bitness\ndebug_gdb_only run_in_function\n"
  },
  {
    "path": "src/test/rusage.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct rusage* r;\n\n  ALLOCATE_GUARD(r, 0);\n  test_assert(0 == getrusage(RUSAGE_SELF, r));\n  test_assert(r->ru_maxrss > 0);\n  VERIFY_GUARD(r);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/samask.c",
    "content": "#include \"util.h\"\n\nstatic void segv_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  test_assert(0 && \"Should not reach here\");\n}\n\nstatic void usr1_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  // Generate SIGSEGV. Can't use raise, because that will be blocked\n  (*(int*)1) = 0;\n  test_assert(0 && \"Should not reach here\");\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  raise(SIGUSR1);\n  test_assert(0 && \"Should not reach here!\");\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  pthread_t thread;\n\n  if ((child = fork()) == 0) {\n    struct sigaction act;\n    act.sa_sigaction = segv_handler;\n    act.sa_flags = SA_ONSTACK | SA_SIGINFO;\n    sigemptyset(&act.sa_mask);\n    sigaction(SIGSEGV, &act, NULL);\n\n    act.sa_sigaction = usr1_handler;\n    sigaddset(&act.sa_mask, SIGSEGV);\n    sigaction(SIGUSR1, &act, NULL);\n\n    pthread_create(&thread, NULL, do_thread, NULL);\n    test_assert(0 == sched_yield());\n    sleep(1000);\n    test_assert(0 && \"Should not reach here\");\n    return 0;\n  }\n\n  test_assert(child == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sanity.py",
    "content": "from util import *\n\nsend_gdb('c')\nexpect_rr('Hi')\n\nok()\n"
  },
  {
    "path": "src/test/sanity.run",
    "content": "source `dirname $0`/util.sh\nrecord hello$bitness\ndebug_gdb_only sanity\n"
  },
  {
    "path": "src/test/save_data_fd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DEV_RANDOM \"/dev/urandom\"\n\nint main(void) {\n  int fd = open(DEV_RANDOM, O_RDONLY);\n  int entropy_count;\n  char buf[128];\n  ssize_t nread;\n\n  test_assert(0 <= fd);\n\n  nread = read(fd, buf, sizeof(buf));\n  atomic_printf(\"Read %zd random bytes (expected %zu)\\n\", nread, sizeof(buf));\n  test_assert(nread == sizeof(buf));\n\n  check_data(buf, sizeof(buf));\n\n  test_assert(ioctl(fd, RNDGETENTCNT, &entropy_count) == 0);\n  atomic_printf(\"Entropy Count: %d\\n\", entropy_count);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sched_attr.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstruct rr_sched_attr {\n  uint32_t size;\n  uint32_t sched_policy;\n  uint64_t sched_flags;\n  int32_t sched_nice;\n  uint32_t sched_priority;\n  uint64_t sched_runtime;\n  uint64_t sched_deadline;\n  uint64_t sched_period;\n};\n\nint main(void) {\n  struct rr_sched_attr* attr;\n  ALLOCATE_GUARD(attr, 'x');\n  syscall(__NR_sched_getattr, 0, attr, sizeof(*attr), 0);\n  /* Don't check specific scheduling parameters in case someone\n     is running the rr tests with low priority or something like that */\n  test_assert(attr->size == sizeof(*attr));\n  test_assert(attr->sched_flags == 0);\n  VERIFY_GUARD(attr);\n\n  test_assert(0 == syscall(__NR_sched_setattr, 0, attr, 0));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sched_setaffinity.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  cpu_set_t* cpus;\n  cpu_set_t* cpus_out;\n  cpu_set_t* cpus_out_2;\n\n  ALLOCATE_GUARD(cpus, 'x');\n  CPU_ZERO(cpus);\n  CPU_SET(0, cpus);\n  test_assert(0 == sched_setaffinity(0, sizeof(*cpus), cpus));\n  VERIFY_GUARD(cpus);\n\n  ALLOCATE_GUARD(cpus_out, 'x');\n  test_assert(0 == sched_getaffinity(0, sizeof(*cpus_out), cpus_out));\n  /* We can't assert this because rr assigns us random affinity itself.\n  test_assert(0 == memcmp(cpus, cpus_out, sizeof(*cpus))); */\n  VERIFY_GUARD(cpus_out);\n\n  ALLOCATE_GUARD(cpus_out_2, 'y');\n  test_assert(0 == sched_getaffinity(0, sizeof(*cpus_out_2), cpus_out_2));\n  test_assert(0 == memcmp(cpus_out, cpus_out_2, sizeof(*cpus_out)));\n  VERIFY_GUARD(cpus_out_2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sched_setparam.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct sched_param* param;\n  int scheduler;\n  int min_priority;\n  int max_priority;\n\n  scheduler = sched_getscheduler(0);\n  test_assert(scheduler >= 0);\n\n  ALLOCATE_GUARD(param, 'x');\n  test_assert(0 == sched_getparam(0, param));\n  VERIFY_GUARD(param);\n\n  min_priority = sched_get_priority_min(scheduler);\n  test_assert(min_priority >= 0);\n  max_priority = sched_get_priority_max(scheduler);\n  test_assert(max_priority >= 0);\n  test_assert(min_priority <= max_priority);\n\n  param->sched_priority = min_priority;\n  test_assert(0 == sched_setparam(0, param));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sched_yield.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nenum { PING, PONG } last;\n\npthread_once_t init_once = PTHREAD_ONCE_INIT;\nstatic void init_ping(void) { last = PONG; }\nstatic void init_pong(void) { last = PING; }\n\nstatic pthread_barrier_t bar;\n\nstatic int ping_ready;\nstatic int pong_ready;\n\nstatic void ping_pong(int which) {\n  volatile int* self_ready = which == PING ? &ping_ready : &pong_ready;\n  volatile int* other_ready = which == PING ? &pong_ready : &ping_ready;\n  int i;\n\n  /* Efficiently wait for the other thread to arrive. */\n  pthread_barrier_wait(&bar);\n\n  /* Semi-busy-wait for both threads to be runnable.  (One\n   * thread exiting a barrier doesn't guarantee that the other\n   * thread is immediately runnable.) */\n  *self_ready = 1;\n  do {\n    sched_yield();\n  } while (!*other_ready);\n  /* Whichever thread reaches this loop first initializes the\n   * other to be \"last\". */\n  pthread_once(&init_once, which == PING ? init_ping : init_pong);\n  for (i = 0; i < 50; ++i) {\n    /* Ensure that the other thread was the last to run\n     * the loop body. */\n    which == PING ? test_assert(\"ping thread: \" && PONG == last)\n                  : test_assert(\"pong thread: \" && PING == last);\n    last = which;\n    /* Schedule the other thread run the next loop\n     * iteration.\n     *\n     * NB: because the kernel scheduler is far more\n     * complicated than rr's, this simplistic assumption\n     * won't hold.  If rr's scheduler grows to that level\n     * of complexity, it's probably best to remove this\n     * test. */\n    sched_yield();\n  }\n}\n\nstatic void* pong_thread(__attribute__((unused)) void* unused) {\n  ping_pong(PONG);\n  return NULL;\n}\n\nint main(void) {\n  cpu_set_t cpus;\n  pthread_t t;\n\n  CPU_ZERO(&cpus);\n  CPU_SET(0, &cpus);\n  sched_setaffinity(0, sizeof(cpus), &cpus);\n\n  pthread_barrier_init(&bar, NULL, 2);\n\n  test_assert(0 == pthread_create(&t, NULL, pong_thread, NULL));\n\n  ping_pong(PING);\n\n  pthread_join(t, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sched_yield_to_lower_priority.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int low_priority_thread_scheduled;\n\nstatic void* low_priority_thread(__attribute__((unused)) void* p) {\n  setpriority(PRIO_PROCESS, 0, 4);\n\n  low_priority_thread_scheduled = 1;\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, low_priority_thread, NULL);\n\n  test_assert(!low_priority_thread_scheduled);\n\n  do {\n    sched_yield();\n  } while (!low_priority_thread_scheduled);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/scm_rights.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define MAGIC 0x1cd00d00\n\nstatic void child(int sock, int fd_minus_one) {\n  struct sockaddr addr;\n  int fd;\n  struct msghdr msg;\n  union {\n    int ints[2];\n    uint8_t bytes[sizeof(int[2])];\n  } mbuf;\n  struct iovec iov;\n  /* make cbuf bigger than necessary so we can test that the correct\n     value is written back (the amount actually written by the kernel) */\n  uint8_t cbuf[CMSG_SPACE(sizeof(fd)) + 77];\n  const struct cmsghdr* cmsg;\n  int zero = ~0;\n  ssize_t nread;\n\n  memset(&msg, 0, sizeof(msg));\n  memset(&addr, 0x51, sizeof(addr));\n  msg.msg_name = &addr;\n  msg.msg_namelen = sizeof(addr);\n\n  mbuf.ints[0] = mbuf.ints[1] = ~MAGIC;\n  iov.iov_base = mbuf.bytes;\n  iov.iov_len = sizeof(mbuf);\n  msg.msg_iov = &iov;\n  msg.msg_iovlen = 1;\n  msg.msg_control = cbuf;\n  msg.msg_controllen = sizeof(cbuf);\n  msg.msg_flags = -1;\n\n  atomic_printf(\"c: receiving msg ...\\n\");\n  nread = recvmsg(sock, &msg, 0);\n\n  atomic_printf(\"c:   ... got %#x (%zd bytes), %ju control bytes\\n\",\n                mbuf.ints[0], nread, (uintmax_t)msg.msg_controllen);\n  test_assert(nread == sizeof(mbuf.ints[0]));\n  test_assert(MAGIC == mbuf.ints[0]);\n  test_assert(~MAGIC == mbuf.ints[1]);\n  test_assert(msg.msg_controllen == CMSG_SPACE(sizeof(fd)));\n\n  atomic_printf(\"c:   ... and %d name bytes\\n\", msg.msg_namelen);\n  test_assert(0 == msg.msg_namelen);\n\n  atomic_printf(\"c:  ... and flags %d\\n\", msg.msg_flags);\n  test_assert(0 == msg.msg_flags);\n\n  cmsg = CMSG_FIRSTHDR(&msg);\n  test_assert(SOL_SOCKET == cmsg->cmsg_level && SCM_RIGHTS == cmsg->cmsg_type);\n  memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd));\n  atomic_printf(\"c:   ... and fd %d; should have received %d\\n\", fd,\n                fd_minus_one + 1);\n  test_assert(fd - 1 == fd_minus_one || fd - 2 == fd_minus_one);\n\n  atomic_printf(\"c: reading from /dev/zero ...\\n\");\n  nread = read(fd, &zero, sizeof(zero));\n  atomic_printf(\"c:   ... got %d (%zd bytes) %s\\n\", zero, nread,\n                strerror(errno));\n  test_assert(0 == zero);\n\n  exit(0);\n}\n\nint main(void) {\n  int sockfds[2];\n  int sock;\n  pid_t c;\n  int fd;\n  struct msghdr msg;\n  int mbuf = MAGIC;\n  struct iovec iov;\n  uint8_t cbuf[CMSG_SPACE(sizeof(fd))];\n  struct cmsghdr* cmsg;\n  ssize_t nsent;\n  int err;\n  int status;\n\n  memset(&msg, 0, sizeof(msg));\n  test_assert(0 == socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds));\n  sock = sockfds[0];\n\n  fd = open(\"/dev/null\", O_WRONLY);\n\n  if (0 == (c = fork())) {\n    child(sockfds[1], fd);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  usleep(500000);\n  fd = open(\"/dev/zero\", O_RDONLY);\n\n  iov.iov_base = &mbuf;\n  iov.iov_len = sizeof(mbuf);\n  msg.msg_iov = &iov;\n  msg.msg_iovlen = 1;\n\n  msg.msg_control = cbuf;\n  msg.msg_controllen = sizeof(cbuf);\n  cmsg = CMSG_FIRSTHDR(&msg);\n  cmsg->cmsg_level = SOL_SOCKET;\n  cmsg->cmsg_type = SCM_RIGHTS;\n  cmsg->cmsg_len = CMSG_LEN(sizeof(fd));\n  memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));\n\n  atomic_printf(\"P: sending %#x with fd %d ...\\n\", mbuf, fd);\n  nsent = sendmsg(sock, &msg, 0);\n  err = errno;\n  atomic_printf(\"P:   ... sent %zd bytes (%s/%d)\\n\", nsent, strerror(err), err);\n  test_assert(0 < nsent);\n\n  atomic_printf(\"P: waiting on child %d ...\\n\", c);\n  test_assert(c == waitpid(c, &status, 0));\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/scratch_read.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int scratch_size = 512 * page_size;\n  int fd = open(\"tempfile\", O_RDWR | O_CREAT | O_TRUNC, 0700);\n  void* buf = mmap(NULL, scratch_size, PROT_READ | PROT_WRITE,\n                   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  int ret;\n  test_assert(fd >= 0);\n\n  /* First initialize the file */\n  ret = write(fd, buf, scratch_size);\n  test_assert(ret == scratch_size);\n\n  /* Now read from the file. This should attempt a clone. */\n  ret = lseek(fd, 0, SEEK_SET);\n  test_assert(ret == 0);\n  ret = read(fd, buf, scratch_size);\n  test_assert(ret == scratch_size);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/search.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Make buf weird so that when we search the whole address space,\n   we don't find any accidental matches.\n*/\nchar buf[1024] = { 99, 1, 2, 2, 3, 0xff, 0xfa, 0xde, 0xbc };\nchar* p;\nchar* p_end;\nint* argc_ptr;\n\nstatic void breakpoint(void) {}\n\nint main(int argc, __attribute__((unused)) char* argv[]) {\n  /* 'buf' could be mapped twice in our address space, once in our data segment\n     and once in the text segment. Tests that search the whole address space for\n     the contents of 'buf' don't want to find a spurious match in .text, so\n     setup buf with its intended contents here. After this the copy in .text\n     should continue to map the old value. */\n  buf[0] = 0;\n\n  argc_ptr = &argc;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = (char*)mmap(NULL, page_size * 4, PROT_READ | PROT_WRITE,\n                  MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  p_end = p + page_size * 4;\n\n  /* Don't copy the whole buf. If we do, we may trigger memcpy routines\n   * that copy state to registers which are later spilled to the stack,\n   * causing false positives. These short memcpys are performed using volatile\n   * registers.\n   */\n  memcpy(p + page_size, buf, 12);\n  memcpy(p + page_size * 2, buf, 12);\n\n  test_assert(0 == munmap(p, page_size));\n  test_assert(0 == munmap(p + page_size * 3, page_size));\n  test_assert(0 == mprotect(p + page_size, page_size, PROT_NONE));\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/search.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('find buf,+1,(char)0')\nexpect_gdb('<buf>')\nexpect_gdb('1 pattern found')\n\nsend_gdb('find buf,+1000,(char)99')\nexpect_gdb('Pattern not found')\n\nsend_gdb('find buf,+1000,(char)2')\nexpect_gdb('<buf')\nexpect_gdb('<buf')\nexpect_gdb('2 patterns found')\n\nsend_gdb('find buf,+14,(int)0')\nexpect_gdb('<buf')\nexpect_gdb('<buf')\nexpect_gdb('2 patterns found')\n\nsend_gdb('find buf,+1000,(char)1,(char)2')\nexpect_gdb('<buf')\nexpect_gdb('1 pattern found')\n\nsend_gdb('find p + (p_end - p)/2, +1, (char)0')\nexpect_gdb('1 pattern found')\n\nsend_gdb('find p,p_end,(char)1')\nexpect_gdb('2 patterns found')\n\nsend_gdb('find p, p + (p_end - p)/2,(char)0,(char)0,(char)1')\nexpect_gdb('Pattern not found')\n\n# Test search string crossing page boundaries\nsend_gdb('find p, p_end,(char)0,(char)0,(char)1')\nexpect_gdb('1 pattern found')\n\n# Search the whole address space\nsend_gdb('find 0,-10L,0xabcdef01')\nexpect_gdb('Pattern not found')\n\nsend_gdb('find 0,-10L,(char)0,(char)1,(char)2,(char)2,(char)3,(char)0xff,(char)0xfa,(char)0xde,(char)0xbc')\n# One pattern in 'buf', and two in 'p'\nexpect_gdb('<buf>')\nexpect_gdb('3 patterns found')\n\nsend_gdb('up');\nsend_gdb('find 0,-10L,&argc')\nexpect_gdb('<argc_ptr>')\nsend_gdb('down');\n\nok()\n"
  },
  {
    "path": "src/test/search.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/seccomp.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int count_SIGSYS = 0;\n\nstatic int pipe_fds[2];\n\nstatic void handler(int sig, siginfo_t* si, void* p) {\n  ucontext_t* ctx = p;\n/* some versions of system headers don't define si_arch, si_call_addr or\n * si_syscall. Just skip tests on those systems.\n */\n#ifdef __i386__\n  int syscallno = ctx->uc_mcontext.gregs[REG_EAX];\n#elif defined(__x86_64__)\n  int syscallno = ctx->uc_mcontext.gregs[REG_RAX];\n#elif defined(__aarch64__)\n  int syscallno = ctx->uc_mcontext.regs[8];\n#else\n#error define architecture here\n#endif\n\n#ifdef si_arch\n#ifdef __i386__\n  test_assert(si->si_arch == AUDIT_ARCH_I386);\n#elif defined(__x86_64__)\n  test_assert(si->si_arch == AUDIT_ARCH_X86_64);\n#elif defined(__aarch64__)\n  test_assert(si->si_arch == AUDIT_ARCH_AARCH64);\n#endif\n#endif\n  test_assert(syscallno == SYS_geteuid || syscallno == SYS_openat);\n\n  test_assert(sig == SIGSYS);\n  test_assert(si->si_signo == SIGSYS);\n  test_assert(si->si_errno == 0);\n  test_assert(si->si_code == 1 /* SYS_SECCOMP */);\n#ifdef si_call_addr\n#ifdef __i386__\n  test_assert((intptr_t)si->si_call_addr == ctx->uc_mcontext.gregs[REG_EIP]);\n#elif defined(__x86_64__)\n  test_assert((intptr_t)si->si_call_addr == ctx->uc_mcontext.gregs[REG_RIP]);\n#elif defined(__aarch64__)\n  test_assert((uintptr_t)si->si_call_addr == ctx->uc_mcontext.pc);\n#else\n#error define architecture here\n#endif\n#endif\n\n  int return_value = syscallno == SYS_geteuid ? 42 : -EACCES;\n#ifdef __i386__\n  ctx->uc_mcontext.gregs[REG_EAX] = return_value;\n#elif defined(__x86_64__)\n  ctx->uc_mcontext.gregs[REG_RAX] = return_value;\n#elif defined(__aarch64__)\n  ctx->uc_mcontext.regs[0] = return_value;\n#else\n#error define architecture here\n#endif\n\n#ifdef si_syscall\n  test_assert(si->si_syscall == syscallno);\n#endif\n  ++count_SIGSYS;\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_pipe2 */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_pipe2, 0, 1),\n    /* Error out with ESRCH */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (ESRCH & SECCOMP_RET_DATA)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_geteuid */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_geteuid, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_openat */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_openat, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Jump forward 1 instruction if system call number\n       is not RR_rrcall_init_buffers */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, RR_rrcall_init_buffers, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_ioctl */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_ioctl, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_sched_yield */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_sched_yield, 0, 1),\n    /* Kill process */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nstatic void* waiting_thread(__attribute__((unused)) void* p) {\n  char buf;\n  test_assert(1 == read(pipe_fds[0], &buf, 1));\n  /* Check this thread wasn't affected by the SET_SECCOMP */\n  test_assert(0 == prctl(PR_GET_SECCOMP));\n  return NULL;\n}\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  atomic_printf(\"EXIT-\");\n  return NULL;\n}\n\nstatic void test_get_action_avail(void) {\n  // `SECCOMP_RET_ALLOW` is available since the first version of `SECCOMP_GET_ACTION_AVAIL`\n  uint32_t action = SECCOMP_RET_ALLOW;\n  int ret = syscall(RR_seccomp, SECCOMP_GET_ACTION_AVAIL, 0, &action);\n  if (ret != 0) {\n    test_assert(errno == EINVAL);\n  }\n}\n\nstatic void test_get_notif_sizes(void) {\n  struct {\n    uint16_t seccomp_notif;\n    uint16_t seccomp_notif_resp;\n    uint16_t seccomp_data;\n  } sizes;\n  int ret = syscall(RR_seccomp, SECCOMP_GET_NOTIF_SIZES, 0, &sizes);\n  if (ret == 0) {\n    // These were the sizes when `SECCOMP_GET_NOTIF_SIZES` was first added.\n    test_assert(sizes.seccomp_notif >= 80);\n    test_assert(sizes.seccomp_notif_resp >= 24);\n    test_assert(sizes.seccomp_data >= 64);\n  } else {\n    test_assert(errno == EINVAL);\n  }\n}\n\nint main(void) {\n  struct sigaction sa;\n  pthread_t thread;\n  pthread_t w_thread;\n  char ch;\n\n  test_get_action_avail();\n  test_get_notif_sizes();\n\n  test_assert(0 == pipe(pipe_fds));\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  pthread_create(&w_thread, NULL, waiting_thread, NULL);\n\n  /* Prepare syscallbuf patch path. Need to do this after\n     pthread_create since when we have more than one\n     thread we take a different syscall path... */\n  open(\"/dev/null\", O_RDONLY);\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n  test_assert(2 == prctl(PR_GET_SECCOMP));\n\n  test_assert(1 == write(pipe_fds[1], \"c\", 1));\n  pthread_join(w_thread, NULL);\n\n  test_assert(-1 == syscall(SYS_pipe2, pipe_fds, 0));\n  test_assert(ESRCH == errno);\n\n  /* Spawning a thread will execute an rrcall_init_buffers syscall,\n     which our filter tries to block but shouldn't be able to. */\n  pthread_create(&thread, NULL, run_thread, NULL);\n  pthread_join(thread, NULL);\n\n  /* Check that the ioctls used by syscallbuf aren't blocked */\n  test_assert(1 == write(pipe_fds[1], \"c\", 1));\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n  test_assert(1 == write(pipe_fds[1], \"c\", 1));\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  test_assert(syscall(SYS_geteuid) == 42);\n  syscall(SYS_openat, -1, \"/dev/null\", O_RDONLY);\n  test_assert(count_SIGSYS == 2);\n\n  atomic_puts(\"SUCCESS\");\n\n  sched_yield();\n  abort();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_blocks_rr.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number is less than 1000 */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1000, 0, 1),\n    /* Error out with EPERM */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (EPERM & SECCOMP_RET_DATA)),\n    /* Allow other syscalls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(int argc, char* argv[]) {\n  if (argc > 1 && !strcmp(argv[1], \"--inner\")) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n  test_assert(2 == prctl(PR_GET_SECCOMP));\n\n  execve(argv[1], &argv[1], environ); // Should not return\n  test_assert(0);\n}\n"
  },
  {
    "path": "src/test/seccomp_blocks_rr.run",
    "content": "source `dirname $0`/util.sh\nRR_EXE=\"$TESTNAME $(which $RR_EXE)\"\nRECORD_ARGS=\"--nested=ignore\"\nsave_exe \"$TESTNAME\"\nrecord $TESTNAME --inner\n\nfunction expect_record_fail {\n    if [[ $(cat record.err) == \"\" ]]; then\n        echo \"Test '$TESTNAME' FAILED: record should have failed, but it succeeded.\"\n        exit 1\n    fi\n    echo \"  (record failed as expected)\"\n}\n\necho We have $LIB_ARG\nif [[ \"\" == \"$LIB_ARG\" || \"-b\" == \"$LIB_ARG\" ]]; then\n    expect_record_fail\n    exit 0\nfi\n\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/seccomp_clone_fail.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_clone */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_clone, 0, 1),\n    /* Error out with ENOTTY */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ERRNO | (ENOTTY & SECCOMP_RET_DATA)),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nstatic int child(__attribute__((unused)) void* arg) {\n  /* NOT REACHED */\n  syscall(SYS_exit, 77);\n  return 0;\n}\n\nint main(void) {\n  const size_t stack_size = 1 << 20;\n  void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                     MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  install_filter();\n\n  pid_t ret = clone(child, stack + stack_size, CLONE_VM | CLONE_THREAD | CLONE_SIGHAND,\n                    NULL, NULL, NULL, NULL);\n  test_assert(ret == -1 && errno == ENOTTY);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_cloning.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define BUF_SIZE 65536\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_read */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_read, 0, 1),\n    /* Allow syscall */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_write */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_write, 0, 1),\n    /* Allow syscall */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_exit_group */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_exit_group, 0, 1),\n    /* Allow syscall */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n    /* Kill process */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  char buf[BUF_SIZE];\n  int fd = open(\"tmp.bin\", O_RDWR | O_CREAT | O_EXCL, 0600);\n  test_assert(fd >= 0);\n  unlink(\"tmp.bin\");\n\n  memset(buf, 1, sizeof(buf));\n\n  test_assert(write(fd, buf, BUF_SIZE) == BUF_SIZE);\n  test_assert(0 == lseek(fd, 0, SEEK_SET));\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  install_filter();\n\n  test_assert(read(fd, buf, BUF_SIZE) == BUF_SIZE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  syscall(SYS_exit_group, 0);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_desched.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic void handler(__attribute__((unused)) int sig,\n                    __attribute__((unused)) siginfo_t* si,\n                    __attribute__((unused)) void* p) {\n  /* Make a non-buffered syscall to check that it gets recorded OK */\n  struct statfs fs;\n  memset(&fs, 0, sizeof(fs));\n  test_assert(0 == statfs(\"/\", &fs));\n  test_assert(fs.f_bsize > 0);\n}\n\nstatic void install_filter(void) {\n  prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);\n\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_read */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_read, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  struct sigaction sa;\n  int i;\n  SyscallWrapper spurious_desched_syscall = get_spurious_desched_syscall();\n\n  test_assert(0 == pipe(pipe_fds));\n\n  install_filter();\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  for (i = 0; i < 2; ++i) {\n    char chs[3] = { 9, 9, 9 };\n    struct syscall_info read_syscall = {\n      SYS_read, { pipe_fds[0], (long)chs, 1, 0, 0, 0 }\n    };\n    spurious_desched_syscall(&read_syscall);\n    /* This should not have been altered! */\n    test_assert(chs[1] == 9);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_kill_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_sched_yield */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_sched_yield, 0, 1),\n    /* Kill process */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_KILL),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  char* p =\n      mmap(0, 1, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  pid_t child;\n  int status;\n  test_assert(p != MAP_FAILED);\n\n  child = fork();\n  if (!child) {\n    test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n    install_filter();\n    p[0] = 77;\n    sched_yield();\n    exit(1);\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSIGNALED(status));\n  if (0) {\n    /* Don't check this yet; currently we return SIGKILL */\n    test_assert(WTERMSIG(status) == SIGSYS);\n  }\n  test_assert(p[0] == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_madvise.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 5 instructions if system call number\n       is not SYS_madvise */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_madvise, 0, 6),\n    /* Load advice argument from `seccomp_data` buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, args[2])),\n    /* Jump forward 1 instruction if advice is not MADV_DONTNEED */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, MADV_DONTNEED, 0, 1),\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n    /* Jump forward 1 instruction if advice is not MADV_FREE */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, MADV_FREE, 0, 1),\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  int ret;\n  size_t page_size = sysconf(_SC_PAGE_SIZE);\n  void* p = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  /* Trigger syscall patching for madvise. */\n  test_assert(0 == madvise(p, page_size, MADV_NORMAL));\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n\n  /* Test that MADV_DONTNEED (which we rewrite to MADV_COLD)\n   * doesn't trigger the seccomp filter.\n   */\n  ret = madvise(p, page_size, MADV_DONTNEED);\n  test_assert(ret == 0);\n\n  /* Test that MADV_FREE (which we rewrite to -1 to disallow)\n   * doesn't trigger the seccomp filter.\n   */\n  ret = madvise(p, page_size, MADV_FREE);\n  test_assert(ret == 0 || (ret == -1 && errno == EINVAL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_null.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, (void*)0);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, NULL);\n  }\n  test_assert(ret == -1 && errno == EFAULT);\n\n  test_assert(0 == prctl(PR_GET_SECCOMP));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_open.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(int sig, siginfo_t* si, void* p) {\n  ucontext_t* ctx = p;\n/* some versions of system headers don't define si_arch, si_call_addr or\n * si_syscall. Just skip tests on those systems.\n */\n#ifdef __i386__\n  int syscallno = ctx->uc_mcontext.gregs[REG_EAX];\n#elif defined(__x86_64__)\n  int syscallno = ctx->uc_mcontext.gregs[REG_RAX];\n#elif defined(__aarch64__)\n  int syscallno = ctx->uc_mcontext.regs[8];\n#else\n#error define architecture here\n#endif\n\n  test_assert(syscallno == SYS_openat);\n\n  test_assert(sig == SIGSYS);\n  test_assert(si->si_signo == SIGSYS);\n  test_assert(si->si_errno == 0);\n  test_assert(si->si_code == 1 /* SYS_SECCOMP */);\n\n  int return_value = 75; /* fd number of rr-test-blacklist-file_name */\n#ifdef __i386__\n  ctx->uc_mcontext.gregs[REG_EAX] = return_value;\n#elif defined(__x86_64__)\n  ctx->uc_mcontext.gregs[REG_RAX] = return_value;\n#elif defined(__aarch64__)\n  ctx->uc_mcontext.regs[0] = return_value;\n#else\n#error define architecture here\n#endif\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_openat */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_openat, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nstatic const char message[] = \"EXIT-SUCCESS\\n\";\n\nint main(void) {\n  struct sigaction sa;\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  install_filter();\n\n  int ret = syscall(SYS_openat, -1, \"/dev/null\", O_RDONLY);\n  test_assert(ret == 75);\n  /* our sighandler stopped us from doing the syscall but fd 75 should still\n     be open */\n\n  ret = write(75, message, sizeof(message));\n  test_assert(ret == sizeof(message));\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_open.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME 75>rr-test-blacklist-file_name\nreplay\ncheck EXIT-SUCCESS\ngrep -q EXIT-SUCCESS rr-test-blacklist-file_name || failed \"Didn't write success to rr-test-blacklist-file_name\"\n"
  },
  {
    "path": "src/test/seccomp_signals.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic void handler(__attribute__((unused)) int sig,\n                    __attribute__((unused)) siginfo_t* si,\n                    __attribute__((unused)) void* p) {}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_pipe */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_read, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  struct sigaction sa;\n  int i;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  install_filter();\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  for (i = 0; i < 1000; ++i) {\n    char ch;\n    read(pipe_fds[0], &ch, 1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_signals.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c100\"\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/seccomp_sigsys_args.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(int sig, __attribute__((unused)) siginfo_t* si, void* p) {\n  ucontext_t* ctx = p;\n  test_assert(sig == SIGSYS);\n#ifdef __i386__\n  test_assert(ctx->uc_mcontext.gregs[REG_EBX] == 0);\n  ctx->uc_mcontext.gregs[REG_EAX] = 42;\n#elif defined(__x86_64__)\n  test_assert(ctx->uc_mcontext.gregs[REG_RDI] == 0);\n  ctx->uc_mcontext.gregs[REG_RAX] = 42;\n#elif defined(__aarch64__)\n  test_assert(ctx->uc_mcontext.regs[0] == 0);\n  ctx->uc_mcontext.regs[0] = 42;\n#else\n#error define architecture here\n#endif\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_sched_setaffinity */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_sched_setaffinity, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  struct sigaction sa;\n  sigset_t sigs;\n\n  test_assert(open(\"/dev/null\", O_RDONLY) >= 0);\n\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGTRAP);\n  sigprocmask(SIG_SETMASK, &sigs, NULL);\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n\n  /* Test SIGSYS for a syscall rr mucks with */\n  test_assert(sched_setaffinity(0, 0, NULL) == 42);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_sigsys_sigtrap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(int sig, __attribute__((unused)) siginfo_t* si, void* p) {\n  ucontext_t* ctx = p;\n  test_assert(sig == SIGSYS);\n#ifdef __i386__\n  ctx->uc_mcontext.gregs[REG_EAX] = 42;\n#elif defined(__x86_64__)\n  ctx->uc_mcontext.gregs[REG_RAX] = 42;\n#elif defined(__aarch64__)\n  ctx->uc_mcontext.regs[0] = 42;\n#else\n#error define architecture here\n#endif\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_openat */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_openat, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  struct sigaction sa;\n  sigset_t sigs;\n\n  test_assert(open(\"/dev/null\", O_RDONLY) >= 0);\n\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGTRAP);\n  sigprocmask(SIG_SETMASK, &sigs, NULL);\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n\n  /* Test SIGSYS for a buffered syscall */\n  test_assert(syscall(SYS_openat, -1, \"/dev/null\", O_RDONLY) == 42);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_sigsys_syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(int sig, __attribute__((unused)) siginfo_t* si, void* p) {\n  ucontext_t* ctx = p;\n  uintptr_t tv;\n  test_assert(sig == SIGSYS);\n#ifdef __i386__\n  tv = ctx->uc_mcontext.gregs[REG_EBX];\n  ctx->uc_mcontext.gregs[REG_EAX] = 0;\n#elif defined(__x86_64__)\n  tv = ctx->uc_mcontext.gregs[REG_RDI];\n  ctx->uc_mcontext.gregs[REG_RAX] = 0;\n#elif defined(__aarch64__)\n  tv = ctx->uc_mcontext.regs[0];\n  ctx->uc_mcontext.regs[0] = 0;\n#else\n#error define architecture here\n#endif\n  ((struct timeval*)tv)->tv_sec = 99;\n  ((struct timeval*)tv)->tv_usec = 0;\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_gettimeofday */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_gettimeofday, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(void) {\n  struct sigaction sa;\n  struct timeval tv = { 0, 0 };\n  struct timeval dummy;\n\n  test_assert(open(\"/dev/null\", O_RDONLY) >= 0);\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  /* Trigger syscall patching for gettimeofday. */\n  test_assert(0 == gettimeofday(&dummy, NULL));\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n\n  /* Test SIGSYS for a buffered syscall with memory argument */\n  test_assert(gettimeofday(&tv, NULL) == 0);\n  test_assert(tv.tv_sec != 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_tsync.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = { /* Allow all system calls */\n                                  BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, SECCOMP_FILTER_FLAG_TSYNC,\n                &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    atomic_puts(\"seccomp syscall not supported\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n  }\n  test_assert(ret == 0);\n}\n\nstatic void* waiting_thread(__attribute__((unused)) void* p) {\n  char buf;\n  test_assert(1 == read(pipe_fds[0], &buf, 1));\n  /* Check this thread *was* affected by SECCOMP_FILTER_FLAG_TSYNC */\n  test_assert(2 == prctl(PR_GET_SECCOMP));\n  return NULL;\n}\n\nint main(void) {\n  pthread_t w_thread;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  pthread_create(&w_thread, NULL, waiting_thread, NULL);\n\n  /* Prepare syscallbuf patch path. Need to do this after\n     pthread_create since when we have more than one\n     thread we take a different syscall path... */\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  install_filter();\n  test_assert(2 == prctl(PR_GET_SECCOMP));\n\n  test_assert(1 == write(pipe_fds[1], \"c\", 1));\n  pthread_join(w_thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seccomp_veto_exec.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int count_SIGSYS = 0;\n\nstatic void handler(int sig, siginfo_t* si, void* p) {\n  ucontext_t* ctx = p;\n/* some versions of system headers don't define si_arch, si_call_addr or\n * si_syscall. Just skip tests on those systems.\n */\n#ifdef __i386__\n  int syscallno = ctx->uc_mcontext.gregs[REG_EAX];\n#elif defined(__x86_64__)\n  int syscallno = ctx->uc_mcontext.gregs[REG_RAX];\n#elif defined(__aarch64__)\n  int syscallno = ctx->uc_mcontext.regs[8];\n#else\n#error define architecture here\n#endif\n\n#ifdef si_arch\n#ifdef __i386__\n  test_assert(si->si_arch == AUDIT_ARCH_I386);\n#elif defined(__x86_64__)\n  test_assert(si->si_arch == AUDIT_ARCH_X86_64);\n#elif defined(__aarch64__)\n  test_assert(si->si_arch == AUDIT_ARCH_AARCH64);\n#endif\n#endif\n  test_assert(syscallno == SYS_execve);\n\n  test_assert(sig == SIGSYS);\n  test_assert(si->si_signo == SIGSYS);\n  test_assert(si->si_errno == 0);\n  test_assert(si->si_code == 1 /* SYS_SECCOMP */);\n#ifdef si_call_addr\n#ifdef __i386__\n  test_assert((intptr_t)si->si_call_addr == ctx->uc_mcontext.gregs[REG_EIP]);\n#elif defined(__x86_64__)\n  test_assert((intptr_t)si->si_call_addr == ctx->uc_mcontext.gregs[REG_RIP]);\n#elif defined(__aarch64__)\n  test_assert((uintptr_t)si->si_call_addr == ctx->uc_mcontext.pc);\n#else\n#error define architecture here\n#endif\n#endif\n\n#ifdef si_syscall\n  test_assert(si->si_syscall == syscallno);\n#endif\n  ++count_SIGSYS;\n}\n\nstatic void install_filter(void) {\n  struct sock_filter filter[] = {\n    /* Load system call number from 'seccomp_data' buffer into\n       accumulator */\n    BPF_STMT(BPF_LD | BPF_W | BPF_ABS, offsetof(struct seccomp_data, nr)),\n    /* Jump forward 1 instruction if system call number\n       is not SYS_execve */\n    BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, SYS_execve, 0, 1),\n    /* Trigger SIGSYS */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),\n    /* Destination of system call number mismatch: allow other\n       system calls */\n    BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW)\n  };\n  struct sock_fprog prog = {\n    .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),\n    .filter = filter,\n  };\n  int ret;\n\n  ret = syscall(RR_seccomp, SECCOMP_SET_MODE_FILTER, 0, &prog);\n  if (ret == -1 && errno == ENOSYS) {\n    ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog);\n  }\n  test_assert(ret == 0);\n}\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  struct sigaction sa;\n\n  sa.sa_sigaction = handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGSYS, &sa, NULL);\n\n  test_assert(0 == prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));\n  test_assert(1 == prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0));\n  install_filter();\n  test_assert(2 == prctl(PR_GET_SECCOMP));\n\n  // What we actually exec here doesn't matter since seccomp will veto it.\n  execv(\"\", argv);\n\n  test_assert(count_SIGSYS == 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seekticks.py",
    "content": "from util import *\nimport re\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('when-ticks')\nexpect_gdb(re.compile(r'Current tick: (\\d+)'))\nticks = int(last_match().group(1))\nif ticks != 0:\n    failed('ERROR in first \"when-ticks\"')\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('del 1')\n\nsend_gdb('when-ticks')\nexpect_gdb(re.compile(r'Current tick: (\\d+)'))\nticks2 = int(last_match().group(1))\nif ticks2 < 0 or ticks2 > 1000000:\n    failed('ERROR in second \"when-ticks\"')\nif ticks2 <= ticks:\n    failed('ERROR ... \"when-ticks\" failed to advance')\n\nsend_gdb('c')\n\nsend_gdb('when-ticks')\nexpect_gdb(re.compile(r'Current tick: (\\d+)'))\nticks3 = int(last_match().group(1))\nif ticks3 < 0 or ticks3 > 1000000:\n    failed('ERROR in second \"when-ticks\"')\nif ticks3 <= ticks2:\n    failed('ERROR ... \"when-ticks\" failed to advance')\n\nsend_gdb(f'seek-ticks {ticks2}')\nexpect_gdb('Program stopped.')\nsend_gdb('when-ticks')\nexpect_gdb(re.compile(r'Current tick: (\\d+)'))\nticks4 = int(last_match().group(1))\nif ticks4 != ticks2:\n    failed('ERROR: Failed to seek back to ticks2')\n\nsend_gdb(f'seek-ticks {ticks}')\nexpect_gdb('Program stopped.')\nsend_gdb('when-ticks')\nexpect_gdb(re.compile(r'Current tick: (\\d+)'))\nticks5 = int(last_match().group(1))\nif ticks5 != ticks:\n    failed('ERROR: Failed to seek back to ticks')\n\nsend_gdb(f'seek-ticks {ticks2}')\nexpect_gdb('Program stopped.')\nsend_gdb('when-ticks')\nexpect_gdb(re.compile(r'Current tick: (\\d+)'))\nticks6 = int(last_match().group(1))\nif ticks6 != ticks2:\n    failed('ERROR: Failed to seek forwards to ticks2')\n\nif ticks2 < 4:\n    failed('ERROR: ticks2 too small to test nearby ticks')\n\ntests = [ticks2, ticks2, ticks2-2, 1, 1, 0, 0, 2, 0, 2, ticks2-2, ticks2-1, ticks2-2, ticks2]\n\nfor i in range(len(tests)):\n    ticks7 = tests[i]\n    send_gdb(f'seek-ticks {ticks7}')\n    expect_gdb('Program stopped.')\n    send_gdb('when-ticks')\n    expect_gdb(re.compile(r'Current tick: (\\d+)'))\n    ticks8 = int(last_match().group(1))\n    if ticks8 != ticks7:\n        failed(f'ERROR: seek-ticks didn\\'t go to correct tick on test {i}')\n\nsend_gdb('seek-ticks 2000000000')\nexpect_gdb('No event found matching specified ticks target')\nsend_gdb('info threads')\n# don't expect anything specific from 'info threads', but make sure gdb at least functions\nsend_gdb('p 123456789+1')\nexpect_gdb('123456790')\nok()\n"
  },
  {
    "path": "src/test/seekticks.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only seekticks\n"
  },
  {
    "path": "src/test/seekticks_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n// Run two threads until there have been at least a couple\n// (approx. 20) context switches between them.\n// Races are technically possible, but they'll only increase the\n// context switch count, which is fine.\nvolatile int counter;\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    int c = counter;\n    if ((c&1) == 1) counter = c+1;\n  }\n  \n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  pthread_create(&thread, NULL, start_thread, NULL);\n  \n  while (1) {\n    int c = counter;\n    if ((c&1) == 0) counter = c+1;\n    if (counter >= 20) break;\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/seekticks_threads.py",
    "content": "from util import *\nimport re, os\n\nsend_gdb('restart 9')\nexpect_gdb(re.compile(r'Checkpoint 9 not found'))\n\ndef curr_thread():\n    send_gdb('thread')\n    expect_gdb(re.compile(r'\\[Current thread is \\d+ \\(Thread (.*?)\\)\\]'))\n    return last_match().group(1)\n\ndef expect_thread_tick(expected_thread, expected_tick):\n    if curr_thread() != expected_thread:\n        failed('ERROR: Incorrect thread: expected %s, got %s' % (expected_thread, curr_thread()))\n    \n    send_gdb('when-ticks')\n    expect_gdb(re.compile(r'Current tick: (\\d+)'))\n    got_tick = int(last_match().group(1))\n    if expected_tick != got_tick:\n        failed('ERROR: Incorrect ticks: expected %d, got %d' % (expected_tick, got_tick))\n\ndef expect_stopped():\n    expect_gdb(re.compile(r'(Thread \\d+|Program) stopped'))\n    \n\n\nsched_matches = re.compile(r'global_time:(\\d+).*ticks:(\\d+)').findall(os.environ['SCHED_EVENTS'])\nsched_events = [[int(y) for y in x] for x in sched_matches][:-2]\nadj_count = 5\nwhile True:\n    if (len(sched_events) < adj_count):\n        failed('ERROR: Adjacent SCHED events not found')\n    last = sched_events[-adj_count:]\n    if all([last[0][0]+i == last[i][0] for i in range(adj_count)]):\n        break\n    sched_events.pop()\n\nsched_events = sched_events[-adj_count:]\n[event_A, tick_A] = sched_events[1]\n[event_B, tick_B] = sched_events[2]\n[event_C, tick_C] = sched_events[3]\n[event_D, tick_D] = sched_events[4]\n\ntests = [\n    # event; expected tick at event; another tick on the same thread\n    [event_B, tick_A, tick_C],\n    [event_C, tick_B, tick_D]]\n\nthreads = set()\nis_first = True\nfor [start_event, initial_tick, other_tick] in tests:\n    center_tick = (initial_tick + other_tick) // 2\n    \n    send_gdb('run %d' % start_event)\n    if not is_first:\n        expect_gdb('from the beginning')\n        send_gdb('y')\n    is_first = False\n    expect_stopped()\n    \n    thread = curr_thread()\n    threads.add(thread)\n    \n    expect_thread_tick(thread, initial_tick)\n\n    send_gdb('seek-ticks %d' % center_tick)\n    expect_stopped()\n    expect_thread_tick(thread, center_tick)\n\n    send_gdb('seek-ticks %d' % center_tick)\n    expect_stopped()\n    expect_thread_tick(thread, center_tick)\n\n    ticks = center_tick + 1\n    send_gdb('seek-ticks %d' % ticks)\n    expect_stopped()\n    expect_thread_tick(thread, ticks)\n\n    ticks = center_tick - 1\n    send_gdb('seek-ticks %d' % ticks)\n    expect_stopped()\n    expect_thread_tick(thread, ticks)\n\n    send_gdb('seek-ticks %d' % initial_tick)\n    expect_stopped()\n    expect_thread_tick(thread, initial_tick)\n\n    send_gdb('seek-ticks %d' % other_tick)\n    expect_stopped()\n    expect_thread_tick(thread, other_tick)\n    \n    send_gdb('info threads')\n    expect_gdb(r'\\d\\s*Thread')\n    expect_gdb(r'\\d\\s*Thread')\n    \nif len(threads) != 2:\n    failed('ERROR: Tested events had the same thread')\n\nok()\n"
  },
  {
    "path": "src/test/seekticks_threads.run",
    "content": "source `dirname $0`/util.sh\nrecord seekticks_threads$bitness\nSCHED_EVENTS=\"$(get_events | grep \\`SCHED\\')\" \\\ndebug_gdb_only seekticks_threads\n"
  },
  {
    "path": "src/test/segfault.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(int sig) {\n  atomic_printf(\"caught signal %d, exiting\\n\", sig);\n  _exit(0);\n}\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  signal(SIGSEGV, sighandler);\n\n  breakpoint();\n  /* NO SYSCALLS BETWEEN HERE AND SEGFAULT BELOW: next event to\n   * replay must be the signal. */\n\n  *((volatile int*)0) = 0;\n  return 0;\n}\n"
  },
  {
    "path": "src/test/segfault.run",
    "content": "source `dirname $0`/util.sh\ncompare_test 'caught signal 11, exiting'\n"
  },
  {
    "path": "src/test/self_shebang.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  int ret;\n  char self[PATH_MAX];\n\n  if (argc > 1 && strcmp(argv[1], \"from_shebang\") == 0) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  ret = readlink(\"/proc/self/exe\", self, sizeof(self) - 1);\n  test_assert(ret >= 0);\n  /* readlink does not null-terminate the buffer */\n  self[ret] = 0;\n\n  int dst_fd = open(\"shebang_test\", O_WRONLY | O_CREAT, 0700);\n  char buf[PATH_MAX + 1024];\n  int nbytes = snprintf(buf, sizeof(buf), \"#!%s from_shebang\\n\", self);\n  write(dst_fd, buf, nbytes);\n  close(dst_fd);\n\n  char* const new_argv[] = { \"shebang_test\", NULL };\n  execve(\"shebang_test\", new_argv, environ);\n  test_assert(0);\n  return 1;\n}\n"
  },
  {
    "path": "src/test/self_sigint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  /* rr should ignore SIGINT */\n  kill(getppid(), SIGINT);\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(getpid(), SIGINT);\n  test_assert(0 && \"Shouldn't reach here\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sem.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define COUNT 4\n\nstatic int semid;\nstatic char* shmem;\n\n#ifdef _SEM_SEMUN_UNDEFINED\nunion semun {\n  int val;\n  struct semid_ds* buf;\n  unsigned short int* array;\n  struct seminfo* __buf;\n};\n#endif\n\nstatic int run_child(void) {\n  int child2;\n  int status;\n  struct sembuf ops[2];\n  struct timespec ts = { 0, 20000000 };\n  struct timespec ts_short = { 0, 10000000 };\n  struct timespec ts_long = { 10000, 0 };\n  union semun un_arg;\n  struct semid_ds* ds;\n  struct seminfo* si;\n  unsigned short* array;\n\n  ops[0].sem_num = 0;\n  ops[0].sem_op = 1;\n  ops[0].sem_flg = SEM_UNDO;\n  ops[1].sem_num = 1;\n  ops[1].sem_op = 1;\n  ops[1].sem_flg = SEM_UNDO;\n  test_assert(0 == semop(semid, ops, 2));\n  *shmem = 0;\n\n  ALLOCATE_GUARD(ds, 'd');\n  un_arg.buf = ds;\n  test_assert(0 == semctl(semid, 0, IPC_STAT, un_arg));\n  VERIFY_GUARD(ds);\n  test_assert(ds->sem_perm.mode == 0666);\n  test_assert(ds->sem_nsems == COUNT);\n\n  ds->sem_perm.mode = 0660;\n  test_assert(0 == semctl(semid, 0, IPC_SET, un_arg));\n\n  ALLOCATE_GUARD(si, 'i');\n  un_arg.__buf = si;\n  /* The following syscall should always return >= 1, but\n     sometimes it returns 0. I don't know why. */\n  test_assert(0 <= semctl(semid, 0, IPC_INFO, un_arg));\n  VERIFY_GUARD(si);\n  test_assert(si->semvmx > 0);\n  test_assert(si->semusz < 100000);\n\n  /* The following syscall should always return >= 1, but\n     sometimes it returns 0. I don't know why. */\n  test_assert(0 <= semctl(semid, 0, SEM_INFO, un_arg));\n  VERIFY_GUARD(si);\n  test_assert(si->semusz > 0);\n  test_assert(si->semusz < 100000);\n\n  array = allocate_guard(COUNT * sizeof(*array), 'a');\n  un_arg.array = array;\n  test_assert(0 == semctl(semid, 0, GETALL, un_arg));\n  verify_guard(COUNT * sizeof(*array), array);\n  test_assert(array[0] == 1);\n  test_assert(array[1] == 1);\n  test_assert(array[2] == 0);\n  test_assert(array[3] == 0);\n\n  array[2] = 2;\n  test_assert(0 == semctl(semid, 0, SETALL, un_arg));\n\n  test_assert(0 == semctl(semid, 1, GETNCNT, NULL));\n\n  test_assert(getpid() == semctl(semid, 1, GETPID, NULL));\n\n  test_assert(2 == semctl(semid, 2, GETVAL, NULL));\n\n  test_assert(0 == semctl(semid, 0, GETZCNT, NULL));\n\n  un_arg.val = 0;\n  test_assert(0 == semctl(semid, 2, SETVAL, un_arg));\n\n  if ((child2 = fork()) == 0) {\n    ops[0].sem_op = -1;\n    ops[1].sem_op = -1;\n    /* The semtimedop timeout is irrelevant. We're just checking that the\n       syscall works. */\n    test_assert(0 == semtimedop(semid, ops, 2, &ts_long));\n\n    *shmem = 1;\n\n    test_assert(0 == nanosleep(&ts, NULL));\n\n    *shmem = 0;\n\n    ops[0].sem_op = 1;\n    ops[1].sem_op = 1;\n    test_assert(0 == semtimedop(semid, ops, 2, &ts));\n\n    return 0;\n  }\n\n  test_assert(0 == nanosleep(&ts_short, NULL));\n\n  ops[0].sem_op = -1;\n  ops[1].sem_op = -1;\n  test_assert(0 == semop(semid, ops, 2));\n\n  test_assert(*shmem == 0);\n\n  ops[0].sem_op = 1;\n  ops[1].sem_op = 1;\n  test_assert(0 == semop(semid, ops, 2));\n\n  test_assert(child2 == waitpid(child2, &status, __WALL));\n  test_assert(0 == status);\n\n  return 0;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  shmem = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n               MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  test_assert(shmem != (void*)-1);\n\n  semid = semget(IPC_PRIVATE, COUNT, 0666);\n  test_assert(semid >= 0);\n\n  if ((child = fork()) == 0) {\n    return run_child();\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n\n  test_assert(child == waitpid(child, &status, __WALL));\n  /* delete the sem before testing status, because we want to ensure the\n     segment is deleted even if the test failed. */\n  test_assert(0 == semctl(semid, 0, IPC_RMID, NULL));\n  test_assert(status == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/send_block.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_PACKETS 1000\n#define BUF_SIZE 1000\n\nstatic int fds[2];\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  int i;\n  char buf[BUF_SIZE];\n  for (i = 0; i < NUM_PACKETS; ++i) {\n    test_assert(BUF_SIZE == recv(fds[0], buf, sizeof(buf), 0));\n  }\n  return NULL;\n}\n\nint main(void) {\n  int i;\n  char buf[BUF_SIZE];\n  pthread_t thread;\n\n  test_assert(0 == socketpair(AF_UNIX, SOCK_STREAM, 0, fds));\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  memset(buf, 'x', BUF_SIZE);\n  for (i = 0; i < NUM_PACKETS; ++i) {\n    test_assert(BUF_SIZE == send(fds[1], buf, BUF_SIZE, 0));\n  }\n\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sendfile.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TOKEN \"ABC\"\n#define TOKEN_SIZE sizeof(TOKEN)\n\nstatic const char token_file[] = \"rr-sendfile-file.txt\";\nstatic const char token_file_out[] = \"rr-sendfile-file-out.txt\";\n\nvoid verify_token(int fd) {\n  ssize_t len;\n  char buf[TOKEN_SIZE];\n\n  len = read(fd, buf, sizeof(buf));\n  if (len != TOKEN_SIZE || strcmp(buf, TOKEN)) {\n    atomic_puts(\"Internal error: FAILED: sendfile wrote the wrong data\");\n    exit(1);\n  }\n  atomic_puts(\"Got expected token \" TOKEN);\n}\n\nint main(void) {\n  int filefd;\n  int filefd_out;\n  loff_t off = 0;\n\n  filefd = open(token_file, O_RDWR | O_CREAT | O_TRUNC, 0600);\n  filefd_out = open(token_file, O_RDWR | O_CREAT | O_TRUNC, 0600);\n  write(filefd, TOKEN, TOKEN_SIZE);\n\n  sendfile64(filefd_out, filefd, &off, TOKEN_SIZE);\n\n  atomic_printf(\n      \"sendfile %zu bytes from %d to %d; off changed from 0 to %\" PRId64 \"\\n\",\n      TOKEN_SIZE, filefd, filefd_out, off);\n  lseek(filefd_out, 0, SEEK_SET);\n  verify_token(filefd_out);\n\n  lseek(filefd, 0, SEEK_SET);\n  sendfile64(filefd_out, filefd, NULL, TOKEN_SIZE);\n\n  atomic_printf(\"sendfile %zu bytes from %d to %d\\n\", TOKEN_SIZE, filefd,\n                filefd_out);\n  lseek(filefd_out, 0, SEEK_SET);\n  verify_token(filefd_out);\n\n  /* The test driver will clean up after us if the test failed\n   * before this. */\n  unlink(token_file);\n  unlink(token_file_out);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/set_ptracer.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  test_assert(0 == prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/set_tid_address.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int v;\nstatic int* p;\nstatic int pipe_fds[2];\n\nstatic void* run_thread(__attribute__((unused)) void* p) {\n  char ch;\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n  test_assert(sys_gettid() == syscall(SYS_set_tid_address, &v));\n  return NULL;\n}\n\nstatic void* run_thread2(__attribute__((unused)) void* q) {\n  test_assert(sys_gettid() == syscall(SYS_set_tid_address, p));\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  char ch;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  v = 1;\n  pthread_create(&thread, NULL, run_thread, NULL);\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  int ret = syscall(SYS_futex, &v, FUTEX_WAIT, 1, (void*)0, (void*)0, 0);\n  // The above is slightly racy. If the thread finishes before we enter\n  // the syscall we will exit with EAGAIN. This is unfortunate, but there\n  // is no much we can do. Luckily this failure mode is different from\n  // the one we really care about (the FUTEX_WAKE not happening), which\n  // would manifest itself as a hang in the call above.\n  test_assert(0 == ret || (-1 == ret && errno == EAGAIN));\n  test_assert(0 == v);\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  p = mmap(NULL, page_size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p, page_size));\n\n  pthread_create(&thread, NULL, run_thread2, NULL);\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/setgid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  gid_t gid = getgid();\n  int err = setgid(gid);\n  atomic_printf(\"setgid returned: %d\\n\", err);\n  test_assert(0 == err);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/setgroups.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <grp.h>\n\nint main(void) {\n  gid_t old_groups[1024];\n  gid_t new_groups[1024];\n  int i;\n  int ret;\n  int num_groups = getgroups(ALEN(old_groups), old_groups);\n  test_assert(num_groups >= 0);\n\n  /* make sure we have some new groups for setgroups() */\n  for (i = 0; i < num_groups; ++i) {\n    new_groups[i] = old_groups[i] + 1;\n  }\n  if (num_groups == 0) {\n    new_groups[0] = getegid();\n    num_groups = 1;\n  }\n  ret = setgroups(num_groups, new_groups);\n  if (ret == -1) {\n    test_assert(errno == EPERM);\n    atomic_puts(\"Test did nothing because process does not have CAP_SETGID?\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  } else {\n    test_assert(getgroups(ALEN(old_groups), old_groups) == num_groups);\n    for (i = 0; i < num_groups; ++i) {\n      test_assert(new_groups[i] == old_groups[i]);\n    }\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/setitimer.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct itimerval* v1;\n  struct itimerval* v2;\n  struct itimerval* v3;\n\n  ALLOCATE_GUARD(v1, 0);\n  v1->it_interval.tv_sec = 10000;\n  v1->it_interval.tv_usec = 0;\n  v1->it_value.tv_sec = 10000;\n  v1->it_value.tv_usec = 0;\n  test_assert(0 == setitimer(ITIMER_REAL, v1, NULL));\n  VERIFY_GUARD(v1);\n\n  ALLOCATE_GUARD(v2, 1);\n  test_assert(0 == setitimer(ITIMER_REAL, v1, v2));\n  test_assert(v2->it_interval.tv_sec == v1->it_interval.tv_sec);\n  VERIFY_GUARD(v2);\n\n  ALLOCATE_GUARD(v3, 2);\n  test_assert(0 == getitimer(ITIMER_REAL, v3));\n  test_assert(v3->it_interval.tv_sec == v1->it_interval.tv_sec);\n  VERIFY_GUARD(v3);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/setsid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t newsid;\n\n  newsid = setsid();\n  atomic_printf(\"New session ID: %d\\n\", newsid);\n\n  if (newsid >= 0) {\n    atomic_puts(\"EXIT-SUCCESS\");\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/setuid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <sys/types.h>\n#include <unistd.h>\n\nint main(int argc, char** argv) {\n  uid_t orig;\n  uid_t new;\n  gid_t orig_g;\n  gid_t new_g;\n  int ret;\n  struct passwd* p = getpwnam(\"nobody\");\n  struct group* g = getgrnam(\"nobody\");\n  pid_t child;\n  int status;\n\n  if (argc > 1) {\n    return 77;\n  }\n\n  orig = getuid();\n  test_assert(0 == setuid(orig));\n  orig_g = getgid();\n  new = p && p->pw_uid != orig ? p->pw_uid : orig + 1;\n  new_g = g && g->gr_gid != orig_g ? g->gr_gid : orig_g + 1;\n\n  ret = setgid(new_g);\n  if (ret == -1) {\n    test_assert(errno == EPERM || errno == EINVAL);\n    atomic_puts(\"Test did nothing because process does not have CAP_SETUID\\n\"\n                \"or is running inside user namespace with unmapped `nobody`.\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0 == setgroups(0, NULL));\n  test_assert(getgid() == new_g);\n\n  test_assert(0 == setuid(new));\n  test_assert(getuid() == new);\n\n  child = fork();\n  if (!child) {\n    char* args[] = { argv[0], \"dummy\", NULL };\n    execve(argv[0], args, environ);\n    test_assert(errno == EACCES);\n    atomic_printf(\n        \"We can't reexecute %s because it's not executable by 'nobody'\\n\",\n        argv[0]);\n    return 77;\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/setuid.run",
    "content": "source `dirname $0`/util.sh\nskip_if_old_systemd\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/shared_exec.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"output\", O_RDWR | O_CREAT, 0777);\n  int ret = write(fd, \"x\", 1);\n  test_assert(ret == 1);\n  char* p = (char*)mmap(NULL, 1, PROT_READ | PROT_WRITE | PROT_EXEC,\n                        MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  *p = 1;\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shared_map.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"tmp.txt\", O_RDWR | O_CREAT | O_EXCL, 0700);\n  ssize_t page_size = sysconf(_SC_PAGESIZE);\n  char buf[page_size];\n  char* p;\n  char* q;\n  pid_t child;\n  int status;\n\n  test_assert(fd >= 0);\n  memset(buf, 1, sizeof(buf));\n  test_assert(page_size == write(fd, buf, page_size));\n  test_assert(0 == close(fd));\n\n  fd = open(\"tmp.txt\", O_RDWR);\n  p = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[0] == 1);\n  test_assert(p[9] == 1);\n  test_assert(p[10] == 1);\n  memset(p, 2, 10);\n\n  child = fork();\n  if (!child) {\n    q = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);\n    test_assert(q != MAP_FAILED);\n    test_assert(q[0] == 2);\n    test_assert(q[9] == 2);\n    test_assert(q[10] == 1);\n    return 77;\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  memset(buf, 3, 10);\n  test_assert(10 == pwrite(fd, buf, 10, 0));\n  test_assert(0 == fsync(fd));\n  test_assert(0 == close(fd));\n  test_assert(0 == unlink(\"tmp.txt\"));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shared_map.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME\nreplay\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/shared_monitor.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = syscall(SYS_memfd_create, \"temp\", 0);\n  char buf[4096];\n  int size = sizeof(buf);\n  int ret;\n  uint8_t* p;\n  memset(buf, 1, size);\n  ret = write(fd, buf, size);\n  test_assert(ret == size);\n  p = (uint8_t*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n\n  memset(buf, 0, size);\n  ret = pwrite(fd, buf, size, 0);\n  test_assert(ret == size);\n\n  p = (uint8_t*)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[0] == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shared_offset.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = syscall(RR_memfd_create, \"shared\", 0);\n  if (fd < 0 && errno == ENOSYS) {\n    atomic_puts(\"SYS_memfd_create not supported on this kernel\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(fd >= 0);\n  test_assert(0 == ftruncate(fd, page_size*2));\n  char* map = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n    MAP_SHARED, fd, page_size);\n  test_assert(map != MAP_FAILED);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shared_persistent_file.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nint main(void) {\n  int fd = open(\"/bin/sh\", O_RDONLY);\n  void* p = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);\n  pid_t pid;\n  int status;\n\n  test_assert(fd >= 0);\n  test_assert(p != MAP_FAILED);\n  pid = fork();\n\n  breakpoint();\n\n  if (!pid) {\n    return 77;\n  }\n  test_assert(pid == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shared_persistent_file.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('check')\nexpect_gdb('Checkpoint 1 at')\nsend_gdb('c')\nexpect_gdb('xited normally')\nsend_gdb('restart 1')\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('xited normally')\n\nok()\n"
  },
  {
    "path": "src/test/shared_persistent_file.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/shared_write.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"output\", O_RDWR | O_CREAT, 0777);\n  int ret = write(fd, \"x\", 1);\n  test_assert(ret == 1);\n  char* p = (char*)mmap(NULL, 1, PROT_READ | PROT_WRITE,\n                        MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  *p = 1;\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shm.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Make SIZE not a multiple of the page size, to ensure we handle that case.\n   But make sure it's even, since we divide it by two. */\n#define SIZE ((int)(16 * page_size) - 10)\n\nstatic int shmid;\n\nstatic void before_writing(void) {}\nstatic void after_writing(void) {}\n\nstatic int run_child(void) {\n  int i;\n  char* p;\n  char* p2;\n  pid_t child2;\n  int status;\n  struct shmid_ds* ds;\n  /* These are the wrong types, to work around\n     https://sourceware.org/bugzilla/show_bug.cgi?id=26636 */\n  struct shmid_ds* info;\n  struct shmid_ds* info2;\n  int used_ids;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  ALLOCATE_GUARD(ds, 'd');\n  test_assert(0 == shmctl(shmid, IPC_STAT, ds));\n  VERIFY_GUARD(ds);\n  test_assert((int)ds->shm_segsz == SIZE);\n  test_assert(ds->shm_cpid == getppid());\n  test_assert(ds->shm_nattch == 0);\n\n  ds->shm_perm.mode = 0660;\n  test_assert(0 == shmctl(shmid, IPC_SET, ds));\n\n  ALLOCATE_GUARD(info, 'i');\n  test_assert(0 <= shmctl(shmid, IPC_INFO, info));\n  VERIFY_GUARD(info);\n  test_assert(((struct shminfo*)info)->shmmin == 1);\n\n  ALLOCATE_GUARD(info2, 'j');\n  test_assert(0 <= shmctl(shmid, SHM_INFO, (struct shmid_ds*)info2));\n  VERIFY_GUARD(info2);\n  used_ids = ((struct shm_info*)info2)->used_ids;\n  if (used_ids == 0x6a6a6a6a && sizeof(void*) == 4) {\n    atomic_puts(\"SHM_INFO apparently failed, perhaps due to glibc bug. Ignoring.\");\n  } else {\n    test_assert(used_ids > 0);\n    test_assert(used_ids < 1000000);\n  }\n\n  p = shmat(shmid, NULL, 0);\n  test_assert(p != (char*)-1);\n\n  before_writing();\n\n  for (i = 0; i < SIZE; ++i) {\n    test_assert(p[i] == 0);\n  }\n  memset(p, 'r', SIZE / 2);\n\n  after_writing();\n\n  p2 = shmat(shmid, NULL, 0);\n  test_assert(p2 != (char*)-1);\n  memset(p + SIZE / 2, 'r', SIZE / 2);\n  test_assert(0 == shmdt(p));\n  test_assert(0 == shmdt(p2));\n\n  test_assert(p ==\n              mmap(p, SIZE, PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));\n  test_assert(p[0] == 0);\n\n  p = shmat(shmid, p, SHM_REMAP);\n  test_assert(p != (char*)-1);\n  for (i = 0; i < SIZE; ++i) {\n    test_assert(p[i] == 'r');\n  }\n\n  if ((child2 = fork()) == 0) {\n    memset(p, 's', SIZE);\n    return 0;\n  }\n  test_assert(child2 == waitpid(child2, &status, __WALL));\n  test_assert(0 == status);\n  for (i = 0; i < SIZE; ++i) {\n    test_assert(p[i] == 's');\n  }\n\n  return 0;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  shmid = shmget(IPC_PRIVATE, SIZE, 0666);\n  test_assert(shmid >= 0);\n\n  if ((child = fork()) == 0) {\n    return run_child();\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n\n  test_assert(child == waitpid(child, &status, __WALL));\n  /* delete the shm before testing status, because we want to ensure the\n     segment is deleted even if the test failed. */\n  test_assert(0 == shmctl(shmid, IPC_RMID, NULL));\n  test_assert(status == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/shm_checkpoint.py",
    "content": "from util import *\n\nsend_gdb('b before_writing')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b after_writing')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c');\nexpect_gdb('Breakpoint 1, before_writing')\n\nsend_gdb('checkpoint');\nexpect_gdb('Checkpoint 1 at');\n\nsend_gdb('c');\nexpect_gdb('Breakpoint 2, after_writing')\n\nsend_gdb('restart 1');\nexpect_gdb('stopped')\nsend_gdb('c');\nexpect_gdb('Breakpoint 2, after_writing')\n\nok()\n\n"
  },
  {
    "path": "src/test/shm_checkpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord shm$bitness\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\ndebug_gdb_only shm_checkpoint \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/shm_unmap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  void* p;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int shmid = shmget(IPC_PRIVATE, page_size * 3, 0666);\n  test_assert(shmid >= 0);\n\n  p = shmat(shmid, NULL, 0);\n  test_assert(p != (void*)-1);\n  test_assert(munmap(p, page_size) == 0);\n  test_assert(shmdt(p) == 0);\n\n  p = shmat(shmid, NULL, 0);\n  test_assert(p != (void*)-1);\n  test_assert(munmap(p + page_size, page_size) == 0);\n  test_assert(shmdt(p) == 0);\n\n  test_assert(0 == shmctl(shmid, IPC_RMID, NULL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigaction_old.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler1(__attribute__((unused)) int sig,\n                     __attribute__((unused)) siginfo_t* si,\n                     __attribute__((unused)) void* p) {}\n\nstatic void handler2(__attribute__((unused)) int sig,\n                     __attribute__((unused)) siginfo_t* si,\n                     __attribute__((unused)) void* p) {}\n\nstatic void handler3(__attribute__((unused)) int sig,\n                     __attribute__((unused)) siginfo_t* si,\n                     __attribute__((unused)) void* p) {}\n\nint main(void) {\n  struct sigaction sa;\n  struct sigaction old_sa;\n\n  sa.sa_sigaction = handler1;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGUSR1, &sa, NULL);\n\n  sa.sa_sigaction = handler2;\n  old_sa.sa_sigaction = handler3;\n  sigaction(SIGUSR1, &sa, &old_sa);\n  test_assert(old_sa.sa_sigaction == handler1);\n\n  sigaction(SIGUSR1, NULL, &old_sa);\n  test_assert(old_sa.sa_sigaction == handler2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigaltstack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char buf[128 * 1024];\n\nint main(void) {\n  stack_t* ss;\n  stack_t* oss;\n\n  ALLOCATE_GUARD(ss, 'x');\n  ss->ss_sp = buf;\n  ss->ss_flags = 0;\n  ss->ss_size = sizeof(buf);\n  test_assert(0 == sigaltstack(ss, NULL));\n  VERIFY_GUARD(ss);\n\n  ALLOCATE_GUARD(oss, 'y');\n  test_assert(0 == sigaltstack(ss, oss));\n  test_assert(oss->ss_sp == buf);\n  test_assert(oss->ss_flags == 0);\n  test_assert(oss->ss_size == sizeof(buf));\n  VERIFY_GUARD(ss);\n  VERIFY_GUARD(oss);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigchld_interrupt_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t c;\n  int dummy = 0, i;\n  int status;\n\n  atomic_puts(\"forking child\");\n\n  if (0 == (c = fork())) {\n    usleep(10000);\n    atomic_puts(\"child exiting\");\n    exit(0);\n  }\n\n  /* NO SYSCALLS AFTER HERE!  (Up to the test_asserts.) */\n  for (i = 1; i < (1 << 28); ++i) {\n    dummy += (dummy + i) % 9735;\n  }\n\n  test_assert(c == waitpid(c, &status, 0));\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigcont.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_sig(__attribute__((unused)) int sig) {}\n\nint main(void) {\n  signal(SIGTTIN, handle_sig);\n  kill(getpid(), SIGTTIN);\n\n  signal(SIGTTOU, handle_sig);\n  kill(getpid(), SIGTTOU);\n\n  signal(SIGTSTP, handle_sig);\n  kill(getpid(), SIGTSTP);\n\n  signal(SIGCONT, handle_sig);\n  kill(getpid(), SIGCONT);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigcont_threaded.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void *child_process_extra_thread(__attribute__((unused)) void *extra_thread) {\n  int r;\n\n  // Slap in a sched_yield or two here so that the parent process is going to be\n  // blocked in pthread_join.\n  sched_yield();\n  sched_yield();\n\n  // Now, stop ourselves. We'll be unstopped by the parent process.\n  r = kill(sys_gettid(), SIGSTOP);\n  test_assert(r == 0);\n\n  // Now allow self to exit, and the thread-group-leader can continue.\n  return NULL;\n}\n\nstatic void child_process(void) {\n  pthread_t extra_thread;\n  int r;\n  // Spawn an additional thread\n  r = pthread_create(&extra_thread, NULL, child_process_extra_thread, NULL);\n  test_assert(r == 0);\n\n  // Wait for the child thread we made. It will send SIGSTOP to the process.\n  r = pthread_join(extra_thread, NULL);\n  test_assert(r == 0);\n}\n\nstatic void parent_process(pid_t pid) {\n  int wait_status, r;\n  pid_t wpid;\n\n  // Wait for the child process to have sent itself SIGSTOP\n  wpid = waitpid(pid, &wait_status, WUNTRACED);\n  test_assert(wpid == pid);\n  test_assert(WIFSTOPPED(wait_status));\n  test_assert(WSTOPSIG(wait_status) == SIGSTOP);\n\n  // Let it continue\n  r = kill(pid, SIGCONT);\n  test_assert(r == 0);\n\n  // Now the child process should actually exit\n  wpid = waitpid(pid, &wait_status, 0);\n  test_assert(wpid == pid);\n  test_assert(WIFEXITED(wait_status));\n}\n\nint main(void) {\n  pid_t pid = fork();\n  test_assert(pid != -1);\n  if (pid == 0) {\n    child_process();\n  } else {\n    parent_process(pid);\n    atomic_puts(\"EXIT-SUCCESS\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigframe_grow_stack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_usr1(__attribute__((unused)) int sig) {}\n\nstatic void recursive(int n) {\n  char buf[1024];\n  sprintf(buf, \"hello %d\", n);\n  raise(SIGUSR1);\n  if (n > 0) {\n    recursive(n - 1);\n  }\n}\n\nint main(void) {\n  signal(SIGUSR1, handle_usr1);\n\n  /* Consume about 1MB of stack. This should be fine. */\n  recursive(1000);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sighandler_bad_rsp_sigsegv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <signal.h>\n\nstatic char buf[128 * 1024];\n\nstatic void handler(int sig,\n                    __attribute__((unused)) siginfo_t* si,\n                    __attribute__((unused)) void* ucontext_ptr) {\n  test_assert(sig == SIGSEGV);\n\n#ifdef __x86_64__\n  ucontext_t* ctx = (ucontext_t*)ucontext_ptr;\n  // Skip the current instruction.\n  ctx->uc_mcontext.gregs[REG_RIP] += 2;\n#elif defined(__i386__)\n  ucontext_t* ctx = (ucontext_t*)ucontext_ptr;\n  // Skip the current instruction.\n  ctx->uc_mcontext.gregs[REG_EIP] += 2;\n#else\n  test_assert(0);\n#endif\n}\n\nint main(void) {\n  stack_t* ss;\n\n  ALLOCATE_GUARD(ss, 'x');\n  ss->ss_sp = buf;\n  ss->ss_flags = 0;\n  ss->ss_size = sizeof(buf);\n  test_assert(0 == sigaltstack(ss, NULL));\n  VERIFY_GUARD(ss);\n\n  struct sigaction sig;\n  sig.sa_sigaction = handler;\n  sigemptyset(&sig.sa_mask);\n  sig.sa_flags = SA_SIGINFO | SA_RESTART | SA_NODEFER;\n  test_assert(0 == sigaction(SIGILL, &sig, NULL));\n  sig.sa_flags |= SA_ONSTACK;\n  test_assert(0 == sigaction(SIGSEGV, &sig, NULL));\n\n#ifdef __x86_64__\n  asm volatile(\"mov %%rsp, %%rax\\n\"\n               \"mov $0x800794b90ed0, %%rsp\\n\"\n               \"ud2\\n\"\n               \"mov %%rax, %%rsp\\n\"\n\t       : : : \"rax\");\n#elif defined(__i386__)\n  asm volatile(\"mov %%esp, %%eax\\n\"\n               \"mov $0xdeafbeef, %%esp\\n\"\n               \"ud2\\n\"\n               \"mov %%eax, %%esp\\n\"\n\t       : : : \"eax\");\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sighandler_fork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(int sig) {\n  atomic_printf(\"caught signal %d, exiting\\n\", sig);\n}\n\nint main(void) {\n  pid_t c;\n\n  signal(SIGCHLD, sighandler);\n\n  atomic_puts(\"forking child\");\n\n  if (0 == (c = fork())) {\n    // Child\n    usleep(10000);\n    atomic_puts(\"forking grandchild\");\n    if (0 == (c = fork())) {\n      // Grandchild\n      usleep(10000);\n      exit(0);\n    }\n    waitpid(c, NULL, 0);\n    return 0;\n  }\n\n  // Because why not.\n  signal(SIGCHLD, NULL);\n\n  waitpid(c, NULL, 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sighandler_mask.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\nstatic pid_t child;\n\nstatic void handle_sigterm(__attribute__((unused)) int sig,\n                           __attribute__((unused)) siginfo_t* info,\n                           __attribute__((unused)) void* mcontext) {\n  char ch;\n  /* Make sure our signals are enabled. This will hang if they\n     aren't. */\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nint main(void) {\n  struct sigaction sa;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  child = fork();\n  if (!child) {\n    struct timespec ts = { 0, 1000000 };\n    nanosleep(&ts, NULL);\n    test_assert(1 == write(pipe_fds[1], \"x\", 1));\n    return 77;\n  }\n\n  sa.sa_flags = SA_SIGINFO;\n  sa.sa_sigaction = handle_sigterm;\n  sigfillset(&sa.sa_mask);\n  sigaction(SIGUSR1, &sa, NULL);\n\n  kill(getpid(), SIGUSR1);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigill.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(int sig) {\n  atomic_printf(\"caught signal %d, exiting\\n\", sig);\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nint main(void) {\n  signal(SIGILL, sighandler);\n\n  atomic_puts(\"running undefined instruction ...\");\n  undefined_instr();\n  test_assert(\"should have terminated!\" && 0);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/siginfo.py",
    "content": "from util import *\nimport re\n\nsend_gdb('c')\nexpect_gdb('SIGUSR1')\nsend_gdb('print $_siginfo')\nexpect_gdb('si_signo = 10')\nexpect_gdb('si_code = -6')\n\nok()\n"
  },
  {
    "path": "src/test/siginfo.run",
    "content": "source `dirname $0`/util.sh\nrecord tgkill$bitness\ndebug_gdb_only siginfo\n"
  },
  {
    "path": "src/test/signal_checkpoint.py",
    "content": "from util import *\n\nsend_gdb('b sighandler')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Program received signal SIGILL')\n\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 1 at')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, sighandler')\n\nsend_gdb('restart 1');\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, sighandler')\n\nok()\n"
  },
  {
    "path": "src/test/signal_checkpoint.run",
    "content": "source `dirname $0`/util.sh\nrecord sigill$bitness\ndebug_gdb_only signal_checkpoint\n"
  },
  {
    "path": "src/test/signal_deferred.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child = fork();\n  int status;\n\n  if (!child) {\n    int pipe_fds[2];\n\n    test_assert(0 == pipe(pipe_fds));\n    test_assert(0 == close(pipe_fds[0]));\n\n    /* Trigger a SIGPIPE inside the syscallbuf.\n       The signal will have to be deferred until the\n       syscallbuf has returned. */\n    write(pipe_fds[1], \"x\", 1);\n    test_assert(0 && \"Should not reach here\");\n    return 0;\n  }\n\n  test_assert(child == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGPIPE);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/signal_during_preload_init.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n  atomic_puts(\"In handler\");\n}\n\nstatic void* run_child(__attribute__((unused)) void* arg) {\n  sched_yield();\n  return 0;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  signal(SIGCHLD, handler);\n\n  pthread_create(&thread, NULL, run_child, NULL);\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/signal_frame.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n  write(1, \"EXIT-SUCCESS\\n\", 13);\n  _exit(0);\n}\n\nstatic int do_thread(__attribute__((unused)) void* p) {\n  /* Enter a signal handler at the top of our thread stack.\n     rr's estimate of the sighandler frame size will spill beyond the\n     thread stack. */\n  signal(SIGSEGV, handler);\n  *(volatile char*)0 = 0;\n  test_assert(0 && \"Should not be reached\");\n  return 0;\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  size_t stack_len = page_size * 8;\n  int fd;\n  int ret;\n  char* p = (char*)mmap(NULL, stack_len + page_size, PROT_READ | PROT_WRITE,\n    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  /* Map a readonly trace page immediately after our thread stack */\n  fd = open(\"/bin/ls\", O_RDONLY);\n  test_assert(fd >= 0);\n  munmap(p + stack_len, page_size);\n  char* pp = (char*)mmap(p + stack_len, page_size, PROT_NONE, MAP_SHARED, fd, 0);\n  test_assert(pp == p + stack_len);\n\n  ret = clone(do_thread, p + stack_len, CLONE_THREAD | CLONE_SIGHAND | CLONE_VM, NULL);\n  test_assert(ret >= 0);\n\n  sleep(1000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/signal_numbers.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int sig;\n\n  for (sig = 1; sig <= 64; ++sig) {\n    struct sigaction sa;\n\n    /* Skip signals that are fatal and can't be ignored, and skip\n       signals that rr uses for itself. */\n    if (sig == SIGKILL || sig == SIGSTOP || sig == SIGSTKFLT || sig == SIGPWR) {\n      continue;\n    }\n\n    sa.sa_handler = SIG_IGN;\n    sa.sa_flags = 0;\n    sa.sa_restorer = NULL;\n    sigemptyset(&sa.sa_mask);\n    /* Avoid libc wrappers since glibc won't let us send certain signals that\n       it reserves for itself */\n    test_assert(0 == syscall(SYS_rt_sigaction, sig, &sa, (void*)0, 8));\n    test_assert(0 == kill(getpid(), sig));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/signal_numbers.py",
    "content": "from util import *\n\ngdb_signals = [\n  '',\n  'SIGHUP',\n  'SIGINT',\n  'SIGQUIT',\n  'SIGILL',\n  'SIGTRAP',\n  'SIGABRT',\n  'SIGBUS',\n  'SIGFPE',\n  '#SIGKILL',\n  'SIGUSR1',\n  'SIGSEGV',\n  'SIGUSR2',\n  'SIGPIPE',\n  'SIGALRM',\n  'SIGTERM',\n  '#SIGSTKFLT',\n  'SIGCHLD',\n  'SIGCONT',\n  '#SIGSTOP',\n  'SIGTSTP',\n  'SIGTTIN',\n  'SIGTTOU',\n  'SIGURG',\n  'SIGXCPU',\n  'SIGXFSZ',\n  'SIGVTALRM',\n  'SIGPROF',\n  'SIGWINCH',\n  'SIGIO',\n  '#SIGPWR',\n  'SIGSYS']\n\nfor sig in range(32,65):\n    gdb_signals.append('SIG%d'%sig)\n\nfor sig in range(1,65):\n    gdb_sig = gdb_signals[sig]\n    if not gdb_sig.startswith('#'):\n        send_gdb('handle %s stop'%gdb_sig)\n        if gdb_sig == 'SIGINT' or gdb_sig == 'SIGTRAP':\n            expect_gdb('used by the debugger')\n            send_gdb('y')\n        expect_gdb('(rr)')\n        send_gdb('c')\n        expect_gdb('received signal %s'%gdb_sig)\n\nok()\n"
  },
  {
    "path": "src/test/signal_numbers.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/signal_stop.py",
    "content": "from util import *\n\nsend_gdb('b sighandler')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Program received signal SIGILL')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, sighandler')\n\nok()\n"
  },
  {
    "path": "src/test/signal_stop.run",
    "content": "source `dirname $0`/util.sh\nrecord sigill$bitness\ndebug_gdb_only signal_stop\n"
  },
  {
    "path": "src/test/signal_unstoppable.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {}\n\nint main(void) {\n  sigset_t sigs;\n\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGKILL);\n  sigprocmask(SIG_BLOCK, &sigs, NULL);\n  signal(SIGKILL, SIG_IGN);\n  signal(SIGKILL, handler);\n\n  sigemptyset(&sigs);\n  sigaddset(&sigs, SIGSTOP);\n  sigprocmask(SIG_BLOCK, &sigs, NULL);\n  signal(SIGSTOP, SIG_IGN);\n  signal(SIGSTOP, handler);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/signalfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  sigset_t mask;\n  int fd;\n  struct signalfd_siginfo si;\n\n  test_assert(0 == sigemptyset(&mask));\n  test_assert(0 == sigaddset(&mask, SIGURG));\n  fd = signalfd(-1, &mask, 0);\n  test_assert(fd >= 0);\n\n  test_assert(0 == sigprocmask(SIG_BLOCK, &mask, NULL));\n\n  test_assert(0 == kill(getpid(), SIGURG));\n  test_assert(sizeof(si) == read(fd, &si, sizeof(si)));\n  test_assert(si.ssi_signo == SIGURG);\n  test_assert((pid_t)si.ssi_pid == getpid());\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int signals_unblocked;\n\nstatic void handle_usr1(__attribute__((unused)) int sig) {\n  atomic_puts(\"Caught usr1\");\n  test_assert(signals_unblocked);\n}\n\nint main(void) {\n  sigset_t mask, oldmask;\n  int i, err, dummy = 0;\n\n  signal(SIGUSR1, handle_usr1);\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGUSR1);\n  /* The libc function invokes rt_sigprocmask. */\n  err = sigprocmask(SIG_BLOCK, &mask, &oldmask);\n  test_assert(err == 0);\n\n  raise(SIGUSR1);\n\n  for (i = 0; i < 1 << 25; ++i) {\n    dummy += (dummy + i) % 9735;\n  }\n\n  /* Do a syscall() call to avoid us going through lazy linking code\n     on the way to the sigprocmask below */\n  syscall(SYS_sched_yield);\n\n  signals_unblocked = 1;\n#if defined(__i386__) || defined(__x86_64__)\n  char xmm_buf[16] =\n    { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};\n  asm (\"movdqu %0,%%xmm0\\n\\t\"\n       \"movdqu %0,%%xmm1\\n\\t\"\n       \"movdqu %0,%%xmm2\\n\\t\"\n       \"movdqu %0,%%xmm3\\n\\t\"\n       \"movdqu %0,%%xmm4\\n\\t\"\n       \"movdqu %0,%%xmm5\\n\\t\"\n       \"movdqu %0,%%xmm6\\n\\t\"\n       \"movdqu %0,%%xmm7\\n\\t\" : : \"m\"(xmm_buf)\n       : \"xmm0\", \"xmm1\", \"xmm2\", \"xmm3\", \"xmm4\" ,\"xmm5\", \"xmm6\", \"xmm7\");\n#endif\n/* Some systems only have rt_sigprocmask. */\n#if defined(SYS_sigprocmask)\n  syscall(SYS_sigprocmask, SIG_SETMASK, &oldmask, (void*)0);\n#else\n  sigprocmask(SIG_SETMASK, &oldmask, NULL);\n#endif\n\n  /* Make sure that rt_sigprocmask (the syscall) does not clobber stack memory\n     beyond what it's supposed to */\n  uint64_t set1[10];\n  uint64_t set2[10];\n  set1[0] = set2[0] = 0;\n  memset(&set1[1], 0xab, 9 * sizeof(uint64_t));\n  memset(&set2[1], 0xcd, 9 * sizeof(uint64_t));\n  set1[0] = ((uint64_t)1) << (SIGPWR - 1);\n  test_assert(0 == syscall(SYS_rt_sigprocmask, SIG_SETMASK, set1, (void*)0,\n                           sizeof(uint64_t)));\n  for (size_t i = 0; i < 9 * sizeof(uint64_t); ++i) {\n    test_assert(((uint8_t*)(&set1[1]))[i] == 0xab);\n    test_assert(((uint8_t*)(&set2[1]))[i] == 0xcd);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_ensure_delivery.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int got_sig;\n\nstatic void handle_sig(__attribute__((unused)) int sig,\n                       __attribute__((unused)) siginfo_t* info,\n                       __attribute__((unused)) void* mcontext) {\n  got_sig = 1;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  sigset_t sigs;\n  sigemptyset(&sigs);\n  pthread_sigmask(SIG_SETMASK, &sigs, NULL);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  struct sigaction sa;\n  struct sigevent sevp;\n  timer_t id;\n  sigset_t new_mask;\n  uint64_t sigset = (uint64_t)1 << (SIGUSR1 - 1);\n  struct itimerspec timeout = { { 0, 0 }, { 0, 1000000 } };\n  struct syscall_info sigprocmask_syscall = {\n    SYS_rt_sigprocmask, { SIG_BLOCK, (long)&sigset, 0, 8, 0, 0 }\n  };\n  SyscallWrapper delayed_syscall = get_delayed_syscall();\n\n  sa.sa_flags = SA_SIGINFO;\n  sa.sa_sigaction = handle_sig;\n  sigemptyset(&sa.sa_mask);\n  sigaction(SIGUSR1, &sa, NULL);\n\n  sevp.sigev_notify = SIGEV_SIGNAL;\n  sevp.sigev_signo = SIGUSR1;\n  test_assert(0 == timer_create(CLOCK_MONOTONIC, &sevp, &id));\n  test_assert(0 == timer_settime(id, 0, &timeout, NULL));\n\n  delayed_syscall(&sigprocmask_syscall);\n\n  test_assert(0 == sigprocmask(SIG_BLOCK, NULL, &new_mask));\n  test_assert(sigismember(&new_mask, SIGUSR1));\n\n  while (1) {\n    struct itimerspec curr;\n    test_assert(0 == timer_gettime(id, &curr));\n    if (curr.it_value.tv_sec == 0 && curr.it_value.tv_nsec == 0) {\n      break;\n    }\n    sleep(1);\n  }\n\n  /**\n   * The signal might have been delivered after the sigprocmask due to\n   * scheduling vagaries. If so, create a thread to receive the signal.\n   * The rr bug we're testing for is that the signal is stashed before\n   * the sigprocmask and can only be delivered to the main thread, but\n   * never is.\n   */\n  pthread_create(&thread, NULL, do_thread, NULL);\n  pthread_join(thread, NULL);\n\n  test_assert(got_sig);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_evil.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void exit_handler(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nint main(void) {\n  uint64_t old, new;\n  signal(SIGSEGV, exit_handler);\n  new = (uint64_t)-1;\n  test_assert(0 == syscall(SYS_rt_sigprocmask, 2, &new, (void*)0, sizeof(new)));\n  test_assert(new == (uint64_t)-1);\n  new = 0x4226;\n  test_assert(0 == syscall(SYS_rt_sigprocmask, 2, &new, (void*)0, sizeof(new)));\n  test_assert(0 == syscall(SYS_rt_sigprocmask, 0, (void*)0, &old, sizeof(old)));\n  new = (uint64_t)-1;\n  test_assert(0 == syscall(SYS_rt_sigprocmask, 2, &new, &new, sizeof(new)));\n  test_assert(new == old);\n  test_assert(0 == syscall(SYS_rt_sigprocmask, 2, &new, (void*)0, sizeof(new)));\n  crash_null_deref();\n  test_assert(0);\n}\n"
  },
  {
    "path": "src/test/sigprocmask_exec.c",
    "content": "#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  sigset_t set;\n  test_assert(argc == 1 || (argc == 2 && !strcmp(\"self\", argv[1])));\n\n  if (argc != 2) {\n    char* argv[] = { \"/proc/self/mem\", \"self\", 0 };\n    sigemptyset(&set);\n    sigaddset(&set, SIGSEGV);\n    sigprocmask(SIG_SETMASK, &set, NULL);\n    execv(\"/proc/self/exe\", argv);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  sigprocmask(SIG_SETMASK, NULL, &set);\n  test_assert(sigismember(&set, SIGSEGV));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_in_syscallbuf_sighandler.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nstatic void handle_signal(__attribute__((unused)) int sig) {\n  sigset_t mask;\n\n  atomic_puts(\"Caught SIGALRM\");\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGUSR1);\n  test_assert(0 == sigprocmask(SIG_BLOCK, &mask, NULL));\n\n  /* Syscallbuf should be still locked here. If it's not this\n     could corrupt syscallbuf state. */\n  test_assert(2 == write(pipe_fds[1], \"xx\", 2));\n}\n\nint main(void) {\n  struct sigaction sact;\n  char buf;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_RESTART;\n  sact.sa_handler = handle_signal;\n  test_assert(0 == sigaction(SIGALRM, &sact, NULL));\n\n  test_assert(0 == alarm(1));\n  /* If the syscallbuf state is corrupted by the signal handler\n     we'll probably crash out here. */\n  test_assert(1 == read(pipe_fds[0], &buf, 1));\n  /* Or here */\n  test_assert(1 == read(pipe_fds[0], &buf, 1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  sigset_t blocked_mask;\n  sigset_t unblocked_mask;\n\n  sigemptyset(&unblocked_mask);\n  sigemptyset(&blocked_mask);\n  sigaddset(&blocked_mask, SIGCHLD);\n\n  for (i = 0; i < 2000; ++i) {\n    pthread_sigmask(SIG_SETMASK, &blocked_mask, NULL);\n    pthread_sigmask(SIG_SETMASK, &unblocked_mask, NULL);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_race.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c100\"\n# This test tests the interaction of the syscallbuf with frequent ticks\n# interrupts, so without the syscallbuf it doesn't matter. Also,\n# without the syscallbuf it's rather slow.\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/sigprocmask_rr_sigs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  sigset_t mask, oldmask;\n  int err;\n\n  sigfillset(&mask);\n  /* SIGPWR is used internally by rr, and we won't be able to turn it off.\n     rr shouldn't observably change `mask` when it does this though */\n  err = sigprocmask(SIG_BLOCK, &mask, &oldmask);\n  test_assert(err == 0);\n\n  err = sigprocmask(SIG_BLOCK, &mask, &oldmask);\n  test_assert(err == 0);\n  test_assert(!sigismember(&oldmask, SIGPWR));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_rr_sigs_nondefault.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  sigset_t mask, oldmask;\n  int err;\n\n  sigfillset(&mask);\n  /* Since we passed --syscall-buffer-sig=SIGPROF, SIGPROF is now used\n   * internally by rr, and we won't be able to turn it off.\n   * rr shouldn't observably change `mask` when it does this though */\n  err = sigprocmask(SIG_BLOCK, &mask, &oldmask);\n  test_assert(err == 0);\n\n  err = sigprocmask(SIG_BLOCK, &mask, &oldmask);\n  test_assert(err == 0);\n  test_assert(!sigismember(&oldmask, SIGPROF));\n  /* But SIGPWR should be maskable now */\n  test_assert(sigismember(&oldmask, SIGPWR));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprocmask_rr_sigs_nondefault.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS=--syscall-buffer-sig=SIGPROF\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/sigprocmask_syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\n\nint main(void) {\n  char buf;\n  pid_t pid;\n  int status;\n  sigset_t mask;\n\n  test_assert(0 == pipe(pipe_fds));\n\n  sigemptyset(&mask);\n  sigfillset(&mask);\n  test_assert(0 == sigprocmask(SIG_BLOCK, &mask, NULL));\n\n  /* Check that even when all signals are supposedly blocked,\n     syscallbuf still works */\n  pid = fork();\n  if (!pid) {\n    test_assert(1 == write(pipe_fds[1], \"y\", 1));\n    return 77;\n  }\n  test_assert(1 == read(pipe_fds[0], &buf, 1));\n  test_assert(pid == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigprof.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int count;\n\nstatic void handler(__attribute__((unused)) int sig) { ++count; }\n\nint main(void) {\n  struct itimerval itv = {\n    { 0, 500 },\n    { 0, 500 },\n  };\n\n  test_assert(0 == signal(SIGPROF, handler));\n  test_assert(0 == signal(SIGALRM, handler));\n\n  setitimer(ITIMER_REAL, &itv, NULL);\n  setitimer(ITIMER_PROF, &itv, NULL);\n\n  while (count < 100) {\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigpwr.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n\nint main(void) {\n  signal(SIGPWR, handler);\n  raise(SIGPWR);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigqueueinfo.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void queue_siginfo(int sig, int val) {\n  siginfo_t si;\n  memset(&si, 0, sizeof(si));\n\n  si.si_code = SI_QUEUE;\n  si.si_pid = getpid();\n  si.si_uid = geteuid();\n  si.si_value.sival_int = val;\n  syscall(SYS_rt_sigqueueinfo, getpid(), sig, &si);\n}\n\nstatic void queue_siginfo_tg(int sig, int val) {\n  siginfo_t si;\n  memset(&si, 0, sizeof(si));\n\n  si.si_code = SI_QUEUE;\n  si.si_pid = getpid();\n  si.si_uid = geteuid();\n  si.si_value.sival_int = val;\n  syscall(SYS_rt_tgsigqueueinfo, getpid(), getpid(), sig, &si);\n}\n\nstatic int usr1_val;\nstatic int usr2_val;\n\nstatic void handle_signal(int sig, siginfo_t* si,\n                          __attribute__((unused)) void* ctx) {\n  int val = si->si_value.sival_int;\n  if (SIGUSR1 == sig) {\n    usr1_val = val;\n  } else if (SIGUSR2 == sig) {\n    usr2_val = val;\n  } else {\n    test_assert(\"Unexpected signal\" && 0);\n  }\n}\n\nint main(void) {\n  struct sigaction sa;\n\n  sa.sa_sigaction = handle_signal;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGUSR1, &sa, NULL);\n  sigaction(SIGUSR2, &sa, NULL);\n\n  queue_siginfo(SIGUSR1, -42);\n  test_assert(-42 == usr1_val);\n  queue_siginfo(SIGUSR2, 12345);\n  test_assert(12345 == usr2_val);\n  queue_siginfo_tg(SIGUSR1, -43);\n  test_assert(-43 == usr1_val);\n  queue_siginfo_tg(SIGUSR2, 123456);\n  test_assert(123456 == usr2_val);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigreturn_reg.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvolatile int caught_sig = 0;\nlong long v = 99;\n\nvoid catcher(__attribute__((unused)) int signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             __attribute__((unused)) void* ucontext_ptr) {\n#ifdef __x86_64__\n  ucontext_t* ctx = (ucontext_t*)ucontext_ptr;\n  test_assert(ctx->uc_mcontext.gregs[REG_RCX] == 0);\n  test_assert(ctx->uc_mcontext.gregs[REG_RDI] == 0);\n  ctx->uc_mcontext.gregs[REG_RDI] = (long long)&v;\n#elif defined(__aarch64__)\n  ucontext_t* ctx = (ucontext_t*)ucontext_ptr;\n  test_assert(ctx->uc_mcontext.regs[1] == 0);\n  test_assert(ctx->uc_mcontext.regs[2] == 0);\n  ctx->uc_mcontext.regs[2] = (long)&v;\n#endif\n  caught_sig = signum;\n}\n\nint main(void) {\n  struct sigaction sact;\n  long long ax = v;\n  long long cx = 0;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = catcher;\n  sigaction(SIGSEGV, &sact, NULL);\n\n#ifdef __x86_64__\n  ax = 0;\n  __asm__(\"\\txor %%rdi,%%rdi\\n\"\n          \"\\txor %%rcx,%%rcx\\n\"\n          \"\\tmov (%%rdi),%%rax\\n\"\n          : \"=c\"(cx), \"=a\"(ax)\n          :: \"memory\");\n  test_assert(caught_sig == SIGSEGV);\n#elif defined(__aarch64__)\n  ax = 0;\n  register long x0 __asm__(\"x0\") = ax;\n  register long x1 __asm__(\"x1\") = cx;\n  register long x2 __asm__(\"x2\") = (long)0;\n  __asm__(\"\\tmov x2, xzr\\n\"\n          \"\\tmov x1, xzr\\n\"\n          \"\\tldr x0, [x2]\\n\"\n          : \"+r\"(x0), \"+r\"(x1), \"+r\"(x2)\n          :: \"memory\");\n  ax = x0;\n  cx = x1;\n  test_assert(caught_sig == SIGSEGV);\n#endif\n\n  test_assert(cx == 0);\n  test_assert(ax == v);\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigreturnmask.c",
    "content": "#include \"util.h\"\n\nstatic void segv_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  test_assert(0 && \"Should not reach here\");\n}\n\nstatic void usr1_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  ucontext_t* ctx = (ucontext_t*)context;\n  sigaddset(&ctx->uc_sigmask, SIGSEGV);\n  return;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  raise(SIGUSR1); // just a strange way to spell sigprocmask\n  // Generate SIGSEGV. Can't use raise, because that will be blocked\n  (*(int*)1) = 0;\n  test_assert(0 && \"Should not reach here!\");\n  return NULL;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  pthread_t thread;\n\n  if ((child = fork()) == 0) {\n    struct sigaction act;\n    act.sa_sigaction = segv_handler;\n    act.sa_flags = SA_ONSTACK | SA_SIGINFO;\n    sigemptyset(&act.sa_mask);\n    sigaction(SIGSEGV, &act, NULL);\n\n    act.sa_sigaction = usr1_handler;\n    sigaction(SIGUSR1, &act, NULL);\n\n    pthread_create(&thread, NULL, do_thread, NULL);\n    test_assert(0 == sched_yield());\n    sleep(1000);\n    test_assert(0 && \"Should not reach here\");\n    return 0;\n  }\n\n  test_assert(child == wait(&status));\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigrt.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic int num_signals_caught;\n\nstatic void handle_sigrt(int sig) {\n  atomic_printf(\"Caught signal %d\\n\", sig);\n\n  ++num_signals_caught;\n}\n\nstatic void __attribute__((noinline)) my_raise(int sig) {\n/* Don't call raise() directly, since that can go through our syscall hooks\n   which mess up gdb's reverse-finish slightly.\n   Also, glibc's raise calls __pthread_kill_internal to make the syscall.\n   If the symbol for this cannot be found (as is the case on ArchLinux)\n   gdb's reverse-finish will keep reverse-continuing and hit the signal\n   when we reverse-finishing out of the signal handler.\n*/\n#ifdef __i386__\n  int tid = getpid();\n  /* Use a special instruction after the syscall to make sure we don't patch\n     it */\n  __asm__ __volatile__(\"xchg %%ebx,%%edi\\n\\t\"\n                       \"int $0x80\\n\\t\"\n                       \"xchg %%ebx,%%edi\\n\\t\" ::\"a\"(SYS_tgkill),\n                       \"c\"(tid), \"d\"(sig), \"D\"(tid));\n#elif defined(__x86_64__)\n  int tid = getpid();\n  /* Use a special instruction after the syscall to make sure we don't patch\n     it */\n  __asm__ __volatile__(\"syscall\\n\\t\"\n                       \"xchg %%rdx,%%rdx\\n\\t\" ::\"a\"(SYS_tgkill),\n                       \"D\"(tid), \"S\"(tid), \"d\"(sig));\n#elif defined(__aarch64__)\n  int tid = getpid();\n  register long x8 __asm__(\"x8\") = SYS_tgkill;\n  register long x0 __asm__(\"x0\") = (long)tid;\n  register long x1 __asm__(\"x1\") = (long)tid;\n  register long x2 __asm__(\"x2\") = (long)sig;\n  __asm__ volatile(\"b 1f\\n\\t\"\n                   \"mov x8, 0xdc\\n\"\n                   \"1:\\n\\t\"\n                   \"svc #0\\n\\t\"\n                   : \"+r\"(x0)\n                   : \"r\"(x1), \"r\"(x2), \"r\"(x8));\n#else\n  raise(sig);\n#endif\n}\n\n// Split this out because some aggressive inlining can confuse gdb, but\n// we rely on gdb being able to step properly.\nstatic sighandler_t __attribute__((noinline))\nmy_signal(int signum, sighandler_t handler) {\n  return signal(signum, handler);\n}\n\nint main(void) {\n  int i;\n\n  for (i = SIGRTMIN; i <= SIGRTMAX; ++i) {\n    breakpoint();\n    my_signal(i, handle_sigrt);\n    my_raise(i);\n  }\n\n  atomic_printf(\"caught %d signals; expected %d\\n\", num_signals_caught,\n                1 + SIGRTMAX - SIGRTMIN);\n  test_assert(1 + SIGRTMAX - SIGRTMIN == num_signals_caught);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigstop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status = -1;\n  struct timespec ts = { 0, 50000000 };\n\n  if (0 == (child = fork())) {\n    kill(getpid(), SIGSTOP);\n    test_assert(0 && \"child should not resume\");\n    return 77;\n  }\n\n  nanosleep(&ts, NULL);\n  test_assert(0 == waitpid(child, &status, WNOHANG));\n  test_assert(-1 == status);\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigstop2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status = -1;\n  struct timespec ts = { 0, 50000000 };\n\n  if (0 == (child = fork())) {\n    nanosleep(&ts, NULL);\n    kill(getpid(), SIGSTOP);\n    test_assert(0 && \"child should not resume\");\n    return 77;\n  }\n\n  test_assert(0 == waitpid(child, &status, WNOHANG));\n  test_assert(-1 == status);\n\n  test_assert(0 == kill(child, SIGKILL));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigsuspend.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* thread(__attribute__((unused)) void* p) {\n  sigset_t mask;\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGUSR1);\n  sigaddset(&mask, SIGUSR2);\n  test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, NULL));\n\n  test_assert(0 == kill(getpid(), SIGUSR1));\n  test_assert(0 == kill(getpid(), SIGUSR2));\n\n  return NULL;\n}\n\nstatic int usr1_hit;\nstatic int usr2_hit;\n\nstatic void handle_signal(int sig, __attribute__((unused)) siginfo_t* si,\n                          __attribute__((unused)) void* ctx) {\n  if (SIGUSR1 == sig) {\n    ++usr1_hit;\n  } else if (SIGUSR2 == sig) {\n    ++usr2_hit;\n  } else {\n    test_assert(\"Unexpected signal\" && 0);\n  }\n}\n\nint main(void) {\n  struct sigaction sa;\n  pthread_t t;\n  sigset_t mask;\n  int ret;\n  struct timespec ts;\n  siginfo_t si;\n\n  sa.sa_sigaction = handle_signal;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  sigaction(SIGUSR1, &sa, NULL);\n  sigaction(SIGUSR2, &sa, NULL);\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGUSR1);\n  sigaddset(&mask, SIGUSR2);\n  test_assert(0 == pthread_sigmask(SIG_BLOCK, &mask, NULL));\n\n  pthread_create(&t, NULL, thread, NULL);\n\n  sigemptyset(&mask);\n  sigaddset(&mask, SIGUSR1);\n  sigsuspend(&mask);\n\n  test_assert(usr1_hit == 0);\n  test_assert(usr2_hit == 1);\n\n  test_assert(0 == sigpending(&mask));\n  test_assert(1 == sigismember(&mask, SIGUSR1));\n  test_assert(0 == sigismember(&mask, SIGUSR2));\n\n  ts.tv_sec = 5;\n  ts.tv_nsec = 0;\n  ret = sigtimedwait(&mask, &si, &ts);\n  atomic_printf(\"Signal %d became pending\\n\", ret);\n  test_assert(SIGUSR1 == ret);\n  test_assert(si.si_signo == SIGUSR1);\n  test_assert(si.si_code == SI_USER);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigtrap.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_sigtrap(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nstatic void* dummy_thread(__attribute__((unused)) void* p) { return NULL; }\n\nint main(void) {\n  int status;\n  pthread_t thread;\n\n  signal(SIGTRAP, handle_sigtrap);\n\n  /* Test that if a process gets our SIGTRAP handler then that\n     works OK. */\n  if (!fork()) {\n    return 77;\n  }\n  test_assert(wait(&status) >= 0);\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  pthread_create(&thread, NULL, dummy_thread, NULL);\n  pthread_join(thread, NULL);\n\n  atomic_puts(\"raising SIGTRAP ...\");\n\n  raise(SIGTRAP);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sigtrap_process_group.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(0, SIGTRAP);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/simple.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/simple.run",
    "content": "source `dirname $0`/util.sh\nunset RR_TRUST_TEMP_FILES\nexport RR_COPY_ALL_FILES=1\nrecord simple$bitness\nif ! ( ls $workdir/latest-trace | grep -q 'mmap_.*libc.*\\.so' ); then\n    failed \"Can't find libc\"\nfi\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/simple_script.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_rr_32_bit_with_shell_64_bit\n\njust_record $TESTDIR/simple_script.sh\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/simple_script.sh",
    "content": "#!/bin/sh\n\necho EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/simple_script_debug.py",
    "content": "from util import *\n\nsend_gdb('b write')\n# \"Make breakpoint pending on future shared library load?\"\nsend_gdb('y')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nok()\n"
  },
  {
    "path": "src/test/simple_script_debug.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_rr_32_bit_with_shell_64_bit\n\njust_record $TESTDIR/simple_script.sh\ndebug_gdb_only simple_script_debug \"--onprocess simple_script.sh\"\n"
  },
  {
    "path": "src/test/simple_threads_stress.c",
    "content": "#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) { return 0; }\n\nint main(void) {\n  int i;\n  pthread_t thread[100];\n  for (i = 0; i < 100; ++i) {\n    pthread_create(&thread[i], NULL, do_thread, NULL);\n  }\n  for (i = 0; i < 100; ++i) {\n    pthread_join(thread[i], NULL);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/simple_winch.py",
    "content": "from util import *\n\n# Signal all processes in the process group\nsend_gdb('!kill -WINCH 0')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('run')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('!kill -WINCH 0')\nsend_gdb('reverse-cont')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/simple_winch.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only simple_winch\n"
  },
  {
    "path": "src/test/sioc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nconst char* sockaddr_name(const struct sockaddr* addr) {\n  const struct sockaddr_in* sin = (const struct sockaddr_in*)addr;\n  static char str[PATH_MAX];\n  /* FIXME: add INET6 support (original author didn't\n   * have ipv6 iface available to test).  */\n  test_assert(AF_INET == addr->sa_family);\n  return inet_ntop(AF_INET, (void*)&sin->sin_addr, str, sizeof(str));\n}\n\nconst char* sockaddr_hw_name(const struct sockaddr* addr) {\n  static char str[PATH_MAX];\n  const unsigned char* data = (const unsigned char*)addr->sa_data;\n  sprintf(str, \"%02x:%02x:%02x:%02x:%02x:%02x\", data[0], data[1], data[2],\n          data[3], data[4], data[5]);\n  return str;\n}\n\n/**\n * Fetch and print the ifconfig for this machine.  Fill in\n * |req.ifr_name| with the first non-loopback interface name found, preferring\n * a wireless interface if possible.\n * |eth_req| returns an ethernet interface if possible.\n */\nstatic void get_ifconfig(int sockfd, struct ifreq* req, struct ifreq* eth_req) {\n  struct {\n    struct ifreq ifaces[100];\n  }* ifaces;\n  struct ifconf* ifconf;\n  int ret;\n  ssize_t num_ifaces;\n  int i;\n  int wireless_index = -1;\n  int eth_index = -1;\n  int non_loop_index = -1;\n\n  ALLOCATE_GUARD(ifconf, 0xff);\n  ALLOCATE_GUARD(ifaces, 'y');\n  ifconf->ifc_len = sizeof(*ifaces);\n  ifconf->ifc_req = ifaces->ifaces;\n\n  ret = ioctl(sockfd, SIOCGIFCONF, ifconf);\n  VERIFY_GUARD(ifconf);\n  VERIFY_GUARD(ifaces);\n  num_ifaces = ifconf->ifc_len / sizeof(ifaces->ifaces[0]);\n  test_assert(num_ifaces < 100);\n  atomic_printf(\"SIOCGIFCONF(ret %d): %zd ifaces (%d bytes of ifreq)\\n\", ret,\n                num_ifaces, ifconf->ifc_len);\n  test_assert(0 == ret);\n  test_assert(0 == (ifconf->ifc_len % sizeof(ifaces->ifaces[0])));\n\n  if (!num_ifaces) {\n    atomic_puts(\"No interfaces found\\n\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n  }\n\n  for (i = 0; i < num_ifaces; ++i) {\n    const struct ifreq* ifc = &ifconf->ifc_req[i];\n    atomic_printf(\"  iface %d: name:%s addr:%s\\n\", i, ifc->ifr_name,\n                  sockaddr_name(&ifc->ifr_addr));\n    switch (ifc->ifr_name[0]) {\n      case 'w':\n        wireless_index = i;\n        non_loop_index = i;\n        break;\n      case 'e':\n        eth_index = i;\n        non_loop_index = i;\n        break;\n      case 't':\n      case 'l':\n        break;\n      default:\n        non_loop_index = i;\n        break;\n    }\n  }\n\n  if (wireless_index >= 0) {\n    strcpy(req->ifr_name, ifaces->ifaces[wireless_index].ifr_name);\n  } else if (non_loop_index >= 0) {\n    strcpy(req->ifr_name, ifaces->ifaces[non_loop_index].ifr_name);\n  } else {\n    strcpy(req->ifr_name, ifaces->ifaces[0].ifr_name);\n  }\n  if (eth_index >= 0) {\n    strcpy(eth_req->ifr_name, ifaces->ifaces[eth_index].ifr_name);\n  } else if (non_loop_index >= 0) {\n    strcpy(eth_req->ifr_name, ifaces->ifaces[non_loop_index].ifr_name);\n  } else {\n    strcpy(eth_req->ifr_name, ifaces->ifaces[0].ifr_name);\n  }\n}\n\n// Returns 0 if the request failed.\n// can fail non-fatally.\nstatic int generic_request_by_name(int sockfd, struct ifreq* req, int nr,\n                                   const char* nr_str) {\n  int ret;\n  memset(&req->ifr_ifru, 0xff, sizeof(req->ifr_ifru));\n  ret = ioctl(sockfd, nr, req);\n  VERIFY_GUARD(req);\n  atomic_printf(\"%s(ret:%d): %s \", nr_str, ret, req->ifr_name);\n  if (ret < 0) {\n    if (errno == EFAULT) {\n      /* Work around https://bugzilla.kernel.org/show_bug.cgi?id=202273 */\n      atomic_puts(\"Buggy kernel detected; aborting test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      exit(0);\n    }\n    if (errno == EADDRNOTAVAIL) {\n      // Some devices can return this in some configurations, e.g.\n      // see mac802154_wpan_ioctl\n      atomic_printf(\"(errno:%d/%s)\\n\", errno, strerror(errno));\n      return 0;\n    }\n    if (errno == EPERM) {\n      atomic_printf(\"(errno:%d/%s)\\n\", errno, strerror(errno));\n      return 0;\n    }\n  }\n\n  test_assert(0 == ret);\n  return 1;\n}\n\n#define GENERIC_REQUEST_BY_NAME(nr)                                            \\\n  generic_request_by_name(sockfd, req, nr, #nr)\n\nstatic int generic_wireless_request_by_name_internal(int sockfd,\n                                                     struct iwreq** wreq,\n                                                     const char* name, int nr,\n                                                     const char* nr_str) {\n  int err;\n  int ret;\n  /* Note that we use sizeof(struct ifreq) here, not iwreq, because of\n   * https://bugzilla.kernel.org/show_bug.cgi?id=195869\n   */\n  *wreq = allocate_guard(sizeof(struct ifreq), 'd');\n  strcpy((*wreq)->ifr_ifrn.ifrn_name, name);\n  ret = ioctl(sockfd, nr, *wreq);\n  VERIFY_GUARD(*wreq);\n  err = errno;\n  atomic_printf(\"%s(ret:%d): %s: \", nr_str, ret, (*wreq)->ifr_name);\n  if (-1 == ret) {\n    atomic_printf(\"WARNING: %s doesn't support ioctl %s\\n\", name, nr_str);\n    /* \"bond\" network devices can return ENODEV.\n       Some virtual ethernet devices can return ENOTTY. */\n    test_assert(EOPNOTSUPP == err || EPERM == err || EINVAL == err || ENODEV == err || ENOTTY == err);\n  }\n  return ret;\n}\n\n#define GENERIC_WIRELESS_REQUEST_BY_NAME_INTERNAL(nr, nr_str, args)            \\\n  if (generic_wireless_request_by_name_internal(sockfd, &wreq, name, nr,       \\\n                                                nr_str) == 0) {                \\\n    atomic_printf args;                                                        \\\n    atomic_puts(\"\");                                                           \\\n  }                                                                            \\\n  while (0)\n\n#define GENERIC_WIRELESS_REQUEST_BY_NAME(nr, args)                             \\\n  GENERIC_WIRELESS_REQUEST_BY_NAME_INTERNAL(nr, #nr, args)\n\n#define GENERIC_WIRELESS_PARAM_REQUEST_BY_NAME(nr, name)                       \\\n  GENERIC_WIRELESS_REQUEST_BY_NAME_INTERNAL(                                   \\\n      nr, #nr, (\"wireless %s:%d (fixed? %s; disabled? %s) flags:%#x\", #name,   \\\n                wreq->u.name.value, wreq->u.name.fixed ? \"yes\" : \"no\",         \\\n                wreq->u.name.disabled ? \"yes\" : \"no\", wreq->u.name.flags));\n\n#define GENERIC_ETHTOOL_REQUEST_BY_NAME(ptr, nr) \\\n  (ptr)->cmd = nr; \\\n  req->ifr_data = (char*)ptr; \\\n  ret = ioctl(sockfd, SIOCETHTOOL, req); \\\n  VERIFY_GUARD(req); \\\n  VERIFY_GUARD(ptr); \\\n  err = errno; \\\n  atomic_printf(\"SIOCETHTOOL(ret:%d) \" #nr \": %s ethtool data: \", ret, req->ifr_name); \\\n  if (-1 == ret) { \\\n    atomic_printf(\"WARNING: %s doesn't appear to support SIOCETHTOOL \" #nr \"\\n\", req->ifr_name); \\\n    test_assert(EOPNOTSUPP == err || EPERM == err); \\\n  }\n\nstatic inline unsigned int our_ethtool_cmd_speed(const struct ethtool_cmd *ep)\n{\n  return (ep->speed_hi << 16) | ep->speed;\n}\n\nstatic void ethtool(int sockfd, struct ifreq* req) {\n  struct ethtool_cmd* et_set;\n  struct ethtool_drvinfo* et_drvinfo;\n  struct ethtool_wolinfo* et_wolinfo;\n  union {\n    struct ethtool_regs et;\n    char data[sizeof(struct ethtool_regs) + 32];\n  }* et_regs;\n  union {\n    struct ethtool_eeprom et;\n    char data[sizeof(struct ethtool_eeprom) + 32];\n  }* et_eeprom;\n  struct ethtool_eee* et_eee;\n  struct ethtool_modinfo* et_modinfo;\n  struct ethtool_coalesce* et_coalesce;\n  struct ethtool_ringparam* et_ringparam;\n  struct ethtool_channels* et_channels;\n  struct ethtool_pauseparam* et_pauseparam;\n  union {\n    struct ethtool_sset_info et;\n    char data[sizeof(struct ethtool_sset_info) + 8*sizeof(uint32_t)];\n  }* et_sset_info;\n  union {\n    struct ethtool_gfeatures et;\n    char data[sizeof(struct ethtool_gfeatures) + 20*sizeof(struct ethtool_get_features_block)];\n  }* et_gfeatures;\n  union {\n    struct ethtool_perm_addr et;\n    char data[sizeof(struct ethtool_perm_addr) + 32];\n  }* et_perm_addr;\n  struct ethtool_value* et_glink;\n  struct ethtool_rxnfc* et_rxnfc;\n  int i;\n  int err;\n  int ret;\n\n  ALLOCATE_GUARD(et_set, 'b');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_set, ETHTOOL_GSET);\n  if (-1 == ret) {\n    return;\n  }\n  atomic_printf(\"speed:%#x duplex:%#x port:%#x physaddr:%#x, maxtxpkt:%u \"\n                \"maxrxpkt:%u ...\\n\",\n                our_ethtool_cmd_speed(et_set), et_set->duplex, et_set->port,\n                et_set->phy_address, et_set->maxtxpkt, et_set->maxrxpkt);\n\n  ALLOCATE_GUARD(et_drvinfo, 'c');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_drvinfo, ETHTOOL_GDRVINFO);\n  if (-1 != ret) {\n    #ifdef ETHTOOL_EROMVERS_LEN\n    atomic_printf(\"driver:%s version:%s fw_version:%s bus_info:%s erom_version:%s\\n\",\n                  et_drvinfo->driver, et_drvinfo->version, et_drvinfo->fw_version,\n                  et_drvinfo->bus_info, et_drvinfo->erom_version);\n    #else\n    atomic_printf(\"driver:%s version:%s fw_version:%s bus_info:%s\\n\",\n                  et_drvinfo->driver, et_drvinfo->version, et_drvinfo->fw_version,\n                  et_drvinfo->bus_info);\n    #endif\n  }\n\n  ALLOCATE_GUARD(et_wolinfo, 'd');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_wolinfo, ETHTOOL_GWOL);\n\n  ALLOCATE_GUARD(et_regs, 'e');\n  et_regs->et.len = sizeof(*et_regs) - sizeof(et_regs->et);\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(&et_regs->et, ETHTOOL_GREGS);\n  if (-1 != ret) {\n    uint32_t i;\n    for (i = 0; i < et_regs->et.len; ++i) {\n      atomic_printf(\"%02x \", et_regs->et.data[i]);\n    }\n    atomic_printf(\"\\n\");\n  }\n\n  ALLOCATE_GUARD(et_eeprom, 'f');\n  et_eeprom->et.offset = 0;\n  et_eeprom->et.len = sizeof(*et_eeprom) - sizeof(et_eeprom->et);\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(&et_eeprom->et, ETHTOOL_GEEPROM);\n  if (-1 != ret) {\n    uint32_t i;\n    for (i = 0; i < et_eeprom->et.len; ++i) {\n      atomic_printf(\"%02x \", et_eeprom->et.data[i]);\n    }\n    atomic_printf(\"\\n\");\n  }\n\n  ALLOCATE_GUARD(et_eeprom, 'g');\n  et_eeprom->et.offset = 0;\n  et_eeprom->et.len = sizeof(*et_eeprom) - sizeof(et_eeprom->et);\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(&et_eeprom->et, ETHTOOL_GMODULEEEPROM);\n  if (-1 != ret) {\n    uint32_t i;\n    for (i = 0; i < et_eeprom->et.len; ++i) {\n      atomic_printf(\"%02x \", et_eeprom->et.data[i]);\n    }\n    atomic_printf(\"\\n\");\n  }\n\n  ALLOCATE_GUARD(et_eee, 'h');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_eee, ETHTOOL_GEEE);\n  if (-1 != ret) {\n    atomic_printf(\"tx_lpi_timer:%d enabled:%d\\n\",\n                  et_eee->tx_lpi_timer, et_eee->eee_enabled);\n  }\n\n  ALLOCATE_GUARD(et_modinfo, 'i');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_modinfo, ETHTOOL_GMODULEINFO);\n\n  ALLOCATE_GUARD(et_coalesce, 'j');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_coalesce, ETHTOOL_GCOALESCE);\n  if (-1 != ret) {\n    atomic_printf(\"rx_coalesce_usecs:%d tx_coalesce_usecs:%d\\n\",\n                  et_coalesce->rx_coalesce_usecs, et_coalesce->tx_coalesce_usecs);\n  }\n\n  ALLOCATE_GUARD(et_ringparam, 'k');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_ringparam, ETHTOOL_GRINGPARAM);\n  if (-1 != ret) {\n    atomic_printf(\"rx_max_pending:%d rx_pending:%d tx_max_pending:%d tx_pending:%d\\n\",\n                  et_ringparam->rx_max_pending, et_ringparam->rx_pending,\n                  et_ringparam->rx_pending, et_ringparam->tx_pending);\n  }\n\n  ALLOCATE_GUARD(et_channels, 'l');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_channels, ETHTOOL_GCHANNELS);\n  if (-1 != ret) {\n    atomic_printf(\"max_rx:%d max_tx:%d\\n\",\n                  et_channels->max_rx, et_channels->max_tx);\n  }\n\n  ALLOCATE_GUARD(et_pauseparam, 'm');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_pauseparam, ETHTOOL_GPAUSEPARAM);\n  if (-1 != ret) {\n    atomic_printf(\"rx_pause:%d tx_pause:%d\\n\",\n                  et_pauseparam->rx_pause, et_pauseparam->tx_pause);\n  }\n\n  ALLOCATE_GUARD(et_sset_info, 'n');\n  et_sset_info->et.sset_mask = 0xff;\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(&et_sset_info->et, ETHTOOL_GSSET_INFO);\n  atomic_printf(\"\\n\");\n  if (-1 != ret) {\n    int index = 0;\n    for (i = 0; i < 8; ++i) {\n      if (et_sset_info->et.sset_mask & (1 << i)) {\n        uint32_t len = et_sset_info->et.data[index++];\n        size_t size = sizeof(struct ethtool_gstrings) + len*ETH_GSTRING_LEN;\n        char* buf = (char*)allocate_guard(size, 'o');\n        struct ethtool_gstrings* et_gstrings = (struct ethtool_gstrings*)buf;\n        et_gstrings->cmd = ETHTOOL_GSTRINGS;\n        et_gstrings->string_set = i;\n        req->ifr_data = buf;\n        ret = ioctl(sockfd, SIOCETHTOOL, req);\n        VERIFY_GUARD(req);\n        verify_guard(size, buf);\n        err = errno;\n        atomic_printf(\"SIOCETHTOOL(ret:%d) ETHTOOL_GSTRINGS: %s ethtool data: \", ret, req->ifr_name);\n        if (-1 == ret) {\n          atomic_printf(\"WARNING: %s doesn't appear to support SIOCETHTOOL ETHTOOL_GSTRINGS\\n\", req->ifr_name);\n          test_assert(EOPNOTSUPP == err || EPERM == err);\n        } else {\n          uint32_t j;\n          for (j = 0; j < len; ++j) {\n            atomic_printf(\"Group %d string %d: %s\\n\",\n                          i, j, buf + sizeof(struct ethtool_gstrings) + j*ETH_GSTRING_LEN);\n          }\n        }\n      }\n    }\n  }\n\n  ALLOCATE_GUARD(et_gfeatures, 'p');\n  et_gfeatures->et.size = 20;\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(&et_gfeatures->et, ETHTOOL_GFEATURES);\n  if (-1 != ret) {\n    int n = et_gfeatures->et.size;\n    if (n > 20) {\n      n = 20;\n    }\n    for (i = 0; i < n; ++i) {\n      atomic_printf(\"Feature %d available:%x requested:%x\\n\",\n        i, et_gfeatures->et.features[i].available, et_gfeatures->et.features[i].requested);\n    }\n  }\n\n  ALLOCATE_GUARD(et_perm_addr, 'q');\n  et_perm_addr->et.size = sizeof(*et_perm_addr) - sizeof(et_perm_addr->et);\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(&et_perm_addr->et, ETHTOOL_GPERMADDR);\n  if (-1 != ret) {\n    uint32_t i;\n    for (i = 0; i < et_perm_addr->et.size; ++i) {\n      atomic_printf(\"%02x \", et_perm_addr->et.data[i]);\n    }\n    atomic_printf(\"\\n\");\n  }\n\n  ALLOCATE_GUARD(et_glink, 'r');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_glink, ETHTOOL_GLINK);\n  if (-1 != ret) {\n    atomic_printf(\"interface is %s\\n\", et_glink->data ? \"up\" : \"down\");\n  }\n\n  ALLOCATE_GUARD(et_rxnfc, 's');\n  GENERIC_ETHTOOL_REQUEST_BY_NAME(et_rxnfc, ETHTOOL_GRXRINGS);\n  if (-1 != ret) {\n    atomic_printf(\"interface has %d RX rings/queues\\n\", (__u32)et_rxnfc->data);\n  }\n}\n\nint main(void) {\n  int sockfd = socket(AF_INET, SOCK_DGRAM, 0);\n  struct ifreq* req;\n  struct ifreq* eth_req;\n  char name[PATH_MAX];\n  int index;\n  int err, ret;\n  struct iwreq* wreq;\n  char buf[1024];\n\n  ALLOCATE_GUARD(req, 'a');\n  ALLOCATE_GUARD(eth_req, 'a');\n  get_ifconfig(sockfd, req, eth_req);\n  strcpy(name, req->ifr_name);\n\n  req->ifr_ifindex = -1;\n  strcpy(req->ifr_name, name);\n  ret = ioctl(sockfd, SIOCGIFINDEX, req);\n  VERIFY_GUARD(req);\n  atomic_printf(\"SIOCGIFINDEX(ret:%d): %s index is %d\\n\", ret, req->ifr_name,\n                req->ifr_ifindex);\n  if (ret < 0 && errno == EFAULT) {\n    /* Work around https://bugzilla.kernel.org/show_bug.cgi?id=199469 */\n    atomic_puts(\"Buggy kernel detected; aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0 == ret);\n  test_assert(req->ifr_ifindex != -1);\n  index = req->ifr_ifindex;\n\n  memset(&req->ifr_name, 0xff, sizeof(req->ifr_name));\n  req->ifr_ifindex = index;\n  ret = ioctl(sockfd, SIOCGIFNAME, req);\n  VERIFY_GUARD(req);\n  atomic_printf(\"SIOCGIFNAME(ret:%d): index %d(%s) name is %s\\n\", ret, index,\n                name, req->ifr_name);\n  test_assert(0 == ret);\n\n  GENERIC_REQUEST_BY_NAME(SIOCGIFFLAGS);\n  atomic_printf(\"flags are %#x\\n\", req->ifr_flags);\n\n  if (GENERIC_REQUEST_BY_NAME(SIOCGIFADDR)) {\n    atomic_printf(\"addr is %s\\n\", sockaddr_name(&req->ifr_addr));\n  }\n\n  if (GENERIC_REQUEST_BY_NAME(SIOCGIFDSTADDR)) {\n    atomic_printf(\"addr is %s\\n\", sockaddr_name(&req->ifr_addr));\n  }\n\n  if (GENERIC_REQUEST_BY_NAME(SIOCGIFBRDADDR)) {\n    atomic_printf(\"addr is %s\\n\", sockaddr_name(&req->ifr_addr));\n  }\n\n  if (GENERIC_REQUEST_BY_NAME(SIOCGIFNETMASK)) {\n    atomic_printf(\"netmask is %s\\n\", sockaddr_name(&req->ifr_addr));\n  }\n  if (ret < 0 && errno == EFAULT) {\n    /* Work around https://bugzilla.kernel.org/show_bug.cgi?id=202273 */\n    atomic_puts(\"Buggy kernel detected; aborting test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  GENERIC_REQUEST_BY_NAME(SIOCGIFMETRIC);\n  atomic_printf(\"metric is %d\\n\", req->ifr_metric);\n\n  GENERIC_REQUEST_BY_NAME(SIOCGIFMAP);\n  atomic_printf(\"map is %llu,%llu,%u,%d,%d,%d\\n\",\n                (unsigned long long)req->ifr_map.mem_start,\n                (unsigned long long)req->ifr_map.mem_end,\n                req->ifr_map.base_addr, req->ifr_map.irq, req->ifr_map.dma,\n                req->ifr_map.port);\n\n  memset(&req->ifr_metric, 0xff, sizeof(req->ifr_metric));\n  ret = ioctl(sockfd, SIOCGIFMEM, req);\n  VERIFY_GUARD(req);\n  test_assert(-1 == ret && errno == ENOTTY);\n\n  GENERIC_REQUEST_BY_NAME(SIOCGIFMTU);\n  atomic_printf(\"MTU is %d\\n\", req->ifr_mtu);\n\n  GENERIC_REQUEST_BY_NAME(SIOCGIFHWADDR);\n  atomic_printf(\"hwaddr %s\\n\", sockaddr_hw_name(&req->ifr_addr));\n\n  memset(&req->ifr_flags, 0xff, sizeof(req->ifr_flags));\n  ret = ioctl(sockfd, SIOCGIFPFLAGS, req);\n  VERIFY_GUARD(req);\n  if (ret != -1 || errno != EINVAL) {\n    test_assert(0 == ret);\n    atomic_printf(\"SIOCGIFPFLAGS(ret:%d): %s flags are\", ret, req->ifr_name);\n    atomic_printf(\" %#x\\n\", req->ifr_flags);\n  }\n\n  GENERIC_REQUEST_BY_NAME(SIOCGIFTXQLEN);\n  atomic_printf(\"qlen is %d\\n\", req->ifr_qlen);\n\n  ethtool(sockfd, eth_req);\n\n  GENERIC_WIRELESS_REQUEST_BY_NAME(SIOCGIWNAME,\n                                   (\"wireless protocol name:%s\", wreq->u.name));\n\n  GENERIC_WIRELESS_REQUEST_BY_NAME(SIOCGIWMODE,\n                                   (\" wireless mode:%d\", wreq->u.mode));\n\n  GENERIC_WIRELESS_PARAM_REQUEST_BY_NAME(SIOCGIWSENS, sens);\n\n  GENERIC_WIRELESS_PARAM_REQUEST_BY_NAME(SIOCGIWRATE, bitrate);\n\n  /* Note that we use sizeof(struct ifreq) here, not iwreq, because of\n   * https://bugzilla.kernel.org/show_bug.cgi?id=195869\n   */\n  wreq = allocate_guard(sizeof(struct ifreq), 'e');\n  strcpy(wreq->ifr_ifrn.ifrn_name, name);\n  wreq->u.essid.length = sizeof(buf);\n  wreq->u.essid.pointer = buf;\n  wreq->u.essid.flags = 0;\n  ret = ioctl(sockfd, SIOCGIWESSID, wreq);\n  VERIFY_GUARD(wreq);\n  err = errno;\n  atomic_printf(\"SIOCGIWESSID(ret:%d): %s: \", ret, wreq->ifr_name);\n  if (-1 == ret) {\n    atomic_printf(\"WARNING: %s doesn't appear to be a wireless iface\\n\", name);\n    /* \"bond\" network devices can return ENODEV.\n       Some virtual ethernet devices return ENOTTY. */\n    test_assert(EOPNOTSUPP == err || EPERM == err || EINVAL == err || ENODEV == err || ENOTTY == err);\n  } else {\n    atomic_printf(\"wireless ESSID:%s\\n\", buf);\n  }\n\n  if (GENERIC_REQUEST_BY_NAME(SIOCGMIIPHY)) {\n    atomic_printf(\"flags is %d\\n\", req->ifr_ifru.ifru_flags);\n  }\n\n  if (GENERIC_REQUEST_BY_NAME(SIOCGMIIREG)) {\n    atomic_printf(\"flags is %d\\n\", req->ifr_ifru.ifru_flags);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/small_holes.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char* p;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"small\", O_RDWR | O_TRUNC | O_CREAT, 0700);\n  test_assert(0 == ftruncate(fd, page_size*7));\n  pwrite(fd, \"x\", 1, page_size);\n  pwrite(fd, \"y\", 1, page_size*3);\n  pwrite(fd, \"z\", 1, page_size*5);\n  p = (char*)mmap(NULL, page_size*7, PROT_READ, MAP_SHARED, fd, 0);\n  test_assert(p != MAP_FAILED);\n  test_assert(p[page_size] == 'x');\n  test_assert(p[page_size*3] == 'y');\n  test_assert(p[page_size*5] == 'z');\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sock_name_null.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int sock_fd = socket(AF_UNIX, SOCK_STREAM, 0);\n  int ret;\n  socklen_t len = 0;\n  test_assert(sock_fd >= 0);\n\n  ret = getsockname(sock_fd, NULL, &len);\n  test_assert(ret == 0);\n  test_assert(len > 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/sock_names_opts.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void client(const struct sockaddr_un* addr) {\n  int clientfd;\n  char c;\n  struct sockaddr_un got_peer_addr;\n  socklen_t got_peer_addr_len = sizeof(got_peer_addr);\n\n  clientfd = socket(AF_UNIX, SOCK_STREAM, 0);\n  test_assert(clientfd >= 0);\n  test_assert(0 == connect(clientfd, (struct sockaddr*)addr, sizeof(*addr)));\n\n  test_assert(0 == getpeername(clientfd, (struct sockaddr*)&got_peer_addr, &got_peer_addr_len));\n  test_assert(got_peer_addr_len > 0 &&\n              got_peer_addr_len <= sizeof(got_peer_addr));\n  test_assert(0 == memcmp(&got_peer_addr, addr, got_peer_addr_len));\n\n  test_assert(1 == read(clientfd, &c, 1));\n  test_assert(c == '!');\n\n  exit(7);\n}\n\nint main(void) {\n  struct sockaddr_un addr;\n  struct sockaddr_un got_name;\n  socklen_t got_name_len = sizeof(got_name);\n  int listenfd;\n  int servefd;\n  struct sockaddr_un peer_addr;\n  socklen_t peer_addr_len = sizeof(peer_addr);\n  pid_t child;\n  int on = 1;\n  int got_opt = -1;\n  socklen_t got_opt_len = sizeof(got_opt);\n  int status;\n\n  memset(&addr, 0, sizeof(addr));\n  addr.sun_family = AF_UNIX;\n  strncpy(addr.sun_path, \"socket.unix\", sizeof(addr.sun_path) - 1);\n\n  test_assert(0 <= (listenfd = socket(AF_UNIX, SOCK_STREAM, 0)));\n  test_assert(0 == bind(listenfd, (struct sockaddr*)&addr, sizeof(addr)));\n\n  test_assert(0 == getsockname(listenfd, (struct sockaddr*)&got_name, &got_name_len));\n  test_assert(got_name_len > 0 && got_name_len <= sizeof(got_name));\n  test_assert(0 == memcmp(&addr, &got_name, got_name_len));\n\n  test_assert(0 == listen(listenfd, 1));\n  if (0 == (child = fork())) {\n    client(&addr);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  test_assert(0 <= (servefd = accept(listenfd, (struct sockaddr*)&peer_addr, &peer_addr_len)));\n\n  test_assert(0 == getsockopt(servefd, SOL_SOCKET, SO_PASSCRED, &got_opt,\n                              &got_opt_len));\n  test_assert(got_opt_len == sizeof(got_opt));\n  test_assert(got_opt == 0);\n  test_assert(0 ==\n              setsockopt(servefd, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)));\n  test_assert(0 == getsockopt(servefd, SOL_SOCKET, SO_PASSCRED, &got_opt,\n                              &got_opt_len));\n  test_assert(got_opt_len == sizeof(got_opt));\n  test_assert(got_opt == 1);\n\n  test_assert(1 == write(servefd, \"!\", 1));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 7);\n\n  unlink(addr.sun_path);\n\n  // Make sure the syscallbuf doesn't crash on an invalid fd\n  int procfd = open(\"/proc/self/mem\", O_RDONLY);\n  test_assert(procfd >= 0);\n  test_assert(-1 == getsockopt(procfd, SOL_SOCKET, SO_PASSCRED, &got_opt,\n                               &got_opt_len));\n  test_assert(errno == ENOTSOCK);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/spinlock_priorities.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int low_priority_thread_scheduled = 0;\n\nstatic int low_to_high[2];\nstatic int high_to_low[2];\n\nstatic void* low_priority_thread(__attribute__((unused)) void* p) {\n  char ch;\n\n  setpriority(PRIO_PROCESS, 0, 4);\n\n  test_assert(1 == write(low_to_high[1], \"x\", 1));\n  test_assert(1 == read(high_to_low[0], &ch, 1));\n\n  __sync_val_compare_and_swap(&low_priority_thread_scheduled, 0, 1);\n\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  char ch;\n\n  test_assert(0 == pipe(low_to_high));\n  test_assert(0 == pipe(high_to_low));\n\n  pthread_create(&thread, NULL, low_priority_thread, NULL);\n\n  test_assert(1 == read(low_to_high[0], &ch, 1));\n  test_assert(1 == write(high_to_low[1], \"y\", 1));\n\n  test_assert(!low_priority_thread_scheduled);\n\n  while (__sync_val_compare_and_swap(&low_priority_thread_scheduled, 1, 0) ==\n         0) {\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/splice.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define TOKEN \"ABC\"\n#define TOKEN_SIZE sizeof(TOKEN)\n\nstatic const char token_file[] = \"rr-splice-file.txt\";\n\nvoid verify_token(int fd) {\n  ssize_t len;\n  char buf[TOKEN_SIZE];\n\n  len = read(fd, buf, sizeof(buf));\n  if (len != TOKEN_SIZE || strcmp(buf, TOKEN)) {\n    atomic_puts(\"Internal error: FAILED: splice wrote the wrong data\");\n    exit(1);\n  }\n  atomic_puts(\"Got expected token \" TOKEN);\n}\n\nint main(void) {\n  int pipefds[2];\n  int filefd;\n  loff_t off;\n  ssize_t nmoved;\n\n  filefd = open(token_file, O_RDWR | O_CREAT | O_TRUNC, 0600);\n  pipe2(pipefds, 0 /*no flags*/);\n  write(pipefds[1], TOKEN, TOKEN_SIZE);\n\n  off = 0;\n  nmoved = splice(pipefds[0], NULL, filefd, &off, TOKEN_SIZE, 0 /*no flags*/);\n  atomic_printf(\n      \"spliced %zd bytes from %d to %d; off changed from 0 to %\" PRId64 \"\\n\",\n      nmoved, pipefds[0], filefd, off);\n\n  lseek(filefd, 0, SEEK_SET);\n  verify_token(filefd);\n\n  off = 0;\n  nmoved = splice(filefd, &off, pipefds[1], NULL, TOKEN_SIZE, 0 /*no flags*/);\n  atomic_printf(\n      \"spliced %zd bytes from %d to %d; off changed from 0 to %\" PRId64 \"\\n\",\n      nmoved, filefd, pipefds[1], off);\n\n  verify_token(pipefds[0]);\n\n  /* The test driver will clean up after us if the test failed\n   * before this. */\n  unlink(token_file);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_growth.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int v = 0;\n\nstatic void breakpoint(void) {}\n\nstatic void funcall(void) {\n  char buf[2000000];\n  size_t i;\n  breakpoint();\n  for (i = 0; i < sizeof(buf); ++i) {\n    buf[i] = (char)i;\n  }\n  for (i = 0; i < sizeof(buf); ++i) {\n    v += buf[i % 777777];\n  }\n}\n\nint main(void) {\n  funcall();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_growth.py",
    "content": "import re\n\nfrom util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\n\nsend_gdb('watch -l buf[100]')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb(re.compile('New value = ([0-9]+)'))\nvalue = int(last_match().group(1))\n# gcc/gdb on Ubuntu 24 LTS Aarch64 produce 84 here.\n# I think it's a gdb bug, using the wrong frame base.\n# The value of i is also incorrect in gdb (always zero).\nif value != 100 and value != 84:\n    failed('Unexpected value')\n\nok()\n"
  },
  {
    "path": "src/test/stack_growth.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/stack_growth_after_syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int recurse(int count) {\n  if (count == 0) {\n    return 77;\n  }\n  return recurse(count - 1) * 99;\n}\n\nint main(void) {\n  struct rlimit limit;\n  int fd = open(\"/dev/zero\", O_RDONLY);\n  char ch;\n  test_assert(fd >= 0);\n\n  test_assert(0 == getrlimit(RLIMIT_STACK, &limit));\n  limit.rlim_cur = RLIM_INFINITY;\n  /* This could fail; that's OK. We just want to try to test an\n     unlimited stack size. */\n  setrlimit(RLIMIT_STACK, &limit);\n\n  test_assert(1 == read(fd, &ch, 1));\n  test_assert(1 == read(fd, &ch, 1));\n\n  atomic_printf(\"recurse=%d\\n\", recurse(10000));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_growth_syscallbuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int fd;\n\nstatic int recurse(int n) {\n  char ch[8];\n  if (n <= 0) {\n    return 0;\n  }\n  /* Use a system call that goes through SYSENTER on x86-32 */\n  test_assert(8 == read(fd, ch, 8));\n  return recurse(n - 1) + ch[0];\n}\n\nint main(void) {\n  fd = open(\"/dev/zero\", O_RDONLY);\n  test_assert(fd >= 0);\n\n  recurse(10000);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_growth_with_guard.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char* volatile end_of_guard_addr;\nstatic volatile char got_segv;\n\nstatic void handler(__attribute__((unused)) int sig) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  test_assert(end_of_guard_addr ==\n              mmap(end_of_guard_addr, page_size, PROT_READ | PROT_WRITE,\n                   MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0));\n  got_segv = 1;\n}\n\nint main(void) {\n  int local_var;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  char* guard_addr =\n      (char*)(((uintptr_t)&local_var) & ~((uintptr_t)page_size - 1)) -\n      262 * page_size;\n  int i;\n  test_assert(guard_addr == mmap(guard_addr, page_size * 128, PROT_NONE,\n                                 MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1,\n                                 0));\n  end_of_guard_addr = guard_addr + page_size * 128;\n  atomic_printf(\"guard_addr=%p end_of_guard_addr=%p\\n\", guard_addr,\n                end_of_guard_addr);\n\n  /* Extend mapping close to the actual address we want to test. */\n  for (i = 127; i >= 5; --i) {\n    end_of_guard_addr[page_size * i] = 77;\n  }\n\n  signal(SIGSEGV, handler);\n  /* This should cause a SEGV since we should not be able to extend the stack\n     to make it adjacent to our guard page.\n     The handler should fire and unmap the guard page so the write can\n     succeed. */\n  end_of_guard_addr[0] = 77;\n  test_assert(got_segv);\n  test_assert(end_of_guard_addr[0] == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_invalid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char ch = 'E';\nstatic long saved_sp;\n\nstatic ssize_t my_write(int fd, void* buf, size_t size) {\n  ssize_t ret;\n/* Do a write syscall with no valid stack. */\n#ifdef __x86_64__\n  asm(\"mov %%rsp,%5\\n\\t\"\n      \"xor %%rsp,%%rsp\\n\\t\"\n      \"syscall\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"mov %5,%%rsp\\n\\t\"\n      : \"=a\"(ret)\n      : \"a\"(SYS_write), \"D\"(fd), \"S\"(buf), \"d\"(size), \"m\"(saved_sp));\n#elif __i386__\n  asm(\"mov %%esp,%5\\n\\t\"\n      \"xor %%esp,%%esp\\n\\t\"\n      \"int $0x80\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"mov %5,%%esp\\n\\t\"\n      : \"=a\"(ret)\n      : \"a\"(SYS_write), \"b\"(fd), \"c\"(buf), \"d\"(size), \"m\"(saved_sp));\n#elif __aarch64__\n  register long x8 __asm__(\"x8\") = SYS_write;\n  register long x0 __asm__(\"x0\") = (long)fd;\n  register long x1 __asm__(\"x1\") = (long)buf;\n  register long x2 __asm__(\"x2\") = (long)size;\n  register long x6 __asm__(\"x6\") = 0;\n  asm(\"mov x6, sp\\n\\t\"\n      \"str x6,%1\\n\\t\"\n      \"eor x6,x6,x6\\n\\t\"\n      \"mov sp,x6\\n\\t\"\n      \"svc #0\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"ldr x6,%1\\n\\t\"\n      \"mov sp,x6\\n\\t\"\n      : \"+r\"(x0), \"+m\"(saved_sp), \"+r\"(x6) :\n      \"r\"(x1), \"r\"(x2), \"r\"(x8));\n  ret = x0;\n#else\n#error Unknown architecture\n#endif\n  return ret;\n}\n\nint main(void) {\n  test_assert(1 == my_write(STDOUT_FILENO, &ch, 1));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_overflow.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int* depth;\n\nstatic int recurse(void) {\n  int result;\n  ++*depth;\n  if (*depth > 10000000) {\n    return 3;\n  }\n  result = recurse() * 13 + 1;\n  --*depth;\n  return result;\n}\n\nstatic void SEGV_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  atomic_puts(\n      \"Should not reach SEGV handler, since there's no safe altstack to use\");\n  exit(1);\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  depth = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n               MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  test_assert(depth != MAP_FAILED);\n\n  child = fork();\n\n  if (!child) {\n    /* Testing shows that the output value of |depth| is not very sensitive to\n       small values of the limit, but it's very sensitive around the 500K mark.\n    */\n    struct rlimit r = { 500000, 500000 };\n    struct sigaction act;\n\n    act.sa_sigaction = SEGV_handler;\n    act.sa_flags = SA_SIGINFO;\n    sigemptyset(&act.sa_mask);\n    test_assert(0 == sigaction(SIGSEGV, &act, NULL));\n\n    test_assert(0 == setrlimit(RLIMIT_STACK, &r));\n\n    return recurse();\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n  test_assert(wait(&status) == child);\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n  atomic_printf(\"depth = %d\\n\", *depth);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stack_overflow_altstack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int depth = 0;\n\nstatic void SEGV_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  atomic_printf(\"depth = %d\\n\", depth);\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nstatic int recurse(void) {\n  int result;\n  ++depth;\n  if (depth > 10000000) {\n    return 3;\n  }\n  result = recurse() * 13 + 1;\n  --depth;\n  return result;\n}\n\nint main(void) {\n  /* Testing shows that the output value of |depth| is not very sensitive to\n     small values of the limit, but it's very sensitive around the 500K mark.\n  */\n  struct rlimit r = { 500000, 500000 };\n  struct sigaction act;\n  stack_t stack;\n  size_t stack_size = SIGSTKSZ;\n\n  stack.ss_flags = 0;\n  stack.ss_size = stack_size;\n  stack.ss_sp = mmap(NULL, stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(0 == sigaltstack(&stack, NULL));\n\n  act.sa_sigaction = SEGV_handler;\n  act.sa_flags = SA_SIGINFO | SA_ONSTACK;\n  sigemptyset(&act.sa_mask);\n  test_assert(0 == sigaction(SIGSEGV, &act, NULL));\n\n  test_assert(0 == setrlimit(RLIMIT_STACK, &r));\n\n  return recurse();\n}\n"
  },
  {
    "path": "src/test/stack_overflow_debug.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('c')\nexpect_gdb('SIGSEGV')\nsend_gdb('stepi')\nexpect_gdb('SIGSEGV')\nsend_gdb('stepi')\nexpect_gdb('SIGKILL')\n\nsend_gdb('reverse-stepi')\nexpect_gdb('SIGSEGV')\nsend_gdb('reverse-stepi')\nexpect_gdb('SIGSEGV')\nsend_gdb('reverse-continue')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/stack_overflow_debug.run",
    "content": "source `dirname $0`/util.sh\n\nrecord stack_overflow$bitness\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only stack_overflow_debug \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/stack_overflow_with_guard.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int* depth;\n\nstatic int recurse(void) {\n  int result;\n  ++*depth;\n  if (*depth > 10000000) {\n    return 3;\n  }\n  result = recurse() * 13 + 1;\n  --*depth;\n  return result;\n}\n\nstatic void SEGV_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si,\n                         __attribute__((unused)) void* context) {\n  atomic_puts(\n      \"Should not reach SEGV handler, since there's no safe altstack to use\");\n  exit(1);\n}\n\nint main(int argc, __attribute__((unused)) char* argv[]) {\n  pid_t child;\n  int status;\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  depth = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n               MAP_ANONYMOUS | MAP_SHARED, -1, 0);\n  test_assert(depth != MAP_FAILED);\n\n  child = fork();\n\n  if (!child) {\n    struct sigaction act;\n    int* fake_sp = &argc;\n\n    act.sa_sigaction = SEGV_handler;\n    act.sa_flags = SA_SIGINFO;\n    sigemptyset(&act.sa_mask);\n    test_assert(0 == sigaction(SIGSEGV, &act, NULL));\n\n    void* p =\n        (void*)((size_t)(fake_sp - 8 * page_size) & ~(size_t)(page_size - 1));\n\n    test_assert(mmap(p, page_size, PROT_NONE,\n                     MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0) == p);\n\n    return recurse();\n  }\n\n  test_assert(wait(&status) == child);\n  test_assert(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV);\n\n  atomic_printf(\"depth = %d\\n\", *depth);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/statfs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define DUMMY_FILENAME \"foo.txt\"\n\nstatic void dump_statfs(const char* label, const struct statfs* s) {\n  atomic_printf(\"%s: {\\n\"\n                \"    type:0x%lx, bsize:%ld, \\n\"\n                \"    blocks:%lld, bfree:%lld, bavail:%lld,\\n\"\n                \"    files:%llu, ffree:%llu,\\n\"\n                \"    fsid: { %d, %d },\\n\"\n                \"    namelen:%ld, frsize:%ld,\\n\"\n                \"    flags:0x%lx\\n\"\n                \"}\\n\",\n                label, (long)s->f_type, (long)s->f_bsize, (long long)s->f_blocks,\n                (long long)s->f_bfree, (long long)s->f_bavail, (unsigned long long)s->f_files, (unsigned long long)s->f_ffree,\n                s->f_fsid.__val[0], s->f_fsid.__val[1], (long)s->f_namelen,\n                (long)s->f_frsize, (long)s->f_flags);\n}\n\nstatic int same_statfs_det(const struct statfs* s1, const struct statfs* s2) {\n  /* Only compare the ~deterministic members; the free/avail\n   * resource members can change in between calls. */\n  return (s1->f_type == s2->f_type && s1->f_bsize == s2->f_bsize &&\n          s1->f_blocks == s2->f_blocks &&\n          s1->f_fsid.__val[0] == s2->f_fsid.__val[0] &&\n          s1->f_fsid.__val[1] == s2->f_fsid.__val[1] &&\n          s1->f_namelen == s2->f_namelen && s1->f_frsize == s2->f_frsize &&\n          s1->f_flags == s2->f_flags);\n}\n\nint main(void) {\n  int fd;\n  struct statfs* sfs1;\n  struct statfs* sfs2;\n\n  ALLOCATE_GUARD(sfs1, 0);\n  ALLOCATE_GUARD(sfs2, 1);\n  fd = creat(DUMMY_FILENAME, 0600);\n  test_assert(fd >= 0);\n  test_assert(0 == statfs(DUMMY_FILENAME, sfs1));\n  test_assert(0 == fstatfs(fd, sfs2));\n  VERIFY_GUARD(sfs1);\n  VERIFY_GUARD(sfs2);\n\n  dump_statfs(\"statfs buffer\", sfs1);\n  dump_statfs(\"fstatfs buffer\", sfs2);\n\n  test_assert(same_statfs_det(sfs1, sfs2));\n\n  unlink(DUMMY_FILENAME);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/statx.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstruct rr_statx_timestamp {\n  int64_t tv_sec;\n  uint32_t tv_nsec;\n  int32_t __reserved;\n};\n\nstruct rr_statx {\n  uint32_t stx_mask;\n  uint32_t stx_blksize;\n  uint64_t stx_attributes;\n  uint32_t stx_nlink;\n  uint32_t stx_uid;\n  uint32_t stx_gid;\n  uint16_t stx_mode;\n  uint16_t __spare0;\n  uint64_t stx_ino;\n  uint64_t stx_size;\n  uint64_t stx_blocks;\n  uint64_t stx_attributes_mask;\n  struct rr_statx_timestamp stx_atime;\n  struct rr_statx_timestamp stx_btime;\n  struct rr_statx_timestamp stx_ctime;\n  struct rr_statx_timestamp stx_mtime;\n  uint32_t stx_rdev_major;\n  uint32_t stx_rdev_minor;\n  uint32_t stx_dev_major;\n  uint32_t stx_dev_minor;\n  uint64_t __spare2[14];\n};\n\n#define RR_STATX_ALL 0xfff\n\nint main(void) {\n  struct rr_statx* buf;\n  int ret;\n\n  ALLOCATE_GUARD(buf, 0);\n  ret = syscall(RR_statx, AT_FDCWD, \".\", 0, RR_STATX_ALL, buf);\n  VERIFY_GUARD(buf);\n\n  if (ret < 0) {\n    test_assert(errno == ENOSYS);\n  } else {\n    test_assert(buf->stx_mask != 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/std_random.cc",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <random>\n\nint main(void) {\n  std::random_device device;\n  atomic_printf(\"Random value = %d\\n\", device());\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stdout_child.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  pid_t child;\n  int status;\n\n  if (argc == 2) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  if (0 == (child = fork())) {\n    execl(argv[0], argv[0], \"step2\", NULL);\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stdout_cloexec.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  pid_t child;\n  int status;\n\n  if (argc == 2) {\n    /* With syscallbuf disabled, this should open on fd 1.\n       Then, the following puts will succeed, but rr should\n       not echo to the terminal during replay, as long as our\n       CLOEXEC handling works. */\n    open(\"/dev/null\", O_WRONLY);\n    atomic_puts(\"FAILED: this output should be hidden\");\n    return 77;\n  }\n\n  if (0 == (child = fork())) {\n    test_assert(0 == fcntl(STDOUT_FILENO, F_SETFD, FD_CLOEXEC));\n    execl(argv[0], argv[0], \"step2\", NULL);\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stdout_dup.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = dup(STDOUT_FILENO);\n\n  static const char msg[] = \"EXIT-SUCCESS\\n\";\n  write(fd, msg, sizeof(msg) - 1);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stdout_redirect.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  pid_t child;\n  int status;\n\n  if (argc == 2) {\n    atomic_puts(\"FAILED: this output should be hidden\");\n    return 77;\n  }\n\n  if (0 == (child = fork())) {\n    int fd = open(\"/dev/null\", O_WRONLY);\n    test_assert(fd >= 0);\n    test_assert(STDOUT_FILENO == dup2(fd, STDOUT_FILENO));\n    execl(argv[0], argv[0], \"step2\", NULL);\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/step1.py",
    "content": "from util import *\n\nsend_gdb('b A')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_rr('calling A')\nexpect_gdb('Breakpoint 1, A')\n\nsend_gdb('n')\nexpect_rr('calling B')\n\nsend_gdb('s')\nexpect_gdb('B ()')\n\nsend_gdb('n')\nexpect_rr('calling C')\n\nsend_gdb('s')\nexpect_gdb('C ()')\n\nsend_gdb('bt')\nexpect_gdb('#0[^C]+C[^#]+#1[^B]+B[^#]+#2[^A]+A[^#]+#3[^m]+main')\n\nok()\n"
  },
  {
    "path": "src/test/step1.run",
    "content": "source `dirname $0`/util.sh\nrecord breakpoint$bitness\ndebug_gdb_only step1\n"
  },
  {
    "path": "src/test/step_into_lib.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid lib_exit_success(void);\n\nint main(void) {\n  lib_exit_success();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/step_into_lib.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('continue')\nexpect_gdb('Breakpoint 1')\nexpect_gdb(re.compile(r'\\s([a-z_]+)\\('))\nif last_match().group(1) == 'main':\n    send_gdb('s')\n    expect_gdb('lib_exit_success')\n\nsend_gdb('s')\n# Should have stepped into lib_exit_success where there's an atomic_puts\nexpect_gdb('atomic_puts')\n\nok()\n"
  },
  {
    "path": "src/test/step_into_lib.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/step_signal.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nsend_gdb('fin')\nindex = expect_list([re.compile(r'signal\\(i, handle_sigrt\\)'), re.compile('breakpoint')])\nif index == 1:\n    send_gdb('n')\n    expect_gdb(r'signal\\(i, handle_sigrt\\)')\n\nsend_gdb('n')\nexpect_gdb(r'raise\\(i\\)')\n\nsend_gdb('n')\nexpect_gdb('Program received signal SIG34')\n\nsend_gdb('stepi')\nsend_gdb('n')\nexpect_gdb(r'atomic_printf\\(\"Caught signal')\n\nok()\n"
  },
  {
    "path": "src/test/step_signal.run",
    "content": "source `dirname $0`/util.sh\nrecord sigrt$bitness\ndebug_gdb_only step_signal\n"
  },
  {
    "path": "src/test/step_thread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\npthread_barrier_t bar;\n\n/* NB: these must *not* be macros so that debugger step-next works as\n * expected per the program source. */\nstatic void A(void) {\n  pthread_barrier_wait(&bar); // Barrier 3\n  pthread_barrier_wait(&bar); // Barrier 4\n}\nstatic void B(void) {\n  pthread_barrier_wait(&bar); // Barrier 3\n  pthread_barrier_wait(&bar); // Barrier 4\n}\n\nstatic void* threadA(__attribute__((unused)) void* unused) {\n  pthread_barrier_wait(&bar); // Barrier 1\n  pthread_barrier_wait(&bar); // Barrier 2\n  A();\n  return NULL;\n}\nstatic void* threadB(__attribute__((unused)) void* unused) {\n  pthread_barrier_wait(&bar); // Barrier 1\n  pthread_barrier_wait(&bar); // Barrier 2\n  B();\n  return NULL;\n}\n\nstatic void C(void) {\n  pthread_barrier_wait(&bar); // Barrier 3\n}\n\nstatic void hit_barrier(void) {\n  int break_here = 1;\n  (void)break_here;\n  atomic_puts(\"hit barrier\");\n}\n\nstatic void ready(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  pthread_t a, b;\n\n  pthread_barrier_init(&bar, NULL, 3);\n\n  pthread_create(&a, NULL, threadA, NULL);\n  pthread_create(&b, NULL, threadB, NULL);\n\n  pthread_barrier_wait(&bar); // Barrier 1\n\n  ready();\n\n  pthread_barrier_wait(&bar); // Barrier 2\n\n  C();\n  hit_barrier();\n\n  pthread_barrier_wait(&bar); // Barrier 4\n\n  pthread_join(a, NULL);\n  pthread_join(b, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/step_thread.py",
    "content": "import re\nfrom util import *\n\nsend_gdb('set scheduler-locking off')\n\nsend_gdb('b hit_barrier')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('b ready')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 2, ready')\n\nbps = set(('A', 'B', 'C'))\nfor bp in bps:\n    send_gdb('b '+ bp +'')\n    expect_gdb('Breakpoint \\d')\n\nexpect_gdb(r'\\(rr\\)')\n\nhit_bps = { 'A': 0, 'B': 0, 'C': 0 }\n\nevents = [ re.compile(r'Breakpoint 1, hit_barrier'),\n           re.compile(r'Breakpoint \\d, ([ABC])'),\n           re.compile(r'Remote connection closed'),\n           re.compile(r'internal-error:'),\n           re.compile(r'Cannot find bounds of current function'),\n           re.compile(r'\\(rr\\)') ]\nnext_cmd = 's'\nwhile 1:\n    send_gdb(next_cmd)\n    next_cmd = 's'\n    i = expect_list(events)\n    if 0 == i:\n        break\n    if 2 == i or 3 == i:\n        assert False, 'Program stopped unexpectedly, review gdb_rr.log'\n    if 4 == i:\n        expect_gdb(r'\\(rr\\)')\n        next_cmd = 'stepi'\n        continue\n    if 5 == i:\n        continue\n\n    bp = last_match().group(1)\n    assert not hit_bps[bp]\n    hit_bps[bp] = 1\n    expect_gdb(r'\\(rr\\)')\n\nfor bp in hit_bps.keys():\n    assert hit_bps[bp]\n\narch = get_exe_arch()\n\n# The locations the threads are stopped at depends on the architecture.\nstopped_locations = {\n    # on i386, we sometimes stop in the middle of nowhere\n    'i386': ['(0x[0-9a-f]+ in )?__kernel_vsyscall',\n             '(0x[0-9a-f]+ in )?_traced_raw_syscall',\n              '0x[0-9a-f]+ in \\?\\?',\n             '(0x[0-9a-f]+ in )?rr_page_start',\n             '(0x[0-9a-f]+ in )?syscall_traced',\n             '(0x[0-9a-f]+ in )?__lll_lock_wait',\n             '(0x[0-9a-f]+ in )?pthread_barrier_wait',\n             '(0x[0-9a-f]+ in )?futex_wait'],\n    'i386:x86-64': ['(0x[0-9a-f]+ in )?__lll_lock_wait',\n                    '(0x[0-9a-f]+ in )?pthread_barrier_wait',\n                    '(0x[0-9a-f]+ in )?futex_wait',\n                    '0x0*70000002 in \\?\\?',\n                    '(0x[0-9a-f]+ in )?syscall_traced',\n                    '(0x[0-9a-f]+ in )?rr_page_start'\n                    ],\n    'aarch64': ['(0x[0-9a-f]+ in )?syscall_traced',\n                '(0x[0-9a-f]+ in )?pthread_barrier_wait',\n                '(0x[0-9a-f]+ in )?futex_wait'],\n}\n\nlocation_regex = '|'.join(stopped_locations[arch])\n\nsend_gdb('info threads')\nexpect_gdb(r'1\\s+Thread.+hit_barrier')\nexpect_gdb(r'\\(rr\\)')\n\nsend_gdb('info threads')\nexpect_gdb(r'2\\s+Thread.+?(?:%s)' % location_regex)\nexpect_gdb(r'\\(rr\\)')\n\nsend_gdb('info threads')\nexpect_gdb(r'3\\s+Thread.+?(?:%s)' % location_regex)\nexpect_gdb(r'\\(rr\\)')\n\nok()\n"
  },
  {
    "path": "src/test/step_thread.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/stray_time_slice_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  int fd = open(\"/dev/zero\", O_RDONLY);\n  int sum = 0;\n  pid_t pid;\n  int status;\n\n  test_assert(fd >= 0);\n\n  pid = fork();\n  if (!pid) {\n    pid_t pp = getppid();\n    for (i = 0; i < 1000; ++i) {\n      kill(pp, SIGCHLD);\n    }\n    return 77;\n  }\n\n  for (i = 0; i < 1000; ++i) {\n    int j;\n    for (j = 0; j < i % 50; ++j) {\n      sum += j * i;\n    }\n  }\n\n  test_assert(pid == wait(&status));\n\n  atomic_printf(\"token = %d\\n\", sum);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/stray_time_slice_signal.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS = \"-c3\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/strict_priorities.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <sched.h>\n#include <sys/types.h>\n#include <unistd.h>\n\n#define NUM_ITERATIONS (1 << 30)\n\nstatic volatile int main_thread_done = 0;\n\nstatic void* low_priority_func(__attribute__((unused)) void* unused) {\n  setpriority(PRIO_PROCESS, 0, 4);\n  /* This thread should never be scheduled again unless/until the main\n     thread exits. */\n  test_assert(main_thread_done);\n  return NULL;\n}\n\nstatic volatile int dummy;\n\nint main(void) {\n  int i, j;\n  pthread_t low_priority_thread;\n\n  pthread_create(&low_priority_thread, NULL, low_priority_func, NULL);\n\n  /* Eat some CPU and do some (nonblocking) system calls */\n  for (i = 0; i < 64; ++i) {\n    getpid();\n    for (j = 0; j < NUM_ITERATIONS / 64; ++j) {\n      dummy += j % (1 << 20);\n      dummy += j % (79 * (1 << 20));\n    }\n  }\n\n  /* Set this before the puts below since the puts could block */\n  main_thread_done = 1;\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/strict_priorities.run",
    "content": "source `dirname $0`/util.sh\nexport RR_DISABLE_ROUND_ROBIN=1\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/subprocess_exit_ends_session.py",
    "content": "import re\n\nfrom util import *\n\nBAD_TOKEN = r'EXIT-SUCCESS'\nGOOD_TOKEN = r'Inferior 1 \\(process \\d+\\) exited normally'\n\ndef observe_child_crash_and_exit():\n    expect_gdb('Program received signal SIGSEGV')\n\n    send_gdb('c')\n    for line in iterlines_both():\n        m = re.search(BAD_TOKEN, line)\n        if m:\n            failed('Saw illegal token \"'+ BAD_TOKEN +'\"')\n        m = re.search(GOOD_TOKEN, line)\n        if m:\n            return\n\nsend_gdb('c')\nobserve_child_crash_and_exit()\n\nrestart_replay()\nobserve_child_crash_and_exit()\n\nok()\n"
  },
  {
    "path": "src/test/subprocess_exit_ends_session.run",
    "content": "source `dirname $0`/util.sh\n\nrecord fork_child_crash$bitness\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\ndebug_gdb_only subprocess_exit_ends_session \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/switch_processes.py",
    "content": "from util import *\nimport re\n\n# Restart at the first debuggable event, which will be in a different\n# process! We should stay focused on the child process, instead of\n# trying to switch to that process. At least we shouldn't crash.\nrestart_replay(1)\nexpect_gdb('(rr)')\nexpect_list([re.compile('Program stopped'), re.compile('exited normally')])\n\nok()\n"
  },
  {
    "path": "src/test/switch_processes.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe write_race$bitness\nsaved_exe=\"write_race$bitness-$nonce\"\nrecord target_process$bitness $saved_exe\n\ndebug_gdb_only switch_processes \"-g 1000\"\n"
  },
  {
    "path": "src/test/switch_read.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char start_token = '!';\nstatic const char sentinel_token = ' ';\n\nstatic pthread_t reader;\nstatic pthread_barrier_t barrier;\n\nstatic int sockfds[2];\n\nstatic void* reader_thread(__attribute__((unused)) void* dontcare) {\n  int readsock = sockfds[1];\n  char c = sentinel_token;\n  struct timeval tv;\n\n  pthread_barrier_wait(&barrier);\n\n  atomic_puts(\"r: blocking on read ...\");\n\n  test_assert(1 == read(readsock, &c, sizeof(c)));\n\n  gettimeofday(&tv, NULL);\n\n  atomic_printf(\"r: ... read '%c'\\n\", c);\n  test_assert(c == start_token);\n\n  return NULL;\n}\n\nint main(void) {\n  char token = start_token;\n  struct timeval ts;\n\n  /* (Kick on the syscallbuf if it's enabled.) */\n  gettimeofday(&ts, NULL);\n\n  socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfds);\n\n  pthread_barrier_init(&barrier, NULL, 2);\n  pthread_create(&reader, NULL, reader_thread, NULL);\n\n  pthread_barrier_wait(&barrier);\n\n  /* Force a blocked read() that's interrupted by a SIGUSR1,\n   * which then itself blocks on read() and succeeds. */\n  atomic_puts(\"M: sleeping ...\");\n  usleep(500000);\n  atomic_printf(\"M: finishing reader by writing '%c' to socket ...\\n\", token);\n  write(sockfds[0], &token, sizeof(token));\n  ++token;\n\n  atomic_puts(\"M:   ... done\");\n\n  pthread_join(reader, NULL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/symlink.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  static const char token_file[] = \"rr-link-file.txt\";\n  static const char link_name[] = \"rr-link-file.link\";\n\n  test_assert(0 == symlink(token_file, link_name));\n  test_assert(0 == unlink(link_name));\n  test_assert(0 == symlinkat(token_file, AT_FDCWD, link_name));\n  test_assert(0 == unlink(link_name));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sync.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define FILENAME \"foo.txt\"\n\nint main(void) {\n  int fd;\n\n  sync();\n\n  fd = open(FILENAME, O_CREAT | O_RDWR, 0600);\n  test_assert(0 == unlink(FILENAME));\n  test_assert(fd >= 0);\n  test_assert(0 == syncfs(fd));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sync_file_range.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"dummy.txt\", O_RDWR | O_CREAT | O_TRUNC, 0600);\n  int ret;\n  test_assert(fd >= 0);\n  ret = write(fd, \"x\", 1);\n  test_assert(ret == 1);\n  ret = sync_file_range(fd, 0, 1, SYNC_FILE_RANGE_WAIT_BEFORE);\n  test_assert(ret == 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscall_bp.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#if defined(__i386__) || defined(__x86_64__)\nchar breakpoint_instruction[] = { 0xcc };\n#elif defined(__aarch64__)\nchar breakpoint_instruction[] = { 0x0, 0x0, 0x20, 0xd4 };\n#else\n#error Unknown architecture\n#endif\n\n#define RR_PAGE_ADDR 0x70000000\n\nint main(void) {\n  uint8_t* syscall_addr = (uint8_t*)RR_PAGE_ADDR;\n  uintptr_t current_brk = (uintptr_t)sbrk(0);\n  // Write a breakpoint instruction to the vdso syscall address.\n  // We don't do this by mprotecting, since we'd have to use RWX,\n  // which may be disallowed by some kernels.\n  int memfd = open(\"/proc/self/mem\", O_RDWR);\n  int nwritten = pwrite(memfd, &breakpoint_instruction,\n                        sizeof(breakpoint_instruction), (uintptr_t)syscall_addr);\n  if (nwritten == -1 && errno == EIO) {\n    atomic_puts(\"Not running under rr\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(nwritten == sizeof(breakpoint_instruction));\n  // Now make a syscall that we know rr will want to use a remote syscall\n  // for. Don't use the glibc wrapper to make absolutely sure we don't hit\n  // our own breakpoint.\n  unbufferable_syscall(SYS_brk, current_brk + 0x100000, 0, 0);\n  unbufferable_syscall(SYS_write, STDOUT_FILENO, (uintptr_t) \"EXIT-SUCCESS\", 14);\n  // Exit directly.\n  unbufferable_syscall(SYS_exit, 0x0, 0, 0);\n  return 1;\n}\n"
  },
  {
    "path": "src/test/syscall_in_writable_mem.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* ptr;\n\nstatic char syscall_bytes[] =\n#ifdef __x86_64__\n    { 0x0f, 0x05, 0xc3 }\n#elif __i386__\n    { 0xcd, 0x80, 0xc3 }\n#elif defined(__aarch64__)\n    { 0x01, 0x00, 0x00, 0xd4,   // svc #0\n      0xc0, 0x03, 0x5f, 0xd6 } // ret\n#endif\n;\n\nstatic void do_write(int fd, const char* p) {\n  size_t ret;\n  size_t len = strlen(p);\n#ifdef __x86_64__\n  __asm__ __volatile__(\"call *%%rcx\\n\\t\"\n                       : \"=a\"(ret)\n                       : \"a\"(SYS_write), \"c\"(ptr), \"D\"(fd), \"S\"(p), \"d\"(len));\n#elif __i386__\n  __asm__ __volatile__(\"call *%%esi\\n\\t\"\n                       : \"=a\"(ret)\n                       : \"a\"(SYS_write), \"S\"(ptr), \"b\"(fd), \"c\"(p), \"d\"(len));\n#elif __aarch64__\n  register long x8 __asm__(\"x8\") = SYS_write;\n  register long x7 __asm__(\"x7\") = (long)ptr;\n  register long x0 __asm__(\"x0\") = (long)fd;\n  register long x1 __asm__(\"x1\") = (long)p;\n  register long x2 __asm__(\"x2\") = (long)len;\n  __asm__ __volatile__(\"blr x7\\n\\t\"\n                       : \"+r\"(x0)\n                       : \"r\"(x1), \"r\"(x2), \"r\"(x7), \"r\"(x8));\n  ret = x0;\n#else\n#error Unknown architecture\n#endif\n  test_assert(ret == len);\n}\n\nint main(void) {\n  int fd = open(\"dummy\", O_RDWR | O_CREAT | O_EXCL, 0700);\n  test_assert(fd >= 0);\n  unlink(\"dummy\");\n  test_assert(write(fd, syscall_bytes, sizeof(syscall_bytes)) ==\n              sizeof(syscall_bytes));\n\n  ptr = mmap(NULL, 2, PROT_READ | PROT_EXEC, MAP_SHARED, fd, 0);\n  test_assert(ptr != MAP_FAILED);\n\n  do_write(STDOUT_FILENO, \"EXIT-SUCCESS\\n\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_fd_disabling.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  atomic_puts(\"Line 1\");\n  atomic_puts(\"Line 2\");\n  atomic_puts(\"Line 3\");\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_fd_disabling.run",
    "content": "source `dirname $0`/util.sh\nGLOBAL_OPTIONS=\"$GLOBAL_OPTIONS -M\"\nrecord $TESTNAME\nif [[ \"record.out\" != $(grep -l '^\\[.*\\]Line 2$' record.out) ]]; then\n  failed \"Missing line annotation\"\n  exit\nfi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/syscallbuf_signal_blocking.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\nstatic int got_sigs;\n\nstatic void handle_sig(__attribute__((unused)) int sig,\n                       __attribute__((unused)) siginfo_t* info,\n                       __attribute__((unused)) void* mcontext) {\n  write(pipe_fds[1], \"x\", 1);\n  ++got_sigs;\n}\n\nint main(void) {\n  struct sigaction sa;\n  struct sigevent sevp;\n  char ch;\n  timer_t id;\n  struct itimerspec timeout = { { 0, 0 }, { 0, 1000000 } };\n  struct syscall_info read_syscall = { SYS_read, { 0, 0, 0, 0, 0, 0 } };\n  SyscallWrapper delayed_syscall = get_delayed_syscall();\n\n  test_assert(0 == pipe(pipe_fds));\n\n  sa.sa_flags = SA_SIGINFO | SA_RESTART;\n  sa.sa_sigaction = handle_sig;\n  sigemptyset(&sa.sa_mask);\n  sigaction(SIGUSR1, &sa, NULL);\n\n  sa.sa_flags = SA_RESTART;\n  sa.sa_handler = SIG_IGN;\n  sigaction(SIGTRAP, &sa, NULL);\n\n  sevp.sigev_notify = SIGEV_SIGNAL;\n  sevp.sigev_signo = SIGUSR1;\n  test_assert(0 == timer_create(CLOCK_MONOTONIC, &sevp, &id));\n  test_assert(0 == timer_settime(id, 0, &timeout, NULL));\n\n  /* This will hang unless SIGUSR1 is processed before we read from the pipe */\n  read_syscall.args[0] = pipe_fds[0];\n  read_syscall.args[1] = (long)&ch;\n  read_syscall.args[2] = 1;\n  delayed_syscall(&read_syscall);\n\n  test_assert(got_sigs == 1);\n\n  /* Should be ignored */\n  raise(SIGTRAP);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_signal_blocking_read.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = open(\"dummy.txt\", O_RDWR | O_CREAT | O_EXCL, 0700);\n  char* buf = malloc(100 * 1024 * 1024);\n  int i;\n  unlink(\"dummy.txt\");\n\n  for (i = 0; i < 1000; ++i) {\n    /* Do a large read that can't be buffered so will cause a traced\n       read, though we will try to do an ioctl FIOCLONERANGE on it first\n       (which we're testing for interference with many TIME_SLICE_SIGNALs) */\n    ssize_t ret = read(fd, buf, 100 * 1024 * 1024);\n    test_assert(ret == 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_signal_blocking_read.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c100\"\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/syscallbuf_signal_reset.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void sighandler(__attribute__((unused)) int sig) {\n  /* Must be a syscall we've already executed, otherwise patching gets in the\n   * way */\n  open(\"/dev/zero\", O_RDONLY);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  exit(0);\n}\n\nint main(void) {\n  char ch;\n  int fd = open(\"/dev/zero\", O_RDONLY);\n\n  signal(SIGSEGV, sighandler);\n\n  read(fd, &ch, 1);\n\n  crash_null_deref();\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_sigstop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int do_child(void) {\n  int fd = open(\"/dev/zero\", O_RDONLY);\n  int i;\n  char ch;\n\n  test_assert(fd >= 0);\n  for (i = 0; i < 10000; ++i) {\n    test_assert(1 == read(fd, &ch, 1));\n    sched_yield();\n  }\n  return 77;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  int i;\n\n  child = fork();\n  if (!child) {\n    return do_child();\n  }\n\n  for (i = 0; i < 100; ++i) {\n    kill(child, SIGSTOP);\n    sched_yield();\n    kill(child, SIGCONT);\n    sched_yield();\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_timeslice.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {}\n\nint main(void) {\n  int fd;\n  char buf[10];\n  int i;\n\n  signal(SIGTRAP, handler);\n\n  fd = open(\"/dev/zero\", O_RDONLY);\n  for (i = 0; i < 1 << 12; ++i) {\n    read(fd, buf, sizeof(buf));\n    if (!(i & ((1 << 8) - 1))) {\n      atomic_printf(\".\");\n    }\n  }\n\n  atomic_puts(\"\\nEXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_timeslice2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd;\n  char buf[10];\n  int i;\n\n  for (i = 0; i < 1 << 12; ++i) {\n    fd = open(\"/dev/zero\", O_RDONLY);\n    read(fd, buf, sizeof(buf));\n    close(fd);\n    if (!(i & ((1 << 8) - 1))) {\n      atomic_printf(\".\");\n    }\n  }\n\n  atomic_puts(\"\\nEXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syscallbuf_timeslice2_250.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c250\"\n\nrecord syscallbuf_timeslice2$bitness\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/syscallbuf_timeslice_250.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c250\"\n\nrecord syscallbuf_timeslice$bitness\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/sysconf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  long pagesize = sysconf(_SC_PAGESIZE);\n  long ncpus = sysconf(_SC_NPROCESSORS_ONLN);\n\n  atomic_printf(\"sysconf says page size is %ld bytes\\n\", pagesize);\n#ifdef __aarch64__\n  test_assert((64 * 1024) % pagesize == 0);\n#else\n  test_assert(4096 == pagesize);\n#endif\n\n  atomic_printf(\"sysconf says %ld processors are online\\n\", ncpus);\n  /* TODO: change this when rr supports parallel recording. */\n  test_assert(1 == ncpus);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sysconf_conf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  long ncpus = sysconf(_SC_NPROCESSORS_CONF);\n  unsigned cpu;\n  int ret = sys_getcpu(&cpu, NULL);\n  test_assert(ret == 0);\n  atomic_printf(\"sysconf says %ld processors are configured, getcpu()=%d\\n\", ncpus, cpu);\n\n  if (cpu >= (unsigned)ncpus) {\n    if (ncpus == 1 && access(\"/sys/devices/system/cpu\", X_OK) < 0) {\n      atomic_puts(\"Can't access /sys/devices/system/cpu; _SC_NPROCESSORS_CONF is probably broken, skipping test\");\n      atomic_puts(\"EXIT-SUCCESS\");\n      return 0;\n    }\n    system(\"ls /sys/devices/system/cpu\");\n    atomic_puts(\"present:\");\n    system(\"cat /sys/devices/system/cpu/present\");\n    atomic_puts(\"possible:\");\n    system(\"cat /sys/devices/system/cpu/possible\");\n    abort();\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sysconf_onln.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  long ncpus = sysconf(_SC_NPROCESSORS_ONLN);\n\n  char arg[] = \"--expected-cpus=\";\n  if (argc <= 1 || 0 != strncmp(argv[1], arg, sizeof(arg)-1)) {\n    atomic_puts(\"Usage: sys_cpu_online --expected-cpus=[n] [--inner]\");\n    return 1;\n  }\n\n  // We test this both with and without the preload library\n  // We also always allow 1 in case that's all the machine has\n  test_assert(ncpus == atoi(argv[1]+sizeof(arg)-1) || ncpus == 1);\n\n  if (argc > 2) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  // Test reading /sys/devices/system/cpu/online directly, making sure that\n  // rr properly emulates the fd position\n  int fd = open(\"/sys/devices/system/cpu/online\", O_RDONLY);\n  if (fd < 0 && errno == ENOENT) {\n    atomic_puts(\"Warning: sysfs not mapped. Skipping test.\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n  test_assert(fd >= 0);\n\n  char result[1024];\n  size_t nread = read(fd, &result, sizeof(result));\n  test_assert(nread > 0);\n  nread = read(fd, &result, sizeof(result));\n  test_assert(nread == 0);\n  close(fd);\n\n  char* execv_argv[] = {\"/proc/self/exe\", argv[1], \"--inner\", NULL};\n  // NULL here drops LD_PRELOAD\n  execve(\"/proc/self/exe\", execv_argv, NULL);\n  test_assert(0 && \"Should not have returned\");\n}\n"
  },
  {
    "path": "src/test/sysconf_onln.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME \"--expected-cpus=1\"\nreplay\ncheck EXIT-SUCCESS\nRECORD_ARGS=\"--num-cores=2\"\nrecord $TESTNAME \"--expected-cpus=2\"\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/sysctl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef CTL_KERN\n#define CTL_KERN 1\n#endif\n#ifndef KERN_RTSIGMAX\n#define KERN_RTSIGMAX 33\n#endif\n\nstruct sysctl_args {\n  int *name;\n  int nlen;\n  void *oldval;\n  size_t *oldlenp;\n  void *newval;\n  size_t newlen;\n};\n\nint main(void) {\n  int name[2] = { CTL_KERN, KERN_RTSIGMAX };\n  int sig_max = -1;\n  size_t len = sizeof(sig_max);\n\n  name[0] = CTL_KERN;\n  name[1] = KERN_RTSIGMAX;\n  struct sysctl_args args = { name, 2, &sig_max, &len, NULL, 0 };\n  if (syscall(RR__sysctl, &args) < 0) {\n    /* many kernels don't support this */\n    atomic_printf(\"sysctl KERN_RTSIGMAX returned errno %d\\n\", errno);\n    atomic_puts(\"EXIT-SUCCESS\");\n  } else {\n    test_assert(len == sizeof(sig_max));\n    atomic_printf(\"sysctl KERN_RTSIGMAX returned %d\\n\", sig_max);\n    test_assert(sig_max > 0);\n    atomic_puts(\"EXIT-SUCCESS\");\n  }\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sysemu_singlestep.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/**\n * This test makes sure that replay does not fail if the instruction after a\n * system call is non-idempotent. For each architecture, the assembly sequence\n * should issue a system call, followed immediately by an increment operation\n * or other non-idempotent operation on a memory address.\n */\n\nint main(void) {\n  int var = 41;\n\n#ifdef __i386__\n  __asm__ __volatile__(\"int $0x80\\n\\t\"\n                       \"incl %0\\n\\t\"\n                       : \"+m\"(var)\n                       : \"a\"(SYS_gettid));\n#elif defined(__x86_64__)\n  __asm__ __volatile__(\"syscall\\n\\t\"\n                       \"incl %0\\n\\t\"\n                       : \"+m\"(var)\n                       : \"a\"(SYS_gettid));\n#elif defined(__aarch64__)\n  // We use an atomic instruction here, because we need to do a read-modify\n  // write cycle all in one instruction. Everything else would be idempotent\n  register long x8 __asm__(\"x8\") = SYS_gettid;\n  register long x1 __asm__(\"x1\") = 1;\n  register long x0 __asm__(\"x0\") = 0;\n  __asm__ __volatile__(\"svc #0\\n\\t\"\n                       \"stadd w1, %0\\n\\t\"\n                       : \"+Q\"(var), \"+r\"(x0)\n                       : \"r\"(x8), \"r\"(x1));\n#else\n#error Define your architecture here\n#endif\n\n  test_assert(var == 42);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/sysinfo.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct sysinfo* info;\n\n  ALLOCATE_GUARD(info, 0);\n  test_assert(0 == sysinfo(info));\n  test_assert(info->mem_unit > 0);\n  test_assert(info->procs > 0);\n  VERIFY_GUARD(info);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/syslog.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <sys/klog.h>\n\n#define BUF1_SIZE 500\n\nint main(void) {\n  int log_buf_size = klogctl(10 /* SYSLOG_ACTION_SIZE_BUFFER */, NULL, 42);\n  if (log_buf_size == -1 && errno == EPERM) {\n    atomic_puts(\"Skipping test because it requires CAP_SYSLOG\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(log_buf_size >= 0);\n\n  char* buf1 = allocate_guard(BUF1_SIZE, '1');\n  int buf2_size = log_buf_size + 10;\n  char* buf2 = allocate_guard(buf2_size, '2');\n\n  int size1 = klogctl(3 /* SYSLOG_ACTION_READ_ALL */, buf1, BUF1_SIZE);\n  test_assert(size1 >= 0);\n  verify_guard(BUF1_SIZE, buf1);\n\n  int size2 = klogctl(3 /* SYSLOG_ACTION_READ_ALL */, buf2, buf2_size);\n  test_assert(size2 >= 0);\n  verify_guard(buf2_size, buf2);\n\n  test_assert(size2 >= size1);\n  test_assert(0 == memcmp(buf1, buf2 + (size2 - size1), size1));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/target_fork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void bad_breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void good_breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(int argc, char* argv[]) {\n  int num_syscalls;\n  int child;\n  int i;\n\n  bad_breakpoint();\n\n  test_assert(argc == 2);\n  num_syscalls = atoi(argv[1]);\n\n  atomic_printf(\"%d: running %d syscalls ...\\n\", getpid(), num_syscalls);\n  for (i = 0; i < num_syscalls; ++i) {\n    event_syscall();\n  }\n\n  if (0 == (child = fork())) {\n    good_breakpoint();\n    exit(0);\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n\n  waitpid(child, NULL, 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/target_fork.run",
    "content": "source `dirname $0`/util.sh\n\nEVENTS=1000\nrecord $TESTNAME $EVENTS\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only bad_good_break \"-f $TARGET_PID -g $EVENTS\"\n"
  },
  {
    "path": "src/test/target_process.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(int argc, char* argv[]) {\n  const char* exe_image;\n  int child;\n\n  test_assert(argc == 2);\n  exe_image = argv[1];\n\n  atomic_printf(\"%d: forking and exec'ing %s...\\n\", getpid(), exe_image);\n  if (0 == (child = fork())) {\n    execl(exe_image, exe_image, NULL);\n    test_assert(\"Not reached; execl() failed.\" && 0);\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n\n  waitpid(child, NULL, 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/target_process.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe breakpoint$bitness\nsaved_breakpoint=\"breakpoint$bitness-$nonce\"\n\nrecord $TESTNAME \"$saved_breakpoint\"\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only restart_breakpoint \"-p $TARGET_PID -g 1\"\n"
  },
  {
    "path": "src/test/tcp_sockets.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  // ipv4\n  int socket_fd[3];\n  socket_fd[0] = socket(AF_INET, SOCK_STREAM, 0);\n  test_assert(socket_fd[0] >= 0);\n  int reuseaddr = 1;\n  test_assert(0 == setsockopt(socket_fd[0], SOL_SOCKET, SO_REUSEADDR, &reuseaddr,\n\t\t\t      sizeof(reuseaddr)));\n  socket_fd[1] = socket(AF_INET, SOCK_STREAM, 0);\n  test_assert(socket_fd[1] >= 0);\n\n  struct sockaddr_storage sa;\n  socklen_t sa_size = sizeof(sa);\n  struct sockaddr_in* sa_in = (struct sockaddr_in*)&sa;\n  sa_in->sin_family = AF_INET;\n  sa_in->sin_addr.s_addr = htonl (INADDR_LOOPBACK);\n  sa_in->sin_port = 0;\n\n  test_assert(0 == bind(socket_fd[0], (struct sockaddr*)&sa, sa_size));\n  test_assert(0 == getsockname(socket_fd[0], (struct sockaddr*)&sa, &sa_size));\n  test_assert(0 == listen(socket_fd[0], 1));\n  test_assert(0 == connect(socket_fd[1], (struct sockaddr*)&sa, sa_size));\n\n  socket_fd[2] = accept(socket_fd[0], (struct sockaddr*)&sa, &sa_size);\n  test_assert(socket_fd[2] >= 0);\n\n  close(socket_fd[0]);\n  close(socket_fd[1]);\n  close(socket_fd[2]);\n\n  // ipv6\n  socket_fd[0] = socket(AF_INET6, SOCK_STREAM, 0);\n  test_assert(socket_fd[0] >= 0);\n  test_assert(0 == setsockopt(socket_fd[0], SOL_SOCKET, SO_REUSEADDR, &reuseaddr,\n\t\t\t      sizeof(reuseaddr)));\n  socket_fd[1] = socket(AF_INET6, SOCK_STREAM, 0);\n  test_assert(socket_fd[1] >= 0);\n\n  sa_size = sizeof(sa);\n  struct sockaddr_in6* sa_in6 = (struct sockaddr_in6*)&sa;\n  sa_in6->sin6_family = AF_INET6;\n  sa_in6->sin6_addr = in6addr_loopback;\n  sa_in6->sin6_port = 0;\n\n  test_assert(0 == bind(socket_fd[0], (struct sockaddr*)&sa, sa_size));\n  test_assert(0 == getsockname(socket_fd[0], (struct sockaddr*)&sa, &sa_size));\n  test_assert(0 == listen(socket_fd[0], 1));\n  assert(0 == connect(socket_fd[1], (struct sockaddr*)&sa, sa_size));\n\n  socket_fd[2] = accept(socket_fd[0], (struct sockaddr*)&sa, &sa_size);\n  test_assert(socket_fd[2] >= 0);\n\n  close(socket_fd[0]);\n  close(socket_fd[1]);\n  close(socket_fd[2]);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/tcp_sockets.run",
    "content": "source `dirname $0`/util.sh\n\nexe=tcp_sockets$bitness\ncp ${OBJDIR}/bin/$exe $exe-$nonce\njust_record $exe-$nonce\n# The test binary might fail due to IPv6 being unsupported\nEXIT_CODE=$?\nif [[ `rr dump --socket-addresses latest-trace|grep --count -F 127.0.0.1` != 2 ]]; then\n    failed \"Wrong number of '127.0.0.1's\"\nfi\nif [[ $EXIT_CODE == 0 ]]; then\n  if [[ `rr dump --socket-addresses latest-trace|grep --count -F ::1:` != 2 ]]; then\n      failed \"Wrong number of '::1:'s\"\n  fi\nfi\n"
  },
  {
    "path": "src/test/term_nonmain.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void waittermsig(int sig, const char* waiter) {\n  struct timespec ts = {.tv_sec = 1 };\n  sigset_t set;\n  siginfo_t si;\n\n  sigemptyset(&set);\n  sigaddset(&set, sig);\n  sigtimedwait(&set, &si, &ts);\n\n  atomic_printf(\"FAILED: %s: signal %d either not caught or didn't terminate \"\n                \"process within 1 second\\n\",\n                waiter, sig);\n}\n\nstatic void* kill_thread(__attribute__((unused)) void* dontcare) {\n  const int termsig = SIGTERM;\n\n  atomic_puts(\"killing...\");\n  kill(getpid(), termsig);\n  waittermsig(termsig, \"kill_thread\");\n  return NULL; /* not reached */\n}\n\nint main(void) {\n  pthread_t t;\n\n  pthread_create(&t, NULL, kill_thread, NULL);\n  pthread_join(t, NULL);\n  atomic_puts(\"FAILED: joined thread that should have died\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/term_nonmain.run",
    "content": "source `dirname $0`/util.sh\ncompare_test 'killing ...'\n"
  },
  {
    "path": "src/test/term_rr.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  signal(SIGTERM, SIG_IGN);\n  kill(getppid(), SIGTERM);\n  atomic_puts(\"EXIT-SUCCESS\");\n  sleep(10000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/term_rr.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\nsend_gdb('handle SIGTERM stop')\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('received signal SIGTERM')\nsend_gdb('c')\nexpect_gdb('received signal SIGKILL')\n\nok()\n"
  },
  {
    "path": "src/test/term_rr.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/term_rr_ok.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n  exit(0);\n}\n\nint main(void) {\n  signal(SIGTERM, handler);\n  atomic_puts(\"EXIT-SUCCESS\");\n  kill(getppid(), SIGTERM);\n  sleep(10000);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/term_rr_ok.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME || failed \"$TESTNAME failed\"\nreplay\ncheck EXIT-SUCCESS"
  },
  {
    "path": "src/test/term_trace_cpu.run",
    "content": "source `dirname $0`/util.sh\n\n# We want to test two things here:\n# 1) Terminating rr when the next tracee event is a reschedule\n# 2) Terminating rr when the syscallbuf contains events that need to be flushed\n# To test both of these, we need to set the reschedule threshold high enough\n# that our signal is delivered before the first reschedule after sending\n# the SYNC_TOKEN. We also need to set the reschedule threshold low enough\n# that a reschedule occurs before chew_cpu's spin() loop finishes. Currently\n# that loop has 2^30 iterations, so 100M events per reschedule sounds good.\nRECORD_ARGS=\"-c100000000\"\n\nEXE=chew_cpu$bitness\nSYNC_TOKEN=spinning\nWAIT_SECS=1\n\nrecord $EXE &\nSUB_ID=$!\n\necho \"Waiting for token '$SYNC_TOKEN' from tracee ...\"\nuntil grep -q $SYNC_TOKEN record.out; do\n        sleep 0\n        if ! kill -0 \"$SUB_ID\" >/dev/null 2>&1; then failed \"subshell died, no need to longer wait for '$SYNC_TOKEN'\"; exit; fi\ndone\n\nrrpid=$(parent_pid_of $(pidof $EXE-$nonce))\n\n# It's possible for this signal to be acted on before chew_cpu actually\n# reaches the spin() loop, e.g. with syscallbuf disabled it might be delivered\n# before rr has finished handling the syscalls of atomic_puts. But scheduling\n# variations should ensure that sometimes we reach spin() first.\necho \"  done.  Delivering SIGTERM to $rrpid ...\"\nkill -TERM $rrpid\n\necho \"  done.\"\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written, and we might\n# fail to see the tracee write EXIT-SUCCESS.\nwait\n\nif [[ \"record.out\" == $(grep -l \"EXIT-SUCCESS\" record.out) ]]; then\n        echo \"warning: tracer not interrupted in time.\"\nfi\n\necho \"Replaying ...\"\nreplay\ncheck \"\"\n"
  },
  {
    "path": "src/test/term_trace_reset.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvolatile int dummy;\n\nint main(void) {\n  int i = 0;\n\n  atomic_puts(\"ready\");\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  struct timespec ts;\n  clock_gettime(CLOCK_MONOTONIC, &ts);\n\n  while (1) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/term_trace_reset.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME &\n\nuntil grep -q ready record.out; do\n  sleep 0\ndone\n\nsleep 0.01\nrrpid=$(parent_pid_of $(pidof $TESTNAME-$nonce))\nkill -TERM $rrpid >& /dev/null\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/term_trace_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_SIGTERM(__attribute__((unused)) int sig) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nint main(void) {\n  struct timespec ts = { 1000000, 0 };\n\n  signal(SIGTERM, handle_SIGTERM);\n  atomic_puts(\"sleeping\");\n\n  nanosleep(&ts, NULL);\n  atomic_puts(\"FAILED\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/term_trace_syscall.run",
    "content": "source `dirname $0`/util.sh\n\nSYNC_TOKEN=sleeping\n\nrecord $TESTNAME &             # sleep \"forever\"\nSUB_ID=$!\n\necho \"Waiting for token '$SYNC_TOKEN' from tracee ...\"\nuntil grep -q $SYNC_TOKEN record.out; do\n    sleep 0\n    if ! kill -0 \"$SUB_ID\" >/dev/null 2>&1; then failed \"subshell died, no need to longer wait for '$SYNC_TOKEN'\"; exit; fi\ndone\n\nrrpid=$(parent_pid_of $(pidof $TESTNAME-$nonce))\n\necho \"  done.  Delivering SIGTERM to $rrpid ...\"\nkill -TERM $rrpid\n\necho \"  done.\"\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written, and we might\n# fail to see the tracee write EXIT-SUCCESS.\nwait\n\nif [[ \"record.out\" == $(grep -l \"FAILED\" record.out) ]]; then\n    echo \"Test '$TESTNAME' FAILED: error during recording: tracer not interrupted in time.\"\nfi\n\necho \"Replaying ...\"\nreplay\ncheck \"\"\n"
  },
  {
    "path": "src/test/test_lib.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n  struct timespec ts = { 1, 0 };\n  clock_nanosleep(CLOCK_MONOTONIC, 0, &ts, NULL);\n}\n\nstatic void* start_thread(__attribute__((unused)) void* dontcare) {\n  struct timespec ts = { 1, 0 };\n  signal(SIGCHLD, handler);\n  nanosleep(&ts, NULL);\n  return NULL;\n}\n\nstatic void constructor(void) __attribute__((constructor));\n\nstatic void constructor(void) {\n  struct timeval tv;\n  pthread_t t;\n  gettimeofday(&tv, NULL);\n\n  pthread_create(&t, NULL, start_thread, NULL);\n  /* Try to make the thread enter its sleep syscalls */\n  struct timespec ts = { 0, 1000000 };\n  nanosleep(&ts, NULL);\n  /* Trigger signal handler */\n  pthread_kill(t, SIGCHLD);\n  /* Ensure that signal handler is entered before we proceed to init preload */\n  nanosleep(&ts, NULL);\n}\n\nvoid lib_exit_success(void) { atomic_puts(\"EXIT-SUCCESS\"); }\n"
  },
  {
    "path": "src/test/test_setup.gdb",
    "content": "set pagination off\nhandle SIGSEGV stop\nhandle SIGKILL nostop\n# This fails in gdb < 8.3\nset style enabled off\n# gdb >= 10\nset debuginfod enabled off\n"
  },
  {
    "path": "src/test/test_setup.lldb",
    "content": "process handle -p true -s true SIGSEGV\nprocess handle -p false -s false SIGKILL\n\n"
  },
  {
    "path": "src/test/tgkill.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int num_signals_caught;\n\nstatic void sighandler(int sig) {\n  atomic_printf(\"Task %d got signal %d\\n\", sys_gettid(), sig);\n  ++num_signals_caught;\n}\n\nint main(void) {\n  signal(SIGUSR1, sighandler);\n  signal(SIGUSR2, sighandler);\n  tgkill(getpid(), sys_gettid(), SIGUSR1);\n  tgkill(getpid(), sys_gettid(), SIGUSR2);\n\n  test_assert(2 == num_signals_caught);\n\n  syscall(SYS_tkill, sys_gettid(), SIGUSR1);\n  syscall(SYS_tkill, sys_gettid(), SIGUSR2);\n\n  test_assert(4 == num_signals_caught);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/thread_exit_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int count;\nstatic volatile int stop;\n\nstatic void handler(__attribute__((unused)) int sig) { ++count; }\n\nstatic void handler2(__attribute__((unused)) int sig) { stop = 1; }\n\nstatic void* do_thread(__attribute__((unused)) void* p) { return NULL; }\n\nint main(void) {\n  test_assert(0 == signal(SIGCHLD, handler));\n  test_assert(0 == signal(SIGUSR2, handler2));\n\n  atomic_puts(\"ready\");\n\n  while (!stop) {\n    pthread_t thread;\n    pthread_create(&thread, NULL, do_thread, NULL);\n    pthread_join(thread, NULL);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/thread_exit_signal.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME &\n\nuntil grep -q ready record.out; do\n  sleep 0\ndone\n\npid=$(pidof $TESTNAME-$nonce)\nfor i in $(seq 1 100); do\n  sleep 0.001\n  kill -CHLD $pid >& /dev/null\ndone\nkill -USR2 $pid >& /dev/null\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait %1 || failed \"Abnormal record termination\"\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/thread_open_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int stop = 0;\n\nstatic const char file_name[] = \"blahblah.xyz\";\n\nstatic void* opener(__attribute__((unused)) void* p) {\n  while (!stop) {\n    int fd = open(file_name, O_RDONLY);\n    test_assert(fd >= 0);\n    close(fd);\n  }\n  return NULL;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  return NULL;\n}\n\nint main(void) {\n  pthread_t opener_thread;\n  int i;\n  int fd = open(file_name, O_RDWR | O_CREAT, 0700);\n  test_assert(fd >= 0);\n\n  pthread_create(&opener_thread, NULL, opener, NULL);\n\n  for (i = 0; i < 1000; ++i) {\n    pthread_t dummy_thread;\n    pthread_create(&dummy_thread, NULL, do_thread, NULL);\n    pthread_join(dummy_thread, NULL);\n  }\n\n  stop = 1;\n  pthread_join(opener_thread, NULL);\n\n  unlink(file_name);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/thread_open_race.run",
    "content": "source `dirname $0`/util.sh\n\n# This test requires syscallbuf syscall patching\nskip_if_no_syscall_buf\n\nif [ $TIMEOUT -lt 300 ]; then TIMEOUT=300; fi\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/thread_stress.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Chosen so that |3MB * THREAD_GROUPS * THREADS_PER_GROUP| exhausts a\n * 32-bit address space. */\n#define THREAD_GROUPS 150\n#define THREADS_PER_GROUP 10\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  struct timeval tv;\n  gettimeofday(&tv, NULL);\n  return NULL;\n}\n\nint main(void) {\n  int i;\n\n  for (i = 0; i < THREAD_GROUPS; ++i) {\n    pthread_t threads[THREADS_PER_GROUP];\n    int j;\n    for (j = 0; j < THREADS_PER_GROUP; ++j) {\n      test_assert(0 == pthread_create(&threads[j], NULL, thread, NULL));\n    }\n    for (j = 0; j < THREADS_PER_GROUP; ++j) {\n      test_assert(0 == pthread_join(threads[j], NULL));\n    }\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/thread_stress.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/thread_yield.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint spin(int iterations) {\n  int i, dummy = 0;\n\n  atomic_puts(\"spinning\");\n  for (i = 1; i < iterations; ++i) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n  }\n  return dummy;\n}\n\nstatic int ran_thread = 0;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  ran_thread = 1;\n  return NULL;\n}\n\nint main(void) {\n  pthread_t t;\n\n  pthread_create(&t, NULL, do_thread, NULL);\n\n  spin(1 << 28);\n\n  test_assert(ran_thread);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/threaded_syscall_spam.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int num_its;\n\nstatic void syscall_spam(void) {\n  int i;\n  struct timespec ts;\n  struct timeval tv;\n  for (i = 0; i < 1 << num_its; ++i) {\n    /* The odds of the signal being caught in the library\n     * implementing these syscalls is very high.  But even\n     * if it's not caught there, this test will pass. */\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n    gettimeofday(&tv, NULL);\n  }\n}\n\nstatic void unblock_signals(void) {\n  sigset_t set;\n  sigfillset(&set);\n  test_assert(0 == pthread_sigmask(SIG_UNBLOCK, &set, NULL));\n  atomic_printf(\"  %d: unblocked all sigs\\n\", sys_gettid());\n}\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  unblock_signals();\n  syscall_spam();\n  return NULL;\n}\n\nint main(int argc, char** argv) {\n  sigset_t set;\n  pthread_t t;\n\n  test_assert(argc == 2);\n  num_its = atoi(argv[1]);\n  test_assert(num_its > 0);\n\n  atomic_printf(\"Running 2^%d iterations in two threads\\n\", num_its);\n\n  atomic_printf(\"parent %d: blocking all sigs ...\\n\", getpid());\n  sigfillset(&set);\n  test_assert(0 == pthread_sigmask(SIG_BLOCK, &set, NULL));\n\n  pthread_create(&t, NULL, thread, NULL);\n\n  unblock_signals();\n  syscall_spam();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/threaded_syscall_spam.run",
    "content": "source `dirname $0`/util.sh\n\n# Without the syscallbuf, trying to record the large number of\n# syscalls in this test is impractical.\nskip_if_no_syscall_buf\n\n# 2^17 iterations is arbitrarily chosen to take ~3s on a fast machine\nrecord $TESTNAME 17\n\n# Because of issue #184, replay takes longer than practical.  So for\n# now we'll skip it and hope other tests exercise the relevant code\n# well enough.\n#replay\n#check 'EXIT-SUCCESS'\npassed\n"
  },
  {
    "path": "src/test/threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nlong int counter = 0;\npthread_barrier_t bar;\n\nvoid catcher(__attribute__((unused)) int sig) {\n  atomic_printf(\"Signal caught, Counter is %ld\\n\", counter);\n  atomic_puts(\"EXIT-SUCCESS\");\n  _exit(0);\n}\n\nvoid* receiver(__attribute__((unused)) void* name) {\n  struct sigaction sact;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = 0;\n  sact.sa_handler = catcher;\n  sigaction(SIGALRM, &sact, NULL);\n  pthread_barrier_wait(&bar);\n\n  while (1) {\n    counter++;\n    if (counter % 100000 == 0) {\n      write(1, \".\", 1);\n    }\n  }\n  return NULL;\n}\n\nvoid* sender(void* id) {\n  sleep(1);\n  pthread_barrier_wait(&bar);\n  pthread_kill(*((pthread_t*)id), SIGALRM);\n  return NULL;\n}\n\nint main(void) {\n  struct timeval tv;\n  pthread_t thread1, thread2;\n\n  /* (Kick on the syscallbuf lib.) */\n  gettimeofday(&tv, NULL);\n\n  /* init barrier */\n  pthread_barrier_init(&bar, NULL, 2);\n  /* Create independent threads each of which will execute\n   * function */\n  pthread_create(&thread1, NULL, receiver, NULL);\n  pthread_create(&thread2, NULL, sender, &thread1);\n\n  /* Wait till threads are complete before main\n   * continues. Unless we wait we run the risk of executing an\n   * exit which will terminate the process and all threads\n   * before the threads have completed. */\n  pthread_join(thread1, NULL);\n  pthread_join(thread2, NULL);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/threads.run",
    "content": "source `dirname $0`/util.sh\n\n# When the syscallbuf is enabled, this test looks to rr like a long\n# series of CPU chewing, with buffer flushes at each time-slice\n# interrupt.  This makes replay take a pathologically long time\n# because of all the async-signal replaying.  So speed things up by\n# bumping up the timeslice.\nRECORD_ARGS=\"-c20000000\"\n\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/tick0.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n// This is not linked to anything, not even the dynamic linker.\n\nvolatile int nloop = 100000;\nconst char exit_msg[] = \"EXIT-SUCCESS\\n\";\n\n#ifdef __x86_64__\n#define SYS_write 1\n#define SYS_exit 60\n#define SYS_getpid 39\n#elif defined(__i386__)\n#define SYS_write 4\n#define SYS_exit 1\n#define SYS_getpid 20\n#elif defined(__aarch64__)\n#define SYS_write 64\n#define SYS_exit 93\n#define SYS_getpid 172\n#else\n#error define syscall numbers here\n#endif\n\n\nstatic inline __attribute__((always_inline))\nunsigned long my_syscall(unsigned long syscall, unsigned long arg1,\n                         unsigned long arg2, unsigned long arg3) {\n  unsigned long ret;\n#ifdef __x86_64__\n  __asm__ volatile(\"syscall\\n\\t\"\n                   : \"=a\"(ret)\n                   : \"a\"(syscall), \"D\"(arg1), \"S\"(arg2), \"d\"(arg3)\n                   : \"flags\");\n#elif defined(__i386__)\n  __asm__ volatile(\"xchg %%esi,%%edi\\n\\t\"\n                   \"int $0x80\\n\\t\"\n                   \"xchg %%esi,%%edi\\n\\t\"\n                   : \"=a\"(ret)\n                   : \"a\"(syscall), \"b\"(arg1), \"c\"(arg2), \"d\"(arg3));\n#elif defined(__aarch64__)\n  register unsigned long x8 __asm__(\"x8\") = syscall;\n  register unsigned long x0 __asm__(\"x0\") = arg1;\n  register unsigned long x1 __asm__(\"x1\") = arg2;\n  register unsigned long x2 __asm__(\"x2\") = arg3;\n  __asm__ volatile(\"svc #0\\n\\t\"\n                   : \"+r\"(x0)\n                   : \"r\"(x1), \"r\"(x2), \"r\"(x8));\n  ret = x0;\n#else\n#error define syscall here\n#endif\n  return ret;\n}\n\nvoid _start(void) {\n#ifdef HAS_TICK0\n  my_syscall(SYS_getpid, 0, 0, 0);\n#endif\n  // Do some branches to make sure the very first event on this program\n  // happens at ticks != 0\n  for (int i = 0; i < nloop; i++) {\n    asm volatile (\"\" : \"+r\"(i) :: \"memory\");\n  }\n\n  unsigned long nchar = sizeof(exit_msg) - 1; // remove terminal NUL byte\n\n  my_syscall(SYS_write, 1, (unsigned long)exit_msg, nchar);\n  my_syscall(SYS_exit, 0, 0, 0);\n  __builtin_unreachable();\n}\n"
  },
  {
    "path": "src/test/tick0.py",
    "content": "from util import *\nimport re\n\nsend_gdb('handle SIGKILL stop')\n\ndef get_when():\n    send_gdb('when')\n    expect_gdb(re.compile(r'Completed event: (\\d+)'))\n    event = int(last_match().group(1))\n\n    send_gdb('when-ticks')\n    expect_gdb(re.compile(r'Current tick: (\\d+)'))\n    ticks = int(last_match().group(1))\n    return (event, ticks)\n\n(event_start, ticks_start) = get_when()\nif ticks_start != 0:\n    failed('ERROR: Wrong initial ticks')\n\nsend_gdb('c')\n\n(event_end, ticks_end) = get_when()\nif ticks_end < 99999:\n    failed('End ticks too low')\n\nsend_gdb(f'seek-ticks {ticks_start}')\nexpect_gdb('Program stopped.')\n(event_exp, ticks_from_end) = get_when()\nif ticks_from_end != ticks_start:\n    failed('ERROR: Failed to seek back to tick 0 from end')\n\n# test at some starting events\nfor event in range(event_start-1, min(event_start+5, event_end-1)):\n    send_gdb('run %d' % event)\n    expect_gdb('from the beginning')\n    send_gdb('y')\n    expect_gdb(re.compile(r'(Thread \\d+|Program) stopped'))\n    \n    \n    send_gdb(f'seek-ticks {ticks_start}')\n    expect_gdb('Program stopped.')\n    \n    (event, ticks) = get_when()\n    if ticks != 0:\n        failed('ERROR: Failed to seek back to tick 0 from run')\n    if event != event_exp:\n        failed('ERROR: Inconsistent result events from seek-ticks 0')\n\nok()\n"
  },
  {
    "path": "src/test/tick0.run",
    "content": "source `dirname $0`/util.sh\nrecord tick0$bitness\ndebug_gdb_only tick0\n"
  },
  {
    "path": "src/test/tick0_less.run",
    "content": "source `dirname $0`/util.sh\nrecord tick0_less$bitness\ndebug_gdb_only tick0\n"
  },
  {
    "path": "src/test/timer.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int caught_sig = 0;\n\n// This test depends on making many context switch which can take a very long\n// time on slow or virtualized hardware. Limit the total execution time of this\n// test.\nstatic volatile int caught_limit_sig = 0;\n\nvoid alrm_catcher(int signum, __attribute__((unused)) siginfo_t* siginfo_ptr,\n                  __attribute__((unused)) void* ucontext_ptr) {\n  caught_sig = signum;\n}\n\nstatic timer_t* id;\nstatic timer_t* timeout_id = NULL;\nstatic struct itimerspec its = { { 100000, 0 }, { 0, 100000000 } };\nstatic struct itimerspec its2 = { { 100000, 0 }, { 100000, 0 } };\nstatic struct itimerspec its3 = { { 0, 1000000 }, { 0, 1000000 } };\n\nvoid usr1_catcher(int signum, __attribute__((unused)) siginfo_t* siginfo_ptr,\n                  __attribute__((unused)) void* ucontext_ptr) {\n  caught_sig = caught_limit_sig = signum;\n  // Set the actual timer to a long period. Otherwise we risk that on very\n  // slow machines, the timer fires so frequently that we never make it around\n  // the loop to check if it fired.\n  timer_settime(*id, 0, &its2, NULL);\n}\n\nint main(void) {\n  // The total runtime of this test must not exceed 120 seconds. Since we\n  // run the stress test twice and we also need to replay it, limit each stress\n  // test to 20 seconds, which should put the total run time at ~80 seconds,\n  // sufficient to complete the test on fast hardware, but low enough to\n  // hopefully not trigger the timeout on slow hardware;\n  struct itimerspec timeout = { { 100000, 0 }, { 20, 0 } };\n  struct itimerspec* old;\n  struct itimerspec* old2;\n  struct sigaction sact;\n  int counter;\n\n  sigemptyset(&sact.sa_mask);\n  sact.sa_flags = SA_SIGINFO;\n  sact.sa_sigaction = alrm_catcher;\n  sigaction(SIGALRM, &sact, NULL);\n  sigaddset(&sact.sa_mask, SIGALRM);\n  sact.sa_sigaction = usr1_catcher;\n  sigaction(SIGUSR1, &sact, NULL);\n\n  ALLOCATE_GUARD(id, 'a');\n  ALLOCATE_GUARD(timeout_id, 'b');\n  clockid_t clocks[2] = { CLOCK_REALTIME, CLOCK_MONOTONIC };\n  for (unsigned int i = 0; i < sizeof(clocks) / sizeof(clockid_t); ++i) {\n    struct sigevent sevp;\n\n    test_assert(0 == timer_create(clocks[i], NULL, id));\n    VERIFY_GUARD(id);\n\n    // Set up timeout timer\n    sevp.sigev_notify = SIGEV_SIGNAL;\n    sevp.sigev_signo = SIGUSR1;\n    test_assert(0 == timer_create(CLOCK_MONOTONIC, &sevp, timeout_id));\n    caught_limit_sig = 0;\n    test_assert(0 == timer_settime(*timeout_id, 0, &timeout, NULL));\n\n    /* This tries to trigger the following condition:\n     * - Timer expiration in user space\n     * - Right after a syscall return (same ip/ticks)\n     * The bug that this is a test for did not reproduce if the timer expired\n     * in kernel space or if there were any intervening ticks. In testing this\n     * took a few thousand iterations to reproduce, so 5000 may not be\n     * sufficient for reliable reproduction, but it should be an ok trade-off,\n     * between test runtime and reproducibility.\n     */\n    test_assert(0 == timer_settime(*id, 0, &its3, NULL));\n    for (int i = 0; i < 5000 && !caught_limit_sig; ++i) {\n      caught_sig = 0;\n      for (counter = 0; counter >= 0 && !caught_sig && !caught_limit_sig; counter++) {\n        (void)sys_gettid();\n      }\n    }\n\n    test_assert(0 == timer_delete(*timeout_id));\n\n    // The time interval above is pretty short and susceptible to overruns on\n    // systems under high load. That's fine, but we want to check for the next\n    // tests that no overruns occur, so we delete and recreate the timer.\n    test_assert(0 == timer_delete(*id));\n\n    // Reset this before restarting the counter, to avoid causing a race\n    // condition.\n    caught_sig = 0;\n\n    test_assert(0 == timer_create(clocks[i], NULL, id));\n    test_assert(0 == timer_settime(*id, 0, &its, NULL));\n\n    for (counter = 0; counter >= 0 && !caught_sig; counter++) {\n      if (counter % 100000 == 0) {\n        write(STDOUT_FILENO, \".\", 1);\n      }\n    }\n\n    atomic_printf(\"\\nSignal %d caught, Counter is %d\\n\", caught_sig, counter);\n    test_assert(SIGALRM == caught_sig);\n\n    test_assert(0 == timer_getoverrun(*id));\n\n    ALLOCATE_GUARD(old, 'b');\n    test_assert(0 == timer_settime(*id, 0, &its2, old));\n    VERIFY_GUARD(old);\n    test_assert(old->it_interval.tv_sec == its.it_interval.tv_sec);\n    test_assert(old->it_interval.tv_nsec == its.it_interval.tv_nsec);\n    test_assert(old->it_value.tv_sec <= its.it_interval.tv_sec);\n    test_assert(old->it_value.tv_sec >= its.it_interval.tv_sec / 2);\n    test_assert(old->it_value.tv_nsec < 1000000000);\n\n    ALLOCATE_GUARD(old2, 'c');\n    test_assert(0 == timer_gettime(*id, old2));\n    VERIFY_GUARD(old2);\n    test_assert(old2->it_interval.tv_sec == its2.it_interval.tv_sec);\n    test_assert(old2->it_interval.tv_nsec == its2.it_interval.tv_nsec);\n    test_assert(old2->it_value.tv_sec <= its2.it_interval.tv_sec);\n    test_assert(old2->it_value.tv_sec >= its2.it_interval.tv_sec / 2);\n    test_assert(old2->it_value.tv_nsec < 1000000000);\n\n    test_assert(0 == timer_delete(*id));\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/timerfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int fd = timerfd_create(CLOCK_MONOTONIC, 0);\n  struct itimerspec spec, old;\n  uint64_t num_expirations;\n\n  atomic_printf(\"created timerfd %d\\n\", fd);\n  test_assert(fd >= 0);\n\n  memset(&spec, 0, sizeof(spec));\n  spec.it_value.tv_nsec = 100000000;\n  atomic_printf(\"setting timer to expire in {sec:%ld,nsec:%ld}\\n\",\n                spec.it_value.tv_sec, spec.it_value.tv_nsec);\n  timerfd_settime(fd, 0, &spec, &old);\n\n  atomic_printf(\"  (old expiration was {sec:%ld,nsec:%ld})\\n\",\n                old.it_value.tv_sec, old.it_value.tv_nsec);\n  test_assert(0 == old.it_value.tv_sec && 0 == old.it_value.tv_nsec);\n\n  atomic_puts(\"sleeping 50ms ...\");\n  usleep(50000);\n\n  timerfd_gettime(fd, &old);\n  atomic_printf(\"  expiration now in {sec:%ld,nsec:%ld})\\n\",\n                old.it_value.tv_sec, old.it_value.tv_nsec);\n  test_assert(0 == old.it_value.tv_sec && old.it_value.tv_nsec <= 50000000);\n\n  atomic_puts(\"waiting for timer to expire ...\");\n  read(fd, &num_expirations, sizeof(num_expirations));\n\n  atomic_printf(\"  timer expired %\" PRIu64 \" times\\n\", num_expirations);\n  test_assert(1 == num_expirations);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/times.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct tms* buf;\n  clock_t t;\n\n  ALLOCATE_GUARD(buf, -1);\n  test_assert((t = times(buf)) != (clock_t)-1);\n  test_assert(buf->tms_cutime == 0);\n  test_assert(buf->tms_utime >= 0);\n  VERIFY_GUARD(buf);\n\n  atomic_printf(\"tms_utime = %lld\\n\", (long long)buf->tms_utime);\n  atomic_printf(\"result = %lld\\n\", (long long)t);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/tls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n__thread int tlsvar;\n\nvoid breakpoint_fn(void) {}\n\nvoid* thread_fn(void* arg) {\n  tlsvar = *(int*)arg;\n  breakpoint_fn();\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n\n  int value = 97;\n  pthread_create(&thread, NULL, thread_fn, &value);\n  pthread_join(thread, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/tls.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint_fn')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('print tlsvar')\nexpect_gdb(' = 97')\n\nsend_gdb('reverse-stepi')\nsend_gdb('print tlsvar')\nexpect_gdb(' = 97')\n\nok()\n"
  },
  {
    "path": "src/test/tls.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/trace_events.run",
    "content": "source `dirname $0`/util.sh\n\nexe=simple$bitness\ncp ${OBJDIR}/bin/$exe $exe-$nonce\njust_record $exe-$nonce\nif [[ `rr dump -e latest-trace|grep --count TraceTaskEvent::EXEC` != 1 ]]; then\n    failed \"Wrong number of TraceTaskEvent::EXECs\"\nfi\nif [[ `rr dump -e latest-trace|grep --count TraceTaskEvent::EXIT` != 1 ]]; then\n    failed \"Wrong number of TraceTaskEvent::EXITs\"\nfi\n"
  },
  {
    "path": "src/test/trace_version.run",
    "content": "source `dirname $0`/util.sh\n\nTRACE_DIR=trace_0\n\nfunction expect_replay_fail {\n    replay\n    if [[ $(cat replay.err) == \"\" ]]; then\n        echo \"Test '$TESTNAME' FAILED: replay should have failed, but it succeeded.\"\n        exit 1\n    fi\n    echo \"  (replay failed as expected)\"\n}\n\nrecord simple$bitness\ntrace_dir=\"simple$bitness-$nonce-0\"\n\nif [ ! -f \"$trace_dir/version\" ]; then\n    echo \"Test '$TESTNAME' FAILED: version file not found in trace directory.\"\n    exit 1\nfi;\n\necho \"Moving version file away ...\"\nmv \"$trace_dir/version\" ./version.tmp\nexpect_replay_fail\n\necho \"Trying to replay with empty version file ...\"\necho \"\" > \"$trace_dir/version\"\nexpect_replay_fail\n\necho \"Trying to replay with dummy version number ...\"\necho \"-42\\n\" > \"$trace_dir/version\"\nexpect_replay_fail\n\necho \"Restoring trace version file ...\"\nmv ./version.tmp \"$trace_dir/version\"\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/tracee_unmap_vdso.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char* vdso = (char*)getauxval(AT_SYSINFO_EHDR);\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  munmap(vdso, 4*page_size);\n\n  pid_t child = fork();\n  if (!child) {\n    return 77;\n  }\n  int status;\n  int ret = waitpid(child, &status, 0);\n  test_assert(ret == child);\n  test_assert(WIFEXITED(status));\n  test_assert(WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/tracee_unmap_vdso.run",
    "content": "source `dirname $0`/util.sh\n# Unmapping the rr page breaks ssycallbuf; we don't support that.\nskip_if_syscall_buf\n# Unmapping the VDSO breaks all syscalls on 32-bit x86.\nskip_if_test_32_bit\nskip_if_rr_32_bit\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/traceinfo.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\n_RR_TRACE_DIR=\"$workdir\" $RR_EXE $GLOBAL_OPTIONS traceinfo > traceinfo.txt || failed \"traceinfo failed\"\njq < traceinfo.txt > /dev/null || failed \"invalid JSON\"\ngrep -q '\"uuid\":' < traceinfo.txt || failed \"missing uuid\"\ngrep -q '\"bindToCpu\":' < traceinfo.txt || failed \"missing bindToCpu\"\ngrep -q '\"cpuidFaulting\":' < traceinfo.txt || failed \"missing cpuidFaulting\"\ngrep -q '\"ticksSemantics\":' < traceinfo.txt || failed \"missing ticksSemantics\"\ngrep -q '\"chaosMode\":false' < traceinfo.txt || failed \"missing chaosMode\"\ngrep -q '\"cpuImproperlyConfigured\":' < traceinfo.txt || failed \"missing cpuImproperlyConfigured\"\ngrep -q '\"maxVirtualAddressSize\":' < traceinfo.txt || failed \"missing maxVirtualAddressSize\"\ngrep -q '\"uname\":' < traceinfo.txt || failed \"missing uname\"\ngrep -q '\"sysname\":' < traceinfo.txt || failed \"missing sysname\"\ngrep -q '\"nodename\":' < traceinfo.txt || failed \"missing nodename\"\ngrep -q '\"release\":' < traceinfo.txt || failed \"missing release\"\ngrep -q '\"machine\":' < traceinfo.txt || failed \"missing machine\"\ngrep -q '\"environ\":' < traceinfo.txt || failed \"missing environ\"\ngrep -q '\"HOME=/' < traceinfo.txt || failed \"missing HOME\"\ngrep -q '\"program\":' < traceinfo.txt || failed \"missing program\"\n"
  },
  {
    "path": "src/test/transient_fault_replay_all.run",
    "content": "source `dirname $0`/util.sh\n\nskip_if_rr_32_bit_with_shell_64_bit\n\nRECORD_ARGS=-M\njust_record seq \"1 100\"\nRR_SIMULATE_ERROR_AT_EVENT=300 replay -M\ncheck 100 || exit 1\nRR_SIMULATE_ERROR_AT_EVENT=301 replay -M\ncheck 100\n"
  },
  {
    "path": "src/test/truncate_temp.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#define _FILE_OFFSET_BITS 64\n\n#include \"util.h\"\n\n#define TEST_FILE \"foo.txt\"\n\nssize_t get_file_size(const char* filename) {\n  struct stat* st;\n  ssize_t result;\n\n  ALLOCATE_GUARD(st, 'x');\n  test_assert(0 == stat(filename, st));\n  result = st->st_size;\n  FREE_GUARD(st);\n  return result;\n}\n\nint main(void) {\n  int fd;\n  ssize_t size;\n\n  fd = open(TEST_FILE, O_CREAT | O_EXCL | O_RDWR, 0600);\n  test_assert(0 <= fd);\n\n  size = get_file_size(TEST_FILE);\n  atomic_printf(\"initial file size: %zd\\n\", size);\n  test_assert(0 == size);\n\n  truncate(TEST_FILE, 4096);\n  size = get_file_size(TEST_FILE);\n  atomic_printf(\"after truncate(4096): %zd\\n\", size);\n  test_assert(4096 == size);\n\n  ftruncate(fd, 8192);\n  size = get_file_size(TEST_FILE);\n  atomic_printf(\"after truncate(8192): %zd\\n\", size);\n  test_assert(8192 == size);\n\n  unlink(TEST_FILE);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/tty.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\nreplay \"--tty tty-output\"\n\ntoken=EXIT-SUCCESS\nif [[ \"tty-output\" != $(grep -l $token tty-output) ]]; then\n    failed \": token '$token' not in tty-output:\"\n    echo \"--------------------------------------------------\"\n    cat tty-output\n    echo \"--------------------------------------------------\"\nelse\n    passed\nfi\n"
  },
  {
    "path": "src/test/tty_tostop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int do_child(void) {\n  test_assert(getpid() == setsid());\n\n  int fd = open(\"/dev/ptmx\", O_RDWR);\n  test_assert(fd >= 0);\n\n  atomic_printf(\"pty ptsname = %s\\n\", ptsname(fd));\n\n  test_assert(0 == ioctl(fd, TIOCSCTTY, 0));\n  test_assert(0 == tcsetpgrp(fd, getpid()));\n\n  struct termios tios;\n  test_assert(0 == tcgetattr(fd, &tios));\n  tios.c_lflag |= TOSTOP | ECHO;\n  test_assert(0 == tcsetattr(fd, TCSANOW, &tios));\n\n  pid_t child = fork();\n  if (!child) {\n    test_assert(0 == setpgid(0, 0));\n    tios.c_lflag &= ~ECHO;\n    test_assert(0 == tcsetattr(fd, TCSANOW, &tios));\n    return 76;\n  }\n\n  int status;\n  test_assert(child == waitpid(child, &status, WUNTRACED));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTTOU);\n  return 77;\n}\n\nint main(void) {\n  // Spawn a child since we need to call setsid() in a non-process-group-leader.\n  pid_t child = fork();\n  if (!child) {\n    return do_child();\n  }\n  int status;\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ttyname.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char* tty = ttyname(STDIN_FILENO);\n  atomic_printf(\"ttyname = %s\\n\", tty);\n  if (!tty) {\n    atomic_puts(\"No tty attached to stdin\");\n    fputs(\"EXIT-SUCCESS\", stderr);\n    return 0;\n  }\n  int fd = open(tty, O_RDWR);\n  if (fd < 0 && errno == EACCES) {\n    atomic_puts(\"tty access denied (su in progress?), skipping test\");\n    fputs(\"EXIT-SUCCESS\", stderr);\n    return 0;\n  }\n  test_assert(fd >= 0);\n  test_assert(13 == write(fd, \"EXIT-SUCCESS\\n\", 13));\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ttyname.run",
    "content": "source `dirname $0`/util.sh\nrecord $TESTNAME\nreplay\ntoken=EXIT-SUCCESS\nif [[ \"replay.err\" != $(grep -l $token replay.err) ]]; then\n    failed \": token '$token' not in replay.err:\"\n    echo \"--------------------------------------------------\"\n    cat replay.err\n    echo \"--------------------------------------------------\"\n    cat replay.out\n    echo \"--------------------------------------------------\"\nelse\n    passed\nfi\n"
  },
  {
    "path": "src/test/tun.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nstatic void test_tun(void) {\n  struct ifreq* ifr;\n  int* features;\n  int* sndbuf;\n  int* hdrsz;\n  int fd = open(\"/dev/net/tun\", O_RDWR);\n\n  if (fd < 0) {\n    atomic_puts(\"Can't open /dev/net/tun --- not supported?\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n  }\n\n  ALLOCATE_GUARD(features, 0);\n  test_assert(ioctl(fd, TUNGETFEATURES, (void*)features) == 0);\n  VERIFY_GUARD(features);\n  test_assert((*features & IFF_TAP) != 0);\n\n  ALLOCATE_GUARD(ifr, 'a');\n  memset(ifr, 0, sizeof(*ifr));\n  ifr->ifr_flags = IFF_TAP;\n  test_assert(ioctl(fd, TUNSETIFF, (void*)ifr) == 0);\n  VERIFY_GUARD(ifr);\n  test_assert(ifr->ifr_name[0] != 0);\n  atomic_printf(\"ifname: %s\\n\", ifr->ifr_name);\n\n  ALLOCATE_GUARD(ifr, 0);\n  test_assert(ioctl(fd, TUNGETIFF, (void*)ifr) == 0);\n  VERIFY_GUARD(ifr);\n  atomic_printf(\"flags: 0x%x\\n\", ifr->ifr_flags);\n  test_assert((ifr->ifr_flags & IFF_TAP) != 0);\n  test_assert(ifr->ifr_name[0] != 0);\n\n  ALLOCATE_GUARD(sndbuf, 0);\n  test_assert(ioctl(fd, TUNGETSNDBUF, (void*)sndbuf) == 0);\n  VERIFY_GUARD(sndbuf);\n  test_assert(*sndbuf > 0);\n\n  ALLOCATE_GUARD(hdrsz, 0);\n  test_assert(ioctl(fd, TUNGETVNETHDRSZ, (void*)hdrsz) == 0);\n  VERIFY_GUARD(hdrsz);\n  test_assert(*hdrsz > 0);\n\n#ifdef __x86_64__\n  /* TUNDETACHFILTER/TUNGETFILTER (and probably TUNATTACHFILTER) are\n     incorrectly implemented (as of 4.12 at least). The ioctl values are\n     defined with a size field of 8 bytes (struct sock_fprog) on x86-32,\n     but an x86-64 kernel expects the x86-64 size (16 bytes) and the\n     64-bit sock_fprog layout. */\n  /* The actual ioctl numbers will depend on whether the kernel is 32-bit\n     or 64-bit so testing this on 32-bit is not worth the hassle. */\n  test_assert(ioctl(fd, TUNDETACHFILTER, NULL) == 0);\n\n  /* The actual results will depend on whether we're running on a 32-bit\n     or 64-bit kernel, which we don't want to try to detect, so only run\n     this test on 64-bit kernels. */\n  struct sock_fprog* fprog;\n  ALLOCATE_GUARD(fprog, 'x');\n  test_assert(ioctl(fd, TUNGETFILTER, (void*)fprog) == 0);\n  VERIFY_GUARD(fprog);\n  test_assert(fprog->len == 0);\n#endif\n}\n\nint main(void) {\n  if (-1 == try_setup_ns(CLONE_NEWNET)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  test_tun();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/two_signals_with_mask.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int pipe_fds[2];\nstatic int got_sigs;\n\nstatic void handle_sig(__attribute__((unused)) int sig,\n                       __attribute__((unused)) siginfo_t* info,\n                       __attribute__((unused)) void* mcontext) {\n  if (sig == SIGUSR2) {\n    write(pipe_fds[1], \"x\", 1);\n  }\n  ++got_sigs;\n}\n\nint main(void) {\n  struct sigaction sa;\n  struct sigevent sevp;\n  char ch;\n  timer_t id;\n  timer_t id2;\n  struct itimerspec timeout = { { 0, 0 }, { 0, 1000000 } };\n  struct syscall_info read_syscall = { SYS_read, { 0, 0, 0, 0, 0, 0 } };\n  SyscallWrapper delayed_syscall = get_delayed_syscall();\n\n  test_assert(0 == pipe(pipe_fds));\n\n  sa.sa_flags = SA_SIGINFO | SA_RESTART;\n  sa.sa_sigaction = handle_sig;\n  sigemptyset(&sa.sa_mask);\n  sigaction(SIGUSR2, &sa, NULL);\n  sigaddset(&sa.sa_mask, SIGUSR2);\n  sigaction(SIGUSR1, &sa, NULL);\n\n  sevp.sigev_notify = SIGEV_SIGNAL;\n  sevp.sigev_signo = SIGUSR1;\n  test_assert(0 == timer_create(CLOCK_MONOTONIC, &sevp, &id));\n  sevp.sigev_signo = SIGUSR2;\n  test_assert(0 == timer_create(CLOCK_MONOTONIC, &sevp, &id2));\n  test_assert(0 == timer_settime(id, 0, &timeout, NULL));\n  test_assert(0 == timer_settime(id2, 0, &timeout, NULL));\n\n  /* This will hang unless SIGUSR2 is processed before we read from the pipe */\n  read_syscall.args[0] = pipe_fds[0];\n  read_syscall.args[1] = (long)&ch;\n  read_syscall.args[2] = 1;\n  delayed_syscall(&read_syscall);\n\n  test_assert(got_sigs == 2);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/ulimit_low.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  struct rlimit limit;\n  test_assert(0 == getrlimit(RLIMIT_NOFILE, &limit));\n\n  // Set a low rlimit\n  limit.rlim_cur = 30;\n  test_assert(0 == setrlimit(RLIMIT_NOFILE, &limit));\n\n  pid_t child;\n  // Test both forking and thread creation under the low ulimit\n  if ((child = fork()) == 0) {\n    pthread_create(&thread, NULL, do_thread, NULL);\n    pthread_join(thread, NULL);\n    return 0;\n  }\n\n  int status;\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/uname.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  struct utsname* buf;\n\n  ALLOCATE_GUARD(buf, 0);\n  test_assert(0 == uname(buf));\n  test_assert(buf->sysname[0] != 0);\n  test_assert(buf->nodename[0] != 0);\n  test_assert(buf->release[0] != 0);\n  test_assert(buf->version[0] != 0);\n  test_assert(buf->machine[0] != 0);\n  VERIFY_GUARD(buf);\n\n  atomic_printf(\"{ sysname: '%s', nodename: '%s', release: '%s',\\n\"\n                \"  version: '%s', machine: '%s', domainname: '%s' }\\n\",\n                buf->sysname, buf->nodename, buf->release, buf->version,\n                buf->machine, buf->domainname);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unexpected_exit.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int child_to_parent[2];\n\nstatic void* run_child_thread(__attribute__((unused)) void* p) {\n  setpriority(PRIO_PROCESS, 0, 10);\n  atomic_printf(\"off-main-thread id = %d\\n\", sys_gettid());\n  write(child_to_parent[1], \"x\", 1);\n  pause();\n  return NULL;\n}\n\nstatic int do_child(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, run_child_thread, NULL);\n  pause();\n  return 66;\n}\n\n/* Do a busy delay loop that changes registers so won't trigger\n   rr's spinlock-detection heuristic */\nstatic char delay(void) {\n#if defined(__x86_64__) || defined(__i386__)\n  asm(\"mov $10000000,%%ecx\\n\\t\"\n      \"1: loop 1b\\n\\t\"\n      : : : \"ecx\");\n  return 0;\n#else\n  /* Does this actually change registers on ARM??? */\n  int i;\n  static volatile char ch;\n  for (i = 0; i < 10000000; ++i) {\n    ch = i % 3;\n  }\n  return ch;\n#endif\n}\n\nint main(__attribute__((unused)) int argc, char** argv) {\n  int fd = open(argv[0], O_RDONLY);\n  pid_t child;\n  int status;\n  char cc;\n  struct timespec ts = { 0, 1000000 };\n\n  pipe(child_to_parent);\n  child = fork();\n  if (!child) {\n    return do_child();\n  }\n\n  read(child_to_parent[0], &cc, 1);\n  atomic_printf(\"sending SIGTERM to %d\\n\", child);\n  kill(child, SIGTERM);\n  /* Delay a bit. During this delay the child's main thread\n     will handle SIGTERM, rr will schedule it and process the SIGTERM,\n     triggering a thread-group exit; the child main thread will proceed\n     to its PTRACE_EVENT_EXIT stop, rr will process that too, and the\n     child main thread will complete exit and go into zombie state.\n     rr will not schedule the child off-main thread since it has lower priority,\n     so that thread will advance to its PTRACE_EVENT_EXIT stop and wait there. */\n  delay();\n\n  atomic_printf(\"sending SIGKILL to %d\\n\", child);\n  kill(child, SIGKILL);\n  /* Delay a bit more. During this delay the child's off-main thread will\n     respond to the SIGKILL by exiting its PTRACE_EVENT_EXIT stop and going into\n     zombie state. rr still won't schedule that thread and doesn't know anything\n     about it exiting. */\n  delay();\n\n  /* Trigger the logic that scans tracee tasks to see if they have the file open\n     for writing. */\n  mmap(NULL, 4091, PROT_READ, MAP_SHARED, fd, 0);\n\n  atomic_printf(\"Sleeping...\\n\");\n  /* Try scheduling the now-dead task to make sure we survive that */\n  nanosleep(&ts, NULL);\n\n  /* Make sure we can fork after that, i.e. we didn't mess up the state of our\n     tracee communication socket. */\n  child = fork();\n  if (!child) {\n    return 77;\n  }\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unexpected_exit_execve.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int child_to_parent[2];\n\nstatic void* run_child_thread(__attribute__((unused)) void* p) {\n  setpriority(PRIO_PROCESS, 0, 10);\n  atomic_printf(\"off-main-thread id = %d\\n\", sys_gettid());\n  write(child_to_parent[1], \"x\", 1);\n  pause();\n  return NULL;\n}\n\nstatic int do_child(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, run_child_thread, NULL);\n  pause();\n  return 66;\n}\n\n/* Do a busy delay loop that changes registers so won't trigger\n   rr's spinlock-detection heuristic */\nstatic char delay(void) {\n#if defined(__x86_64__) || defined(__i386__)\n  asm(\"mov $10000000,%%ecx\\n\\t\"\n      \"1: loop 1b\\n\\t\"\n      : : : \"ecx\");\n  return 0;\n#else\n  /* Does this actually change registers on ARM??? */\n  int i;\n  static volatile char ch;\n  for (i = 0; i < 10000000; ++i) {\n    ch = i % 3;\n  }\n  return ch;\n#endif\n}\n\nint main(int argc, __attribute__((unused)) char** argv) {\n  pid_t child;\n  pid_t exec_child;\n  int status;\n  char cc;\n  char* execv_argv[] = {\"/proc/self/exe\", \"dummy\", NULL};\n\n  if (argc > 1) {\n    return 99;\n  }\n\n  pipe(child_to_parent);\n  child = fork();\n  if (!child) {\n    return do_child();\n  }\n\n  read(child_to_parent[0], &cc, 1);\n  atomic_printf(\"sending SIGTERM to %d\\n\", child);\n  kill(child, SIGTERM);\n  /* Delay a bit. During this delay the child's main thread\n     will handle SIGTERM, rr will schedule it and process the SIGTERM,\n     triggering a thread-group exit; the child main thread will proceed\n     to its PTRACE_EVENT_EXIT stop, rr will process that too, and the\n     child main thread will complete exit and go into zombie state.\n     rr will not schedule the child off-main thread since it has lower priority,\n     so that thread will advance to its PTRACE_EVENT_EXIT stop and wait there. */\n  delay();\n\n  atomic_printf(\"sending SIGKILL to %d\\n\", child);\n  kill(child, SIGKILL);\n  /* Delay a bit more. During this delay the child's off-main thread will\n     respond to the SIGKILL by exiting its PTRACE_EVENT_EXIT stop and going into\n     zombie state. rr still won't schedule that thread and doesn't know anything\n     about it exiting. */\n  delay();\n\n  atomic_printf(\"Sleeping...\\n\");\n  /* Do an execve and let the other task run during that */\n  exec_child = fork();\n  if (exec_child == 0) {\n    execve(\"/proc/self/exe\", execv_argv, NULL);\n  }\n  test_assert(exec_child == waitpid(exec_child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 99);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unexpected_exit_execve_twice.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int child_to_parent[2];\n\nstatic void* run_child_thread(__attribute__((unused)) void* p) {\n  setpriority(PRIO_PROCESS, 0, 10);\n  atomic_printf(\"off-main-thread id = %d\\n\", sys_gettid());\n  write(child_to_parent[1], \"x\", 1);\n  pause();\n  return NULL;\n}\n\nstatic int do_child(void) {\n  pthread_t thread;\n\n  pthread_create(&thread, NULL, run_child_thread, NULL);\n  pause();\n  return 66;\n}\n\n/* Do a busy delay loop that changes registers so won't trigger\n   rr's spinlock-detection heuristic */\nstatic char delay(void) {\n#if defined(__x86_64__) || defined(__i386__)\n  asm(\"mov $10000000,%%ecx\\n\\t\"\n      \"1: loop 1b\\n\\t\"\n      : : : \"ecx\");\n  return 0;\n#else\n  /* Does this actually change registers on ARM??? */\n  int i;\n  static volatile char ch;\n  for (i = 0; i < 10000000; ++i) {\n    ch = i % 3;\n  }\n  return ch;\n#endif\n}\n\nint main(int argc, __attribute__((unused)) char** argv) {\n  pid_t child;\n  pid_t exec_child;\n  int status;\n  char cc;\n  char* execv_argv[] = {\"/proc/self/exe\", \"dummy\", NULL};\n\n  if (argc > 1) {\n    return 99;\n  }\n\n  pipe(child_to_parent);\n  child = fork();\n  if (!child) {\n    return do_child();\n  }\n\n  read(child_to_parent[0], &cc, 1);\n  atomic_printf(\"sending SIGTERM to %d\\n\", child);\n  kill(child, SIGTERM);\n  /* Delay a bit. During this delay the child's main thread\n     will handle SIGTERM, rr will schedule it and process the SIGTERM,\n     triggering a thread-group exit; the child main thread will proceed\n     to its PTRACE_EVENT_EXIT stop, rr will process that too, and the\n     child main thread will complete exit and go into zombie state.\n     rr will not schedule the child off-main thread since it has lower priority,\n     so that thread will advance to its PTRACE_EVENT_EXIT stop and wait there. */\n  delay();\n\n  atomic_printf(\"Sleeping...\\n\");\n  /* Do an execve. Here we'll see the child off-main thread's PTRACE_EVENT_EXIT\n     stop but we won't act on it because we're in an execve for another\n     thread group */\n  exec_child = fork();\n  if (exec_child == 0) {\n    execve(\"/proc/self/exe\", execv_argv, NULL);\n  }\n  test_assert(exec_child == waitpid(exec_child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 99);\n\n  atomic_printf(\"sending SIGKILL to %d\\n\", child);\n  assert(kill(child, SIGKILL) == 0);\n  /* Delay a bit more. During this delay the child's off-main thread will\n     respond to the SIGKILL by exiting its PTRACE_EVENT_EXIT stop and going into\n     zombie state. rr still won't schedule that thread and doesn't know anything\n     about it exiting. */\n  delay();\n\n  atomic_printf(\"Sleeping...\\n\");\n  /* Do a second execve. Here rr will see the child's off-main thread go into\n     the zombie state but we still won't act on it because we're in yet another\n     execve for yet another thread group. */\n  exec_child = fork();\n  if (exec_child == 0) {\n    execve(\"/proc/self/exe\", execv_argv, NULL);\n  }\n  test_assert(exec_child == waitpid(exec_child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 99);\n\n  /* Finally, make the child's off-main thread schedulable by making the last\n     surviving higher-priority task sleep. */\n  sleep(1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unexpected_exit_pid_ns.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"nsutils.h\"\n#include \"util.h\"\n\nstatic int child_to_parent[2];\n\n/* Do a busy delay loop that changes registers so won't trigger\n   rr's spinlock-detection heuristic */\nstatic char delay(void) {\n#if defined(__x86_64__) || defined(__i386__)\n  asm(\"mov $10000000,%%ecx\\n\\t\"\n      \"1: loop 1b\\n\\t\"\n      : : : \"ecx\", \"memory\");\n  return 0;\n#else\n  /* Does this actually change registers on ARM??? */\n  int i;\n  static volatile char ch;\n  for (i = 0; i < 10000000; ++i) {\n    ch = i % 3;\n  }\n  return ch;\n#endif\n}\n\nstatic void* run_child_thread(__attribute__((unused)) void* p) {\n  setpriority(PRIO_PROCESS, 0, 10);\n  write(child_to_parent[1], \"x\", 2);\n  /* Make sure it stays runnable so rr can switch to us without\n     trying to observe a state change */\n  for (;;) {\n    delay();\n  }\n  return NULL;\n}\n\nstatic int do_child(void) {\n  pthread_t thread;\n  char cc;\n\n  pthread_create(&thread, NULL, run_child_thread, NULL);\n  read(child_to_parent[0], &cc, 1);\n  return 66;\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  char cc;\n  struct timespec ts = { 0, 1000000 };\n\n  if (-1 == try_setup_ns(CLONE_NEWPID)) {\n    /* We may not have permission to set up namespaces, so bail. */\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  pipe(child_to_parent);\n  child = fork();\n  if (!child) {\n    return do_child();\n  }\n  atomic_printf(\"off-main-thread id = %d\\n\", child + 1);\n\n  read(child_to_parent[0], &cc, 1);\n  /* Delay a bit. During this delay the child's main thread\n     will complete its exit, triggering a thread-group exit;\n     the child main thread will proceed to its PTRACE_EVENT_EXIT stop,\n     rr will process that too, and the\n     child main thread will complete exit and go into zombie state.\n     rr will not schedule the child off-main thread since it has lower priority,\n     so that thread will advance to its PTRACE_EVENT_EXIT stop and wait there. */\n  delay();\n\n  atomic_printf(\"sending SIGKILL to %d\\n\", child);\n  kill(child, SIGKILL);\n  /* Delay a bit more. During this delay the child's off-main thread will\n     respond to the SIGKILL by exiting its PTRACE_EVENT_EXIT stop and going into\n     zombie state. rr still won't schedule that thread and doesn't know anything\n     about it exiting. */\n  delay();\n\n  atomic_printf(\"Sleeping...\\n\");\n  /* Let the now-dead task resume without waiting for it to change state (since\n     rr thinks it's not blocked). */\n  nanosleep(&ts, NULL);\n\n  test_assert(child == waitpid(child, &status, 0));\n  /* We should exit normally with status 66 but if scheduling is particularly messed\n     up we could see SIGKILL. */\n  test_assert((WIFEXITED(status) && WEXITSTATUS(status) == 66) ||\n              (WIFSIGNALED(status) && WTERMSIG(status) == 9));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unexpected_stack_growth.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic volatile int vv = 0;\n\nstatic void breakpoint(void) {}\n\nstatic void funcall(void) {\n  char buf[2000000];\n  size_t i;\n  for (i = 0; i < sizeof(buf); ++i) {\n    buf[i] = (char)i;\n  }\n  for (i = 0; i < sizeof(buf); ++i) {\n    vv += buf[i % 777777];\n  }\n}\n\nint main(void) {\n  char v;\n  char* fix_addr;\n  void* p;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  breakpoint();\n  fix_addr =\n      (char*)(((uintptr_t)&v - 256 * 1024) & ~(uintptr_t)(page_size - 1));\n  p = mmap(fix_addr, page_size, PROT_READ | PROT_WRITE,\n           MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(p == fix_addr);\n\n  funcall();\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unexpected_stack_growth.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\n\nsend_gdb('watch -l *(&v - 1000000)')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('signal SIGSEGV')\n\nsend_gdb('c')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/unexpected_stack_growth.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/unicode.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic void outer(__attribute__((unused)) char* arg) {\n  /* On some gdb/distro combinations, function parameters don't have\n     correct debuginfo when stopped at a breakpoint on the function\n     itself. So stop in `breakpoint()` and then use `finish` to return\n     to this stack frame at a point where `arg` is sure to print\n     correctly. */\n  breakpoint();\n}\n\nint main(void) {\n  outer(\"\\xf0\\x9d\\x95\\xa8\\xc4\\x81\\xe2\\x89\\xa5\\x33\");\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unicode.py",
    "content": "from util import *\nimport re\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\n\nsend_gdb('checkpoint')\nexpect_gdb(re.compile(r'Checkpoint 1 at.*\"𝕨ā≥3\"'))\n\nok()\n"
  },
  {
    "path": "src/test/unicode.run",
    "content": "source `dirname $0`/util.sh\nset_utf_locale\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/unjoined_thread.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  sleep(-1);\n  return NULL;\n}\n\nint main(void) {\n  pthread_t t;\n\n  pthread_create(&t, NULL, thread, NULL);\n  /* Don't join |t|. */\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unmap_vdso.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS=\"--unmap-vdso\"\njust_record cat /proc/self/maps\nif grep \"vdso\" record.out; then\n    failed \"vdso should have been unmapped\"\nfi\n"
  },
  {
    "path": "src/test/unshare.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define MAX_FDS 2048\n\nextern int capset(cap_user_header_t header, const cap_user_data_t data);\n\nstatic char tmp_name[] = \"tempXXXXXX\";\nstatic uid_t uid;\nstatic uid_t gid;\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  test_assert(0 == unshare(CLONE_FILES));\n  test_assert(0 == close(STDOUT_FILENO));\n  return NULL;\n}\n\nstatic void test_mount(void) {\n  test_assert(0 == mkdir(\"/aaa\", 0777));\n  /* Most filesystems can't be mounted in a non-root namespace,\n     but proc can. */\n  test_assert(0 == mount(\"dummy\", \"/aaa\", \"proc\", 0, NULL));\n  test_assert(0 == access(\"/aaa/cpuinfo\", F_OK));\n  test_assert(0 == umount(\"/aaa\"));\n  test_assert(0 == mount(\"dummy\", \"/aaa\", \"proc\", 0, NULL));\n  test_assert(0 == umount2(\"/aaa\", 0));\n  test_assert(0 == rmdir(\"/aaa\"));\n}\n\nstatic void test_uids(void) {\n  test_assert(0 == syscall(SYS_setreuid, 7, 7) || errno == ENOSYS);\n#ifdef SYS_setreuid32\n  test_assert(0 == syscall(SYS_setreuid32, 7, 7));\n#endif\n  test_assert(0 == syscall(SYS_setregid, 8, 8) || errno == ENOSYS);\n#ifdef SYS_setreuid32\n  test_assert(0 == syscall(SYS_setregid32, 8, 8));\n#endif\n  test_assert(0 == syscall(SYS_setresuid, 7, 7, 7) || errno == ENOSYS);\n#ifdef SYS_setresuid32\n  test_assert(0 == syscall(SYS_setresuid32, 7, 7, 7));\n#endif\n  test_assert(0 == syscall(SYS_setresgid, 8, 8, 8) || errno == ENOSYS);\n#ifdef SYS_setresuid32\n  test_assert(0 == syscall(SYS_setresgid32, 8, 8, 8));\n#endif\n  test_assert(0 == syscall(SYS_setuid, 7) || errno == ENOSYS);\n#ifdef SYS_setuid32\n  test_assert(0 == syscall(SYS_setuid32, 7));\n#endif\n  test_assert(0 == syscall(SYS_setgid, 8) || errno == ENOSYS);\n#ifdef SYS_setgid32\n  test_assert(0 == syscall(SYS_setgid32, 8));\n#endif\n  test_assert(7 == syscall(SYS_setfsuid, 7) || errno == ENOSYS);\n#ifdef SYS_setfsuid32\n  test_assert(7 == syscall(SYS_setfsuid32, 7));\n#endif\n  test_assert(8 == syscall(SYS_setfsgid, 8) || errno == ENOSYS);\n#ifdef SYS_setfsgid32\n  test_assert(8 == syscall(SYS_setfsgid32, 8));\n#endif\n  test_assert(7 == syscall(SYS_getuid) || errno == ENOSYS);\n#ifdef SYS_getuid32\n  test_assert(7 == syscall(SYS_getuid32));\n#endif\n  test_assert(8 == syscall(SYS_getgid) || errno == ENOSYS);\n#ifdef SYS_getgid32\n  test_assert(8 == syscall(SYS_getgid32));\n#endif\n  test_assert(7 == syscall(SYS_geteuid) || errno == ENOSYS);\n#ifdef SYS_geteuid32\n  test_assert(7 == syscall(SYS_geteuid32));\n#endif\n  test_assert(8 == syscall(SYS_getegid) || errno == ENOSYS);\n#ifdef SYS_getegid32\n  test_assert(8 == syscall(SYS_getegid32));\n#endif\n}\n\nstatic void test_setns(void) {\n  int uts_ns = open(\"/proc/self/ns/uts\", O_RDONLY);\n  pid_t child;\n  int status;\n  test_assert(uts_ns >= 0);\n\n  child = fork();\n  if (!child) {\n    test_assert(0 == unshare(CLONE_NEWUTS));\n    /* setns requires that this process be privileged in both the old and new\n     * uts namespaces. We are. */\n    test_assert(0 == setns(uts_ns, CLONE_NEWUTS));\n    exit(76);\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 76);\n  test_assert(0 == close(uts_ns));\n}\n\nstatic void test_sethostname(void) {\n  char name[] = \"hello\";\n  char buf[1000];\n  test_assert(0 == sethostname(name, strlen(name)));\n  test_assert(0 == gethostname(buf, sizeof(buf)));\n  test_assert(0 == strcmp(buf, name));\n}\n\nstatic void test_setdomainname(void) {\n  char name[] = \"kitty\";\n  char buf[1000];\n  test_assert(0 == setdomainname(name, strlen(name)));\n  test_assert(0 == getdomainname(buf, sizeof(buf)));\n  test_assert(0 == strcmp(buf, name));\n}\n\nstatic void test_capset_and_drop_privileges(void) {\n  struct __user_cap_header_struct hdr = { _LINUX_CAPABILITY_VERSION_1, 0 };\n  struct __user_cap_data_struct data = { 0x1, 0x1, 0x1 };\n\n  /* Test using capset. capset is privileged, but we are privileged\n     in our user namespace. After this we are no longer privileged. */\n  test_assert(0 == capset(&hdr, &data));\n}\n\nstatic void write_user_namespace_mappings(void) {\n  char buf[100];\n  int fd;\n\n  fd = open(\"/proc/self/uid_map\", O_WRONLY | O_CREAT, 0600);\n  test_assert(fd >= 0);\n  sprintf(buf, \"7 %d 1\\n\", uid);\n  test_assert((ssize_t)strlen(buf) == write(fd, buf, strlen(buf)));\n  test_assert(0 == close(fd));\n\n  /* Per user_namespaces(7), we need to write 'deny' to /proc/self/setgroups\n   * before we set up gid_map. This means we can't test setgroups here. Oh well.\n   */\n  fd = open(\"/proc/self/setgroups\", O_WRONLY | O_CREAT, 0600);\n  /* This file does not exist in some old kernel */\n  if (fd >= 0) {\n    sprintf(buf, \"deny\");\n    test_assert((ssize_t)strlen(buf) == write(fd, buf, strlen(buf)));\n    test_assert(0 == close(fd));\n  }\n\n  fd = open(\"/proc/self/gid_map\", O_WRONLY | O_CREAT, 0600);\n  test_assert(fd >= 0);\n  sprintf(buf, \"8 %d 1\\n\", gid);\n  test_assert((ssize_t)strlen(buf) == write(fd, buf, strlen(buf)));\n  test_assert(0 == close(fd));\n}\n\nstatic void run_child(void) {\n  pid_t child;\n  int status;\n\n  child = fork();\n  if (!child) {\n    test_assert(0 == mkdir(\"/proc\", 0777));\n    test_assert(0 == mount(\"dummy\", \"/proc\", \"proc\", 0, NULL));\n\n    write_user_namespace_mappings();\n\n    /* Test creating a nested child */\n    pid_t nested_child = fork();\n    if (!nested_child) {\n      exit(77);\n    }\n    test_assert(nested_child == wait(&status));\n    test_assert(WIFEXITED(status) && 77 == WEXITSTATUS(status));\n\n    /* Test creating a thread */\n    pthread_t thread;\n    pthread_create(&thread, NULL, start_thread, NULL);\n    pthread_join(thread, NULL);\n\n    test_mount();\n    test_uids();\n    test_setns();\n    test_sethostname();\n    test_setdomainname();\n\n    test_assert(0 == umount(\"/proc\"));\n    test_assert(0 == rmdir(\"/proc\"));\n\n    test_capset_and_drop_privileges();\n\n    /* stdout should still be writable due to the unshare() in start_thread */\n    test_assert(13 == write(STDOUT_FILENO, \"EXIT-SUCCESS\\n\", 13));\n    exit(55);\n  }\n  test_assert(child == wait(&status));\n  test_assert(WIFEXITED(status) && 55 == WEXITSTATUS(status));\n}\n\nstatic int run_test(void) {\n  int ret;\n  int fd;\n  struct rlimit nofile;\n  int fd_limit;\n\n  test_assert(0 == getrlimit(RLIMIT_NOFILE, &nofile));\n  if (nofile.rlim_cur == RLIM_INFINITY || nofile.rlim_cur > MAX_FDS) {\n    fd_limit = MAX_FDS;\n  } else {\n    fd_limit = nofile.rlim_cur;\n  }\n\n  for (fd = STDERR_FILENO + 1; fd < fd_limit; ++fd) {\n    ret = close(fd);\n    test_assert(ret == 0 || (ret == -1 && errno == EBADF));\n  }\n\n  ret = unshare(CLONE_NEWUSER);\n  if (ret == -1 && (errno == EINVAL || errno == EPERM)) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n  test_assert(0 == ret);\n\n  test_assert(0 == unshare(CLONE_NEWNS));\n  test_assert(0 == unshare(CLONE_NEWIPC));\n  test_assert(0 == unshare(CLONE_NEWNET));\n  test_assert(0 == unshare(CLONE_NEWUTS));\n  ret = unshare(CLONE_NEWPID);\n  if (ret == -1 && errno == EINVAL) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  test_assert(0 == ret);\n\n  test_assert(0 == chroot(tmp_name));\n\n  run_child();\n  return 77;\n}\n\nint main(void) {\n  pid_t child;\n  int ret;\n  int status;\n\n  uid = getuid();\n  gid = getgid();\n\n  mkdtemp(tmp_name);\n\n  child = fork();\n  if (!child) {\n    return run_test();\n  }\n  ret = wait(&status);\n  test_assert(0 == rmdir(tmp_name));\n  test_assert(child == ret);\n  test_assert(WIFEXITED(status) && 77 == WEXITSTATUS(status));\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/unwind_on_signal.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p (int)strdup(0)')\nexpect_gdb('received signal SIGSEGV')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('SIGKILL')\n\nok()\n"
  },
  {
    "path": "src/test/unwind_on_signal.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only unwind_on_signal\n"
  },
  {
    "path": "src/test/unwind_rr_page.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* The C++ standard mandates an unwinder, so we assume that by making a C++\n   file, the compiler will link in an appropriate unwind library */\n\nextern \"C\" void *_Unwind_FindEnclosingFunction(void *);\n\n#ifdef __i386__\nvoid callback(uint64_t env, char* name, map_properties_t* props) {\n  uintptr_t* ip = (uintptr_t*)env;\n  if (strstr(name, \"[vdso]\") != 0) {\n    if (*ip >= props->start && *ip < props->end) {\n      /* This test does not work when built for i386 and using no syscall buffering.\n         Because then ip is in [vdso] which seems not to be in the list of the dynamic loader. */\n      atomic_puts(\"skipping. EXIT-SUCCESS\");\n      exit(0);\n    }\n  }\n}\n#endif\n\nvoid catcher(__attribute__((unused)) int signum,\n             __attribute__((unused)) siginfo_t* siginfo_ptr,\n             void* ucontext_ptr) {\n    ucontext_t* ctx = (ucontext_t*)ucontext_ptr;\n    uintptr_t ip;\n#ifdef __i386__\n    ip = ctx->uc_mcontext.gregs[REG_EIP];\n    FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n    iterate_maps((uintptr_t)&ip, callback, maps_file);\n#elif defined(__x86_64__)\n    ip = ctx->uc_mcontext.gregs[REG_RIP];\n#elif defined(__aarch64__)\n    ip = ctx->uc_mcontext.pc;\n#endif\n    test_assert(_Unwind_FindEnclosingFunction((void*)ip) != NULL);\n    atomic_puts(\"EXIT-SUCCESS\");\n    exit(0);\n}\n\nint main(void) {\n    /* First make sure the unwind library itself is sane */\n    test_assert(_Unwind_FindEnclosingFunction((char*)&main+1) == (void*)&main);\n\n    struct sigaction sact;\n    sigemptyset(&sact.sa_mask);\n    sact.sa_flags = SA_SIGINFO;\n    sact.sa_sigaction = catcher;\n    sigaction(SIGALRM, &sact, NULL);\n\n    /* Use syscall to ensure a patchable syscall location */\n    struct timespec sleep = { 0, 0 };\n    /* Give the syscallbuf a chance to patch this */\n    test_assert(0 == syscall(SYS_clock_nanosleep, CLOCK_MONOTONIC, 0, &sleep, NULL));\n\n    sleep.tv_sec = 1;\n\n    alarm(1); /* timer will pop in 1 second */\n    test_assert(0 == syscall(SYS_clock_nanosleep, CLOCK_MONOTONIC, 0, &sleep, NULL));\n    return 0;\n}\n"
  },
  {
    "path": "src/test/usb.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n/* Based on https://github.com/ktossell/libuvc/blob/master/src/example.c\n\nSoftware License Agreement (BSD License)\n\nCopyright (C) 2010-2015 Ken Tossell\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n\n * Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n * Redistributions in binary form must reproduce the above\n   copyright notice, this list of conditions and the following\n   disclaimer in the documentation and/or other materials provided\n   with the distribution.\n * Neither the name of the author nor other contributors may be\n   used to endorse or promote products derived from this software\n   without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\nFOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\nCOPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,\nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\nANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n*/\n\n/* Tests a subset of the USBDEVFS ioctls. Requires libuvc to build:\n   https://github.com/ktossell/libuvc\n   Therefore this test is not built/run by default. */\n\n#include \"util.h\"\n\n#include \"libuvc/libuvc.h\"\n\nstatic int frame_count = 0;\n\nvoid cb(uvc_frame_t* frame, __attribute__((unused)) void* ptr) {\n  uvc_frame_t* bgr;\n  uvc_error_t ret;\n  bgr = uvc_allocate_frame(frame->width * frame->height * 3);\n  test_assert(bgr != NULL);\n  ret = uvc_any2bgr(frame, bgr);\n  test_assert(ret == 0);\n  ++frame_count;\n  uvc_free_frame(bgr);\n}\n\nint main(void) {\n  uvc_context_t* ctx;\n  uvc_device_t* dev;\n  uvc_device_handle_t* devh;\n  uvc_stream_ctrl_t ctrl;\n  uvc_error_t res;\n  res = uvc_init(&ctx, NULL);\n  test_assert(res >= 0);\n  atomic_puts(\"UVC initialized\");\n  /* Locates the first attached UVC device, stores in dev */\n  res = uvc_find_device(ctx, &dev, 0, 0, NULL); /* filter devices: vendor_id,\n                                                   product_id, \"serial_num\" */\n  if (res < 0) {\n    atomic_puts(\"No device found\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  atomic_puts(\"Device found\");\n  /* Try to open the device: requires exclusive access */\n  res = uvc_open(dev, &devh);\n  if (res < 0) {\n    atomic_puts(\"Can't open device\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  atomic_puts(\"Device opened\");\n  /* Print out a message containing all the information that libuvc\n   * knows about the device */\n  uvc_print_diag(devh, stdout);\n  /* Try to negotiate a 640x480 30 fps YUYV stream profile */\n  res = uvc_get_stream_ctrl_format_size(\n      devh, &ctrl,           /* result stored in ctrl */\n      UVC_FRAME_FORMAT_YUYV, /* YUV 422, aka YUV 4:2:2. try _COMPRESSED */\n      640, 480, 30           /* width, height, fps */\n      );\n  /* Print out the result */\n  uvc_print_stream_ctrl(&ctrl, stdout);\n  if (res < 0) {\n    atomic_puts(\"No matching stream\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  /* Start the video stream. The library will call user function cb:\n   *   cb(frame, (void*) 12345)\n   */\n  res = uvc_start_streaming(devh, &ctrl, cb, (void*)12345, 0);\n  test_assert(res >= 0);\n  atomic_puts(\"Streaming...\");\n  uvc_set_ae_mode(devh, 1); /* e.g., turn on auto exposure */\n  sleep(2);                 /* stream for 2 seconds */\n  atomic_puts(\"Stopping streaming.\");\n  /* End the stream. Blocks until last callback is serviced */\n  uvc_stop_streaming(devh);\n  atomic_puts(\"Done streaming.\");\n  /* Release our handle on the device */\n  uvc_close(devh);\n  atomic_puts(\"Device closed\");\n  /* Release the device descriptor */\n  uvc_unref_device(dev);\n  /* Close the UVC context. This closes and cleans up any existing device\n   * handles,\n   * and it closes the libusb context if one was not provided. */\n  uvc_exit(ctx);\n  test_assert(frame_count > 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/user_ignore_sig.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handle_usr1(__attribute__((unused)) int sig) {\n  test_assert(\"Shouldn't have caught SIGUSR1\" && 0);\n}\n\nint main(void) {\n  /* NB: unlike most other rr tests, this one verifies that rr\n   * can \"intervene\" in execution to block signals, for the\n   * purposes of unit tests.  This test *will* fail if not run\n   * under rr with the right command-line options. */\n  signal(SIGUSR1, handle_usr1);\n  raise(SIGUSR1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/user_ignore_sig.run",
    "content": "source `dirname $0`/util.sh\n\n# Ignore SIGUSR1; block its delivery to tracees.\nRECORD_ARGS=\"-i10\"\n\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/userfaultfd.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret = syscall(RR_userfaultfd, 0);\n  test_assert(ret == -1 && errno == ENOSYS);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/util.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RRUTIL_H\n#define RRUTIL_H\n\n#define _GNU_SOURCE 1\n#define _POSIX_C_SOURCE 2\n\n/* we assume code in assert() is executed.  */\n#ifdef NDEBUG\n#error The rr testsuite requires NDEBUG to be undefined.\n#endif\n\n/* btrfs needs NULL but doesn't #include it */\n#include <stdlib.h>\n/* need to include sys/mount.h before linux/fs.h */\n#include <sys/mount.h>\n\n#include <arpa/inet.h>\n#include <assert.h>\n#include <ctype.h>\n#include <dirent.h>\n#include <dlfcn.h>\n#include <elf.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <grp.h>\n#include <inttypes.h>\n#include <linux/aio_abi.h>\n#include <linux/audit.h>\n#include <linux/capability.h>\n#include <linux/cdrom.h>\n#include <linux/ethtool.h>\n#include <linux/fb.h>\n#include <linux/fiemap.h>\n#include <linux/filter.h>\n#include <linux/fs.h>\n#include <linux/futex.h>\n#include <linux/if.h>\n#include <linux/if_packet.h>\n#include <linux/if_tun.h>\n#include <linux/kd.h>\n#include <linux/limits.h>\n#include <linux/mtio.h>\n#include <linux/netlink.h>\n#include <linux/perf_event.h>\n#include <linux/personality.h>\n#include <linux/random.h>\n#include <linux/seccomp.h>\n#include <linux/sockios.h>\n#include <linux/unistd.h>\n#include <linux/videodev2.h>\n#include <linux/vt.h>\n#include <linux/wireless.h>\n#ifdef MQUEUE_H\n#include <mqueue.h>\n#endif\n#include <poll.h>\n#include <pthread.h>\n#include <pty.h>\n#include <pwd.h>\n#include <sched.h>\n#include <scsi/sg.h>\n#include <signal.h>\n#include <sound/asound.h>\n#include <stdarg.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <string.h>\n#include <sys/auxv.h>\n#include <sys/epoll.h>\n#include <sys/eventfd.h>\n#ifdef FANOTIFY_H\n#include <sys/fanotify.h>\n#endif\n#include <sys/file.h>\n#include <sys/fsuid.h>\n#include <sys/inotify.h>\n#include <sys/ioctl.h>\n#include <sys/ipc.h>\n#include <sys/mman.h>\n#include <sys/mount.h>\n#include <sys/msg.h>\n#include <sys/prctl.h>\n#include <sys/ptrace.h>\n#include <sys/quota.h>\n#include <sys/resource.h>\n#include <sys/select.h>\n#include <sys/sem.h>\n#include <sys/sendfile.h>\n#include <sys/shm.h>\n#include <sys/signalfd.h>\n#include <sys/socket.h>\n#include <sys/stat.h>\n#include <sys/sysinfo.h>\n#include <sys/sysmacros.h>\n#include <sys/time.h>\n#include <sys/timerfd.h>\n#include <sys/times.h>\n#include <sys/types.h>\n#include <sys/ucontext.h>\n#include <sys/uio.h>\n#include <sys/un.h>\n#include <sys/user.h>\n#include <sys/utsname.h>\n#include <sys/vfs.h>\n#include <sys/wait.h>\n#include <sys/xattr.h>\n#include <syscall.h>\n#include <termios.h>\n#include <time.h>\n#include <ucontext.h>\n#include <unistd.h>\n#include <utime.h>\n\n// X86 specific headers\n#if defined(__i386__) || defined(__x86_64__)\n#include <asm/prctl.h>\n#include <x86intrin.h>\n#endif\n\n#include <rr/rr.h>\n\n#include \"util_syscall.h\"\n\ntypedef unsigned char uint8_t;\n\n#define ALEN(_a) (sizeof(_a) / sizeof(_a[0]))\n\n#ifndef SOL_NETLINK\n#define SOL_NETLINK 270\n#endif\n\n/**\n * Allocate new memory of |size| in bytes. The pointer returned is never NULL.\n * This calls aborts the program if the host runs out of memory.\n */\ninline static void* xmalloc(size_t size) {\n  void* mem_ptr = malloc(size);\n  if (!mem_ptr) {\n    abort();\n  }\n  return mem_ptr;\n}\n\n/**\n * Print the printf-like arguments to stdout as atomic-ly as we can\n * manage.  Async-signal-safe.  Does not flush stdio buffers (doing so\n * isn't signal safe).\n */\n__attribute__((format(printf, 1, 2))) inline static int atomic_printf(\n    const char* fmt, ...) {\n  va_list args;\n  char buf[1024];\n  int len;\n\n  va_start(args, fmt);\n  len = vsnprintf(buf, sizeof(buf) - 1, fmt, args);\n  va_end(args);\n  return write(STDOUT_FILENO, buf, len);\n}\n\n/**\n * Write |str| on its own line to stdout as atomic-ly as we can\n * manage.  Async-signal-safe.  Does not flush stdio buffers (doing so\n * isn't signal safe).\n */\ninline static int atomic_puts(const char* str) {\n  return atomic_printf(\"%s\\n\", str);\n}\n\n#define fprintf(...) USE_dont_write_stderr\n#define printf(...) USE_atomic_printf_INSTEAD\n#define puts(...) USE_atomic_puts_INSTEAD\n\ninline static int atomic_assert(int cond, const char *str,\n\t\t\t\tconst char *file, const int line) {\n  if (!cond) {\n    atomic_printf(\"FAILED at %s:%d: !(%s) errno:%d (%s)\\n\", file, line, str,\n\t\t  errno, strerror(errno));\n    raise(SIGABRT);\n  }\n  return 1;\n}\n\n#define test_assert(cond) atomic_assert(cond, #cond, __FILE__, __LINE__)\n\n/**\n * Return the calling task's id.\n */\ninline static pid_t sys_gettid(void) { return syscall(SYS_gettid); }\n\n/**\n * get the current cpu/node\n */\ninline static int sys_getcpu(unsigned int* cpu, unsigned int* node) {\n  /* The 'tcache' parameter is unused in all kernels rr works on */\n  return syscall(SYS_getcpu, cpu, node, (void*)0);\n}\n\n/**\n * Ensure that |len| bytes of |buf| are the same across recording and\n * replay.\n */\ninline static void check_data(void* buf, size_t len) {\n  ssize_t ret = syscall(SYS_write, RR_MAGIC_SAVE_DATA_FD, buf, len);\n  if (ret == -1 && errno == EBADF) {\n    atomic_printf(\"Failed to write to RR_MAGIC_SAVE_DATA_FD. Not running under rr?\\n\");\n  } else {\n    test_assert(ret == (ssize_t)len);\n    atomic_printf(\"Wrote %zu bytes to magic fd\\n\", len);\n  }\n}\n\n#if defined(__i386__) || defined(__x86_64)\n/**\n * Return the current value of the time-stamp counter.\n */\ninline static uint64_t rdtsc(void) { return __rdtsc(); }\n#endif\n\ninline static void trigger_timer_counter_trap(void) {\n#if defined(__i386__) || defined(__x86_64)\n  rdtsc();\n#elif defined(__aarch64__)\n  __asm__ __volatile__(\"mrs xzr, cntvct_el0\");\n#else\n#error \"Unknown architecture\"\n#endif\n}\n\n/**\n * Perform some syscall that writes an event, i.e. is not syscall-buffered.\n */\ninline static void event_syscall(void) { syscall(-1); }\n\nstatic uint64_t GUARD_VALUE = 0xdeadbeeff00dbaad;\n\ninline static size_t ceil_page_size(size_t size) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  return (size + page_size - 1) & ~(page_size - 1);\n}\n\n#if defined(__i386__) || defined(__x86_64)\n#define debug_trap() __asm__(\"int $3\")\n#define undefined_instr() __asm__(\"ud2\")\n#elif defined(__aarch64__)\n#define debug_trap() __asm__(\"brk #0\")\n/**\n * GCC emits `brk #1000` for __builtin_trap,\n * Clang emits `brk #1` for the same.\n * It appears there was some plans early on to generate\n * SIGILL for breakpoint instructions with a high immediate,\n * but that never materialized. Instead, to get SIGILL, we use\n * an mrs instruction, which will cause SIGILL if the system\n * register used isn't accessible in EL0. Which register we\n * use doesn't matter here, but we should one that is neither\n * unused and might do something else in the future, nor one\n * that the kernel or a hypervisor might emulate in the future.\n * Here we use `S3_6_C15_C8_0` which is a microcode patching\n * register and only available in EL3. Accessing it here\n * should always cause SIGILL\n */\n#define undefined_instr() __asm__(\"mrs x0, S3_6_C15_C8_0\")\n#else\n#error \"Unknown architecture\"\n#endif\n\n/**\n * Allocate 'size' bytes, fill with 'value', place canary value before\n * the allocated block, and put guard pages before and after. Ensure\n * there's a guard page immediately after `size`.\n * This lets us catch cases where too much data is being recorded --- which can\n * cause errors if the recorder tries to read invalid memory.\n */\ninline static void* allocate_guard(size_t size, char value) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  size_t map_size = ceil_page_size(size + sizeof(GUARD_VALUE)) + 2 * page_size;\n  char* cp = (char*)mmap(NULL, map_size, PROT_READ | PROT_WRITE,\n                         MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(cp != MAP_FAILED);\n  /* create guard pages */\n  test_assert(munmap(cp, page_size) == 0);\n  test_assert(munmap(cp + map_size - page_size, page_size) == 0);\n  cp = cp + map_size - page_size - size;\n  memcpy(cp - sizeof(GUARD_VALUE), &GUARD_VALUE, sizeof(GUARD_VALUE));\n  memset(cp, value, size);\n  return cp;\n}\n\n/**\n * Verify that canary value before the block allocated at 'p'\n * (of size 'size') is still valid.\n */\ninline static void verify_guard(__attribute__((unused)) size_t size, void* p) {\n  int tmp_errno = errno;\n  char* cp = (char*)p;\n  test_assert(\n      memcmp(cp - sizeof(GUARD_VALUE), &GUARD_VALUE, sizeof(GUARD_VALUE)) == 0);\n\n  /* Create a \"checksum\" from the memory and get it checked at syscall boundary. */\n  int verify_guard_checksum = 0;\n  for (size_t i = 0; i < size; i++) {\n      verify_guard_checksum += ((unsigned char*)p)[i];\n  }\n  syscall(-1, verify_guard_checksum);\n  errno = tmp_errno;\n}\n\n/**\n * Verify that canary value before the block allocated at 'p'\n * (of size 'size') is still valid, and free the block.\n */\ninline static void free_guard(size_t size, void* p) {\n  verify_guard(size, p);\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  size_t map_size = ceil_page_size(size + sizeof(GUARD_VALUE)) + 2 * page_size;\n  char* cp = (char*)p + size + page_size - map_size;\n  test_assert(0 == munmap(cp, map_size - 2 * page_size));\n}\n\ninline static void crash_null_deref(void) { *(volatile int*)NULL = 0; }\n\ninline static void chdir_nontmp_workdir(void) {\n  const char* nontmp_workdir = getenv(\"NONTMP_WORKDIR\");\n  test_assert(nontmp_workdir && \"NONTMP_WORKDIR environment variable not set\");\n  /* Could be the empty string if the original directory from which tests were run\n     is a read-only directory */\n  if (*nontmp_workdir) {\n    test_assert(chdir(nontmp_workdir) == 0);\n  }\n}\n\nstatic char* trim_leading_blanks(char* str) {\n  char* trimmed = str;\n  while (isblank(*trimmed)) {\n    ++trimmed;\n  }\n  return trimmed;\n}\n\ntypedef struct map_properties {\n  uint64_t start, end, offset, inode;\n  int dev_major, dev_minor;\n  char flags[32];\n} map_properties_t;\ntypedef void (*maps_callback)(uint64_t env, char* name,\n                              map_properties_t* props);\ninline static void iterate_maps(uint64_t env, maps_callback callback,\n                                FILE* maps_file) {\n  while (!feof(maps_file)) {\n    char line[PATH_MAX * 2];\n    if (!fgets(line, sizeof(line), maps_file)) {\n      break;\n    }\n\n    map_properties_t properties;\n    int chars_scanned;\n    int nparsed = sscanf(\n        line, \"%\" SCNx64 \"-%\" SCNx64 \" %31s %\" SCNx64 \" %x:%x %\" SCNu64 \" %n\",\n        &properties.start, &properties.end, properties.flags,\n        &properties.offset, &properties.dev_major, &properties.dev_minor,\n        &properties.inode, &chars_scanned);\n    assert(8 /*number of info fields*/ == nparsed ||\n           7 /*num fields if name is blank*/ == nparsed);\n\n    // trim trailing newline, if any\n    int last_char = strlen(line) - 1;\n    if (line[last_char] == '\\n') {\n      line[last_char] = 0;\n    }\n    char* name = trim_leading_blanks(line + chars_scanned);\n\n    callback(env, name, &properties);\n  }\n}\n\n/**\n * Represents syscall params.  Makes it simpler to pass them around,\n * and avoids pushing/popping all the data for calls.\n */\nstruct syscall_info {\n  long no;\n  long args[6];\n};\n\ntypedef void (*SyscallWrapper)(struct syscall_info* info);\n\ninline static void default_syscall_wrapper(struct syscall_info* info) {\n  syscall(info->no, info->args[0], info->args[1], info->args[2], info->args[3],\n          info->args[4], info->args[5]);\n}\n\n/**\n * Returns a function which will execute a syscall after spending a long time\n * stuck in syscallbuf code doing nothing. Returns NULL\n */\ninline static SyscallWrapper get_delayed_syscall(void) {\n  SyscallWrapper ret = (SyscallWrapper)dlsym(RTLD_DEFAULT, \"delayed_syscall\");\n  return ret ? ret : default_syscall_wrapper;\n}\n\n/**\n * Returns a function which will execute a syscall after spending a long time\n * stuck in syscallbuf code doing nothing. Returns NULL\n */\ninline static SyscallWrapper get_spurious_desched_syscall(void) {\n  SyscallWrapper ret =\n      (SyscallWrapper)dlsym(RTLD_DEFAULT, \"spurious_desched_syscall\");\n  return ret ? ret : default_syscall_wrapper;\n}\n\n/* Old systems don't have these functions, re-define using the syscall */\n#define tgkill(tgid, tid, sig) \\\n  syscall(SYS_tgkill, (int)(tgid), (int)(tid), (int)(sig))\n\n#define ALLOCATE_GUARD(p, v) p = allocate_guard(sizeof(*p), v)\n#define VERIFY_GUARD(p) verify_guard(sizeof(*p), p)\n#define FREE_GUARD(p) free_guard(sizeof(*p), p)\n\n#ifndef SECCOMP_SET_MODE_STRICT\n#define SECCOMP_SET_MODE_STRICT 0\n#endif\n#ifndef SECCOMP_SET_MODE_FILTER\n#define SECCOMP_SET_MODE_FILTER 1\n#endif\n#ifndef SECCOMP_FILTER_FLAG_TSYNC\n#define SECCOMP_FILTER_FLAG_TSYNC 1\n#endif\n#ifndef SECCOMP_GET_ACTION_AVAIL\n#define SECCOMP_GET_ACTION_AVAIL 2\n#endif\n#ifndef SECCOMP_GET_NOTIF_SIZES\n#define SECCOMP_GET_NOTIF_SIZES 3\n#endif\n\n/* Old systems don't have linux/kcmp.h */\n#define RR_KCMP_FILE 0\n#define RR_KCMP_FILES 2\n\n/* Old systems don't have linux/openat2.h */\nstruct rr_open_how {\n\t__u64 flags;\n\t__u64 mode;\n\t__u64 resolve;\n};\n#define RESOLVE_BENEATH\t0x08\n\n/* Old systems don't have these */\n#ifndef TIOCGPKT\n#define TIOCGPKT _IOR('T', 0x38, int)\n#endif\n#ifndef TIOCGPTLCK\n#define TIOCGPTLCK _IOR('T', 0x39, int)\n#endif\n#ifndef TIOCGEXCL\n#define TIOCGEXCL _IOR('T', 0x40, int)\n#endif\n#ifndef TIOCGPTPEER\n#define TIOCGPTPEER _IO('T', 0x41)\n#endif\n\n#ifndef MADV_FREE\n#define MADV_FREE 8\n#endif\n#ifndef MADV_DONTDUMP\n#define MADV_DONTDUMP 16\n#endif\n#ifndef MADV_DODUMP\n#define MADV_DODUMP 17\n#endif\n#ifndef MADV_WIPEONFORK\n#define MADV_WIPEONFORK 18\n#endif\n#ifndef MADV_KEEPONFORK\n#define MADV_KEEPONFORK 19\n#endif\n#ifndef MADV_SOFT_OFFLINE\n#define MADV_SOFT_OFFLINE 101\n#endif\n#ifndef MADV_COLD\n#define MADV_COLD 20\n#endif\n#ifndef MADV_PAGEOUT\n#define MADV_PAGEOUT 21\n#endif\n#ifndef MADV_POPULATE_READ\n#define MADV_POPULATE_READ 22\n#endif\n#ifndef MADV_POPULATE_WRITE\n#define MADV_POPULATE_WRITE 23\n#endif\n#ifndef MADV_DONTNEED_LOCKED\n#define MADV_DONTNEED_LOCKED 24\n#endif\n#ifndef MADV_COLLAPSE\n#define MADV_COLLAPSE 25\n#endif\n#ifndef MADV_GUARD_INSTALL\n#define MADV_GUARD_INSTALL 102\n#endif\n#ifndef MADV_GUARD_REMOVE\n#define MADV_GUARD_REMOVE 103\n#endif\n\n#ifndef F_OFD_GETLK\n#define F_OFD_GETLK 36\n#endif\n#ifndef F_OFD_SETLK\n#define F_OFD_SETLK 37\n#endif\n\n#ifndef PR_CAP_AMBIENT\n#define PR_CAP_AMBIENT 47\n#endif\n#ifndef PR_CAP_AMBIENT_IS_SET\n#define PR_CAP_AMBIENT_IS_SET 1\n#endif\n#ifndef PR_CAP_AMBIENT_RAISE\n#define PR_CAP_AMBIENT_RAISE 2\n#endif\n#ifndef PR_CAP_AMBIENT_LOWER\n#define PR_CAP_AMBIENT_LOWER 3\n#endif\n#ifndef PR_CAP_AMBIENT_CLEAR_ALL\n#define PR_CAP_AMBIENT_CLEAR_ALL 4\n#endif\n\n#ifndef PR_GET_SPECULATION_CTRL\n#define PR_GET_SPECULATION_CTRL 52\n#endif\n#ifndef PR_SET_SPECULATION_CTRL\n#define PR_SET_SPECULATION_CTRL 53\n#endif\n#ifndef PR_SPEC_STORE_BYPASS\n#define PR_SPEC_STORE_BYPASS 0\n#endif\n#ifndef PR_SPEC_NOT_AFFECTED\n#define PR_SPEC_NOT_AFFECTED 0\n#endif\n#ifndef PR_SPEC_PRCTL\n#define PR_SPEC_PRCTL 1\n#endif\n#ifndef PR_SPEC_ENABLE\n#define PR_SPEC_ENABLE 2\n#endif\n#ifndef PR_SPEC_DISABLE\n#define PR_SPEC_DISABLE 4\n#endif\n#ifndef PR_SPEC_FORCE_DISABLE\n#define PR_SPEC_FORCE_DISABLE 8\n#endif\n#ifndef PR_SET_VMA\n#define PR_SET_VMA 0x53564d41\n#endif\n#ifndef PR_SET_VMA_ANON_NAME\n#define PR_SET_VMA_ANON_NAME 0\n#endif\n#ifndef PR_GET_MDWE\n#define PR_GET_MDWE 66\n#endif\n#ifndef PR_GET_AUXV\n#define PR_GET_AUXV 0x41555856\n#endif\n\n#ifndef BLKGETDISKSEQ\n#define BLKGETDISKSEQ _IOR(0x12,128,__u64)\n#endif\n\n#ifndef MREMAP_DONTUNMAP\n#define MREMAP_DONTUNMAP 4\n#endif\n\nstruct rseq {\n  uint32_t cpu_id_start;\n  uint32_t cpu_id;\n  uint64_t rseq_cs;\n  uint32_t flags;\n} __attribute__((aligned(32)));\n\nstruct rseq_cs {\n  uint32_t version;\n  uint32_t flags;\n  uint64_t start_ip;\n  uint64_t post_commit_offset;\n  uint64_t abort_ip;\n} __attribute__((aligned(32)));\n\nenum {\n  RR_BPF_MAP_CREATE,\n  RR_BPF_MAP_LOOKUP_ELEM,\n  RR_BPF_MAP_UPDATE_ELEM,\n  RR_BPF_MAP_DELETE_ELEM,\n  RR_BPF_MAP_GET_NEXT_KEY,\n  RR_BPF_PROG_LOAD,\n  RR_BPF_OBJ_PIN,\n  RR_BPF_OBJ_GET,\n  RR_BPF_PROG_ATTACH,\n  RR_BPF_PROG_DETACH,\n  RR_BPF_PROG_TEST_RUN,\n  RR_BPF_PROG_GET_NEXT_ID,\n  RR_BPF_MAP_GET_NEXT_ID,\n  RR_BPF_PROG_GET_FD_BY_ID,\n  RR_BPF_MAP_GET_FD_BY_ID,\n  RR_BPF_OBJ_GET_INFO_BY_FD,\n  RR_BPF_PROG_QUERY,\n  RR_BPF_RAW_TRACEPOINT_OPEN,\n  RR_BPF_BTF_LOAD,\n  RR_BPF_BTF_GET_FD_BY_ID,\n  RR_BPF_TASK_FD_QUERY,\n  RR_BPF_MAP_LOOKUP_AND_DELETE_ELEM,\n  RR_BPF_MAP_FREEZE,\n  RR_BPF_BTF_GET_NEXT_ID,\n  RR_BPF_MAP_LOOKUP_BATCH,\n  RR_BPF_MAP_LOOKUP_AND_DELETE_BATCH,\n  RR_BPF_MAP_UPDATE_BATCH,\n  RR_BPF_MAP_DELETE_BATCH,\n  RR_BPF_LINK_CREATE,\n  RR_BPF_LINK_UPDATE,\n  RR_BPF_LINK_GET_FD_BY_ID,\n  RR_BPF_LINK_GET_NEXT_ID,\n  RR_BPF_ENABLE_STATS,\n  RR_BPF_ITER_CREATE,\n  RR_BPF_LINK_DETACH,\n  RR_BPF_PROG_BIND_MAP,\n  RR_BPF_TOKEN_CREATE,\n};\n\n#ifndef FSCONFIG_CMD_CREATE\n#define FSCONFIG_CMD_CREATE 6\n#endif\n#ifndef MOVE_MOUNT_F_EMPTY_PATH\n#define MOVE_MOUNT_F_EMPTY_PATH 0x00000004\n#endif\n\n#endif /* RRUTIL_H */\n"
  },
  {
    "path": "src/test/util.py",
    "content": "import pexpect, re, signal, sys, time, os\n\n__all__ = [ 'expect_rr', 'expect_list', 'expect_debugger',\n            'restart_replay', 'interrupt_gdb', 'expect_gdb', 'send_gdb',\n            'ok', 'failed', 'iterlines_both', 'last_match', 'get_exe_arch',\n            'get_gdb_version', 'breakpoint_at_function',\n            'watchpoint_at_address', 'cont', 'backtrace', 'up',\n            'expect_breakpoint_stop', 'expect_watchpoint_stop',\n            'expect_history_end', 'history_end_regex',\n            'delete_watchpoint', 'expect_signal_stop',\n            'set_breakpoint_commands', 'select_thread',\n            'scheduler_locking_on', 'scheduler_locking_off',\n            'expect_expression', 'expect_threads',\n            'send_custom_command', 'stepi', 'watchpoint_at_address_fail' ]\n\n# Don't use python timeout. Use test-monitor timeout instead.\nTIMEOUT_SEC = 10000\n# The debugger and rr are part of the same process tree, so they share\n# stdin/stdout.\nchild = None\ndebugger_type = 'GDB'\n\n# Public API\ndef expect_debugger(what):\n    expect(child, what)\n\ndef expect_list(pats):\n    return child.expect_list(pats)\n\ndef expect_rr(what):\n    expect(child, what)\n\ndef failed(why, e=None):\n    print('FAILED:', why)\n    if e:\n        print('exception:', e)\n    clean_up()\n    sys.exit(1)\n\ndef interrupt_debugger():\n    try:\n        child.kill(signal.SIGINT)\n    except Exception as e:\n        failed('interrupting debugger', e)\n    expect_gdb('stopped.')\n\ndef iterlines_both():\n    return child\n\ndef last_match():\n    return child.match\n\ndef expect_gdb(what):\n    assert debugger_type == 'GDB'\n    expect_debugger(what)\n\ndef interrupt_gdb():\n    assert debugger_type == 'GDB'\n    interrupt_debugger()\n\ndef send_gdb(what):\n    assert debugger_type == 'GDB'\n    send(child, f'{what}\\n')\n\ndef send_lldb(what):\n    assert debugger_type == 'LLDB'\n    send(child, f'{what}\\n')\n\n# Restarts and continues execution\ndef restart_replay(event=0):\n    if event:\n        send_gdb('r %d'%(event))\n    else:\n        send_gdb('r')\n    # gdb may not prompt here. It's ok to send an unnecessary 'y'\n    # since there is no such command.\n    send_gdb('y')\n    # Wait to see 'stopped'. We don't want this to get buffered up\n    # so callers expecting a 'stopped' *after* replay has resumed\n    # get confused.\n    expect_rr('stopped')\n    send_gdb('c')\n\ndef breakpoint_at_function(function):\n    send_debugger(f'break {function}', f'breakpoint set --name {function}')\n    expect_debugger(r'Breakpoint (\\d+)')\n    return int(last_match().group(1))\n\nsize_to_type = {1: 'char', 2:'short', 4:'int', 8:'long long'}\n\ndef watchpoint_at_address(address, size):\n    send_debugger(f'watch -l *({size_to_type[size]}*)({address})',\n                  f'watchpoint set expression -s {size} -- ({address})')\n    expect_debugger(r'atchpoint (\\d+)')\n    return int(last_match().group(1))\n\ndef watchpoint_at_address_fail(address, size):\n    send_debugger(f'watch -l *({size_to_type[size]}*)({address})',\n                  f'watchpoint set expression -s {size} -- ({address})')\n    if debugger_type == 'GDB':\n        expect_debugger(r'atchpoint (\\d+)')\n        wp = int(last_match().group(1))\n        # Force watchpoint allocation\n        send_gdb('stepi')\n        expect_debugger(r'not insert hardware watchpoint')\n        send_gdb(f'delete {wp}')\n    else:\n        expect_debugger(r'creation failed')\n\ndef delete_watchpoint(watchpoint):\n    send_debugger(f'delete {watchpoint}', f'watchpoint delete {watchpoint}')\n\ndef cont():\n    send_debugger('continue', 'continue')\n\ndef stepi():\n    send_debugger('stepi', 'stepi')\n\ndef up():\n    send_debugger('up', 'up')\n\ndef backtrace():\n    send_debugger('bt', 'thread backtrace')\n\ndef history_end_regex():\n    if debugger_type == 'GDB':\n        return 'No more reverse-execution history|Reached end of recorded history'\n    else:\n        # Add LLDB case\n        assert False\n\ndef expect_history_end():\n    expect_debugger(history_end_regex())\n\ndef expect_breakpoint_stop(number):\n    if debugger_type == 'GDB':\n        expect_debugger(f'Breakpoint {number}')\n    else:\n        expect_debugger(f'stop reason = breakpoint {number}')\n\ndef expect_watchpoint_stop(number):\n    if debugger_type == 'GDB':\n        expect_debugger(f'atchpoint {number}')\n    else:\n        expect_debugger(f'stop reason = watchpoint {number}')\n\ndef expect_signal_stop(signal_name):\n    if debugger_type == 'GDB':\n        expect_debugger(f'received signal {signal_name}')\n    else:\n        expect_debugger(f'received signal: {signal_name}')\n\ndef set_breakpoint_commands(number, commands):\n    if debugger_type == 'GDB':\n        send_gdb(f'commands {number}')\n        for command in commands:\n            send_gdb(command)\n        send_gdb('end')\n    else:\n        send_lldb(f'breakpoint command add {number}')\n        expect_debugger('Enter your debugger command')\n        for command in commands:\n            send_lldb(command)\n        send_lldb('DONE')\n        expect_debugger('(rr)')\n\ndef expect_expression(expression, value):\n    send_debugger(f'print {expression}', f'expression -- {expression}')\n    expect_debugger(f' = {value}')\n\ndef expect_threads(num_threads, selected_thread):\n    send_debugger('info threads', 'thread list')\n    for i in range(1, num_threads + 1):\n        selected = r'\\*' if i == selected_thread else ''\n        if debugger_type == 'GDB':\n            expect_debugger(f'{selected} +{i} ')\n        else:\n            expect_debugger(f'{selected} +thread #{i}:')\n\ndef select_thread(index):\n    if debugger_type == 'GDB':\n        send_gdb(f'thread {index}')\n        expect_debugger(f'Switching to thread {index} ')\n    else:\n        send_lldb(f'thread select {index}')\n        expect_debugger(f'thread #{index}')\n\ndef scheduler_locking_on():\n    if debugger_type == 'GDB':\n        send_gdb('set scheduler-locking on')\n\ndef scheduler_locking_off():\n    if debugger_type == 'GDB':\n        send_gdb('set scheduler-locking off')\n\ndef send_custom_command(cmd):\n    send_debugger(cmd, cmd)\n\ndef send_debugger(gdb_cmd, lldb_cmd):\n    if debugger_type == 'GDB':\n        send_gdb(gdb_cmd)\n    else:\n        send_lldb(lldb_cmd)\n\ndef ok():\n    send_debugger('quit', 'quit')\n    send_debugger('y', 'y')\n    clean_up()\n\ndef get_exe_arch():\n    send_gdb('show architecture')\n    expect_gdb(r'The target architecture is set (automatically|to \"auto\") \\(currently \"?([0-9a-z:-]+)\"?\\)\\.?')\n    global child\n    return child.match.group(2)\n\ndef get_gdb_version():\n    '''Return the gdb version'''\n    send_gdb('python print(gdb.VERSION)')\n    expect_gdb(r'(\\d+.\\d+)')\n    global child\n    return float(child.match.group(1))\n\n# Internal helpers\ndef clean_up():\n    global child\n    iterations = 0\n    while child:\n        try:\n            # FIXME: without this sleep python freezes instead of exiting.\n            # The sleep has to be before BufferedRWPair.close()\n            time.sleep(0.1)\n            child.close(force=1)\n            child = None\n        except Exception as e:\n            if iterations < 5:\n                print(f'close() failed with \"{e}\", retrying...')\n                iterations = iterations + 1\n            else:\n                child = None\n\ndef expect(prog, what):\n    try:\n        prog.expect(what)\n    except Exception as e:\n        failed(f'expecting \"{what}\"', e)\n\ndef send(prog, what):\n    try:\n        prog.send(what)\n    except Exception as e:\n        failed(f'sending \"{what}\"', e)\n\ndef set_up():\n    global child\n    global debugger_type\n    args = sys.argv[1:]\n    log_file = 'gdb_rr.log'\n    if args[0] == '--lldb':\n        debugger_type = 'LLDB'\n        args = args[1:] + ['-d', 'lldb', '-o', '--no-use-colors']\n        log_file = 'lldb_rr.log'\n    try:\n        child = pexpect.spawn(args[0], args[1:], codec_errors='ignore',\n            timeout=TIMEOUT_SEC, encoding='utf-8', logfile=open(log_file, 'w'))\n        child.delaybeforesend = 0\n        expect_debugger(r'\\(rr\\)')\n        if debugger_type == 'LLDB':\n            script = os.environ[\"TESTDIR\"] + \"/test_setup.lldb\"\n            send_lldb(f'command source -s 0 {script}')\n    except Exception as e:\n        failed('initializing rr and debugger', e)\n\nset_up()\n"
  },
  {
    "path": "src/test/util.sh",
    "content": "#\n# This file is included by foo.run test-driver files.  It provides\n# some helpers for common test operations.  A driver file foo.run\n# will want to include this file as follows\n#\n#  source `dirname $0`/util.sh\n#\n# It is essential that util.sh inherit its $n parameters from the\n# driver script's parameters.\n#\n# Most tests are either \"compare_test\"s, which check that record and\n# replay successfully complete and the output is the same, or,\n# \"debug_test\"s, which launch a debugger script.  So the remainder of\n# your test runner probably looks like\n#\n#  compare_test  # or, |debug_test|\n#\n# Test runners may set the environment variable $RECORD_ARGS to pass\n# arguments to rr for recording.  This is only useful for tweaking the\n# scheduler, don't use it for anything else.\n#\n\nif ! which pidof &> /dev/null; then\n    pidof() {\n        ps ax -o 'pid= exe=' | grep ' \\(\\|.*/\\)'\"$1\"'$' | awk '{print $1}'\n    }\nfi\n\n#  delay_kill <sig> <delay_secs> <proc>\n#\n# Deliver the signal |sig|, after waiting |delay_secs| seconds, to the\n# process named |proc|.  If there's more than |proc|, the signal is\n# not delivered.\nfunction delay_kill { sig=$1; delay_secs=$2; proc=$3\n    sleep $delay_secs\n\n    pid=\"\"\n    for i in `seq 1 5`; do\n        live=`ps ax -o 'pid= cmd=' | awk '{print $1 \" \" $2}' | grep $proc`\n        num=`echo \"$live\" | wc -l`\n        if [[ \"$num\" -eq 1 ]]; then\n            pid=`echo \"$live\" | awk '{print $1}'`\n            break\n        fi\n        sleep 0.1\n    done\n\n    if [[ \"$num\" -gt 1 ]]; then\n        test_passed=n\n        echo FAILED: \"$num\" of \"'$proc'\" >&2\n        exit 1\n    elif [[ -z \"$pid\" ]]; then\n        test_passed=n\n        echo FAILED: process \"'$proc'\" not located >&2\n        exit 1\n    fi\n\n    # Wait for the test to print \"ready\", indicating it has completed\n    # any required setup.\n    until grep -q ready record.out; do\n        sleep 0\n    done\n\n    kill -s $sig $pid\n    if [[ $? != 0 ]]; then\n        # Sometimes we fail to deliver a signal to a process because\n        # it finished first (due to scheduling races). That's a benign\n        # failure.\n        echo signal $sig not delivered to \"'$proc'\", letting test succeed anyway\n    else\n        echo Successfully delivered signal $sig to \"'$proc'\"\n    fi\n}\n\nfunction fatal { #...\n    echo \"$@\" >&2\n    exit 1\n}\n\nfunction onexit {\n    cd\n    if [[ \"$test_passed\" == \"y\" ]]; then\n        if [[ \"$tmp_workdir\" != \"\" ]]; then\n            rm -rf $tmp_workdir\n        fi\n        if [[ \"$nontmp_workdir\" != \"\" ]]; then\n            rm -rf $nontmp_workdir\n        fi\n    else\n        echo -n Test $TESTNAME failed, leaving behind $tmp_workdir\n        (rmdir \"$nontmp_workdir\" 2>/dev/null && echo) || echo \" and $nontmp_workdir\"\n        echo To replay the failed test, run\n        echo \" \" _RR_TRACE_DIR=\"$workdir\" rr replay\n        exit 1\n    fi\n}\n\nfunction parent_pid_of { pid=$1\n    ps -p $pid -o ppid=\n}\n\nfunction usage {\n    echo Usage: \"util.sh TESTNAME [LIB_ARG] [OBJDIR]\"\n}\n\nGLOBAL_OPTIONS=\"--suppress-environment-warnings --fatal-errors\"\nif [[ \"$NO_CHECK_CACHED_MMAP\" == \"\" ]]; then\n    GLOBAL_OPTIONS=\"${GLOBAL_OPTIONS} --check-cached-mmaps\"\nfi\n\nSRCDIR=`dirname ${BASH_SOURCE[0]}`/../..\nSRCDIR=`realpath $SRCDIR`\n\nTESTNAME=$1\nif [[ \"$TESTNAME\" == \"\" ]]; then\n    [[ $0 =~ ([A-Za-z0-9_]+)\\.run$ ]] || fatal \"FAILED: bad test script name\"\n    TESTNAME=${BASH_REMATCH[1]}\nfi\nif [[ $TESTNAME =~ ([A-Za-z0-9_]+)_32$ ]]; then\n    bitness=_32\n    TESTNAME_NO_BITNESS=${BASH_REMATCH[1]}\nelse\n    TESTNAME_NO_BITNESS=$TESTNAME\nfi\n\n# We may want to retrieve this from python\nexport TESTNAME=$TESTNAME\n\nLIB_ARG=$2\nOBJDIR=$3\nif [[ \"$OBJDIR\" == \"\" ]]; then\n    # Default to assuming that the user's working directory is the\n    # src/test/ directory within the rr clone.\n    OBJDIR=\"$SRCDIR/../obj\"\nfi\nif [[ ! -d \"$OBJDIR\" ]]; then\n    fatal \"FAILED: objdir missing\"\nfi\nOBJDIR=`realpath $OBJDIR`\nTIMEOUT=$4\nif [[ \"$TIMEOUT\" == \"\" ]]; then\n    TIMEOUT=120\nfi\n\n# The temporary directory we create for this test run.\nworkdir=\n# A temporary directory likely to be in a tmpfs. Usually same as 'workdir'.\ntmp_workdir=\n# Another temporary directory that we created for this test run, in a real\n# (non-tmpfs) filesystem if possible. It might be empty or still in a tmpfs.\nnontmp_workdir=\n# Did the test pass?  If not, then we'll leave the recording and\n# output around for developers to debug, and exit with a nonzero\n# exit code.\ntest_passed=y\n# The unique ID allocated to this test directory.\nnonce=\n\n# Set up the environment and working directory.\nexport TESTDIR=\"${SRCDIR}/src/test\"\n\n# Make rr treat temp files as durable. This saves copying all test\n# binaries into the trace.\nexport RR_TRUST_TEMP_FILES=1\n\n# Have rr processes coordinate to not oversubscribe CPUs\nexport _RR_CPU_LOCK_FILE=\"/tmp/rr-test-cpu-lock\"\n\n# Set options to find rr and resource files in the expected places.\nexport PATH=\"${OBJDIR}/bin:${PATH}\"\n\n# Resource path is normally the same as the build directory, however, it is\n# slightly different when using the installable testsuite. The installable\n# testsuite will look for resources under DESTDIR/CMAKE_INSTALL_PREFIX. We\n# can detect if it's the installable testsuite being run by checking if the\n# rr binary exists in the build directory.\nif [[ -f \"$OBJDIR/bin/rr\" ]]; then\n    RESOURCE_PATH=$OBJDIR\nelse\n    # The resources are located at DESTDIR/CMAKE_INSTALL_PREFIX. We don't have\n    # access to these variables while running the testsuite. However, OBJDIR is\n    # set as DESTDIR/CMAKE_INSTALL_PREFIX/CMAKE_INSTALL_LIBDIR/rr/testsuite/obj.\n    # We can use this to locate the resources by going up exactly 4 directories.\n    RESOURCE_PATH=`realpath $OBJDIR/../../../..`\nfi\n\nGLOBAL_OPTIONS=\"${GLOBAL_OPTIONS} --resource-path=${RESOURCE_PATH}\"\n\nwhich rr >/dev/null 2>&1\nif [[ \"$?\" != \"0\" ]]; then\n    fatal FAILED: rr not found in PATH \"($PATH)\"\nfi\n\nif [[ ! -d $SRCDIR ]]; then\n    fatal FAILED: SRCDIR \"($SRCDIR)\" not found. objdir and srcdir must share the same parent.\nfi\n\nif [[ ! -d $TESTDIR ]]; then\n    fatal FAILED: TESTDIR \"($TESTDIR)\" not found.\nfi\n\nRR_EXE=rr\n\n# Our test programs intentionally crash a lot. Don't generate coredumps for them.\nulimit -c 0\n\n# NB: must set up the trap handler *before* mktemp\ntrap onexit EXIT\nworkdir=`mktemp -dt rr-test-$TESTNAME-XXXXXXXXX`\ntmp_workdir=$workdir\nnontmp_workdir=`mktemp -p $PWD -dt rr-test-$TESTNAME-XXXXXXXXX`\ncd $workdir\n# NB: the testsuite should run on any system with different settings,\n#     so create a reasonable default for all tests\nexport LC_ALL=C\n\n# XXX technically the trailing -XXXXXXXXXX isn't unique, since there\n# could be \"foo-123456789\" and \"bar-123456789\", but if that happens,\n# buy me a lottery ticket.\nbaseworkdir=$(basename ${workdir})\nnonce=${baseworkdir#rr-test-$TESTNAME-}\n\n##--------------------------------------------------\n## Now we come to the helpers available to test runners.  This is the\n## testing \"API\".\n##\n\nfunction fails { why=$1;\n    echo NOTE: Skipping \"'$TESTNAME'\" because it fails: $why\n    exit 0\n}\n\n# If the test takes too long to run without the syscallbuf enabled,\n# use this to prevent it from running when that's the case.\nfunction skip_if_no_syscall_buf {\n    if [[ \"-n\" == \"$LIB_ARG\" ]]; then\n        echo NOTE: Skipping \"'$TESTNAME'\" because syscallbuf is disabled\n        exit 0\n    fi\n}\n\n# If the systemd version doesn't allow disabling RDRAND, skip the test,\n# because it might trigger systemd code.\nfunction skip_if_old_systemd {\n    systemd_version=`systemctl --version | head -n1 | cut -d' ' -f2`\n    if [[ $systemd_version != \"\" && $systemd_version < 247 ]]; then\n        echo \"can't disable RDRAND for systemd, skipping test\"\n        exit 0\n    fi\n}\n\nfunction skip_if_test_32_bit {\n    if [[ \"_32\" == $bitness ]]; then\n        echo NOTE: Skipping \"'$TESTNAME'\" because 32-bit test\n        exit 0\n    fi\n}\n\nfunction skip_if_rr_32_bit {\n    if [[ \"$(file $RESOURCE_PATH/lib/rr/librrpage.so | grep 32-bit -c)\" == \"1\" ]]; then\n        echo NOTE: Skipping \"'$TESTNAME'\" because 32-bit rr\n        exit 0\n    fi\n}\n\nfunction skip_if_rr_32_bit_with_shell_64_bit {\n    if [[ \"$(file $RESOURCE_PATH/lib/rr/librrpage.so | grep 32-bit -c)\" == \"1\" ]] &&\n       [[ \"$(file -L $(which sh) | grep 64-bit -c)\" == \"1\" ]];\n    then\n        echo NOTE: Skipping \"'$TESTNAME'\" because 32-bit rr with 64-bit shell\n        exit 0\n    fi\n}\n\n# If the test is causing an unrealistic failure when the syscallbuf is\n# enabled, skip it.  This better be a temporary situation!\nfunction skip_if_syscall_buf {\n    if [[ \"\" == \"$LIB_ARG\" ]]; then\n        echo NOTE: Skipping \"'$TESTNAME'\" because syscallbuf is enabled\n        exit 0\n    fi\n}\n\nfunction just_record { exe=\"$1\"; exeargs=$2;\n    _RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT record.err \\\n        $RR_EXE $GLOBAL_OPTIONS record --bind-to-cpu=any $LIB_ARG $RECORD_ARGS \"$exe\" $exeargs 1> record.out 2> record.err\n}\n\nfunction save_exe { exe=$1;\n    # If the installable testsuite is being run, most of the exes will\n    # be located under OBJDIR and the remaining under RESOURCE_PATH.\n    if [[ -f \"${OBJDIR}/bin/$exe\" ]]; then\n        EXE_PATH=$OBJDIR/bin/$exe\n    else\n        EXE_PATH=$RESOURCE_PATH/bin/$exe\n    fi\n    cp \"${EXE_PATH}\" \"$exe-$nonce\"\n}\n\nfunction switch_to_nontmp_workdir_if_possible {\n    if [[ \"$nontmp_workdir\" != \"\" ]]; then\n        workdir=$nontmp_workdir\n        cd $workdir\n    fi\n}\n\n# Record $exe with $exeargs.\nfunction record { exe=$1;\n    save_exe \"$exe\"\n    just_record \"./$exe-$nonce\" \"$2 $3 $4 $5\"\n}\n\n#  record_async_signal <signal> <delay-secs> <test>\n#\n# Record $test, delivering $signal to it after $delay-secs.\n# If for some reason delay_kill doesn't run in time, the signal\n# will not be delivered but the test will not be aborted.\nfunction record_async_signal { sig=$1; delay_secs=$2; exe=$3; exeargs=$4;\n    delay_kill $sig $delay_secs $exe-$nonce &\n    record $exe $exeargs\n    wait\n}\n\nfunction replay { replayflags=$1\n    _RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT replay.err \\\n        $RR_EXE $GLOBAL_OPTIONS replay --retry-transient-errors -a \\\n        $replayflags 1> replay.out 2> replay.err\n}\n\nfunction rerun { rerunflags=$1\n    _RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT rerun.err \\\n        $RR_EXE $GLOBAL_OPTIONS rerun $rerunflags 1> rerun.out 2> rerun.err\n}\n\nfunction pack {\n    _RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT pack.err \\\n        $RR_EXE $GLOBAL_OPTIONS pack $@ 1> pack.out 2> pack.err\n}\n\nfunction do_ps { psflags=$1\n    _RR_TRACE_DIR=\"$workdir\" \\\n        $RR_EXE $GLOBAL_OPTIONS ps $psflags\n}\n\n#  debug <expect-script-name> [replay-args]\nfunction debug {\n    debug_gdb_only $TEST_PREFIX$TESTNAME_NO_BITNESS\n    if [[ \"$test_passed\" == \"y\" ]]; then\n        debug_lldb_only $TEST_PREFIX$TESTNAME_NO_BITNESS\n    fi\n}\n\n#  debug_lldb_only <expect-script-name> [replay-args]\n#\n# Load the \"expect\" script to drive replay of the recording of |exe|.\n# Only LLDB is tested.\nfunction debug_lldb_only { expectscript=$1; replayargs=$2\n    RR_LOG_FILE=rr.log _RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT test-monitor.output \\\n        python3 $TESTDIR/$expectscript.py --lldb \\\n        $RR_EXE $GLOBAL_OPTIONS replay $replayargs\n    if [[ $? == 0 ]]; then\n        passed_msg lldb\n    else\n        failed \"debug script failed (lldb); see `pwd`/lldb_rr.log and `pwd`/test-monitor.output\"\n        echo \"--------------------------------------------------\"\n        echo \"rr.log:\"\n        cat rr.log\n        echo \"--------------------------------------------------\"\n    fi\n}\n\n#  debug_gdb_only <expect-script-name> [replay-args]\n#\n# Load the \"expect\" script to drive replay of the recording of |exe|.\n# Only GDB is tested.\nfunction debug_gdb_only { expectscript=$1; replayargs=$2\n    RR_LOG_FILE=rr.log _RR_TRACE_DIR=\"$workdir\" test-monitor $TIMEOUT test-monitor.output \\\n        python3 $TESTDIR/$expectscript.py \\\n        $RR_EXE $GLOBAL_OPTIONS replay -o-n -o-ix -o$TESTDIR/test_setup.gdb $replayargs\n    if [[ $? == 0 ]]; then\n        passed_msg gdb\n    else\n        failed \"debug script failed (gdb); see `pwd`/gdb_rr.log and `pwd`/test-monitor.output\"\n        echo \"--------------------------------------------------\"\n        echo \"rr.log:\"\n        cat rr.log\n        echo \"--------------------------------------------------\"\n    fi\n}\n\nfunction failed { msg=$1;\n    test_passed=n\n    echo \"Test '$TESTNAME' FAILED: $msg\"\n}\n\nfunction passed {\n    echo \"Test '$TESTNAME' PASSED\"\n}\n\nfunction passed_msg { msg=$1\n    echo \"Test '$TESTNAME' PASSED ($msg)\"\n}\n\nfunction just_check_replay_err {\n    if [[ $(cat replay.err) != \"\" ]]; then\n        failed \": error during replay:\"\n        echo \"--------------------------------------------------\"\n        cat replay.err\n        echo \"--------------------------------------------------\"\n        echo \"replay.out:\"\n        echo \"--------------------------------------------------\"\n        cat replay.out\n        echo \"--------------------------------------------------\"\n        return 1\n    fi\n    return 0\n}\n\nfunction just_check_record { token=$1;\n     if [ ! -f record.out -o ! -f replay.err -o ! -f replay.out -o ! -f record.err ]; then\n        failed \"output files not found.\"\n    elif [[ $(cat record.err) != \"\" ]]; then\n        failed \": error during recording:\"\n        echo \"--------------------------------------------------\"\n        cat record.err\n        echo \"--------------------------------------------------\"\n        echo \"record.out:\"\n        echo \"--------------------------------------------------\"\n        cat record.out\n        echo \"--------------------------------------------------\"\n    elif [[ \"$token\" != \"\" && \"record.out\" != $(grep -l \"$token\" record.out) ]]; then\n        failed \": token '$token' not in record.out:\"\n        echo \"--------------------------------------------------\"\n        cat record.out\n        echo \"--------------------------------------------------\"\n    else\n        return 0;\n    fi\n    return 1\n}\n\nfunction just_check_record_replay_match {\n    if [[ $(diff record.out replay.out) != \"\" ]]; then\n        failed \": output from recording different than replay\"\n        echo \"diff -U8 $workdir/record.out $workdir/replay.out\"\n        diff -U8 record.out replay.out\n        return 1\n    fi\n    return 0\n}\n\n# Check that (i) no error during replay; (ii) recorded and replayed\n# output match; (iii) the supplied token was found in the output.\n# Otherwise the test fails.\nfunction check { token=$1;\n    if ! just_check_record $1; then return;\n    elif ! just_check_replay_err; then return;\n    elif ! just_check_record_replay_match; then return;\n    else\n        passed\n    fi\n}\n\n# Like `check`, but omit the check that the output matches between record and\n# replay\nfunction check_record { token=$1;\n    if ! just_check_record $token; then return;\n    elif ! just_check_replay_err; then return;\n    else\n        passed\n    fi\n}\n\n# Like `check`, but don't look at the record output at all\nfunction check_replay_token { token=$1;\n    if [[ \"$token\" != \"\" && \"replay.out\" != $(grep -l \"$token\" replay.out) ]]; then\n        failed \": token '$token' not in replay.out:\"\n        echo \"--------------------------------------------------\"\n        cat replay.out\n        echo \"--------------------------------------------------\"\n    elif ! just_check_replay_err; then return;\n    else\n        passed\n    fi\n}\n\n\n#  compare_test <token> [<replay-flags>] [executable]\n#\n# Record the test name passed to |util.sh|, then replay it (optionally\n# with $replayflags) and verify record/replay output match and $token\n# appears in the output. Uses $executable instead of the passed-in testname\n# if present.\nfunction compare_test { token=$1; replayflags=$2;\n    test=$TESTNAME\n    if (( $# >= 3 )); then\n        test=$3\n    fi\n    if [[ $token == \"\" ]]; then\n        failed \": didn't pass an exit token\"\n    fi\n    record $test\n    replay $replayflags\n    check $token\n}\n\n#  debug_test\n#\n# Record the test name passed to |util.sh|, then replay the recording\n# using the \"expect\" script $test-name.py, which is responsible for\n# computing test pass/fail.\nfunction debug_test {\n    record $TESTNAME\n    debug\n}\n\n#  debug_test_gdb_only\n#\n# Record the test name passed to |util.sh|, then replay the recording\n# using the \"expect\" script $test-name.py, which is responsible for\n# computing test pass/fail. Only GDB is tested.\nfunction debug_test_gdb_only {\n    record $TESTNAME\n    debug_gdb_only $TEST_PREFIX$TESTNAME_NO_BITNESS\n}\n\n#  rerun_singlestep_test\n#\n# Record the test name passed to |util.sh|, then rerun --singlestep\n# the recording.\nfunction rerun_singlestep_test {\n    record $TESTNAME\n    rerun \"--singlestep=rip,gp_x16,flags\"\n}\n\n# Return an rr dump result of the most recent local recording.\nfunction get_events {\n    $RR_EXE $GLOBAL_OPTIONS dump \"$@\" latest-trace\n}\n\n# Return the number of events in the most recent local recording.\nfunction count_events {\n    local events=$(get_events -r | wc -l)\n    # The |simple| test is just about the simplest possible C program,\n    # and has around 180 events (when recorded on a particular\n    # developer's machine).  If we count a number of events\n    # significantly less than that, almost certainly something has gone\n    # wrong.\n    if [ \"$events\" -le 150 ]; then\n        failed \": Recording had too few events.  Is |rr dump -r| broken?\"\n    fi\n    # This event count is used to loop over attaching the debugger.\n    # The tests assume that the debugger can be attached at all\n    # events, but at the very last events, EXIT and so forth, rr can't\n    # attach the debugger.  So we fudge the event count down to avoid\n    # that edge case.\n    let \"events -= 10\"\n    echo $events\n}\n\n# Return a random number from the range [min, max], inclusive.\nfunction rand_range { min=$1; max=$2\n    local num=$RANDOM\n    local range=\"\"\n    let \"range = 1 + $max - $min\"\n    let \"num %= $range\"\n    let \"num += $min\"\n    echo $num\n}\n\n# Record |exe|, then replay it using the |restart_finish| debugger\n# script attaching at every recorded event.  To make the\n# debugger-replays more practical, the events are strided between at a\n# random interval between [min, max], inclusive.\n#\n# So for example, |checkpoint_test simple 3 5| means to record the\n# \"simple\" test, and attach the debugger at every X'th event, where X\n# is a random number in [3, 5].\nfunction checkpoint_test { exe=$1; min=$2; max=$3;\n    record $exe\n    num_events=$(count_events)\n    stride=$(rand_range $min $max)\n    for i in $(seq 1 $stride $num_events); do\n        echo Checkpointing at event $i ...\n        debug_gdb_only restart_finish \"-g $i\"\n        if [[ \"$test_passed\" != \"y\" ]]; then\n            break\n        fi\n    done\n}\n\nfunction wait_for_complete {\n    local record_dir=${1:-\"${workdir}/latest-trace\"}\n    for ((i = 0; i < $TIMEOUT * 10; i++)); do\n        [[ -f \"$record_dir/incomplete\" ]] || break\n        sleep 0.1\n    done\n}\n\n# If not given by user, try to find out if C.UTF-8 or en_US.UTF-8 is available, if not use any UTF-8 locale.\nfunction set_utf_locale {\n    unset LC_ALL\n    if [ -z \"$(which locale)\" ]; then\n        if [ -z \"$LC_ALL\" ]; then export LC_ALL=en_US.UTF-8; fi\n    else\n        if [ -z \"$LC_ALL\" ]; then export LC_ALL=$(locale -a | grep -i -E \"C\\.utf.*8\" | head -n1); fi\n        if [ -z \"$LC_ALL\" ]; then export LC_ALL=$(locale -a | grep -i -E \"en_US\\.utf.*8\" | head -n1); fi\n        if [ -z \"$LC_ALL\" ]; then export LC_ALL=$(locale -a | grep -i -E \".*\\.utf.*8\" | head -n1); fi\n        if [ -z \"$LC_ALL\" ]; then\n            echo \"Warning: no UTF-8 locale found.\"\n        else\n            echo \"Using LC_ALL=$LC_ALL\"\n        fi\n    fi\n}\n"
  },
  {
    "path": "src/test/util_internal.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RRUTIL_INTERNAL_H\n#define RRUTIL_INTERNAL_H\n\n#include \"util.h\"\n#include \"rrcalls.h\"\n\nint running_under_rr(void) {\n  return 0 == syscall(SYS_rrcall_check_presence, (long)0, (long)0,\n      (long)0, (long)0, (long)0, (long)0);\n}\n\nvoid rr_detach_teleport(void) {\n  int err = syscall(SYS_rrcall_detach_teleport, (long)0, (long)0,\n      (long)0, (long)0, (long)0, (long)0);\n  test_assert(err == 0);\n}\n\nvoid rr_freeze_tid(pid_t tid, int freeze) {\n  int err = syscall(SYS_rrcall_freeze_tid, tid, freeze,\n      (long)0, (long)0, (long)0, (long)0);\n  test_assert(err == 0 && \"Failed to freeze tid\");\n}\n\n#endif /* RRUTIL_INTERNAL_H */\n"
  },
  {
    "path": "src/test/util_syscall.h",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RRUTIL_SYSCALL_H\n#define RRUTIL_SYSCALL_H\n\n#include <stdint.h>\n\n#if defined(__i386__)\n#include \"SyscallEnumsForTestsX86.generated\"\n#elif defined(__x86_64__)\n#include \"SyscallEnumsForTestsX64.generated\"\n#elif defined(__aarch64__)\n#include \"SyscallEnumsForTestsGeneric.generated\"\n#else\n#error Unknown architecture\n#endif\n\nstatic inline uintptr_t unbufferable_syscall(uintptr_t syscall, uintptr_t arg1,\n                                             uintptr_t arg2,\n                                             uintptr_t arg3) {\n  uintptr_t ret;\n#ifdef __x86_64__\n  __asm__ volatile(\"syscall\\n\\t\"\n                   /* Make sure we don't patch this syscall for syscall buffering */\n                   \"cmp $0x77,%%rax\\n\\t\"\n                   : \"=a\"(ret)\n                   : \"a\"(syscall), \"D\"(arg1), \"S\"(arg2), \"d\"(arg3)\n                   : \"flags\");\n#elif defined(__i386__)\n  __asm__ volatile(\"xchg %%esi,%%edi\\n\\t\"\n                   \"int $0x80\\n\\t\"\n                   \"xchg %%esi,%%edi\\n\\t\"\n                   : \"=a\"(ret)\n                   : \"a\"(syscall), \"b\"(arg1), \"c\"(arg2), \"d\"(arg3));\n#elif defined(__aarch64__)\n  register long x8 __asm__(\"x8\") = syscall;\n  register long x0 __asm__(\"x0\") = (long)arg1;\n  register long x1 __asm__(\"x1\") = (long)arg2;\n  register long x2 __asm__(\"x2\") = (long)arg3;\n  __asm__ volatile(\"b 1f\\n\\t\"\n                   \"mov x8, 0xdc\\n\"\n                   \"1:\\n\\t\"\n                   \"svc #0\\n\\t\"\n                   : \"+r\"(x0)\n                   : \"r\"(x1), \"r\"(x2), \"r\"(x8));\n  ret = x0;\n#else\n#error define syscall here\n#endif\n  return ret;\n}\n\n#endif\n"
  },
  {
    "path": "src/test/utimes.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const int MOD_TIME = 888888;\nstatic const int ACCESS_TIME = 999999;\n\nint main(void) {\n  char path[] = \"rr-test-file-XXXXXX\";\n  int fd = mkstemp(path);\n  struct utimbuf utim = { ACCESS_TIME, MOD_TIME };\n  struct timeval tv[2] = { { ACCESS_TIME + 1, 0 }, { MOD_TIME + 1, 0 } };\n  struct stat st;\n\n  test_assert(0 <= fd);\n\n  test_assert(0 == utime(path, &utim));\n  test_assert(0 == fstat(fd, &st));\n  test_assert(st.st_atime == ACCESS_TIME);\n  test_assert(st.st_mtime == MOD_TIME);\n\n  test_assert(0 == utimes(path, tv));\n  test_assert(0 == fstat(fd, &st));\n  test_assert(st.st_atime == ACCESS_TIME + 1);\n  test_assert(st.st_mtime == MOD_TIME + 1);\n\n  test_assert(0 == unlink(path));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/v4l_dmabuf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <linux/dma-buf.h>\n\n#ifndef DMA_BUF_IOCTL_EXPORT_SYNC_FILE\nstruct dma_buf_export_sync_file {\n  uint32_t flags;\n  int32_t fd;\n};\n#define DMA_BUF_IOCTL_EXPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 2, struct dma_buf_export_sync_file)\n#endif\n#ifndef DMA_BUF_IOCTL_IMPORT_SYNC_FILE\nstruct dma_buf_import_sync_file {\n  uint32_t flags;\n  int32_t fd;\n};\n#define DMA_BUF_IOCTL_IMPORT_SYNC_FILE _IOWR(DMA_BUF_BASE, 3, struct dma_buf_import_sync_file)\n#endif\n\nstatic const char device_name[] = \"/dev/video0\";\n\nstatic void no_v4l2(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nstatic int open_device(void) {\n  struct v4l2_capability* cap;\n  int fd = open(\"/dev/video0\", O_RDWR);\n  int ret;\n\n  if (fd < 0 && errno == ENOENT) {\n    atomic_printf(\"%s not found; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  if (fd < 0 && errno == EACCES) {\n    atomic_printf(\"%s not accessible; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  test_assert(fd >= 0);\n\n  ALLOCATE_GUARD(cap, 'a');\n  ret = ioctl(fd, VIDIOC_QUERYCAP, cap);\n  VERIFY_GUARD(cap);\n  if (ret < 0 && errno == EINVAL) {\n    atomic_printf(\"%s is not a V4L2 device; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  if (ret < 0 && errno == EACCES) {\n    atomic_printf(\"%s is not accessible; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  if (!(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)) {\n    atomic_printf(\"%s is not a V4L2 capture device; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n  if (!(cap->capabilities & V4L2_CAP_STREAMING)) {\n    atomic_printf(\"%s does not support streaming; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n\n  uint32_t* input;\n  ALLOCATE_GUARD(input, 'b');\n  ret = ioctl(fd, VIDIOC_G_INPUT, input);\n  VERIFY_GUARD(input);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_G_INPUT\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_G_INPUT returns %d\\n\", device_name, *input);\n  }\n\n#ifdef VIDIOC_QUERY_EXT_CTRL\n  struct v4l2_query_ext_ctrl* qec;\n  ALLOCATE_GUARD(qec, 'c');\n  memset(qec, 0, sizeof(*qec));\n  qec->id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;\n  ret = ioctl(fd, VIDIOC_QUERY_EXT_CTRL, qec);\n  VERIFY_GUARD(qec);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_QUERY_EXT_CTRL\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_QUERY_EXT_CTRL returns id=%d, type=%d, name=%s\\n\",\n                  device_name, qec->id, qec->type, qec->name);\n  }\n#endif\n\n  enum v4l2_priority* prio;\n  ALLOCATE_GUARD(prio, 'd');\n  ret = ioctl(fd, VIDIOC_G_PRIORITY, prio);\n  VERIFY_GUARD(prio);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_G_PRIORITY\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_G_PRIORITY returns prio=%d\\n\", device_name, *prio);\n  }\n\n  struct v4l2_queryctrl* qc;\n  ALLOCATE_GUARD(qc, 'e');\n  memset(qc, 0, sizeof(*qc));\n  qc->id = V4L2_CTRL_FLAG_NEXT_CTRL;\n  ret = ioctl(fd, VIDIOC_QUERYCTRL, qc);\n  VERIFY_GUARD(qc);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_QUERYCTRL\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_QUERYCTRL returns id=%d, type=%d, name=%s\\n\",\n                  device_name, qc->id, qc->type, qc->name);\n  }\n\n  return fd;\n}\n\nstatic int get_dmabuf(int fd) {\n  struct v4l2_requestbuffers* req;\n  int ret;\n  struct v4l2_exportbuffer* exp;\n\n  ALLOCATE_GUARD(req, 'a');\n  req->count = 1;\n  req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  req->memory = V4L2_MEMORY_MMAP;\n  ret = ioctl(fd, VIDIOC_REQBUFS, req);\n  VERIFY_GUARD(req);\n  if (ret < 0 && errno == EINVAL) {\n    atomic_printf(\"%s does not support memory mapping; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n  if (ret < 0 && errno == EBUSY) {\n    atomic_printf(\"%s is busy; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  test_assert(0 == ret);\n  if (req->count < 1) {\n    atomic_puts(\"Got no buffers, aborting test\");\n    no_v4l2();\n  }\n\n  ALLOCATE_GUARD(exp, 'b');\n  exp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  exp->index = 0;\n  exp->plane = 0;\n  exp->flags = O_RDONLY;\n  memset(exp->reserved, 0, sizeof(exp->reserved));\n  ret = ioctl(fd, VIDIOC_EXPBUF, exp);\n  VERIFY_GUARD(exp);\n  test_assert(ret == 0);\n  test_assert(exp->fd >= 0);\n  return exp->fd;\n}\n\nint main(void) {\n  int fd = open_device();\n  int dmabuf = get_dmabuf(fd);\n\n  struct dma_buf_sync* sync;\n  ALLOCATE_GUARD(sync, 'a');\n  sync->flags = DMA_BUF_SYNC_START | DMA_BUF_SYNC_READ;\n  int ret = ioctl(dmabuf, DMA_BUF_IOCTL_SYNC, sync);\n  VERIFY_GUARD(sync);\n  test_assert(ret == 0);\n\n  sync->flags = DMA_BUF_SYNC_END | DMA_BUF_SYNC_READ;\n  ret = ioctl(dmabuf, DMA_BUF_IOCTL_SYNC, sync);\n  VERIFY_GUARD(sync);\n  test_assert(ret == 0);\n\n  struct dma_buf_export_sync_file* sync_file;\n  ALLOCATE_GUARD(sync_file, 'b');\n  sync_file->flags = DMA_BUF_SYNC_READ;\n  ret = ioctl(dmabuf, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, sync_file);\n  VERIFY_GUARD(sync_file);\n  test_assert(ret == 0);\n  test_assert(sync_file->fd >= 0);\n\n  struct dma_buf_import_sync_file* import_sync_file;\n  ALLOCATE_GUARD(import_sync_file, 'c');\n  import_sync_file->flags = DMA_BUF_SYNC_READ;\n  import_sync_file->fd = sync_file->fd;\n  ret = ioctl(dmabuf, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, import_sync_file);\n  VERIFY_GUARD(import_sync_file);\n  test_assert(ret == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vdso_clock_gettime_stack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  struct timespec ts;\n  for (i = 0; i < 160000; ++i) {\n    clock_gettime(CLOCK_MONOTONIC, &ts);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vdso_clock_gettime_stack.run",
    "content": "source `dirname $0`/util.sh\n\n# This test is only relevant for syscallbuf and relies on setting a breakpoint\n# inside syscallbuf.\nskip_if_no_syscall_buf\n\n# Ubuntu 5.8.0-25-generic, at least, doesn't produce usable stacks inside certain VDSO syscalls\n# with gdb and we can't under rr either due to the VDSO functions being too short for a single\n# patch without call-outs.\nskip_if_test_32_bit\n\n# Use 4K syscallbuf size to force frequent overflows\nRECORD_ARGS=--syscall-buffer-size=4\nrecord $TESTNAME\ndebug_gdb_only vdso_stack\n"
  },
  {
    "path": "src/test/vdso_gettimeofday_stack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  struct timeval tv;\n  for (i = 0; i < 160000; ++i) {\n    gettimeofday(&tv, NULL);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vdso_gettimeofday_stack.run",
    "content": "source `dirname $0`/util.sh\n\n# This test is only relevant for syscallbuf and relies on setting a breakpoint\n# inside syscallbuf.\nskip_if_no_syscall_buf\n\n# Ubuntu 5.8.0-25-generic, at least, doesn't produce usable stacks inside certain VDSO syscalls\n# with gdb and we can't under rr either due to the VDSO functions being too short for a single\n# patch without call-outs.\nskip_if_test_32_bit\nskip_if_rr_32_bit\n\n# Use 4K syscallbuf size to force frequent overflows\nRECORD_ARGS=--syscall-buffer-size=4\nrecord $TESTNAME\ndebug_gdb_only vdso_stack\n"
  },
  {
    "path": "src/test/vdso_parts.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __x86_64__\nstatic int found_dyn(Elf64_Dyn* dyn, Elf64_Sxword tag) {\n  while (dyn->d_tag != DT_NULL) {\n    if (dyn->d_tag == tag) {\n      return 1;\n    }\n    ++dyn;\n  }\n  return 0;\n}\n#elif defined(__i386__)\nstatic int found_dyn(Elf32_Dyn* dyn, Elf32_Sxword tag) {\n  while (dyn->d_tag != DT_NULL) {\n    if (dyn->d_tag == tag) {\n      return 1;\n    }\n    ++dyn;\n  }\n  return 0;\n}\n#endif\n\nint main(void) {\n#ifdef __x86_64__\n  char* vdso = (char*)getauxval(AT_SYSINFO_EHDR);\n  Elf64_Ehdr* ehdr = (Elf64_Ehdr*)vdso;\n  Elf64_Phdr* dynamic = NULL;\n  for (int i = 0; i < ehdr->e_phnum; ++i) {\n    Elf64_Phdr* phdr = (Elf64_Phdr*)(vdso + ehdr->e_phoff + i*ehdr->e_phentsize);\n    if (phdr->p_type == PT_DYNAMIC) {\n      dynamic = phdr;\n      break;\n    }\n  }\n  if (!dynamic) {\n    atomic_puts(\"PT_DYNAMIC not found in VDSO\");\n    return 1;\n  }\n  Elf64_Dyn* dyn = (Elf64_Dyn*)(vdso + dynamic->p_offset);\n  test_assert(found_dyn(dyn, DT_HASH));\n  test_assert(found_dyn(dyn, DT_SYMTAB));\n  test_assert(found_dyn(dyn, DT_STRTAB));\n  test_assert(found_dyn(dyn, DT_VERSYM));\n  test_assert(found_dyn(dyn, DT_VERDEF));\n  test_assert(found_dyn(dyn, DT_VERDEFNUM));\n  test_assert(found_dyn(dyn, DT_STRSZ));\n#elif defined(__i386__)\n  char* vdso = (char*)getauxval(AT_SYSINFO_EHDR);\n  Elf32_Ehdr* ehdr = (Elf32_Ehdr*)vdso;\n  Elf32_Phdr* dynamic = NULL;\n  for (int i = 0; i < ehdr->e_phnum; ++i) {\n    Elf32_Phdr* phdr = (Elf32_Phdr*)(vdso + ehdr->e_phoff + i*ehdr->e_phentsize);\n    if (phdr->p_type == PT_DYNAMIC) {\n      dynamic = phdr;\n      break;\n    }\n  }\n  if (!dynamic) {\n    atomic_puts(\"PT_DYNAMIC not found in VDSO\");\n    return 1;\n  }\n  Elf32_Dyn* dyn = (Elf32_Dyn*)(vdso + dynamic->p_offset);\n  test_assert(found_dyn(dyn, DT_HASH));\n  test_assert(found_dyn(dyn, DT_SYMTAB));\n  test_assert(found_dyn(dyn, DT_STRTAB));\n  test_assert(found_dyn(dyn, DT_VERSYM));\n  test_assert(found_dyn(dyn, DT_VERDEF));\n  test_assert(found_dyn(dyn, DT_VERDEFNUM));\n  test_assert(found_dyn(dyn, DT_STRSZ));\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vdso_stack.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('break traced_raw_syscall')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('where')\nexpect_gdb(' main ')\n\nok()\n"
  },
  {
    "path": "src/test/vdso_symbols.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#if defined(__x86_64__) || defined(__aarch64__)\ntypedef Elf64_Ehdr Ehdr;\ntypedef Elf64_Shdr Shdr;\ntypedef Elf64_Sym Sym;\n#else\ntypedef Elf32_Ehdr Ehdr;\ntypedef Elf32_Shdr Shdr;\ntypedef Elf32_Sym Sym;\n#endif\n\nstatic const char* find_string(Ehdr* ehdr, uintptr_t offset) {\n  Shdr* strings = (Shdr*)((char*)ehdr + ehdr->e_shoff + ehdr->e_shstrndx*ehdr->e_shentsize);\n  return (char*)ehdr + strings->sh_offset + offset;\n}\n\nstatic Shdr* find_section(Ehdr* ehdr, const char* name) {\n  for (int i = 0; i < ehdr->e_shnum; ++i) {\n    Shdr* hdr = (Shdr*)((char*)ehdr + ehdr->e_shoff + i*ehdr->e_shentsize);\n    if (!strcmp(find_string(ehdr, hdr->sh_name), name)) {\n      return hdr;\n    }\n  }\n  return NULL;\n}\n\n#ifdef __aarch64__\n#define PRELOAD_LIBRARY_PAGE_SIZE 65536\n#else\n#define PRELOAD_LIBRARY_PAGE_SIZE 4096\n#endif\n\nint main(void) {\n  char* vdso = (char*)getauxval(AT_SYSINFO_EHDR);\n  Ehdr* ehdr = (Ehdr*)vdso;\n  Shdr* dynsym = find_section(ehdr, \".dynsym\");\n  if (!dynsym) {\n    atomic_puts(\"dynsym not found in VDSO\");\n    return 1;\n  }\n\n  for (int si = 0; si*dynsym->sh_entsize < dynsym->sh_size; ++si) {\n    Sym* sym = (Sym*)(vdso + dynsym->sh_offset) + si;\n    // All symbols must be within the VDSO size, i.e. not the\n    // absolute address. We assume the VDSO is less than 4 pages.\n    test_assert(sym->st_value < 4*PRELOAD_LIBRARY_PAGE_SIZE);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vdso_time_stack.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  for (i = 0; i < 160000; ++i) {\n    time(NULL);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vdso_time_stack.run",
    "content": "source `dirname $0`/util.sh\n\n# This test is only relevant for syscallbuf and relies on setting a breakpoint\n# inside syscallbuf.\nskip_if_no_syscall_buf\n\n# Ubuntu 5.8.0-25-generic, at least, doesn't produce usable stacks inside certain VDSO syscalls\n# with gdb and we can't under rr either due to the VDSO functions being too short for a single\n# patch without call-outs.\nskip_if_test_32_bit\nskip_if_rr_32_bit\n\n# Use 4K syscallbuf size to force frequent overflows\nRECORD_ARGS=--syscall-buffer-size=4\nrecord $TESTNAME\ndebug_gdb_only vdso_stack\n"
  },
  {
    "path": "src/test/vfork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(int argc, char* argv[]) {\n  const char* exe;\n  pid_t child;\n  int status;\n\n  test_assert(2 == argc);\n  exe = argv[1];\n\n  if (0 == (child = vfork())) {\n    execl(exe, exe, NULL);\n    test_assert(\"Not reached\" && 0);\n  }\n\n  atomic_printf(\"child %d\\n\", child);\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && 0 == WEXITSTATUS(status));\n\n  breakpoint();\n\n  atomic_puts(\"vforker-EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vfork.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe simple$bitness\nrecord $TESTNAME simple$bitness-$nonce\nreplay\ncheck vforker-EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/vfork_break_parent.py",
    "content": "from util import *\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\nok()\n"
  },
  {
    "path": "src/test/vfork_break_parent.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe simple$bitness\nsaved_exe=\"simple$bitness-$nonce\"\n\nrecord vfork$bitness \"$saved_exe\"\ndebug_gdb_only vfork_break_parent\n"
  },
  {
    "path": "src/test/vfork_done.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n\n#ifndef PTRACE_EVENT_STOP\n#define PTRACE_EVENT_STOP 128\n#endif\n\n#include <math.h>\n#include <signal.h>\n\nstatic int EXECUTION_FENCE_PIPES[2];\nstatic char force_clone;\nstatic char stack[65536];\n\nstatic void seize(const pid_t pid) {\n  const int opts =\n      PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACESYSGOOD;\n  test_assert(0 == ptrace(PTRACE_SEIZE, pid, 0, opts));\n}\n\nstatic int vfork_child(__attribute__((unused)) void* p) {\n  long res = 0;\n  for (int i = 1; i < 1000000; i++) {\n    for (int j = 1; j < 100; j++) {\n      res = (res / 3) + 14*i;\n      if (res /= res > 2) {\n        res = 3;\n      }\n    }\n  }\n  exit(99);\n  return 0;\n}\n\nstatic int tracees(void) {\n  pid_t child;\n  if (force_clone) {\n    child = clone(vfork_child, stack + sizeof(stack),\n                  CLONE_VFORK | CLONE_VM | SIGCHLD, NULL);\n  } else {\n    child = vfork();\n    if (!child) {\n      vfork_child(NULL);\n      return 0;\n    }\n  }\n  if (child < 0) {\n    exit(EXIT_FAILURE);\n  } else {\n    exit(66);\n  }\n}\n\nint main(int argc, char** argv) {\n  char notify;\n  assert(0 == pipe(EXECUTION_FENCE_PIPES));\n\n  if (argc > 1 && !strcmp(argv[1], \"clone\")) {\n    force_clone = 1;\n  }\n\n  pid_t fork_child = fork();\n\n  switch (fork_child) {\n    case 0: {\n      assert(1 == read(EXECUTION_FENCE_PIPES[0], &notify, 1) &&\n             \"Failed to read notify event\");\n      tracees();\n    } break;\n    default:\n      seize(fork_child);\n      test_assert(1 == write(EXECUTION_FENCE_PIPES[1], \"1\", 1));\n      int ws;\n      long grand_child = 0;\n\n      test_assert(fork_child == waitpid(fork_child, &ws, 0));\n      // Wait for fork-child to stop at VFORK event\n      test_assert(WIFSTOPPED(ws) && WSTOPSIG(ws) == SIGTRAP &&\n                  ws >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK << 8)));\n      // Get vfork-child's pid\n      test_assert(0 == ptrace(PTRACE_GETEVENTMSG, fork_child, NULL, &grand_child));\n      // Wait for vfork-child to stop\n      test_assert(grand_child == waitpid(0, &ws, 0));\n      // PTRACE_O_TRACEVFORK generates PTRACE_EVENT_STOP (for vfork child) if\n      // SEIZE is used for ATTACH, SIGSTOP will be generated instead (man\n      // ptrace)\n      test_assert(WIFSTOPPED(ws) && WSTOPSIG(ws) == SIGTRAP &&\n                  ws >> 8 == (SIGTRAP | (PTRACE_EVENT_STOP << 8)));\n      // Just to be sure; let's send SIGINT *before* grand child is done\n      // and make sure it arrives *after* VFORK_DONE\n      kill(fork_child, SIGINT);\n      test_assert(0 == ptrace(PTRACE_CONT, grand_child, NULL, NULL));\n      // Continue fork-child at vfork event\n      test_assert(0 == ptrace(PTRACE_CONT, fork_child, NULL, NULL));\n      test_assert(fork_child == waitpid(fork_child, &ws, 0));\n      // Verify that fork-child (vfork-parent), received VFORK_DONE\n      test_assert(ws >> 8 == (SIGTRAP | (PTRACE_EVENT_VFORK_DONE << 8)));\n\n      // Check that vfork-child exited with correct exit code\n      test_assert(grand_child == waitpid(grand_child, &ws, 0));\n      test_assert(WIFEXITED(ws) && WEXITSTATUS(ws) == 99);\n\n      // Check that fork-child (vfork-parent) stopped due to SIGCHILD\n      test_assert(0 == ptrace(PTRACE_CONT, fork_child, NULL, NULL));\n      test_assert(fork_child == waitpid(fork_child, &ws, 0));\n      test_assert(WIFSTOPPED(ws) && WSTOPSIG(ws) == SIGINT);\n\n      test_assert(0 == ptrace(PTRACE_CONT, fork_child, NULL, NULL));\n      test_assert(fork_child == waitpid(fork_child, &ws, 0));\n      test_assert(WIFSTOPPED(ws) && WSTOPSIG(ws) == SIGCHLD);\n\n      // And finally verify fork-childs exit code\n      test_assert(0 == ptrace(PTRACE_CONT, fork_child, NULL, NULL));\n      test_assert(fork_child == waitpid(fork_child, &ws, 0));\n      test_assert(WIFEXITED(ws) && WEXITSTATUS(ws) == 66);\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/vfork_done_clone.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe vfork_done$bitness\njust_record vfork_done$bitness-$nonce clone\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/vfork_exec.run",
    "content": "source `dirname $0`/util.sh\n\nsave_exe rr_exec_stub$bitness\nsaved_exe=\"rr_exec_stub$bitness-$nonce\"\n\nrecord vfork$bitness \"$saved_exe\"\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}')\n\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only first_instruction \"-p $TARGET_PID\"\n"
  },
  {
    "path": "src/test/vfork_flush.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void unblock_signals(void) {\n  sigset_t mask;\n  sigemptyset(&mask);\n  sigprocmask(SIG_SETMASK, &mask, NULL);\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n\n  if (0 == (child = vfork())) {\n    /* Unblocking SIGSYS should be OK */\n    unblock_signals();\n    test_assert(0 == close(0));\n    _exit(77);\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  /* Unblocking SIGSYS should be OK */\n  unblock_signals();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vfork_read_clone_stress.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n// Global to protect them from the compiler potentially\n// smashing them, thinking they're unused\nvolatile int fd;\nvolatile void* buf;\nvolatile int counter;\nvolatile int counter2 = 0;\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int scratch_size = 512 * page_size;\n  fd = open(\"tempfile\", O_RDWR | O_CREAT | O_TRUNC, 0700);\n  buf = mmap(NULL, scratch_size, PROT_READ | PROT_WRITE,\n                   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(fd >= 0);\n\n  /* First, initialize the file, so the syscall buffer will attempt to\n     clone it in each thread */\n  int ret = write(fd, (void*)buf, scratch_size);\n  test_assert(ret == scratch_size);\n\n  for (counter = 0; counter < 20; ++counter) {\n    // Make sure the clone fd ends up having a different number in each task\n    open(\"/dev/null\", O_RDONLY);\n    if (!vfork()) {\n      continue;\n    }\n    atomic_printf(\"child %d\\n\", getpid());\n    ret = lseek(fd, 0, SEEK_SET);\n    test_assert(ret == 0);\n    ret = read(fd, (void*)buf, scratch_size);\n    test_assert(ret == scratch_size);\n    if (++counter2 == counter) {\n      atomic_puts(\"EXIT-SUCCESS\");\n    }\n    _exit(0);\n    break;\n  }\n  _exit(0);\n}\n"
  },
  {
    "path": "src/test/vfork_read_clone_stress.py",
    "content": "from util import *\nimport re\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('c')\nexpect_gdb('Program received signal SIGKILL')\n\nsend_gdb('rc')\nexpect_gdb([f'({history_end_regex()})', '(child)'])\n\nassert 'child' not in last_match().group(1)\n\nsend_gdb('c')\nexpect_gdb('Program received signal SIGKILL')\n\nok()\n"
  },
  {
    "path": "src/test/vfork_read_clone_stress.run",
    "content": "source `dirname $0`/util.sh\n\nrecord $TESTNAME\nTARGET_PID=$(grep 'child ' record.out | awk '{print $2}' | tail -n 5 | head -n 1)\necho Targeting recorded pid $TARGET_PID ...\ndebug_gdb_only vfork_read_clone_stress \"-f $TARGET_PID\"\n"
  },
  {
    "path": "src/test/vfork_setopts.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n#include \"util.h\"\n\nstatic int EXECUTION_FENCE_PIPES[2];\n\nstatic void attach(const pid_t pid) {\n  test_assert(0 == ptrace(PTRACE_ATTACH, pid, 0, 0));\n}\n\nint main(void) {\n  char notify;\n  assert(0 == pipe(EXECUTION_FENCE_PIPES));\n  pid_t fork_child = fork();\n\n  switch (fork_child) {\n    case 0: {\n      assert(1 == read(EXECUTION_FENCE_PIPES[0], &notify, 1) &&\n             \"Failed to read notify event\");\n      exit(66);\n    } break;\n    default:\n      attach(fork_child);\n      test_assert(1 == write(EXECUTION_FENCE_PIPES[1], \"1\", 1));\n      int ws;\n      // PTRACE_ATTACH SIGSTOP delivered only after suspension of blocked read\n      // has ended. We can now ptrace SET_OPTIONS.\n      test_assert(fork_child == waitpid(fork_child, &ws, 0));\n      test_assert(WIFSTOPPED(ws) && WSTOPSIG(ws) == SIGSTOP);\n      const int opts =\n          PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE | PTRACE_O_TRACESYSGOOD;\n      test_assert(0 == ptrace(PTRACE_SETOPTIONS, fork_child, 0, opts));\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n}\n"
  },
  {
    "path": "src/test/vfork_shared.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int* p;\n\nint main(void) {\n  pid_t child;\n  int status;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  if (0 == (child = vfork())) {\n    p = (int*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n    *p = 88;\n    test_assert(p != MAP_FAILED);\n    _exit(77);\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  test_assert(*p == 88);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/video_capture.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char device_name[] = \"/dev/video0\";\n\nstruct buffer {\n  struct v4l2_buffer vbuf;\n  unsigned char* mmap_data;\n};\nstatic struct buffer buffers[4];\nstatic size_t buffer_count;\n\nstatic void no_v4l2(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  exit(0);\n}\n\nstatic int open_device(void) {\n  struct v4l2_capability* cap;\n  int fd = open(\"/dev/video0\", O_RDWR);\n  int ret;\n\n  if (fd < 0 && errno == ENOENT) {\n    atomic_printf(\"%s not found; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  if (fd < 0 && errno == EACCES) {\n    atomic_printf(\"%s not accessible; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  test_assert(fd >= 0);\n\n  ALLOCATE_GUARD(cap, 'a');\n  ret = ioctl(fd, VIDIOC_QUERYCAP, cap);\n  VERIFY_GUARD(cap);\n  if (ret < 0 && errno == EINVAL) {\n    atomic_printf(\"%s is not a V4L2 device; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  if (ret < 0 && errno == EACCES) {\n    atomic_printf(\"%s is not accessible; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  if (!(cap->capabilities & V4L2_CAP_VIDEO_CAPTURE)) {\n    atomic_printf(\"%s is not a V4L2 capture device; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n  if (!(cap->capabilities & V4L2_CAP_STREAMING)) {\n    atomic_printf(\"%s does not support streaming; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n\n  uint32_t* input;\n  ALLOCATE_GUARD(input, 'b');\n  ret = ioctl(fd, VIDIOC_G_INPUT, input);\n  VERIFY_GUARD(input);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_G_INPUT\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_G_INPUT returns %d\\n\", device_name, *input);\n  }\n\n#ifdef VIDIOC_QUERY_EXT_CTRL\n  struct v4l2_query_ext_ctrl* qec;\n  ALLOCATE_GUARD(qec, 'c');\n  memset(qec, 0, sizeof(*qec));\n  qec->id = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;\n  ret = ioctl(fd, VIDIOC_QUERY_EXT_CTRL, qec);\n  VERIFY_GUARD(qec);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_QUERY_EXT_CTRL\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_QUERY_EXT_CTRL returns id=%d, type=%d, name=%s\\n\",\n                  device_name, qec->id, qec->type, qec->name);\n  }\n#endif\n\n  enum v4l2_priority* prio;\n  ALLOCATE_GUARD(prio, 'd');\n  ret = ioctl(fd, VIDIOC_G_PRIORITY, prio);\n  VERIFY_GUARD(prio);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_G_PRIORITY\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_G_PRIORITY returns prio=%d\\n\", device_name, *prio);\n  }\n\n  struct v4l2_queryctrl* qc;\n  ALLOCATE_GUARD(qc, 'e');\n  memset(qc, 0, sizeof(*qc));\n  qc->id = V4L2_CTRL_FLAG_NEXT_CTRL;\n  ret = ioctl(fd, VIDIOC_QUERYCTRL, qc);\n  VERIFY_GUARD(qc);\n  if (ret < 0) {\n    atomic_printf(\"%s does not support VIDIOC_QUERYCTRL\\n\", device_name);\n  } else {\n    atomic_printf(\"%s VIDIOC_QUERYCTRL returns id=%d, type=%d, name=%s\\n\",\n                  device_name, qc->id, qc->type, qc->name);\n  }\n\n  return fd;\n}\n\nstatic void init_device(int fd) {\n  struct v4l2_format* fmt;\n  struct v4l2_requestbuffers* req;\n  int ret;\n  size_t i;\n  enum v4l2_buf_type* type;\n\n  ALLOCATE_GUARD(fmt, 'a');\n  fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  ret = ioctl(fd, VIDIOC_G_FMT, fmt);\n  VERIFY_GUARD(fmt);\n  if (ret < 0 && errno == EINVAL) {\n    // v4l2_loopback doesn't support G_FMT\n    atomic_printf(\"%s does not support G_FMT; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n  test_assert(0 == ret);\n  atomic_printf(\"%s returning %dx%d frames\\n\", device_name, fmt->fmt.pix.width,\n                fmt->fmt.pix.height);\n\n  ALLOCATE_GUARD(req, 'b');\n  req->count = 4;\n  req->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  req->memory = V4L2_MEMORY_MMAP;\n  ret = ioctl(fd, VIDIOC_REQBUFS, req);\n  VERIFY_GUARD(req);\n  if (ret < 0 && errno == EINVAL) {\n    atomic_printf(\"%s does not support memory mapping; aborting test\\n\",\n                  device_name);\n    no_v4l2();\n  }\n  if (ret < 0 && errno == EBUSY) {\n    atomic_printf(\"%s is busy; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  test_assert(0 == ret);\n  if (req->count < 2) {\n    atomic_printf(\"%s only supports one buffer; aborting test\\n\", device_name);\n    no_v4l2();\n  }\n  buffer_count = req->count;\n\n  for (i = 0; i < buffer_count; ++i) {\n    struct buffer* buf = buffers + i;\n    buf->vbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n    buf->vbuf.memory = V4L2_MEMORY_MMAP;\n    buf->vbuf.index = i;\n    test_assert(0 == ioctl(fd, VIDIOC_QUERYBUF, &buf->vbuf));\n    buf->mmap_data = mmap(NULL, buf->vbuf.length, PROT_READ | PROT_WRITE,\n                          MAP_SHARED, fd, buf->vbuf.m.offset);\n    test_assert(buf->mmap_data != MAP_FAILED);\n    atomic_printf(\"Buffer %d, addr %p, device offset 0x%llx, device len 0x%llx\\n\",\n                  (int)i, buf->mmap_data, (long long)buf->vbuf.m.offset,\n                  (long long)buf->vbuf.length);\n    test_assert(0 == ioctl(fd, VIDIOC_QBUF, &buf->vbuf));\n  }\n  ALLOCATE_GUARD(type, 'c');\n  *type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  test_assert(0 == ioctl(fd, VIDIOC_STREAMON, type));\n  VERIFY_GUARD(type);\n}\n\nstatic void print_fourcc(int v) {\n  union {\n    int v;\n    char cs[4];\n  } u;\n  u.v = v;\n  atomic_printf(\"%c%c%c%c\", u.cs[0], u.cs[1], u.cs[2], u.cs[3]);\n}\n\nstatic double fract_to_fps(struct v4l2_fract* f) {\n  return (double)f->denominator / f->numerator;\n}\n\nstatic void dump_sizes(int fd) {\n  struct v4l2_fmtdesc* fmt;\n\n  ALLOCATE_GUARD(fmt, 'a');\n  fmt->index = 0;\n  fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  while (1) {\n    struct v4l2_frmsizeenum* size;\n    int ret = ioctl(fd, VIDIOC_ENUM_FMT, fmt);\n    VERIFY_GUARD(fmt);\n    if (ret < 0) {\n      test_assert(errno == EINVAL);\n      break;\n    }\n\n    atomic_printf(\"Format %d fourcc \", fmt->index);\n    print_fourcc(fmt->pixelformat);\n    ++fmt->index;\n    atomic_printf(\" name '%s'\\n\", fmt->description);\n\n    ALLOCATE_GUARD(size, 'b');\n    size->index = 0;\n    size->pixel_format = fmt->pixelformat;\n    while (1) {\n      ret = ioctl(fd, VIDIOC_ENUM_FRAMESIZES, size);\n      VERIFY_GUARD(size);\n      if (ret < 0) {\n        test_assert(errno == EINVAL);\n        break;\n      }\n      ++size->index;\n\n      if (size->type == V4L2_FRMSIZE_TYPE_DISCRETE) {\n        struct v4l2_frmivalenum* interval;\n        ALLOCATE_GUARD(interval, 'c');\n        atomic_printf(\"  Frame size %dx%d\\n\", size->discrete.width,\n                      size->discrete.height);\n        interval->index = 0;\n        interval->pixel_format = fmt->pixelformat;\n        interval->width = size->discrete.width;\n        interval->height = size->discrete.height;\n        while (1) {\n          ret = ioctl(fd, VIDIOC_ENUM_FRAMEINTERVALS, interval);\n          VERIFY_GUARD(interval);\n          if (ret < 0) {\n            test_assert(errno == EINVAL);\n            break;\n          }\n          ++interval->index;\n\n          if (interval->type == V4L2_FRMIVAL_TYPE_DISCRETE) {\n            atomic_printf(\"    %f fps\\n\", fract_to_fps(&interval->discrete));\n          } else if (interval->type == V4L2_FRMIVAL_TYPE_CONTINUOUS ||\n                     interval->type == V4L2_FRMIVAL_TYPE_STEPWISE) {\n            atomic_printf(\"    %f-%f fps\\n\",\n                          fract_to_fps(&interval->stepwise.min),\n                          fract_to_fps(&interval->stepwise.max));\n          }\n        }\n      } else if (size->type == V4L2_FRMSIZE_TYPE_STEPWISE) {\n        atomic_printf(\"  Frame size %dx%d to %dx%d step %dx%d\\n\",\n                      size->stepwise.min_width, size->stepwise.min_height,\n                      size->stepwise.max_width, size->stepwise.max_height,\n                      size->stepwise.step_width, size->stepwise.step_height);\n      }\n    }\n  }\n}\n\nstatic void read_frames(int fd) {\n  size_t i, j;\n\n  for (i = 0; i < buffer_count * 2; ++i) {\n    struct v4l2_buffer* buf;\n    int ret;\n    size_t bytes;\n    struct buffer* buffer;\n\n    ALLOCATE_GUARD(buf, 'a');\n    buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n    buf->memory = V4L2_MEMORY_MMAP;\n    ret = ioctl(fd, VIDIOC_DQBUF, buf);\n    VERIFY_GUARD(buf);\n    test_assert(ret == 0);\n    test_assert(buf->index < buffer_count);\n\n    bytes = buf->length < 16 ? buf->length : 16;\n    buffer = &buffers[buf->index];\n    atomic_printf(\"Frame %d, buffer %d, addr %p: \", (int)i, (int)buf->index,\n                  buffer->mmap_data);\n    for (j = 0; j < bytes; ++j) {\n      atomic_printf(\"%2x \", buffer->mmap_data[j]);\n    }\n    atomic_printf(\"...\\n\");\n\n    /* Reallocate the mmap data to check for bugs involving the length\n       of the shared memory area */\n    munmap(buffer->mmap_data, buffer->vbuf.length);\n    buffer->mmap_data =\n      mmap(NULL, buffer->vbuf.length, PROT_READ | PROT_WRITE, MAP_SHARED,\n           fd, buffer->vbuf.m.offset);\n    test_assert(buffer->mmap_data != MAP_FAILED);\n\n    test_assert(0 == ioctl(fd, VIDIOC_QBUF, buf));\n    VERIFY_GUARD(buf);\n    FREE_GUARD(buf);\n  }\n}\n\nstatic void close_device(int fd) {\n  enum v4l2_buf_type* type;\n\n  ALLOCATE_GUARD(type, 'a');\n  *type = V4L2_BUF_TYPE_VIDEO_CAPTURE;\n  test_assert(0 == ioctl(fd, VIDIOC_STREAMOFF, type));\n  VERIFY_GUARD(type);\n}\n\nint main(void) {\n  int fd = open_device();\n  init_device(fd);\n  dump_sizes(fd);\n  read_frames(fd);\n  close_device(fd);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vm_readv_writev.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void clear(unsigned char* p) {\n  size_t i;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  for (i = 0; i < (unsigned)page_size; ++i) {\n    p[i] = i & 0xFF;\n  }\n}\n\nstatic void check_page1(unsigned char* p, size_t page_size, int ret) {\n  if (3 == ret) {\n    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));\n    test_assert(p[page_size - 6] == 0);\n    test_assert(p[page_size - 5] == 1);\n    test_assert(p[page_size - 4] == 3);\n    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));\n    test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));\n    test_assert(p[page_size - 1] == ((page_size - 1) & 0xff));\n  } else {\n    test_assert(4 == ret);\n    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));\n    test_assert(p[page_size - 6] == 0);\n    test_assert(p[page_size - 5] == 1);\n    test_assert(p[page_size - 4] == 3);\n    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));\n    test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));\n    test_assert(p[page_size - 1] == 4);\n  }\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  unsigned char* p =\n      (unsigned char*)mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,\n                           MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  struct iovec in_iov[2];\n  struct iovec out_iov[2];\n  int ret;\n\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p + page_size, page_size));\n\n  in_iov[0].iov_base = p;\n  in_iov[0].iov_len = 2;\n  in_iov[1].iov_base = p + 3;\n  in_iov[1].iov_len = 3;\n  out_iov[0].iov_base = p + page_size - 6;\n  out_iov[0].iov_len = 3;\n  out_iov[1].iov_base = p + page_size - 1;\n  out_iov[1].iov_len = 2;\n\n  clear(p);\n  ret = process_vm_readv(getpid(), out_iov, 2, in_iov, 2, 0);\n  test_assert(out_iov[1].iov_len == 2);\n  check_page1(p, page_size, ret);\n  clear(p);\n  ret = process_vm_writev(getpid(), in_iov, 2, out_iov, 2, 0);\n  test_assert(out_iov[1].iov_len == 2);\n  check_page1(p, page_size, ret);\n\n  out_iov[1].iov_base = p + page_size - 2;\n  out_iov[1].iov_len = 3;\n\n  clear(p);\n  test_assert(5 == process_vm_readv(getpid(), out_iov, 2, in_iov, 2, 0));\n  test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));\n  test_assert(p[page_size - 6] == 0);\n  test_assert(p[page_size - 5] == 1);\n  test_assert(p[page_size - 4] == 3);\n  test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));\n  test_assert(p[page_size - 2] == 4);\n  test_assert(p[page_size - 1] == 5);\n  clear(p);\n  ret = process_vm_writev(getpid(), in_iov, 2, out_iov, 2, 0);\n  if (3 == ret) {\n    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));\n    test_assert(p[page_size - 6] == 0);\n    test_assert(p[page_size - 5] == 1);\n    test_assert(p[page_size - 4] == 3);\n    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));\n    test_assert(p[page_size - 2] == ((page_size - 2) & 0xff));\n    test_assert(p[page_size - 1] == ((page_size - 1) & 0xff));\n  } else {\n    test_assert(5 == ret);\n    test_assert(p[page_size - 7] == ((page_size - 7) & 0xff));\n    test_assert(p[page_size - 6] == 0);\n    test_assert(p[page_size - 5] == 1);\n    test_assert(p[page_size - 4] == 3);\n    test_assert(p[page_size - 3] == ((page_size - 3) & 0xff));\n    test_assert(p[page_size - 2] == 4);\n    test_assert(p[page_size - 1] == 5);\n  }\n\n  in_iov[0].iov_base = p + page_size - 1;\n  in_iov[0].iov_len = 2;\n  out_iov[0].iov_base = p;\n  out_iov[0].iov_len = 3;\n\n  clear(p);\n  ret = process_vm_readv(getpid(), out_iov, 1, in_iov, 1, 0);\n  if (ret == -1 && errno == EFAULT) {\n    test_assert(p[0] == 0);\n    test_assert(p[1] == 1);\n  } else {\n    test_assert(1 == ret);\n    test_assert(p[0] == ((page_size - 1) & 0xff));\n    test_assert(p[1] == 1);\n  }\n  clear(p);\n  ret = process_vm_writev(getpid(), in_iov, 1, out_iov, 1, 0);\n  if (ret == -1 && errno == EFAULT) {\n    test_assert(p[0] == 0);\n    test_assert(p[1] == 1);\n  } else {\n    test_assert(1 == ret);\n    test_assert(p[0] == ((page_size - 1) & 0xff));\n    /* Linux kernel bug: should be 1, but sometimes is zero ---\n       extra data written. https://bugzilla.kernel.org/show_bug.cgi?id=113541 */\n    if (p[1] == 0) {\n      atomic_puts(\"Kernel bug detected!\");\n    }\n    test_assert(p[1] == 1 || p[1] == 0);\n  }\n\n  in_iov[0].iov_base = p + page_size - 4;\n  in_iov[0].iov_len = 2;\n  in_iov[1].iov_base = p + page_size - 2;\n  in_iov[1].iov_len = 3;\n  out_iov[0].iov_base = p;\n  out_iov[0].iov_len = 1;\n  out_iov[1].iov_base = p + 2;\n  out_iov[1].iov_len = 4;\n\n  clear(p);\n  ret = process_vm_readv(getpid(), out_iov, 2, in_iov, 2, 0);\n  if (2 == ret) {\n    test_assert(p[0] == ((page_size - 4) & 0xff));\n    test_assert(p[1] == 1);\n    test_assert(p[2] == ((page_size - 3) & 0xff));\n    test_assert(p[3] == 3);\n    test_assert(p[4] == 4);\n    test_assert(p[5] == 5);\n  } else {\n    test_assert(4 == ret);\n    test_assert(p[0] == ((page_size - 4) & 0xff));\n    test_assert(p[1] == 1);\n    test_assert(p[2] == ((page_size - 3) & 0xff));\n    test_assert(p[3] == ((page_size - 2) & 0xff));\n    test_assert(p[4] == ((page_size - 1) & 0xff));\n    test_assert(p[5] == 5);\n  }\n  clear(p);\n  test_assert(4 == process_vm_writev(getpid(), in_iov, 2, out_iov, 2, 0));\n  test_assert(p[0] == ((page_size - 4) & 0xff));\n  test_assert(p[1] == 1);\n  test_assert(p[2] == ((page_size - 3) & 0xff));\n  test_assert(p[3] == ((page_size - 2) & 0xff));\n  test_assert(p[4] == ((page_size - 1) & 0xff));\n  if (p[5] == 0) {\n    atomic_puts(\"Kernel bug detected!\");\n  }\n  test_assert(p[5] == 5 || p[5] == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vsyscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __x86_64__\n\nstatic long gettimeofday_vsyscall(struct timeval* tv, struct timezone* tz)\n{\n  long ret;\n  __asm__ __volatile(\n    \"movq $0xffffffffff600000, %%rax\\n\\t\"\n    \"callq *%%rax\\n\\t\" : \"=a\"(ret) : \"D\"(tv), \"S\"(tz) : \"cc\", \"memory\");\n  return ret;\n}\n\nstatic time_t time_vsyscall(time_t* t)\n{\n  time_t ret;\n  __asm__ __volatile(\n    \"movq $0xffffffffff600400, %%rax\\n\\t\"\n    \"callq *%%rax\\n\\t\" : \"=a\"(ret) : \"D\"(t) : \"cc\", \"memory\");\n  return ret;\n}\n\nstatic long getcpu_vsyscall(unsigned* cpu, unsigned* node, void* tcache)\n{\n  long ret;\n  __asm__ __volatile(\n    \"movq $0xffffffffff600800, %%rax\\n\\t\"\n    \"callq *%%rax\\n\\t\" : \"=a\"(ret) : \"D\"(cpu), \"S\"(node), \"d\"(tcache) : \"cc\", \"memory\");\n  return ret;\n}\n\nvoid callback(uint64_t env, char *name, __attribute__((unused)) map_properties_t* props) {\n  if (strcmp(name, \"[vsyscall]\") == 0) {\n    int* has_vsyscall = (int*)(uintptr_t)env;\n    *has_vsyscall = 1;\n  }\n}\n#endif\n\nint main(void) {\n  // x86_64 only\n#ifdef __x86_64__\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  int has_vsyscall = 0;\n  iterate_maps((uintptr_t)&has_vsyscall, callback, maps_file);\n\n  if (has_vsyscall) {\n    // gettimeofday\n    struct timeval tv = { 0, 0 };\n    test_assert(gettimeofday_vsyscall(&tv, NULL) == 0);\n    test_assert(tv.tv_sec != 0);\n\n    // time\n    time_t tim;\n    time_t ret = (time_t)time_vsyscall(&tim);\n    test_assert(ret == tim);\n\n    // getcpu\n    unsigned* cpu;\n    unsigned* node;\n    ALLOCATE_GUARD(cpu, -1);\n    ALLOCATE_GUARD(node, -1);\n    test_assert(0 == getcpu_vsyscall(cpu, node, NULL));\n    test_assert(*cpu <= 0xffffff);\n    test_assert(*node <= 0xffffff);\n    VERIFY_GUARD(cpu);\n    VERIFY_GUARD(node);\n  }\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vsyscall_reverse_next.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  time(NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/vsyscall_reverse_next.py",
    "content": "from util import *\n\nsend_gdb('break vsyscall_reverse_next.c:6')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('disable 1')\n\nsend_gdb('n')\nexpect_gdb('atomic_puts')\n\nsend_gdb('reverse-next')\nexpect_gdb('time')\n\nok()\n"
  },
  {
    "path": "src/test/vsyscall_reverse_next.run",
    "content": "source `dirname $0`/util.sh\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/vsyscall_singlestep.run",
    "content": "source `dirname $0`/util.sh\nskip_if_test_32_bit\nrecord vsyscall$bitness\n_RR_TRACE_DIR=\"$workdir\" rr rerun -s 300 --singlestep=rip > /dev/null || failed \"Singlestepping through vsyscall failed\"\n"
  },
  {
    "path": "src/test/vsyscall_timeslice.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"util_internal.h\"\n\n#ifdef __x86_64__\nextern void generate_tick(long generate);\n\n__asm__(\n\"generate_tick:\\n\\t\"\n  \"test %rdi, %rdi\\n\\t\"\n  \"jnz 1f\\n\\t\"\n  \"ud2\\n\\t\"\n  \"1: retq\\n\\t\");\n\nstatic void test_vsyscall_timeslice_sig(void)\n{\n  intptr_t ret;\n  uintptr_t syscall = SYS_rrcall_arm_time_slice;\n  uintptr_t request = 1;\n  register long r10 __asm__(\"r10\") = 0;\n  register long r8 __asm__(\"r8\") = 0;\n  register long r9 __asm__(\"r9\") = 0;\n  __asm__ __volatile(\n    \"syscall\\n\\t\"\n    \"test %%rax, %%rax\\n\\t\"\n    \"jnz .Ldone\\n\\t\"\n    // Create a pipeline stall - the CPU will speculate through\n    // these, but because of the dependency from %rax (the result of the\n    // division) to the %rdi argument of generate_tick will not be able to\n    // retire the conditional branches therein, thus skidding our time\n    // slice signal into the vsyscall.\n    \"movq $1, %%rax\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    \"div %%rdi\\n\\t\"\n    // Two taken conditional branches here will trigger the\n    // time slice expiration. We expect this to skid into\n    // the subsequent vsyscall, triggering the condition we\n    // want to test\n    \"movq %%rax, %%rdi\\n\\t\"\n    // N.B.: This only works if the branches contained herein are\n    // predicted taken. Below we train the branch predictor to make\n    // sure this happens.\n    \"callq generate_tick\\n\\t\"\n    \"callq generate_tick\\n\\t\"\n    \"xorq %%rdi, %%rdi\\n\\t\"\n    \"movq $0xffffffffff600400, %%rax\\n\\t\" // time(NULL)\n    \"callq *%%rax\\n\\t\"\n    \".Ldone:\"\n    \"nop\\n\\t\"\n        : \"=a\"(ret)\n        : \"a\"(syscall), \"D\"(request), \"S\"(NULL), \"d\"(NULL),\n            \"r\"(r10), \"r\"(r8), \"r\"(r9)  : \"cc\", \"memory\");\n  test_assert(ret > 0);\n}\n\nvoid callback(uint64_t env, char *name, __attribute__((unused)) map_properties_t* props) {\n  if (strcmp(name, \"[vsyscall]\") == 0) {\n    int* has_vsyscall = (int*)(uintptr_t)env;\n    *has_vsyscall = 1;\n  }\n}\n#endif\n\nint main(void) {\n  // x86_64 only\n#ifdef __x86_64__\n  FILE* maps_file = fopen(\"/proc/self/maps\", \"r\");\n  int has_vsyscall = 0;\n  iterate_maps((uintptr_t)&has_vsyscall, callback, maps_file);\n\n  if (!running_under_rr()) {\n    atomic_puts(\"WARNING: This test only works under rr.\");\n  } else if (has_vsyscall) {\n    for (int i = 0; i < 20000; ++i) {\n      // Train the branch predictor that these branches are taken\n      generate_tick(1);\n    }\n    test_vsyscall_timeslice_sig();\n  }\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/wait.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i = 0;\n  pid_t pid;\n  int status;\n  siginfo_t si;\n\n  ++i;\n  pid = fork();\n  if (!pid) {\n    usleep(100);\n    exit(i);\n  }\n  test_assert(pid == wait(&status));\n  atomic_printf(\"%d exited with status %#x\\n\", pid, status);\n  test_assert(WIFEXITED(status) && i == WEXITSTATUS(status));\n\n  ++i;\n  pid = fork();\n  if (!pid) {\n    usleep(100);\n    exit(i);\n  }\n  test_assert(pid == waitpid(pid, &status, 0));\n  atomic_printf(\"%d exited with status %#x\\n\", pid, status);\n  test_assert(WIFEXITED(status) && i == WEXITSTATUS(status));\n\n  ++i;\n  pid = fork();\n  if (!pid) {\n    usleep(100);\n    exit(i);\n  }\n  test_assert(0 == waitid(P_PID, pid, &si, WEXITED | WSTOPPED));\n  atomic_printf(\"%d exited with exit-type %d; code %d\\n\", si.si_pid, si.si_code,\n                si.si_status);\n  test_assert(SIGCHLD == si.si_signo && CLD_EXITED == si.si_code);\n  test_assert(pid == si.si_pid && i == si.si_status);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/wait_for_all.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int do_child(void) {\n  sleep(1);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\nint main(void) {\n  if (!fork()) {\n    return do_child();\n  }\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/wait_for_all.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-w\"\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/wait_sigstop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct timespec ts = { 0, 5000000 }; /* 1ms */\n\n  /* Test case where child receives SIGSTOP while parent is in waitpid */\n  child = fork();\n  if (!child) {\n    test_assert(0 == nanosleep(&ts, NULL));\n    test_assert(0 == kill(getpid(), SIGSTOP));\n    return 77;\n  }\n\n  test_assert(child == waitpid(child, &status, WUNTRACED));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  test_assert(0 == kill(child, SIGCONT));\n  test_assert(child == waitpid(child, &status, WUNTRACED));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  /* Test case where child receives SIGSTOP before parent is in waitpid */\n  child = fork();\n  if (!child) {\n    test_assert(0 == kill(getpid(), SIGSTOP));\n    return 77;\n  }\n  test_assert(0 == nanosleep(&ts, NULL));\n\n  test_assert(child == waitpid(child, &status, WUNTRACED));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  test_assert(0 == kill(child, SIGCONT));\n  test_assert(child == waitpid(child, &status, WUNTRACED));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watch_code.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('watch -l *(int*)$pc')\nexpect_gdb('Hardware watchpoint 2')\n\nsend_gdb('reverse-continue')\nexpect_history_end()\n\nok()\n"
  },
  {
    "path": "src/test/watch_code.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug_gdb_only watch_code\n"
  },
  {
    "path": "src/test/watchpoint.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic volatile int var;\n\nstatic void* thread(__attribute__((unused)) void* unused) {\n  var = 1337;\n  return NULL;\n}\n\nint main(void) {\n  pthread_t t;\n\n  breakpoint();\n\n  var = 42;\n\n  pthread_create(&t, NULL, thread, NULL);\n  pthread_join(t, NULL);\n\n  atomic_printf(\"var=%d\\n\", var);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\n# Test write watchpoint\n\nsend_gdb('p &var')\nexpect_gdb(r'\\$1 = \\(volatile int \\*\\) ')\n\nsend_gdb('watch *$1')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 42')\n\nsend_gdb('c')\nexpect_gdb('Old value = 42')\nexpect_gdb('New value = 1337')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1')\n\n# Test read-write watchpoint\n\nsend_gdb('delete 2')\nsend_gdb('awatch *$1')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 3')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 42')\n\nsend_gdb('c')\nexpect_gdb('Old value = 42')\nexpect_gdb('New value = 1337')\n\nsend_gdb('c')\nexpect_gdb('Value = 1337')\n\nrestart_replay()\nexpect_gdb('Breakpoint 1')\n\n# Test read watchpoint. x86 treats these as read-write.\n\nsend_gdb('delete 3')\nsend_gdb('rwatch *$1')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 4')\n\nsend_gdb('c')\nexpect_gdb('Value = 42')\n\nsend_gdb('c')\nexpect_gdb('Value = 1337')\n\nsend_gdb('c')\nexpect_gdb('Value = 1337')\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/watchpoint_at_sched.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int x;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n  }\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  int i;\n  int v = 0;\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  /* Trigger async SCHED signal */\n  for (i = 0; i < 1000; ++i) {\n    v = v * 7 + 3;\n    x = v;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint_at_sched.py",
    "content": "from util import *\n\nsend_gdb('handle SIGKILL stop')\n\nsend_gdb('c')\nexpect_gdb('SIGKILL')\n\nsend_gdb('watch -l x')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 1')\n\nsend_gdb('rc')\nexpect_gdb('watchpoint 1')\nexpect_gdb('New value = 1564779003')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_at_sched.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS=\"-c50\"\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/watchpoint_before_signal.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int x;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n  }\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  int i;\n  int v = 0;\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  x = 1;\n\n  /* Trigger async SCHED signal */\n  for (i = 0; i < 1000; ++i) {\n    v = v * 7 + 3;\n  }\n\n  x = v;\n\n#if defined(__i386__) || defined(__x86_64__)\n  /* Trigger synchronous signal */\n  rdtsc();\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint_before_signal.py",
    "content": "from util import *\n\nsend_gdb('watch -l x')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 1')\n\nsend_gdb('c')\nexpect_gdb('Old value = 1')\nexpect_gdb('New value = -1931448864')\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_before_signal.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS=\"-c50\"\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/watchpoint_cond.py",
    "content": "from util import *\n\n# Test conditional hardware breakpoint. For some reason\n# gdb doesn't seem to use agent conditions for hardware\n# watchpoint types other than conditional breakpoints.\n\nsend_gdb('hbreak main')\nexpect_gdb('reakpoint 1')\nsend_gdb('cond 1 var==0x1234')\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_cond.run",
    "content": "source `dirname $0`/util.sh\nrecord watchpoint$bitness\ndebug_gdb_only watchpoint_cond\n"
  },
  {
    "path": "src/test/watchpoint_no_progress.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __x86_64__\n__asm__ (\"my_syscall: mov %rdi,%rax\\n\\t\"\n         \"syscall_instruction: syscall\\n\\t\"\n         \"ret\");\n#elif defined(__i386__)\n__asm__ (\"my_syscall: mov 4(%esp),%eax\\n\\t\"\n         \"syscall_instruction: int $0x80\\n\\t\"\n         \"ret\");\n#elif defined(__aarch64__)\n__asm__ (\"my_syscall: mov x8, x0\\n\\t\"\n         \"b 1f\\n\\t\"\n         \"mov x8, 0xdc\\n\"\n         \"1:\\n\\t\"\n         \"syscall_instruction: svc #0\\n\\t\"\n         \"ret\");\n#else\n#error define syscall here\n#endif\n\nextern void my_syscall(int number);\n\nint main(void) {\n  my_syscall(SYS_sched_yield);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 1;\n}\n"
  },
  {
    "path": "src/test/watchpoint_no_progress.py",
    "content": "from util import *\nimport re\n\narch = get_exe_arch()\n\nsend_gdb('hbreak *syscall_instruction')\nexpect_gdb('breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('stepi')\nif arch == 'aarch64':\n    send_gdb('print $pc == syscall_instruction + 4')\nelse:\n    send_gdb('print $pc == syscall_instruction + 2')\nexpect_gdb('= 1')\nsend_gdb('reverse-stepi')\nsend_gdb('print $pc == syscall_instruction')\nexpect_gdb('= 1')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_no_progress.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/watchpoint_size_change.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define SIZE (10*1024*1024)\n\nstatic void string_store(char* dest, uintptr_t a, uintptr_t size) {\n#if defined(__i386__) || defined(__x86_64__)\n  __asm__(\"rep stosb\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n#else\n  memset(dest, a, size);\n#endif\n}\n\nint main(void) {\n  char* p = xmalloc(SIZE);\n  memset(p, 0, SIZE);\n  string_store(p + 1, 1, SIZE - 10);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint_size_change.py",
    "content": "from util import *\n\n# Test conditional hardware breakpoint. For some reason\n# gdb doesn't seem to use agent conditions for hardware\n# watchpoint types other than conditional breakpoints.\n\nsend_gdb('break string_store')\nexpect_gdb('reakpoint 1')\nsend_gdb('c')\nexpect_gdb('reakpoint 1')\nsend_gdb('watch -l *(void**)(dest + 4095)')\nexpect_gdb('Hardware watchpoint 2')\nsend_gdb('c')\nexpect_gdb('Hardware watchpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_size_change.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/watchpoint_step.py",
    "content": "from util import *\n\nsend_gdb('break main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p &var')\nexpect_gdb(r'\\$1 = \\(volatile int \\*\\) ')\n\nsend_gdb('watch *$1')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 42')\n\nsend_gdb('reverse-stepi')\nexpect_gdb('Old value = 42')\nexpect_gdb('New value = 0')\n\nsend_gdb('stepi')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 42')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_step.run",
    "content": "source `dirname $0`/util.sh\nrecord watchpoint$bitness\ndebug_gdb_only watchpoint_step\n"
  },
  {
    "path": "src/test/watchpoint_syscall.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {}\n\nstatic char* p;\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  int fd = open(\"/dev/zero\", O_RDONLY);\n  test_assert(fd >= 0);\n\n  p = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                  MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(p != MAP_FAILED);\n\n  breakpoint();\n\n  *p = 'a';\n\n  test_assert(1 == read(fd, p, 1));\n  test_assert(*p == 0);\n\n  *p = 'b';\n\n  test_assert(p == mmap(p, page_size, PROT_READ | PROT_WRITE,\n                        MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0));\n  test_assert(*p == 0);\n\n  test_assert(0 == munmap(p, page_size));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint_syscall.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('watch -l *p')\nexpect_gdb('Hardware[()/a-z ]+watchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 97')\n\nsend_gdb('c')\nexpect_gdb('Old value = 97')\nexpect_gdb('New value = 0')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 98')\n\nsend_gdb('c')\nexpect_gdb('Old value = 98')\nexpect_gdb('New value = 0')\n\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = <unreadable>')\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_syscall.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/watchpoint_unaligned.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(__attribute__((unused)) uintptr_t wp_addr) {}\n\nvoid test(uintptr_t wp_addr, uintptr_t store_addr) {\n  breakpoint(wp_addr);\n  *(uint16_t *)store_addr = 0x0101;\n\n  breakpoint(wp_addr);\n  *(uint32_t *)store_addr = 0x02020202;\n\n  breakpoint(wp_addr);\n  *(uint64_t *)store_addr = 0x0303030303030303;\n}\n\nint main(void) {\n  char* m = xmalloc(0x1000);\n  uintptr_t aligned_addr = ((uintptr_t)m | 0xff) + 1;\n  test(aligned_addr - 1, aligned_addr - 1);\n  test(aligned_addr + 16, aligned_addr + 15);\n  test(aligned_addr + 15, aligned_addr + 16);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint_unaligned.py",
    "content": "from util import *\n\nbreakpoint = breakpoint_at_function('breakpoint')\n\ndef test():\n    for size in [2, 4, 8]:\n        cont()\n        expect_breakpoint_stop(breakpoint)\n        # Get the value of `wp_addr` from the parent frame.\n        # On Ubuntu 20 LTS, gdb stops before the `breakpoint` prelude so\n        # gets the wrong value of `wp_addr`.\n        up()\n        expect_debugger('test')\n        wp = watchpoint_at_address('wp_addr', size)\n        cont()\n        expect_watchpoint_stop(wp)\n        delete_watchpoint(wp)\n\ntest()\ntest()\ntest()\nok()\n"
  },
  {
    "path": "src/test/watchpoint_unaligned.run",
    "content": "source `dirname $0`/util.sh\ndebug_test\n"
  },
  {
    "path": "src/test/watchpoint_unaligned2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstruct {\n  uint32_t low;\n  uint32_t high;\n} value;\n\nint main(void) {\n  // -O3 should consolidate these into a single store.\n  value.low = 1;\n  value.high = 2;\n\n  // This will fail; we just want the compiler to not optimize out\n  // the store.\n  test_assert(-1 == write(-1, &value, sizeof(value)));\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/watchpoint_unaligned2.py",
    "content": "from util import *\n\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('watch -l value.high')\nexpect_gdb('Hardware watchpoint 2')\nsend_gdb('c')\nexpect_gdb('watchpoint 2')\nsend_gdb('delete 2')\n\nok()\n"
  },
  {
    "path": "src/test/watchpoint_unaligned2.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/when.py",
    "content": "from util import *\nimport re\n\nsend_custom_command('when')\nexpect_debugger(re.compile(r'Completed event: (\\d+)'))\nt = int(last_match().group(1))\nif t < 1 or t > 10000:\n    failed('ERROR in first \"when\"')\n\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nticks = int(last_match().group(1))\nif ticks != 0:\n    failed('ERROR in first \"when-ticks\"')\n\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\ntid = int(last_match().group(1))\n\nbp = breakpoint_at_function('main')\ncont()\nexpect_breakpoint_stop(bp)\n\nsend_custom_command('when')\nexpect_debugger(re.compile(r'Completed event: (\\d+)'))\nt2 = int(last_match().group(1))\nif t2 < 1 or t2 > 10000:\n    failed('ERROR in second \"when\"')\nif t2 <= t:\n    failed('ERROR ... \"when\" failed to advance')\n\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nticks2 = int(last_match().group(1))\nif ticks2 < 0 or ticks2 > 1000000:\n    failed('ERROR in second \"when-ticks\"')\nif ticks2 <= ticks:\n    failed('ERROR ... \"when-ticks\" failed to advance')\n\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\ntid2 = int(last_match().group(1))\nif tid2 != tid:\n    failed('ERROR ... tid changed')\n\n# Ensure 'when' terminates a diversion\nexpect_expression('(int)strlen(\"abcd\")', 4)\nsend_custom_command('when')\nexpect_debugger(re.compile(r'Completed event: (\\d+)'))\nt3 = int(last_match().group(1))\nif t3 != t2:\n    failed('ERROR ... diversion changed event')\n\nexpect_expression('(int)strlen(\"abcd\")', 4)\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nticks3 = int(last_match().group(1))\nif ticks3 != ticks2:\n    failed('ERROR ... diversion changed ticks')\n\nexpect_expression('(int)strlen(\"abcd\")', 4)\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\ntid3 = int(last_match().group(1))\nif tid3 != tid2:\n    failed('ERROR ... diversion changed tid')\n\nok()\n"
  },
  {
    "path": "src/test/when.run",
    "content": "source `dirname $0`/util.sh\nrecord simple$bitness\ndebug when\n"
  },
  {
    "path": "src/test/when_threads.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  pthread_create(&thread, NULL, do_thread, NULL);\n  sleep(1);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/when_threads.py",
    "content": "from util import *\nimport re\n\nbp = breakpoint_at_function('do_thread')\ncont()\nexpect_breakpoint_stop(bp)\n\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nthread_ticks = int(last_match().group(1))\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\nthread_tid = int(last_match().group(1))\n\nexpect_threads(2, 2)\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nthread_ticks2 = int(last_match().group(1))\nassert thread_ticks == thread_ticks2\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\nthread_tid2 = int(last_match().group(1))\nassert thread_tid == thread_tid2\n\nselect_thread(1)\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nmain_ticks = int(last_match().group(1))\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\nmain_tid = int(last_match().group(1))\n\nexpect_threads(2, 1)\nsend_custom_command('when-ticks')\nexpect_debugger(re.compile(r'Current tick: (\\d+)'))\nmain_ticks2 = int(last_match().group(1))\nassert main_ticks == main_ticks2\nsend_custom_command('when-tid')\nexpect_debugger(re.compile(r'Current tid: (\\d+)'))\nmain_tid2 = int(last_match().group(1))\nassert main_tid == main_tid2\n\nok()\n"
  },
  {
    "path": "src/test/when_threads.run",
    "content": "source `dirname $0`/util.sh\ndebug_test\n"
  },
  {
    "path": "src/test/write_race.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_PROCESSES 4\n#define NUM_ITERATIONS 500\n\nint main(void) {\n  int i;\n  int j;\n\n  for (i = 0; i < NUM_PROCESSES; ++i) {\n    if (0 == fork()) {\n      for (j = 0; j < NUM_ITERATIONS; ++j) {\n        char buf[1000];\n        sprintf(buf, \"Child %d writing line %d\\n\", i, j);\n        write(1, buf, strlen(buf));\n      }\n      return 0;\n    }\n  }\n\n  for (i = 0; i < NUM_PROCESSES; ++i) {\n    wait(NULL);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/writev.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char data[11] = \"0123456789\";\n\nstatic void test(int use_pwritev) {\n  static const char name[] = \"temp\";\n  int fd = open(name, O_CREAT | O_EXCL | O_RDWR, 0600);\n  struct {\n    char ch[50];\n  } * buf;\n  struct iovec iovs[2];\n  ssize_t nwritten;\n\n  test_assert(fd >= 0);\n  test_assert(0 == unlink(name));\n\n  iovs[0].iov_base = data;\n  iovs[0].iov_len = 7;\n  iovs[1].iov_base = data + iovs[0].iov_len;\n  iovs[1].iov_len = sizeof(data) - iovs[0].iov_len;\n  if (use_pwritev) {\n    /* Work around busted pwritev prototype in older libcs */\n    nwritten = syscall(SYS_pwritev, fd, iovs, 2, (off_t)0, 0);\n  } else {\n    nwritten = writev(fd, iovs, 2);\n  }\n  test_assert(sizeof(data) == nwritten);\n\n  ALLOCATE_GUARD(buf, 'x');\n  test_assert(sizeof(data) == pread(fd, buf, sizeof(*buf), 0));\n  test_assert(0 == memcmp(buf, data, sizeof(data)));\n  test_assert(buf->ch[sizeof(data)] == 'x');\n  VERIFY_GUARD(buf);\n}\n\nint main(void) {\n  test(0);\n  test(1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/arch_prctl_x86.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n#ifdef __x86_64__\n  unsigned long addr;\n  test_assert(0 == syscall(SYS_arch_prctl, ARCH_GET_FS, &addr));\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/arch_prctl_xstate.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifndef ARCH_GET_XCOMP_SUPP\n#define ARCH_GET_XCOMP_SUPP 0x1021\n#endif\n#ifndef ARCH_GET_XCOMP_PERM\n#define ARCH_GET_XCOMP_PERM 0x1022\n#endif\n#ifndef ARCH_REQ_XCOMP_PERM\n#define ARCH_REQ_XCOMP_PERM 0x1023\n#endif\n#ifndef ARCH_XCOMP_TILEDATA\n#define ARCH_XCOMP_TILEDATA 18\n#endif\n\nint main(void) {\n  uint64_t* features;\n  ALLOCATE_GUARD(features, 'a');\n  int ret = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_SUPP, features);\n  if (ret < 0 && errno == EINVAL) {\n    atomic_puts(\"XSTATE features not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(0 == ret);\n  VERIFY_GUARD(features);\n  atomic_printf(\"XSTATE features: %llx\\n\", (long long)*features);\n\n  uint64_t* features_perm;\n  ALLOCATE_GUARD(features_perm, 'b');\n  ret = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, features_perm);\n  test_assert(0 == ret);\n  VERIFY_GUARD(features_perm);\n  atomic_printf(\"XSTATE features permitted: %llx\\n\", (long long)*features_perm);\n\n  ret = syscall(SYS_arch_prctl, ARCH_REQ_XCOMP_PERM, ARCH_XCOMP_TILEDATA);\n  if ((1 << ARCH_XCOMP_TILEDATA) & *features_perm) {\n    test_assert(0 == ret);\n  } else if (0 == ret) {\n    ret = syscall(SYS_arch_prctl, ARCH_GET_XCOMP_PERM, features_perm);\n    test_assert(0 == ret);\n    VERIFY_GUARD(features_perm);\n    test_assert((1 << ARCH_XCOMP_TILEDATA) & *features_perm);\n  } else {\n    test_assert(-1 == ret && errno == EOPNOTSUPP);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/blocked_sigsegv.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void fault_handler(__attribute__((unused)) int sig,\n                          __attribute__((unused)) siginfo_t* si,\n                          __attribute__((unused)) void* context) {\n  atomic_puts(\"FAILED: handler should not have been called for blocked signal\");\n}\n\nstatic void* start_thread(__attribute__((unused)) void* p) {\n  sigset_t s;\n\n  sigemptyset(&s);\n  sigaddset(&s, SIGSEGV);\n  sigprocmask(SIG_BLOCK, &s, NULL);\n\n  rdtsc();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  crash_null_deref();\n\n  return NULL;\n}\n\nint main(void) {\n  struct sigaction act;\n  pthread_t thread;\n\n  act.sa_sigaction = fault_handler;\n  act.sa_flags = SA_SIGINFO | SA_NODEFER;\n  sigemptyset(&act.sa_mask);\n  sigaction(SIGSEGV, &act, NULL);\n\n  pthread_create(&thread, NULL, start_thread, NULL);\n  pthread_join(thread, NULL);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/blocked_sigsegv.run",
    "content": "source `dirname $0`/util.sh\n( record $TESTNAME ) >& /dev/null\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/break_rdtsc.run",
    "content": "source `dirname $0`/util.sh\nrecord rdtsc$bitness\ndebug_gdb_only generic_break\n"
  },
  {
    "path": "src/test/x86/chew_cpu_cpuid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NUM_ITERATIONS 1000000\n\nstatic void cpuid(void) {\n  int eax, ebx, ecx, edx;\n  asm volatile(\"cpuid\"\n               : \"=a\"(eax), \"=b\"(ebx), \"=c\"(ecx),\n                 \"=d\"(edx)\n               : \"a\"(0));\n}\n\nint spin(void) {\n  int i, dummy = 0;\n\n  /* NO SYSCALLS AFTER HERE: the point of this test is to hit\n   * hpc interrupts to exercise the nonvoluntary interrupt\n   * scheduler with some CPUID instructions in the mix. */\n  for (i = 1; i < NUM_ITERATIONS; ++i) {\n    dummy += i % (1 << 20);\n    dummy += i % (79 * (1 << 20));\n    if (i%1000 == 0) {\n      cpuid();\n    }\n  }\n  return dummy;\n}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  spin();\n  return NULL;\n}\n\nint main(void) {\n  pthread_t thread;\n  pthread_create(&thread, NULL, do_thread, NULL);\n  spin();\n  pthread_join(thread, NULL);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/cpuid.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nextern int cpuid_loop(int iterations);\n\nint main(void) {\n  int sum;\n  getegid();\n  sum = cpuid_loop(1000);\n  atomic_printf(\"EXIT-SUCCESS; sum=%d\\n\", sum);\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/cpuid.run",
    "content": "source `dirname $0`/util.sh\ncompare_test EXIT-SUCCESS\nif [[ $@ == -n ]]; then\n    bin=$(which $TESTNAME)\n    case $(file bin) in\n\t*x86-64*)\n\t    syscall=geteuid\n\t    ;;\n\t*i386*)\n\t    syscall=geteuid32\n\t    ;;\n\t*)\n\t    failed \"can't determine architecture\"\n\t    ;;\n    esac\n    rr --suppress-environment-warnings dump $workdir/latest-trace | \\\n        python3 $TESTDIR/check_syscall_perf_interval.py $syscall rbc 2\n    if [[ $? != 0 ]]; then\n        failed \"expected 2 rbcs between each geteuid32 syscall\"\n    fi\nfi\n"
  },
  {
    "path": "src/test/x86/cpuid_loop.S",
    "content": "#if defined(__i386__)\n        .text\n\n\n\n        .p2align 4,,15\n        .globl  cpuid_call\n        .type   cpuid_call, @function\ncpuid_call:\n_cpuid_call:\n        .cfi_startproc\n        pushl   %edi\n        .cfi_def_cfa_offset 8\n        .cfi_offset 7, -8\n        pushl   %esi\n        .cfi_def_cfa_offset 12\n        .cfi_offset 6, -12\n        pushl   %ebx\n        .cfi_def_cfa_offset 16\n        .cfi_offset 3, -16\n        xorl    %ebx, %ebx\n        movl    20(%esp), %esi\n        movl    %ebx, %eax\n        xchgl   %ebx, %edi\n        cpuid\n        xchgl   %ebx, %edi\n        movl    %eax, %ebx\n        xorl    %eax, %eax\n        cmpl    $4, %ebx\n        jbe     .L4\n        movl    16(%esp), %eax\n        andl    $4, %eax\n        cpuid\n        movl    %eax, (%esi)\n        movl    24(%esp), %eax\n        movl    %ebx, (%eax)\n        movl    (%esi), %eax\n.L4:\n        popl    %ebx\n        .cfi_restore 3\n        .cfi_def_cfa_offset 12\n        popl    %esi\n        .cfi_restore 6\n        .cfi_def_cfa_offset 8\n        popl    %edi\n        .cfi_restore 7\n        .cfi_def_cfa_offset 4\n        ret\n        .cfi_endproc\n.LFE89:\n        .size   cpuid_call, .-cpuid_call\n\n\n\n        .p2align 4,,15\n        .globl  cpuid_loop\n        .type   cpuid_loop, @function\ncpuid_loop:\n        .cfi_startproc\n        pushl   %ebp\n        .cfi_def_cfa_offset 8\n        .cfi_offset 5, -8\n        pushl   %edi\n        .cfi_def_cfa_offset 12\n        .cfi_offset 7, -12\n        pushl   %esi\n        .cfi_def_cfa_offset 16\n        .cfi_offset 6, -16\n        movl    16(%esp), %esi\n        pushl   %ebx\n        .cfi_def_cfa_offset 20\n        .cfi_offset 3, -20\n        xorl    %ebx, %ebx\n        subl    $44, %esp\n        .cfi_def_cfa_offset 64\n        leal    28(%esp), %ebp\n        leal    24(%esp), %edi\n        .p2align 4,,7\n        .p2align 3\n.L10:\n        movl    %ebx, (%esp)\n        movl    %ebp, 8(%esp)\n        movl    %edi, 4(%esp)\n        call    _cpuid_call\n        addl    %eax, %ebx\n        mov     $201, %eax\n        int     $0x80\n        subl    $1, %esi\n        jne     .L10\n        addl    $44, %esp\n        .cfi_def_cfa_offset 20\n        movl    %ebx, %eax\n        popl    %ebx\n        .cfi_restore 3\n        .cfi_def_cfa_offset 16\n        popl    %esi\n        .cfi_restore 6\n        .cfi_def_cfa_offset 12\n        popl    %edi\n        .cfi_restore 7\n        .cfi_def_cfa_offset 8\n        popl    %ebp\n        .cfi_restore 5\n        .cfi_def_cfa_offset 4\n        ret\n        .cfi_endproc\n        .size   cpuid_loop, .-cpuid_loop\n#elif defined(__x86_64__)\n        .text\n        .p2align 4,,15\n        .globl cpuid_call\n        .type  cpuid_call, @function\ncpuid_call:\n_cpuid_call:\n        pushq %rbx\n        /* Call CPUID twice, once under a conditional.  */\n        xorl %eax, %eax\n        cpuid\n        cmpl $4, %eax\n        jbe 1f\n        movl $1, %eax\n        cpuid\n1:\n        popq %rbx\n        ret\n        .size  cpuid_call, .-cpuid_call\n\n        .p2align 4,,15\n        .globl cpuid_loop\n        .type  cpuid_loop, @function\ncpuid_loop:\n        pushq %rbx\n        mov %rdi, %rbx\n        xor %r11d, %r11d\n1:\n        call _cpuid_call\n        addq %rax, %r11\n        mov $107, %rax\n        syscall\n        subq $1, %rbx\n        jne 1b\n        movq %r11, %rax\n        popq %rbx\n        ret\n        .size  cpuid_loop, .-cpuid_loop\n#else\n#error unknown CPU architecture\n#endif /* __i386__/__x86_64__ */\n        .section        .note.GNU-stack,\"\",@progbits\n"
  },
  {
    "path": "src/test/x86/cpuid_same_state.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n__attribute__((noinline))\nstatic void cpuid(int code, int subrequest, unsigned int* a, unsigned int* c,\n                  unsigned int* d) {\n  asm volatile(\"cpuid_instruction_label: cpuid\"\n               : \"=a\"(*a), \"=c\"(*c), \"=d\"(*d)\n               : \"a\"(code), \"c\"(subrequest)\n               : \"ebx\");\n}\n\nint main(void) {\n  unsigned int a, c, d;\n  cpuid(0, 2000, &a, &c, &d);\n  cpuid(0, 2000, &a, &c, &d);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/cpuid_singlestep.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void cpuid(int code, int subrequest, unsigned int* a, unsigned int* c,\n                  unsigned int* d) {\n  asm volatile(\"cpuid_instruction_label: cpuid\"\n               : \"=a\"(*a), \"=c\"(*c), \"=d\"(*d)\n               : \"a\"(code), \"c\"(subrequest)\n               : \"ebx\");\n}\n\nint main(void) {\n  unsigned int a, c, d;\n  /* CX ignored for AX==0 */\n  cpuid(0, 2000, &a, &c, &d);\n  test_assert(a > 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/cpuid_singlestep.py",
    "content": "from util import *\nimport re\n\nsend_gdb('break *cpuid_instruction_label')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nexpect_gdb('(rr)')\n\nsend_gdb('p $pc')\nexpect_gdb(re.compile(r'(0x[a-f0-9]+)'))\npc = eval(last_match().group(1));\nexpect_gdb('(rr)')\nsend_gdb('stepi')\nexpect_gdb('(rr)')\n\nsend_gdb('p $pc')\nexpect_gdb(re.compile(r'(0x[a-f0-9]+)'))\npc2 = eval(last_match().group(1));\nif pc2 - pc != 2:\n    failed('Expected 0x%x after singlestep, got 0x%x'%(pc + 2, pc2))\n\nsend_gdb('c')\nexpect_gdb('EXIT-SUCCESS')\n\nok()\n"
  },
  {
    "path": "src/test/x86/cpuid_singlestep.run",
    "content": "source `dirname $0`/util.sh\n# Try recording without CPUID faulting and then replaying with it\nGLOBAL_OPTIONS=--disable-cpuid-faulting\nrecord $TESTNAME\nGLOBAL_OPTIONS=\ndebug_gdb_only x86/cpuid_singlestep\n"
  },
  {
    "path": "src/test/x86/cross_arch.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#if !defined(__i386__) && !defined(__x86_64__)\n#error \"Adjust or disable this test for your architecture\"\n#else\nstatic int32_t my_syscall(uint32_t syscallno, uint32_t arg1, uint32_t arg2,\n                          uint32_t arg3) {\n  int32_t ret;\n  /* Use int $0x80 to do the syscall. This will use the i386 syscall table\n     regardless of whether or not this is a 64bit process or not */\n  asm(\"int $0x80\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      \"nop\\n\\t\"\n      : \"=a\"(ret)\n      : \"a\"(syscallno), \"b\"(arg1), \"c\"(arg2), \"d\"(arg3));\n  return ret;\n}\n#define SYS32_exit 1  /* write on x64 */\n#define SYS32_write 4 /* stat on x64 */\n#endif\n\nchar token[] = \"EXIT-SUCCESS\";\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* low_buffer = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                          MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, 0, 0);\n  memcpy(low_buffer, token, sizeof(token));\n  test_assert(sizeof(token) == my_syscall(SYS32_write, STDOUT_FILENO,\n                                          (uintptr_t)low_buffer,\n                                          sizeof(token)));\n  my_syscall(SYS32_exit, 0, 0, 0);\n  test_assert(0 && \"Should have exited\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/deferred_patch.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"rrcalls.h\"\n\n/*\n * When we see a syscall patch region in which the syscall is the last instruction,\n * we defer patching until we exit the corresponding syscall\n * (since we can't assume that we can jump to the top of the patch and re-execute\n * the preceeding instructions). This test tests a few corner cases:\n *\n * 1. When a syscall that had such a deferred patch is interrupted by a signal and the\n *    signal handler itself makes a syscall, we need to be sure that we don't accidentally\n *    try to patch that syscall.\n *\n * 2. If another thread is in the middle of the same syscall we need to make sure that we\n *    don't accidentally patch it (but do patch it on the exit of the second syscall).\n *\n * 3. If the signal handler rewrites the signal context to resume execution elsewhere, we still\n *    want to try patching the original syscall.\n */\n\n#ifdef __x86_64__\nstatic __attribute__((noinline)) uintptr_t deferred_patch_syscall(\n    uintptr_t syscall, uintptr_t arg1, uintptr_t arg2,\n    uintptr_t arg3, uintptr_t arg4) {\n  uintptr_t ret;\n  register uintptr_t r10 __asm__(\"r10\") = arg4;\n  register long r8 __asm__(\"r8\") = 0;\n  register long r9 __asm__(\"r9\") = 0;\n  __asm__ volatile(\n                   /* Use a syscall sequence for which we have a PATCH_SYSCALL_INSTRUCTION_IS_LAST */\n                   \".byte 0x0f, 0x1f, 0x44, 0x00, 0x00\\n\\t\"\n                   \"syscall\\n\\t\"\n                   /* Make sure we don't accidentally match any hook pattern with the instructions after */\n                   \"cmp $0x77,%%rax\\n\\t\"\n                   : \"=a\"(ret)\n                   : \"a\"(syscall), \"D\"(arg1), \"S\"(arg2), \"d\"(arg3), \"r\"(r10), \"r\"(r8), \"r\"(r9)\n                   : \"flags\");\n  return ret;\n}\n\nstatic __attribute__((noinline)) uintptr_t deferred_patch_syscall2(\n    uintptr_t syscall, uintptr_t arg1, uintptr_t arg2,\n    uintptr_t arg3, uintptr_t arg4) {\n  uintptr_t ret;\n  register uintptr_t r10 __asm__(\"r10\") = arg4;\n  register long r8 __asm__(\"r8\") = 0;\n  register long r9 __asm__(\"r9\") = 0;\n  __asm__ volatile(\n                   \".byte 0x0f, 0x1f, 0x44, 0x00, 0x00\\n\\t\"\n                   \"syscall\\n\\t\"\n                   \"cmp $0x77,%%rax\\n\\t\"\n                   : \"=a\"(ret)\n                   : \"a\"(syscall), \"D\"(arg1), \"S\"(arg2), \"d\"(arg3), \"r\"(r10), \"r\"(r8), \"r\"(r9)\n                   : \"flags\");\n  return ret;\n}\n\nint pipefds[2];\nint pipefds2[2];\nuint8_t byte = 0x1;\nvolatile uint32_t futex = 0;\n\nstatic void handle_alrm(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si, void* user) {\n  ucontext_t* ctx = (ucontext_t*)user;\n  // Skip the syscall and cmp after and have it return 0\n  ctx->uc_mcontext.gregs[REG_RIP] += 4;\n  ctx->uc_mcontext.gregs[REG_RAX] = 0;\n  futex = 1;\n  return;\n}\n\nstatic void handle_usr1(__attribute__((unused)) int sig) {\n  // Wake up child\n  test_assert(1 == write(pipefds2[1], &byte, 1));\n  // We need this read to desched, so that rr sees a syscall inside the rr page.\n  // We want to make sure that rr doesn't acccidentally try patching that syscall\n  // rather than the futex one that we interrupted.\n  test_assert(1 == read(pipefds[0], &byte, 1));\n  futex = 2;\n  test_assert(1 == write(pipefds2[1], &byte, 1));\n  return;\n}\n\nstatic void handle_usr2(__attribute__((unused)) int sig) {\n  futex = 3;\n  return;\n}\n\nstatic void futex_wait(uintptr_t val)\n{\n  test_assert((uintptr_t)-EAGAIN == deferred_patch_syscall(SYS_futex, (uintptr_t)&futex, FUTEX_WAIT, val, (uintptr_t)NULL));\n}\n\npid_t parent;\n\nstatic void *do_thread(__attribute__((unused)) void* p) {\n  test_assert(1 == read(pipefds2[0], &byte, 1));\n  sched_yield();\n  syscall(SYS_tkill, parent, SIGALRM);\n  test_assert(1 == read(pipefds2[0], &byte, 1));\n  sched_yield();\n  syscall(SYS_tkill, parent, SIGUSR1);\n  test_assert(1 == read(pipefds2[0], &byte, 1));\n  test_assert(1 == write(pipefds[1], &byte, 1));\n  test_assert(1 == read(pipefds2[0], &byte, 1));\n  futex_wait(2);\n  test_assert(futex == 3);\n  return NULL;\n}\n\nint main(void) {\n  test_assert(0 == pipe(pipefds));\n  test_assert(0 == pipe(pipefds2));\n\n  parent = sys_gettid();\n\n  pthread_t t;\n\n  // Setup signal handlers\n  struct sigaction sa;\n  sa.sa_sigaction = handle_alrm;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  test_assert(0 == sigaction(SIGALRM, &sa, NULL));\n  test_assert(0 == signal(SIGUSR1, handle_usr1));\n  test_assert(0 == signal(SIGUSR2, handle_usr2));\n\n  // Kick off driver thread\n  pthread_create(&t, NULL, do_thread, NULL);\n\n  // Wait for SIGALARM\n  test_assert(1 == write(pipefds2[1], &byte, 1));\n  test_assert(0 == deferred_patch_syscall2(SYS_futex, (uintptr_t)&futex, FUTEX_WAIT, 0, (uintptr_t)NULL));\n  test_assert(futex == 1);\n\n  // Wait for SIGUSR1\n  test_assert(1 == write(pipefds2[1], &byte, 1));\n  futex_wait(1);\n\n  // Issue SIGUSR2 in thread to let it out of the futex (and let it patch the syscall)\n  sched_yield(); sched_yield();\n  pthread_kill(t, SIGUSR2);\n  pthread_join(t, NULL);\n\n  // Make sure that the patching actually happened (if the syscallbuf is enabled)\n  uintptr_t ret = deferred_patch_syscall(SYS_rrcall_check_presence, RRCALL_CHECK_SYSCALLBUF_USED_OR_DISABLED, 0, 0, 0);\n  test_assert(ret == (uintptr_t)-ENOSYS || ret == 0);\n\n  ret = deferred_patch_syscall2(SYS_rrcall_check_presence, RRCALL_CHECK_SYSCALLBUF_USED_OR_DISABLED, 0, 0, 0);\n  test_assert(ret == (uintptr_t)-ENOSYS || ret == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n#else\nint main(void) {\n  atomic_puts(\"This test can only be run on x86_64. Skipping...\");\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 77;\n}\n#endif\n"
  },
  {
    "path": "src/test/x86/diversion_rdtsc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic uint64_t first;\n\nstatic __attribute__((noinline)) uint64_t buffered_rdtsc(void) {\n  return rdtsc();\n}\n\nvoid do_stuff(void) {\n  uint64_t second = buffered_rdtsc();\n  uint32_t third_lo;\n  uint32_t third_hi;\n  asm volatile (\"rdtsc\\n\\t\"\n                : \"=a\"(third_lo), \"=d\"(third_hi));\n  test_assert(first < second);\n  test_assert(second < ((uint64_t)third_hi << 32) + third_lo);\n  atomic_puts(\"Printed stuff OK\");\n}\n\nint main(void) {\n  first = buffered_rdtsc();\n\n  /* Diversion will start here */\n  breakpoint();\n\n  do_stuff();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/x86/diversion_rdtsc.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('call do_stuff()')\nexpect_gdb('Printed stuff OK')\n\nok()\n"
  },
  {
    "path": "src/test/x86/diversion_rdtsc.run",
    "content": "source `dirname $0`/util.sh\nrecord diversion_rdtsc$bitness\ndebug_gdb_only x86/diversion_rdtsc\n"
  },
  {
    "path": "src/test/x86/explicit_checkpoints.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint2(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void breakpoint3(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  /* NO SYSCALLS BETWEEN HERE AND RDTSC: next event for\n   * replay must be rdtsc */\n  rdtsc();\n  breakpoint2();\n  atomic_printf(\"Write syscall...\\n\");\n  breakpoint3();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/explicit_checkpoints.py",
    "content": "from util import *\nimport re\n\n# Setup breakpoints\nsend_gdb('b main')\nexpect_gdb('Breakpoint 1')\nsend_gdb('b breakpoint2')\nexpect_gdb('Breakpoint 2')\nsend_gdb('b breakpoint3')\nexpect_gdb('Breakpoint 3')\n\n# Empty checkpoint list\nsend_gdb('info checkpoint')\nexpect_gdb('No checkpoints.')\n\n# Create checkpoint at each breakpoint\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('checkpoint')\nindex = expect_list([re.compile(r'Checkpoint 1 at .*'), re.compile(r'ERROR')])\nif index > 0:\n    failed('ERROR detected in rr output')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2, breakpoint2')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 2 at')\nsend_gdb('c')\nexpect_gdb('Breakpoint 3, breakpoint3')\nsend_gdb('checkpoint')\nexpect_gdb('Checkpoint 3 at')\n\n# Checkpoint list\nsend_gdb('info checkpoint')\nexpect_gdb('ID\\tWhen\\tWhere')\nexpect_gdb('1\\t')\nexpect_gdb('2\\t')\nexpect_gdb('3\\t')\n\n# Resume checkpoints: each one stops at its breakpoint\nsend_gdb(\"restart 1\");\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2, breakpoint2')\nsend_gdb(\"restart 3\");\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_rr('exited normally')\nsend_gdb(\"restart 2\");\nexpect_gdb('stopped')\nsend_gdb('c')\nexpect_gdb('Breakpoint 3, breakpoint3')\n\n# Bare 'run' defaults to last resumed checkpoint\nrestart_replay()\nexpect_gdb('Breakpoint 3, breakpoint3')\n\n# Remove checkpoint 2 and try resuming it; it should fail\nsend_gdb('delete checkpoint 2')\nsend_gdb(\"restart 2\");\nsend_gdb('c')\nexpect_gdb('failed')\n\nsend_gdb('delete checkpoint')\nexpect_gdb('requires an argument')\n\nok()\n"
  },
  {
    "path": "src/test/x86/explicit_checkpoints.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/fault_in_code_page.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\ntypedef int (*fn_type)(void);\nstatic fn_type fn = NULL;\nstatic const uint8_t fn_insns[] = {\n  0xb8, 0x2a, 0x00, 0x00, 0x00, /* movl $42, %eax */\n  0xc3,                         /* ret */\n};\n\nstatic uint8_t* code_page;\nstatic size_t page_size;\n\nstatic int fault_count;\nstatic void fault_in_code_page(int sig, siginfo_t* si,\n                               __attribute__((unused)) void* context) {\n  atomic_printf(\"FAULT: signal %d: code %d for addr %p\\n\", sig, si->si_code,\n                si->si_addr);\n  test_assert(SIGSEGV == sig);\n  test_assert(SEGV_ACCERR == si->si_code);\n  test_assert(code_page == si->si_addr);\n  test_assert(1 == ++fault_count);\n\n  atomic_puts(\"  populating page...\");\n  test_assert(0 == mprotect(code_page, page_size, PROT_READ | PROT_WRITE));\n  test_assert(sizeof(fn_insns) < page_size);\n  memcpy(code_page, fn_insns, sizeof(fn_insns));\n\n  test_assert(0 == mprotect(code_page, page_size, PROT_READ | PROT_EXEC));\n  atomic_puts(\"  ... and protected it. sigreturn'ing\");\n}\n\nstatic uint64_t sigsegv_blocked_rdtsc(void) {\n  sigset_t s, old;\n\n  sigemptyset(&s);\n  sigaddset(&s, SIGSEGV);\n\n  sigprocmask(SIG_BLOCK, &s, &old);\n  uint64_t tsc = rdtsc();\n  sys_gettid();\n  sigprocmask(SIG_SETMASK, &old, NULL);\n\n  return tsc;\n}\n\nint main(void) {\n  struct sigaction act;\n\n  page_size = sysconf(_SC_PAGESIZE);\n\n  act.sa_sigaction = fault_in_code_page;\n  act.sa_flags = SA_SIGINFO;\n  sigemptyset(&act.sa_mask);\n  sigaction(SIGSEGV, &act, NULL);\n\n  atomic_printf(\"current tsc: %\" PRIu64 \"\\n\", sigsegv_blocked_rdtsc());\n\n  atomic_printf(\"    and now: %\" PRIu64 \"\\n\", sigsegv_blocked_rdtsc());\n\n  code_page =\n      mmap(NULL, page_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n  atomic_printf(\"(%d) mapped code page to %p\\n\", errno, code_page);\n  test_assert(code_page != (void*)-1);\n  fn = (fn_type)code_page;\n\n  atomic_printf(\"calling fn(), faulting ...\\n\");\n  int ret = fn();\n\n  atomic_printf(\"fn() returned %d\\n\", ret);\n  test_assert(42 == ret);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/fxregs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nenum cpuid_requests {\n  CPUID_GETFEATURES = 0x01,\n};\n\nstatic void cpuid(int code, int subrequest, unsigned int* a, unsigned int* c,\n                  unsigned int* d) {\n  asm volatile(\"cpuid\"\n               : \"=a\"(*a), \"=c\"(*c), \"=d\"(*d)\n               : \"a\"(code), \"c\"(subrequest)\n               : \"ebx\");\n}\n\nstatic __attribute__((used)) const double st0 = 1;\nstatic __attribute__((used)) const double st1 = 2;\nstatic __attribute__((used)) const double st2 = 3;\nstatic __attribute__((used)) const double st3 = 4;\nstatic __attribute__((used)) const double st4 = 5;\nstatic __attribute__((used)) const double st5 = 6;\nstatic __attribute__((used)) const double st6 = 7;\nstatic __attribute__((used)) const double st7 = 8;\n\nstatic __attribute__((used)) const float xmm0 = 10;\nstatic __attribute__((used)) const float xmm1 = 11;\nstatic __attribute__((used)) const float xmm2 = 12;\nstatic __attribute__((used)) const float xmm3 = 13;\nstatic __attribute__((used)) const float xmm4 = 14;\nstatic __attribute__((used)) const float xmm5 = 15;\nstatic __attribute__((used)) const float xmm6 = 16;\nstatic __attribute__((used)) const float xmm7 = 17;\nstatic __attribute__((used)) const float xmm8 = 18;\nstatic __attribute__((used)) const float xmm9 = 19;\nstatic __attribute__((used)) const float xmm10 = 20;\nstatic __attribute__((used)) const float xmm11 = 21;\nstatic __attribute__((used)) const float xmm12 = 22;\nstatic __attribute__((used)) const float xmm13 = 23;\nstatic __attribute__((used)) const float xmm14 = 24;\nstatic __attribute__((used)) const float xmm15 = 25;\n\n#define AVX_FEATURE_FLAG (1 << 28)\n#define OSXSAVE_FEATURE_FLAG (1 << 27)\n\nstatic int AVX_enabled;\n\nint main(void) {\n  unsigned int eax, ecx, edx;\n  unsigned int required_cpuid_flags = AVX_FEATURE_FLAG | OSXSAVE_FEATURE_FLAG;\n\n  cpuid(CPUID_GETFEATURES, 0, &eax, &ecx, &edx);\n  AVX_enabled = (ecx & required_cpuid_flags) == required_cpuid_flags;\n\n  if (!AVX_enabled) {\n    atomic_puts(\"AVX YMM registers disabled, not tested\");\n  }\n\n  __asm__ __volatile__(\n/* Push the constants in stack order so they look as\n * we expect in gdb. */\n#if __i386__\n      \"call __x86.get_pc_thunk.ax\\n\\t\"\n      \"addl $_GLOBAL_OFFSET_TABLE_, %eax\\n\\t\"\n      \"fldl st7@GOTOFF(%eax)\\n\\t\"\n      \"fldl st6@GOTOFF(%eax)\\n\\t\"\n      \"fldl st5@GOTOFF(%eax)\\n\\t\"\n      \"fldl st4@GOTOFF(%eax)\\n\\t\"\n      \"fldl st3@GOTOFF(%eax)\\n\\t\"\n      \"fldl st2@GOTOFF(%eax)\\n\\t\"\n      \"fldl st1@GOTOFF(%eax)\\n\\t\"\n      \"fldl st0@GOTOFF(%eax)\\n\\t\"\n      \"movss xmm0@GOTOFF(%eax), %xmm0\\n\\t\"\n      \"movss xmm1@GOTOFF(%eax), %xmm1\\n\\t\"\n      \"movss xmm2@GOTOFF(%eax), %xmm2\\n\\t\"\n      \"movss xmm3@GOTOFF(%eax), %xmm3\\n\\t\"\n      \"movss xmm4@GOTOFF(%eax), %xmm4\\n\\t\"\n      \"movss xmm5@GOTOFF(%eax), %xmm5\\n\\t\"\n      \"movss xmm6@GOTOFF(%eax), %xmm6\\n\\t\"\n      \"movss xmm7@GOTOFF(%eax), %xmm7\\n\\t\"\n#elif __x86_64__\n      \"fldl st7(%rip)\\n\\t\"\n      \"fldl st6(%rip)\\n\\t\"\n      \"fldl st5(%rip)\\n\\t\"\n      \"fldl st4(%rip)\\n\\t\"\n      \"fldl st3(%rip)\\n\\t\"\n      \"fldl st2(%rip)\\n\\t\"\n      \"fldl st1(%rip)\\n\\t\"\n      \"fldl st0(%rip)\\n\\t\"\n      \"movss xmm0(%rip), %xmm0\\n\\t\"\n      \"movss xmm1(%rip), %xmm1\\n\\t\"\n      \"movss xmm2(%rip), %xmm2\\n\\t\"\n      \"movss xmm3(%rip), %xmm3\\n\\t\"\n      \"movss xmm4(%rip), %xmm4\\n\\t\"\n      \"movss xmm5(%rip), %xmm5\\n\\t\"\n      \"movss xmm6(%rip), %xmm6\\n\\t\"\n      \"movss xmm7(%rip), %xmm7\\n\\t\"\n      \"movss xmm8(%rip), %xmm8\\n\\t\"\n      \"movss xmm9(%rip), %xmm9\\n\\t\"\n      \"movss xmm10(%rip), %xmm10\\n\\t\"\n      \"movss xmm11(%rip), %xmm11\\n\\t\"\n      \"movss xmm12(%rip), %xmm12\\n\\t\"\n      \"movss xmm13(%rip), %xmm13\\n\\t\"\n      \"movss xmm14(%rip), %xmm14\\n\\t\"\n      \"movss xmm15(%rip), %xmm15\\n\\t\"\n#else\n#error unexpected architecture\n#endif\n      );\n\n  if (AVX_enabled) {\n    __asm__ __volatile__(\n#if defined(__i386__) || defined(__x86_64__)\n        \"vinsertf128 $1,%xmm1,%ymm0,%ymm0\\n\\t\"\n        \"vinsertf128 $1,%xmm2,%ymm1,%ymm1\\n\\t\"\n        \"vinsertf128 $1,%xmm3,%ymm2,%ymm2\\n\\t\"\n        \"vinsertf128 $1,%xmm4,%ymm3,%ymm3\\n\\t\"\n        \"vinsertf128 $1,%xmm5,%ymm4,%ymm4\\n\\t\"\n        \"vinsertf128 $1,%xmm6,%ymm5,%ymm5\\n\\t\"\n        \"vinsertf128 $1,%xmm7,%ymm6,%ymm6\\n\\t\"\n        \"vinsertf128 $1,%xmm0,%ymm7,%ymm7\\n\\t\"\n#endif\n#ifdef __x86_64__\n        \"vinsertf128 $1,%xmm9,%ymm8,%ymm8\\n\\t\"\n        \"vinsertf128 $1,%xmm10,%ymm9,%ymm9\\n\\t\"\n        \"vinsertf128 $1,%xmm11,%ymm10,%ymm10\\n\\t\"\n        \"vinsertf128 $1,%xmm12,%ymm11,%ymm11\\n\\t\"\n        \"vinsertf128 $1,%xmm13,%ymm12,%ymm12\\n\\t\"\n        \"vinsertf128 $1,%xmm14,%ymm13,%ymm13\\n\\t\"\n        \"vinsertf128 $1,%xmm15,%ymm14,%ymm14\\n\\t\"\n        \"vinsertf128 $1,%xmm8,%ymm15,%ymm15\\n\\t\"\n#endif\n        );\n  }\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/fxregs.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1, breakpoint')\n\n# See fxregs.c for the list of constants that are loaded into the\n# $st*, $xmm* and $ymm* registers.\nfor i in range(8):\n    send_gdb('p $st%d'%(i))\n    expect_gdb(' = %d'%(i + 1))\n\nfor i in range(8):\n    send_gdb('p $xmm%d.v4_float[0]'%(i))\n    expect_gdb(' = %d'%(i + 10))\n\nsend_gdb('show architecture')\nhave_64 = 0 == expect_list([re.compile('i386:x86-64\"?\\)'), re.compile('i386\"?\\)')])\n\nif have_64:\n    for i in range(8,16):\n        send_gdb('p $xmm%d.v4_float[0]'%(i))\n        expect_gdb(' = %d'%(i + 10))\n\nsend_gdb('p AVX_enabled')\nhave_AVX = 0 == expect_list([re.compile(' = 1'), re.compile(' = 0')])\n\nif have_AVX:\n    for i in range(8):\n        send_gdb('p $ymm%d.v8_float[0]'%(i))\n        expect_gdb(' = %d'%(i + 10))\n        send_gdb('p $ymm%d.v8_float[4]'%(i))\n        expect_gdb(' = %d'%((i + 1)%8 + 10))\n    if have_64:\n        for i in range(8,16):\n            send_gdb('p $ymm%d.v8_float[0]'%(i))\n            expect_gdb(' = %d'%(i + 10))\n            send_gdb('p $ymm%d.v8_float[4]'%(i))\n            expect_gdb(' = %d'%((i - 8 + 1)%8 + 18))\n\nok()\n"
  },
  {
    "path": "src/test/x86/fxregs.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/gdb_avx512.c",
    "content": "static int set_registers(void) {\n\n    __attribute__((aligned(64))) unsigned char increasing[64];\n    __attribute__((aligned(64))) unsigned char decreasing[64];\n\n    for (int i = 0; i < 64; i++) {\n        increasing[i] = i + 1;\n        decreasing[i] = 0xFF - i;\n    }\n\n    // __m512i zmm1;  // Declare the ZMM register variable\n    // Inline assembly to fill the registers\n    __asm__ volatile (\n        \"vmovdqu64 %0, %%zmm0  \\n\\t\"  // Load increasing bytes into zmm0\n        :: \"m\"(increasing)\n        :\n    );\n    __asm__ volatile (\n        \"vmovdqu64 %0, %%zmm1  \\n\\t\"  // Load increasing bytes into zmm0\n        :: \"m\"(decreasing)\n        :\n    );\n    return 0;\n}\n\nstatic int broadcast_to_three_zmm(void) {\n    asm volatile (\n        \"vpbroadcastb %0, %%zmm0 \\n\\t\"\n        :\n        : \"r\"(0x1a)\n        : \"zmm0\"\n    );\n#if !defined(__ILP32__)\n    asm volatile (\n        \"vpbroadcastb %0, %%zmm16 \\n\\t\"\n        :\n        : \"r\"(0x5b)\n        :\n    );\n    asm volatile (\n        \"vpbroadcastb %0, %%zmm30 \\n\\t\"\n        :\n        : \"r\"(0xff)\n        :\n    );\n#else // 32-bit only has 0-8 vector registers\n    asm volatile (\n        \"vpbroadcastb %0, %%zmm4 \\n\\t\"\n        :\n        : \"r\"(0x5b)\n        : \"zmm4\"\n    );\n    asm volatile (\n        \"vpbroadcastb %0, %%zmm7 \\n\\t\"\n        :\n        : \"r\"(0xff)\n        : \"zmm7\"\n    );\n#endif\n    return 0;\n}\n\nint main(void)\n{\n  int a = set_registers();\n  int b = broadcast_to_three_zmm();\n  return a + b;\n}\n"
  },
  {
    "path": "src/test/x86/gdb_avx512.py",
    "content": "from util import *\nimport sys\nimport os\n\ntest = os.getenv(\"TESTNAME\")\n\n# Breakpoint on return 0;\nsend_gdb(\"break 23\")\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb(\"print/x $xmm0.v16_int8\")\nexpect_gdb(\"0x1.*0x2.*0x3.*0x4.*0x5.*0x6.*0x7.*0x8.*0x9.*0xa.*0xb.*0xc.*0xd.*0xe.*0xf.*0x10\")\n\nsend_gdb(\"print/x $ymm0.v32_int8\")\nexpect_gdb(\"0x1.*0x2.*0x3.*0x4.*0x5.*0x6.*0x7.*0x8.*0x9.*0xa.*0xb.*0xc.*0xd.*0xe.*0xf.*0x10.*0x11.*0x12.*0x13.*0x14.*0x15.*0x16.*0x17.*0x18.*0x19.*0x1a.*0x1b.*0x1c.*0x1d.*0x1e.*0x1f.*0x20\")\n\nsend_gdb(\"print/x $zmm0.v64_int8\")\nexpect_gdb(\"0x1.*0x2.*0x3.*0x4.*0x5.*0x6.*0x7.*0x8.*0x9.*0xa.*0xb.*0xc.*0xd.*0xe.*0xf.*0x10.*0x11.*0x12.*0x13.*0x14.*0x15.*0x16.*0x17.*0x18.*0x19.*0x1a.*0x1b.*0x1c.*0x1d.*0x1e.*0x1f.*0x20.*0x21.*0x22.*0x23.*0x24.*0x25.*0x26.*0x27.*0x28.*0x29.*0x2a.*0x2b.*0x2c.*0x2d.*0x2e.*0x2f.*0x30.*0x31.*0x32.*0x33.*0x34.*0x35.*0x36.*0x37.*0x38.*0x39.*0x3a.*0x3b.*0x3c.*0x3d.*0x3e.*0x3f.*0x40\")\n\n# Breakpoint on return 0;\nsend_gdb('break 60')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb(\"print/x $xmm0.uint128\")\nexpect_gdb(r\"0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a\")\n\nsend_gdb(\"print/x $ymm0.v2_int128\")\nexpect_gdb(r\"0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a,\\s+0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a\")\n\nsend_gdb(\"print/x $zmm0.v4_int128\")\nexpect_gdb(r\"0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a,\\s+0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a,\\s+0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a,\\s+0x1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a\")\n\nregs_per_mode = []\n\nif test[-3:] == \"_32\":\n  regs_per_mode = [4, 7]\nelse:\n  regs_per_mode = [16, 30]\n\nsend_gdb(f\"print/x $xmm{regs_per_mode[0]}.uint128\")\nexpect_gdb(r\"0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b\")\n\nsend_gdb(f\"print/x $ymm{regs_per_mode[0]}.v2_int128\")\nexpect_gdb(r\"0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b,\\s+0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b\")\n\nsend_gdb(f\"print/x $zmm{regs_per_mode[0]}.v4_int128\")\nexpect_gdb(r\"0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b,\\s+0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b,\\s+0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b,\\s+0x5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b\")\n\nsend_gdb(f\"print/x $xmm{regs_per_mode[1]}.uint128\")\nexpect_gdb(r\"0xffffffffffffffffffffffffffffffff\")\n\nsend_gdb(f\"print/x $ymm{regs_per_mode[1]}.v2_int128\")\nexpect_gdb(r\"0xffffffffffffffffffffffffffffffff,\\s+0xffffffffffffffffffffffffffffffff\")\n\nsend_gdb(f\"print/x $zmm{regs_per_mode[1]}.v4_int128\")\nexpect_gdb(r\"0xffffffffffffffffffffffffffffffff,\\s+0xffffffffffffffffffffffffffffffff,\\s+0xffffffffffffffffffffffffffffffff,\\s+0xffffffffffffffffffffffffffffffff\")\n\nsend_gdb('c')\nok()\n"
  },
  {
    "path": "src/test/x86/gdb_avx512.run",
    "content": "# check if we have avx512, if not, don't run test\n\nif ! lscpu | grep -q \"avx512f\"; then\n    echo \"not running avx512 test\"\n    exit 0\nfi\n\nsource `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/hle.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int lock;\nstatic int accumulator = 9999;\n\nstatic void hle_abort(void) {\n  int j;\n#if defined(__x86_64__) || defined(__i386__)\n  /* Use .byte 0xf2 instead of XACQUIRE for old assemblers */\n  asm(\".byte 0xf2; lock addl $1,%0\\n\\t\" : : \"m\"(lock));\n#else\n#error Unknown architecture\n#endif\n  /* Execute some conditional branches */\n  for (j = 0; j < 10; ++j) {\n    if ((accumulator % 2) == 0) {\n      accumulator /= 2;\n    } else {\n      accumulator = accumulator * 3 + 1;\n    }\n  }\n  /* Force abort */\n  sched_yield();\n#if defined(__x86_64__) || defined(__i386__)\n  /* Use .byte 0xf3 instead of XRELEASE for old assemblers */\n  asm(\".byte 0xf3; lock subl $1,%0\\n\\t\" : : \"m\"(lock));\n#else\n#error Unknown architecture\n#endif\n}\n\nint main(void) {\n  int i;\n  sched_yield();\n  for (i = 0; i < 1000; ++i) {\n    hle_abort();\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/hlt.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void skip_handler(__attribute__((unused)) int sig,\n                         __attribute__((unused)) siginfo_t* si, void* user) {\n  ucontext_t* ctx = (ucontext_t*)user;\n#if defined(__i386__)\n  ctx->uc_mcontext.gregs[REG_EIP] += 1;\n#elif defined(__x86_64__)\n  ctx->uc_mcontext.gregs[REG_RIP] += 1;\n#else\n#error unknown architecture\n#endif\n}\n\nint main(void) {\n  int status;\n  pid_t child;\n\n  child = fork();\n  if (!child) {\n    struct sigaction sa;\n    sa.sa_sigaction = skip_handler;\n    sigemptyset(&sa.sa_mask);\n    sa.sa_flags = SA_SIGINFO;\n    test_assert(0 == sigaction(SIGSEGV, &sa, NULL));\n\n    asm volatile (\"hlt\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 77;\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/int3_ok.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  debug_trap();\n  /* NB: the above instruction *must* be at line 6 in this file.\n   * Tests rely on that. */\n}\n\nint main(void) {\n  atomic_puts(\"doing int3 ...\");\n\n  breakpoint();\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/int3_ok.run",
    "content": "source `dirname $0`/util.sh\nRECORD_ARGS=-t5\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/x86/ioperm.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret;\n  ret = syscall(SYS_ioperm, 0, 1024, 1);\n  atomic_printf(\"ioperm returned %d\\n\", ret);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/iopl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int ret;\n  ret = syscall(SYS_iopl, 3);\n  atomic_printf(\"iopl returned %d\\n\", ret);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/la57.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n#ifdef __x86_64__\n  size_t num_bytes = sysconf(_SC_PAGESIZE);\n  /* NB: No MAP_FIXED here, to allow the test to pass on systems without\n   * 5 level paging.\n   */\n  void* map = mmap((void*)(1ULL << 47), num_bytes, PROT_READ | PROT_WRITE,\n                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n  test_assert(map != MAP_FAILED);\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/lsl.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int value;\n  asm volatile (\"lsl %1,%0\" : \"=r\"(value) : \"r\"(0x7b));\n  atomic_printf(\"%d\\n\", value);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/modify_ldt.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include <asm/ldt.h>\n\nint main(void) {\n  uint32_t limit = 0x1234;\n  struct user_desc desc = {.entry_number = 0,\n                           .base_addr = 0x0,\n                           .limit = limit,\n                           .seg_32bit = 1,\n                           .contents = 2,\n                           .read_exec_only = 0,\n                           .seg_not_present = 0,\n                           .useable = 1 };\n  test_assert(0 == syscall(SYS_modify_ldt, 0x11, &desc, sizeof(desc)));\n  uint32_t new_limit = 0, has_limit = 0;\n  uint32_t selector = (desc.entry_number << 3) | 0x4 /* LDT */ | 0x3 /* RPL */;\n  asm(\"lsl %[selector], %[the_limit]\\n\\t\"\n      \"jnz 1f\\n\\tmovl $1, %[has_limit]\\n\\t1:\"\n      : [the_limit] \"=r\"(new_limit), [has_limit] \"+rm\"(has_limit)\n      : [selector] \"r\"(selector));\n  test_assert(has_limit && new_limit == limit);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/morestack_unwind.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void start_test(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nint main(void) {\n  // glibc write() might only be patched after the first time it is executed.\n  atomic_puts(\"Ensure glibc write() is patched...\");\n\n  start_test();\n  // The test requires this write() be buffered:\n  atomic_puts(\"EXIT-SUCCESS\");\n  breakpoint();\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/morestack_unwind.py",
    "content": "from util import *\n\nsend_gdb('break start_test')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('break _syscall_hook_trampoline')\nexpect_gdb('Breakpoint 2')\nsend_gdb('c')\nexpect_gdb('Breakpoint 2')\n\nsend_gdb('fin')\nsend_gdb('fin')\nsend_gdb('fin')\n\n# Verify we didn't run too far\n\nsend_gdb('b breakpoint')\nexpect_gdb('Breakpoint 3')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 3')\n\nok()\n"
  },
  {
    "path": "src/test/x86/morestack_unwind.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/old_fork.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  pid_t child;\n  int status;\n\n  if (0 == (child = syscall(SYS_fork))) {\n    return 11;\n  }\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 11);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/patch_40_80_f6_81.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#if defined(__i386__)\n/* Don't do anything for 32 bit. */\n#elif defined(__x86_64__)\nstatic const uint8_t code[] = { 0x40, 0x80, 0xf6, 0x81, 0x0f, 0x05, 0xc3, 0x99 };\n\nstatic long do_call(pid_t pid, uint8_t* p) {\n  long ret;\n  __asm__ __volatile__(\"call *%2\\n\\t\" : \"=a\"(ret) : \"a\"(SYS_kill), \"c\"(p), \"D\"(pid), \"S\"(0x8F));\n  return ret;\n}\n\nstatic void check_patch(uint8_t* p) { test_assert(p[0] == 0xe9); }\n\nstatic int caught_signal = 0;\nstatic void handle_signal(__attribute__((unused)) int sig) { ++caught_signal; }\n#else\n#error unsupported arch\n#endif\n\nint main(void) {\n#ifdef __x86_64__\n  signal(SIGALRM, handle_signal);\n\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* p = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,\n                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  pid_t pid = getpid();\n  test_assert(p != MAP_FAILED);\n  test_assert(0 == munmap(p + page_size, page_size));\n  memcpy(p, code, sizeof(code));\n\n  test_assert(0 == mprotect(p, page_size, PROT_READ | PROT_EXEC));\n  do_call(pid, p);\n  do_call(pid, p);\n  test_assert(caught_signal == 2);\n  check_patch(p); // If run outside of rr, we should die here.\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/patch_40_80_f6_81.run",
    "content": "source `dirname $0`/util.sh\n\n# This test requires syscallbuf syscall patching\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/patch_pc_rel.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#if defined(__i386__)\n/* Don't do anything for 32 bit. */\n#elif defined(__x86_64__)\n/* nop x 8; rdtsc; mov -17(%rip),%r9; ret */\nstatic const uint8_t code[] = { 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n                                0x0f, 0x31, 0x4c, 0x8b, 0x0d, 0xef, 0xff, 0xff, 0xff,\n                                0xc3 };\n\nstatic unsigned long do_call(uint8_t* p) {\n  unsigned long ret;\n  __asm__ __volatile__(\"call *%1\\n\\t\"\n                       \"mov %%r9,%%rax\" : \"=a\"(ret) : \"r\"(p) : \"r9\", \"rdx\");\n  return ret;\n}\n\nstatic void check_patch(uint8_t* p) { test_assert(p[8] == 0xe9); }\n#else\n#error unsupported arch\n#endif\n\nint main(void) {\n#ifdef __x86_64__\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* p = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  memcpy(p, code, sizeof(code));\n\n  test_assert(0 == mprotect(p, page_size, PROT_READ | PROT_EXEC));\n  test_assert(do_call(p) == 0x9090909090909090L);\n  check_patch(p); // If run outside of rr, we should die here.\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/patch_pc_rel.run",
    "content": "source `dirname $0`/util.sh\n\n# This test requires syscallbuf syscall patching\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/patch_syscall_restart.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#if defined(__i386__)\n/* Don't do anything for 32 bit. */\n#elif defined(__x86_64__)\nstatic int pipe_fds[2];\n\n/* Syscall-bufferable version of read(fd, buf, 1).\n   Designed to be patched at the mov $0xffffffffffffffff,%%r9.\n   This will be patched only after the syscall returns. */\nstatic void read_one_byte(int fd) {\n  char buf[1];\n  __asm__ __volatile__(\"mov $0xffffffffffffffff,%%r9\\n\\t\"\n                       \"syscall\\n\\t\"\n                       \"or %%rsp,%%rsp\\n\\t\"\n                       : : \"a\"(SYS_read), \"D\"(fd), \"S\"(buf), \"d\"(1)\n                       : \"r9\");\n}\n\nstatic void handle_signal(__attribute__((unused)) int sig) {}\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  /* Try to read a byte from pipe_fds[0]; this should block forever. */\n  read_one_byte(pipe_fds[0]);\n  /* We should never reach here because the read should automatically restart\n     after the signal */\n  atomic_puts(\"FAILED\");\n  exit(1);\n  return NULL;\n}\n#else\n#error unsupported arch\n#endif\n\nint main(void) {\n#ifdef __x86_64__\n  pthread_t thread;\n  struct timespec ten_ms = { 0, 10000000 };\n\n  pipe(pipe_fds);\n  signal(SIGUSR1, handle_signal);\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n  /* Allow the child thread to run until it blocks in the buffered read. */\n  nanosleep(&ten_ms, NULL);\n  /* Read from an invalid fd. This should trigger syscallbuf patching\n     of the syscall in read_one_byte. That patching needds to *fail*\n     because the child thread is currently blocked in the syscall\n     and will need to restart the syscall after we signal it;\n     if the syscall instruction is patched out, that restart\n     won't happen and this test fails. */\n  read_one_byte(-1);\n  pthread_kill(thread, SIGUSR1);\n  // The child thread should still be blocked. Let it run again to make sure.\n  nanosleep(&ten_ms, NULL);\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/pkeys.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef PKEY_DISABLE_ACCESS\nenum cpuid_requests {\n  CPUID_GETEXTENDEDFEATURES = 0x07,\n};\n\nstatic void cpuid(int code, int subrequest, unsigned int* a, unsigned int* c,\n                  unsigned int* d) {\n  asm volatile(\"cpuid\"\n               : \"=a\"(*a), \"=c\"(*c), \"=d\"(*d)\n               : \"a\"(code), \"c\"(subrequest)\n               : \"ebx\");\n}\n\nstatic unsigned int rdpkru(void) {\n  unsigned int eax;\n  unsigned int ecx = 0;\n\n  asm volatile(\".byte 0x0f,0x01,0xee\\n\\t\"\n               : \"=a\" (eax) : \"c\" (ecx) : \"edx\");\n  return eax;\n}\n\nstatic void wrpkru(unsigned int pkru) {\n  unsigned int eax = pkru;\n  unsigned int ecx = 0;\n  unsigned int edx = 0;\n\n  asm volatile(\".byte 0x0f,0x01,0xef\\n\\t\"\n               : : \"a\" (eax), \"c\" (ecx), \"d\" (edx));\n}\n\nstatic char* p;\n\nstatic void unset_pkey(__attribute__((unused)) int sig) {\n  syscall(SYS_pkey_mprotect, p, 4096, PROT_READ | PROT_WRITE, 0);\n}\n\nint main(void) {\n  unsigned int eax, ecx, edx;\n  cpuid(CPUID_GETEXTENDEDFEATURES, 0, &eax, &ecx, &edx);\n  if (!(ecx & (1 << 3))) {\n    // PKU not present.\n    atomic_puts(\"pkeys not supported on this system, skipping\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  unsigned int initial_pkru = rdpkru();\n  test_assert(initial_pkru == 0x55555554);\n  int pkey = syscall(SYS_pkey_alloc, 0, 0);\n  int ret;\n  if (pkey < 0 && errno == ENOSYS) {\n    atomic_puts(\"pkeys not supported in kernel, skipping\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  if (pkey < 0 && (errno == ENOSPC || errno == EINVAL)) {\n    atomic_puts(\"pkeys not supported on this system, skipping\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(pkey >= 0);\n  unsigned int modified_pkru = rdpkru();\n  test_assert(initial_pkru == (modified_pkru | PKEY_DISABLE_ACCESS << (2 * pkey)));\n  test_assert((initial_pkru & ~(PKEY_DISABLE_ACCESS << (2 * pkey ))) == modified_pkru);\n\n  p = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  ret = syscall(SYS_pkey_mprotect, p, 4096, PROT_READ | PROT_WRITE, pkey);\n  test_assert(ret == 0);\n  p[0] = 1;\n\n  wrpkru(PKEY_DISABLE_ACCESS << (2 * pkey));\n  signal(SIGSEGV, unset_pkey);\n  p[0] = 2;\n\n  ret = syscall(SYS_pkey_free, pkey);\n  test_assert(ret == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n#else\nint main(void) {\n  atomic_puts(\"pkeys not supported on the machine compiling this test, skipping\");\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n#endif\n"
  },
  {
    "path": "src/test/x86/ptrace.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define NEW_VALUE 0xabcdef\n\nstatic size_t static_data = 0x12345678;\n\nenum cpuid_requests {\n  CPUID_GETFEATURES = 0x01,\n  CPUID_GETXSAVE = 0x0D,\n};\n\nstatic void cpuid(int code, int subrequest, unsigned int* a, unsigned int* c,\n                  unsigned int* d) {\n  asm volatile(\"cpuid\"\n               : \"=a\"(*a), \"=c\"(*c), \"=d\"(*d)\n               : \"a\"(code), \"c\"(subrequest)\n               : \"ebx\");\n}\n\nstatic size_t find_xsave_size(void) {\n  unsigned int eax, ecx, edx;\n  cpuid(CPUID_GETFEATURES, 0, &eax, &ecx, &edx);\n  if (!(ecx & (1 << 26))) {\n    // XSAVE not present\n    return 0;\n  }\n\n  // We'll use the largest possible area all the time\n  // even when it might not be needed. Simpler that way.\n  cpuid(CPUID_GETXSAVE, 0, &eax, &ecx, &edx);\n  return ecx;\n}\n\n/*\n * Let's talk about why this is necessary, because in theory it shouldn't be.\n *\n * Intel defines bytes 416-511 of the (FP)XSAVE area as reserved and none of the\n * xsave instructions touch it. However, bytes 464-511 are used by the linux\n * kernel to keep metadata about the memory layout of the frame. That leaves\n * bytes 416-463 to cause trouble. Note that while these bytes do not have any\n * corresponding register values, the kernel does keep a copy in the fpu\n * structure. The kernel zeros these bytes on allocation, but ptrace moves them\n * in and out of the kernel fairly non-discriminately, so if these bytes end up\n * non-zero we'll notice in this test, which brings us to how they actually end\n * up non-zero in this test (spoiler not via ptrace):\n *\n * When rr forks a new task, it sends an artificial signal to that new task in\n * order to force the preload library to set up its required task-local state.\n * When the kernel delivers a signal, it sets up a signal frame with information\n * about the signal as well as the full register state of the current thread.\n * Now, when it comes time to save out the FPU state, the kernel uses the xsave\n * instruction directly to write out the registers, but as mentioned, those\n * instructions do not touch the reserved area. Bits 464-511 then get touched\n * up manually with the required information, but bits 416-463 are not touched\n * at all, so they end up with whatever happened to be on the stack when the\n * kernel sets up the signal frame. However, when the kernel restores the\n * register state from the signal frame, it first copies in the entire area into\n * its internal data structures, and then restores the actual registers from\n * there. This means that the bits 416-463 which had invalid stack data in them\n * are now saved in the kernel fpu data structure and thus observable from\n * ptrace.\n *\n * Lastly, note that this depends on whether or not the current CPU has support\n * for the XSAVES instruction (and if not whether fpregs are active for the\n * current thread). If that is not the case, writing out also happens from\n * the fpu data structure and the reserved area is thus preserved.\n */\nstatic void clear_reserved_area(uint8_t* fxregs) {\n  int i;\n  for (i = 416; i < 464; ++i) {\n    fxregs[i] = 0;\n  }\n}\n\nint main(void) {\n  pid_t child;\n  int status;\n  struct user_regs_struct* regs;\n  struct user_regs_struct* regs2;\n  struct user_fpregs_struct* fpregs;\n  struct user_fpregs_struct* fpregs2;\n#ifdef __i386__\n  struct user_fpxregs_struct* fpxregs;\n#endif\n  void* xsave_regs;\n  struct iovec iov;\n  int ret;\n  size_t xsave_size = find_xsave_size();\n  uintptr_t saved_ip;\n  siginfo_t* siginfo;\n  int dummy[4] = { 1, 2, 3, 4 };\n\n  if (0 == (child = fork())) {\n    /* Ensure XMM registers are modified so that ptrace will read\n       the real registers, not stale registers. Working around kernel bug.\n       Also, puts them in a known state in case they were actually used.\n     */\n    asm(\"movdqu %0,%%xmm0\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm1\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm2\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm3\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm4\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm5\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm6\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm7\" ::\"m\"(dummy));\n#ifdef __x86_64__\n    asm(\"movdqu %0,%%xmm8\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm9\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm10\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm11\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm12\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm13\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm14\" ::\"m\"(dummy));\n    asm(\"movdqu %0,%%xmm15\" ::\"m\"(dummy));\n#endif\n\n    // Also initialize at least one ymm register. Otherwise the initial state\n    // optimization might prevent the kernel from writing this state component.\n    if (xsave_size > 576) {\n      asm(\"vinsertf128 $128,%0,%%ymm2,%%ymm1\" ::\"m\"(dummy));\n    }\n\n    kill(getpid(), SIGSTOP);\n    test_assert(static_data == NEW_VALUE);\n    return 77;\n  }\n\n  test_assert(0 == ptrace(PTRACE_SEIZE, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n\n  ALLOCATE_GUARD(regs, 0xFF);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, regs));\n  VERIFY_GUARD(regs);\n#if defined(__i386__)\n  test_assert((int32_t)regs->eip != -1);\n  test_assert((int32_t)regs->esp != -1);\n  saved_ip = regs->eip;\n  regs->eip = 77;\n#elif defined(__x86_64__)\n  test_assert((int64_t)regs->rip != -1);\n  test_assert((int64_t)regs->rsp != -1);\n  saved_ip = regs->rip;\n  regs->rip = 77;\n#else\n#error unknown architecture\n#endif\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, regs));\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, regs));\n#if defined(__i386__)\n  test_assert((int32_t)regs->eip == 77);\n  regs->eip = saved_ip;\n#elif defined(__x86_64__)\n  test_assert((int64_t)regs->rip == 77);\n  regs->rip = saved_ip;\n#else\n#error unknown architecture\n#endif\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSEGV);\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, regs));\n\n  ALLOCATE_GUARD(siginfo, 0xFE);\n  test_assert(0 == ptrace(PTRACE_GETSIGINFO, child, NULL, siginfo));\n  VERIFY_GUARD(siginfo);\n  test_assert(siginfo->si_signo == SIGSEGV);\n  test_assert(siginfo->si_code == SEGV_MAPERR);\n  test_assert(siginfo->si_addr == (void*)77);\n\n  ALLOCATE_GUARD(fpregs, 0xBB);\n  test_assert(0 == ptrace(PTRACE_GETFPREGS, child, NULL, fpregs));\n  test_assert(NULL == memchr(fpregs, 0xBB, sizeof(*fpregs)));\n  VERIFY_GUARD(fpregs);\n  fpregs->cwd = -1;\n  test_assert(0 == ptrace(PTRACE_SETFPREGS, child, NULL, fpregs));\n  {\n    struct user_fpregs_struct fpregs3;\n    test_assert(0 == ptrace(PTRACE_GETFPREGS, child, NULL, &fpregs3));\n    test_assert(0 == memcmp(fpregs, &fpregs3, sizeof(fpregs3)));\n  }\n\n#ifdef __i386__\n  ALLOCATE_GUARD(fpxregs, 0xCC);\n  test_assert(0 == ptrace(PTRACE_GETFPXREGS, child, NULL, fpxregs));\n  clear_reserved_area((uint8_t*)fpxregs);\n  test_assert(NULL == memchr(fpxregs, 0xCC, sizeof(*fpxregs)));\n  VERIFY_GUARD(fpxregs);\n  fpxregs->xmm_space[0] = 0xFFFFF;\n  test_assert(0 == ptrace(PTRACE_SETFPXREGS, child, NULL, fpxregs));\n\n  {\n    struct user_fpxregs_struct fpxregs3;\n    test_assert(0 == ptrace(PTRACE_GETFPXREGS, child, NULL, &fpxregs3));\n    test_assert(0 == memcmp(fpxregs, &fpxregs3, sizeof(fpxregs3)));\n  }\n#endif\n\n  ALLOCATE_GUARD(regs2, 0xCD);\n  iov.iov_base = regs2;\n  iov.iov_len = sizeof(*regs2);\n  test_assert(0 == ptrace(PTRACE_GETREGSET, child, (void*)NT_PRSTATUS, &iov));\n  test_assert(iov.iov_len == sizeof(*regs2));\n  test_assert(0 == memcmp(regs, regs2, sizeof(*regs)));\n  VERIFY_GUARD(regs2);\n  test_assert(0 == ptrace(PTRACE_SETREGSET, child, (void*)NT_PRSTATUS, &iov));\n\n  ALLOCATE_GUARD(fpregs2, 0xCE);\n  iov.iov_base = fpregs2;\n  iov.iov_len = sizeof(*fpregs2);\n  test_assert(0 == ptrace(PTRACE_GETREGSET, child, (void*)NT_FPREGSET, &iov));\n  test_assert(iov.iov_len == sizeof(*fpregs2));\n  test_assert(0 == memcmp(fpregs, fpregs2, sizeof(*fpregs)));\n  VERIFY_GUARD(fpregs2);\n  test_assert(0 == ptrace(PTRACE_SETREGSET, child, (void*)NT_FPREGSET, &iov));\n\n  if (xsave_size > 0) {\n    int len;\n    xsave_regs = allocate_guard(xsave_size, 0xCF);\n    iov.iov_base = xsave_regs;\n    iov.iov_len = xsave_size;\n    ret = ptrace(PTRACE_GETREGSET, child, (void*)NT_X86_XSTATE, &iov);\n    test_assert(0 == ret);\n    test_assert(iov.iov_len <= xsave_size);\n    len = iov.iov_len;\n    if (len > 832) {\n      /* Only look at the first 832 bytes since the rest may contain unknown\n         xsave data which may validly contain 0xCF */\n      len = 832;\n    }\n    clear_reserved_area((uint8_t*)xsave_regs);\n    test_assert(NULL == memchr(xsave_regs, 0xCF, len));\n    verify_guard(xsave_size, xsave_regs);\n\n    test_assert(0 ==\n                ptrace(PTRACE_SETREGSET, child, (void*)NT_X86_XSTATE, &iov));\n  }\n\n  test_assert(static_data ==\n              (size_t)ptrace(PTRACE_PEEKDATA, child, &static_data, NULL));\n  test_assert(0 ==\n              ptrace(PTRACE_POKEDATA, child, &static_data, (void*)NEW_VALUE));\n  test_assert(NEW_VALUE == ptrace(PTRACE_PEEKDATA, child, &static_data, NULL));\n\n  /* Test invalid locations */\n  test_assert(-1 == ptrace(PTRACE_PEEKDATA, child, NULL, NULL));\n  test_assert(errno == EIO || errno == EFAULT);\n  test_assert(-1 == ptrace(PTRACE_POKEDATA, child, NULL, (void*)NEW_VALUE));\n  test_assert(errno == EIO || errno == EFAULT);\n\n  test_assert((long)regs->eflags ==\n              ptrace(PTRACE_PEEKUSER, child,\n                     (void*)offsetof(struct user, regs.eflags), NULL));\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, regs.eflags), 0x246));\n  test_assert(0 == ptrace(PTRACE_PEEKUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[0]), NULL));\n  test_assert(0 == ptrace(PTRACE_PEEKUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]), NULL));\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[0]),\n                          (void*)55));\n  test_assert(55 == ptrace(PTRACE_PEEKUSER, child,\n                           (void*)offsetof(struct user, u_debugreg[0]), NULL));\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[0]),\n                          (void*)0));\n#ifdef __x86_64__\n  // On x86-64 the user struct also includes error_code and fault_address at the\n  // end. This is not in glibc's copy of user.\n  test_assert(0 == ptrace(PTRACE_PEEKUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[9]), NULL));\n#endif\n\n  /* Test invalid signal in continue */\n  test_assert(-1 == ptrace(PTRACE_CONT, child, NULL, -1) && errno == EIO);\n  test_assert(-1 == ptrace(PTRACE_CONT, child, NULL, _NSIG + 1) &&\n              errno == EIO);\n\n  test_assert(0 == ptrace(PTRACE_DETACH, child, NULL, NULL));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status));\n  test_assert(WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/ptrace_debug_regs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n// The 4 lowest bits of DR6.\n#define DR_TRAP_BITS 0xf\n#define NEW_VALUE 0xabcdef\n\nstatic void breakpoint(void) {}\n\nstatic char watch_var;\n\nint main(void) {\n  pid_t child;\n  int status;\n  int pipe_fds[2];\n\n  test_assert(0 == pipe(pipe_fds));\n\n  if (0 == (child = fork())) {\n    char ch;\n    read(pipe_fds[0], &ch, 1);\n    breakpoint();\n    watch_var = 1;\n    return 77;\n  }\n\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGSTOP << 8) | 0x7f));\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[0]),\n                          (void*)breakpoint));\n  /* Enable DR0 break-on-exec */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0x1));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  test_assert(0x1 == (ptrace(PTRACE_PEEKUSER, child,\n                             (void*)offsetof(struct user, u_debugreg[6])) & DR_TRAP_BITS));\n\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[0]),\n                          &watch_var));\n  /* Enable DR0 break-on-write */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0x10001));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  test_assert(0x1 == (ptrace(PTRACE_PEEKUSER, child,\n                             (void*)offsetof(struct user, u_debugreg[6])) & DR_TRAP_BITS));\n\n  test_assert(0 == ptrace(PTRACE_DETACH, child, NULL, NULL));\n\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status));\n  test_assert(WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/ptrace_exec32.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic int original_syscallno(const struct user_regs_struct* regs) {\n#if defined(__i386__)\n  return regs->orig_eax;\n#elif defined(__x86_64__)\n  return regs->orig_rax;\n#else\n#error unknown architecture\n#endif\n}\n\nstatic int syscall_result(const struct user_regs_struct* regs) {\n#if defined(__i386__)\n  return regs->eax;\n#elif defined(__x86_64__)\n  return regs->rax;\n#else\n#error unknown architecture\n#endif\n}\n\nint main(int argc, char** argv) {\n  pid_t child;\n  int status;\n  struct user_regs_struct regs;\n  char* name;\n\n  if (sizeof(void*) == 4) {\n    atomic_puts(\"EXIT-SUCCESS\");\n    return argc <= 1 ? 0 : atoi(argv[1]);\n  }\n\n  asprintf(&name, \"%s_32\", argv[0]);\n  if (access(name, F_OK)) {\n    atomic_printf(\"%s not found; skipping test\\n\", name);\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n\n  if (0 == (child = fork())) {\n    char* args[] = { name, \"77\", NULL };\n    kill(getpid(), SIGSTOP);\n    execve(name, args, environ);\n    /* should never reach here */\n    test_assert(0);\n    return 1;\n  }\n\n  test_assert(0 == ptrace(PTRACE_ATTACH, child, NULL, NULL));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  while (1) {\n    test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n    test_assert(child == waitpid(child, &status, 0));\n    if (status == ((SIGTRAP << 8) | 0x7f)) {\n      break;\n    }\n    test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n  }\n\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* Without rr, the old syscall number persists in orig_eax. Under rr,\n     we update the syscall number to be correct for the new architecture\n     to simplify rr's workings. */\n  test_assert(SYS_execve == original_syscallno(&regs) ||\n              11 == original_syscallno(&regs));\n  test_assert(0 == syscall_result(&regs));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/ptrace_sysemu.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n#include \"../ptrace_util.h\"\n\n/* This tests PTRACE_SYSEMU, PTRACE_SINGLESTEP and PTRACE_SYSEMU_SINGLESTEP */\n\n#define DS_SINGLESTEP (1 << 14)\n\n#ifdef SYS_geteuid32\n#define SYSCALLNO SYS_geteuid32\n#else\n#define SYSCALLNO SYS_geteuid\n#endif\n\nextern char syscall_addr;\n\nstatic void wait_for_syscall_enter(pid_t child) {\n  int status;\n  siginfo_t si;\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == (((0x80 | SIGTRAP) << 8) | 0x7f));\n  test_assert(0 == ptrace(PTRACE_GETSIGINFO, child, NULL, &si));\n  test_assert(SIGTRAP == si.si_signo);\n}\n\nstatic void wait_for_singlestep(pid_t child) {\n  int status;\n  siginfo_t si;\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  test_assert(0 == ptrace(PTRACE_GETSIGINFO, child, NULL, &si));\n  test_assert(SIGTRAP == si.si_signo);\n}\n\nstatic void check_dr6(pid_t child) {\n#if defined(__i386__) || defined(__x86_64__)\n  uintptr_t dr6;\n  errno = 0;\n  dr6 = ptrace(PTRACE_PEEKUSER, child,\n               (void*)offsetof(struct user, u_debugreg[6]), (void*)0);\n  test_assert(!errno);\n  test_assert(dr6 & DS_SINGLESTEP);\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[6]),\n                          (void*)0));\n#endif\n}\n\nint main(int argc, char** argv) {\n  pid_t child;\n  int status;\n  int pipe_fds[2];\n  struct user_regs_struct regs;\n  uid_t uid = geteuid();\n  char ch;\n  int strict = !(argc == 2 && !strcmp(argv[1], \"relaxed\"));\n\n  test_assert(0 == pipe(pipe_fds));\n  test_assert(1 == write(pipe_fds[1], \"x\", 1));\n  /* Make sure 'read' path is patched properly, because we won't patch it\n   * once ptrace has attached.\n   */\n  test_assert(1 == read(pipe_fds[0], &ch, 1));\n\n  if (0 == (child = fork())) {\n    uid_t ret;\n    kill(getpid(), SIGSTOP);\n    /* This will be skipped by the ptracer */\n    syscall(SYS_exit, 6);\n    ret = my_geteuid();\n    test_assert(ret == uid);\n    ret = my_geteuid();\n    test_assert(ret == uid);\n    ret = my_geteuid();\n    test_assert(ret == uid);\n    ret = my_geteuid();\n    test_assert(ret == uid);\n    /* This 'read' is skipped by the ptracer. */\n    read(pipe_fds[0], &ch, 1);\n    return 77;\n  }\n\n  test_assert(0 ==\n              ptrace(PTRACE_SEIZE, child, NULL, (void*)PTRACE_O_TRACESYSGOOD));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  /* Test PTRACE_SYSEMU running into syscall */\n  test_assert(0 == ptrace(PTRACE_SYSEMU, child, NULL, (void*)0));\n  wait_for_syscall_enter(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  test_assert(SYS_exit == regs.ORIG_SYSCALLNO);\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n\n  /* Test PTRACE_SINGLESTEP stepping out of a syscall.\n     We make sure it doesn't run. If the syscall runs then the child will\n     exit prematurely. */\n  test_assert(0 == ptrace(PTRACE_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n\n  /* Test PTRACE_SYSEMU running into syscall */\n  test_assert(0 == ptrace(PTRACE_SYSEMU, child, NULL, (void*)0));\n  wait_for_syscall_enter(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* This assert will fail if we patched the syscall for syscallbuf. */\n  test_assert(&syscall_addr + SYSCALL_SIZE == (char*)regs.IP);\n  test_assert(SYSCALLNO == regs.ORIG_SYSCALLNO);\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n\n  /* Test PTRACE_SINGLESTEP stepping out of a syscall */\n  test_assert(0 == ptrace(PTRACE_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n  test_assert(&syscall_addr + SYSCALL_SIZE == (char*)regs.IP);\n  regs.SYSCALL_RESULT = uid;\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, &regs));\n\n  /* Test PTRACE_SINGLESTEP stepping normally */\n  test_assert(0 == ptrace(PTRACE_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  check_dr6(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  test_assert(&syscall_addr + 3 == (char*)regs.IP);\n\n  /* Test PTRACE_SYSEMU_SINGLESTEP stepping normally */\n  test_assert(0 == ptrace(PTRACE_SYSEMU_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  check_dr6(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  test_assert(&syscall_addr + 4 == (char*)regs.IP);\n\n  /* Set a HW breakpoint at |syscall_addr| */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[0]),\n                          &syscall_addr));\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0x1));\n  /* Run to it */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  /* Disable breakpoint */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0));\n\n  /* Test PTRACE_SYSEMU_SINGLESTEP stepping into syscall */\n  test_assert(0 == ptrace(PTRACE_SYSEMU_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_syscall_enter(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* This assert will fail if we patched the syscall for syscallbuf. */\n  test_assert(&syscall_addr + 2 == (char*)regs.IP);\n  test_assert(SYSCALLNO == regs.ORIG_SYSCALLNO);\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n\n  /* Test PTRACE_SYSEMU_SINGLESTEP stepping out of a syscall */\n  test_assert(0 == ptrace(PTRACE_SYSEMU_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* check that syscall did not run */\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n  /* PTRACE_SYSEMU_SINGLESTEP does an extra instruction when stepping out\n     of a syscall. Dunno why. */\n  test_assert(&syscall_addr + 2 == (char*)regs.IP ||\n              (!strict && &syscall_addr + 3 == (char*)regs.IP));\n  regs.SYSCALL_RESULT = uid;\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, &regs));\n\n  /* Reenable breakpoint */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0x1));\n  /* Run to it */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  /* Disable breakpoint */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0));\n\n  /* Test PTRACE_SYSCALL entering syscall */\n  test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n  wait_for_syscall_enter(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  test_assert(&syscall_addr + 2 == (char*)regs.IP);\n  test_assert(SYSCALLNO == regs.ORIG_SYSCALLNO);\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n  /* force syscall to be invalid/skipped */\n  regs.ORIG_SYSCALLNO = -1;\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, &regs));\n\n  /* Test PTRACE_SYSEMU_SINGLESTEP stepping out of a syscall */\n  test_assert(0 == ptrace(PTRACE_SYSEMU_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* check that syscall did not run */\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n  /* PTRACE_SYSEMU_SINGLESTEP does an extra instruction when stepping out\n     of a syscall. Dunno why. */\n  test_assert(&syscall_addr + 2 == (char*)regs.IP ||\n              (!strict && &syscall_addr + 3 == (char*)regs.IP));\n  regs.SYSCALL_RESULT = uid;\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, &regs));\n\n  /* Reenable breakpoint */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0x1));\n  /* Run to it */\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(status == ((SIGTRAP << 8) | 0x7f));\n  /* Disable breakpoint */\n  test_assert(0 == ptrace(PTRACE_POKEUSER, child,\n                          (void*)offsetof(struct user, u_debugreg[7]),\n                          (void*)0));\n\n  /* Test PTRACE_SINGLESTEP stepping over syscall */\n  test_assert(0 == ptrace(PTRACE_SINGLESTEP, child, NULL, (void*)0));\n  wait_for_singlestep(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* This assert will fail if we patched the syscall for syscallbuf. */\n  test_assert(&syscall_addr + 2 == (char*)regs.IP);\n  test_assert(SYSCALLNO == regs.ORIG_SYSCALLNO);\n  test_assert((uid_t)regs.SYSCALL_RESULT == uid);\n\n  /* Test PTRACE_SYSCALL entering buffered 'read' syscall.\n     This tests that privileged syscalls for arming/disarming\n     desched events are ignored. */\n  test_assert(0 == ptrace(PTRACE_SYSCALL, child, NULL, (void*)0));\n  wait_for_syscall_enter(child);\n  test_assert(0 == ptrace(PTRACE_GETREGS, child, NULL, &regs));\n  /* We allow syscallbuf patching of 'read' so don't check the IP. */\n  test_assert(SYS_read == regs.ORIG_SYSCALLNO);\n  test_assert(-ENOSYS == (int)regs.SYSCALL_RESULT);\n  /* force syscall to be invalid/skipped */\n  regs.ORIG_SYSCALLNO = -1;\n  test_assert(0 == ptrace(PTRACE_SETREGS, child, NULL, &regs));\n\n  test_assert(0 == ptrace(PTRACE_CONT, child, NULL, (void*)0));\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 77);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/ptrace_tls.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <asm/ldt.h>\n#include <asm/prctl.h>\n#include <linux/unistd.h>\n#include <sys/prctl.h>\n\n#ifndef PTRACE_GET_THREAD_AREA\n#define PTRACE_GET_THREAD_AREA 25\n#endif\n\n#ifndef PTRACE_SET_THREAD_AREA\n#define PTRACE_SET_THREAD_AREA 26\n#endif\n\n#ifndef PTRACE_ARCH_PRCTL\n#define PTRACE_ARCH_PRCTL 30\n#endif\n\nint main(void) {\n\n  pid_t child;\n  int status;\n  size_t page_size = sysconf(_SC_PAGESIZE);\n\n  uint8_t pattern = 0xab;\n  uint8_t pattern_verify = 0;\n\n#if defined(__i386__)\n\n  // The minimum usable TLS descriptor varies between kernel configurations\n  // Allocate the next usable one in the parent, which should then also be\n  // available in the child.\n  struct user_desc parent_desc;\n  parent_desc.entry_number = -1;\n  parent_desc.base_addr = ((uintptr_t)&main & ~(page_size - 1));\n  parent_desc.limit = 1;\n  parent_desc.seg_32bit = 1;\n  parent_desc.contents = 0;\n  parent_desc.read_exec_only = 0;\n  parent_desc.limit_in_pages = 1;\n  parent_desc.seg_not_present = 0;\n  parent_desc.useable = 1;\n\n  test_assert(0 == syscall(SYS_set_thread_area, &parent_desc));\n#endif\n\n  if (0 == (child = fork())) {\n    ptrace(PTRACE_TRACEME, 0, 0, 0);\n    raise(SIGSTOP);\n#if defined(__i386__)\n    struct user_desc desc;\n    memset(&desc, 0, sizeof(struct user_desc));\n    desc.entry_number = parent_desc.entry_number;\n    test_assert(0 == syscall(SYS_get_thread_area, &desc));\n    test_assert(desc.base_addr == ((uintptr_t)&main & ~(page_size - 1)));\n    test_assert(desc.limit == 1);\n    desc.limit = 2;\n    test_assert(0 == syscall(SYS_set_thread_area, &desc));\n    desc.limit = 0;\n    test_assert(0 == syscall(SYS_get_thread_area, &desc));\n    test_assert(desc.limit == 2);\n    raise(SIGSTOP);\n    asm(\"mov %1, %%fs\\n\\t\"\n        \"mov %%fs:0, %0\"\n        : \"=r\"(pattern_verify)\n        : \"r\"(desc.entry_number << 3 | 3));\n    test_assert(pattern_verify == pattern);\n    raise(SIGSTOP);\n\n#elif defined(__x86_64__)\n    uintptr_t gs_base, fs_base;\n    test_assert(0 == syscall(SYS_arch_prctl, ARCH_GET_GS, &gs_base));\n    test_assert(0 == syscall(SYS_arch_prctl, ARCH_GET_FS, &fs_base));\n    test_assert(0 == syscall(SYS_arch_prctl, ARCH_SET_GS, gs_base + 0x10));\n\n    pid_t pid = getpid();\n    // Avoid entering libc for anything too complex, until we're back from the\n    // SIGSTOP.\n    // The TLS is invalid, so anything that looks at it may cause strange\n    // behavior\n    int err = syscall(SYS_arch_prctl, ARCH_SET_FS, fs_base - 0x10);\n    syscall(SYS_tgkill, pid, sys_gettid(), SIGSTOP);\n    test_assert(err == 0);\n\n    uintptr_t new_gs_base, new_fs_base;\n    test_assert(0 == syscall(SYS_arch_prctl, ARCH_GET_GS, &new_gs_base));\n    test_assert(0 == syscall(SYS_arch_prctl, ARCH_GET_FS, &new_fs_base));\n    test_assert(gs_base == new_gs_base);\n    test_assert(fs_base == new_fs_base);\n    raise(SIGSTOP);\n\n    asm(\"mov %%gs:0, %0\" : \"=r\"(pattern_verify) :);\n    test_assert(pattern_verify == pattern);\n    raise(SIGSTOP);\n#else\n#error Test any architecture specific TLS options here\n#endif\n    return 0;\n  }\n\n  /* Wait until the tracee stops */\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n#if defined(__i386__)\n  test_assert(0 == ptrace(PTRACE_SET_THREAD_AREA, child,\n                          parent_desc.entry_number, &parent_desc));\n\n  /* Restart the tracee, which will look at and modify this */\n  ptrace(PTRACE_CONT, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  test_assert(0 == ptrace(PTRACE_GET_THREAD_AREA, child,\n                          parent_desc.entry_number, &parent_desc));\n  test_assert(parent_desc.limit == 2);\n\n  /* Next we're going to verify that these are actually reflected into the LDT\n     during execution */\n  parent_desc.base_addr = (uintptr_t)&pattern;\n  test_assert(0 == ptrace(PTRACE_SET_THREAD_AREA, child,\n                          parent_desc.entry_number, &parent_desc));\n\n  /* Restart the tracee */\n  ptrace(PTRACE_CONT, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n#elif defined(__x86_64__)\n  (void)page_size;\n  uintptr_t gs_base, fs_base;\n  ptrace(PTRACE_ARCH_PRCTL, child, &gs_base, ARCH_GET_GS);\n  ptrace(PTRACE_ARCH_PRCTL, child, &fs_base, ARCH_GET_FS);\n\n  /* Restart the tracee, which will modify these */\n  ptrace(PTRACE_CONT, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  uintptr_t new_gs_base, new_fs_base;\n  ptrace(PTRACE_ARCH_PRCTL, child, &new_gs_base, ARCH_GET_GS);\n  ptrace(PTRACE_ARCH_PRCTL, child, &new_fs_base, ARCH_GET_FS);\n  test_assert(new_gs_base == gs_base + 0x10);\n  test_assert(new_fs_base == fs_base - 0x10);\n\n  /* Reset these. The tracee will make sure that it can see them */\n  ptrace(PTRACE_ARCH_PRCTL, child, fs_base, ARCH_SET_FS);\n  ptrace(PTRACE_ARCH_PRCTL, child, gs_base, ARCH_SET_GS);\n\n  /* Restart the tracee */\n  ptrace(PTRACE_CONT, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n  /* Lastly, we check that these registers actually get reflected into the\n     tracee */\n  ptrace(PTRACE_ARCH_PRCTL, child, &pattern, ARCH_SET_GS);\n\n  /* Restart the tracee */\n  ptrace(PTRACE_CONT, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);\n\n#else\n#error Test any architecture specific TLS options here\n#endif\n\n  ptrace(PTRACE_DETACH, child, 0, 0);\n  test_assert(child == waitpid(child, &status, 0));\n  test_assert(WIFEXITED(status) && WEXITSTATUS(status) == 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/rdtsc.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void breakpoint(void) {\n  int break_here = 1;\n  (void)break_here;\n}\n\nstatic uint64_t my_rdtsc(void) {\n  uint32_t low;\n  uint32_t high;\n  /* Make sure this doesn't get buffered */\n  asm (\"rdtsc_instruction: rdtsc; xchg %%edx,%%edx\" : \"=a\"(low), \"=d\"(high));\n  return ((uint64_t)high << 32) + low;\n}\n\nint main(void) {\n  int i;\n  unsigned int u;\n  uint64_t last_tsc = 0;\n\n  for (i = 0; i < 100; ++i) {\n    uint64_t tsc;\n\n    breakpoint();\n    /* NO SYSCALLS BETWEEN HERE AND RDTSC: next event for\n     * replay must be rdtsc */\n    tsc = my_rdtsc();\n    test_assert(last_tsc < tsc);\n    atomic_printf(\"%\" PRIu64 \",\", tsc);\n    last_tsc = tsc;\n  }\n  atomic_puts(\"\");\n\n  __rdtscp(&u);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/rdtsc_flags.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n#ifdef __x86_64__\n  char zero_ok;\n  char nonzero_ok;\n  uint64_t r11;\n\n  /* Check that ZF=0 holds across buffered RDTSC\n     and that R11 is preserved */\n  asm volatile (\"xor %%eax,%%eax\\n\\t\"\n                \"xor %%r11,%%r11\\n\\t\"\n                \"rdtsc\\n\\t\"\n                \"mov %%rax,%%rcx\\n\\t\" /* make it bufferable */\n                \"sete %0\\n\\t\"\n                \"mov %%r11,%1\\n\\t\"\n                : \"=m\"(zero_ok), \"=m\"(r11) :: \"eax\", \"edx\", \"rcx\", \"r11\");\n  test_assert(zero_ok);\n  test_assert(r11 == 0);\n\n  /* Check that ZF=1 holds across buffered RDTSC\n     and that R11 is preserved */\n  asm volatile (\"xor %%eax,%%eax\\n\\t\"\n                \"mov $1,%%r11d\\n\\t\"\n                \"cmp $1,%%eax\\n\\t\"\n                \"rdtsc\\n\\t\"\n                \"mov %%rax,%%rcx\\n\\t\" /* make it bufferable */\n                \"setne %0\\n\\t\"\n                \"mov %%r11,%1\\n\\t\"\n                : \"=m\"(nonzero_ok), \"=m\"(r11) :: \"eax\", \"edx\", \"rcx\", \"r11\");\n  test_assert(nonzero_ok);\n  test_assert(r11 == 1);\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/x86/rdtsc_interfering.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nvoid do_rdtsc_loop(uint32_t with_jump) {\n#ifdef __x86_64__\n  int i;\n\n  uint64_t prev_tsc = 0;\n  for (i = 0; i < 2500000; ++i) {\n    uint32_t out;\n    uint32_t out_hi;\n    asm volatile (\"test %%rcx, %%rcx\\n\\t\"\n                  // This branch is useless, but let's make sure it works anyway.\n                  // In practice, we mostly want to make sure that spurious interfering\n                  // branches don't prevent patching so that the `nopl 0(%ax, %ax, 1); rdtsc`\n                  // sequence is guaranteed to patch properly.\n                  \"jnz 1f\\n\\t\"\n                  \".byte 0x0f, 0x1f, 0x44, 0x00, 0x00\\n\\t\"\n                  \"1: rdtsc\\n\\t\"\n                  : \"=a\"(out), \"=d\"(out_hi)\n                  : \"c\"(with_jump)\n                  : \"cc\");\n    uint64_t tsc = ((uint64_t)out_hi << 32) + out;\n    test_assert(prev_tsc < tsc);\n    prev_tsc = tsc;\n  }\n#endif\n  (void)with_jump;\n}\n\nuint64_t rdtsc_interfering_sideeffect(uint32_t do_jump) {\n  uint64_t check = 0xdeadbeef;\n  uint64_t challenge = 0xfeedbeef;\n  uint32_t out = 0;\n  uint32_t out_hi = 0;\n#ifdef __x86_64__\n  asm volatile (\n              \"xor %%rbx, %%rbx\\n\\t\" // Zero rbx\n              \"test %%rcx, %%rcx\\n\\t\"\n              // This branch is useless, but let's make sure it works anyway.\n              // In practice, we mostly want to make sure that spurious interfering\n              // branches don't prevent patching so that the `nopl 0(%ax, %ax, 1); rdtsc`\n              // sequence is guaranteed to patch properly.\n              \"jnz 1f\\n\\t\"\n              // What instruction exactly this is doesn't really matter, all we\n              // care about is that it has a syscallbuf patch and that we can check\n              // whether it ran or not.\n              \"mov %%rdi,%%rbx\\n\\t\"\n              \"1: rdtsc\\n\\t\"\n              : \"=a\"(out), \"=d\"(out_hi), \"=b\"(check)\n              : \"c\"(do_jump), \"D\"(challenge)\n              : \"cc\");\n#endif\n  test_assert(check == (do_jump ? 0 : challenge));\n  return ((uint64_t)out_hi << 32) + out;\n}\n\nint main(void) {\n  uint64_t tsc1 = rdtsc_interfering_sideeffect(0);\n  uint64_t tsc2 = rdtsc_interfering_sideeffect(1);\n  test_assert(tsc1 < tsc2);\n  do_rdtsc_loop(0);\n  do_rdtsc_loop(1);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/rdtsc_interfering.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\nskip_if_test_32_bit\nskip_if_rr_32_bit\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/rdtsc_loop.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n#ifdef __x86_64__\n  int i;\n\n  uint64_t prev_tsc = 0;\n  for (i = 0; i < 5000000; ++i) {\n    uint32_t out;\n    uint32_t out_hi;\n    asm volatile (\"rdtsc\\n\\t\"\n                  \"mov %%rax,%%rcx\\n\\t\"\n                  : \"=c\"(out), \"=d\"(out_hi)\n                  :: \"rax\");\n    uint64_t tsc = ((uint64_t)out_hi << 32) + out;\n    test_assert(prev_tsc < tsc || tsc < 1000000000);\n    prev_tsc = tsc;\n  }\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/rdtsc_loop.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/rdtsc_loop2.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void do_rdtsc(void) {\n  asm(\"rdtsc\");\n}\n\nint main(void) {\n  int i;\n  for (i = 0; i < 2000000; ++i) {\n    do_rdtsc();\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/rdtsc_loop2.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\nskip_if_test_32_bit\nskip_if_rr_32_bit\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/set_thread_area.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <asm/ldt.h>\n\nint main(void) {\n\n#if defined(__x86_64__)\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  void* stack_limit = mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                           MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, 0, 0);\n  uint32_t stack32 = (uint32_t)((uint64_t)stack_limit + page_size);\n  uint32_t result_eax = 0;\n  uint32_t result_entry = 0;\n\n  struct user_desc* parent_desc = (struct user_desc*)(uint64_t)(stack32 - 0x20);\n  parent_desc->entry_number = -1;\n  parent_desc->base_addr = stack32; /* ? */\n  parent_desc->limit = -1;\n  parent_desc->seg_32bit = 1;\n  parent_desc->contents = 0;\n  parent_desc->read_exec_only = 0;\n  parent_desc->limit_in_pages = 0;\n  parent_desc->seg_not_present = 0;\n  parent_desc->useable = 1;\n\n  asm volatile(\n               /* set random value to $rcx */\n               \"mov $0xdeadbeefdeadbeef,%%rcx\\n\"\n\n               /* prepare and switch to a 32-bit stack */\n               \"pushq %%rbx\\n\"\n               \"pushq %%r12\\n\"\n               \"movq %%rsp,%%r12\\n\"\n               \"movl %2,%%esp\\n\"\n               \"subl $0x20,%%esp\\n\"\n\n               /* call SYS_set_thread_area and save results */\n               \"movl %%esp,%%ebx\\n\"\n               \"movl $0xf3,%%eax\\n\"\n               \"int $0x80\\n\"\n               \"movl %%eax,%0\\n\"\n               \"movl (%%rsp),%1\\n\"\n\n               /* switch back to regular stack */\n               \"movq %%r12,%%rsp\\n\"\n               \"popq %%r12\\n\"\n               \"popq %%rbx\\n\"\n               : \"=r\"(result_eax),\"=r\"(result_entry) : \"r\"(stack32) : \"eax\",\"rcx\");\n\n  atomic_printf(\"result_eax=%x result_entry=%x\\n\", result_eax, result_entry);\n\n#endif\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n\n"
  },
  {
    "path": "src/test/x86/signal_xmm_state.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void handler(__attribute__((unused)) int sig) {\n}\n\nint main(void) {\n  /* 5ms */\n  struct itimerval val = { { 0, 0 }, { 0, 5000 } };\n  uint64_t counter = 0;\n  uint64_t incr = 1;\n\n  signal(SIGVTALRM, handler);\n  setitimer(ITIMER_VIRTUAL, &val, NULL);\n\n#ifdef __i386__\n#define SP \"esp\"\n#else\n#define SP \"rsp\"\n#endif\n  for (int i = 0; i < 10000000; ++i) {\n    asm(\"movd %0,%%xmm0\\n\\t\"\n        \"movd %1,%%xmm1\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"call 1f\\n\\t\"\n        \"jmp 2f\\n\\t\"\n        /* Make sure that rr's sigframe restore doesn't overwrite our return address */\n        \"1: sub $4096,%%\" SP \"\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"paddd %%xmm1,%%xmm0\\n\\t\"\n        \"add $4096,%%\" SP \"\\n\\t\"\n        \"ret\\n\\t\"\n        \"2: movd %%xmm0,%0\\n\\t\"\n        : \"=m\"(counter) : \"m\"(incr) : \"xmm0\", \"xmm1\");\n  }\n\n  atomic_printf(\"counter=%lld\\n\", (long long)counter);\n  if (counter != 640000000) {\n    atomic_puts(\"Invalid counter\");\n    return 1;\n  }\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/sigreturn.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* Test to ensure that sigreturn restores all necessary registers */\n\nstruct reg_ops {\n  void (*set)(const void* p);\n  void (*get)(void* p);\n};\n\nstatic struct reg_ops xmm_ops[8];\nstatic struct reg_ops st_ops[8];\n\n/* The assignments to uint32_t* in the inline assembly statements below\n   are because if we used *p in the asm constraints, GCC would think we\n   were dereferencing a void pointer (!).\n*/\n#define DEFINE_XMM_HELPERS(i)                                                  \\\n  void set_xmm##i(const void* p) {                                             \\\n    const uint32_t* x = p;                                                     \\\n    asm(\"movaps %[ptr], %%xmm\" #i : /* no outputs */ : [ptr] \"m\"(*x));         \\\n  }                                                                            \\\n  void get_xmm##i(void* p) {                                                   \\\n    uint32_t* x = p;                                                           \\\n    asm(\"movaps %%xmm\" #i \", %[ptr]\" : [ptr] \"=m\"(*x) : /* no inputs */);      \\\n  }\n\nDEFINE_XMM_HELPERS(0)\nDEFINE_XMM_HELPERS(1)\nDEFINE_XMM_HELPERS(2)\nDEFINE_XMM_HELPERS(3)\nDEFINE_XMM_HELPERS(4)\nDEFINE_XMM_HELPERS(5)\nDEFINE_XMM_HELPERS(6)\nDEFINE_XMM_HELPERS(7)\n\nvoid set_st7(const void* p) {\n  const uint32_t* x = p;\n  asm(\"\\tfinit\\n\"\n      \"\\tfldt %[ptr]\\n\"\n      \"\\tfst %%st(7)\\n\"\n      : /* no outputs */\n      : [ptr] \"m\"(*x));\n}\nvoid get_st7(void* p) {\n  uint32_t* x = p;\n  asm(\"\\tfdecstp\\n\"\n      \"\\tfstpt %[ptr]\\n\"\n      : [ptr] \"=m\"(*x)\n      : /* no inputs */);\n}\n\n#define DEFINE_ST_HELPERS(i)                                                   \\\n  void set_st##i(const void* p) {                                              \\\n    const uint32_t* x = p;                                                     \\\n    asm(\"\\tfinit\\n\"                                                            \\\n        \"\\tfldt %[ptr]\\n\"                                                      \\\n        \"\\tfst %%st(\" #i \")\\n\"                                                 \\\n        : /* no outputs */                                                     \\\n        : [ptr] \"m\"(*x));                                                      \\\n  }                                                                            \\\n  void get_st##i(void* p) {                                                    \\\n    uint32_t* x = p;                                                           \\\n    asm(\"\\tfld %%st(\" #i \")\\n\"                                                 \\\n        \"\\tfstpt %[ptr]\\n\"                                                     \\\n        : [ptr] \"=m\"(*x)                                                       \\\n        : /* no inputs */);                                                    \\\n  }\n\nDEFINE_ST_HELPERS(0)\nDEFINE_ST_HELPERS(1)\nDEFINE_ST_HELPERS(2)\nDEFINE_ST_HELPERS(3)\nDEFINE_ST_HELPERS(4)\nDEFINE_ST_HELPERS(5)\nDEFINE_ST_HELPERS(6)\n\nstatic void init(void) {\n#define INIT(i)                                                                \\\n  xmm_ops[i].set = set_xmm##i;                                                 \\\n  xmm_ops[i].get = get_xmm##i;                                                 \\\n  st_ops[i].set = set_st##i;                                                   \\\n  st_ops[i].get = get_st##i;\n\n  INIT(0)\n  INIT(1)\n  INIT(2)\n  INIT(3)\n  INIT(4)\n  INIT(5)\n  INIT(6)\n  INIT(7)\n}\n\n// On bionic, scsi/sg.h defines GOOD\n#undef GOOD\n#define GOOD 0x12345678\n#define BAD 0xFEDCBA98\n\n#define XMM_SIZE 16\n#define XMM_ALIGNMENT __attribute__((aligned(XMM_SIZE)))\n\nstatic const int xmm_good[XMM_SIZE / sizeof(int)] XMM_ALIGNMENT = {\n  GOOD, GOOD + 1, GOOD + 2, GOOD + 3\n};\nstatic const int xmm_bad[XMM_SIZE / sizeof(int)] XMM_ALIGNMENT = { BAD, BAD + 1,\n                                                                   BAD + 2,\n                                                                   BAD + 3 };\n\n#define ST_SIZE 10\n\nstatic long double st_good = 12345678.90;\nstatic long double st_bad = -1.23456789;\n\nstatic int regnum;\n\nstatic void handle_usr1_xmm(__attribute__((unused)) int sig) {\n  int xmm[XMM_SIZE / sizeof(int)] XMM_ALIGNMENT;\n  xmm_ops[regnum].get(xmm);\n  /* Print incoming xmm value to ensure any modifications made while\n     entering the signal handler are replayed correctly */\n  atomic_printf(\"xmm %d incoming: %x %x %x %x\\n\", regnum, xmm[0], xmm[1],\n                xmm[2], xmm[3]);\n  /* Try to corrupt register, to see if it gets restored */\n  xmm_ops[regnum].set(xmm_bad);\n}\n\nstatic void handle_usr1_st(__attribute__((unused)) int sig) {\n  char st[ST_SIZE];\n  st_ops[regnum].get(st);\n  /* Print incoming st value to ensure any modifications made while\n     entering the signal handler are replayed correctly */\n  atomic_printf(\"st %d incoming: %x %x %x\\n\", regnum, *((int*)(st)),\n                *((int*)(st + 4)), *((short*)(st + 8)) & 0xffff);\n  /* Try to corrupt register, to see if it gets restored */\n  st_ops[regnum].set(&st_bad);\n}\n\n/* Some libcs use the xmm registers for signal mask manipulation in\n   `raise`. Provide a version that doesn't. */\nstatic void my_raise(int sig) {\n  pid_t tid = sys_gettid();\n  syscall(SYS_tgkill, tid, tid, sig);\n}\n\nint main(void) {\n  init();\n\n  signal(SIGUSR1, handle_usr1_xmm);\n  for (regnum = 0; regnum < 8; ++regnum) {\n    int xmm[XMM_SIZE / sizeof(int)] XMM_ALIGNMENT;\n    memcpy(xmm, xmm_bad, sizeof(xmm));\n\n    xmm_ops[regnum].set(xmm_good);\n    my_raise(SIGUSR1);\n    xmm_ops[regnum].get(xmm);\n\n    test_assert(\"XMM register should have been preserved\" &&\n                memcmp(xmm, xmm_good, sizeof(xmm)) == 0);\n  }\n\n  signal(SIGUSR1, handle_usr1_st);\n  for (regnum = 0; regnum < 8; ++regnum) {\n    char st[ST_SIZE];\n    memcpy(st, &st_bad, sizeof(st));\n\n    st_ops[regnum].set(&st_good);\n    my_raise(SIGUSR1);\n    st_ops[regnum].get(st);\n\n    test_assert(\"ST register should have been preserved\" &&\n                memcmp(st, &st_good, sizeof(st)) == 0);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/sigreturn_checksum.run",
    "content": "source `dirname $0`/util.sh\nGLOBAL_OPTIONS=\"$GLOBAL_OPTIONS --checksum=on-all-events\"\nrecord sigreturn$bitness\nreplay\ncheck EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/singlestep_pushf.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  uintptr_t val;\n#if defined(__x86_64__) || defined(__i386__)\n  asm (\"breakpoint: pushf\\n\"\n       \"pop %0\\n\"\n       : \"=a\"(val));\n#else\n#error Unknown architecture\n#endif\n\n  if (val & 0x100) {\n    atomic_puts(\"TF set!\");\n    return 1;\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/singlestep_pushf.py",
    "content": "from util import *\n\nsend_gdb('break breakpoint')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('stepi')\n\nsend_gdb('c')\nexpect_rr('EXIT-SUCCESS')\nexpect_gdb('exited normally')\n\nok()\n"
  },
  {
    "path": "src/test/x86/singlestep_pushf.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/step_rdtsc.py",
    "content": "import re\nfrom util import *\n\nsend_gdb('hbreak *rdtsc_instruction')\nexpect_gdb('breakpoint 1')\n\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('disass')\nexpect_gdb(re.compile(r'=> ([0-9a-fx]+) <\\+[0-9]+>:\\trdtsc'))\n\naddr = last_match().group(1)\n\nsend_gdb('stepi')\nsend_gdb('disass')\nexpect_gdb(re.compile(r'=> ([0-9a-fx]+) '))\n\naddr2 = last_match().group(1)\n\nif eval(addr) + 2 != eval(addr2):\n  failed(\"stepi from rdtsc at %s ended at incorrect %s\" % (addr, addr2));\n\nok()\n"
  },
  {
    "path": "src/test/x86/step_rdtsc.run",
    "content": "source `dirname $0`/util.sh\nrecord rdtsc$bitness\ndebug_gdb_only x86/step_rdtsc\n"
  },
  {
    "path": "src/test/x86/string_instructions.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define SIZE 10 * 1024 * 1024\n\n#define FORWARD 1\n#define BACKWARD -1\n\nstatic char* p;\nstatic char* q;\nstatic char* r;\n\nstatic uintptr_t to_uintptr(char* val) {\n  union {\n    char buf[9];\n    uintptr_t p;\n  } u;\n  memset(u.buf, 0, sizeof(u.buf));\n  strcpy(u.buf, val);\n  return u.p;\n}\n\nstatic inline void set_dir(int dir) {\n#if defined(__i386__) || defined(__x86_64__)\n  if (dir < 0) {\n    __asm__(\"std\\n\\t\");\n  } else {\n    __asm__(\"cld\\n\\t\");\n  }\n#endif\n}\n\nstatic void string_store(char* dest, uintptr_t a, uintptr_t size, int unit,\n                         int dir) {\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"rep stosb\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n    case 2:\n      __asm__(\"rep stosw\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n    case 4:\n      __asm__(\"rep stosl\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"rep stosq\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    memcpy(dest, &a, unit);\n    dest += dir;\n  }\n#endif\n  set_dir(1);\n}\n\nstatic void string_copy(char* dest, char* src, uintptr_t size, int unit,\n                        int dir) {\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"rep movsb\\n\\t\" ::\"S\"(src), \"c\"(size), \"D\"(dest));\n      break;\n    case 2:\n      __asm__(\"rep movsw\\n\\t\" ::\"S\"(src), \"c\"(size), \"D\"(dest));\n      break;\n    case 4:\n      __asm__(\"rep movsl\\n\\t\" ::\"S\"(src), \"c\"(size), \"D\"(dest));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"rep movsq\\n\\t\" ::\"S\"(src), \"c\"(size), \"D\"(dest));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    memcpy(dest, src, unit);\n    dest += dir;\n    src += dir;\n  }\n#endif\n  set_dir(1);\n}\n\nstatic int string_scan_equal(char* s, uintptr_t a, uintptr_t size, int unit,\n                             int dir) {\n  char* end = s;\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"repe scasb\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n    case 2:\n      __asm__(\"repe scasw\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n    case 4:\n      __asm__(\"repe scasl\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"repe scasq\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    end += dir;\n    if (memcmp(end - dir, &a, unit) != 0) {\n      break;\n    }\n  }\n#endif\n  set_dir(1);\n  return (end - s - dir) / dir;\n}\n\nstatic int string_scan_not_equal(char* s, uintptr_t a, uintptr_t size, int unit,\n                                 int dir) {\n  char* end = s;\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"repne scasb\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n    case 2:\n      __asm__(\"repne scasw\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n    case 4:\n      __asm__(\"repne scasl\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"repne scasq\\n\\t\" : \"=D\"(end) : \"a\"(a), \"D\"(s), \"c\"(size));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    end += dir;\n    if (memcmp(end - dir, &a, unit) == 0) {\n      break;\n    }\n  }\n#endif\n  set_dir(1);\n  return (end - s - dir) / dir;\n}\n\nstatic int string_cmp_equal(char* s, char* t, uintptr_t size, int unit,\n                            int dir) {\n  char* sp = s;\n  char* tp = t;\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"repe cmpsb\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n    case 2:\n      __asm__(\"repe cmpsw\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n    case 4:\n      __asm__(\"repe cmpsl\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"repe cmpsq\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    sp += dir;\n    tp += dir;\n    if (memcmp(sp - dir, tp - dir, unit) != 0) {\n      break;\n    }\n  }\n#endif\n  set_dir(1);\n  return (sp - s - dir) / dir;\n}\n\nstatic int string_cmp_not_equal(char* s, char* t, uintptr_t size, int unit,\n                                int dir) {\n  char* sp = s;\n  char* tp = t;\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"repne cmpsb\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n    case 2:\n      __asm__(\"repne cmpsw\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n    case 4:\n      __asm__(\"repne cmpsl\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"repne cmpsq\\n\\t\" : \"=D\"(sp) : \"S\"(tp), \"D\"(s), \"c\"(size));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    sp += dir;\n    tp += dir;\n    if (memcmp(sp - dir, tp - dir, unit) == 0) {\n      break;\n    }\n  }\n#endif\n  set_dir(1);\n  return (sp - s - dir) / dir;\n}\n\nint main(void) {\n  int u;\n  uintptr_t pattern = to_uintptr(\"aaaaaaaa\");\n  uintptr_t pattern2 = to_uintptr(\"bbbbbbbb\");\n\n  p = xmalloc(SIZE);\n  q = xmalloc(SIZE);\n  r = xmalloc(SIZE);\n\n  for (u = 0; u < (sizeof(void*) == 8 ? 4 : 3); ++u) {\n    int unit = 1 << u;\n    int dir = FORWARD * unit;\n    int size_units = SIZE / unit;\n    int ret;\n\n    memset(p, 0, SIZE);\n    memset(q, 0, SIZE);\n    memset(r, 0, SIZE);\n\n    string_store(p, pattern, size_units, unit, dir);\n    test_assert(memcmp(&p[SIZE - unit], &pattern, unit) == 0);\n\n    string_copy(q, p, size_units, unit, dir);\n    test_assert(memcmp(&q[SIZE - unit], &pattern, unit) == 0);\n\n    memcpy(&p[SIZE - unit], &pattern2, unit);\n    ret = string_scan_equal(p, pattern, size_units, unit, dir);\n    test_assert(ret == size_units - 1);\n\n    ret = string_scan_not_equal(p, pattern2, size_units, unit, dir);\n    test_assert(ret == size_units - 1);\n\n    ret = string_cmp_equal(p, q, size_units, unit, dir);\n    test_assert(ret == size_units - 1);\n\n    memset(&p[SIZE - unit], 0, unit);\n    ret = string_cmp_not_equal(p, r, size_units, unit, dir);\n    test_assert(ret == size_units - 1);\n\n    dir = BACKWARD * unit;\n\n    string_store(p + SIZE - unit, pattern2, size_units, unit, dir);\n    test_assert(memcmp(&p[0], &pattern2, unit) == 0);\n\n    string_copy(q + SIZE - unit, p + SIZE - unit, size_units, unit, dir);\n    test_assert(memcmp(&q[0], &pattern2, unit) == 0);\n\n    memcpy(&p[0], &pattern, unit);\n    ret = string_scan_equal(p + SIZE - unit, pattern2, size_units, unit, dir);\n    test_assert(ret == size_units - 1);\n\n    ret =\n        string_scan_not_equal(p + SIZE - unit, pattern, size_units, unit, dir);\n    test_assert(ret == size_units - 1);\n\n    ret = string_cmp_equal(p + SIZE - unit, q + SIZE - unit, size_units, unit,\n                           dir);\n    test_assert(ret == size_units - 1);\n\n    memset(&p[0], 0, unit);\n    ret = string_cmp_not_equal(p + SIZE - unit, r + SIZE - unit, size_units,\n                               unit, dir);\n    test_assert(ret == size_units - 1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions.py",
    "content": "from util import *\n\nsend_gdb('break string_store')\nexpect_gdb('Breakpoint 1')\n\n# string_store 1-byte forwards\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\nsend_gdb('watch -l p[1000000]')\nexpect_gdb('watchpoint')\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 97')\nexpect_gdb('New value = 0')\nsend_gdb('p p[999999]')\nexpect_gdb('= 97')\nsend_gdb('p p[1000000]')\nexpect_gdb('= 0')\nsend_gdb('p p[1000001]')\nexpect_gdb('= 0')\nsend_gdb('disable')\nsend_gdb('enable 1')\n\n# string_store 1-byte backwards\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\nsend_gdb('watch -l p[1000000]')\nexpect_gdb('watchpoint')\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 98')\nexpect_gdb('New value = 97')\nsend_gdb('p p[1000001]')\nexpect_gdb('= 98')\nsend_gdb('p p[1000000]')\nexpect_gdb('= 97')\nsend_gdb('p p[999999]')\nexpect_gdb('= 97')\nsend_gdb('disable')\nsend_gdb('enable 1')\n\n# string_store 2-bytes forwards\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\nsend_gdb('watch -l p[1000001]')\nexpect_gdb('watchpoint')\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 97')\nexpect_gdb('New value = 0')\nsend_gdb('p p[999999]')\nexpect_gdb('= 97')\nsend_gdb('p p[1000000]')\nexpect_gdb('= 0')\nsend_gdb('p p[1000001]')\nexpect_gdb('= 0')\nsend_gdb('disable')\nsend_gdb('enable 1')\n\n# string_store 2-bytes backwards\n# Check that a watch at the end of the loop is OK\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('finish')\nsend_gdb('watch -l p[0]')\nexpect_gdb('watchpoint')\nsend_gdb('reverse-continue')\nexpect_gdb('Old value = 98')\nexpect_gdb('New value = 97')\nsend_gdb('p p[0]')\nexpect_gdb('= 97')\nsend_gdb('disable')\nsend_gdb('enable 1')\n\n# string_store 4-bytes forwards\n# Just check that the late-watchpoint quirk is suppressed\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\nsend_gdb('watch -l p[800000]')\nexpect_gdb('watchpoint')\nsend_gdb('continue')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 97')\nsend_gdb('p p[800003]')\nexpect_gdb('= 97')\nsend_gdb('p p[800004]')\nexpect_gdb('= 0')\n\nok()\n"
  },
  {
    "path": "src/test/x86/string_instructions.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/string_instructions_async_signals.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* This test is designed to trigger the following:\n   -- SCHED event targets the start of a string instruction\n   -- ReplaySession::advance_to sets an internal breakpoint at that string\n   instruction and runs to it, stopping at an execution of that instruction\n   before the SCHED point\n   -- advance_to does a fast_forward over the string instruction\n   -- fast_forward singlesteps, then sets a breakpoint after the string\n   instruction and continues\n   -- the byte at offset 1 triggers the string instruction to stop immediately,\n   so we hit the fast_forward breakpoint without changing any other state\n   -- fast_forward resets the register state and prepares to retry the\n   instruction, but doesn't execute anything because it observes we're already\n   in the state to stop at.\n   -- Back in ReplaySession, compute_trap_type goes wrong because we see\n   the task stopped at an internal breakpoint (but there is no internal\n   breakpoint there) */\n#define SIZE 256\n#define COUNT 8 * 256 * 256\n\nstatic char* p;\nstatic int ctr;\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n  }\n  return NULL;\n}\n\nint main(void) {\n  int v;\n  pthread_t thread;\n\n  p = xmalloc(SIZE);\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  memset(p, 0, SIZE);\n  p[1] = 'a';\n\n  for (v = 0; v < COUNT; ++v) {\n    int ret;\n#if defined(__i386__) || defined(__x86_64__)\n    char* end;\n    __asm__(\"cld\\n\\t\"\n            \"repne scasb\\n\\t\"\n            : \"=D\"(end)\n            : \"a\"('a'), \"D\"(p), \"c\"(SIZE), \"b\"(ctr));\n    ret = end - p - 1;\n#else\n    int i;\n    for (i = 0; i < SIZE; ++i) {\n      if (p[i] == 'a') {\n        ret = i;\n        break;\n      }\n    }\n#endif\n    ++ctr;\n    test_assert(ret == 1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions_async_signals.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c1000\"\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/x86/string_instructions_async_signals_shared.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n/* This test is designed to trigger the following:\n   -- SCHED event targets the start of a string instruction\n   -- ReplaySession::advance_to sets an internal breakpoint at that string\n   instruction and runs to it, stopping at an execution of that instruction\n   before the SCHED point\n   -- advance_to does a fast_forward over the string instruction\n   -- because the string instruction is in a MAP_SHARED mapping, rr has to\n   inject an mprotect call to insert a breakpoint\n   -- AutoRemoteSyscalls clobbers Task::wait_status with the result of\n   waiting on the injected syscall\n   -- rr asserts because we're at an unexpected syscall stop */\n#define SIZE 256\n#define COUNT 8 * 256 * 256\n\nstatic char* p;\nstatic int ctr;\nstatic void* mapping;\n\nconst uint8_t string_code[] = {\n  0xfc,       // CLD\n  0xf2, 0xae, // REPNZ SCAS %ES:(%RDI),%AL\n  0xc3,       // RET\n};\n\nstatic void* do_thread(__attribute__((unused)) void* p) {\n  while (1) {\n    sched_yield();\n  }\n  return NULL;\n}\n\nint main(void) {\n  int v;\n  pthread_t thread;\n\n  mapping = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS,\n                 -1, 0);\n  test_assert(mapping != NULL);\n\n  memcpy(mapping, string_code, sizeof(string_code));\n\n  v = mprotect(mapping, 4096, PROT_READ | PROT_EXEC);\n  test_assert(v == 0);\n\n  p = xmalloc(SIZE);\n\n  pthread_create(&thread, NULL, do_thread, NULL);\n\n  memset(p, 0, SIZE);\n  p[1] = 'a';\n\n  for (v = 0; v < COUNT; ++v) {\n    int ret;\n#if defined(__i386__) || defined(__x86_64__)\n    char* end;\n    __asm__(\"call *%5\\n\\t\"\n            : \"=D\"(end)\n            : \"a\"('a'), \"D\"(p), \"c\"(SIZE), \"b\"(ctr), \"m\"(mapping));\n    ret = end - p - 1;\n#else\n    int i;\n    for (i = 0; i < SIZE; ++i) {\n      if (p[i] == 'a') {\n        ret = i;\n        break;\n      }\n    }\n#endif\n    ++ctr;\n    test_assert(ret == 1);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions_async_signals_shared.run",
    "content": "source `dirname $0`/util.sh\n\nRECORD_ARGS=\"-c1000\"\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ncompare_test EXIT-SUCCESS\n\n"
  },
  {
    "path": "src/test/x86/string_instructions_break.py",
    "content": "from util import *\n\nsend_gdb('break string_store')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('watch -l p[0]')\nexpect_gdb('watchpoint 2')\nsend_gdb('c')\nexpect_gdb('watchpoint 2')\n\nsend_gdb('break')\nexpect_gdb('Breakpoint 3')\nsend_gdb('disable 3')\nsend_gdb('finish')\nexpect_gdb('main')\n\nsend_gdb('enable 3')\nsend_gdb('reverse-continue')\nexpect_gdb('Breakpoint 3')\n\nok()\n"
  },
  {
    "path": "src/test/x86/string_instructions_break.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\nrecord string_instructions_replay$bitness\ndebug_gdb_only x86/string_instructions_break\n"
  },
  {
    "path": "src/test/x86/string_instructions_multiwatch.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic void my_memmove(char* dest, char* src, uintptr_t size) {\n#if defined(__i386__) || defined(__x86_64__)\n  __asm__(\"rep movsb\\n\\t\" ::\"c\"(size), \"S\"(src), \"D\"(dest));\n#else\n  memmove(dest, src, size);\n#endif\n}\n\nint main(void) {\n  char* buf = (char*)mmap(NULL, 100000, PROT_READ | PROT_WRITE,\n                          MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  int i;\n  test_assert(buf != MAP_FAILED);\n\n  for (i = 0; i < 100000; ++i) {\n    buf[i] = i;\n  }\n\n  atomic_printf(\"Buf is at %p\\n\", buf);\n  my_memmove(buf, buf + 4000, 90000);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions_multiwatch.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b my_memmove')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb(re.compile(r'Buf is at ([^ \\n]+)'))\nbuf = eval(last_match().group(1));\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('watch -l *(char*)%d'%(buf + 14000))\nexpect_gdb('atchpoint 2')\n\nsend_gdb('c')\nexpect_gdb('atchpoint 2')\n\nok()\n"
  },
  {
    "path": "src/test/x86/string_instructions_multiwatch.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/string_instructions_replay.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#define SIZE 10 * 1024 * 1024\n#define DIFF 2 * 1024 * 1024\n#define CMP_LEN 3 * 1024 * 1024\n\nstatic char* p;\nstatic char* q;\n\nstatic void string_store(char* dest, int a, uintptr_t size) {\n#if defined(__i386__) || defined(__x86_64__)\n  __asm__(\"rep stosb\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n#else\n  memset(dest, a, size);\n#endif\n}\n\nstatic int string_compare(char* s1, char* s2, uintptr_t size) {\n#if defined(__i386__) || defined(__x86_64__)\n  char* result;\n  __asm__(\"repe cmpsb\\n\\t\" : \"=D\"(result) : \"c\"(size), \"S\"(s1), \"D\"(s2));\n  uintptr_t i = result - s2;\n  if (i == size) {\n    return s1[size - 1] == s2[size - 1] ? size : size - 1;\n  }\n  return i - 1;\n#else\n  for (uintptr_t i = 0; i < size; ++i) {\n    if (s1[i] != s2[i]) {\n      return i;\n    }\n  }\n  return size;\n#endif\n}\n\nint main(void) {\n  int i;\n\n  p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1,\n           0);\n  test_assert(p != MAP_FAILED);\n  q = mmap(NULL, SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1,\n           0);\n  test_assert(q != MAP_FAILED);\n\n  for (i = 1; i < 1000; ++i) {\n    string_store(p, i, SIZE);\n    string_store(q, i, SIZE);\n    q[DIFF] = i ^ 0xff;\n    test_assert(string_compare(p, q, (uintptr_t)-1) == DIFF);\n  }\n\n  atomic_puts(\"EXIT-SUCCESS\");\n\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions_replay.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\n\nrecord $TESTNAME &\n\nfor i in $(seq 1 30); do\n  sleep 0.05\n  kill -CHLD $rrpid $(pidof $TESTNAME-$nonce) >& /dev/null\ndone\n\n# Wait for 'record' to actually terminate. Otherwise we might start\n# replaying before the trace file has been completely written.\nwait\n\necho \"Replaying ...\"\nreplay\ncheck 'EXIT-SUCCESS'\n"
  },
  {
    "path": "src/test/x86/string_instructions_replay_quirk.py",
    "content": "from util import *\n\nsend_gdb('break string_store')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('disable')\nsend_gdb('watch -l p[0]')\nexpect_gdb('watchpoint')\nsend_gdb('c')\nexpect_gdb('Old value = 0')\nexpect_gdb('New value = 1')\nsend_gdb('p p[0]')\nexpect_gdb('= 1')\nsend_gdb('p p[1]')\nexpect_gdb('= 0')\n\nok()\n"
  },
  {
    "path": "src/test/x86/string_instructions_replay_quirk.run",
    "content": "source `dirname $0`/util.sh\n\nif [ $TIMEOUT -lt 600 ]; then TIMEOUT=600; fi\nrecord string_instructions_replay$bitness\ndebug_gdb_only x86/string_instructions_replay_quirk\n"
  },
  {
    "path": "src/test/x86/string_instructions_singlestep_fastforward.c",
    "content": "#include \"util.h\"\n\nstatic int string_cmp_equal(char* s, char* t, uintptr_t size) {\n  int b;\n  __asm__(\"repe cmpsb\\n\\t;\"\n          \"sete %%al\\n\\t;\"\n          \"movzx %%al,%0;\": \"=r\"(b) : \"S\"(t), \"D\"(s), \"c\"(size) : \"al\");\n  return b;\n}\n\nint main(void) {\n  char* STRING1 = \"almost_the_same1\";\n  char* STRING2 = \"almost_the_same2\";\n  int x = string_cmp_equal(STRING1, STRING2, 17);\n  return x;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions_singlestep_fastforward.run",
    "content": "source `dirname $0`/util.sh\n\nrerun_singlestep_test\n"
  },
  {
    "path": "src/test/x86/string_instructions_watch.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char* buf;\n\nstatic uintptr_t to_uintptr(char* val) {\n  union {\n    char buf[9];\n    uintptr_t p;\n  } u;\n  memset(u.buf, 0, sizeof(u.buf));\n  strcpy(u.buf, val);\n  return u.p;\n}\n\nstatic inline void set_dir(int dir) {\n#if defined(__i386__) || defined(__x86_64__)\n  if (dir < 0) {\n    __asm__(\"std\\n\\t\");\n  } else {\n    __asm__(\"cld\\n\\t\");\n  }\n#endif\n}\n\nstatic void string_store(char* dest, uintptr_t a, uintptr_t size, int unit,\n                         int dir) {\n  set_dir(dir);\n#if defined(__i386__) || defined(__x86_64__)\n  switch (unit) {\n    case 1:\n      __asm__(\"rep stosb\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n    case 2:\n      __asm__(\"rep stosw\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n    case 4:\n      __asm__(\"rep stosl\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n#ifdef __x86_64__\n    case 8:\n      __asm__(\"rep stosq\\n\\t\" ::\"a\"(a), \"c\"(size), \"D\"(dest));\n      break;\n#endif\n  }\n#else\n  int i;\n  for (i = 0; i < size; i += unit) {\n    memcpy(dest, &a, unit);\n    dest += dir;\n  }\n#endif\n  set_dir(1);\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  buf = (char*)mmap(NULL, page_size, PROT_READ | PROT_WRITE,\n                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n\n  string_store(buf, to_uintptr(\"aaaaaaaa\"), 16, 1, 1);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/string_instructions_watch.py",
    "content": "from util import *\nimport re\n\nsend_gdb('b string_store')\nexpect_gdb('Breakpoint 1')\nsend_gdb('c')\nexpect_gdb('Breakpoint 1')\n\nsend_gdb('p buf')\nexpect_gdb(re.compile(r'= ([^ ]+)'))\nbuf = eval(last_match().group(1));\n\nsend_gdb('watch -l *(uint16_t*)%d'%(buf + 13))\nexpect_gdb('atchpoint 2')\n\nsend_gdb('watch -l *(char*)-1')\nexpect_gdb('atchpoint 3')\n\nsend_gdb('c')\nexpect_gdb('atchpoint 2')\n\nsend_gdb('p buf[13]')\nexpect_gdb('= 97')\nsend_gdb('p buf[14]')\nexpect_gdb('= 0')\n\nok()\n"
  },
  {
    "path": "src/test/x86/string_instructions_watch.run",
    "content": "source `dirname $0`/util.sh\ndebug_test_gdb_only\n"
  },
  {
    "path": "src/test/x86/syscallbuf_branch_check.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __x86_64__\n#define SYS1 0x0f\n#define SYS2 0x05\n#else\n#define SYS1 0xcd\n#define SYS2 0x80\n#endif\n\nstatic const uint8_t forward_branch_bad_code[136] = {\n  0xe3, 0x7f, /* jecxz syscall */\n  0xeb, 0x7f, /* jmp target */\n  /* 125 nops */\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90,\n  SYS1, SYS2, /* syscall */\n  /* target: nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n};\n\nstatic const uint8_t forward_branch_ok_code[136] = {\n  0xe3, 0x7f, /* jecxz syscall */\n  0xeb, 0x7d, /* jmp target-2 */\n  /* 125 nops */\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90,\n  SYS1, SYS2, /* syscall */\n  /* target: nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n};\n\nstatic const uint8_t backward_branch_bad_code[132] = {\n  0xe3, 0x06, /* jecxz skip */\n  SYS1, SYS2, /* syscall */\n  /* target: nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n  /* skip: 122 nops */\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90,\n  /* jmp target */\n  0xeb, 0x80,\n};\n\nstatic const uint8_t backward_branch_bad_code2[132] = {\n  0xe3, 0x06, /* jecxz skip */\n  SYS1, SYS2, /* syscall */\n  /* target: nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n  /* skip: 122 nops */\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90,\n  /* jmp target+1 */\n  0xeb, 0x81,\n};\n\nstatic const uint8_t backward_branch_ok_code[132] = {\n  0xe3, 0x06, /* jecxz skip */\n  SYS1, SYS2, /* syscall */\n  /* target: nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n  /* skip: 122 nops */\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,\n  0x90, 0x90,\n  /* jmp target+3 */\n  0xeb, 0x7d,\n};\n\nstatic const uint8_t standalone_syscall[6] = {\n  SYS1, SYS2, /* syscall */\n  /* nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n};\n\nstatic long do_call(uint8_t* page, uint8_t* code, int ecx) {\n  long ret;\n  mprotect(page, 1, PROT_READ | PROT_EXEC);\n  __asm__ __volatile__(\"call *%3\\n\\t\" : \"=a\"(ret) :\n                       \"a\"(SYS_sched_yield), \"c\"(ecx), \"d\"(code));\n  mprotect(page, 1, PROT_READ | PROT_WRITE);\n  return ret;\n}\n\nstatic uint8_t* allocate_code(const uint8_t* code, size_t size) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* p = mmap(NULL, page_size * 3, PROT_READ | PROT_WRITE,\n                    MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  munmap(p, page_size);\n  munmap(p + 2*page_size, page_size);\n\n  p += page_size;\n  memcpy(p, code, size);\n  return p;\n}\n\nint main(void) {\n  size_t page_size = sysconf(_SC_PAGESIZE);\n  uint8_t* code;\n  /* Test that code is patched even when it starts at a page boundary */\n  uint8_t* p = allocate_code(standalone_syscall, sizeof(standalone_syscall));\n  do_call(p, p, 0);\n  test_assert(p[0] == 0xe9);\n\n  /* Test that code is patched even when it ends at a page boundary */\n  code = p + page_size - sizeof(standalone_syscall);\n  memcpy(code, standalone_syscall, sizeof(standalone_syscall));\n  do_call(p, code, 0);\n  test_assert(code[0] == 0xe9);\n\n  p = allocate_code(forward_branch_bad_code, sizeof(forward_branch_bad_code));\n  do_call(p, p, 0);\n  /* Code should not have been patched, due to the inferering branch */\n  test_assert(memcmp(p, forward_branch_bad_code, sizeof(forward_branch_bad_code)) == 0);\n\n  p = allocate_code(forward_branch_ok_code, sizeof(forward_branch_ok_code));\n  do_call(p, p, 0);\n  /* Code should have been patched */\n  test_assert(memcmp(p, forward_branch_ok_code, sizeof(forward_branch_ok_code)) != 0);\n\n  p = allocate_code(backward_branch_bad_code, sizeof(backward_branch_bad_code));\n  do_call(p, p, 1);\n  /* Code should not have been patched, due to the inferering branch */\n  test_assert(memcmp(p, backward_branch_bad_code, sizeof(backward_branch_bad_code)) == 0);\n\n  p = allocate_code(backward_branch_bad_code2, sizeof(backward_branch_bad_code2));\n  do_call(p, p, 1);\n  /* Code should not have been patched, due to the inferering branch */\n  test_assert(memcmp(p, backward_branch_bad_code2, sizeof(backward_branch_bad_code2)) == 0);\n\n  p = allocate_code(backward_branch_ok_code, sizeof(backward_branch_ok_code));\n  do_call(p, p, 1);\n  /* Code should have been patched */\n  test_assert(memcmp(p, backward_branch_ok_code, sizeof(backward_branch_ok_code)) != 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/syscallbuf_branch_check.run",
    "content": "source `dirname $0`/util.sh\n\n# This test requires syscallbuf syscall patching\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/syscallbuf_rdtsc_page.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __i386__\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n#else\nstatic const uint8_t code[6] = {\n  0x0f, 0x31, /* rdtsc */\n  /* nop; nop; nop; ret */\n  0x90, 0x90, 0x90, 0xc3,\n};\n\nstatic long do_call(uint8_t* page, uint8_t* code, int ecx) {\n  long ret;\n  mprotect(page, 1, PROT_READ | PROT_EXEC);\n  __asm__ __volatile__(\"call *%3\\n\\t\" : \"=a\"(ret) :\n                       \"a\"(SYS_sched_yield), \"c\"(ecx), \"d\"(code));\n  mprotect(page, 1, PROT_READ | PROT_WRITE);\n  return ret;\n}\n\nstatic const uint64_t GB = 1024*1024*1024;\n\nint main(void) {\n  uint8_t* p = mmap(NULL, 9*GB, PROT_READ | PROT_WRITE,\n                    MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE, -1, 0);\n  test_assert(p != MAP_FAILED);\n  munmap(p, 4*GB);\n  munmap(p + 5*GB, 4*GB);\n\n  p += 4*GB;\n  memcpy(p, code, sizeof(code));\n  /* Force allocation of a new syscallbuf stub page for this call */\n  do_call(p, p, 0);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n#endif\n"
  },
  {
    "path": "src/test/x86/syscallbuf_rdtsc_page.run",
    "content": "source `dirname $0`/util.sh\nskip_if_no_syscall_buf\ncompare_test EXIT-SUCCESS\n"
  },
  {
    "path": "src/test/x86/sysfs.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  int i;\n  int ret;\n  int num_types = syscall(SYS_sysfs, 3);\n  if (num_types < 0 && errno == ENOSYS) {\n    atomic_puts(\"sysfs not supported, skipping test\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(num_types > 0);\n\n  for (i = 0; i < num_types; ++i) {\n    char buf[1024];\n    ret = syscall(SYS_sysfs, 2, i, buf);\n    test_assert(ret == 0);\n    atomic_printf(\"Type %d: %s\\n\", i, buf);\n  }\n\n  ret = syscall(SYS_sysfs, 4);\n  test_assert(ret < 0 && errno == EINVAL);\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/util.h",
    "content": "#include \"../util.h\"\n"
  },
  {
    "path": "src/test/x86/util.sh",
    "content": "TEST_PREFIX=x86/\nsource `dirname $0`/../util.sh\n"
  },
  {
    "path": "src/test/x86/watchpoint_error.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic char buffer[64];\n\nint main(void) {\n  atomic_puts(\"EXIT-SUCCESS\");\n  strcpy(buffer, \"hello\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/x86/watchpoint_error.py",
    "content": "from util import *\n\nbreakpoint = breakpoint_at_function('main')\ncont()\nexpect_breakpoint_stop(breakpoint)\n\nwatchpoint_at_address(\"&buffer[0]\", 1)\nwatchpoint_at_address(\"&buffer[8]\", 1)\nwatchpoint_at_address(\"&buffer[16]\", 1)\nwp4 = watchpoint_at_address(\"&buffer[24]\", 1)\nwatchpoint_at_address_fail(\"&buffer[32]\", 1)\n\ndelete_watchpoint(wp4)\nwatchpoint_at_address(\"&buffer[24]\", 1)\n\nbreakpoint_puts = breakpoint_at_function('atomic_puts')\ncont()\nexpect_breakpoint_stop(breakpoint_puts)\n\nok()\n\n"
  },
  {
    "path": "src/test/x86/watchpoint_error.run",
    "content": "source `dirname $0`/util.sh\ndebug_test watchpoint_error\n"
  },
  {
    "path": "src/test/x86/x87env.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#ifdef __x86_64__\nextern char _x87_instruction;\nstatic int cpu_has_xsave_fip_fdp_quirk(void) {\n  uint64_t xsave_buf[576/sizeof(uint64_t)] __attribute__((aligned(64)));\n  xsave_buf[1] = 0;\n  asm volatile(\"finit\\n\"\n               \"fld1\\n\"\n               \"xsave64 %0\\n\"\n               : \"=m\"(xsave_buf)\n               : \"a\"(1), \"d\"(0)\n               : \"memory\");\n  return !xsave_buf[1];\n}\n#endif\n\nint main(void) {\n#ifdef __x86_64__\n  long double x;\n  uint32_t fstenv_buf[256];\n  /* use mmap to get alignment >= 64 bytes */\n  uint64_t* xsave_buf = (uint64_t*)mmap(NULL, 65536, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);\n  __asm__ volatile(\"finit\\n\"\n                   \"_x87_instruction: fld1\\n\");\n  /* Trigger PLT code and syscall */\n  sched_yield();\n  __asm__ volatile(\"fstenv %1\\n\"\n                   \"xsave64 %2\\n\"\n                   \"fldz\\n\"\n                   \"fldenv %1\\n\"\n                   : \"=t\"(x), \"=m\"(fstenv_buf), \"=m\"(*xsave_buf)\n                   : \"a\"(0xffffffff), \"d\"(0xffffffff)\n                   : \"memory\");\n  test_assert(x == 1.0);\n  /* Check saved FIPs */\n  atomic_printf(\"FIP=0x%x\\n\", fstenv_buf[3]);\n  if (cpu_has_xsave_fip_fdp_quirk()) {\n    /* rr or the kernel should have cleared this during the sched_yield syscall */\n    test_assert(fstenv_buf[3] == 0);\n  } else {\n    test_assert(fstenv_buf[3] == (uint32_t)(uintptr_t)&_x87_instruction);\n  }\n  atomic_printf(\"XSAVE FIP=0x%llx\\n\", (long long)xsave_buf[1]);\n  if (cpu_has_xsave_fip_fdp_quirk()) {\n    test_assert(xsave_buf[1] == 0);\n  } else {\n    test_assert(xsave_buf[1] == (uintptr_t)&_x87_instruction);\n  }\n#endif\n\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/xattr.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nstatic const char path_name[] = \"rr-test-file\";\nstatic const char link_name[] = \"rr-test-link\";\nstatic const char attr_name1[] = \"user.testAttr1\";\nstatic const char attr_name2[] = \"user.testAttr2\";\nstatic const char link_attr_name[] = \"trusted.testA1\";\nstatic const char attr_value1[] = \"hello kitty\";\nstatic const char attr_value2[] = \"hello scarf\";\n\nstatic int list_contains(const char* buf, size_t buf_size, const char* name) {\n  const char* end = buf + buf_size;\n  while (buf < end) {\n    if (strcmp(buf, name) == 0) {\n      return 1;\n    }\n    buf += strlen(buf) + 1;\n  }\n  return 0;\n}\n\nint main(void) {\n  int ret;\n  int fd;\n  size_t buf_size = sizeof(attr_value1) + 1;\n  char* buf = allocate_guard(buf_size, '-');\n  int test_link = 1;\n  size_t file_list_size;\n  size_t link_list_size;\n\n  fd = open(path_name, O_RDWR | O_CREAT, 0700);\n  test_assert(0 <= fd);\n\n  ret = setxattr(path_name, attr_name1, attr_value1, sizeof(attr_value1),\n                 XATTR_CREATE);\n  if (ret < 0 && errno == ENOTSUP) {\n    test_assert(0 == unlink(path_name));\n    atomic_puts(\"Filesystem does not support xattrs; skipping tests\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(ret == 0);\n\n  test_assert(0 == fsetxattr(fd, attr_name2, attr_value2, sizeof(attr_value2),\n                             XATTR_CREATE));\n\n  test_assert(0 == symlink(path_name, link_name));\n  ret = lsetxattr(link_name, link_attr_name, attr_value1, sizeof(attr_value1),\n                  XATTR_CREATE);\n  if (ret < 0 && errno == EPERM) {\n    atomic_puts(\"Not allowed to create xattrs on links; skipping link tests\");\n    /* Only trusted xattrs can be created on links. Currently Linux does not\n       allow non-root users to create trusted xattrs, even if they're\n       privileged in a user/fs namespace. If it did, we could run link tests\n       in unshare.c... */\n    test_link = 0;\n  } else {\n    test_assert(ret == 0);\n  }\n\n  test_assert(-1 ==\n              getxattr(path_name, attr_name2, buf, sizeof(attr_value2) - 1));\n  verify_guard(buf_size, buf);\n  test_assert(errno == ERANGE);\n  memset(buf, '-', buf_size);\n  test_assert(-1 == fgetxattr(fd, attr_name1, buf, sizeof(attr_value1) - 1));\n  verify_guard(buf_size, buf);\n  test_assert(errno == ERANGE);\n  memset(buf, '-', buf_size);\n  if (test_link) {\n    test_assert(-1 == lgetxattr(link_name, link_attr_name, buf,\n                                sizeof(attr_value1) - 1));\n    verify_guard(buf_size, buf);\n    test_assert(errno == ERANGE);\n    memset(buf, '-', buf_size);\n  }\n\n  test_assert(sizeof(attr_value2) ==\n              getxattr(path_name, attr_name2, buf, sizeof(attr_value2)));\n  verify_guard(buf_size, buf);\n  test_assert(0 == memcmp(attr_value2, buf, sizeof(attr_value2)));\n  test_assert(buf[sizeof(attr_value2)] == '-');\n  memset(buf, '-', buf_size);\n  test_assert(sizeof(attr_value1) ==\n              fgetxattr(fd, attr_name1, buf, sizeof(attr_value1)));\n  verify_guard(buf_size, buf);\n  test_assert(0 == memcmp(attr_value1, buf, sizeof(attr_value1)));\n  test_assert(buf[sizeof(attr_value1)] == '-');\n  memset(buf, '-', buf_size);\n  if (test_link) {\n    test_assert(sizeof(attr_value2) ==\n                lgetxattr(link_name, link_attr_name, buf, sizeof(attr_value1)));\n    verify_guard(buf_size, buf);\n    test_assert(0 == memcmp(attr_value1, buf, sizeof(attr_value1)));\n    test_assert(buf[sizeof(attr_value1)] == '-');\n    memset(buf, '-', buf_size);\n  }\n\n  test_assert(-1 == listxattr(path_name, buf, sizeof(attr_name1) - 1));\n  verify_guard(buf_size, buf);\n  test_assert(errno == ERANGE);\n  test_assert(buf[0] == '-');\n  test_assert(-1 == flistxattr(fd, buf, sizeof(attr_name1) - 1));\n  verify_guard(buf_size, buf);\n  test_assert(errno == ERANGE);\n  test_assert(buf[0] == '-');\n  if (test_link) {\n    test_assert(-1 == llistxattr(link_name, buf, sizeof(link_attr_name) - 1));\n    verify_guard(buf_size, buf);\n    test_assert(errno == ERANGE);\n    test_assert(buf[0] == '-');\n  }\n\n  file_list_size = listxattr(path_name, NULL, 0);\n  test_assert(file_list_size >= sizeof(attr_name1) + sizeof(attr_name2));\n  if (test_link) {\n    link_list_size = llistxattr(link_name, NULL, 0);\n    test_assert(link_list_size >= sizeof(link_attr_name));\n  } else {\n    link_list_size = 0;\n  }\n\n  buf_size = file_list_size + 1;\n  buf = allocate_guard(buf_size, '-');\n  test_assert(file_list_size == (size_t)listxattr(path_name, buf, buf_size));\n  verify_guard(buf_size, buf);\n  test_assert(list_contains(buf, file_list_size, attr_name1));\n  test_assert(list_contains(buf, file_list_size, attr_name2));\n  test_assert(buf[file_list_size] == '-');\n  memset(buf, '-', buf_size);\n  test_assert(file_list_size == (size_t)flistxattr(fd, buf, buf_size));\n  verify_guard(buf_size, buf);\n  test_assert(list_contains(buf, file_list_size, attr_name1));\n  test_assert(list_contains(buf, file_list_size, attr_name2));\n  test_assert(buf[file_list_size] == '-');\n  memset(buf, '-', buf_size);\n  if (test_link) {\n    buf_size = link_list_size + 1;\n    buf = allocate_guard(buf_size, '-');\n    test_assert(link_list_size == (size_t)llistxattr(link_name, buf, buf_size));\n    verify_guard(buf_size, buf);\n    test_assert(list_contains(buf, link_list_size, link_attr_name));\n    test_assert(buf[link_list_size] == '-');\n    memset(buf, '-', buf_size);\n  }\n\n  test_assert(0 == removexattr(path_name, attr_name2));\n  test_assert(-1 == getxattr(path_name, attr_name2, buf, buf_size));\n  test_assert(errno == ENODATA);\n  test_assert(buf[0] == '-');\n  test_assert(0 == fremovexattr(fd, attr_name1));\n  test_assert(-1 == getxattr(path_name, attr_name1, buf, buf_size));\n  test_assert(errno == ENODATA);\n  test_assert(buf[0] == '-');\n  if (test_link) {\n    test_assert(0 == lremovexattr(link_name, link_attr_name));\n    test_assert(-1 == getxattr(link_name, link_attr_name, buf, buf_size));\n    test_assert(errno == ENODATA);\n    test_assert(buf[0] == '-');\n  }\n\n  test_assert(0 == unlink(link_name));\n  test_assert(0 == unlink(path_name));\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test/zero_length_read.c",
    "content": "/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\nint main(void) {\n  char buf[1024];\n\n  signal(SIGTTIN, SIG_IGN);\n\n  ssize_t count = read(STDIN_FILENO, &buf[0], 0);\n  if (count == -1 && errno == EIO &&\n      tcgetpgrp(STDIN_FILENO) != getpgrp()) {\n    atomic_puts(\"Running in background process group, cannot read from terminal.\");\n    atomic_puts(\"EXIT-SUCCESS\");\n    return 0;\n  }\n  test_assert(count == 0);\n  atomic_puts(\"EXIT-SUCCESS\");\n  return 0;\n}\n"
  },
  {
    "path": "src/test-monitor/test-monitor.cc",
    "content": "#include <dirent.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <limits.h>\n#include <signal.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <unistd.h>\n\n#include <ctime>\n#include <string>\n#include <unordered_map>\n#include <unordered_set>\n#include <vector>\n\nusing namespace std;\n\nstatic void print_usage(FILE* out) {\n  fputs(\"Usage:\\n\"\n        \"test-monitor <timeout-secs> <out-file> <command> [<args>...]\\n\"\n        \"Runs the command for up to <timeout-secs>. If the timeout expires,\\n\"\n        \"or a SIGURG signal is received, attaches gdb to the child to get a\\n\"\n        \"stack trace and dumps various other information to <out-file>\\n\"\n        \"then exits with error code 124. Otherwise exits with the child's\\n\"\n        \"exit code. Runs the child with\\n\"\n        \"RUNNING_UNDER_TEST_MONITOR=<pid-of-test-monitor>.\\n\"\n        \"\\n\"\n        \"If the environment variable RR_TEST_DIAGNOSE_TIMEOUT is set to a number\\n\"\n        \"the value will be used as the timeout for each diagnostic commands\\n\"\n        \"(e.g. gdb) after a test failure.\\n\",\n        out);\n}\n\nstatic unsigned long timeout;\nstatic unsigned long diagnose_timeout = ULONG_MAX;\n\nstatic siginfo_t received_siginfo;\n\nstatic void sighandler(__attribute__((unused)) int sig, siginfo_t* si,\n                       __attribute__((unused)) void* ctx) {\n  received_siginfo = *si;\n}\n\nstruct ProcessInfo {\n  ProcessInfo() : is_traced(false) {}\n  vector<pid_t> children;\n  string name;\n  bool is_traced;\n};\n\nstruct ProcessMap {\npublic:\n  explicit ProcessMap(FILE* out);\n  unordered_map<pid_t, ProcessInfo> map;\n};\n\nProcessMap::ProcessMap(FILE* out) {\n  DIR* proc = opendir(\"/proc\");\n  if (!proc) {\n    fprintf(out, \"Couldn't read /proc\");\n    return;\n  }\n  while (true) {\n    struct dirent* f = readdir(proc);\n    if (!f) {\n      break;\n    }\n    pid_t pid = atoi(f->d_name);\n    if (pid) {\n      char path[PATH_MAX];\n      sprintf(path, \"/proc/%d/status\", pid);\n      FILE* status = fopen(path, \"r\");\n      if (status) {\n        while (true) {\n          char buf[1024 * 10];\n          if (!fgets(buf, sizeof(buf), status)) {\n            break;\n          }\n          ssize_t len = strlen(buf);\n          if (len > 0 && buf[len - 1] == '\\n') {\n            buf[len - 1] = 0;\n          }\n          if (strncmp(buf, \"Name:\", 5) == 0) {\n            char* s = buf + 5;\n            while (*s == ' ' || *s == '\\t') {\n              ++s;\n            }\n            map[pid].name = string(s);\n          }\n          if (strncmp(buf, \"PPid:\", 5) == 0) {\n            pid_t ppid = atoi(buf + 5);\n            if (ppid) {\n              map[ppid].children.push_back(pid);\n            }\n          }\n          if (strncmp(buf, \"TracerPid:\", 10) == 0) {\n            pid_t tracer_pid = atoi(buf + 10);\n            if (tracer_pid) {\n              map[pid].is_traced = true;\n            }\n            break;\n          }\n        }\n        fclose(status);\n      }\n    }\n  }\n  closedir(proc);\n}\n\nstatic void dump_proc_for_process(pid_t child, const char* suffix, FILE* out) {\n  char path[PATH_MAX];\n  sprintf(path, \"/proc/%d/%s\", child, suffix);\n  fprintf(out, \"====== %s\\n\", path);\n  FILE* f = fopen(path, \"r\");\n  if (!f) {\n    fprintf(out, \"(file couldn't be opened)\\n\");\n    return;\n  }\n  char line[1024 * 10];\n  while (fgets(line, sizeof(line), f)) {\n    fputs(line, out);\n  }\n  fclose(f);\n}\n\nstatic void dump_popen_cmdline(const char* cmdline, FILE* out) {\n  fprintf(out, \"====== %s\\n\", cmdline);\n  int fds[2];\n  if (pipe(fds) != 0) {\n      fprintf(out, \"(pipe creation failed)\\n\");\n      return;\n  }\n  pid_t pid = fork();\n  if (pid == -1) {\n      fprintf(out, \"(process creation failed)\\n\");\n      return;\n  }\n  if (pid == 0) {\n      close(fds[0]);\n      dup2(fds[1], 1);\n      close(fds[1]);\n      int ret = execl(\"/bin/sh\", \"/bin/sh\", \"-c\", cmdline, NULL);\n      const char *msg = \"(execution failed)\\n\";\n      __attribute__((unused)) ssize_t ret2 = write(fds[1], msg, strlen(msg));\n      exit(ret);\n  }\n  close(fds[1]);\n  fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | O_NONBLOCK);\n  char line[1024 * 10];\n  time_t start_time = time(NULL);\n\n  while (true) {\n      int status;\n      int ret = waitpid(pid, &status, WNOHANG);\n      ssize_t sz;\n      bool has_output = false;\n      while ((sz = read(fds[0], line, sizeof(line))) > 0) {\n          has_output = true;\n          fwrite(line, 1, sz, out);\n      }\n      // Error or exited\n      if (ret != 0)\n          break;\n      time_t new_time = time(NULL);\n      if (new_time > start_time &&\n          (unsigned long)(new_time - start_time) > diagnose_timeout) {\n          fprintf(out, \"Command timeout: %s\\n\", cmdline);\n          kill(pid, SIGKILL);\n          break;\n      }\n      if (has_output)\n          continue;\n      sleep(1);\n  }\n  close(fds[0]);\n}\n\nstatic void dump_gdb_stacktrace(pid_t child, FILE* out) {\n  char cmdline[1024 * 10];\n  sprintf(cmdline, \"gdb -p %d -ex 'set confirm off' -ex 'set height 0' -ex \"\n                   \"'thread apply all bt' -ex q </dev/null 2>&1\",\n          child);\n  dump_popen_cmdline(cmdline, out);\n}\n\nstatic void force_trace_closure(pid_t child, FILE* out) {\n  char cmdline[1024 * 10];\n  sprintf(cmdline, \"gdb -p %d \"\n                   \"-ex 'set confirm off' \"\n                   \"-ex 'set height 0' \"\n                   \"-ex 'b rr::force_close_record_session' \"\n                   \"-ex 'p rr::force_close_record_session()' \"\n                   \"-ex detach \"\n                   \"-ex q </dev/null 2>&1\",\n          child);\n  dump_popen_cmdline(cmdline, out);\n  sleep(2); /* give the force_close_record_session time to take effect */\n}\n\nstatic void dump_emergency_debugger(char* gdb_cmd, FILE* out) {\n  char cmdline[1024 * 10];\n  char* file_name = nullptr;\n  for (ssize_t i = strlen(gdb_cmd) - 1; i >= 0; --i) {\n    if (gdb_cmd[i] == ' ') {\n      gdb_cmd[i] = 0;\n      file_name = &gdb_cmd[i + 1];\n      break;\n    }\n  }\n  if (!file_name) {\n    fprintf(out, \"Can't find file name in cmd %s\\n\", gdb_cmd);\n    return;\n  }\n  snprintf(cmdline, sizeof(cmdline),\n           \"%s -ex 'set confirm off' -ex 'set height 0' \"\n           \"-ex 'info registers' -ex \"\n           \"'thread apply all bt' -ex q %s </dev/null 2>&1\",\n           gdb_cmd, file_name);\n  dump_popen_cmdline(cmdline, out);\n}\n\nstatic vector<pid_t> get_child_threads(pid_t pid) {\n  vector<pid_t> ret;\n  char path[PATH_MAX];\n  sprintf(path, \"/proc/%d/task\", pid);\n  DIR* threads = opendir(path);\n  if (threads) {\n    while (true) {\n      struct dirent* t = readdir(threads);\n      if (!t) {\n        break;\n      }\n      pid_t tid = atoi(t->d_name);\n      if (tid && tid != pid) {\n        ret.push_back(tid);\n      }\n    }\n    closedir(threads);\n  }\n  return ret;\n}\n\n/**\n * Dumps purely passive data for the entire process subtree.\n */\nstatic void dump_subtree(ProcessMap& child_processes,\n                         unordered_set<pid_t>& visited, pid_t child, FILE* out,\n                         pid_t* rr_pid) {\n  if (visited.find(child) != visited.end()) {\n    fprintf(out, \"Warning: tree structure violation detected at process %d\\n\",\n            child);\n    return;\n  }\n  visited.insert(child);\n\n  dump_proc_for_process(child, \"status\", out);\n  dump_proc_for_process(child, \"stack\", out);\n\n  auto threads = get_child_threads(child);\n  for (pid_t p : threads) {\n    dump_proc_for_process(p, \"status\", out);\n    dump_proc_for_process(p, \"stack\", out);\n  }\n\n  auto it = child_processes.map.find(child);\n  if (it != child_processes.map.end()) {\n    if (!*rr_pid && it->second.name == \"rr\") {\n      *rr_pid = child;\n    }\n    for (pid_t p : it->second.children) {\n      dump_subtree(child_processes, visited, p, out, rr_pid);\n    }\n  }\n}\n\nstatic void dump_state_and_kill(pid_t child, const char* out_file_name) {\n  FILE* out = fopen(out_file_name, \"a\");\n  if (!out) {\n    fprintf(stderr, \"Couldn't open %s for writing\\n\", out_file_name);\n    return;\n  }\n\n  setlinebuf(out);\n\n  if (received_siginfo.si_signo == SIGURG) {\n    fprintf(out, \"process %d sent SIGURG\\n\", received_siginfo.si_pid);\n  } else {\n    fprintf(out, \"timeout %lu exceeded\\n\", timeout);\n  }\n\n  ProcessMap child_processes(out);\n  unordered_set<pid_t> visited;\n  pid_t rr_pid = 0;\n  dump_subtree(child_processes, visited, child, out, &rr_pid);\n\n  // If something goes wrong while dumping the gdb stacktrace below, we want\n  // to make sure rr doesn't overwrite what we just printed. Seek the stderr\n  // fd (which we share with rr) to the end, to make sure rr prints in the\n  // right place.\n  lseek(STDERR_FILENO, 0, SEEK_END);\n\n  // We get a stacktrace for rr first. We don't try to get stacktraces for\n  // all processes because sometimes attaching and then detaching gdb can\n  // cause a process to wake up from a wait, and we don't want that. Attaching\n  // and detaching from rr should be harmless.\n  pid_t sig_pid =\n      received_siginfo.si_signo == SIGURG ? received_siginfo.si_pid : 0;\n  if (rr_pid || sig_pid) {\n    if (rr_pid && sig_pid && rr_pid != sig_pid) {\n      fprintf(out,\n              \"Confused about rr pid; signal says %d, process tree says %d\\n\",\n              sig_pid, rr_pid);\n    }\n    dump_gdb_stacktrace(sig_pid ? sig_pid : rr_pid, out);\n    lseek(STDERR_FILENO, 0, SEEK_END);\n\n    if (sig_pid) {\n      // Try to connect to the emergency debugger and get stack/regs.\n      // If rr is in a broken state this might hang, so we do this last.\n      FILE* gdb_cmd = fopen(\"gdb_cmd\", \"r\");\n      if (gdb_cmd) {\n        char buf[1024 * 10];\n        if (fgets(buf, sizeof(buf), gdb_cmd)) {\n          dump_emergency_debugger(buf, out);\n        }\n        fclose(gdb_cmd);\n      }\n    } else {\n      force_trace_closure(rr_pid, out);\n    }\n  }\n\n  fclose(out);\n  lseek(STDERR_FILENO, 0, SEEK_END);\n\n  for (pid_t p : visited) {\n    kill(p, SIGKILL);\n  }\n}\n\nint main(int argc, char* argv[]) {\n  if (argc < 4) {\n    print_usage(stderr);\n    return 1;\n  }\n\n  char* endp;\n  timeout = strtoul(argv[1], &endp, 10);\n  if (*endp || timeout > UINT32_MAX) {\n    fprintf(stderr, \"Invalid timeout %s\\n\", argv[1]);\n    return 1;\n  }\n  if (char *diagnose_timeout_str = getenv(\"RR_TEST_DIAGNOSE_TIMEOUT\")) {\n      diagnose_timeout = strtoul(diagnose_timeout_str, &endp, 10);\n      if (*endp) {\n          diagnose_timeout = ULONG_MAX;\n      }\n  }\n\n  pid_t child;\n  while (true) {\n    child = fork();\n    if (child < 0) {\n      if (errno == EAGAIN) {\n        continue;\n      }\n      perror(\"fork failed\");\n      return 2;\n    }\n    if (child > 0) {\n      break;\n    }\n    /* Put the child in its own process group */\n    setpgid(0, 0);\n    char buf[1024];\n    sprintf(buf, \"%d\", getppid());\n    setenv(\"RUNNING_UNDER_TEST_MONITOR\", buf, 1);\n    execvp(argv[3], &argv[3]);\n    perror(\"exec failed\");\n    return 2;\n  }\n\n  struct sigaction sa;\n  sa.sa_flags = SA_SIGINFO;\n  sa.sa_sigaction = sighandler;\n  sigemptyset(&sa.sa_mask);\n  sigaction(SIGURG, &sa, NULL);\n  sigaction(SIGALRM, &sa, NULL);\n\n  alarm(timeout);\n  int status;\n  int ret = waitpid(child, &status, 0);\n  if (ret < 0) {\n    if (errno != EINTR) {\n      perror(\"waitpid failed\");\n      return 2;\n    }\n    if (!received_siginfo.si_signo) {\n      fputs(\"Interrupted by unexpected signal\\n\", stderr);\n      return 3;\n    }\n\n    dump_state_and_kill(child, argv[2]);\n    abort();\n  }\n  if (WIFEXITED(status)) {\n    return WEXITSTATUS(status);\n  }\n  raise(WTERMSIG(status));\n  return 3;\n}\n"
  },
  {
    "path": "src/util.cc",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#include \"util.h\"\n\n#include <arpa/inet.h>\n#include <dirent.h>\n#include <elf.h>\n#ifdef EXECINFO_BACKTRACE\n#include <execinfo.h>\n#endif\n#include <fcntl.h>\n#include <inttypes.h>\n#include <limits.h>\n#include <linux/capability.h>\n#include <linux/magic.h>\n#include <math.h>\n#include <netdb.h>\n#include <netinet/in.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/resource.h>\n#include <sys/prctl.h>\n#include <sys/socket.h>\n#include <sys/syscall.h>\n#include <sys/time.h>\n#include <sys/types.h>\n#include <sys/uio.h>\n#include <sys/vfs.h>\n#include <unistd.h>\n\n#include <algorithm>\n#include <filesystem>\n#include <fstream>\n#include <numeric>\n#include <random>\n#include <sstream>\n#include <string>\n#include <unordered_set>\n\n#include \"preload/preload_interface.h\"\n\n#include \"AddressSpace.h\"\n#include \"AutoRemoteSyscalls.h\"\n#include \"CPUs.h\"\n#include \"Flags.h\"\n#include \"PerfCounters.h\"\n#include \"ReplaySession.h\"\n#include \"RecordTask.h\"\n#include \"ReplayTask.h\"\n#include \"ScopedFd.h\"\n#include \"TraceStream.h\"\n#include \"WaitManager.h\"\n#include \"core.h\"\n#include \"kernel_abi.h\"\n#include \"kernel_metadata.h\"\n#include \"log.h\"\n#include \"seccomp-bpf.h\"\n\nvoid good_random(uint8_t* out, size_t out_len);\n\nusing namespace std;\n\nnamespace rr {\n\ntemplate <typename Arch> static remote_ptr<typename Arch::unsigned_word> env_ptr(Task* t) {\n  auto stack_ptr = t->regs().sp().cast<typename Arch::unsigned_word>();\n\n  auto argc = t->read_mem(stack_ptr);\n  stack_ptr += argc + 1;\n\n  // Check final NULL in argv\n  auto null_ptr = t->read_mem(stack_ptr);\n  ASSERT(t, null_ptr == 0);\n  stack_ptr++;\n  return stack_ptr;\n}\n\ntemplate <typename Arch> remote_ptr<typename Arch::unsigned_word> auxv_ptr(Task* t) {\n  auto stack_ptr = env_ptr<Arch>(t);\n\n  // Should now point to envp\n  while (0 != t->read_mem(stack_ptr)) {\n    stack_ptr++;\n  }\n  stack_ptr++;\n  // should now point to ELF Auxiliary Table\n  return stack_ptr;\n}\n\ntemplate <typename Arch>\nstatic vector<uint8_t> read_auxv_arch(Task* t, remote_ptr<typename Arch::unsigned_word> stack_ptr) {\n  vector<uint8_t> result;\n  while (true) {\n    auto pair_vec = t->read_mem(stack_ptr, 2);\n    stack_ptr += 2;\n    typename Arch::unsigned_word pair[2] = { pair_vec[0], pair_vec[1] };\n    result.resize(result.size() + sizeof(pair));\n    memcpy(result.data() + result.size() - sizeof(pair), pair, sizeof(pair));\n    if (pair[0] == 0) {\n      break;\n    }\n  }\n  return result;\n}\n\ntemplate <typename Arch> static vector<uint8_t> read_auxv_arch(Task* t) {\n  auto stack_ptr = auxv_ptr<Arch>(t);\n  return read_auxv_arch<Arch>(t, stack_ptr);\n}\n\nvector<uint8_t> read_auxv(Task* t) {\n  RR_ARCH_FUNCTION(read_auxv_arch, t->arch(), t);\n}\n\nremote_ptr<void> read_interpreter_base(std::vector<uint8_t> auxv) {\n  if (auxv.size() == 0 || (auxv.size() % sizeof(uint64_t) != 0)) {\n    // Corrupted or missing auxv\n    return nullptr;\n  }\n  remote_ptr<void> interpreter_base = nullptr;\n  for (size_t i = 0; i < (auxv.size() / sizeof(uint64_t)) - 1; i += 2) {\n    uint64_t* entry = ((uint64_t*)auxv.data())+i;\n    uint64_t kind = entry[0];\n    uint64_t value = entry[1];\n    if (kind == AT_BASE) {\n      interpreter_base = value;\n      break;\n    }\n  }\n  return interpreter_base;\n}\n\nstd::string read_ld_path(Task* t, remote_ptr<void> interpreter_base) {\n  if (!interpreter_base) {\n    return {};\n  }\n  // Find first executable mapping after the interpreter_base and use its fsname().\n  // Non-executable maps may not have a file name.\n  remote_ptr<void> addr = interpreter_base;\n  while (true) {\n    if (!t->vm()->has_mapping(addr)) {\n      return {};\n    }\n    const KernelMapping& map = t->vm()->mapping_of(addr).map;\n    if (map.prot() & PROT_EXEC) {\n      return map.fsname();\n    }\n    addr = map.end();\n  }\n}\n\ntemplate <typename Arch> void patch_auxv_vdso_arch(RecordTask* t, uintptr_t search, uintptr_t new_entry_native) {\n  auto stack_ptr = auxv_ptr<Arch>(t);\n  std::vector<uint8_t> v = read_auxv_arch<Arch>(t, stack_ptr);\n  size_t wsize = sizeof(typename Arch::unsigned_word);\n  for (int i = 0; (i + 1)*wsize*2 <= v.size(); ++i) {\n    if (*((typename Arch::unsigned_word*)(v.data() + i*2*wsize)) == search) {\n      auto entry_ptr = stack_ptr + i*2 + 1;\n      typename Arch::unsigned_word new_entry = new_entry_native;\n      t->write_mem(entry_ptr, new_entry);\n      t->record_local(entry_ptr, &new_entry);\n      return;\n    }\n  }\n  return;\n}\n\nvoid patch_auxv_vdso(RecordTask* t, uintptr_t search, uintptr_t new_entry) {\n  RR_ARCH_FUNCTION(patch_auxv_vdso_arch, t->arch(), t, search, new_entry);\n}\n\ntemplate <typename Arch> static vector<string> read_env_arch(Task* t) {\n  auto stack_ptr = env_ptr<Arch>(t);\n\n  // Should now point to envp\n  vector<string> result;\n  while (true) {\n    auto p = t->read_mem(stack_ptr);\n    stack_ptr++;\n    if (!p) {\n      break;\n    }\n    result.push_back(t->read_c_str(remote_ptr<char>(p)));\n  }\n  return result;\n}\n\nvector<string> read_env(Task* t) {\n  RR_ARCH_FUNCTION(read_env_arch, t->arch(), t);\n}\n\n// FIXME this function assumes that there's only one address space.\n// Should instead only look at the address space of the task in\n// question.\nstatic bool is_start_of_scratch_region(Task* t, remote_ptr<void> start_addr) {\n  for (auto& kv : t->session().tasks()) {\n    Task* c = kv.second;\n    if (start_addr == c->scratch_ptr) {\n      return true;\n    }\n  }\n  return false;\n}\n\nbool probably_not_interactive(int fd) {\n  if (Flags::get().non_interactive) {\n    return true;\n  }\n  /* Eminently tunable heuristic, but this is guaranteed to be\n   * true during rr unit tests, where we care most about this\n   * check (to a first degree).  A failing test shouldn't\n   * hang. */\n  return !isatty(fd);\n}\n\nint clone_flags_to_task_flags(int flags_arg) {\n  int flags = CLONE_SHARE_NOTHING;\n  // See Task.h for description of the flags.\n  flags |= (CLONE_CHILD_CLEARTID & flags_arg) ? CLONE_CLEARTID : 0;\n  flags |= (CLONE_SETTLS & flags_arg) ? CLONE_SET_TLS : 0;\n  flags |= (CLONE_SIGHAND & flags_arg) ? CLONE_SHARE_SIGHANDLERS : 0;\n  flags |= (CLONE_THREAD & flags_arg) ? CLONE_SHARE_THREAD_GROUP : 0;\n  flags |= (CLONE_VM & flags_arg) ? CLONE_SHARE_VM : 0;\n  flags |= (CLONE_FILES & flags_arg) ? CLONE_SHARE_FILES : 0;\n  return flags;\n}\n\nsize_t page_size() {\n  /* This sometimes appears in profiles */\n  static size_t size = sysconf(_SC_PAGE_SIZE);\n  return size;\n}\n\nsize_t ceil_page_size(size_t sz) {\n  size_t page_mask = ~(page_size() - 1);\n  return (sz + page_size() - 1) & page_mask;\n}\n\nsize_t floor_page_size(size_t sz) {\n  size_t page_mask = ~(page_size() - 1);\n  return sz & page_mask;\n}\n\nremote_ptr<void> ceil_page_size(remote_ptr<void> addr) {\n  return remote_ptr<void>(ceil_page_size(addr.as_int()));\n}\n\nremote_ptr<void> floor_page_size(remote_ptr<void> addr) {\n  return remote_ptr<void>(floor_page_size(addr.as_int()));\n}\n\n/**\n * Dump |buf_len| words in |buf| to |out|, starting with a line\n * containing |label|.  See |dump_binary_data()| for a description of\n * the remaining parameters.\n */\nstatic void dump_binary_chunk(FILE* out, const char* label, const uint32_t* buf,\n                              size_t buf_len, remote_ptr<void> start_addr) {\n  int i;\n\n  fprintf(out, \"%s\\n\", label);\n  for (i = 0; i < ssize_t(buf_len); i += 1) {\n    uint32_t word = buf[i];\n    fprintf(out, \"0x%08x | [%p]\\n\", word,\n            (void*)(start_addr.as_int() + i * sizeof(*buf)));\n  }\n}\n\nvoid dump_binary_data(const char* filename, const char* label,\n                      const uint32_t* buf, size_t buf_len,\n                      remote_ptr<void> start_addr) {\n  FILE* out = fopen64(filename, \"w\");\n  if (!out) {\n    return;\n  }\n  dump_binary_chunk(out, label, buf, buf_len, start_addr);\n  fclose(out);\n}\n\nstring format_dump_filename(Task* t, FrameTime global_time, const char* tag) {\n  stringstream s;\n  s << t->trace_dir() << \"/\" << global_time << \"_\" << t->rec_tid << \"_\"\n    << tag;\n  return s.str();\n}\n\nbool should_dump_memory(const Event& event, FrameTime time) {\n  const Flags* flags = &Flags::get();\n\n  return flags->dump_on == Flags::DUMP_ON_ALL ||\n         (event.is_syscall_event() &&\n          event.Syscall().number == flags->dump_on) ||\n         (event.is_signal_event() &&\n          event.Signal().siginfo.si_signo == -flags->dump_on) ||\n         (flags->dump_on == Flags::DUMP_ON_RDTSC &&\n          event.type() == EV_INSTRUCTION_TRAP) ||\n         flags->dump_at == time;\n}\n\nvoid dump_process_memory(Task* t, FrameTime global_time, const char* tag) {\n  string filename = format_dump_filename(t, global_time, tag);\n  FILE* dump_file = fopen64(filename.c_str(), \"w\");\n\n  const AddressSpace& as = *(t->vm());\n  for (const auto& m : as.maps()) {\n    vector<uint8_t> mem;\n    mem.resize(m.map.size());\n\n    ssize_t mem_len =\n        t->read_bytes_fallible(m.map.start(), m.map.size(), mem.data());\n    mem_len = max(ssize_t(0), mem_len);\n\n    if (!is_start_of_scratch_region(t, m.map.start())) {\n      dump_binary_chunk(dump_file, m.map.str().c_str(),\n                        (const uint32_t*)mem.data(), mem_len / sizeof(uint32_t),\n                        m.map.start());\n    }\n  }\n  fclose(dump_file);\n}\n\nvoid write_pt_data(Task* t, FrameTime global_time, const vector<vector<uint8_t>>& data) {\n  string filename = format_dump_filename(t, global_time, \"pt\");\n  ScopedFd dump_file(filename.c_str(), O_WRONLY | O_TRUNC | O_CREAT, 0700);\n  ASSERT(t, dump_file.is_open()) << \"Can't write to file \" << filename;\n  for (const auto& d : data) {\n    write_all(dump_file, d.data(), d.size());\n  }\n}\n\nvector<uint8_t> read_pt_data(Task* t, FrameTime global_time) {\n  string filename = format_dump_filename(t, global_time, \"pt\");\n  FILE* dump_file = fopen64(filename.c_str(), \"r\");\n  vector<uint8_t> result;\n  if (!dump_file) {\n    return result;\n  }\n\n  while (true) {\n    char buf[1024*1024];\n    size_t bytes_read = fread(buf, 1, sizeof(buf), dump_file);\n    if (bytes_read) {\n      size_t current_size = result.size();\n      result.resize(current_size + bytes_read);\n      memcpy(result.data() + current_size, buf, bytes_read);\n    }\n    if (bytes_read < sizeof(buf)) {\n      break;\n    }\n  }\n  fclose(dump_file);\n  return result;\n}\n\nstatic void notify_checksum_error(ReplayTask* t, FrameTime global_time,\n                                  unsigned checksum, unsigned rec_checksum,\n                                  const string& raw_map_line) {\n  dump_process_memory(t, global_time, \"checksum_error\");\n\n  /* TODO: if the right recorder memory dump is present,\n   * automatically compare them, taking the oddball\n   * not-mapped-during-replay region(s) into account.  And if\n   * not present, tell the user how to make one in a future\n   * run. */\n  string cur_dump = format_dump_filename(t, global_time, \"checksum_error\");\n  string rec_dump = format_dump_filename(t, global_time, \"rec\");\n\n  const Event& ev = t->current_trace_frame().event();\n  ASSERT(t, checksum == rec_checksum)\n      << \"Divergence in contents of memory segment after '\" << ev << \"':\\n\"\n                                                                     \"\\n\"\n      << raw_map_line << \"    (recorded checksum:\" << HEX(rec_checksum)\n      << \"; replaying checksum:\" << HEX(checksum) << \")\\n\"\n                                                     \"\\n\"\n      << \"Dumped current memory contents to \" << cur_dump\n      << \". If you've created a memory dump for\\n\"\n      << \"the '\" << ev << \"' event (line \" << t->trace_time()\n      << \") during recording by using, for example with\\n\"\n      << \"the args\\n\"\n         \"\\n\"\n      << \"$ rr --dump-at=\" << t->trace_time() << \" record ...\\n\"\n                                                 \"\\n\"\n      << \"then you can use the following to determine which memory cells \"\n         \"differ:\\n\"\n         \"\\n\"\n      << \"$ diff -u \" << rec_dump << \" \" << cur_dump << \" > mem-diverge.diff\\n\";\n}\n\nstatic bool checksum_segment_filter(const AddressSpace::Mapping& m) {\n  struct stat st;\n  int may_diverge;\n\n  if (m.map.fsname() == \"[vsyscall]\") {\n    // This can't be read/checksummed.\n    return false;\n  }\n  if (stat(m.map.fsname().c_str(), &st)) {\n    /* If there's no persistent resource backing this\n     * mapping, we should expect it to change. */\n    LOG(debug) << \"CHECKSUMMING unlinked '\" << m.map.fsname() << \"'\";\n    return true;\n  }\n  /* If we're pretty sure the backing resource is effectively\n   * immutable, skip checksumming, it's a waste of time.  Except\n   * if the mapping is mutable, for example the rw data segment\n   * of a system library, then it's interesting. */\n  static const char mmap_clone[] = \"mmap_clone_\";\n  may_diverge =\n      m.map.fsname().substr(0, array_length(mmap_clone) - 1) != mmap_clone &&\n      (should_copy_mmap_region(m.map, m.map.fsname(), st) || (PROT_WRITE & m.map.prot()));\n  LOG(debug) << (may_diverge ? \"CHECKSUMMING\" : \"  skipping\") << \" '\"\n             << m.map.fsname() << \"'\";\n  return may_diverge;\n}\n\nstatic uint32_t compute_checksum(void* data, size_t len) {\n  uint32_t checksum = len;\n  size_t words = len / sizeof(uint32_t);\n  uint32_t* buf = static_cast<uint32_t*>(data);\n  for (size_t i = 0; i < words; ++i) {\n    checksum = (checksum << 4) + checksum + buf[i];\n  }\n  return checksum;\n}\n\nstatic const uint32_t ignored_checksum = 0x98765432;\nstatic const uint32_t sigbus_checksum = 0x23456789;\n\nbool should_checksum(const Event& event, FrameTime time) {\n  FrameTime checksum = Flags::get().checksum;\n  if (Flags::CHECKSUM_NONE == checksum) {\n    return false;\n  }\n\n  if (event.type() == EV_EXIT) {\n    // Task is dead, or at least detached, and we can't read its memory safely.\n    return false;\n  }\n  if (event.has_ticks_slop()) {\n    // We may not be at the same point during recording and replay, so don't\n    // compute checksums.\n    return false;\n  }\n\n  if (Flags::CHECKSUM_ALL == checksum) {\n    // Don't checksum at syscall entry because we sometimes mutate syscall parameters there\n    // and that will cause false divergence\n    return EV_SYSCALL != event.type() || ENTERING_SYSCALL != event.Syscall().state;\n  }\n  if (Flags::CHECKSUM_SYSCALL == checksum) {\n    return EV_SYSCALL == event.type() && EXITING_SYSCALL == event.Syscall().state;\n  }\n  /* |checksum| is a global time point. */\n  return checksum <= time;\n}\n\nstatic void normalize_syscallbuf(Task* t, vector<uint8_t>& mem) {\n  /* The syscallbuf consists of a region that's written\n   * deterministically wrt the trace events, and a\n   * region that's written nondeterministically in the\n   * same way as trace scratch buffers.  The\n   * deterministic region comprises committed syscallbuf\n   * records, and possibly the one pending record\n   * metadata.  The nondeterministic region starts at\n   * the \"extra data\" for the possibly one pending\n   * record.\n   *\n   * The deterministic region excludes the notify_on_syscall_hook_exit\n   * flag. This flag is written by is_safe_to_deliver_signal and\n   * that write can occur at a different event to where ReplaySession\n   * eventually sets it.\n   *\n   * So here, we set things up so that we only checksum\n   * the deterministic region. */\n  struct syscallbuf_hdr hdr;\n  size_t hdr_size = t->session().syscallbuf_hdr_size();\n  ASSERT(t, mem.size() >= hdr_size);\n  memcpy(&hdr, mem.data(), hdr_size);\n  hdr.notify_on_syscall_hook_exit = 0;\n  memcpy(mem.data(), &hdr, hdr_size);\n  mem.resize(hdr_size + hdr.num_rec_bytes + sizeof(struct syscallbuf_record));\n}\n\nvoid checksum_process_memory(RecordTask* t, FrameTime global_time) {\n  string filename = format_dump_filename(t, global_time, \"mem_checksums\");\n  FILE* checksums_file = fopen64(filename.c_str(), \"w\");\n  if (!checksums_file) {\n    FATAL() << \"Failed to open checksum file \" << filename;\n  }\n\n  AddressSpace& as = *t->vm();\n  for (auto it = as.maps().begin(); it != as.maps().end(); ++it) {\n    AddressSpace::Mapping m = *it;\n    string raw_map_line = m.map.str();\n\n    if (!checksum_segment_filter(m)) {\n      fprintf(checksums_file, \"(%x) %s\\n\", ignored_checksum,\n              raw_map_line.c_str());\n      continue;\n    }\n\n    vector<uint8_t> mem;\n    mem.resize(m.map.size());\n    memset(mem.data(), 0, mem.size());\n    ssize_t valid_mem_len =\n        t->read_bytes_fallible(m.map.start(), mem.size(), mem.data());\n    /* Areas not read are treated as zero. We have to do this because\n       mappings not backed by valid file data are not readable during\n       recording but are read as 0 during replay. */\n    if (valid_mem_len < 0) {\n      /* It is possible for whole mappings to be beyond the extent of the\n       * backing file, in which case read_bytes_fallible will return -1.\n       */\n      ASSERT(t, valid_mem_len == -1 && errno == EIO);\n    }\n\n    if (m.flags & AddressSpace::Mapping::IS_SYSCALLBUF) {\n      normalize_syscallbuf(t, mem);\n    }\n\n    uint32_t checksum = compute_checksum(mem.data(), mem.size());\n    fprintf(checksums_file, \"(%x) %s\\n\", checksum, raw_map_line.c_str());\n  }\n\n  fclose(checksums_file);\n}\n\nvoid validate_process_memory(ReplayTask* t, FrameTime global_time) {\n  string filename = format_dump_filename(t, global_time, \"mem_checksums\");\n  FILE* checksums_file = fopen64(filename.c_str(), \"r\");\n  if (!checksums_file) {\n    FATAL() << \"Failed to open checksum file \" << filename;\n  }\n\n  remote_ptr<unsigned char> in_replay_flag;\n  if (t->session().has_trace_quirk(TraceReader::UsesGlobalsInReplay) && t->preload_globals) {\n    in_replay_flag = REMOTE_PTR_FIELD(t->preload_globals, reserved_legacy_in_replay);\n    t->write_mem(in_replay_flag, (unsigned char)0);\n  }\n\n  while (true) {\n    char line[1024];\n    if (!fgets(line, sizeof(line), checksums_file)) {\n      break;\n    }\n    unsigned int checksum;\n    unsigned long start;\n    unsigned long end;\n    int nparsed = sscanf(line, \"(%x) %lx-%lx\", &checksum, &start, &end);\n    ASSERT(t, 3 == nparsed) << \"Parsed \" << nparsed << \" items\";\n\n    if (is_start_of_scratch_region(t, start)) {\n      /* Replay doesn't touch scratch regions, so\n       * their contents are allowed to diverge.\n       * Tracees can't observe those segments unless\n       * they do something sneaky (or disastrously\n       * buggy). */\n      LOG(debug) << \"Not validating scratch starting at \" << start;\n      continue;\n    }\n\n    if (checksum == ignored_checksum) {\n      LOG(debug) << \"Checksum not computed during recording\";\n      continue;\n    }\n    if (checksum == sigbus_checksum) {\n      continue;\n    }\n\n    vector<uint8_t> mem;\n    mem.resize(end - start);\n    memset(mem.data(), 0, mem.size());\n    t->read_bytes_fallible(start, mem.size(), mem.data());\n\n    const AddressSpace::Mapping& m = t->vm()->mapping_of(start);\n\n    if (m.flags & AddressSpace::Mapping::IS_SYSCALLBUF) {\n      normalize_syscallbuf(t, mem);\n    }\n\n    uint32_t our_checksum = compute_checksum(mem.data(), mem.size());\n\n    if (checksum != our_checksum) {\n      notify_checksum_error(t, global_time, our_checksum, checksum,\n                            m.map.str());\n    }\n  }\n\n  if (in_replay_flag) {\n    t->write_mem(in_replay_flag, (unsigned char)1);\n  }\n\n  fclose(checksums_file);\n}\n\nsignal_action default_action(int sig) {\n  if (32 <= sig && sig <= 64) {\n    return TERMINATE;\n  }\n  switch (sig) {\n/* TODO: SSoT for signal defs/semantics. */\n#define CASE(_sig, _act)                                                       \\\n  case SIG##_sig:                                                              \\\n    return _act\n    CASE(HUP, TERMINATE);\n    CASE(INT, TERMINATE);\n    CASE(QUIT, DUMP_CORE);\n    CASE(ILL, DUMP_CORE);\n    CASE(ABRT, DUMP_CORE);\n    CASE(FPE, DUMP_CORE);\n    CASE(KILL, TERMINATE);\n    CASE(SEGV, DUMP_CORE);\n    CASE(PIPE, TERMINATE);\n    CASE(ALRM, TERMINATE);\n    CASE(TERM, TERMINATE);\n    CASE(USR1, TERMINATE);\n    CASE(USR2, TERMINATE);\n    CASE(CHLD, IGNORE);\n    CASE(CONT, CONTINUE);\n    CASE(STOP, STOP);\n    CASE(TSTP, STOP);\n    CASE(TTIN, STOP);\n    CASE(TTOU, STOP);\n    CASE(BUS, DUMP_CORE);\n    /*CASE(POLL, TERMINATE);*/\n    CASE(PROF, TERMINATE);\n    CASE(SYS, DUMP_CORE);\n    CASE(TRAP, DUMP_CORE);\n    CASE(URG, IGNORE);\n    CASE(VTALRM, TERMINATE);\n    CASE(XCPU, DUMP_CORE);\n    CASE(XFSZ, DUMP_CORE);\n    /*CASE(IOT, DUMP_CORE);*/\n    /*CASE(EMT, TERMINATE);*/\n    CASE(STKFLT, TERMINATE);\n    CASE(IO, TERMINATE);\n    CASE(PWR, TERMINATE);\n    /*CASE(LOST, TERMINATE);*/\n    CASE(WINCH, IGNORE);\n    default:\n      FATAL() << \"Unknown signal \" << sig;\n      return TERMINATE; // not reached\n#undef CASE\n  }\n}\n\nSignalDeterministic is_deterministic_signal(Task* t) {\n  const siginfo_t& si = t->get_siginfo();\n  switch (si.si_signo) {\n    /* These signals may be delivered deterministically;\n     * we'll check for sure below. */\n    case SIGILL:\n    case SIGBUS:\n    case SIGFPE:\n    case SIGSEGV:\n      /* As bits/siginfo.h documents,\n       *\n       *   Values for `si_code'.  Positive values are\n       *   reserved for kernel-generated signals.\n       *\n       * So if the signal is maybe-synchronous, and the\n       * kernel delivered it, then it must have been\n       * delivered deterministically. */\n      return si.si_code > 0 ? DETERMINISTIC_SIG : NONDETERMINISTIC_SIG;\n    case SIGTRAP: {\n      // The kernel code is wrong about this one. It treats singlestep\n      // traps as deterministic, but they aren't. PTRACE_ATTACH traps aren't\n      // really deterministic either.\n      auto reasons = t->compute_trap_reasons();\n      return reasons.breakpoint || reasons.watchpoint ? DETERMINISTIC_SIG\n                                                      : NONDETERMINISTIC_SIG;\n    }\n    default:\n      /* All other signals can never be delivered\n       * deterministically (to the approximation required by\n       * rr). */\n      return NONDETERMINISTIC_SIG;\n  }\n}\n\nstatic bool is_tmp_file(const ScopedFd &fd, const string &tracee_path) {\n  if (getenv(\"RR_TRUST_TEMP_FILES\")) {\n    return false;\n  }\n  struct statfs sfs;\n  int ret = fstatfs(fd.get(), &sfs);\n  return ((ret == 0 && TMPFS_MAGIC == sfs.f_type)\n          // In observed configurations of Ubuntu 13.10, /tmp is\n          // a folder in the / fs, not a separate tmpfs.\n          || tracee_path.c_str() == strstr(tracee_path.c_str(), \"/tmp/\"));\n}\n\nbool should_copy_mmap_region(const KernelMapping& mapping,\n                             const string &file_name,\n                             const struct stat& stat) {\n  if (getenv(\"RR_COPY_ALL_FILES\")) {\n    return true;\n  }\n\n  int flags = mapping.flags();\n  int prot = mapping.prot();\n  bool private_mapping = (flags & MAP_PRIVATE);\n\n  // file_name may point into proc, since we may not have direct access to\n  // the file. Open it, so we can perform the various queries we'd like to ask.\n  ScopedFd fd(file_name.c_str(), O_RDONLY);\n\n  // TODO: handle mmap'd files that are unlinked during\n  // recording or otherwise not available.\n  if (!fd.is_open()) {\n    // This includes files inaccessible because the tracee is using a different\n    // mount namespace with its own mounts\n    // It's also possible for a tracee to mmap a file it doesn't have permission\n    // to read, e.g. if a daemon opened the file and passed the fd over a\n    // socket. We should copy the data now because we won't be able to read\n    // it later. nscd does this.\n    LOG(debug) << \"  copying unlinked/inaccessible file\";\n    return true;\n  }\n  if (!S_ISREG(stat.st_mode)) {\n    LOG(debug) << \"  copying non-regular-file\";\n    return true;\n  }\n  if (is_tmp_file(fd, mapping.fsname())) {\n    LOG(debug) << \"  copying file on tmpfs\";\n    return true;\n  }\n  if (mapping.fsname() == \"/etc/ld.so.cache\") {\n    // This file changes on almost every system update so we should copy it.\n    LOG(debug) << \"  copying \" << mapping.fsname();\n    return true;\n  }\n  if (mapping.fsname().rfind(\"/etc/passwd\", 0) == 0 ||\n      mapping.fsname().rfind(\"/etc/group\", 0) == 0) {\n    // These files (and suffixes such as .cache etc) change very frequently in\n    // some environments.\n    LOG(debug) << \"  copying \" << mapping.fsname();\n    return true;\n  }\n  if (private_mapping && (prot & PROT_EXEC)) {\n    /* Be optimistic about private executable mappings */\n    LOG(debug) << \"  (no copy for +x private mapping \" << mapping.fsname() << \")\";\n    return false;\n  }\n  if (private_mapping && (0111 & stat.st_mode)) {\n    /* A private mapping of an executable file usually\n     * indicates mapping data sections of object files.\n     * Since we're already assuming those change very\n     * infrequently, we can avoid copying the data\n     * sections too. */\n    LOG(debug) << \"  (no copy for private mapping of +x \" << mapping.fsname() << \")\";\n    return false;\n  }\n\n  // TODO: using \"can the euid of the rr process write this\n  // file\" as an approximation of whether the tracee can write\n  // the file.  If the tracee is messing around with\n  // set*[gu]id(), the real answer may be different.\n  bool can_write_file = (0 == access(file_name.c_str(), W_OK));\n\n  // Inside a user namespace, the real root user may be mapped to UID 65534.\n  if (!can_write_file && (0 == stat.st_uid || 65534 == stat.st_uid)) {\n    // We would like to DEBUG_ASSERT this, but on Ubuntu 13.10,\n    // the file /lib/i386-linux-gnu/libdl-2.17.so is\n    // writeable by root for unknown reasons.\n    // DEBUG_ASSERT(!(prot & PROT_WRITE));\n    /* Mapping a file owned by root: we don't care if this\n     * was a PRIVATE or SHARED mapping, because unless the\n     * program is disastrously buggy or unlucky, the\n     * mapping is effectively PRIVATE.  Bad luck can come\n     * from this program running during a system update,\n     * or a user being added, which is probably less\n     * frequent than even system updates.\n     *\n     * XXX what about the fontconfig cache files? */\n    LOG(debug) << \"  (no copy for root-owned \" << mapping.fsname() << \")\";\n    return false;\n  }\n  if (private_mapping) {\n    /* Some programs (at least Firefox) have been observed\n     * to use cache files that are expected to be\n     * consistent and unchanged during the bulk of\n     * execution, but may be destroyed or mutated at\n     * shutdown in preparation for the next session.  We\n     * don't otherwise know what to do with private\n     * mappings, so err on the safe side.\n     *\n     * TODO: could get into dirty heuristics here like\n     * trying to match \"cache\" in the filename ... */\n    LOG(debug) << \"  copying private mapping of non-system -x \" << file_name;\n    return true;\n  }\n  if (!(0222 & stat.st_mode)) {\n    /* We couldn't write the file because it's read only.\n     * But it's not a root-owned file (therefore not a\n     * system file), so it's likely that it could be\n     * temporary.  Copy it. */\n    LOG(debug) << \"  copying read-only, non-system file\";\n    return true;\n  }\n  if (!can_write_file) {\n    /* mmap'ing another user's (non-system) files?  Highly\n     * irregular ... */\n    LOG(warn) << \"Scary mmap \" << file_name << \"(prot:\" << HEX(prot)\n              << ((flags & MAP_SHARED) ? \";SHARED\" : \"\")\n              << \"); uid:\" << stat.st_uid << \" mode:\" << stat.st_mode;\n  }\n  return true;\n}\n\nvoid resize_shmem_segment(ScopedFd& fd, uint64_t num_bytes) {\n  if (ftruncate(fd, num_bytes)) {\n    FATAL() << \"Failed to resize shmem to \" << num_bytes;\n  }\n}\n\nbool xsave_enabled() {\n  CPUIDData features = cpuid(CPUID_GETFEATURES, 0);\n  return (features.ecx & OSXSAVE_FEATURE_FLAG) != 0;\n}\n\n\n#define FATAL_X86_ONLY() FATAL() << \"Reached x86-only code on non-x86 arch\"\n\nuint64_t xcr0() {\n#if defined(__i386__) || defined(__x86_64__)\n  if (!xsave_enabled()) {\n    // Assume x87/SSE enabled.\n    return 3;\n  }\n  uint32_t eax, edx;\n  asm volatile(\"xgetbv\"\n               : \"=a\"(eax), \"=d\"(edx)\n               : \"c\"(0));\n  return (uint64_t(edx) << 32) | eax;\n#else\n  FATAL_X86_ONLY();\n  return 0;\n#endif\n}\n\n#if defined(__i386__) || defined(__x86_64__)\nCPUIDData cpuid(uint32_t code, uint32_t subrequest) {\n  CPUIDData result;\n  asm volatile(\"cpuid\"\n               : \"=a\"(result.eax), \"=b\"(result.ebx), \"=c\"(result.ecx),\n                 \"=d\"(result.edx)\n               : \"a\"(code), \"c\"(subrequest));\n  return result;\n}\n#else\nCPUIDData cpuid(uint32_t, uint32_t) {\n  FATAL_X86_ONLY();\n  __builtin_unreachable();\n}\n#endif\n\n\n#define SEGV_HANDLER_MAGIC 0x98765432\n\nstatic void cpuid_segv_handler(__attribute__((unused)) int sig,\n                               __attribute__((unused)) siginfo_t* si,\n                               void* user) {\n#if defined(__i386__)\n  ucontext_t* ctx = (ucontext_t*)user;\n  ctx->uc_mcontext.gregs[REG_EIP] += 2;\n  ctx->uc_mcontext.gregs[REG_EAX] = SEGV_HANDLER_MAGIC;\n#elif defined(__x86_64__)\n  ucontext_t* ctx = (ucontext_t*)user;\n  ctx->uc_mcontext.gregs[REG_RIP] += 2;\n  ctx->uc_mcontext.gregs[REG_RAX] = SEGV_HANDLER_MAGIC;\n#else\n  (void)user;\n  FATAL_X86_ONLY();\n#endif\n}\n\nstatic CPUIDRecord cpuid_record(uint32_t eax, uint32_t ecx) {\n  CPUIDRecord result = { eax, ecx, cpuid(eax, ecx) };\n  return result;\n}\n\nbool is_cpu_vendor_amd(CPUIDData vendor_string)\n{\n  char vendor[12];\n  memcpy(&vendor[0], &vendor_string.ebx, 4);\n  memcpy(&vendor[4], &vendor_string.edx, 4);\n  memcpy(&vendor[8], &vendor_string.ecx, 4);\n  return strncmp(vendor, \"AuthenticAMD\", sizeof(vendor)) == 0;\n}\n\nstatic vector<CPUIDRecord> gather_cpuid_records(uint32_t up_to) {\n  vector<CPUIDRecord> results;\n  CPUIDRecord vendor_string = cpuid_record(CPUID_GETVENDORSTRING, UINT32_MAX);\n  results.push_back(vendor_string);\n  uint32_t basic_info_max = min(up_to, vendor_string.out.eax);\n  bool has_SGX = false;\n  bool has_hypervisor = false;\n\n  for (uint32_t base = 1; base <= basic_info_max; ++base) {\n    switch (base) {\n      case CPUID_GETCACHEPARAMS:\n        for (int level = 0;; ++level) {\n          CPUIDRecord rec = cpuid_record(base, level);\n          results.push_back(rec);\n          if (!(rec.out.eax & 0x1f)) {\n            // Cache Type Field == no more caches\n            break;\n          }\n        }\n        break;\n      case CPUID_GETEXTENDEDFEATURES: {\n        CPUIDRecord rec = cpuid_record(base, 0);\n        results.push_back(rec);\n        if (rec.out.ebx & 0x4) {\n          has_SGX = true;\n        }\n        for (uint32_t level = 1; level <= rec.out.eax; ++level) {\n          results.push_back(cpuid_record(base, level));\n        }\n        break;\n      }\n      case CPUID_GETEXTENDEDTOPOLOGY: {\n        for (int level = 0;; ++level) {\n          CPUIDRecord rec = cpuid_record(base, level);\n          results.push_back(rec);\n          if (!(rec.out.ecx & 0xff00)) {\n            // Level Type == 0\n            break;\n          }\n        }\n        break;\n      }\n      case CPUID_GETXSAVE:\n        for (uint32_t level = 0; level < 64; ++level) {\n          results.push_back(cpuid_record(base, level));\n        }\n        break;\n      case CPUID_GETRDTMONITORING: {\n        CPUIDRecord rec = cpuid_record(base, 0);\n        results.push_back(rec);\n        for (uint32_t level = 1; level < 64; ++level) {\n          if (rec.out.edx & (1LL << level)) {\n            results.push_back(cpuid_record(base, level));\n          }\n        }\n        break;\n      }\n      case CPUID_GETRDTALLOCATION: {\n        CPUIDRecord rec = cpuid_record(base, 0);\n        results.push_back(rec);\n        for (uint32_t level = 1; level < 64; ++level) {\n          if (rec.out.ebx & (1LL << level)) {\n            results.push_back(cpuid_record(base, level));\n          }\n        }\n        break;\n      }\n      case CPUID_GETSGX:\n        results.push_back(cpuid_record(base, 0));\n        if (has_SGX) {\n          results.push_back(cpuid_record(base, 1));\n          for (int level = 2;; ++level) {\n            CPUIDRecord rec = cpuid_record(base, level);\n            results.push_back(rec);\n            if (!(rec.out.eax & 0x0f)) {\n              // Sub-leaf Type == 0\n              break;\n            }\n          }\n        }\n        break;\n      case CPUID_GETPT:\n      case CPUID_GETSOC: {\n        CPUIDRecord rec = cpuid_record(base, 0);\n        results.push_back(rec);\n        for (uint32_t level = 1; level <= rec.out.eax; ++level) {\n          results.push_back(cpuid_record(base, level));\n        }\n        break;\n      }\n      case CPUID_GETFEATURES: {\n        CPUIDRecord rec = cpuid_record(base, UINT32_MAX);\n        results.push_back(rec);\n        if (rec.out.ecx & (1 << 31)) {\n          has_hypervisor = true;\n        }\n        break;\n      }\n      default:\n        results.push_back(cpuid_record(base, UINT32_MAX));\n        break;\n    }\n  }\n\n  if (up_to < CPUID_HYPERVISOR) {\n    return results;\n  }\n\n  if (has_hypervisor) {\n    CPUIDRecord hv_info = cpuid_record(CPUID_HYPERVISOR, UINT32_MAX);\n    results.push_back(hv_info);\n    int hv_info_max = min(up_to, hv_info.out.eax);\n    for (int extended = CPUID_HYPERVISOR + 1; extended <= hv_info_max;\n         ++extended) {\n      results.push_back(cpuid_record(extended, UINT32_MAX));\n    }\n  }\n\n  if (up_to < CPUID_INTELEXTENDED) {\n    return results;\n  }\n\n  bool is_amd = is_cpu_vendor_amd(vendor_string.out);\n\n  CPUIDRecord extended_info = cpuid_record(CPUID_INTELEXTENDED, UINT32_MAX);\n  results.push_back(extended_info);\n  uint32_t extended_info_max = min(up_to, extended_info.out.eax);\n  for (uint32_t extended = CPUID_INTELEXTENDED + 1; extended <= extended_info_max;\n       ++extended) {\n    if (is_amd) {\n      if (extended == CPUID_AMD_CACHE_TOPOLOGY) {\n        for (int level = 0;; ++level) {\n          CPUIDRecord rec = cpuid_record(extended, level);\n          results.push_back(rec);\n          if (!(rec.out.eax & 0x1f)) {\n            // CacheType: null, no more caches\n            break;\n          }\n        }\n        continue;\n      } else if (extended == CPUID_AMD_PLATFORM_QOS) {\n        cpuid_record(extended, 0);\n        cpuid_record(extended, 1);\n        continue;\n      }\n    }\n    results.push_back(cpuid_record(extended, UINT32_MAX));\n  }\n\n  return results;\n}\n\nvector<CPUIDRecord> all_cpuid_records() {\n  return gather_cpuid_records(UINT32_MAX);\n}\n\n#ifdef SYS_arch_prctl\n#define RR_ARCH_PRCTL(a, b) syscall(SYS_arch_prctl, a, b)\n#else\n#define RR_ARCH_PRCTL(a, b) ((void)a, (void)b, -1)\n#endif\n\nbool cpuid_faulting_works() {\n  static bool did_check_cpuid_faulting = false;\n  static bool cpuid_faulting_ok = false;\n\n#if !(defined(__i386__) || defined(__x86_64__))\n  did_check_cpuid_faulting = true;\n#endif\n  if (did_check_cpuid_faulting) {\n    return cpuid_faulting_ok;\n  }\n  did_check_cpuid_faulting = true;\n\n  // Test to see if CPUID faulting works.\n  if (RR_ARCH_PRCTL(ARCH_SET_CPUID, 0L) != 0) {\n    LOG(debug) << \"CPUID faulting not supported by kernel/hardware\";\n    return false;\n  }\n\n  // Some versions of Xen seem to set the feature bit but the feature doesn't\n  // actually work, so we need to test it.\n  struct sigaction sa;\n  struct sigaction old_sa;\n  sa.sa_sigaction = cpuid_segv_handler;\n  sigemptyset(&sa.sa_mask);\n  sa.sa_flags = SA_SIGINFO;\n  if (sigaction(SIGSEGV, &sa, &old_sa) < 0) {\n    FATAL() << \"Can't set sighandler\";\n  }\n\n  CPUIDData data = cpuid(CPUID_GETVENDORSTRING, 0);\n  if (data.eax == SEGV_HANDLER_MAGIC) {\n    LOG(debug) << \"CPUID faulting works\";\n    cpuid_faulting_ok = true;\n  } else {\n    LOG(debug) << \"CPUID faulting advertised but does not work\";\n  }\n\n  if (sigaction(SIGSEGV, &old_sa, NULL) < 0) {\n    FATAL() << \"Can't restore sighandler\";\n  }\n  if (RR_ARCH_PRCTL(ARCH_SET_CPUID, 1L) < 0) {\n    FATAL() << \"Can't restore ARCH_SET_CPUID\";\n  }\n  return cpuid_faulting_ok;\n}\n\nconst CPUIDRecord* find_cpuid_record(const vector<CPUIDRecord>& records,\n                                     uint32_t eax, uint32_t ecx) {\n  for (const auto& rec : records) {\n    if (rec.eax_in == eax && (rec.ecx_in == ecx || rec.ecx_in == UINT32_MAX)) {\n      return &rec;\n    }\n  }\n  return nullptr;\n}\n\nbool cpuid_compatible(const vector<CPUIDRecord>& trace_records) {\n  // We could compare all CPUID records but that might be fragile (it's hard to\n  // be sure the values don't change in ways applications don't care about).\n  // Let's just check the microarch for now.\n  auto cpuid_data = cpuid(CPUID_GETFEATURES, 0);\n  unsigned int cpu_type = cpuid_data.eax & 0xF0FF0;\n  auto trace_cpuid_data =\n      find_cpuid_record(trace_records, CPUID_GETFEATURES, 0);\n  if (!trace_cpuid_data) {\n    FATAL() << \"GETFEATURES missing???\";\n  }\n  unsigned int trace_cpu_type = trace_cpuid_data->out.eax & 0xF0FF0;\n  return cpu_type == trace_cpu_type;\n}\n\nbool cpu_has_xsave_fip_fdp_quirk() {\n  CPUIDData features = cpuid(CPUID_GETFEATURES, 0);\n  if ((features.ecx & XSAVE_FEATURE_FLAG) == 0) {\n    return false;\n  }\n#if defined(__i386__) || defined(__x86_64__)\n  uint64_t xsave_buf[576/sizeof(uint64_t)] __attribute__((aligned(64)));\n  xsave_buf[1] = 0;\n  asm volatile(\"finit\\n\"\n               \"fld1\\n\"\n#if defined(__x86_64__)\n               \"xsave64 %0\\n\"\n#else\n               \"xsave %0\\n\"\n#endif\n               : \"=m\"(xsave_buf)\n               : \"a\"(1), \"d\"(0)\n               : \"memory\");\n  return !xsave_buf[1];\n#else\n  FATAL_X86_ONLY();\n  return false;\n#endif\n}\n\nbool cpu_has_fdp_exception_only_quirk() {\n#if defined(__i386__) || defined(__x86_64__)\n  uint32_t fenv_buf[7];\n  fenv_buf[5] = 0;\n  asm volatile(\"finit\\n\"\n               \"fld1\\n\"\n               \"fstenv %0\\n\"\n               : \"=m\"(fenv_buf)\n               :\n               : \"memory\");\n  return !fenv_buf[5];\n#else\n  FATAL_X86_ONLY();\n  return false;\n#endif\n}\n\ntemplate <typename Arch>\nstatic CloneParameters extract_clone_parameters_arch(const Registers& regs) {\n  CloneParameters result;\n  result.stack = regs.arg2();\n  result.ptid = regs.arg3();\n  switch (Arch::clone_parameter_ordering) {\n    case Arch::FlagsStackParentTLSChild:\n      result.tls = regs.arg4();\n      result.ctid = regs.arg5();\n      break;\n    case Arch::FlagsStackParentChildTLS:\n      result.tls = regs.arg5();\n      result.ctid = regs.arg4();\n      break;\n  }\n  int flags = (int)regs.orig_arg1();\n  // If these flags aren't set, the corresponding clone parameters may be\n  // invalid pointers, so make sure they're ignored.\n  if (!(flags & (CLONE_PARENT_SETTID | CLONE_PIDFD))) {\n    result.ptid = nullptr;\n  }\n  if (!(flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID))) {\n    result.ctid = nullptr;\n  }\n  if (!(flags & CLONE_SETTLS)) {\n    result.tls = nullptr;\n  }\n  return result;\n}\n\nCloneParameters extract_clone_parameters(Task* t) {\n  RR_ARCH_FUNCTION(extract_clone_parameters_arch, t->arch(), t->regs());\n}\n\nint read_elf_class(const string& filename) {\n  ScopedFd fd(filename.c_str(), O_RDONLY);\n  if (!fd.is_open()) {\n    return NOT_ELF;\n  }\n  char elf_header[EI_CLASS + 1];\n  static const char magic[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };\n  if (read(fd, elf_header, sizeof(elf_header)) != sizeof(elf_header) ||\n      memcmp(magic, elf_header, sizeof(magic)) != 0) {\n    return NOT_ELF;\n  }\n  return elf_header[EI_CLASS];\n}\n\n// Setting these causes us to trace instructions after\n// instruction_trace_at_event_start up to and including\n// instruction_trace_at_event_last\nstatic FrameTime instruction_trace_at_event_start = 0;\nstatic FrameTime instruction_trace_at_event_last = 0;\n\nbool trace_instructions_up_to_event(FrameTime event) {\n  return event > instruction_trace_at_event_start &&\n         event <= instruction_trace_at_event_last;\n}\n\nvoid dump_task_set(const set<Task*>& tasks) {\n  printf(\"[\");\n  for (auto& t : tasks) {\n    printf(\"%p (pid=%d, rec=%d),\", t, t->tid, t->rec_tid);\n  }\n  printf(\"]\\n\");\n}\n\nvoid dump_task_map(const map<pid_t, Task*>& tasks) {\n  printf(\"[\");\n  for (auto& t : tasks) {\n    printf(\"%p (pid=%d, rec=%d),\", t.second, t.second->tid, t.second->rec_tid);\n  }\n  printf(\"]\\n\");\n}\n\nstring real_path(const string& path) {\n  char buf[PATH_MAX];\n  if (realpath(path.c_str(), buf) == buf) {\n    return string(buf);\n  }\n  return path;\n}\n\nstatic string read_exe_dir() {\n  KernelMapping km =\n      AddressSpace::read_local_kernel_mapping((uint8_t*)&read_exe_dir);\n  string exe_path = km.fsname();\n  int end = exe_path.length();\n  // Chop off the filename\n  while (end > 0 && exe_path[end - 1] != '/') {\n    --end;\n  }\n  exe_path.erase(end);\n  return exe_path;\n}\n\nstring resource_path() {\n  string resource_path = Flags::get().resource_path;\n  if (resource_path.empty()) {\n    static string exe_path = read_exe_dir() + \"../\";\n    return exe_path;\n  }\n  return resource_path;\n}\n\n/**\n * Get the current time from the preferred monotonic clock in units of\n * seconds, relative to an unspecific point in the past.\n */\ndouble monotonic_now_sec() {\n  struct timespec tp;\n  clock_gettime(CLOCK_MONOTONIC, &tp);\n  return (double)tp.tv_sec + (double)tp.tv_nsec / 1e9;\n}\n\nbool running_under_rr(bool cache) {\n  static bool rr_under_rr = false;\n  static bool rr_check_done = false;\n  if (!rr_check_done || !cache) {\n    rr_check_done = true;\n    int ret = syscall(SYS_rrcall_check_presence, (uintptr_t)0, (uintptr_t)0,\n      (uintptr_t)0, (uintptr_t)0, (uintptr_t)0, (uintptr_t)0);\n    if (ret > 0 || (ret < 0 && errno != ENOSYS)) {\n      FATAL() << \"Unexpected result for rrcall_check_presence: \" << ret;\n    }\n    rr_under_rr = ret == 0;\n  }\n  return rr_under_rr;\n}\n\nstring find_helper_library(const char *basepath)\n{\n  string lib_path = resource_path() + \"lib64/rr/\";\n  string file_name = lib_path + basepath;\n  if (access(file_name.c_str(), F_OK) == 0) {\n    return lib_path;\n  }\n  lib_path = resource_path() + \"lib/rr/\";\n  file_name = lib_path + basepath;\n  if (access(file_name.c_str(), F_OK) == 0) {\n    return lib_path;\n  }\n\n  std::string full_libdir = filesystem::path(FULL_LIBDIR).lexically_normal().string();\n  lib_path = full_libdir + \"/rr/\";\n  file_name = lib_path + basepath;\n  if (access(file_name.c_str(), F_OK) == 0) {\n    return lib_path;\n  }\n\n  // File does not exist. Assume install put it in LD_LIBRARY_PATH.\n  lib_path = \"\";\n  return lib_path;\n}\n\nvector<string> read_proc_status_fields(pid_t tid, const char* name,\n                                       const char* name2, const char* name3) {\n  vector<string> result;\n  FILE *f;\n  char buf[1000];\n  if (tid == 0) {\n    f = fopen(\"/proc/self/status\", \"r\");\n  } else {\n    sprintf(buf, \"/proc/%d/status\", tid);\n    f = fopen(buf, \"r\");\n  }\n  if (!f) {\n    return result;\n  }\n  vector<string> matches;\n  matches.push_back(string(name) + \":\");\n  if (name2) {\n    matches.push_back(string(name2) + \":\");\n  }\n  if (name3) {\n    matches.push_back(string(name3) + \":\");\n  }\n  for (auto& m : matches) {\n    while (true) {\n      if (!fgets(buf, sizeof(buf), f)) {\n        break;\n      }\n      if (strncmp(buf, m.c_str(), m.size()) == 0) {\n        char* b = buf + m.size();\n        while (*b == ' ' || *b == '\\t') {\n          ++b;\n        }\n        char* e = b;\n        while (*e && *e != '\\n') {\n          ++e;\n        }\n        result.push_back(string(b, e - b));\n        break;\n      }\n    }\n  }\n  fclose(f);\n  return result;\n}\n\nstatic bool check_for_pax_kernel() {\n  auto results = read_proc_status_fields(getpid(), \"PaX\");\n  return !results.empty();\n}\n\nbool uses_invisible_guard_page() {\n  static bool is_pax_kernel = check_for_pax_kernel();\n  return !is_pax_kernel;\n}\n\nbool read_proc_net_socket_addresses(Task* t, int fd,\n                                    std::array<typename NativeArch::sockaddr_storage, 2> &out) {\n  char buf[1000];\n\n  auto stat = t->stat_fd(fd);\n  ino_t inode = stat.st_ino;\n\n  // Check tcp first.\n  if (FILE* f = fopen(\"/proc/net/tcp\", \"r\")) {\n    // Skip the first line, which contains human-readable column labels.\n    if (!fgets(buf, sizeof(buf) - 1, f)) {\n      LOG(warn) << \"Can't read /proc/net/tcp\";\n    }\n    while (fgets(buf, sizeof(buf) - 1, f)) {\n      // Ignore the first field.\n      strtok(buf, \" \");\n      // Then come the local and remote addresses.\n      char* local_addr_str = strtok(NULL, \" \");\n      char* remote_addr_str = strtok(NULL, \" \");\n      // Then six more fields to ignore.\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      // Finally the inode\n      char* ino = strtok(NULL, \" \");\n      ino_t inod = strtoull(ino, NULL, 10);\n      if (inod != inode) {\n        continue;\n      }\n\n      // We have a match.\n      char* next = NULL;\n      unsigned long laddr = strtoul(local_addr_str, &next, 16);\n      if ((laddr == ULONG_MAX && errno == ERANGE) || *next != ':') {\n        LOG(warn) << \"Local address not in expected format\";\n        break;\n      }\n      ++next;\n      unsigned long lport = strtoul(next, NULL, 16);\n      if (lport > USHRT_MAX) {\n        LOG(warn) << \"Local address not in expected format\";\n        break;\n      }\n      struct sockaddr_in* local_addr_in = (struct sockaddr_in*)&out[0];\n      local_addr_in->sin_family = AF_INET;\n      local_addr_in->sin_addr.s_addr = laddr;\n      local_addr_in->sin_port = lport;\n      unsigned long raddr = strtoul(remote_addr_str, &next, 16);\n      if ((raddr == ULONG_MAX && errno == ERANGE) || *next != ':') {\n        LOG(warn) << \"Remote address not in expected format\";\n        break;\n      }\n      ++next;\n      unsigned long rport = strtoul(next, NULL, 16);\n      if (rport > USHRT_MAX) {\n        LOG(warn) << \"Remote address not in expected format\";\n        break;\n      }\n      struct sockaddr_in* remote_addr_in = (struct sockaddr_in*)&out[1];\n      remote_addr_in->sin_family = AF_INET;\n      remote_addr_in->sin_addr.s_addr = raddr;\n      remote_addr_in->sin_port = rport;\n      fclose(f);\n      return true;\n    }\n    fclose(f);\n  } else {\n    LOG(warn) << \"Can't open /proc/net/tcp\";\n  }\n\n  // Then tcp6\n  if (FILE* f = fopen(\"/proc/net/tcp6\", \"r\")) {\n    // Skip the first line, which contains human-readable column labels.\n    if (!fgets(buf, sizeof(buf) - 1, f)) {\n      LOG(warn) << \"Can't read /proc/net/tcp6\";\n    }\n    while (fgets(buf, sizeof(buf) - 1, f)) {\n      // Ignore the first field.\n      strtok(buf, \" \");\n      // Then come the local and remote addresses.\n      char* local_addr_str = strtok(NULL, \" \");\n      char* remote_addr_str = strtok(NULL, \" \");\n      // Then six more fields to ignore.\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      strtok(NULL, \" \");\n      // Finally the inode\n      char* ino = strtok(NULL, \" \");\n      ino_t inod = strtoull(ino, NULL, 10);\n      if (inod != inode) {\n        continue;\n      }\n\n      // We have a match.\n      struct sockaddr_in6* local_addr_in6 = (struct sockaddr_in6*)&out[0];\n      local_addr_in6->sin6_family = AF_INET6;\n\n      if (strlen(local_addr_str) != 37) {\n        break;\n      }\n      char buf[9];\n      for (int i = 0; i < 4; ++i) {\n        char* c = local_addr_str + i * 8;\n        strncpy(buf, c, 8);\n        buf[8] = '\\0';\n        unsigned long local_addr_component = strtoul(buf, NULL, 16);\n        if ((local_addr_component == ULONG_MAX && errno == ERANGE)) {\n          LOG(warn) << \"Local address not in expected format\";\n          break;\n        }\n        local_addr_in6->sin6_addr.s6_addr32[i] = local_addr_component;\n      }\n      if (*(local_addr_str + 32) != ':') {\n        LOG(warn) << \"Local address not in expected format\";\n        break;\n      }\n      unsigned long lport = strtoul(local_addr_str + 33, NULL, 16);\n      if (lport > USHRT_MAX) {\n        LOG(warn) << \"Local address not in expected format\";\n        break;\n      }\n      local_addr_in6->sin6_port = lport;\n\n      struct sockaddr_in6* remote_addr_in6 = (struct sockaddr_in6*)&out[1];\n      remote_addr_in6->sin6_family = AF_INET6;\n\n      if (strlen(remote_addr_str) != 37) {\n        break;\n      }\n      for (int i = 0; i < 4; ++i) {\n        char* c = remote_addr_str + 24 - i * 8;\n        strncpy(buf, c, 8);\n        buf[8] = '\\0';\n        unsigned long remote_addr_component = strtoul(buf, NULL, 16);\n        if ((remote_addr_component == ULONG_MAX && errno == ERANGE)) {\n          LOG(warn) << \"Remote address not in expected format\";\n          break;\n        }\n        remote_addr_in6->sin6_addr.s6_addr32[i] = remote_addr_component;\n      }\n      if (*(remote_addr_str + 32) != ':') {\n        LOG(warn) << \"Remote address not in expected format\";\n        break;\n      }\n      unsigned long rport = strtoul(remote_addr_str + 33, NULL, 16);\n      if (rport > USHRT_MAX) {\n        LOG(warn) << \"Remote address not in expected format\";\n        break;\n      }\n      remote_addr_in6->sin6_port = rport;\n      fclose(f);\n      return true;\n    }\n    fclose(f);\n  } else {\n    LOG(warn) << \"Can't open /proc/net/tcp6\";\n  }\n\n  return false;\n}\n\nstatic bool try_copy_file_by_copy_all(int dest_fd, int src_fd)\n{\n  static bool should_try_copy_all = true;\n  if (!should_try_copy_all) {\n    return false;\n  }\n  struct stat src_stat;\n  if (0 != fstat(src_fd, &src_stat)) {\n    return false;\n  }\n  size_t remaining_size = src_stat.st_size;\n  while (remaining_size > 0) {\n    ssize_t ncopied = syscall(NativeArch::copy_file_range, src_fd, NULL,\n                              dest_fd, NULL, remaining_size, 0);\n    if (ncopied == -1) {\n      if (errno == ENOSYS) {\n        should_try_copy_all = false;\n      }\n      return false;\n    }\n    if (ncopied == 0) {\n      // This doesn't necessarily mean EOF - some file systems don't like this\n      // system call.\n      return false;\n    }\n    remaining_size -= ncopied;\n  }\n  return true;\n}\n\nbool copy_file(int dest_fd, int src_fd) {\n  char buf[32 * 1024];\n  if (try_copy_file_by_copy_all(dest_fd, src_fd)) {\n    return true;\n  }\n  while (1) {\n    ssize_t bytes_read = read(src_fd, buf, sizeof(buf));\n    if (bytes_read < 0) {\n      return false;\n    }\n    if (!bytes_read) {\n      break;\n    }\n    write_all(dest_fd, buf, bytes_read);\n  }\n  return true;\n}\n\nbool has_effective_caps(uint64_t caps) {\n  struct NativeArch::cap_header header = {.version =\n                                              _LINUX_CAPABILITY_VERSION_3,\n                                          .pid = 0 };\n  struct NativeArch::cap_data data[_LINUX_CAPABILITY_U32S_3];\n  if (syscall(NativeArch::capget, &header, data) != 0) {\n    FATAL() << \"FAILED to read capabilities\";\n  }\n  for (int i = 0; i < _LINUX_CAPABILITY_U32S_3; ++i) {\n    if ((data[i].effective & (uint32_t)caps) != (uint32_t)caps) {\n      return false;\n    }\n    caps >>= 32;\n  }\n  return true;\n}\n\nconst XSaveLayout& xsave_native_layout() {\n  static XSaveLayout layout =\n      xsave_layout_from_trace(gather_cpuid_records(CPUID_GETXSAVE));\n  return layout;\n}\n\nXSaveLayout xsave_layout_from_trace(const std::vector<CPUIDRecord> records) {\n  XSaveLayout layout;\n\n  size_t record_index;\n  for (record_index = 0; record_index < records.size(); ++record_index) {\n    if (records[record_index].eax_in == CPUID_GETXSAVE) {\n      break;\n    }\n  }\n  if (record_index >= records.size()) {\n    // XSAVE not present\n    layout.full_size = 512;\n    // x87/XMM always supported\n    layout.supported_feature_bits = 0x3;\n    return layout;\n  }\n\n  CPUIDRecord cpuid_data = records[record_index];\n  DEBUG_ASSERT(cpuid_data.ecx_in == 0);\n  layout.full_size = cpuid_data.out.ebx;\n  layout.supported_feature_bits =\n      cpuid_data.out.eax | (uint64_t(cpuid_data.out.edx) << 32);\n\n  for (size_t i = 2; i < 64; ++i) {\n    if (layout.supported_feature_bits & (uint64_t(1) << i)) {\n      do {\n        ++record_index;\n        if (record_index >= records.size() ||\n            records[record_index].eax_in != CPUID_GETXSAVE) {\n          FATAL() << \"Missing CPUID record for feature \" << i;\n        }\n      } while (records[record_index].ecx_in != i);\n      cpuid_data = records[record_index];\n      while (layout.feature_layouts.size() < i) {\n        layout.feature_layouts.push_back({ 0, 0 });\n      }\n      layout.feature_layouts.push_back(\n          { cpuid_data.out.ebx, cpuid_data.out.eax });\n    }\n  }\n  return layout;\n}\n\nstatic const char localhost_addr[] = \"127.0.0.1\";\nstatic const char localhost_addr_ipv6[] = \"::1\";\n\n// `addr` must be the right size for for the given domain\nstatic bool get_address(int domain, const string& host, struct sockaddr* addr) {\n  struct addrinfo hints;\n  memset(&hints, 0, sizeof(hints));\n  hints.ai_family = domain;\n  hints.ai_socktype = SOCK_STREAM;\n  hints.ai_flags = AI_PASSIVE;\n\n  struct addrinfo* ret;\n  if (getaddrinfo(host.c_str(), nullptr, &hints, &ret) != 0) {\n    return false;\n  }\n  memcpy(addr, ret->ai_addr, ret->ai_addrlen);\n  freeaddrinfo(ret);\n  return true;\n}\n\nOpenedSocket open_socket(const string& host, unsigned short port,\n                         ProbePort probe) {\n  string host4 = host;\n  string host6 = host;\n  if (host.empty()) {\n    host4 = localhost_addr;\n    host6 = localhost_addr_ipv6;\n  }\n\n  struct sockaddr_in addr4;\n  bool ipv4_ok = get_address(AF_INET, host4, (struct sockaddr*)&addr4);\n  struct sockaddr_in6 addr6;\n  bool ipv6_ok = get_address(AF_INET6, host6, (struct sockaddr*)&addr6);\n\n  int domain = -1;\n  ScopedFd listen_fd;\n  if (ipv4_ok) {\n    listen_fd = ScopedFd(socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0));\n    if (listen_fd.is_open()) {\n      domain = AF_INET;\n    }\n  }\n  if (!listen_fd.is_open() && ipv6_ok) {\n    listen_fd = ScopedFd(socket(AF_INET6, SOCK_STREAM | SOCK_CLOEXEC, 0));\n    if (listen_fd.is_open()) {\n      domain = AF_INET6;\n    }\n  }\n  if (!listen_fd.is_open()) {\n    FATAL() << \"Couldn't create socket\";\n  }\n\n  int reuseaddr = 1;\n  int ret = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &reuseaddr,\n                       sizeof(reuseaddr));\n  if (ret < 0) {\n    FATAL() << \"Couldn't set SO_REUSEADDR\";\n  }\n\n  struct sockaddr* addr;\n  size_t addr_size;\n  in_port_t* addr_port;\n  string* host_out;\n  if (domain == AF_INET) {\n    addr = (struct sockaddr*)&addr4;\n    addr_size = sizeof(addr4);\n    addr_port = &addr4.sin_port;\n    addr4.sin_family = AF_INET;\n    host_out = &host4;\n  } else {\n    addr = (struct sockaddr*)&addr6;\n    addr_size = sizeof(addr6);\n    addr_port = &addr6.sin6_port;\n    addr6.sin6_family = AF_INET6;\n    host_out = &host6;\n  }\n\n  do {\n    *addr_port = htons(port);\n    ret = ::bind(listen_fd, addr, addr_size);\n    if (ret && probe == PROBE_PORT && (EADDRINUSE == errno || EACCES == errno || EINVAL == errno)) {\n      port = 0;\n      continue;\n    }\n    if (ret) {\n      CLEAN_FATAL() << \"Couldn't bind to port \" << port;\n    }\n\n    ret = listen(listen_fd, 1 /*backlogged connection*/);\n    if (ret && probe == PROBE_PORT && EADDRINUSE == errno) {\n      port = 0;\n      continue;\n    }\n    if (ret) {\n      FATAL() << \"Couldn't listen on port \" << port;\n    }\n    if (port == 0) {\n      socklen_t sa_size = addr_size;\n      ret = getsockname(listen_fd, addr, &sa_size);\n      if (ret) {\n        FATAL() << \"Could not get socket port\";\n      }\n\n      port = ntohs(*addr_port);\n    }\n    break;\n  } while (probe == PROBE_PORT);\n\n  OpenedSocket result;\n  result.fd = std::move(listen_fd);\n  result.domain = domain;\n  result.host = *host_out;\n  result.port = port;\n  return result;\n}\n\nvoid notifying_abort() {\n  char* test_monitor_pid = getenv(\"RUNNING_UNDER_TEST_MONITOR\");\n  if (test_monitor_pid) {\n    pid_t pid = atoi(test_monitor_pid);\n    // Tell test-monitor to wake up and take a snapshot, and wait for it to\n    // do so.\n    kill(pid, SIGURG);\n    sleep(10000);\n  }\n\n  abort();\n}\n\nvoid dump_rr_stack(ScopedFd& fd) {\n  static const char msg[] = \"=== Start rr backtrace:\\n\";\n  write_all(fd, msg, sizeof(msg) - 1);\n#ifdef EXECINFO_BACKTRACE\n  void* buffer[1024];\n  int count = backtrace(buffer, 1024);\n  backtrace_symbols_fd(buffer, count, fd);\n#else\n  static const char msg_fallback[] = \"<rr backtraces not available on this system>\\n\";\n  write_all(fd, msg_fallback, sizeof(msg_fallback) - 1);\n#endif\n  static const char msg2[] = \"=== End rr backtrace\\n\";\n  write_all(fd, msg2, sizeof(msg2) - 1);\n}\n\nvoid check_for_leaks() {\n  if (running_under_rr()) {\n    // Don't do leak checking. The outer rr may have injected maps into our\n    // address space that look like leaks to us.\n    return;\n  }\n  for (KernelMapIterator it(getpid()); !it.at_end(); ++it) {\n    auto km = it.current();\n    if (km.fsname().find(Session::rr_mapping_prefix()) == 0) {\n      FATAL() << \"Leaked \" << km;\n    }\n  }\n}\n\nvoid ensure_dir(const string& dir, const char* dir_type, mode_t mode) {\n  if (dir.empty()) {\n    FATAL() << \"Empty directory name!\";\n  }\n  size_t last_dir_component = dir.find_last_not_of('/');\n  const string d = last_dir_component == string::npos\n    ? \"/\" : dir.substr(0, last_dir_component + 1);\n  struct stat st;\n  if (0 > stat(d.c_str(), &st)) {\n    if (errno != ENOENT) {\n      FATAL() << \"Error accessing \" << dir_type << \" \" << dir << \"'\";\n    }\n\n    size_t last_slash = d.find_last_of('/');\n    if (last_slash != string::npos) {\n      ensure_dir(d.substr(0, max(last_slash, (size_t)1)), dir_type, mode);\n    }\n\n    // Allow for a race condition where someone else creates the directory\n    if (0 > mkdir(d.c_str(), mode) && errno != EEXIST) {\n      FATAL() << \"Can't create \" << dir_type << \" `\" << dir << \"'\";\n    }\n    if (0 > stat(d.c_str(), &st)) {\n      FATAL() << \"Can't stat \" << dir_type << \" `\" << dir << \"'\";\n    }\n    return;\n  }\n\n  if (!(S_IFDIR & st.st_mode)) {\n    FATAL() << \"`\" << dir << \"' exists but isn't a directory.\";\n  }\n  if (access(d.c_str(), W_OK)) {\n    FATAL() << \"Can't write to \" << dir_type << \" `\" << dir << \"'.\";\n  }\n}\n\nconst char* tmp_dir() {\n  const char* dir = getenv(\"RR_TMPDIR\");\n  if (dir) {\n    ensure_dir(string(dir), \"temporary file directory (RR_TMPDIR)\", S_IRWXU);\n    return dir;\n  }\n  dir = getenv(\"TMPDIR\");\n  if (dir) {\n    ensure_dir(string(dir), \"temporary file directory (TMPDIR)\", S_IRWXU);\n    return dir;\n  }\n  // NB: We can't use P_tmpdir here because bionic also defines it to /tmp\n  // (which is not world-writable).\n  const char* DEFAULT_TMP_DIR =\n#ifdef __BIONIC__\n    \"/data/local/tmp\"\n#else\n    \"/tmp\"\n#endif\n    ;\n  // Don't try to create \"/tmp\", that probably won't work well.\n  if (access(DEFAULT_TMP_DIR, W_OK)) {\n    FATAL() << \"Can't write to temporary file directory \" << DEFAULT_TMP_DIR << \".\";\n  }\n  return DEFAULT_TMP_DIR;\n}\n\nTempFile create_temporary_file(const char* pattern) {\n  char buf[PATH_MAX];\n  snprintf(buf, sizeof(buf) - 1, \"%s/%s\", tmp_dir(), pattern);\n  buf[sizeof(buf) - 1] = 0;\n  TempFile result;\n  result.fd = ScopedFd(mkstemp(buf));\n  result.name = buf;\n  return result;\n}\n\nScopedFd open_memory_file(const std::string &name) {\n  ScopedFd fd(syscall(SYS_memfd_create, name.c_str(), 0));\n  return fd;\n}\n\nvoid good_random(void* out, size_t out_len) {\n  ScopedFd fd(\"/dev/urandom\", O_RDONLY);\n  uint8_t* o = static_cast<uint8_t*>(out);\n  if (fd.is_open()) {\n    while (out_len > 0) {\n      ssize_t ret = read(fd, o, out_len);\n      if (ret <= 0) {\n        break;\n      }\n      o += ret;\n      out_len -= ret;\n    }\n  }\n  for (size_t i = 0; i < out_len; ++i) {\n    o[i] = random();\n  }\n}\n\nvector<string> current_env() {\n  vector<string> env;\n  char** envp = environ;\n  for (; *envp; ++envp) {\n    env.push_back(*envp);\n  }\n  return env;\n}\n\nconst uint8_t rdtsc_insn[2] = { 0x0f, 0x31 };\n\nstatic const uint8_t rdtscp_insn[] = { 0x0f, 0x01, 0xf9 };\nstatic const uint8_t cpuid_insn[] = { 0x0f, 0xa2 };\nstatic const uint8_t int3_insn[] = { 0xcc };\nstatic const uint8_t pushf_insn[] = { 0x9c };\nstatic const uint8_t pushf16_insn[] = { 0x66, 0x9c };\n\n// XXX this probably needs to be extended to decode ignored prefixes\nSpecialInst special_instruction_at(Task* t, remote_code_ptr ip) {\n  if (is_x86ish(t->arch())) {\n    uint8_t insn[sizeof(rdtscp_insn)];\n    ssize_t ret =\n        t->read_bytes_fallible(ip.to_data_ptr<uint8_t>(), sizeof(insn), insn);\n    if (ret < 0) {\n      return {SpecialInstOpcode::NONE};\n    }\n    size_t len = ret;\n    if (len >= sizeof(rdtsc_insn) &&\n        !memcmp(insn, rdtsc_insn, sizeof(rdtsc_insn))) {\n      return {SpecialInstOpcode::X86_RDTSC};\n    }\n    if (len >= sizeof(rdtscp_insn) &&\n        !memcmp(insn, rdtscp_insn, sizeof(rdtscp_insn))) {\n      return {SpecialInstOpcode::X86_RDTSCP};\n    }\n    if (len >= sizeof(cpuid_insn) &&\n        !memcmp(insn, cpuid_insn, sizeof(cpuid_insn))) {\n      return {SpecialInstOpcode::X86_CPUID};\n    }\n    if (len >= sizeof(int3_insn) &&\n        !memcmp(insn, int3_insn, sizeof(int3_insn))) {\n      return {SpecialInstOpcode::X86_INT3};\n    }\n    if (len >= sizeof(pushf_insn) &&\n        !memcmp(insn, pushf_insn, sizeof(pushf_insn))) {\n      return {SpecialInstOpcode::X86_PUSHF};\n    }\n    if (len >= sizeof(pushf16_insn) &&\n        !memcmp(insn, pushf16_insn, sizeof(pushf16_insn))) {\n      return {SpecialInstOpcode::X86_PUSHF16};\n    }\n  } else if (t->arch() == aarch64) {\n    uint8_t insn[4];\n    ssize_t ret =\n        t->read_bytes_fallible(ip.to_data_ptr<uint8_t>(), sizeof(insn), insn);\n    if (ret < 0) {\n      return {SpecialInstOpcode::NONE};\n    }\n    uint32_t insn_word =\n        insn[0] | (insn[1] << 8) | (insn[2] << 16) | (insn[3] << 24);\n    if ((insn_word & 0xffffffe0) == 0xd53be000) {\n      return {SpecialInstOpcode::ARM_MRS_CNTFRQ_EL0, insn_word & 31};\n    }\n    if ((insn_word & 0xffffffe0) == 0xd53be040) {\n      return {SpecialInstOpcode::ARM_MRS_CNTVCT_EL0, insn_word & 31};\n    }\n    if ((insn_word & 0xffffffe0) == 0xd53be0c0) {\n      return {SpecialInstOpcode::ARM_MRS_CNTVCTSS_EL0, insn_word & 31};\n    }\n  }\n  return {SpecialInstOpcode::NONE};\n}\n\nsize_t special_instruction_len(SpecialInstOpcode insn) {\n  if (insn == SpecialInstOpcode::X86_RDTSC) {\n    return sizeof(rdtsc_insn);\n  } else if (insn == SpecialInstOpcode::X86_RDTSCP) {\n    return sizeof(rdtscp_insn);\n  } else if (insn == SpecialInstOpcode::X86_CPUID) {\n    return sizeof(cpuid_insn);\n  } else if (insn == SpecialInstOpcode::X86_INT3) {\n    return sizeof(int3_insn);\n  } else if (insn == SpecialInstOpcode::X86_PUSHF) {\n    return sizeof(pushf_insn);\n  } else if (insn == SpecialInstOpcode::X86_PUSHF16) {\n    return sizeof(pushf16_insn);\n  } else if (insn == SpecialInstOpcode::ARM_MRS_CNTFRQ_EL0 ||\n             insn == SpecialInstOpcode::ARM_MRS_CNTVCT_EL0 ||\n             insn == SpecialInstOpcode::ARM_MRS_CNTVCTSS_EL0) {\n    return 4;\n  } else {\n    return 0;\n  }\n}\n\n/**\n * Certain instructions generate deterministic signals but also advance pc.\n * Look *backwards* and see if this was one of them.\n */\nbool is_advanced_pc_and_signaled_instruction(Task* t, remote_code_ptr ip) {\n#if defined(__i386__) || defined(__x86_64__)\n  uint8_t insn[sizeof(int3_insn)];\n  ssize_t ret =\n      t->read_bytes_fallible(ip.to_data_ptr<uint8_t>() - sizeof(insn), sizeof(insn), insn);\n  if (ret < 0) {\n    return false;\n  }\n  size_t len = ret;\n  if (len >= sizeof(int3_insn) &&\n      !memcmp(insn, int3_insn, sizeof(int3_insn))) {\n    return true;\n  }\n#else\n  UNUSED(t);\n  UNUSED(ip);\n#endif\n  return false;\n}\n\nstring get_cpu_lock_file() {\n  const char* lock_file = getenv(\"_RR_CPU_LOCK_FILE\");\n  return lock_file ? lock_file : trace_save_dir() + \"/cpu_lock\";\n}\n\n// Restrict `cpus` to those that are P-cores, if any are P-cores\nstatic void filter_for_perf_cores(vector<int>& cpus) {\n  const vector<CPUGroup>& groups = CPUs::get().cpu_groups();\n  unordered_set<int> p_cores;\n  for (const auto& group : groups) {\n    if (group.kind == CPUGroup::P_CORE) {\n      for (int cpu = group.start_cpu; cpu < group.end_cpu; ++cpu) {\n        p_cores.insert(cpu);\n      }\n    }\n  }\n  if (p_cores.empty()) {\n    return;\n  }\n\n  vector<int> result;\n  for (int cpu : cpus) {\n    if (p_cores.find(cpu) != p_cores.end()) {\n      result.push_back(cpu);\n    }\n  }\n  if (!result.empty()) {\n    cpus = result;\n  }\n}\n\n/**\n * Pick a CPU at random to bind to, unless --cpu-unbound has been given,\n * in which case we return -1.\n */\nint choose_cpu(BindCPU bind_cpu, ScopedFd &cpu_lock_fd_out) {\n  if (bind_cpu.mode == BindCPU::UNBOUND) {\n    return -1;\n  }\n\n  // When many copies of rr are running on the same machine, it's easy for them\n  // to oversubscribe a CPU. To avoid this situation, we have a lock file, where\n  // each running rr process will lock the n-th byte if it is running on that\n  // particular CPU. That way subsequent rr processes can avoid in-use cores\n  // if possible.\n  string cpu_lock_file = get_cpu_lock_file();\n  cpu_lock_fd_out = ScopedFd(cpu_lock_file.c_str(), O_CREAT | O_WRONLY | O_CLOEXEC, 0600);\n\n  // Make sure the locks file is big enough\n  if (cpu_lock_fd_out.is_open()) {\n    struct stat stat;\n    int err = fstat(cpu_lock_fd_out, &stat);\n    DEBUG_ASSERT(err == 0);\n    int configured_cpus = (int)sysconf(_SC_NPROCESSORS_CONF);\n    if (stat.st_size < configured_cpus) {\n      if (ftruncate(cpu_lock_fd_out, configured_cpus)) {\n        FATAL() << \"Failed to resize locks file\";\n      }\n    }\n  }\n\n  // Pin tracee tasks to a random logical CPU, both in\n  // recording and replay.  Tracees can see which HW\n  // thread they're running on by asking CPUID, and we\n  // don't have a way to emulate it yet.  So if a tracee\n  // happens to be scheduled on a different core in\n  // recording than replay, it can diverge.  (And\n  // indeed, has been observed to diverge in practice,\n  // in glibc.)\n  //\n  // Note that we will pin both the tracee processes *and*\n  // the tracer process.  This ends up being a tidy\n  // performance win in certain circumstances,\n  // presumably due to cheaper context switching and/or\n  // better interaction with CPU frequency scaling.\n  if (bind_cpu.mode == BindCPU::SPECIFIED_CORE) {\n    if (cpu_lock_fd_out.is_open()) {\n      struct flock lock {\n        .l_type = F_WRLCK,\n        .l_whence = SEEK_SET,\n        .l_start = bind_cpu.specified_core,\n        .l_len = 1,\n        .l_pid = 0\n      };\n      // Try to acquire the lock for this CPU\n      (void)fcntl(cpu_lock_fd_out, F_SETLK, &lock);\n      // Ignore fcntl errors - nothing we can do\n    }\n    return bind_cpu.specified_core;\n  }\n\n  vector<int> cpus = CPUs::get().initial_affinity();\n  if (cpus.empty()) {\n    FATAL() << \"Can't find a valid CPU to run on\";\n  }\n\n  if (bind_cpu.mode == BindCPU::PREFER_PERF_CORE) {\n    filter_for_perf_cores(cpus);\n  }\n\n  if (cpu_lock_fd_out.is_open()) {\n    // Try twice to allocate a CPU. If we fail twice, pick a random one\n    for (int i = 0; i < 2; ++i) {\n      shuffle(cpus.begin(), cpus.end(), default_random_engine(random()));\n      for (int cpu : cpus) {\n        struct flock lock {\n          .l_type = F_WRLCK,\n          .l_whence = SEEK_SET,\n          .l_start = cpu,\n          .l_len = 1,\n          .l_pid = 0\n        };\n        // Try to acquire the lock for this CPU\n        int err = fcntl(cpu_lock_fd_out, F_SETLK, &lock);\n        if (err == 0) {\n          return cpu;\n        }\n        else if (err == -1) {\n          if (errno != EACCES && errno != EAGAIN) {\n            FATAL() << \"Unexpected error trying to acquire CPU lock\";\n          }\n        }\n      }\n    }\n  }\n\n  // Didn't work - just use a random CPU\n  cpu_lock_fd_out.close();\n  return cpus[random() % cpus.size()];\n}\n\nuint32_t update_crc32(uint32_t crc, unsigned char* buf, size_t len) {\n  static const uint32_t crc32_table[256] = {\n    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,\n    0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,\n    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,\n    0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,\n    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,\n    0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,\n    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,\n    0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,\n    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,\n    0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,\n    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,\n    0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,\n    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,\n    0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,\n    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,\n    0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,\n    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,\n    0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,\n    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,\n    0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,\n    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,\n    0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,\n    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,\n    0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,\n    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,\n    0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,\n    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,\n    0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,\n    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,\n    0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,\n    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,\n    0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,\n    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,\n    0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,\n    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,\n    0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,\n    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,\n    0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,\n    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,\n    0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,\n    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,\n    0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,\n    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d\n  };\n\n  for (unsigned char* end = buf + len; buf < end; ++buf) {\n    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);\n  }\n  return crc;\n}\n\nvoid write_all(int fd, const void* buf, size_t size) {\n  while (size > 0) {\n    ssize_t ret = ::write(fd, buf, size);\n    if (ret <= 0) {\n      FATAL() << \"Can't write \" << size << \" bytes\";\n    }\n    buf = static_cast<const char*>(buf) + ret;\n    size -= ret;\n  }\n}\n\nssize_t pwrite_all_fallible(int fd, const void* buf, size_t size, off_t offset) {\n  ssize_t written = 0;\n  while (size > 0) {\n    ssize_t ret = ::pwrite64(fd, buf, size, offset);\n    if (ret <= 0) {\n      if (written > 0) {\n        return written;\n      }\n      return ret;\n    }\n    buf = static_cast<const char*>(buf) + ret;\n    written += ret;\n    offset += ret;\n    size -= ret;\n  }\n  return written;\n}\n\nbool is_directory(const char* path) {\n  struct stat buf;\n  if (stat(path, &buf) < 0) {\n    return false;\n  }\n  return (buf.st_mode & S_IFDIR) != 0;\n}\n\nconst char* filename(const char* path) {\n  const char* dir = strrchr(path, '/');\n  return dir ? ++dir : path;\n}\n\nbool is_trace(const string& trace) {\n  string ver = trace + \"/version\";\n  string inc = trace + \"/incomplete\";\n  return access(ver.c_str(), F_OK) == 0 || access(inc.c_str(), F_OK) == 0;\n}\n\nbool is_latest_trace(const string& trace) {\n  string latest = latest_trace_symlink();\n  if (access(latest.c_str(), F_OK) != 0) {\n    return false;\n  }\n  latest = real_path(latest);\n  return latest == trace; \n}\n\nbool remove_latest_trace_symlink() {\n  const string latest = latest_trace_symlink();\n  int ret = remove(latest.c_str());\n  if (ret) {\n    perror(latest.c_str());\n    fprintf(stderr,\n            \"\\n\"\n            \"rr: Failed to remove latest_trace symlink: error code %d\\n\"\n            \"\\n\",\n            ret);\n    return false;\n  }\n  return true;\n}\n\nstatic bool ends_with(std::string_view str, std::string_view suffix) {\n  return str.size() >= suffix.size() && str.compare(str.size()-suffix.size(), suffix.size(), suffix) == 0;\n}\n\nbool is_valid_trace_name(const string& entry, std::string* reason) {\n  // filename corresponds to dirname\n  const string name = filename(entry.c_str());\n\n  if (name.empty()) {\n    if (reason) {\n      *reason = \"Empty\";\n    }\n    return false;\n  }\n  if (name[0] == '.' || name[0] == '#') {\n    if (reason) {\n      *reason = \"Cannot start with . or #\";\n    }\n    return false;\n  }\n  if (name[name.length() - 1] == '~') {\n    if (reason) {\n      *reason = \"Cannot end with ~\";\n    }\n    return false;\n  }\n  if (name == \"cpu_lock\" || name == \"src\" || ends_with(name, \".xml\")) {\n    if (reason) {\n      *reason = \"Name \" + name + \" is reserved\";\n    }\n    return false;\n  }\n\n  return true;\n}\n\nssize_t read_to_end(const ScopedFd& fd, size_t offset, void* buf, size_t size) {\n  ssize_t ret = 0;\n  while (size) {\n    ssize_t r = pread(fd.get(), buf, size, offset);\n    if (r < 0) {\n      return -1;\n    }\n    if (r == 0) {\n      return ret;\n    }\n    offset += r;\n    ret += r;\n    size -= r;\n    buf = static_cast<uint8_t*>(buf) + r;\n  }\n  return ret;\n}\n\nstatic struct rlimit raise_resource_limit(int resource, rlim_t max_value) {\n  struct rlimit initial;\n\n  if (getrlimit(resource, &initial) < 0) {\n    FATAL() << \"Can't get rlimit \" << rlimit_resource_name(resource);\n  }\n\n  struct rlimit new_limit = initial;\n  new_limit.rlim_cur = max<rlim_t>(new_limit.rlim_cur, max_value);\n  if (new_limit.rlim_max != RLIM_INFINITY) {\n    new_limit.rlim_cur = min<rlim_t>(new_limit.rlim_cur, new_limit.rlim_max);\n  }\n  if (new_limit.rlim_cur != initial.rlim_cur) {\n    if (setrlimit(resource, &new_limit) < 0) {\n      LOG(warn) << \"Failed to raise rlimit \" << rlimit_resource_name(resource)\n          << \" to \" << new_limit.rlim_cur;\n    }\n  }\n\n  return initial;\n}\n\nstatic void restore_resource_limit(int resource, const struct rlimit& old_limit) {\n  if (setrlimit(resource, &old_limit) < 0) {\n    LOG(warn) << \"Failed to reset rlimit \" << rlimit_resource_name(resource);\n  }\n}\n\nstatic const int MAX_TRACEE_TASKS = 65536;\nstatic struct rlimit initial_fd_limit;\nstatic struct rlimit initial_memlock_limit;\n\nvoid raise_resource_limits() {\n  // We need up to 7 perf event counters per tracee task\n  initial_fd_limit = raise_resource_limit(RLIMIT_NOFILE, 1024 + 7 * MAX_TRACEE_TASKS);\n  // We may need one page of locked memory per tracee task\n  initial_memlock_limit = raise_resource_limit(RLIMIT_MEMLOCK, page_size() * 1 * MAX_TRACEE_TASKS);\n}\n\nvoid restore_initial_resource_limits() {\n  restore_resource_limit(RLIMIT_NOFILE, initial_fd_limit);\n  restore_resource_limit(RLIMIT_MEMLOCK, initial_memlock_limit);\n}\n\ntemplate <typename Arch> static size_t word_size_arch() {\n  return sizeof(typename Arch::signed_long);\n}\n\nsize_t word_size(SupportedArch arch) {\n  RR_ARCH_FUNCTION(word_size_arch, arch);\n}\n\nstring json_escape(const string& str, size_t pos) {\n  string out;\n  for (size_t i = pos; i < str.size(); ++i) {\n    unsigned char c = str[i];\n    if (c < 32) {\n      char buf[8];\n      sprintf(buf, \"\\\\u%04x\", c);\n      out += buf;\n    } else if (c == '\\\\') {\n      out += \"\\\\\\\\\";\n    } else if (c == '\\\"') {\n      out += \"\\\\\\\"\";\n    } else {\n      out += c;\n    }\n  }\n  return out;\n}\n\nvoid sleep_time(double t) {\n  struct timespec ts;\n  ts.tv_sec = (time_t)floor(t);\n  ts.tv_nsec = (long)((t - ts.tv_sec) * 1e9);\n  nanosleep(&ts, NULL);\n}\n\nstatic bool is_component(const char* p, const char* component) {\n  while (*component) {\n    if (*p != *component) {\n      return false;\n    }\n    ++p;\n    ++component;\n  }\n  return *p == '/' || !*p;\n}\n\nvoid normalize_file_name(string& s)\n{\n  size_t s_len = s.size();\n  size_t out = 0;\n  for (size_t i = 0; i < s_len; ++i) {\n    if (s[i] == '/') {\n      if (s.c_str()[i + 1] == '/') {\n        // Skip redundant '/'\n        continue;\n      }\n      if (is_component(s.c_str() + i + 1, \".\")) {\n        // Skip redundant '/.'\n        ++i;\n        continue;\n      }\n      if (is_component(s.c_str() + i + 1, \"..\")) {\n        // Peel off '/..'\n        if (out == 0) {\n          // If there's nothing to peel off, just discard this.\n          i += 2;\n          continue;\n        }\n        size_t p = s.rfind('/', out - 1);\n        if (p != string::npos) {\n          out = p;\n          i += 2;\n          continue;\n        }\n      }\n    }\n    s[out] = s[i];\n    ++out;\n  }\n  s.resize(out);\n}\n\nstd::vector<int> read_all_proc_fds(pid_t tid)\n{\n  std::vector<int> ret;\n  char buf[1000];\n  sprintf(buf, \"/proc/%d/fd\", tid);\n  DIR *fddir = opendir(buf);\n  DEBUG_ASSERT(fddir != nullptr);\n  while (struct dirent *dir = readdir(fddir)) {\n    ret.push_back(atoi(dir->d_name));\n  }\n  closedir(fddir);\n  return ret;\n}\n\nstd::string find_exec_stub(SupportedArch arch) {\n  string exe_path = resource_path() + \"bin/\";\n  if (arch == x86 && NativeArch::arch() == x86_64) {\n    exe_path += \"rr_exec_stub_32\";\n  } else {\n    exe_path += \"rr_exec_stub\";\n  }\n  return exe_path;\n}\n\nint pop_count(uint64_t v) {\n  int ret = 0;\n  while (v > 0) {\n    if (v & 1) {\n      ++ret;\n    }\n    v >>= 1;\n  }\n  return ret;\n}\n\nvoid SAFE_FATAL(int err, const char *msg)\n{\n  static char prefix[] = \"FATAL (errno = \";\n  const char *errstr = errno_name_cstr(err);\n  char buf[100];\n  if (errstr == NULL) {\n    snprintf(buf, sizeof(buf), \"errno(%d)\", err);\n    errstr = buf;\n  }\n  static char bridge[] = \"): \";\n  static char nl[] = \"\\n\";\n  struct iovec out[5] = {\n    {.iov_base = prefix, .iov_len=sizeof(prefix)},\n    {.iov_base = (char*)errstr, .iov_len=strlen(errstr)},\n    {.iov_base = bridge, .iov_len=sizeof(errstr)},\n    {.iov_base = (char*)msg, .iov_len=strlen(msg)},\n    {.iov_base = nl, .iov_len=sizeof(nl)}\n  };\n  __attribute__((unused)) ssize_t ret = ::writev(STDERR_FILENO, out, sizeof(out)/sizeof(struct iovec));\n  abort();\n}\n\nstatic int child_SIGSEGV(__attribute__((unused)) void* arg) {\n  kill(getpid(), SIGSEGV);\n  return 0;\n}\n\n#ifdef __SANITIZE_ADDRESS__\n#include <sanitizer/lsan_interface.h>\nstatic int rr_lsan_is_turned_off;\nint __lsan_is_turned_off(void)\n{\n  return rr_lsan_is_turned_off;\n}\n#endif\n\nbool coredumping_signal_takes_down_entire_vm() {\n  // The kernel behavior here changed in 5.16. Prior to that,\n  // a coredumping signal would bring down the entire vm.\n  // Starting with 5.16 it only brings down the thread group.\n  // -1 here indicates uninitialized, 0 the new behavior, and\n  // 1 the old behavior.\n  static int coredumping_signal_vm_behavior = -1;\n  if (coredumping_signal_vm_behavior < 0) {\n    pid_t child;\n    LOG(debug) << \"Testing coredumping behavior in the presence of CLONE_VM\";\n    if ((child = fork()) == 0) {\n      // Remove any handlers and make sure we get the default signal behavior.\n      signal(SIGSEGV, SIG_DFL);\n      // Don't litter the system with core dumps.\n      prctl(PR_SET_DUMPABLE, 0);\n#ifdef __SANITIZE_ADDRESS__\n      rr_lsan_is_turned_off = 1;\n#endif\n      // Allocate a stack for the child.\n      const size_t stack_size = 1 << 20;\n      void* stack = mmap(NULL, stack_size, PROT_READ | PROT_WRITE,\n                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);\n\n      pid_t tid = clone(child_SIGSEGV, (void*)((uintptr_t)stack + stack_size),\n                      CLONE_VM, NULL, NULL, NULL, NULL);\n      DEBUG_ASSERT(tid > 0);\n\n      WaitResult result = WaitManager::wait_exit(WaitOptions(tid));\n      DEBUG_ASSERT(result.code == WAIT_OK);\n      DEBUG_ASSERT(result.status.type() == WaitStatus::FATAL_SIGNAL);\n      exit(0);\n    }\n\n    DEBUG_ASSERT(child > 0);\n    WaitResult result = WaitManager::wait_exit(WaitOptions(child));\n    DEBUG_ASSERT(result.code == WAIT_OK);\n    coredumping_signal_vm_behavior = result.status.type() == WaitStatus::FATAL_SIGNAL;\n  }\n\n  return coredumping_signal_vm_behavior > 0;\n}\n\nint parse_tid_from_proc_path(const std::string& pathname,\n                             const std::string& property) {\n  // XXX When rr becomes c++17 - use string view instead. Has better API for\n  // this stuff.\n  const auto proc_length = 6;\n  const auto prop_should_begin =\n      pathname.size() - property.size() - (pathname.back() == '/');\n  if (pathname.substr(prop_should_begin, property.size()) == property) {\n    const auto task = \"task/\"s;\n    const auto pos = pathname.find(task);\n    if (pos == std::string::npos) {\n      auto s = pathname.substr(proc_length);\n      if (pathname.back() == '/')\n        s.pop_back();\n      char* end;\n      const int tid = strtol(s.c_str(), &end, 10);\n      if (end == property) {\n        return tid;\n      }\n    } else {\n      auto s = pathname.substr(pos + task.size());\n      if (pathname.back() == '/')\n        s.pop_back();\n      char* end;\n      const int tid = strtol(s.c_str(), &end, 10);\n      if (end == property) {\n        return tid;\n      }\n    }\n  }\n  return -1;\n}\n\nvoid replace_in_buffer(MemoryRange src, const uint8_t* src_data,\n                       MemoryRange dst, uint8_t* dst_data) {\n  remote_ptr<void> overlap_start = max(src.start(), dst.start());\n  remote_ptr<void> overlap_end = min(src.end(), dst.end());\n  if (overlap_start < overlap_end) {\n    memcpy(dst_data + (overlap_start - dst.start()),\n           src_data + (overlap_start - src.start()),\n           overlap_end - overlap_start);\n  }\n}\n\nvoid base_name(string& s) {\n  size_t p = s.rfind('/');\n  if (p != string::npos) {\n    s.erase(0, p + 1);\n  }\n}\n\nstatic optional<int> init_read_perf_event_paranoid() {\n  ScopedFd fd(\"/proc/sys/kernel/perf_event_paranoid\", O_RDONLY);\n  if (fd.is_open()) {\n    char buf[100];\n    ssize_t size = read(fd, buf, sizeof(buf) - 1);\n    if (size >= 0) {\n      buf[size] = 0;\n      return atoi(buf);\n    }\n  }\n\n  return nullopt;\n}\n\noptional<int> read_perf_event_paranoid() {\n  static optional<int> value = init_read_perf_event_paranoid();\n  return value;\n}\n\nbool virtual_address_size_supported(uint8_t bits) {\n  DEBUG_ASSERT(bits < 64);\n\n  // The easy, statically-determinable case.\n  // Legacy traces with bits == 0 will take this offramp too.\n  if (default_virtual_address_size(NativeArch::arch()) >= bits) {\n    return true;\n  }\n\n  // The architecture may have extensions (like five level paging) that allow\n  // higher addresses to be used. See if they're available.\n  size_t num_bytes = page_size();\n  void* ptr = (void*)(1ULL << (bits - 1));\n  void* map = mmap(ptr, num_bytes, PROT_NONE,\n                   MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0);\n  if (map == ptr) {\n    // If we successfully mapped at a high address, the extensions work.\n    munmap(map, num_bytes);\n    return true;\n  }\n\n  if (map == MAP_FAILED) {\n    if (errno == EEXIST) {\n      // If we failed to map because something else was already at the high\n      // address, the extensions work.\n      return true;\n    }\n    // If we failed for some other reason, assume the extensions do not work.\n    return false;\n  }\n\n  // If we got back a different address, assume the extensions do not work.\n  // NB: We could potentially be on a kernel that supports five level paging (so\n  // >= 4.14) but not MAP_FIXED_NOREPLACE (so < 4.17) *and* have something\n  // already using the address we tried. Handling that situation correctly\n  // adds substantial complexity, so we just give a false negative there.\n  munmap(map, num_bytes);\n  return false;\n}\n\n} // namespace rr\n"
  },
  {
    "path": "src/util.h",
    "content": "/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */\n\n#ifndef RR_UTIL_H_\n#define RR_UTIL_H_\n\n/* This header should not declare any interface types. It should mainly be included\n   in .cc files.\n */\n\n#include <signal.h>\n#include <stdio.h>\n#include <math.h>\n\n#include <array>\n#include <map>\n#include <optional>\n#include <set>\n#include <string>\n#include <vector>\n\n#if defined(__i386__) || defined(__x86_64__)\n#include <x86intrin.h>\n#endif\n\n#include \"CPUs.h\"\n#include \"MemoryRange.h\"\n#include \"ScopedFd.h\"\n#include \"TraceFrame.h\"\n#include \"remote_ptr.h\"\n#include \"kernel_supplement.h\"\n\n/* This is pretty arbitrary. On Linux SIGPWR is sent to PID 1 (init) on\n * power failure, and it's unlikely rr will be recording that.\n * Note that SIGUNUSED means SIGSYS which actually *is* used (by seccomp),\n * so we can't use it. */\n#define SYSCALLBUF_DEFAULT_DESCHED_SIGNAL SIGPWR\n\n#define UNUSED(expr)     \\\n  do {                   \\\n    if (expr) {          \\\n      (void)0;           \\\n    }                    \\\n  } while (0)\n\nnamespace rr {\n\n/*\n * This file is a dumping ground for functionality that needs to be shared but\n * has no other obvious place to go.\n *\n * We should minimize the amount of code here. Code that's only needed in one\n * place can move out of this file.\n */\n\nstruct Event;\nclass KernelMapping;\nclass Task;\nclass TraceFrame;\nclass RecordTask;\nclass ReplayTask;\n\nenum Completion { COMPLETE, INCOMPLETE };\n\n/**\n * Returns a vector containing the raw data you can get from getauxval.\n */\nstd::vector<uint8_t> read_auxv(Task* t);\n\n/**\n * Returns the base address where the interpreter is mapped.\n */\nremote_ptr<void> read_interpreter_base(std::vector<uint8_t> auxv);\n\n/**\n * Returns a string containing the file name of the interpreter.\n */\nstd::string read_ld_path(Task* t, remote_ptr<void> interpreter_base);\n\n/**\n * Returns a vector containing the environment strings.\n */\nstd::vector<std::string> read_env(Task* t);\n\nvoid patch_auxv_vdso(RecordTask* t, uintptr_t search, uintptr_t new_entry);\n\n/**\n * Create a file named |filename| and dump |buf_len| words in |buf| to\n * that file, starting with a line containing |label|.  |start_addr|\n * is the client address at which |buf| resides, if meaningful.\n * |start_addr| is used to compute the output lines of words, which\n * look like \"0xValue | [0xAddr]\".\n */\nvoid dump_binary_data(const char* filename, const char* label,\n                      const uint32_t* buf, size_t buf_len,\n                      remote_ptr<void> start_addr);\n\n/**\n * Format a suitable filename within the trace directory for dumping\n * information about |t| at the current global time, to a file that\n * contains |tag|.  For example, a file for a task with tid 12345 at\n * time 111, for a file tagged \"foo\", would be something like\n * \"trace_0/111_12345_foo\".  The returned name is not guaranteed to be\n * unique, caveat emptor.\n */\nstd::string format_dump_filename(Task* t, FrameTime global_time,\n                                 const char* tag);\n\n/**\n * Return true if the user requested memory be dumped at this event/time.\n */\nbool should_dump_memory(const Event& event, FrameTime time);\n/**\n * Dump all of the memory in |t|'s address to the file\n * \"[trace_dir]/[t->tid]_[global_time]_[tag]\".\n */\nvoid dump_process_memory(Task* t, FrameTime global_time, const char* tag);\n\n/**\n * Return true if the user has requested |t|'s memory be\n * checksummed at this event/time.\n */\nbool should_checksum(const Event& event, FrameTime time);\n/**\n * Write a checksum of each mapped region in |t|'s address space to a\n * special log, where it can be read by |validate_process_memory()|\n * during replay.\n */\nvoid checksum_process_memory(RecordTask* t, FrameTime global_time);\n/**\n * Validate the checksum of |t|'s address space that was written\n * during recording.\n */\nvoid validate_process_memory(ReplayTask* t, FrameTime global_time);\n\n/**\n * Write raw PT data to a file in the trace dir.\n */\nvoid write_pt_data(Task* t, FrameTime global_time,\n                   const std::vector<std::vector<uint8_t>>& data);\n\n/**\n * Read raw PT data to a file in the trace dir. Returns an empty vector if none found.\n */\nstd::vector<uint8_t> read_pt_data(Task* t, FrameTime global_time);\n\n/**\n * Return nonzero if the rr session is probably not interactive (that\n * is, there's probably no user watching or interacting with rr), and\n * so asking for user input or other actions is probably pointless.\n */\nbool probably_not_interactive(int fd = STDERR_FILENO);\n\n/**\n * Convert the flags passed to the clone() syscall, |flags_arg|, into\n * the format understood by Task::clone().\n */\nint clone_flags_to_task_flags(int flags_arg);\n\n/**\n * Return the argument rounded up to the nearest multiple of the\n * system |page_size()|.\n */\nsize_t ceil_page_size(size_t sz);\nremote_ptr<void> ceil_page_size(remote_ptr<void> addr);\n\n/**\n * Return the argument rounded down to the nearest multiple of the\n * system |page_size()|.\n */\nsize_t floor_page_size(size_t sz);\nremote_ptr<void> floor_page_size(remote_ptr<void> addr);\n\n/** Return the system page size. */\nsize_t page_size();\n\n/** Return the default action of |sig|. */\nenum signal_action { DUMP_CORE, TERMINATE, CONTINUE, STOP, IGNORE };\nsignal_action default_action(int sig);\n\nSignalDeterministic is_deterministic_signal(Task* t);\n\n/**\n * Return nonzero if a mapping of |mapping| should almost certainly be copied to\n * trace; i.e., the file contents are likely to change in the interval\n * between recording and replay.  Zero is returned /if we think we can\n * get away/ with not copying the region.  That doesn't mean it's\n * necessarily safe to skip copying!\n */\nbool should_copy_mmap_region(const KernelMapping& mapping,\n                             const std::string &file_name,\n                             const struct stat& stat);\n\n/**\n * Ensure that the shmem segment referred to by |fd| has exactly the\n * size |num_bytes|.\n */\nvoid resize_shmem_segment(ScopedFd& fd, uint64_t num_bytes);\n\nenum cpuid_requests {\n  CPUID_GETVENDORSTRING,\n  CPUID_GETFEATURES,\n  CPUID_GETTLB,\n  CPUID_GETSERIAL,\n  CPUID_GETCACHEPARAMS = 0x04,\n  CPUID_GETEXTENDEDFEATURES = 0x07,\n  CPUID_GETEXTENDEDTOPOLOGY = 0x0B,\n  CPUID_GETXSAVE = 0x0D,\n  CPUID_GETRDTMONITORING = 0x0F,\n  CPUID_GETRDTALLOCATION = 0x10,\n  CPUID_GETSGX = 0x12,\n  CPUID_GETPT = 0x14,\n  CPUID_GETSOC = 0x17,\n  CPUID_HYPERVISOR = 0x40000000,\n  CPUID_INTELEXTENDED = 0x80000000,\n  CPUID_INTELFEATURES,\n  CPUID_INTELBRANDSTRING,\n  CPUID_INTELBRANDSTRINGMORE,\n  CPUID_INTELBRANDSTRINGEND,\n  CPUID_AMD_CACHE_TOPOLOGY = 0x8000001D,\n  CPUID_AMD_PLATFORM_QOS = 0x80000020\n};\n\nconstexpr int AVX_512_FOUNDATION_FLAG = 1 << 16;\nconst int XSAVE_FEATURE_FLAG = 1 << 26;\nconst int OSXSAVE_FEATURE_FLAG = 1 << 27;\nconst int AVX_FEATURE_FLAG = 1 << 28;\nconst int HLE_FEATURE_FLAG = 1 << 4;\nconst int XSAVEC_FEATURE_FLAG = 1 << 1;\nconst int PKU_FEATURE_FLAG = 1 << 3;\n\n/** issue a single request to CPUID. Fits 'intel features', for instance\n *  note that even if only \"eax\" and \"edx\" are of interest, other registers\n *  will be modified by the operation, so we need to tell the compiler about it.\n *  'code' is placed in EAX. 'subrequest' is placed in ECX.\n *  *a, *c and *d receive EAX, ECX and EDX respectively.\n */\nstruct CPUIDData {\n  uint32_t eax, ebx, ecx, edx;\n};\nCPUIDData cpuid(uint32_t code, uint32_t subrequest);\n\n/**\n * Check whether the given result of cpuid(CPUID_GETVENDORSTRING) indicates\n * an AMD processor.\n */\nbool is_cpu_vendor_amd(CPUIDData vendor_string);\n\n/**\n * Check OSXSAVE flag.\n */\nbool xsave_enabled();\n/**\n * Fetch current XCR0 value using XGETBV instruction.\n */\nuint64_t xcr0();\n\n/**\n * Return all CPUID values supported by this CPU.\n */\nstruct CPUIDRecord {\n  uint32_t eax_in;\n  // UINT32_MAX means ECX not relevant\n  uint32_t ecx_in;\n  CPUIDData out;\n};\nstd::vector<CPUIDRecord> all_cpuid_records();\n\n/**\n * Returns true if CPUID faulting is supported by the kernel and hardware and\n * is actually working.\n */\nbool cpuid_faulting_works();\n\n/**\n * Locate a CPUID record for the give parameters, or return nullptr if there\n * isn't one.\n */\nconst CPUIDRecord* find_cpuid_record(const std::vector<CPUIDRecord>& records,\n                                     uint32_t eax, uint32_t ecx);\n\n/**\n * Return true if the trace's CPUID values are \"compatible enough\" with our\n * CPU's CPUID values.\n */\nbool cpuid_compatible(const std::vector<CPUIDRecord>& trace_records);\n\n/**\n * Return true if the CPU stores 0 for FIP/FDP in an XSAVE when no x87 exception\n * is pending.\n */\nbool cpu_has_xsave_fip_fdp_quirk();\n\n/**\n * CPU only sets FDP when an unmasked x87 exception is generated.\n */\nbool cpu_has_fdp_exception_only_quirk();\n\nstruct CloneParameters {\n  remote_ptr<void> stack;\n  remote_ptr<int> ptid;\n  remote_ptr<void> tls;\n  remote_ptr<int> ctid;\n};\n/**\n * Extract various clone(2) parameters out of the given Task's registers.\n */\nCloneParameters extract_clone_parameters(Task* t);\n\n/**\n * Read the ELF CLASS from the given filename. If it's unable to be read,\n * return ELFCLASSNONE. If it's not an ELF file, return NOT_ELF.\n */\nconst int NOT_ELF = 0x10000;\nint read_elf_class(const std::string& filename);\n\nbool trace_instructions_up_to_event(FrameTime event);\n\n/* Helpful for broken debuggers */\n\nvoid dump_task_set(const std::set<Task*>& tasks);\n\nvoid dump_task_map(const std::map<pid_t, Task*>& tasks);\n\nstd::string real_path(const std::string& path);\n\nstd::string resource_path();\n\n/**\n * Get the current time from the preferred monotonic clock in units of\n * seconds, relative to an unspecific point in the past.\n */\ndouble monotonic_now_sec();\n\nbool running_under_rr(bool cache = true);\n\nstd::vector<int> read_all_proc_fds(pid_t tid);\n\nstd::vector<std::string> read_proc_status_fields(pid_t tid, const char* name,\n                                                 const char* name2 = nullptr,\n                                                 const char* name3 = nullptr);\n\n/**\n * Mainline Linux kernels use an invisible (to /proc/<pid>/maps) guard page\n * for stacks. grsecurity kernels don't.\n */\nbool uses_invisible_guard_page();\n\n/**\n * Search /proc/net/ for a socket of the correct family matching the provided fd.\n * If found, returns the local and remote addresses in out and returns true.\n * Otherwise, returns false.\n */\nbool read_proc_net_socket_addresses(Task* t, int fd, std::array<typename NativeArch::sockaddr_storage, 2>& out);\n\nbool copy_file(int dest_fd, int src_fd);\n\n#if defined(__has_feature)\n#if __has_feature(memory_sanitizer)\nextern \"C\" void __msan_unpoison(void*, size_t);\ninline void msan_unpoison(void* ptr, size_t n) { __msan_unpoison(ptr, n); };\n#else\ninline void msan_unpoison(void* ptr, size_t n) {\n  (void)ptr;\n  (void)n;\n};\n#endif\n#else\ninline void msan_unpoison(void* ptr, size_t n) {\n  (void)ptr;\n  (void)n;\n};\n#endif\n\n/**\n * Determine if the given capabilities are a subset of the process' current\n * active capabilities.\n */\nbool has_effective_caps(uint64_t caps);\n\nstruct XSaveFeatureLayout {\n  uint32_t offset;\n  uint32_t size;\n};\n\nstruct XSaveLayout {\n  size_t full_size;\n  uint64_t supported_feature_bits;\n  std::vector<XSaveFeatureLayout> feature_layouts;\n};\n\n/**\n * Determine the layout of the native XSAVE area\n */\nconst XSaveLayout& xsave_native_layout();\n\n/**\n * Determine the layout of the XSAVE area from a trace\n */\nXSaveLayout xsave_layout_from_trace(const std::vector<CPUIDRecord> records);\n\n/**\n * 0 means XSAVE not detected\n */\ninline size_t xsave_area_size() { return xsave_native_layout().full_size; }\n\ninline sig_set_t signal_bit(int sig) { return sig_set_t(1) << (sig - 1); }\n\ninline bool is_kernel_trap(int si_code) {\n  /* XXX unable to find docs on which of these \"should\" be\n   * right.  The SI_KERNEL code is seen in the int3 test, so we\n   * at least need to handle that. */\n  return si_code == TRAP_TRACE || si_code == TRAP_BRKPT || si_code == TRAP_HWBKPT || si_code == SI_KERNEL;\n}\n\nenum ProbePort { DONT_PROBE = 0, PROBE_PORT };\n\nstruct OpenedSocket {\n  ScopedFd fd;\n  int domain;\n  std::string host;\n  unsigned short port;\n};\n\n// Open a socket bound to the given address and port.\n// If PROBE_PORT is set, probes for a usable port and sets it\n// in *port.\n// If `host` is empty, binds to localhost.\n// Returns the actual bound address, socket domain, and port.\n// Selects IPv4 or IPv6 automatically depending on what's in the\n// host address and what's available.\nOpenedSocket open_socket(const std::string& host, unsigned short port,\n                         ProbePort probe);\n\n/**\n * Like `abort`, but tries to wake up test-monitor for a snapshot if possible.\n * We try not to allocate.\n */\nvoid notifying_abort();\n\n/**\n * Dump the current rr stack to the given file.\n * We try not to allocate.\n */\nvoid dump_rr_stack(ScopedFd& fd);\n\n/**\n * Check for leaked mappings etc\n */\nvoid check_for_leaks();\n\n/**\n * Create directory `str`, creating parent directories as needed.\n * `dir_type` is printed in error messages. Fails if the resulting directory\n * is not writeable.\n */\nvoid ensure_dir(const std::string& dir, const char* dir_type, mode_t mode);\n\n/**\n * Returns $TMPDIR or \"/tmp\". We call ensure_dir to make sure the directory\n * exists and is writeable.\n */\nconst char* tmp_dir();\n\nstruct TempFile {\n  std::string name;\n  ScopedFd fd;\n};\n\n/**\n * `pattern is an mkstemp pattern minus any leading path. We'll choose the\n * temp directory ourselves. The file is not automatically deleted, the caller\n * must take care of that.\n */\nTempFile create_temporary_file(const char* pattern);\n\n/**\n * Opens a temporary file backed by RAM.\n */\nScopedFd open_memory_file(const std::string &name);\n\nvoid good_random(void* out, size_t out_len);\n\nstd::vector<std::string> current_env();\n\nenum class SpecialInstOpcode {\n  NONE,\n  ARM_MRS_CNTFRQ_EL0,\n  ARM_MRS_CNTVCT_EL0,\n  ARM_MRS_CNTVCTSS_EL0,\n  X86_RDTSC,\n  X86_RDTSCP,\n  X86_CPUID,\n  X86_INT3,\n  X86_PUSHF,\n  X86_PUSHF16,\n};\n\nstruct SpecialInst {\n  SpecialInstOpcode opcode;\n  unsigned regno = 0;\n};\n\n/* If |t->ip()| points at a decoded instruction, return the instruction */\nSpecialInst special_instruction_at(Task* t, remote_code_ptr ip);\n\nextern const uint8_t rdtsc_insn[2];\n\n/* Return the length of the TrappedInstruction */\nsize_t special_instruction_len(SpecialInstOpcode insn);\n\n/**\n * Certain instructions generate deterministic signals but also advance pc.\n * Look *backwards* and see if this was one of them.\n */\nbool is_advanced_pc_and_signaled_instruction(Task* t, remote_code_ptr ip);\n\n/* Get the path of the cpu lock file */\nstd::string get_cpu_lock_file();\n\n/* Convert a BindCPU to a specific CPU number. If possible, the cpu_lock_fd_out\n   will be set to an fd that holds an advisory fcntl lock for the chosen CPU\n   for coordination with other rr processes.\n   Returns -1 if there should be no binding.\n*/\nint choose_cpu(BindCPU bind_cpu, ScopedFd& cpu_lock_fd_out);\n\n/* Updates an IEEE 802.3 CRC-32 least significant bit first from each byte in\n * |buf|.  Pre- and post-conditioning is not performed in this function and so\n * should be performed by the caller, as required. */\nuint32_t update_crc32(uint32_t crc, unsigned char* buf, size_t len);\n\n/* Like write(2) but any error or \"device full\" is treated as fatal. We also\n * ensure that all bytes are written by looping on short writes. */\nvoid write_all(int fd, const void* buf, size_t size);\n\n/* Like pwrite64(2) but we try to write all bytes by looping on short writes. */\nssize_t pwrite_all_fallible(int fd, const void* buf, size_t size, off_t offset);\n\n/* Returns true if |path| is an accessible directory. Returns false if there\n * was an error.\n */\nbool is_directory(const char* path);\n\n/*\n * Returns a pointer to the filename portion of the path.\n * That is the position after the last '/'\n */\nconst char* filename(const char* path);\n\n/*\n * Returns whether a trace is at the path by checking for a version or\n * incomplete file.\n * Will set errno, if false.\n */\nbool is_trace(const std::string& path);\n\n/*\n * Returns whether the latest_trace symlink (if any) points to |trace|.\n */\nbool is_latest_trace(const std::string& trace);\n\n/*\n * Deletes the latest_trace symlink, logs an error and returns false on failure.\n */\nbool remove_latest_trace_symlink();\n\n/*\n * Returns whether |entry| is a valid trace name.\n * If invalid, optional out-param |reason| will be set to the reason.\n * I.e. does not start with . or #, does not end with ~, is neither cpu_lock\n * nor latest_trace.\n */\nbool is_valid_trace_name(const std::string& entry,\n                         std::string* reason = nullptr);\n\n/**\n * Read bytes from `fd` into `buf` from `offset` until the read returns an\n * error or 0 or the buffer is full. Returns total bytes read or -1 for error.\n */\nssize_t read_to_end(const ScopedFd& fd, size_t offset, void* buf, size_t size);\n\n/**\n * Raise resource limits, in particular the open file descriptor count.\n */\nvoid raise_resource_limits();\n\n/**\n * Restore the initial resource limits for this process.\n */\nvoid restore_initial_resource_limits();\n\n/**\n * Return the word size for the architecture.\n */\nsize_t word_size(SupportedArch arch);\n\n/**\n * Print JSON-escaped version of the string, including double-quotes.\n */\nstd::string json_escape(const std::string& str, size_t pos = 0);\n\nvoid sleep_time(double t);\n\n/**\n * Normalize a file name by lexically resolving `.`,`..`,`//`\n */\nvoid normalize_file_name(std::string& s);\n\nenum NestedBehavior {\n  NESTED_ERROR,\n  NESTED_IGNORE,\n  NESTED_DETACH,\n  NESTED_RELEASE,\n};\n\nstd::string find_exec_stub(SupportedArch arch);\n\nstd::string find_helper_library(const char* basepath);\n\nstatic inline struct timeval to_timeval(double t) {\n  struct timeval v;\n  v.tv_sec = (time_t)floor(t);\n  v.tv_usec = (int)floor((t - v.tv_sec) * 1000000);\n  return v;\n}\n\n/* Slow but simple pop-count implementation. */\nint pop_count(uint64_t v);\n\n/* A version of fatal that uses no allocation/thread resource and is thus\n  safe to use in volatile contexts */\nvoid SAFE_FATAL(int err, const char *msg);\n\nbool coredumping_signal_takes_down_entire_vm();\n\n/* Parse tid from the proc file system path /proc/<pid>/<property> or /proc/<pid>/task/<tid>/<property> */\nint parse_tid_from_proc_path(const std::string& pathname, const std::string& property);\n\ninline unsigned long long rdtsc(void) {\n#if defined(__i386__) || defined(__x86_64__)\n  return __rdtsc();\n#else\n  FATAL() << \"Reached x86-only code path on non-x86 architecture\";\n  return 0;\n#endif\n}\n\ninline unsigned long long cntfrq(void) {\n#if defined(__aarch64__)\n  unsigned long long val;\n  asm volatile(\"mrs %0, CNTFRQ_EL0\" : \"=r\" (val));\n  return val;\n#else\n  FATAL() << \"Reached AArch64-only code path on non-AArch64 architecture\";\n  return 0;\n#endif\n}\n\ninline unsigned long long cntvct(void) {\n#if defined(__aarch64__)\n  unsigned long long val;\n  asm volatile(\"mrs %0, CNTVCT_EL0\" : \"=r\" (val));\n  return val;\n#else\n  FATAL() << \"Reached AArch64-only code path on non-AArch64 architecture\";\n  return 0;\n#endif\n}\n\ninline unsigned long long dczid_el0_block_size(void) {\n#if defined(__aarch64__)\n  unsigned long long val;\n  asm volatile(\"mrs %0, DCZID_EL0\" : \"=r\" (val));\n  return 4ULL << (val & 0xF);\n#else\n  FATAL() << \"Reached AArch64-only code path on non-AArch64 architecture\";\n  return 0;\n#endif\n}\n\n/**\n * If `src` overlaps `dst`, replace the bytes in `dst_data` from the range `dst`\n * with the corresponding bytes in `src_data` from the range `src`.\n */\nvoid replace_in_buffer(MemoryRange src, const uint8_t* src_data,\n                       MemoryRange dst, uint8_t* dst_data);\n\n// Strip any directory part from the filename `s`\nvoid base_name(std::string& s);\n\nstd::optional<int> read_perf_event_paranoid();\n\nbool virtual_address_size_supported(uint8_t bit_size);\n\n} // namespace rr\n\n#endif /* RR_UTIL_H_ */\n"
  },
  {
    "path": "third-party/blake2/README",
    "content": "Taken verbatim from https://github.com/BLAKE2/BLAKE2/commit/997fa5ba1e14b52c554fb03ce39e579e6f27b90c\n\nSources are in the public domain.\n"
  },
  {
    "path": "third-party/blake2/blake2-impl.h",
    "content": "/*\n   BLAKE2 reference source code package - reference C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2_IMPL_H\n#define BLAKE2_IMPL_H\n\n#include <stdint.h>\n#include <string.h>\n\n#if !defined(__cplusplus) && (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901L)\n  #if   defined(_MSC_VER)\n    #define BLAKE2_INLINE __inline\n  #elif defined(__GNUC__)\n    #define BLAKE2_INLINE __inline__\n  #else\n    #define BLAKE2_INLINE\n  #endif\n#else\n  #define BLAKE2_INLINE inline\n#endif\n\nstatic BLAKE2_INLINE uint32_t load32( const void *src )\n{\n#if defined(NATIVE_LITTLE_ENDIAN)\n  uint32_t w;\n  memcpy(&w, src, sizeof w);\n  return w;\n#else\n  const uint8_t *p = ( const uint8_t * )src;\n  return (( uint32_t )( p[0] ) <<  0) |\n         (( uint32_t )( p[1] ) <<  8) |\n         (( uint32_t )( p[2] ) << 16) |\n         (( uint32_t )( p[3] ) << 24) ;\n#endif\n}\n\nstatic BLAKE2_INLINE uint64_t load64( const void *src )\n{\n#if defined(NATIVE_LITTLE_ENDIAN)\n  uint64_t w;\n  memcpy(&w, src, sizeof w);\n  return w;\n#else\n  const uint8_t *p = ( const uint8_t * )src;\n  return (( uint64_t )( p[0] ) <<  0) |\n         (( uint64_t )( p[1] ) <<  8) |\n         (( uint64_t )( p[2] ) << 16) |\n         (( uint64_t )( p[3] ) << 24) |\n         (( uint64_t )( p[4] ) << 32) |\n         (( uint64_t )( p[5] ) << 40) |\n         (( uint64_t )( p[6] ) << 48) |\n         (( uint64_t )( p[7] ) << 56) ;\n#endif\n}\n\nstatic BLAKE2_INLINE uint16_t load16( const void *src )\n{\n#if defined(NATIVE_LITTLE_ENDIAN)\n  uint16_t w;\n  memcpy(&w, src, sizeof w);\n  return w;\n#else\n  const uint8_t *p = ( const uint8_t * )src;\n  return ( uint16_t )((( uint32_t )( p[0] ) <<  0) |\n                      (( uint32_t )( p[1] ) <<  8));\n#endif\n}\n\nstatic BLAKE2_INLINE void store16( void *dst, uint16_t w )\n{\n#if defined(NATIVE_LITTLE_ENDIAN)\n  memcpy(dst, &w, sizeof w);\n#else\n  uint8_t *p = ( uint8_t * )dst;\n  *p++ = ( uint8_t )w; w >>= 8;\n  *p++ = ( uint8_t )w;\n#endif\n}\n\nstatic BLAKE2_INLINE void store32( void *dst, uint32_t w )\n{\n#if defined(NATIVE_LITTLE_ENDIAN)\n  memcpy(dst, &w, sizeof w);\n#else\n  uint8_t *p = ( uint8_t * )dst;\n  p[0] = (uint8_t)(w >>  0);\n  p[1] = (uint8_t)(w >>  8);\n  p[2] = (uint8_t)(w >> 16);\n  p[3] = (uint8_t)(w >> 24);\n#endif\n}\n\nstatic BLAKE2_INLINE void store64( void *dst, uint64_t w )\n{\n#if defined(NATIVE_LITTLE_ENDIAN)\n  memcpy(dst, &w, sizeof w);\n#else\n  uint8_t *p = ( uint8_t * )dst;\n  p[0] = (uint8_t)(w >>  0);\n  p[1] = (uint8_t)(w >>  8);\n  p[2] = (uint8_t)(w >> 16);\n  p[3] = (uint8_t)(w >> 24);\n  p[4] = (uint8_t)(w >> 32);\n  p[5] = (uint8_t)(w >> 40);\n  p[6] = (uint8_t)(w >> 48);\n  p[7] = (uint8_t)(w >> 56);\n#endif\n}\n\nstatic BLAKE2_INLINE uint64_t load48( const void *src )\n{\n  const uint8_t *p = ( const uint8_t * )src;\n  return (( uint64_t )( p[0] ) <<  0) |\n         (( uint64_t )( p[1] ) <<  8) |\n         (( uint64_t )( p[2] ) << 16) |\n         (( uint64_t )( p[3] ) << 24) |\n         (( uint64_t )( p[4] ) << 32) |\n         (( uint64_t )( p[5] ) << 40) ;\n}\n\nstatic BLAKE2_INLINE void store48( void *dst, uint64_t w )\n{\n  uint8_t *p = ( uint8_t * )dst;\n  p[0] = (uint8_t)(w >>  0);\n  p[1] = (uint8_t)(w >>  8);\n  p[2] = (uint8_t)(w >> 16);\n  p[3] = (uint8_t)(w >> 24);\n  p[4] = (uint8_t)(w >> 32);\n  p[5] = (uint8_t)(w >> 40);\n}\n\nstatic BLAKE2_INLINE uint32_t rotr32( const uint32_t w, const unsigned c )\n{\n  return ( w >> c ) | ( w << ( 32 - c ) );\n}\n\nstatic BLAKE2_INLINE uint64_t rotr64( const uint64_t w, const unsigned c )\n{\n  return ( w >> c ) | ( w << ( 64 - c ) );\n}\n\n/* prevents compiler optimizing out memset() */\nstatic BLAKE2_INLINE void secure_zero_memory(void *v, size_t n)\n{\n  static void *(*const volatile memset_v)(void *, int, size_t) = &memset;\n  memset_v(v, 0, n);\n}\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/blake2.h",
    "content": "/*\n   BLAKE2 reference source code package - reference C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2_H\n#define BLAKE2_H\n\n#include <stddef.h>\n#include <stdint.h>\n\n#if defined(_MSC_VER)\n#define BLAKE2_PACKED(x) __pragma(pack(push, 1)) x __pragma(pack(pop))\n#else\n#define BLAKE2_PACKED(x) x __attribute__((packed))\n#endif\n\n#if defined(__cplusplus)\nextern \"C\" {\n#endif\n\n  enum blake2s_constant\n  {\n    BLAKE2S_BLOCKBYTES = 64,\n    BLAKE2S_OUTBYTES   = 32,\n    BLAKE2S_KEYBYTES   = 32,\n    BLAKE2S_SALTBYTES  = 8,\n    BLAKE2S_PERSONALBYTES = 8\n  };\n\n  enum blake2b_constant\n  {\n    BLAKE2B_BLOCKBYTES = 128,\n    BLAKE2B_OUTBYTES   = 64,\n    BLAKE2B_KEYBYTES   = 64,\n    BLAKE2B_SALTBYTES  = 16,\n    BLAKE2B_PERSONALBYTES = 16\n  };\n\n  typedef struct blake2s_state__\n  {\n    uint32_t h[8];\n    uint32_t t[2];\n    uint32_t f[2];\n    uint8_t  buf[BLAKE2S_BLOCKBYTES];\n    size_t   buflen;\n    size_t   outlen;\n    uint8_t  last_node;\n  } blake2s_state;\n\n  typedef struct blake2b_state__\n  {\n    uint64_t h[8];\n    uint64_t t[2];\n    uint64_t f[2];\n    uint8_t  buf[BLAKE2B_BLOCKBYTES];\n    size_t   buflen;\n    size_t   outlen;\n    uint8_t  last_node;\n  } blake2b_state;\n\n  typedef struct blake2sp_state__\n  {\n    blake2s_state S[8][1];\n    blake2s_state R[1];\n    uint8_t       buf[8 * BLAKE2S_BLOCKBYTES];\n    size_t        buflen;\n    size_t        outlen;\n  } blake2sp_state;\n\n  typedef struct blake2bp_state__\n  {\n    blake2b_state S[4][1];\n    blake2b_state R[1];\n    uint8_t       buf[4 * BLAKE2B_BLOCKBYTES];\n    size_t        buflen;\n    size_t        outlen;\n  } blake2bp_state;\n\n\n  BLAKE2_PACKED(struct blake2s_param__\n  {\n    uint8_t  digest_length; /* 1 */\n    uint8_t  key_length;    /* 2 */\n    uint8_t  fanout;        /* 3 */\n    uint8_t  depth;         /* 4 */\n    uint32_t leaf_length;   /* 8 */\n    uint32_t node_offset;  /* 12 */\n    uint16_t xof_length;    /* 14 */\n    uint8_t  node_depth;    /* 15 */\n    uint8_t  inner_length;  /* 16 */\n    /* uint8_t  reserved[0]; */\n    uint8_t  salt[BLAKE2S_SALTBYTES]; /* 24 */\n    uint8_t  personal[BLAKE2S_PERSONALBYTES];  /* 32 */\n  });\n\n  typedef struct blake2s_param__ blake2s_param;\n\n  BLAKE2_PACKED(struct blake2b_param__\n  {\n    uint8_t  digest_length; /* 1 */\n    uint8_t  key_length;    /* 2 */\n    uint8_t  fanout;        /* 3 */\n    uint8_t  depth;         /* 4 */\n    uint32_t leaf_length;   /* 8 */\n    uint32_t node_offset;   /* 12 */\n    uint32_t xof_length;    /* 16 */\n    uint8_t  node_depth;    /* 17 */\n    uint8_t  inner_length;  /* 18 */\n    uint8_t  reserved[14];  /* 32 */\n    uint8_t  salt[BLAKE2B_SALTBYTES]; /* 48 */\n    uint8_t  personal[BLAKE2B_PERSONALBYTES];  /* 64 */\n  });\n\n  typedef struct blake2b_param__ blake2b_param;\n\n  typedef struct blake2xs_state__\n  {\n    blake2s_state S[1];\n    blake2s_param P[1];\n  } blake2xs_state;\n\n  typedef struct blake2xb_state__\n  {\n    blake2b_state S[1];\n    blake2b_param P[1];\n  } blake2xb_state;\n\n  /* Padded structs result in a compile-time error */\n  enum {\n    BLAKE2_DUMMY_1 = 1/(sizeof(blake2s_param) == BLAKE2S_OUTBYTES),\n    BLAKE2_DUMMY_2 = 1/(sizeof(blake2b_param) == BLAKE2B_OUTBYTES)\n  };\n\n  /* Streaming API */\n  int blake2s_init( blake2s_state *S, size_t outlen );\n  int blake2s_init_key( blake2s_state *S, size_t outlen, const void *key, size_t keylen );\n  int blake2s_init_param( blake2s_state *S, const blake2s_param *P );\n  int blake2s_update( blake2s_state *S, const void *in, size_t inlen );\n  int blake2s_final( blake2s_state *S, void *out, size_t outlen );\n\n  int blake2b_init( blake2b_state *S, size_t outlen );\n  int blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen );\n  int blake2b_init_param( blake2b_state *S, const blake2b_param *P );\n  int blake2b_update( blake2b_state *S, const void *in, size_t inlen );\n  int blake2b_final( blake2b_state *S, void *out, size_t outlen );\n\n  int blake2sp_init( blake2sp_state *S, size_t outlen );\n  int blake2sp_init_key( blake2sp_state *S, size_t outlen, const void *key, size_t keylen );\n  int blake2sp_update( blake2sp_state *S, const void *in, size_t inlen );\n  int blake2sp_final( blake2sp_state *S, void *out, size_t outlen );\n\n  int blake2bp_init( blake2bp_state *S, size_t outlen );\n  int blake2bp_init_key( blake2bp_state *S, size_t outlen, const void *key, size_t keylen );\n  int blake2bp_update( blake2bp_state *S, const void *in, size_t inlen );\n  int blake2bp_final( blake2bp_state *S, void *out, size_t outlen );\n\n  /* Variable output length API */\n  int blake2xs_init( blake2xs_state *S, const size_t outlen );\n  int blake2xs_init_key( blake2xs_state *S, const size_t outlen, const void *key, size_t keylen );\n  int blake2xs_update( blake2xs_state *S, const void *in, size_t inlen );\n  int blake2xs_final(blake2xs_state *S, void *out, size_t outlen);\n\n  int blake2xb_init( blake2xb_state *S, const size_t outlen );\n  int blake2xb_init_key( blake2xb_state *S, const size_t outlen, const void *key, size_t keylen );\n  int blake2xb_update( blake2xb_state *S, const void *in, size_t inlen );\n  int blake2xb_final(blake2xb_state *S, void *out, size_t outlen);\n\n  /* Simple API */\n  int blake2s( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n  int blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n\n  int blake2sp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n  int blake2bp( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n\n  int blake2xs( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n  int blake2xb( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n\n  /* This is simply an alias for blake2b */\n  int blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen );\n\n#if defined(__cplusplus)\n}\n#endif\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/neon/blake2b-load-neon.h",
    "content": "/*\n   BLAKE2 reference source code package - reference C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2B_LOAD_NEON_H\n#define BLAKE2B_LOAD_NEON_H\n\n#define LOAD_MSG_0_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); \\\n  b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3));\n\n#define LOAD_MSG_0_2(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m1)); \\\n  b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m3));\n\n#define LOAD_MSG_0_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m5)); \\\n  b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7));\n\n#define LOAD_MSG_0_4(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m5)); \\\n  b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m7));\n\n#define LOAD_MSG_1_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); \\\n  b1 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m6));\n\n#define LOAD_MSG_1_2(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); \\\n  b1 = vextq_u64(m7, m3, 1);\n\n#define LOAD_MSG_1_3(b0, b1) \\\n  b0 = vextq_u64(m0, m0, 1); \\\n  b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m2));\n\n#define LOAD_MSG_1_4(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m1)); \\\n  b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1));\n\n#define LOAD_MSG_2_1(b0, b1) \\\n  b0 = vextq_u64(m5, m6, 1); \\\n  b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7));\n\n#define LOAD_MSG_2_2(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m0)); \\\n  b1 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m6));\n\n#define LOAD_MSG_2_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m5), vget_high_u64(m1)); \\\n  b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m4));\n\n#define LOAD_MSG_2_4(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m3)); \\\n  b1 = vextq_u64(m0, m2, 1);\n\n#define LOAD_MSG_3_1(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); \\\n  b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m5));\n\n#define LOAD_MSG_3_2(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m0)); \\\n  b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7));\n\n#define LOAD_MSG_3_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m2)); \\\n  b1 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m7));\n\n#define LOAD_MSG_3_4(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m5)); \\\n  b1 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m4));\n\n#define LOAD_MSG_4_1(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m2)); \\\n  b1 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m5));\n\n#define LOAD_MSG_4_2(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m0), vget_high_u64(m3)); \\\n  b1 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m7));\n\n#define LOAD_MSG_4_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m7), vget_high_u64(m5)); \\\n  b1 = vcombine_u64(vget_low_u64(m3), vget_high_u64(m1));\n\n#define LOAD_MSG_4_4(b0, b1) \\\n  b0 = vextq_u64(m0, m6, 1); \\\n  b1 = vcombine_u64(vget_low_u64(m4), vget_high_u64(m6));\n\n#define LOAD_MSG_5_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m3)); \\\n  b1 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m4));\n\n#define LOAD_MSG_5_2(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m5)); \\\n  b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m1));\n\n#define LOAD_MSG_5_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m3)); \\\n  b1 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m0));\n\n#define LOAD_MSG_5_4(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m2)); \\\n  b1 = vcombine_u64(vget_low_u64(m7), vget_high_u64(m4));\n\n#define LOAD_MSG_6_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m6), vget_high_u64(m0)); \\\n  b1 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2));\n\n#define LOAD_MSG_6_2(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); \\\n  b1 = vextq_u64(m6, m5, 1);\n\n#define LOAD_MSG_6_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m3)); \\\n  b1 = vextq_u64(m4, m4, 1);\n\n#define LOAD_MSG_6_4(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); \\\n  b1 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m5));\n\n#define LOAD_MSG_7_1(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m3)); \\\n  b1 = vcombine_u64(vget_low_u64(m6), vget_high_u64(m1));\n\n#define LOAD_MSG_7_2(b0, b1) \\\n  b0 = vextq_u64(m5, m7, 1); \\\n  b1 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m4));\n\n#define LOAD_MSG_7_3(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); \\\n  b1 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m1));\n\n#define LOAD_MSG_7_4(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m2)); \\\n  b1 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m5));\n\n#define LOAD_MSG_8_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m7)); \\\n  b1 = vextq_u64(m5, m0, 1);\n\n#define LOAD_MSG_8_2(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m4)); \\\n  b1 = vextq_u64(m1, m4, 1);\n\n#define LOAD_MSG_8_3(b0, b1) \\\n  b0 = m6; \\\n  b1 = vextq_u64(m0, m5, 1);\n\n#define LOAD_MSG_8_4(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m3)); \\\n  b1 = m2;\n\n#define LOAD_MSG_9_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); \\\n  b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m0));\n\n#define LOAD_MSG_9_2(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m2)); \\\n  b1 = vcombine_u64(vget_low_u64(m3), vget_high_u64(m2));\n\n#define LOAD_MSG_9_3(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m4)); \\\n  b1 = vcombine_u64(vget_high_u64(m1), vget_high_u64(m6));\n\n#define LOAD_MSG_9_4(b0, b1) \\\n  b0 = vextq_u64(m5, m7, 1); \\\n  b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m0));\n\n#define LOAD_MSG_10_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); \\\n  b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3));\n\n#define LOAD_MSG_10_2(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m1)); \\\n  b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m3));\n\n#define LOAD_MSG_10_3(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m5)); \\\n  b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7));\n\n#define LOAD_MSG_10_4(b0, b1) \\\n  b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m5)); \\\n  b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m7));\n\n#define LOAD_MSG_11_1(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); \\\n  b1 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m6));\n\n#define LOAD_MSG_11_2(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); \\\n  b1 = vextq_u64(m7, m3, 1);\n\n#define LOAD_MSG_11_3(b0, b1) \\\n  b0 = vextq_u64(m0, m0, 1); \\\n  b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m2));\n\n#define LOAD_MSG_11_4(b0, b1) \\\n  b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m1)); \\\n  b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1));\n\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/neon/blake2b-neon.c",
    "content": "/*\n   BLAKE2 reference source code package - reference C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n\n#include <stdint.h>\n#include <string.h>\n#include <stdio.h>\n#include <arm_neon.h>\n\n#include \"blake2.h\"\n#include \"blake2-impl.h\"\n\nstatic const uint64_t blake2b_IV[8] =\n{\n  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,\n  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,\n  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,\n  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL\n};\n\n/*\nstatic const uint8_t blake2b_sigma[12][16] =\n{\n  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,\n  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 } ,\n  { 11,  8, 12,  0,  5,  2, 15, 13, 10, 14,  3,  6,  7,  1,  9,  4 } ,\n  {  7,  9,  3,  1, 13, 12, 11, 14,  2,  6,  5, 10,  4,  0, 15,  8 } ,\n  {  9,  0,  5,  7,  2,  4, 10, 15, 14,  1, 11, 12,  6,  8,  3, 13 } ,\n  {  2, 12,  6, 10,  0, 11,  8,  3,  4, 13,  7,  5, 15, 14,  1,  9 } ,\n  { 12,  5,  1, 15, 14, 13,  4, 10,  0,  7,  6,  3,  9,  2,  8, 11 } ,\n  { 13, 11,  7, 14, 12,  1,  3,  9,  5,  0, 15,  4,  8,  6,  2, 10 } ,\n  {  6, 15, 14,  9, 11,  3,  0,  8, 12,  2, 13,  7,  1,  4, 10,  5 } ,\n  { 10,  2,  8,  4,  7,  6,  1,  5, 15, 11,  9, 14,  3, 12, 13 , 0 } ,\n  {  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15 } ,\n  { 14, 10,  4,  8,  9, 15, 13,  6,  1, 12,  0,  2, 11,  7,  5,  3 }\n};\n*/\n\nstatic void blake2b_set_lastnode( blake2b_state *S )\n{\n  S->f[1] = (uint64_t)-1;\n}\n\n/* Some helper functions, not necessarily useful */\nstatic int blake2b_is_lastblock( const blake2b_state *S )\n{\n  return S->f[0] != 0;\n}\n\nstatic void blake2b_set_lastblock( blake2b_state *S )\n{\n  if( S->last_node ) blake2b_set_lastnode( S );\n\n  S->f[0] = (uint64_t)-1;\n}\n\nstatic void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )\n{\n  S->t[0] += inc;\n  S->t[1] += ( S->t[0] < inc );\n}\n\nstatic void blake2b_init0( blake2b_state *S )\n{\n  size_t i;\n  memset( S, 0, sizeof( blake2b_state ) );\n\n  for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];\n}\n\n/* init xors IV with input parameter block */\nint blake2b_init_param( blake2b_state *S, const blake2b_param *P )\n{\n  const uint8_t *p = ( const uint8_t * )( P );\n  size_t i;\n\n  blake2b_init0( S );\n\n  /* IV XOR ParamBlock */\n  for( i = 0; i < 8; ++i )\n    S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );\n\n  S->outlen = P->digest_length;\n  return 0;\n}\n\n\n\nint blake2b_init( blake2b_state *S, size_t outlen )\n{\n  blake2b_param P[1];\n\n  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;\n\n  P->digest_length = (uint8_t)outlen;\n  P->key_length    = 0;\n  P->fanout        = 1;\n  P->depth         = 1;\n  store32( &P->leaf_length, 0 );\n  store32( &P->node_offset, 0 );\n  store32( &P->xof_length, 0 );\n  P->node_depth    = 0;\n  P->inner_length  = 0;\n  memset( P->reserved, 0, sizeof( P->reserved ) );\n  memset( P->salt,     0, sizeof( P->salt ) );\n  memset( P->personal, 0, sizeof( P->personal ) );\n  return blake2b_init_param( S, P );\n}\n\n\nint blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )\n{\n  blake2b_param P[1];\n\n  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;\n\n  if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;\n\n  P->digest_length = (uint8_t)outlen;\n  P->key_length    = (uint8_t)keylen;\n  P->fanout        = 1;\n  P->depth         = 1;\n  store32( &P->leaf_length, 0 );\n  store32( &P->node_offset, 0 );\n  store32( &P->xof_length, 0 );\n  P->node_depth    = 0;\n  P->inner_length  = 0;\n  memset( P->reserved, 0, sizeof( P->reserved ) );\n  memset( P->salt,     0, sizeof( P->salt ) );\n  memset( P->personal, 0, sizeof( P->personal ) );\n\n  if( blake2b_init_param( S, P ) < 0 ) return -1;\n\n  {\n    uint8_t block[BLAKE2B_BLOCKBYTES];\n    memset( block, 0, BLAKE2B_BLOCKBYTES );\n    memcpy( block, key, keylen );\n    blake2b_update( S, block, BLAKE2B_BLOCKBYTES );\n    secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */\n  }\n  return 0;\n}\n\n#undef LOAD_MSG_0_1\n#define LOAD_MSG_0_1(b0, b1) \\\ndo { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3)); } while(0)\n\n#undef LOAD_MSG_0_2\n#define LOAD_MSG_0_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m3)); } while(0)\n\n#undef LOAD_MSG_0_3\n#define LOAD_MSG_0_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m5)); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7)); } while(0)\n\n#undef LOAD_MSG_0_4\n#define LOAD_MSG_0_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m5)); b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m7)); } while(0)\n\n#undef LOAD_MSG_1_1\n#define LOAD_MSG_1_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); b1 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m6)); } while(0)\n\n#undef LOAD_MSG_1_2\n#define LOAD_MSG_1_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); b1 = vextq_u64(m7, m3, 1); } while(0)\n\n#undef LOAD_MSG_1_3\n#define LOAD_MSG_1_3(b0, b1) \\\n  do { b0 = vextq_u64(m0, m0, 1); b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m2)); } while(0)\n\n#undef LOAD_MSG_1_4\n#define LOAD_MSG_1_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m1)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); } while(0)\n\n#undef LOAD_MSG_2_1\n#define LOAD_MSG_2_1(b0, b1) \\\n  do { b0 = vextq_u64(m5, m6, 1); b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); } while(0)\n\n#undef LOAD_MSG_2_2\n#define LOAD_MSG_2_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m0)); b1 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m6)); } while(0)\n\n#undef LOAD_MSG_2_3\n#define LOAD_MSG_2_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m5), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m4)); } while(0)\n\n#undef LOAD_MSG_2_4\n#define LOAD_MSG_2_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m3)); b1 = vextq_u64(m0, m2, 1); } while(0)\n\n#undef LOAD_MSG_3_1\n#define LOAD_MSG_3_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m5)); } while(0)\n\n#undef LOAD_MSG_3_2\n#define LOAD_MSG_3_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m0)); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7)); } while(0)\n\n#undef LOAD_MSG_3_3\n#define LOAD_MSG_3_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m2)); b1 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m7)); } while(0)\n\n#undef LOAD_MSG_3_4\n#define LOAD_MSG_3_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m5)); b1 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m4)); } while(0)\n\n#undef LOAD_MSG_4_1\n#define LOAD_MSG_4_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m2)); b1 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m5)); } while(0)\n\n#undef LOAD_MSG_4_2\n#define LOAD_MSG_4_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m0), vget_high_u64(m3)); b1 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m7)); } while(0)\n\n#undef LOAD_MSG_4_3\n#define LOAD_MSG_4_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m7), vget_high_u64(m5)); b1 = vcombine_u64(vget_low_u64(m3), vget_high_u64(m1)); } while(0)\n\n#undef LOAD_MSG_4_4\n#define LOAD_MSG_4_4(b0, b1) \\\n  do { b0 = vextq_u64(m0, m6, 1); b1 = vcombine_u64(vget_low_u64(m4), vget_high_u64(m6)); } while(0)\n\n#undef LOAD_MSG_5_1\n#define LOAD_MSG_5_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m3)); b1 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m4)); } while(0)\n\n#undef LOAD_MSG_5_2\n#define LOAD_MSG_5_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m5)); b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m1)); } while(0)\n\n#undef LOAD_MSG_5_3\n#define LOAD_MSG_5_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m2), vget_high_u64(m3)); b1 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m0)); } while(0)\n\n#undef LOAD_MSG_5_4\n#define LOAD_MSG_5_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m2)); b1 = vcombine_u64(vget_low_u64(m7), vget_high_u64(m4)); } while(0)\n\n#undef LOAD_MSG_6_1\n#define LOAD_MSG_6_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m6), vget_high_u64(m0)); b1 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); } while(0)\n\n#undef LOAD_MSG_6_2\n#define LOAD_MSG_6_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); b1 = vextq_u64(m6, m5, 1); } while(0)\n\n#undef LOAD_MSG_6_3\n#define LOAD_MSG_6_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m3)); b1 = vextq_u64(m4, m4, 1); } while(0)\n\n#undef LOAD_MSG_6_4\n#define LOAD_MSG_6_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); b1 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m5)); } while(0)\n\n#undef LOAD_MSG_7_1\n#define LOAD_MSG_7_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m3)); b1 = vcombine_u64(vget_low_u64(m6), vget_high_u64(m1)); } while(0)\n\n#undef LOAD_MSG_7_2\n#define LOAD_MSG_7_2(b0, b1) \\\n  do { b0 = vextq_u64(m5, m7, 1); b1 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m4)); } while(0)\n\n#undef LOAD_MSG_7_3\n#define LOAD_MSG_7_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m7)); b1 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m1)); } while(0)\n\n#undef LOAD_MSG_7_4\n#define LOAD_MSG_7_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m2)); b1 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m5)); } while(0)\n\n#undef LOAD_MSG_8_1\n#define LOAD_MSG_8_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m3), vget_low_u64(m7)); b1 = vextq_u64(m5, m0, 1); } while(0)\n\n#undef LOAD_MSG_8_2\n#define LOAD_MSG_8_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m4)); b1 = vextq_u64(m1, m4, 1); } while(0)\n\n#undef LOAD_MSG_8_3\n#define LOAD_MSG_8_3(b0, b1) \\\n  do { b0 = m6; b1 = vextq_u64(m0, m5, 1); } while(0)\n\n#undef LOAD_MSG_8_4\n#define LOAD_MSG_8_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m1), vget_high_u64(m3)); b1 = m2; } while(0)\n\n#undef LOAD_MSG_9_1\n#define LOAD_MSG_9_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m0)); } while(0)\n\n#undef LOAD_MSG_9_2\n#define LOAD_MSG_9_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m1), vget_low_u64(m2)); b1 = vcombine_u64(vget_low_u64(m3), vget_high_u64(m2)); } while(0)\n\n#undef LOAD_MSG_9_3\n#define LOAD_MSG_9_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m7), vget_high_u64(m4)); b1 = vcombine_u64(vget_high_u64(m1), vget_high_u64(m6)); } while(0)\n\n#undef LOAD_MSG_9_4\n#define LOAD_MSG_9_4(b0, b1) \\\n  do { b0 = vextq_u64(m5, m7, 1); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m0)); } while(0)\n\n#undef LOAD_MSG_10_1\n#define LOAD_MSG_10_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m0), vget_low_u64(m1)); b1 = vcombine_u64(vget_low_u64(m2), vget_low_u64(m3)); } while(0)\n\n#undef LOAD_MSG_10_2\n#define LOAD_MSG_10_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m0), vget_high_u64(m1)); b1 = vcombine_u64(vget_high_u64(m2), vget_high_u64(m3)); } while(0)\n\n#undef LOAD_MSG_10_3\n#define LOAD_MSG_10_3(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m4), vget_low_u64(m5)); b1 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m7)); } while(0)\n\n#undef LOAD_MSG_10_4\n#define LOAD_MSG_10_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m5)); b1 = vcombine_u64(vget_high_u64(m6), vget_high_u64(m7)); } while(0)\n\n#undef LOAD_MSG_11_1\n#define LOAD_MSG_11_1(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m7), vget_low_u64(m2)); b1 = vcombine_u64(vget_high_u64(m4), vget_high_u64(m6)); } while(0)\n\n#undef LOAD_MSG_11_2\n#define LOAD_MSG_11_2(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m5), vget_low_u64(m4)); b1 = vextq_u64(m7, m3, 1); } while(0)\n\n#undef LOAD_MSG_11_3\n#define LOAD_MSG_11_3(b0, b1) \\\n  do { b0 = vextq_u64(m0, m0, 1); b1 = vcombine_u64(vget_high_u64(m5), vget_high_u64(m2)); } while(0)\n\n#undef LOAD_MSG_11_4\n#define LOAD_MSG_11_4(b0, b1) \\\n  do { b0 = vcombine_u64(vget_low_u64(m6), vget_low_u64(m1)); b1 = vcombine_u64(vget_high_u64(m3), vget_high_u64(m1)); } while(0)\n\n#define vrorq_n_u64_32(x) vreinterpretq_u64_u32(vrev64q_u32(vreinterpretq_u32_u64((x))))\n\n#define vrorq_n_u64_24(x) vcombine_u64( \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 3)), \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 3)))\n\n#define vrorq_n_u64_16(x) vcombine_u64( \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 2)), \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 2)))\n\n#define vrorq_n_u64_63(x) veorq_u64(vaddq_u64(x, x), vshrq_n_u64(x, 63))\n\n#undef G1\n#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \\\n  do { \\\n    row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \\\n    row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \\\n    row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \\\n    row4l = vrorq_n_u64_32(row4l); row4h = vrorq_n_u64_32(row4h); \\\n    row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \\\n    row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \\\n    row2l = vrorq_n_u64_24(row2l); row2h = vrorq_n_u64_24(row2h); \\\n  } while(0)\n\n#undef G2\n#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \\\n  do { \\\n    row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \\\n    row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \\\n    row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \\\n    row4l = vrorq_n_u64_16(row4l); row4h = vrorq_n_u64_16(row4h); \\\n    row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \\\n    row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \\\n    row2l = vrorq_n_u64_63(row2l); row2h = vrorq_n_u64_63(row2h); \\\n  } while(0)\n\n#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n  do { \\\n    uint64x2_t t0 = vextq_u64(row2l, row2h, 1); \\\n    uint64x2_t t1 = vextq_u64(row2h, row2l, 1); \\\n    row2l = t0; row2h = t1; t0 = row3l;  row3l = row3h; row3h = t0; \\\n    t0 = vextq_u64(row4h, row4l, 1); t1 = vextq_u64(row4l, row4h, 1); \\\n    row4l = t0; row4h = t1; \\\n  } while(0)\n\n#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n  do { \\\n    uint64x2_t t0 = vextq_u64(row2h, row2l, 1); \\\n    uint64x2_t t1 = vextq_u64(row2l, row2h, 1); \\\n    row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \\\n    t0 = vextq_u64(row4l, row4h, 1); t1 = vextq_u64(row4h, row4l, 1); \\\n    row4l = t0; row4h = t1; \\\n  } while(0)\n\n#undef ROUND\n#define ROUND(r) \\\n  do { \\\n    uint64x2_t b0, b1; \\\n    LOAD_MSG_ ##r ##_1(b0, b1); \\\n    G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n    LOAD_MSG_ ##r ##_2(b0, b1); \\\n    G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n    DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \\\n    LOAD_MSG_ ##r ##_3(b0, b1); \\\n    G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n    LOAD_MSG_ ##r ##_4(b0, b1); \\\n    G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n    UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \\\n  } while(0)\n\nstatic void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )\n{\n  const uint64x2_t m0 = vreinterpretq_u64_u8(vld1q_u8(&block[  0]));\n  const uint64x2_t m1 = vreinterpretq_u64_u8(vld1q_u8(&block[ 16]));\n  const uint64x2_t m2 = vreinterpretq_u64_u8(vld1q_u8(&block[ 32]));\n  const uint64x2_t m3 = vreinterpretq_u64_u8(vld1q_u8(&block[ 48]));\n  const uint64x2_t m4 = vreinterpretq_u64_u8(vld1q_u8(&block[ 64]));\n  const uint64x2_t m5 = vreinterpretq_u64_u8(vld1q_u8(&block[ 80]));\n  const uint64x2_t m6 = vreinterpretq_u64_u8(vld1q_u8(&block[ 96]));\n  const uint64x2_t m7 = vreinterpretq_u64_u8(vld1q_u8(&block[112]));\n\n  uint64x2_t row1l, row1h, row2l, row2h;\n  uint64x2_t row3l, row3h, row4l, row4h;\n\n  const uint64x2_t h0 = row1l = vld1q_u64(&S->h[0]);\n  const uint64x2_t h1 = row1h = vld1q_u64(&S->h[2]);\n  const uint64x2_t h2 = row2l = vld1q_u64(&S->h[4]);\n  const uint64x2_t h3 = row2h = vld1q_u64(&S->h[6]);\n\n  row3l = vld1q_u64(&blake2b_IV[0]);\n  row3h = vld1q_u64(&blake2b_IV[2]);\n  row4l = veorq_u64(vld1q_u64(&blake2b_IV[4]), vld1q_u64(&S->t[0]));\n  row4h = veorq_u64(vld1q_u64(&blake2b_IV[6]), vld1q_u64(&S->f[0]));\n\n  ROUND( 0 );\n  ROUND( 1 );\n  ROUND( 2 );\n  ROUND( 3 );\n  ROUND( 4 );\n  ROUND( 5 );\n  ROUND( 6 );\n  ROUND( 7 );\n  ROUND( 8 );\n  ROUND( 9 );\n  ROUND( 10 );\n  ROUND( 11 );\n\n  vst1q_u64(&S->h[0], veorq_u64(h0, veorq_u64(row1l, row3l)));\n  vst1q_u64(&S->h[2], veorq_u64(h1, veorq_u64(row1h, row3h)));\n  vst1q_u64(&S->h[4], veorq_u64(h2, veorq_u64(row2l, row4l)));\n  vst1q_u64(&S->h[6], veorq_u64(h3, veorq_u64(row2h, row4h)));\n}\n\n#undef G\n#undef ROUND\n\nint blake2b_update( blake2b_state *S, const void *pin, size_t inlen )\n{\n  const unsigned char * in = (const unsigned char *)pin;\n  if( inlen > 0 )\n  {\n    size_t left = S->buflen;\n    size_t fill = BLAKE2B_BLOCKBYTES - left;\n    if( inlen > fill )\n    {\n      S->buflen = 0;\n      memcpy( S->buf + left, in, fill ); /* Fill buffer */\n      blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );\n      blake2b_compress( S, S->buf ); /* Compress */\n      in += fill; inlen -= fill;\n      while(inlen > BLAKE2B_BLOCKBYTES) {\n        blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);\n        blake2b_compress( S, in );\n        in += BLAKE2B_BLOCKBYTES;\n        inlen -= BLAKE2B_BLOCKBYTES;\n      }\n    }\n    memcpy( S->buf + S->buflen, in, inlen );\n    S->buflen += inlen;\n  }\n  return 0;\n}\n\nint blake2b_final( blake2b_state *S, void *out, size_t outlen )\n{\n  uint8_t buffer[BLAKE2B_OUTBYTES] = {0};\n  size_t i;\n\n  if( out == NULL || outlen < S->outlen )\n    return -1;\n\n  if( blake2b_is_lastblock( S ) )\n    return -1;\n\n  blake2b_increment_counter( S, S->buflen );\n  blake2b_set_lastblock( S );\n  memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */\n  blake2b_compress( S, S->buf );\n\n  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */\n    store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );\n\n  memcpy( out, buffer, S->outlen );\n  secure_zero_memory(buffer, sizeof(buffer));\n  return 0;\n}\n\n/* inlen, at least, should be uint64_t. Others can be size_t. */\nint blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )\n{\n  blake2b_state S[1];\n\n  /* Verify parameters */\n  if ( NULL == in && inlen > 0 ) return -1;\n\n  if ( NULL == out ) return -1;\n\n  if( NULL == key && keylen > 0 ) return -1;\n\n  if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;\n\n  if( keylen > BLAKE2B_KEYBYTES ) return -1;\n\n  if( keylen > 0 )\n  {\n    if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;\n  }\n  else\n  {\n    if( blake2b_init( S, outlen ) < 0 ) return -1;\n  }\n\n  blake2b_update( S, ( const uint8_t * )in, inlen );\n  blake2b_final( S, out, outlen );\n  return 0;\n}\n\nint blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {\n  return blake2b(out, outlen, in, inlen, key, keylen);\n}\n\n#if defined(SUPERCOP)\nint crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )\n{\n  return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );\n}\n#endif\n\n#if defined(BLAKE2B_SELFTEST)\n#include <string.h>\n#include \"blake2-kat.h\"\nint main( void )\n{\n  uint8_t key[BLAKE2B_KEYBYTES];\n  uint8_t buf[BLAKE2_KAT_LENGTH];\n  size_t i, step;\n\n  for( i = 0; i < BLAKE2B_KEYBYTES; ++i )\n    key[i] = ( uint8_t )i;\n\n  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )\n    buf[i] = ( uint8_t )i;\n\n  /* Test simple API */\n  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )\n  {\n    uint8_t hash[BLAKE2B_OUTBYTES];\n    blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );\n\n    if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )\n    {\n      goto fail;\n    }\n  }\n\n  /* Test streaming API */\n  for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {\n    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {\n      uint8_t hash[BLAKE2B_OUTBYTES];\n      blake2b_state S;\n      uint8_t * p = buf;\n      size_t mlen = i;\n      int err = 0;\n\n      if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {\n        goto fail;\n      }\n\n      while (mlen >= step) {\n        if ( (err = blake2b_update(&S, p, step)) < 0 ) {\n          goto fail;\n        }\n        mlen -= step;\n        p += step;\n      }\n      if ( (err = blake2b_update(&S, p, mlen)) < 0) {\n        goto fail;\n      }\n      if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {\n        goto fail;\n      }\n\n      if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {\n        goto fail;\n      }\n    }\n  }\n\n  puts( \"ok\" );\n  return 0;\nfail:\n  puts(\"error\");\n  return -1;\n}\n#endif\n"
  },
  {
    "path": "third-party/blake2/neon/blake2b-round.h",
    "content": "/*\n   BLAKE2 reference source code package - reference C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2B_ROUND_H\n#define BLAKE2B_ROUND_H\n\n#define vrorq_n_u64_32(x) vreinterpretq_u64_u32(vrev64q_u32(vreinterpretq_u32_u64((x))))\n\n#define vrorq_n_u64_24(x) vcombine_u64( \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 3)), \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 3)))\n\n#define vrorq_n_u64_16(x) vcombine_u64( \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_low_u64(x)), vreinterpret_u8_u64(vget_low_u64(x)), 2)), \\\n      vreinterpret_u64_u8(vext_u8(vreinterpret_u8_u64(vget_high_u64(x)), vreinterpret_u8_u64(vget_high_u64(x)), 2)))\n\n#define vrorq_n_u64_63(x) veorq_u64(vaddq_u64(x, x), vshrq_n_u64(x, 63))\n\n#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \\\n  row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \\\n  row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \\\n  row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \\\n  row4l = vrorq_n_u64_32(row4l); row4h = vrorq_n_u64_32(row4h); \\\n  row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \\\n  row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \\\n  row2l = vrorq_n_u64_24(row2l); row2h = vrorq_n_u64_24(row2h);\n\n#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \\\n  row1l = vaddq_u64(vaddq_u64(row1l, b0), row2l); \\\n  row1h = vaddq_u64(vaddq_u64(row1h, b1), row2h); \\\n  row4l = veorq_u64(row4l, row1l); row4h = veorq_u64(row4h, row1h); \\\n  row4l = vrorq_n_u64_16(row4l); row4h = vrorq_n_u64_16(row4h); \\\n  row3l = vaddq_u64(row3l, row4l); row3h = vaddq_u64(row3h, row4h); \\\n  row2l = veorq_u64(row2l, row3l); row2h = veorq_u64(row2h, row3h); \\\n  row2l = vrorq_n_u64_63(row2l); row2h = vrorq_n_u64_63(row2h);\n\n#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n    t0 = vextq_u64(row2l, row2h, 1); \\\n    t1 = vextq_u64(row2h, row2l, 1); \\\n    row2l = t0; row2h = t1; t0 = row3l;  row3l = row3h; row3h = t0; \\\n    t0 = vextq_u64(row4h, row4l, 1); t1 = vextq_u64(row4l, row4h, 1); \\\n    row4l = t0; row4h = t1;\n\n#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n    t0 = vextq_u64(row2h, row2l, 1); \\\n    t1 = vextq_u64(row2l, row2h, 1); \\\n    row2l = t0; row2h = t1; t0 = row3l; row3l = row3h; row3h = t0; \\\n    t0 = vextq_u64(row4l, row4h, 1); t1 = vextq_u64(row4h, row4l, 1); \\\n    row4l = t0; row4h = t1;\n\n#include \"blake2b-load-neon.h\"\n\n#define ROUND(r) \\\n  LOAD_MSG_ ##r ##_1(b0, b1); \\\n  G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  LOAD_MSG_ ##r ##_2(b0, b1); \\\n  G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \\\n  LOAD_MSG_ ##r ##_3(b0, b1); \\\n  G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  LOAD_MSG_ ##r ##_4(b0, b1); \\\n  G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/neon/blake2b.c",
    "content": "/*\n   BLAKE2 reference source code package - reference C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n\n#include <stdint.h>\n#include <string.h>\n#include <stdio.h>\n#include <arm_neon.h>\n\n#include \"../blake2.h\"\n#include \"../blake2-impl.h\"\n\n#include \"blake2b-round.h\"\n\nstatic const uint64_t blake2b_IV[8] =\n{\n  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,\n  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,\n  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,\n  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL\n};\n\n/* Some helper functions */\nstatic void blake2b_set_lastnode( blake2b_state *S )\n{\n  S->f[1] = (uint64_t)-1;\n}\n\nstatic int blake2b_is_lastblock( const blake2b_state *S )\n{\n  return S->f[0] != 0;\n}\n\nstatic void blake2b_set_lastblock( blake2b_state *S )\n{\n  if( S->last_node ) blake2b_set_lastnode( S );\n\n  S->f[0] = (uint64_t)-1;\n}\n\nstatic void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )\n{\n  S->t[0] += inc;\n  S->t[1] += ( S->t[0] < inc );\n}\n\nstatic void blake2b_init0( blake2b_state *S )\n{\n  size_t i;\n  memset( S, 0, sizeof( blake2b_state ) );\n\n  for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i];\n}\n\n/* init xors IV with input parameter block */\nint blake2b_init_param( blake2b_state *S, const blake2b_param *P )\n{\n  const uint8_t *p = ( const uint8_t * )( P );\n  size_t i;\n\n  blake2b_init0( S );\n\n  /* IV XOR ParamBlock */\n  for( i = 0; i < 8; ++i )\n    S->h[i] ^= load64( p + sizeof( S->h[i] ) * i );\n\n  S->outlen = P->digest_length;\n  return 0;\n}\n\n\n\nint blake2b_init( blake2b_state *S, size_t outlen )\n{\n  blake2b_param P[1];\n\n  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;\n\n  P->digest_length = (uint8_t)outlen;\n  P->key_length    = 0;\n  P->fanout        = 1;\n  P->depth         = 1;\n  store32( &P->leaf_length, 0 );\n  store32( &P->node_offset, 0 );\n  store32( &P->xof_length, 0 );\n  P->node_depth    = 0;\n  P->inner_length  = 0;\n  memset( P->reserved, 0, sizeof( P->reserved ) );\n  memset( P->salt,     0, sizeof( P->salt ) );\n  memset( P->personal, 0, sizeof( P->personal ) );\n  return blake2b_init_param( S, P );\n}\n\n\nint blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )\n{\n  blake2b_param P[1];\n\n  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;\n\n  if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1;\n\n  P->digest_length = (uint8_t)outlen;\n  P->key_length    = (uint8_t)keylen;\n  P->fanout        = 1;\n  P->depth         = 1;\n  store32( &P->leaf_length, 0 );\n  store32( &P->node_offset, 0 );\n  store32( &P->xof_length, 0 );\n  P->node_depth    = 0;\n  P->inner_length  = 0;\n  memset( P->reserved, 0, sizeof( P->reserved ) );\n  memset( P->salt,     0, sizeof( P->salt ) );\n  memset( P->personal, 0, sizeof( P->personal ) );\n\n  if( blake2b_init_param( S, P ) < 0 ) return -1;\n\n  {\n    uint8_t block[BLAKE2B_BLOCKBYTES];\n    memset( block, 0, BLAKE2B_BLOCKBYTES );\n    memcpy( block, key, keylen );\n    blake2b_update( S, block, BLAKE2B_BLOCKBYTES );\n    secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */\n  }\n  return 0;\n}\n\nstatic void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )\n{\n  const uint64x2_t m0 = vreinterpretq_u64_u8(vld1q_u8(&block[  0]));\n  const uint64x2_t m1 = vreinterpretq_u64_u8(vld1q_u8(&block[ 16]));\n  const uint64x2_t m2 = vreinterpretq_u64_u8(vld1q_u8(&block[ 32]));\n  const uint64x2_t m3 = vreinterpretq_u64_u8(vld1q_u8(&block[ 48]));\n  const uint64x2_t m4 = vreinterpretq_u64_u8(vld1q_u8(&block[ 64]));\n  const uint64x2_t m5 = vreinterpretq_u64_u8(vld1q_u8(&block[ 80]));\n  const uint64x2_t m6 = vreinterpretq_u64_u8(vld1q_u8(&block[ 96]));\n  const uint64x2_t m7 = vreinterpretq_u64_u8(vld1q_u8(&block[112]));\n\n  uint64x2_t row1l, row1h, row2l, row2h;\n  uint64x2_t row3l, row3h, row4l, row4h;\n  uint64x2_t t0, t1, b0, b1;\n\n  const uint64x2_t h0 = row1l = vld1q_u64(&S->h[0]);\n  const uint64x2_t h1 = row1h = vld1q_u64(&S->h[2]);\n  const uint64x2_t h2 = row2l = vld1q_u64(&S->h[4]);\n  const uint64x2_t h3 = row2h = vld1q_u64(&S->h[6]);\n\n  row3l = vld1q_u64(&blake2b_IV[0]);\n  row3h = vld1q_u64(&blake2b_IV[2]);\n  row4l = veorq_u64(vld1q_u64(&blake2b_IV[4]), vld1q_u64(&S->t[0]));\n  row4h = veorq_u64(vld1q_u64(&blake2b_IV[6]), vld1q_u64(&S->f[0]));\n\n  ROUND( 0 );\n  ROUND( 1 );\n  ROUND( 2 );\n  ROUND( 3 );\n  ROUND( 4 );\n  ROUND( 5 );\n  ROUND( 6 );\n  ROUND( 7 );\n  ROUND( 8 );\n  ROUND( 9 );\n  ROUND( 10 );\n  ROUND( 11 );\n\n  vst1q_u64(&S->h[0], veorq_u64(h0, veorq_u64(row1l, row3l)));\n  vst1q_u64(&S->h[2], veorq_u64(h1, veorq_u64(row1h, row3h)));\n  vst1q_u64(&S->h[4], veorq_u64(h2, veorq_u64(row2l, row4l)));\n  vst1q_u64(&S->h[6], veorq_u64(h3, veorq_u64(row2h, row4h)));\n}\n\n\nint blake2b_update( blake2b_state *S, const void *pin, size_t inlen )\n{\n  const unsigned char * in = (const unsigned char *)pin;\n  if( inlen > 0 )\n  {\n    size_t left = S->buflen;\n    size_t fill = BLAKE2B_BLOCKBYTES - left;\n    if( inlen > fill )\n    {\n      S->buflen = 0;\n      memcpy( S->buf + left, in, fill ); /* Fill buffer */\n      blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );\n      blake2b_compress( S, S->buf ); /* Compress */\n      in += fill; inlen -= fill;\n      while(inlen > BLAKE2B_BLOCKBYTES) {\n        blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);\n        blake2b_compress( S, in );\n        in += BLAKE2B_BLOCKBYTES;\n        inlen -= BLAKE2B_BLOCKBYTES;\n      }\n    }\n    memcpy( S->buf + S->buflen, in, inlen );\n    S->buflen += inlen;\n  }\n  return 0;\n}\n\nint blake2b_final( blake2b_state *S, void *out, size_t outlen )\n{\n  uint8_t buffer[BLAKE2B_OUTBYTES] = {0};\n  size_t i;\n\n  if( out == NULL || outlen < S->outlen )\n    return -1;\n\n  if( blake2b_is_lastblock( S ) )\n    return -1;\n\n  blake2b_increment_counter( S, S->buflen );\n  blake2b_set_lastblock( S );\n  memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */\n  blake2b_compress( S, S->buf );\n\n  for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */\n    store64( buffer + sizeof( S->h[i] ) * i, S->h[i] );\n\n  memcpy( out, buffer, S->outlen );\n  secure_zero_memory(buffer, sizeof(buffer));\n  return 0;\n}\n\n/* inlen, at least, should be uint64_t. Others can be size_t. */\nint blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )\n{\n  blake2b_state S[1];\n\n  /* Verify parameters */\n  if ( NULL == in && inlen > 0 ) return -1;\n\n  if ( NULL == out ) return -1;\n\n  if( NULL == key && keylen > 0 ) return -1;\n\n  if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;\n\n  if( keylen > BLAKE2B_KEYBYTES ) return -1;\n\n  if( keylen > 0 )\n  {\n    if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;\n  }\n  else\n  {\n    if( blake2b_init( S, outlen ) < 0 ) return -1;\n  }\n\n  blake2b_update( S, ( const uint8_t * )in, inlen );\n  blake2b_final( S, out, outlen );\n  return 0;\n}\n\nint blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {\n  return blake2b(out, outlen, in, inlen, key, keylen);\n}\n\n#if defined(SUPERCOP)\nint crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )\n{\n  return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );\n}\n#endif\n\n#if defined(BLAKE2B_SELFTEST)\n#include <string.h>\n#include \"blake2-kat.h\"\nint main( void )\n{\n  uint8_t key[BLAKE2B_KEYBYTES];\n  uint8_t buf[BLAKE2_KAT_LENGTH];\n  size_t i, step;\n\n  for( i = 0; i < BLAKE2B_KEYBYTES; ++i )\n    key[i] = ( uint8_t )i;\n\n  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )\n    buf[i] = ( uint8_t )i;\n\n  /* Test simple API */\n  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )\n  {\n    uint8_t hash[BLAKE2B_OUTBYTES];\n    blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );\n\n    if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )\n    {\n      goto fail;\n    }\n  }\n\n  /* Test streaming API */\n  for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {\n    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {\n      uint8_t hash[BLAKE2B_OUTBYTES];\n      blake2b_state S;\n      uint8_t * p = buf;\n      size_t mlen = i;\n      int err = 0;\n\n      if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {\n        goto fail;\n      }\n\n      while (mlen >= step) {\n        if ( (err = blake2b_update(&S, p, step)) < 0 ) {\n          goto fail;\n        }\n        mlen -= step;\n        p += step;\n      }\n      if ( (err = blake2b_update(&S, p, mlen)) < 0) {\n        goto fail;\n      }\n      if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {\n        goto fail;\n      }\n\n      if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {\n        goto fail;\n      }\n    }\n  }\n\n  puts( \"ok\" );\n  return 0;\nfail:\n  puts(\"error\");\n  return -1;\n}\n#endif\n"
  },
  {
    "path": "third-party/blake2/sse/blake2-config.h",
    "content": "/*\n   BLAKE2 reference source code package - optimized C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2_CONFIG_H\n#define BLAKE2_CONFIG_H\n\n/* These don't work everywhere */\n#if defined(__SSE2__) || defined(__x86_64__) || defined(__amd64__)\n#define HAVE_SSE2\n#endif\n\n#if defined(__SSSE3__)\n#define HAVE_SSSE3\n#endif\n\n#if defined(__SSE4_1__)\n#define HAVE_SSE41\n#endif\n\n#if defined(__AVX__)\n#define HAVE_AVX\n#endif\n\n#if defined(__XOP__)\n#define HAVE_XOP\n#endif\n\n\n#ifdef HAVE_AVX2\n#ifndef HAVE_AVX\n#define HAVE_AVX\n#endif\n#endif\n\n#ifdef HAVE_XOP\n#ifndef HAVE_AVX\n#define HAVE_AVX\n#endif\n#endif\n\n#ifdef HAVE_AVX\n#ifndef HAVE_SSE41\n#define HAVE_SSE41\n#endif\n#endif\n\n#ifdef HAVE_SSE41\n#ifndef HAVE_SSSE3\n#define HAVE_SSSE3\n#endif\n#endif\n\n#ifdef HAVE_SSSE3\n#define HAVE_SSE2\n#endif\n\n#if !defined(HAVE_SSE2)\n#error \"This code requires at least SSE2.\"\n#endif\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/sse/blake2b-load-sse2.h",
    "content": "/*\n   BLAKE2 reference source code package - optimized C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2B_LOAD_SSE2_H\n#define BLAKE2B_LOAD_SSE2_H\n\n#define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)\n#define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)\n#define LOAD_MSG_0_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12)\n#define LOAD_MSG_0_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13)\n#define LOAD_MSG_1_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9)\n#define LOAD_MSG_1_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15)\n#define LOAD_MSG_1_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11)\n#define LOAD_MSG_1_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7)\n#define LOAD_MSG_2_1(b0, b1) b0 = _mm_set_epi64x(m12, m11); b1 = _mm_set_epi64x(m15, m5)\n#define LOAD_MSG_2_2(b0, b1) b0 = _mm_set_epi64x(m0, m8); b1 = _mm_set_epi64x(m13, m2)\n#define LOAD_MSG_2_3(b0, b1) b0 = _mm_set_epi64x(m3, m10); b1 = _mm_set_epi64x(m9, m7)\n#define LOAD_MSG_2_4(b0, b1) b0 = _mm_set_epi64x(m6, m14); b1 = _mm_set_epi64x(m4, m1)\n#define LOAD_MSG_3_1(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m13)\n#define LOAD_MSG_3_2(b0, b1) b0 = _mm_set_epi64x(m1, m9); b1 = _mm_set_epi64x(m14, m12)\n#define LOAD_MSG_3_3(b0, b1) b0 = _mm_set_epi64x(m5, m2); b1 = _mm_set_epi64x(m15, m4)\n#define LOAD_MSG_3_4(b0, b1) b0 = _mm_set_epi64x(m10, m6); b1 = _mm_set_epi64x(m8, m0)\n#define LOAD_MSG_4_1(b0, b1) b0 = _mm_set_epi64x(m5, m9); b1 = _mm_set_epi64x(m10, m2)\n#define LOAD_MSG_4_2(b0, b1) b0 = _mm_set_epi64x(m7, m0); b1 = _mm_set_epi64x(m15, m4)\n#define LOAD_MSG_4_3(b0, b1) b0 = _mm_set_epi64x(m11, m14); b1 = _mm_set_epi64x(m3, m6)\n#define LOAD_MSG_4_4(b0, b1) b0 = _mm_set_epi64x(m12, m1); b1 = _mm_set_epi64x(m13, m8)\n#define LOAD_MSG_5_1(b0, b1) b0 = _mm_set_epi64x(m6, m2); b1 = _mm_set_epi64x(m8, m0)\n#define LOAD_MSG_5_2(b0, b1) b0 = _mm_set_epi64x(m10, m12); b1 = _mm_set_epi64x(m3, m11)\n#define LOAD_MSG_5_3(b0, b1) b0 = _mm_set_epi64x(m7, m4); b1 = _mm_set_epi64x(m1, m15)\n#define LOAD_MSG_5_4(b0, b1) b0 = _mm_set_epi64x(m5, m13); b1 = _mm_set_epi64x(m9, m14)\n#define LOAD_MSG_6_1(b0, b1) b0 = _mm_set_epi64x(m1, m12); b1 = _mm_set_epi64x(m4, m14)\n#define LOAD_MSG_6_2(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m10, m13)\n#define LOAD_MSG_6_3(b0, b1) b0 = _mm_set_epi64x(m6, m0); b1 = _mm_set_epi64x(m8, m9)\n#define LOAD_MSG_6_4(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m2)\n#define LOAD_MSG_7_1(b0, b1) b0 = _mm_set_epi64x(m7, m13); b1 = _mm_set_epi64x(m3, m12)\n#define LOAD_MSG_7_2(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m9, m1)\n#define LOAD_MSG_7_3(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m2, m8)\n#define LOAD_MSG_7_4(b0, b1) b0 = _mm_set_epi64x(m4, m0); b1 = _mm_set_epi64x(m10, m6)\n#define LOAD_MSG_8_1(b0, b1) b0 = _mm_set_epi64x(m14, m6); b1 = _mm_set_epi64x(m0, m11)\n#define LOAD_MSG_8_2(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m8, m3)\n#define LOAD_MSG_8_3(b0, b1) b0 = _mm_set_epi64x(m13, m12); b1 = _mm_set_epi64x(m10, m1)\n#define LOAD_MSG_8_4(b0, b1) b0 = _mm_set_epi64x(m7, m2); b1 = _mm_set_epi64x(m5, m4)\n#define LOAD_MSG_9_1(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m1, m7)\n#define LOAD_MSG_9_2(b0, b1) b0 = _mm_set_epi64x(m4, m2); b1 = _mm_set_epi64x(m5, m6)\n#define LOAD_MSG_9_3(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m13, m3)\n#define LOAD_MSG_9_4(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m0, m12)\n#define LOAD_MSG_10_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4)\n#define LOAD_MSG_10_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5)\n#define LOAD_MSG_10_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12)\n#define LOAD_MSG_10_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13)\n#define LOAD_MSG_11_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9)\n#define LOAD_MSG_11_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15)\n#define LOAD_MSG_11_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11)\n#define LOAD_MSG_11_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7)\n\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/sse/blake2b-load-sse41.h",
    "content": "/*\n   BLAKE2 reference source code package - optimized C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2B_LOAD_SSE41_H\n#define BLAKE2B_LOAD_SSE41_H\n\n#define LOAD_MSG_0_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m0, m1); \\\nb1 = _mm_unpacklo_epi64(m2, m3); \\\n} while(0)\n\n\n#define LOAD_MSG_0_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m0, m1); \\\nb1 = _mm_unpackhi_epi64(m2, m3); \\\n} while(0)\n\n\n#define LOAD_MSG_0_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m4, m5); \\\nb1 = _mm_unpacklo_epi64(m6, m7); \\\n} while(0)\n\n\n#define LOAD_MSG_0_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m4, m5); \\\nb1 = _mm_unpackhi_epi64(m6, m7); \\\n} while(0)\n\n\n#define LOAD_MSG_1_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m7, m2); \\\nb1 = _mm_unpackhi_epi64(m4, m6); \\\n} while(0)\n\n\n#define LOAD_MSG_1_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m5, m4); \\\nb1 = _mm_alignr_epi8(m3, m7, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_1_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \\\nb1 = _mm_unpackhi_epi64(m5, m2); \\\n} while(0)\n\n\n#define LOAD_MSG_1_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m6, m1); \\\nb1 = _mm_unpackhi_epi64(m3, m1); \\\n} while(0)\n\n\n#define LOAD_MSG_2_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_alignr_epi8(m6, m5, 8); \\\nb1 = _mm_unpackhi_epi64(m2, m7); \\\n} while(0)\n\n\n#define LOAD_MSG_2_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m4, m0); \\\nb1 = _mm_blend_epi16(m1, m6, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_2_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m5, m1, 0xF0); \\\nb1 = _mm_unpackhi_epi64(m3, m4); \\\n} while(0)\n\n\n#define LOAD_MSG_2_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m7, m3); \\\nb1 = _mm_alignr_epi8(m2, m0, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_3_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m3, m1); \\\nb1 = _mm_unpackhi_epi64(m6, m5); \\\n} while(0)\n\n\n#define LOAD_MSG_3_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m4, m0); \\\nb1 = _mm_unpacklo_epi64(m6, m7); \\\n} while(0)\n\n\n#define LOAD_MSG_3_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m1, m2, 0xF0); \\\nb1 = _mm_blend_epi16(m2, m7, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_3_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m3, m5); \\\nb1 = _mm_unpacklo_epi64(m0, m4); \\\n} while(0)\n\n\n#define LOAD_MSG_4_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m4, m2); \\\nb1 = _mm_unpacklo_epi64(m1, m5); \\\n} while(0)\n\n\n#define LOAD_MSG_4_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m0, m3, 0xF0); \\\nb1 = _mm_blend_epi16(m2, m7, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_4_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m7, m5, 0xF0); \\\nb1 = _mm_blend_epi16(m3, m1, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_4_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_alignr_epi8(m6, m0, 8); \\\nb1 = _mm_blend_epi16(m4, m6, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_5_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m1, m3); \\\nb1 = _mm_unpacklo_epi64(m0, m4); \\\n} while(0)\n\n\n#define LOAD_MSG_5_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m6, m5); \\\nb1 = _mm_unpackhi_epi64(m5, m1); \\\n} while(0)\n\n\n#define LOAD_MSG_5_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m2, m3, 0xF0); \\\nb1 = _mm_unpackhi_epi64(m7, m0); \\\n} while(0)\n\n\n#define LOAD_MSG_5_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m6, m2); \\\nb1 = _mm_blend_epi16(m7, m4, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_6_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m6, m0, 0xF0); \\\nb1 = _mm_unpacklo_epi64(m7, m2); \\\n} while(0)\n\n\n#define LOAD_MSG_6_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m2, m7); \\\nb1 = _mm_alignr_epi8(m5, m6, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_6_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m0, m3); \\\nb1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2)); \\\n} while(0)\n\n\n#define LOAD_MSG_6_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m3, m1); \\\nb1 = _mm_blend_epi16(m1, m5, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_7_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m6, m3); \\\nb1 = _mm_blend_epi16(m6, m1, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_7_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_alignr_epi8(m7, m5, 8); \\\nb1 = _mm_unpackhi_epi64(m0, m4); \\\n} while(0)\n\n\n#define LOAD_MSG_7_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m2, m7); \\\nb1 = _mm_unpacklo_epi64(m4, m1); \\\n} while(0)\n\n\n#define LOAD_MSG_7_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m0, m2); \\\nb1 = _mm_unpacklo_epi64(m3, m5); \\\n} while(0)\n\n\n#define LOAD_MSG_8_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m3, m7); \\\nb1 = _mm_alignr_epi8(m0, m5, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_8_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m7, m4); \\\nb1 = _mm_alignr_epi8(m4, m1, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_8_3(b0, b1) \\\ndo \\\n{ \\\nb0 = m6; \\\nb1 = _mm_alignr_epi8(m5, m0, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_8_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_blend_epi16(m1, m3, 0xF0); \\\nb1 = m2; \\\n} while(0)\n\n\n#define LOAD_MSG_9_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m5, m4); \\\nb1 = _mm_unpackhi_epi64(m3, m0); \\\n} while(0)\n\n\n#define LOAD_MSG_9_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m1, m2); \\\nb1 = _mm_blend_epi16(m3, m2, 0xF0); \\\n} while(0)\n\n\n#define LOAD_MSG_9_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m7, m4); \\\nb1 = _mm_unpackhi_epi64(m1, m6); \\\n} while(0)\n\n\n#define LOAD_MSG_9_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_alignr_epi8(m7, m5, 8); \\\nb1 = _mm_unpacklo_epi64(m6, m0); \\\n} while(0)\n\n\n#define LOAD_MSG_10_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m0, m1); \\\nb1 = _mm_unpacklo_epi64(m2, m3); \\\n} while(0)\n\n\n#define LOAD_MSG_10_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m0, m1); \\\nb1 = _mm_unpackhi_epi64(m2, m3); \\\n} while(0)\n\n\n#define LOAD_MSG_10_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m4, m5); \\\nb1 = _mm_unpacklo_epi64(m6, m7); \\\n} while(0)\n\n\n#define LOAD_MSG_10_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpackhi_epi64(m4, m5); \\\nb1 = _mm_unpackhi_epi64(m6, m7); \\\n} while(0)\n\n\n#define LOAD_MSG_11_1(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m7, m2); \\\nb1 = _mm_unpackhi_epi64(m4, m6); \\\n} while(0)\n\n\n#define LOAD_MSG_11_2(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m5, m4); \\\nb1 = _mm_alignr_epi8(m3, m7, 8); \\\n} while(0)\n\n\n#define LOAD_MSG_11_3(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \\\nb1 = _mm_unpackhi_epi64(m5, m2); \\\n} while(0)\n\n\n#define LOAD_MSG_11_4(b0, b1) \\\ndo \\\n{ \\\nb0 = _mm_unpacklo_epi64(m6, m1); \\\nb1 = _mm_unpackhi_epi64(m3, m1); \\\n} while(0)\n\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/sse/blake2b-round.h",
    "content": "/*\n   BLAKE2 reference source code package - optimized C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n#ifndef BLAKE2B_ROUND_H\n#define BLAKE2B_ROUND_H\n\n#define LOADU(p)  _mm_loadu_si128( (const __m128i *)(p) )\n#define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r)\n\n#define TOF(reg) _mm_castsi128_ps((reg))\n#define TOI(reg) _mm_castps_si128((reg))\n\n#define LIKELY(x) __builtin_expect((x),1)\n\n\n/* Microarchitecture-specific macros */\n#ifndef HAVE_XOP\n#ifdef HAVE_SSSE3\n#define _mm_roti_epi64(x, c) \\\n    (-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1))  \\\n    : (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \\\n    : (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \\\n    : (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x)))  \\\n    : _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c))))\n#else\n#define _mm_roti_epi64(r, c) _mm_xor_si128(_mm_srli_epi64( (r), -(c) ),_mm_slli_epi64( (r), 64-(-(c)) ))\n#endif\n#else\n/* ... */\n#endif\n\n\n\n#define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \\\n  row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \\\n  row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \\\n  \\\n  row4l = _mm_xor_si128(row4l, row1l); \\\n  row4h = _mm_xor_si128(row4h, row1h); \\\n  \\\n  row4l = _mm_roti_epi64(row4l, -32); \\\n  row4h = _mm_roti_epi64(row4h, -32); \\\n  \\\n  row3l = _mm_add_epi64(row3l, row4l); \\\n  row3h = _mm_add_epi64(row3h, row4h); \\\n  \\\n  row2l = _mm_xor_si128(row2l, row3l); \\\n  row2h = _mm_xor_si128(row2h, row3h); \\\n  \\\n  row2l = _mm_roti_epi64(row2l, -24); \\\n  row2h = _mm_roti_epi64(row2h, -24); \\\n\n#define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \\\n  row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \\\n  row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \\\n  \\\n  row4l = _mm_xor_si128(row4l, row1l); \\\n  row4h = _mm_xor_si128(row4h, row1h); \\\n  \\\n  row4l = _mm_roti_epi64(row4l, -16); \\\n  row4h = _mm_roti_epi64(row4h, -16); \\\n  \\\n  row3l = _mm_add_epi64(row3l, row4l); \\\n  row3h = _mm_add_epi64(row3h, row4h); \\\n  \\\n  row2l = _mm_xor_si128(row2l, row3l); \\\n  row2h = _mm_xor_si128(row2h, row3h); \\\n  \\\n  row2l = _mm_roti_epi64(row2l, -63); \\\n  row2h = _mm_roti_epi64(row2h, -63); \\\n\n#if defined(HAVE_SSSE3)\n#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n  t0 = _mm_alignr_epi8(row2h, row2l, 8); \\\n  t1 = _mm_alignr_epi8(row2l, row2h, 8); \\\n  row2l = t0; \\\n  row2h = t1; \\\n  \\\n  t0 = row3l; \\\n  row3l = row3h; \\\n  row3h = t0;    \\\n  \\\n  t0 = _mm_alignr_epi8(row4h, row4l, 8); \\\n  t1 = _mm_alignr_epi8(row4l, row4h, 8); \\\n  row4l = t1; \\\n  row4h = t0;\n\n#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n  t0 = _mm_alignr_epi8(row2l, row2h, 8); \\\n  t1 = _mm_alignr_epi8(row2h, row2l, 8); \\\n  row2l = t0; \\\n  row2h = t1; \\\n  \\\n  t0 = row3l; \\\n  row3l = row3h; \\\n  row3h = t0; \\\n  \\\n  t0 = _mm_alignr_epi8(row4l, row4h, 8); \\\n  t1 = _mm_alignr_epi8(row4h, row4l, 8); \\\n  row4l = t1; \\\n  row4h = t0;\n#else\n\n#define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n  t0 = row4l;\\\n  t1 = row2l;\\\n  row4l = row3l;\\\n  row3l = row3h;\\\n  row3h = row4l;\\\n  row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \\\n  row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \\\n  row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \\\n  row2h = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(t1, t1))\n\n#define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \\\n  t0 = row3l;\\\n  row3l = row3h;\\\n  row3h = t0;\\\n  t0 = row2l;\\\n  t1 = row4l;\\\n  row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \\\n  row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \\\n  row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \\\n  row4h = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t1, t1))\n\n#endif\n\n#if defined(HAVE_SSE41)\n#include \"blake2b-load-sse41.h\"\n#else\n#include \"blake2b-load-sse2.h\"\n#endif\n\n#define ROUND(r) \\\n  LOAD_MSG_ ##r ##_1(b0, b1); \\\n  G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  LOAD_MSG_ ##r ##_2(b0, b1); \\\n  G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \\\n  LOAD_MSG_ ##r ##_3(b0, b1); \\\n  G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  LOAD_MSG_ ##r ##_4(b0, b1); \\\n  G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \\\n  UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h);\n\n#endif\n"
  },
  {
    "path": "third-party/blake2/sse/blake2b.c",
    "content": "/*\n   BLAKE2 reference source code package - optimized C implementations\n\n   Copyright 2012, Samuel Neves <sneves@dei.uc.pt>.  You may use this under the\n   terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at\n   your option.  The terms of these licenses can be found at:\n\n   - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0\n   - OpenSSL license   : https://www.openssl.org/source/license.html\n   - Apache 2.0        : http://www.apache.org/licenses/LICENSE-2.0\n\n   More information about the BLAKE2 hash function can be found at\n   https://blake2.net.\n*/\n\n#include <stdint.h>\n#include <string.h>\n#include <stdio.h>\n\n#include \"../blake2.h\"\n#include \"../blake2-impl.h\"\n\n#include \"blake2-config.h\"\n\n#ifdef _MSC_VER\n#include <intrin.h> /* for _mm_set_epi64x */\n#endif\n#include <emmintrin.h>\n#if defined(HAVE_SSSE3)\n#include <tmmintrin.h>\n#endif\n#if defined(HAVE_SSE41)\n#include <smmintrin.h>\n#endif\n#if defined(HAVE_AVX)\n#include <immintrin.h>\n#endif\n#if defined(HAVE_XOP)\n#include <x86intrin.h>\n#endif\n\n#include \"blake2b-round.h\"\n\nstatic const uint64_t blake2b_IV[8] =\n{\n  0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,\n  0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,\n  0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,\n  0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL\n};\n\n/* Some helper functions */\nstatic void blake2b_set_lastnode( blake2b_state *S )\n{\n  S->f[1] = (uint64_t)-1;\n}\n\nstatic int blake2b_is_lastblock( const blake2b_state *S )\n{\n  return S->f[0] != 0;\n}\n\nstatic void blake2b_set_lastblock( blake2b_state *S )\n{\n  if( S->last_node ) blake2b_set_lastnode( S );\n\n  S->f[0] = (uint64_t)-1;\n}\n\nstatic void blake2b_increment_counter( blake2b_state *S, const uint64_t inc )\n{\n  S->t[0] += inc;\n  S->t[1] += ( S->t[0] < inc );\n}\n\n/* init xors IV with input parameter block */\nint blake2b_init_param( blake2b_state *S, const blake2b_param *P )\n{\n  size_t i;\n  /*blake2b_init0( S ); */\n  const unsigned char * v = ( const unsigned char * )( blake2b_IV );\n  const unsigned char * p = ( const unsigned char * )( P );\n  unsigned char * h = ( unsigned char * )( S->h );\n  /* IV XOR ParamBlock */\n  memset( S, 0, sizeof( blake2b_state ) );\n\n  for( i = 0; i < BLAKE2B_OUTBYTES; ++i ) h[i] = v[i] ^ p[i];\n\n  S->outlen = P->digest_length;\n  return 0;\n}\n\n\n/* Some sort of default parameter block initialization, for sequential blake2b */\nint blake2b_init( blake2b_state *S, size_t outlen )\n{\n  blake2b_param P[1];\n\n  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;\n\n  P->digest_length = (uint8_t)outlen;\n  P->key_length    = 0;\n  P->fanout        = 1;\n  P->depth         = 1;\n  store32( &P->leaf_length, 0 );\n  store32( &P->node_offset, 0 );\n  store32( &P->xof_length, 0 );\n  P->node_depth    = 0;\n  P->inner_length  = 0;\n  memset( P->reserved, 0, sizeof( P->reserved ) );\n  memset( P->salt,     0, sizeof( P->salt ) );\n  memset( P->personal, 0, sizeof( P->personal ) );\n\n  return blake2b_init_param( S, P );\n}\n\nint blake2b_init_key( blake2b_state *S, size_t outlen, const void *key, size_t keylen )\n{\n  blake2b_param P[1];\n\n  if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1;\n\n  if ( ( !keylen ) || keylen > BLAKE2B_KEYBYTES ) return -1;\n\n  P->digest_length = (uint8_t)outlen;\n  P->key_length    = (uint8_t)keylen;\n  P->fanout        = 1;\n  P->depth         = 1;\n  store32( &P->leaf_length, 0 );\n  store32( &P->node_offset, 0 );\n  store32( &P->xof_length, 0 );\n  P->node_depth    = 0;\n  P->inner_length  = 0;\n  memset( P->reserved, 0, sizeof( P->reserved ) );\n  memset( P->salt,     0, sizeof( P->salt ) );\n  memset( P->personal, 0, sizeof( P->personal ) );\n\n  if( blake2b_init_param( S, P ) < 0 )\n    return 0;\n\n  {\n    uint8_t block[BLAKE2B_BLOCKBYTES];\n    memset( block, 0, BLAKE2B_BLOCKBYTES );\n    memcpy( block, key, keylen );\n    blake2b_update( S, block, BLAKE2B_BLOCKBYTES );\n    secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */\n  }\n  return 0;\n}\n\nstatic void blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] )\n{\n  __m128i row1l, row1h;\n  __m128i row2l, row2h;\n  __m128i row3l, row3h;\n  __m128i row4l, row4h;\n  __m128i b0, b1;\n  __m128i t0, t1;\n#if defined(HAVE_SSSE3) && !defined(HAVE_XOP)\n  const __m128i r16 = _mm_setr_epi8( 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9 );\n  const __m128i r24 = _mm_setr_epi8( 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10 );\n#endif\n#if defined(HAVE_SSE41)\n  const __m128i m0 = LOADU( block + 00 );\n  const __m128i m1 = LOADU( block + 16 );\n  const __m128i m2 = LOADU( block + 32 );\n  const __m128i m3 = LOADU( block + 48 );\n  const __m128i m4 = LOADU( block + 64 );\n  const __m128i m5 = LOADU( block + 80 );\n  const __m128i m6 = LOADU( block + 96 );\n  const __m128i m7 = LOADU( block + 112 );\n#else\n  const uint64_t  m0 = load64(block +  0 * sizeof(uint64_t));\n  const uint64_t  m1 = load64(block +  1 * sizeof(uint64_t));\n  const uint64_t  m2 = load64(block +  2 * sizeof(uint64_t));\n  const uint64_t  m3 = load64(block +  3 * sizeof(uint64_t));\n  const uint64_t  m4 = load64(block +  4 * sizeof(uint64_t));\n  const uint64_t  m5 = load64(block +  5 * sizeof(uint64_t));\n  const uint64_t  m6 = load64(block +  6 * sizeof(uint64_t));\n  const uint64_t  m7 = load64(block +  7 * sizeof(uint64_t));\n  const uint64_t  m8 = load64(block +  8 * sizeof(uint64_t));\n  const uint64_t  m9 = load64(block +  9 * sizeof(uint64_t));\n  const uint64_t m10 = load64(block + 10 * sizeof(uint64_t));\n  const uint64_t m11 = load64(block + 11 * sizeof(uint64_t));\n  const uint64_t m12 = load64(block + 12 * sizeof(uint64_t));\n  const uint64_t m13 = load64(block + 13 * sizeof(uint64_t));\n  const uint64_t m14 = load64(block + 14 * sizeof(uint64_t));\n  const uint64_t m15 = load64(block + 15 * sizeof(uint64_t));\n#endif\n  row1l = LOADU( &S->h[0] );\n  row1h = LOADU( &S->h[2] );\n  row2l = LOADU( &S->h[4] );\n  row2h = LOADU( &S->h[6] );\n  row3l = LOADU( &blake2b_IV[0] );\n  row3h = LOADU( &blake2b_IV[2] );\n  row4l = _mm_xor_si128( LOADU( &blake2b_IV[4] ), LOADU( &S->t[0] ) );\n  row4h = _mm_xor_si128( LOADU( &blake2b_IV[6] ), LOADU( &S->f[0] ) );\n  ROUND( 0 );\n  ROUND( 1 );\n  ROUND( 2 );\n  ROUND( 3 );\n  ROUND( 4 );\n  ROUND( 5 );\n  ROUND( 6 );\n  ROUND( 7 );\n  ROUND( 8 );\n  ROUND( 9 );\n  ROUND( 10 );\n  ROUND( 11 );\n  row1l = _mm_xor_si128( row3l, row1l );\n  row1h = _mm_xor_si128( row3h, row1h );\n  STOREU( &S->h[0], _mm_xor_si128( LOADU( &S->h[0] ), row1l ) );\n  STOREU( &S->h[2], _mm_xor_si128( LOADU( &S->h[2] ), row1h ) );\n  row2l = _mm_xor_si128( row4l, row2l );\n  row2h = _mm_xor_si128( row4h, row2h );\n  STOREU( &S->h[4], _mm_xor_si128( LOADU( &S->h[4] ), row2l ) );\n  STOREU( &S->h[6], _mm_xor_si128( LOADU( &S->h[6] ), row2h ) );\n}\n\n\nint blake2b_update( blake2b_state *S, const void *pin, size_t inlen )\n{\n  const unsigned char * in = (const unsigned char *)pin;\n  if( inlen > 0 )\n  {\n    size_t left = S->buflen;\n    size_t fill = BLAKE2B_BLOCKBYTES - left;\n    if( inlen > fill )\n    {\n      S->buflen = 0;\n      memcpy( S->buf + left, in, fill ); /* Fill buffer */\n      blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES );\n      blake2b_compress( S, S->buf ); /* Compress */\n      in += fill; inlen -= fill;\n      while(inlen > BLAKE2B_BLOCKBYTES) {\n        blake2b_increment_counter(S, BLAKE2B_BLOCKBYTES);\n        blake2b_compress( S, in );\n        in += BLAKE2B_BLOCKBYTES;\n        inlen -= BLAKE2B_BLOCKBYTES;\n      }\n    }\n    memcpy( S->buf + S->buflen, in, inlen );\n    S->buflen += inlen;\n  }\n  return 0;\n}\n\n\nint blake2b_final( blake2b_state *S, void *out, size_t outlen )\n{\n  if( out == NULL || outlen < S->outlen )\n    return -1;\n\n  if( blake2b_is_lastblock( S ) )\n    return -1;\n\n  blake2b_increment_counter( S, S->buflen );\n  blake2b_set_lastblock( S );\n  memset( S->buf + S->buflen, 0, BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */\n  blake2b_compress( S, S->buf );\n\n  memcpy( out, &S->h[0], S->outlen );\n  return 0;\n}\n\n\nint blake2b( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen )\n{\n  blake2b_state S[1];\n\n  /* Verify parameters */\n  if ( NULL == in && inlen > 0 ) return -1;\n\n  if ( NULL == out ) return -1;\n\n  if( NULL == key && keylen > 0 ) return -1;\n\n  if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1;\n\n  if( keylen > BLAKE2B_KEYBYTES ) return -1;\n\n  if( keylen )\n  {\n    if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1;\n  }\n  else\n  {\n    if( blake2b_init( S, outlen ) < 0 ) return -1;\n  }\n\n  blake2b_update( S, ( const uint8_t * )in, inlen );\n  blake2b_final( S, out, outlen );\n  return 0;\n}\n\nint blake2( void *out, size_t outlen, const void *in, size_t inlen, const void *key, size_t keylen ) {\n  return blake2b(out, outlen, in, inlen, key, keylen);\n}\n\n#if defined(SUPERCOP)\nint crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen )\n{\n  return blake2b( out, BLAKE2B_OUTBYTES, in, inlen, NULL, 0 );\n}\n#endif\n\n#if defined(BLAKE2B_SELFTEST)\n#include <string.h>\n#include \"blake2-kat.h\"\nint main( void )\n{\n  uint8_t key[BLAKE2B_KEYBYTES];\n  uint8_t buf[BLAKE2_KAT_LENGTH];\n  size_t i, step;\n\n  for( i = 0; i < BLAKE2B_KEYBYTES; ++i )\n    key[i] = ( uint8_t )i;\n\n  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )\n    buf[i] = ( uint8_t )i;\n\n  /* Test simple API */\n  for( i = 0; i < BLAKE2_KAT_LENGTH; ++i )\n  {\n    uint8_t hash[BLAKE2B_OUTBYTES];\n    blake2b( hash, BLAKE2B_OUTBYTES, buf, i, key, BLAKE2B_KEYBYTES );\n\n    if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) )\n    {\n      goto fail;\n    }\n  }\n\n  /* Test streaming API */\n  for(step = 1; step < BLAKE2B_BLOCKBYTES; ++step) {\n    for (i = 0; i < BLAKE2_KAT_LENGTH; ++i) {\n      uint8_t hash[BLAKE2B_OUTBYTES];\n      blake2b_state S;\n      uint8_t * p = buf;\n      size_t mlen = i;\n      int err = 0;\n\n      if( (err = blake2b_init_key(&S, BLAKE2B_OUTBYTES, key, BLAKE2B_KEYBYTES)) < 0 ) {\n        goto fail;\n      }\n\n      while (mlen >= step) {\n        if ( (err = blake2b_update(&S, p, step)) < 0 ) {\n          goto fail;\n        }\n        mlen -= step;\n        p += step;\n      }\n      if ( (err = blake2b_update(&S, p, mlen)) < 0) {\n        goto fail;\n      }\n      if ( (err = blake2b_final(&S, hash, BLAKE2B_OUTBYTES)) < 0) {\n        goto fail;\n      }\n\n      if (0 != memcmp(hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES)) {\n        goto fail;\n      }\n    }\n  }\n\n  puts( \"ok\" );\n  return 0;\nfail:\n  puts(\"error\");\n  return -1;\n}\n#endif\n"
  },
  {
    "path": "third-party/brotli/README.md",
    "content": "### Origin and License\n\nTaken verbatim from https://github.com/google/brotli/commit/c1bd196833e4ce05ef49b82ec5e124bb79e095ff\nbelow \"c\", with the exception of this file and removal of the directories \"fuzz\" and \"tools\".\n\nSources are under an MIT-style license. Also, Google has made a RF commitment here:\nhttps://datatracker.ietf.org/ipr/2396\nExcerpt:\n\"In addition, to facilitate the use of the Brotli Compression Algorithm in\nother applications, Google hereby provides a W3C RF commitment (that is not\nlimited to font data) to the Brotli Compression Algorithm specification\nlinked above and, if that specification leads to a final IETF RFC for\nBrotli, then to the specification in that RFC.\"\n\n\n### Introduction to Brotli\n\nBrotli is a generic-purpose lossless compression algorithm that compresses data\nusing a combination of a modern variant of the LZ77 algorithm, Huffman coding\nand 2nd order context modeling, with a compression ratio comparable to the best\ncurrently available general-purpose compression methods. It is similar in speed\nwith deflate but offers more dense compression.\n\nThe specification of the Brotli Compressed Data Format is defined in [RFC 7932](https://tools.ietf.org/html/rfc7932).\n\nBrotli is open-sourced under the MIT License, see the LICENSE file.\n\n> **Please note:** brotli is a \"stream\" format; it does not contain\n> meta-information, like checksums or uncompresssed data length. It is possible\n> to modify \"raw\" ranges of the compressed stream and the decoder will not\n> notice that.\n"
  },
  {
    "path": "third-party/brotli/common/constants.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"constants.h\"\n\nconst BrotliPrefixCodeRange\n    _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS] = {\n        {1, 2},     {5, 2},     {9, 2},   {13, 2},    {17, 3},    {25, 3},\n        {33, 3},    {41, 3},    {49, 4},  {65, 4},    {81, 4},    {97, 4},\n        {113, 5},   {145, 5},   {177, 5}, {209, 5},   {241, 6},   {305, 6},\n        {369, 7},   {497, 8},   {753, 9}, {1265, 10}, {2289, 11}, {4337, 12},\n        {8433, 13}, {16625, 24}};\n"
  },
  {
    "path": "third-party/brotli/common/constants.h",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * Common constants used in decoder and encoder API.\n */\n\n#ifndef BROTLI_COMMON_CONSTANTS_H_\n#define BROTLI_COMMON_CONSTANTS_H_\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\n#include \"platform.h\"\n\n/* Specification: 7.3. Encoding of the context map */\n#define BROTLI_CONTEXT_MAP_MAX_RLE 16\n\n/* Specification: 2. Compressed representation overview */\n#define BROTLI_MAX_NUMBER_OF_BLOCK_TYPES 256\n\n/* Specification: 3.3. Alphabet sizes: insert-and-copy length */\n#define BROTLI_NUM_LITERAL_SYMBOLS 256\n#define BROTLI_NUM_COMMAND_SYMBOLS 704\n#define BROTLI_NUM_BLOCK_LEN_SYMBOLS 26\n#define BROTLI_MAX_CONTEXT_MAP_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + \\\n                                        BROTLI_CONTEXT_MAP_MAX_RLE)\n#define BROTLI_MAX_BLOCK_TYPE_SYMBOLS (BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 2)\n\n/* Specification: 3.5. Complex prefix codes */\n#define BROTLI_REPEAT_PREVIOUS_CODE_LENGTH 16\n#define BROTLI_REPEAT_ZERO_CODE_LENGTH 17\n#define BROTLI_CODE_LENGTH_CODES (BROTLI_REPEAT_ZERO_CODE_LENGTH + 1)\n/* \"code length of 8 is repeated\" */\n#define BROTLI_INITIAL_REPEATED_CODE_LENGTH 8\n\n/* \"Large Window Brotli\" */\n\n/**\n * The theoretical maximum number of distance bits specified for large window\n * brotli, for 64-bit encoders and decoders. Even when in practice 32-bit\n * encoders and decoders only support up to 30 max distance bits, the value is\n * set to 62 because it affects the large window brotli file format.\n * Specifically, it affects the encoding of simple huffman tree for distances,\n * see Specification RFC 7932 chapter 3.4.\n */\n#define BROTLI_LARGE_MAX_DISTANCE_BITS 62U\n#define BROTLI_LARGE_MIN_WBITS 10\n/**\n * The maximum supported large brotli window bits by the encoder and decoder.\n * Large window brotli allows up to 62 bits, however the current encoder and\n * decoder, designed for 32-bit integers, only support up to 30 bits maximum.\n */\n#define BROTLI_LARGE_MAX_WBITS 30\n\n/* Specification: 4. Encoding of distances */\n#define BROTLI_NUM_DISTANCE_SHORT_CODES 16\n/**\n * Maximal number of \"postfix\" bits.\n *\n * Number of \"postfix\" bits is stored as 2 bits in meta-block header.\n */\n#define BROTLI_MAX_NPOSTFIX 3\n#define BROTLI_MAX_NDIRECT 120\n#define BROTLI_MAX_DISTANCE_BITS 24U\n#define BROTLI_DISTANCE_ALPHABET_SIZE(NPOSTFIX, NDIRECT, MAXNBITS) ( \\\n    BROTLI_NUM_DISTANCE_SHORT_CODES + (NDIRECT) +                    \\\n    ((MAXNBITS) << ((NPOSTFIX) + 1)))\n/* BROTLI_NUM_DISTANCE_SYMBOLS == 1128 */\n#define BROTLI_NUM_DISTANCE_SYMBOLS \\\n    BROTLI_DISTANCE_ALPHABET_SIZE(  \\\n        BROTLI_MAX_NDIRECT, BROTLI_MAX_NPOSTFIX, BROTLI_LARGE_MAX_DISTANCE_BITS)\n\n/* ((1 << 26) - 4) is the maximal distance that can be expressed in RFC 7932\n   brotli stream using NPOSTFIX = 0 and NDIRECT = 0. With other NPOSTFIX and\n   NDIRECT values distances up to ((1 << 29) + 88) could be expressed. */\n#define BROTLI_MAX_DISTANCE 0x3FFFFFC\n\n/* ((1 << 31) - 4) is the safe distance limit. Using this number as a limit\n   allows safe distance calculation without overflows, given the distance\n   alphabet size is limited to corresponding size\n   (see kLargeWindowDistanceCodeLimits). */\n#define BROTLI_MAX_ALLOWED_DISTANCE 0x7FFFFFFC\n\n\n/* Specification: 4. Encoding of Literal Insertion Lengths and Copy Lengths */\n#define BROTLI_NUM_INS_COPY_CODES 24\n\n/* 7.1. Context modes and context ID lookup for literals */\n/* \"context IDs for literals are in the range of 0..63\" */\n#define BROTLI_LITERAL_CONTEXT_BITS 6\n\n/* 7.2. Context ID for distances */\n#define BROTLI_DISTANCE_CONTEXT_BITS 2\n\n/* 9.1. Format of the Stream Header */\n/* Number of slack bytes for window size. Don't confuse\n   with BROTLI_NUM_DISTANCE_SHORT_CODES. */\n#define BROTLI_WINDOW_GAP 16\n#define BROTLI_MAX_BACKWARD_LIMIT(W) (((size_t)1 << (W)) - BROTLI_WINDOW_GAP)\n\ntypedef struct BrotliDistanceCodeLimit {\n  uint32_t max_alphabet_size;\n  uint32_t max_distance;\n} BrotliDistanceCodeLimit;\n\n/* This function calculates maximal size of distance alphabet, such that the\n   distances greater than the given values can not be represented.\n\n   This limits are designed to support fast and safe 32-bit decoders.\n   \"32-bit\" means that signed integer values up to ((1 << 31) - 1) could be\n   safely expressed.\n\n   Brotli distance alphabet symbols do not represent consecutive distance\n   ranges. Each distance alphabet symbol (excluding direct distances and short\n   codes), represent interleaved (for NPOSTFIX > 0) range of distances.\n   A \"group\" of consecutive (1 << NPOSTFIX) symbols represent non-interleaved\n   range. Two consecutive groups require the same amount of \"extra bits\".\n\n   It is important that distance alphabet represents complete \"groups\".\n   To avoid complex logic on encoder side about interleaved ranges\n   it was decided to restrict both sides to complete distance code \"groups\".\n */\nBROTLI_UNUSED_FUNCTION BrotliDistanceCodeLimit BrotliCalculateDistanceCodeLimit(\n    uint32_t max_distance, uint32_t npostfix, uint32_t ndirect) {\n  BrotliDistanceCodeLimit result;\n  /* Marking this function as unused, because not all files\n     including \"constants.h\" use it -> compiler warns about that. */\n  BROTLI_UNUSED(&BrotliCalculateDistanceCodeLimit);\n  if (max_distance <= ndirect) {\n    /* This case never happens / exists only for the sake of completeness. */\n    result.max_alphabet_size = max_distance + BROTLI_NUM_DISTANCE_SHORT_CODES;\n    result.max_distance = max_distance;\n    return result;\n  } else {\n    /* The first prohibited value. */\n    uint32_t forbidden_distance = max_distance + 1;\n    /* Subtract \"directly\" encoded region. */\n    uint32_t offset = forbidden_distance - ndirect - 1;\n    uint32_t ndistbits = 0;\n    uint32_t tmp;\n    uint32_t half;\n    uint32_t group;\n    /* Postfix for the last dcode in the group. */\n    uint32_t postfix = (1u << npostfix) - 1;\n    uint32_t extra;\n    uint32_t start;\n    /* Remove postfix and \"head-start\". */\n    offset = (offset >> npostfix) + 4;\n    /* Calculate the number of distance bits. */\n    tmp = offset / 2;\n    /* Poor-man's log2floor, to avoid extra dependencies. */\n    while (tmp != 0) {ndistbits++; tmp = tmp >> 1;}\n    /* One bit is covered with subrange addressing (\"half\"). */\n    ndistbits--;\n    /* Find subrange. */\n    half = (offset >> ndistbits) & 1;\n    /* Calculate the \"group\" part of dcode. */\n    group = ((ndistbits - 1) << 1) | half;\n    /* Calculated \"group\" covers the prohibited distance value. */\n    if (group == 0) {\n      /* This case is added for correctness; does not occur for limit > 128. */\n      result.max_alphabet_size = ndirect + BROTLI_NUM_DISTANCE_SHORT_CODES;\n      result.max_distance = ndirect;\n      return result;\n    }\n    /* Decrement \"group\", so it is the last permitted \"group\". */\n    group--;\n    /* After group was decremented, ndistbits and half must be recalculated. */\n    ndistbits = (group >> 1) + 1;\n    /* The last available distance in the subrange has all extra bits set. */\n    extra = (1u << ndistbits) - 1;\n    /* Calculate region start. NB: ndistbits >= 1. */\n    start = (1u << (ndistbits + 1)) - 4;\n    /* Move to subregion. */\n    start += (group & 1) << ndistbits;\n    /* Calculate the alphabet size. */\n    result.max_alphabet_size = ((group << npostfix) | postfix) + ndirect +\n        BROTLI_NUM_DISTANCE_SHORT_CODES + 1;\n    /* Calculate the maximal distance representable by alphabet. */\n    result.max_distance = ((start + extra) << npostfix) + postfix + ndirect + 1;\n    return result;\n  }\n}\n\n/* Represents the range of values belonging to a prefix code:\n   [offset, offset + 2^nbits) */\ntypedef struct {\n  uint16_t offset;\n  uint8_t nbits;\n} BrotliPrefixCodeRange;\n\n/* \"Soft-private\", it is exported, but not \"advertised\" as API. */\nBROTLI_COMMON_API extern const BrotliPrefixCodeRange\n    _kBrotliPrefixCodeRanges[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n\n#endif  /* BROTLI_COMMON_CONSTANTS_H_ */\n"
  },
  {
    "path": "third-party/brotli/common/context.c",
    "content": "#include \"context.h\"\n\n#include <brotli/types.h>\n\n/* Common context lookup table for all context modes. */\nconst uint8_t _kBrotliContextLookupTable[2048] = {\n  /* CONTEXT_LSB6, last byte. */\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n   0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,\n  16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,\n  32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,\n  48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,\n\n  /* CONTEXT_LSB6, second last byte, */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n  /* CONTEXT_MSB6, last byte. */\n   0,  0,  0,  0,  1,  1,  1,  1,  2,  2,  2,  2,  3,  3,  3,  3,\n   4,  4,  4,  4,  5,  5,  5,  5,  6,  6,  6,  6,  7,  7,  7,  7,\n   8,  8,  8,  8,  9,  9,  9,  9, 10, 10, 10, 10, 11, 11, 11, 11,\n  12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15,\n  16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 19, 19, 19, 19,\n  20, 20, 20, 20, 21, 21, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23,\n  24, 24, 24, 24, 25, 25, 25, 25, 26, 26, 26, 26, 27, 27, 27, 27,\n  28, 28, 28, 28, 29, 29, 29, 29, 30, 30, 30, 30, 31, 31, 31, 31,\n  32, 32, 32, 32, 33, 33, 33, 33, 34, 34, 34, 34, 35, 35, 35, 35,\n  36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 39, 39, 39, 39,\n  40, 40, 40, 40, 41, 41, 41, 41, 42, 42, 42, 42, 43, 43, 43, 43,\n  44, 44, 44, 44, 45, 45, 45, 45, 46, 46, 46, 46, 47, 47, 47, 47,\n  48, 48, 48, 48, 49, 49, 49, 49, 50, 50, 50, 50, 51, 51, 51, 51,\n  52, 52, 52, 52, 53, 53, 53, 53, 54, 54, 54, 54, 55, 55, 55, 55,\n  56, 56, 56, 56, 57, 57, 57, 57, 58, 58, 58, 58, 59, 59, 59, 59,\n  60, 60, 60, 60, 61, 61, 61, 61, 62, 62, 62, 62, 63, 63, 63, 63,\n\n  /* CONTEXT_MSB6, second last byte, */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n\n  /* CONTEXT_UTF8, last byte. */\n  /* ASCII range. */\n   0,  0,  0,  0,  0,  0,  0,  0,  0,  4,  4,  0,  0,  4,  0,  0,\n   0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n   8, 12, 16, 12, 12, 20, 12, 16, 24, 28, 12, 12, 32, 12, 36, 12,\n  44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 32, 32, 24, 40, 28, 12,\n  12, 48, 52, 52, 52, 48, 52, 52, 52, 48, 52, 52, 52, 52, 52, 48,\n  52, 52, 52, 52, 52, 48, 52, 52, 52, 52, 52, 24, 12, 28, 12, 12,\n  12, 56, 60, 60, 60, 56, 60, 60, 60, 56, 60, 60, 60, 60, 60, 56,\n  60, 60, 60, 60, 60, 56, 60, 60, 60, 60, 60, 24, 12, 28, 12,  0,\n  /* UTF8 continuation byte range. */\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,\n  /* UTF8 lead byte range. */\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n  2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3,\n\n  /* CONTEXT_UTF8 second last byte. */\n  /* ASCII range. */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1,\n  1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1,\n  1, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, 0,\n  /* UTF8 continuation byte range. */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  /* UTF8 lead byte range. */\n  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n\n  /* CONTEXT_SIGNED, last byte, same as the above values shifted by 3 bits. */\n   0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,\n  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n  16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32,\n  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n  40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, 40,\n  48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 56,\n\n  /* CONTEXT_SIGNED, second last byte. */\n  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,\n  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n  5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7,\n};\n"
  },
  {
    "path": "third-party/brotli/common/context.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup table to map the previous two bytes to a context id.\n\n  There are four different context modeling modes defined here:\n    CONTEXT_LSB6: context id is the least significant 6 bits of the last byte,\n    CONTEXT_MSB6: context id is the most significant 6 bits of the last byte,\n    CONTEXT_UTF8: second-order context model tuned for UTF8-encoded text,\n    CONTEXT_SIGNED: second-order context model tuned for signed integers.\n\n  If |p1| and |p2| are the previous two bytes, and |mode| is current context\n  mode, we calculate the context as:\n\n    context = ContextLut(mode)[p1] | ContextLut(mode)[p2 + 256].\n\n  For CONTEXT_UTF8 mode, if the previous two bytes are ASCII characters\n  (i.e. < 128), this will be equivalent to\n\n    context = 4 * context1(p1) + context2(p2),\n\n  where context1 is based on the previous byte in the following way:\n\n    0  : non-ASCII control\n    1  : \\t, \\n, \\r\n    2  : space\n    3  : other punctuation\n    4  : \" '\n    5  : %\n    6  : ( < [ {\n    7  : ) > ] }\n    8  : , ; :\n    9  : .\n    10 : =\n    11 : number\n    12 : upper-case vowel\n    13 : upper-case consonant\n    14 : lower-case vowel\n    15 : lower-case consonant\n\n  and context2 is based on the second last byte:\n\n    0 : control, space\n    1 : punctuation\n    2 : upper-case letter, number\n    3 : lower-case letter\n\n  If the last byte is ASCII, and the second last byte is not (in a valid UTF8\n  stream it will be a continuation byte, value between 128 and 191), the\n  context is the same as if the second last byte was an ASCII control or space.\n\n  If the last byte is a UTF8 lead byte (value >= 192), then the next byte will\n  be a continuation byte and the context id is 2 or 3 depending on the LSB of\n  the last byte and to a lesser extent on the second last byte if it is ASCII.\n\n  If the last byte is a UTF8 continuation byte, the second last byte can be:\n    - continuation byte: the next byte is probably ASCII or lead byte (assuming\n      4-byte UTF8 characters are rare) and the context id is 0 or 1.\n    - lead byte (192 - 207): next byte is ASCII or lead byte, context is 0 or 1\n    - lead byte (208 - 255): next byte is continuation byte, context is 2 or 3\n\n  The possible value combinations of the previous two bytes, the range of\n  context ids and the type of the next byte is summarized in the table below:\n\n  |--------\\-----------------------------------------------------------------|\n  |         \\                         Last byte                              |\n  | Second   \\---------------------------------------------------------------|\n  | last byte \\    ASCII            |   cont. byte        |   lead byte      |\n  |            \\   (0-127)          |   (128-191)         |   (192-)         |\n  |=============|===================|=====================|==================|\n  |  ASCII      | next: ASCII/lead  |  not valid          |  next: cont.     |\n  |  (0-127)    | context: 4 - 63   |                     |  context: 2 - 3  |\n  |-------------|-------------------|---------------------|------------------|\n  |  cont. byte | next: ASCII/lead  |  next: ASCII/lead   |  next: cont.     |\n  |  (128-191)  | context: 4 - 63   |  context: 0 - 1     |  context: 2 - 3  |\n  |-------------|-------------------|---------------------|------------------|\n  |  lead byte  | not valid         |  next: ASCII/lead   |  not valid       |\n  |  (192-207)  |                   |  context: 0 - 1     |                  |\n  |-------------|-------------------|---------------------|------------------|\n  |  lead byte  | not valid         |  next: cont.        |  not valid       |\n  |  (208-)     |                   |  context: 2 - 3     |                  |\n  |-------------|-------------------|---------------------|------------------|\n*/\n\n#ifndef BROTLI_COMMON_CONTEXT_H_\n#define BROTLI_COMMON_CONTEXT_H_\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\ntypedef enum ContextType {\n  CONTEXT_LSB6 = 0,\n  CONTEXT_MSB6 = 1,\n  CONTEXT_UTF8 = 2,\n  CONTEXT_SIGNED = 3\n} ContextType;\n\n/* \"Soft-private\", it is exported, but not \"advertised\" as API. */\n/* Common context lookup table for all context modes. */\nBROTLI_COMMON_API extern const uint8_t _kBrotliContextLookupTable[2048];\n\ntypedef const uint8_t* ContextLut;\n\n/* typeof(MODE) == ContextType; returns ContextLut */\n#define BROTLI_CONTEXT_LUT(MODE) (&_kBrotliContextLookupTable[(MODE) << 9])\n\n/* typeof(LUT) == ContextLut */\n#define BROTLI_CONTEXT(P1, P2, LUT) ((LUT)[P1] | ((LUT) + 256)[P2])\n\n#endif  /* BROTLI_COMMON_CONTEXT_H_ */\n"
  },
  {
    "path": "third-party/brotli/common/dictionary.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"dictionary.h\"\n#include \"platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\nstatic const uint8_t kBrotliDictionaryData[] =\n/* GENERATED CODE START */\n{\n116,105,109,101,100,111,119,110,108,105,102,101,108,101,102,116,98,97,99,107,99,\n111,100,101,100,97,116,97,115,104,111,119,111,110,108,121,115,105,116,101,99,105\n,116,121,111,112,101,110,106,117,115,116,108,105,107,101,102,114,101,101,119,111\n,114,107,116,101,120,116,121,101,97,114,111,118,101,114,98,111,100,121,108,111,\n118,101,102,111,114,109,98,111,111,107,112,108,97,121,108,105,118,101,108,105,\n110,101,104,101,108,112,104,111,109,101,115,105,100,101,109,111,114,101,119,111,\n114,100,108,111,110,103,116,104,101,109,118,105,101,119,102,105,110,100,112,97,\n103,101,100,97,121,115,102,117,108,108,104,101,97,100,116,101,114,109,101,97,99,\n104,97,114,101,97,102,114,111,109,116,114,117,101,109,97,114,107,97,98,108,101,\n117,112,111,110,104,105,103,104,100,97,116,101,108,97,110,100,110,101,119,115,\n101,118,101,110,110,101,120,116,99,97,115,101,98,111,116,104,112,111,115,116,117\n,115,101,100,109,97,100,101,104,97,110,100,104,101,114,101,119,104,97,116,110,97\n,109,101,76,105,110,107,98,108,111,103,115,105,122,101,98,97,115,101,104,101,108\n,100,109,97,107,101,109,97,105,110,117,115,101,114,39,41,32,43,104,111,108,100,\n101,110,100,115,119,105,116,104,78,101,119,115,114,101,97,100,119,101,114,101,\n115,105,103,110,116,97,107,101,104,97,118,101,103,97,109,101,115,101,101,110,99,\n97,108,108,112,97,116,104,119,101,108,108,112,108,117,115,109,101,110,117,102,\n105,108,109,112,97,114,116,106,111,105,110,116,104,105,115,108,105,115,116,103,\n111,111,100,110,101,101,100,119,97,121,115,119,101,115,116,106,111,98,115,109,\n105,110,100,97,108,115,111,108,111,103,111,114,105,99,104,117,115,101,115,108,97\n,115,116,116,101,97,109,97,114,109,121,102,111,111,100,107,105,110,103,119,105,\n108,108,101,97,115,116,119,97,114,100,98,101,115,116,102,105,114,101,80,97,103,\n101,107,110,111,119,97,119,97,121,46,112,110,103,109,111,118,101,116,104,97,110,\n108,111,97,100,103,105,118,101,115,101,108,102,110,111,116,101,109,117,99,104,\n102,101,101,100,109,97,110,121,114,111,99,107,105,99,111,110,111,110,99,101,108,\n111,111,107,104,105,100,101,100,105,101,100,72,111,109,101,114,117,108,101,104,\n111,115,116,97,106,97,120,105,110,102,111,99,108,117,98,108,97,119,115,108,101,\n115,115,104,97,108,102,115,111,109,101,115,117,99,104,122,111,110,101,49,48,48,\n37,111,110,101,115,99,97,114,101,84,105,109,101,114,97,99,101,98,108,117,101,102\n,111,117,114,119,101,101,107,102,97,99,101,104,111,112,101,103,97,118,101,104,97\n,114,100,108,111,115,116,119,104,101,110,112,97,114,107,107,101,112,116,112,97,\n115,115,115,104,105,112,114,111,111,109,72,84,77,76,112,108,97,110,84,121,112,\n101,100,111,110,101,115,97,118,101,107,101,101,112,102,108,97,103,108,105,110,\n107,115,111,108,100,102,105,118,101,116,111,111,107,114,97,116,101,116,111,119,\n110,106,117,109,112,116,104,117,115,100,97,114,107,99,97,114,100,102,105,108,101\n,102,101,97,114,115,116,97,121,107,105,108,108,116,104,97,116,102,97,108,108,97,\n117,116,111,101,118,101,114,46,99,111,109,116,97,108,107,115,104,111,112,118,111\n,116,101,100,101,101,112,109,111,100,101,114,101,115,116,116,117,114,110,98,111,\n114,110,98,97,110,100,102,101,108,108,114,111,115,101,117,114,108,40,115,107,105\n,110,114,111,108,101,99,111,109,101,97,99,116,115,97,103,101,115,109,101,101,116\n,103,111,108,100,46,106,112,103,105,116,101,109,118,97,114,121,102,101,108,116,\n116,104,101,110,115,101,110,100,100,114,111,112,86,105,101,119,99,111,112,121,49\n,46,48,34,60,47,97,62,115,116,111,112,101,108,115,101,108,105,101,115,116,111,\n117,114,112,97,99,107,46,103,105,102,112,97,115,116,99,115,115,63,103,114,97,121\n,109,101,97,110,38,103,116,59,114,105,100,101,115,104,111,116,108,97,116,101,115\n,97,105,100,114,111,97,100,118,97,114,32,102,101,101,108,106,111,104,110,114,105\n,99,107,112,111,114,116,102,97,115,116,39,85,65,45,100,101,97,100,60,47,98,62,\n112,111,111,114,98,105,108,108,116,121,112,101,85,46,83,46,119,111,111,100,109,\n117,115,116,50,112,120,59,73,110,102,111,114,97,110,107,119,105,100,101,119,97,\n110,116,119,97,108,108,108,101,97,100,91,48,93,59,112,97,117,108,119,97,118,101,\n115,117,114,101,36,40,39,35,119,97,105,116,109,97,115,115,97,114,109,115,103,111\n,101,115,103,97,105,110,108,97,110,103,112,97,105,100,33,45,45,32,108,111,99,107\n,117,110,105,116,114,111,111,116,119,97,108,107,102,105,114,109,119,105,102,101,\n120,109,108,34,115,111,110,103,116,101,115,116,50,48,112,120,107,105,110,100,114\n,111,119,115,116,111,111,108,102,111,110,116,109,97,105,108,115,97,102,101,115,\n116,97,114,109,97,112,115,99,111,114,101,114,97,105,110,102,108,111,119,98,97,98\n,121,115,112,97,110,115,97,121,115,52,112,120,59,54,112,120,59,97,114,116,115,\n102,111,111,116,114,101,97,108,119,105,107,105,104,101,97,116,115,116,101,112,\n116,114,105,112,111,114,103,47,108,97,107,101,119,101,97,107,116,111,108,100,70,\n111,114,109,99,97,115,116,102,97,110,115,98,97,110,107,118,101,114,121,114,117,\n110,115,106,117,108,121,116,97,115,107,49,112,120,59,103,111,97,108,103,114,101,\n119,115,108,111,119,101,100,103,101,105,100,61,34,115,101,116,115,53,112,120,59,\n46,106,115,63,52,48,112,120,105,102,32,40,115,111,111,110,115,101,97,116,110,111\n,110,101,116,117,98,101,122,101,114,111,115,101,110,116,114,101,101,100,102,97,\n99,116,105,110,116,111,103,105,102,116,104,97,114,109,49,56,112,120,99,97,109,\n101,104,105,108,108,98,111,108,100,122,111,111,109,118,111,105,100,101,97,115,\n121,114,105,110,103,102,105,108,108,112,101,97,107,105,110,105,116,99,111,115,\n116,51,112,120,59,106,97,99,107,116,97,103,115,98,105,116,115,114,111,108,108,\n101,100,105,116,107,110,101,119,110,101,97,114,60,33,45,45,103,114,111,119,74,83\n,79,78,100,117,116,121,78,97,109,101,115,97,108,101,121,111,117,32,108,111,116,\n115,112,97,105,110,106,97,122,122,99,111,108,100,101,121,101,115,102,105,115,104\n,119,119,119,46,114,105,115,107,116,97,98,115,112,114,101,118,49,48,112,120,114,\n105,115,101,50,53,112,120,66,108,117,101,100,105,110,103,51,48,48,44,98,97,108,\n108,102,111,114,100,101,97,114,110,119,105,108,100,98,111,120,46,102,97,105,114,\n108,97,99,107,118,101,114,115,112,97,105,114,106,117,110,101,116,101,99,104,105,\n102,40,33,112,105,99,107,101,118,105,108,36,40,34,35,119,97,114,109,108,111,114,\n100,100,111,101,115,112,117,108,108,44,48,48,48,105,100,101,97,100,114,97,119,\n104,117,103,101,115,112,111,116,102,117,110,100,98,117,114,110,104,114,101,102,\n99,101,108,108,107,101,121,115,116,105,99,107,104,111,117,114,108,111,115,115,\n102,117,101,108,49,50,112,120,115,117,105,116,100,101,97,108,82,83,83,34,97,103,\n101,100,103,114,101,121,71,69,84,34,101,97,115,101,97,105,109,115,103,105,114,\n108,97,105,100,115,56,112,120,59,110,97,118,121,103,114,105,100,116,105,112,115,\n35,57,57,57,119,97,114,115,108,97,100,121,99,97,114,115,41,59,32,125,112,104,112\n,63,104,101,108,108,116,97,108,108,119,104,111,109,122,104,58,229,42,47,13,10,32\n,49,48,48,104,97,108,108,46,10,10,65,55,112,120,59,112,117,115,104,99,104,97,116\n,48,112,120,59,99,114,101,119,42,47,60,47,104,97,115,104,55,53,112,120,102,108,\n97,116,114,97,114,101,32,38,38,32,116,101,108,108,99,97,109,112,111,110,116,111,\n108,97,105,100,109,105,115,115,115,107,105,112,116,101,110,116,102,105,110,101,\n109,97,108,101,103,101,116,115,112,108,111,116,52,48,48,44,13,10,13,10,99,111,\n111,108,102,101,101,116,46,112,104,112,60,98,114,62,101,114,105,99,109,111,115,\n116,103,117,105,100,98,101,108,108,100,101,115,99,104,97,105,114,109,97,116,104,\n97,116,111,109,47,105,109,103,38,35,56,50,108,117,99,107,99,101,110,116,48,48,48\n,59,116,105,110,121,103,111,110,101,104,116,109,108,115,101,108,108,100,114,117,\n103,70,82,69,69,110,111,100,101,110,105,99,107,63,105,100,61,108,111,115,101,110\n,117,108,108,118,97,115,116,119,105,110,100,82,83,83,32,119,101,97,114,114,101,\n108,121,98,101,101,110,115,97,109,101,100,117,107,101,110,97,115,97,99,97,112,\n101,119,105,115,104,103,117,108,102,84,50,51,58,104,105,116,115,115,108,111,116,\n103,97,116,101,107,105,99,107,98,108,117,114,116,104,101,121,49,53,112,120,39,39\n,41,59,41,59,34,62,109,115,105,101,119,105,110,115,98,105,114,100,115,111,114,\n116,98,101,116,97,115,101,101,107,84,49,56,58,111,114,100,115,116,114,101,101,\n109,97,108,108,54,48,112,120,102,97,114,109,226,128,153,115,98,111,121,115,91,48\n,93,46,39,41,59,34,80,79,83,84,98,101,97,114,107,105,100,115,41,59,125,125,109,\n97,114,121,116,101,110,100,40,85,75,41,113,117,97,100,122,104,58,230,45,115,105,\n122,45,45,45,45,112,114,111,112,39,41,59,13,108,105,102,116,84,49,57,58,118,105,\n99,101,97,110,100,121,100,101,98,116,62,82,83,83,112,111,111,108,110,101,99,107,\n98,108,111,119,84,49,54,58,100,111,111,114,101,118,97,108,84,49,55,58,108,101,\n116,115,102,97,105,108,111,114,97,108,112,111,108,108,110,111,118,97,99,111,108,\n115,103,101,110,101,32,226,128,148,115,111,102,116,114,111,109,101,116,105,108,\n108,114,111,115,115,60,104,51,62,112,111,117,114,102,97,100,101,112,105,110,107,\n60,116,114,62,109,105,110,105,41,124,33,40,109,105,110,101,122,104,58,232,98,97,\n114,115,104,101,97,114,48,48,41,59,109,105,108,107,32,45,45,62,105,114,111,110,\n102,114,101,100,100,105,115,107,119,101,110,116,115,111,105,108,112,117,116,115,\n47,106,115,47,104,111,108,121,84,50,50,58,73,83,66,78,84,50,48,58,97,100,97,109,\n115,101,101,115,60,104,50,62,106,115,111,110,39,44,32,39,99,111,110,116,84,50,49\n,58,32,82,83,83,108,111,111,112,97,115,105,97,109,111,111,110,60,47,112,62,115,\n111,117,108,76,73,78,69,102,111,114,116,99,97,114,116,84,49,52,58,60,104,49,62,\n56,48,112,120,33,45,45,60,57,112,120,59,84,48,52,58,109,105,107,101,58,52,54,90,\n110,105,99,101,105,110,99,104,89,111,114,107,114,105,99,101,122,104,58,228,39,41\n,41,59,112,117,114,101,109,97,103,101,112,97,114,97,116,111,110,101,98,111,110,\n100,58,51,55,90,95,111,102,95,39,93,41,59,48,48,48,44,122,104,58,231,116,97,110,\n107,121,97,114,100,98,111,119,108,98,117,115,104,58,53,54,90,74,97,118,97,51,48,\n112,120,10,124,125,10,37,67,51,37,58,51,52,90,106,101,102,102,69,88,80,73,99,97,\n115,104,118,105,115,97,103,111,108,102,115,110,111,119,122,104,58,233,113,117,\n101,114,46,99,115,115,115,105,99,107,109,101,97,116,109,105,110,46,98,105,110,\n100,100,101,108,108,104,105,114,101,112,105,99,115,114,101,110,116,58,51,54,90,\n72,84,84,80,45,50,48,49,102,111,116,111,119,111,108,102,69,78,68,32,120,98,111,\n120,58,53,52,90,66,79,68,89,100,105,99,107,59,10,125,10,101,120,105,116,58,51,53\n,90,118,97,114,115,98,101,97,116,39,125,41,59,100,105,101,116,57,57,57,59,97,110\n,110,101,125,125,60,47,91,105,93,46,76,97,110,103,107,109,194,178,119,105,114,\n101,116,111,121,115,97,100,100,115,115,101,97,108,97,108,101,120,59,10,9,125,101\n,99,104,111,110,105,110,101,46,111,114,103,48,48,53,41,116,111,110,121,106,101,\n119,115,115,97,110,100,108,101,103,115,114,111,111,102,48,48,48,41,32,50,48,48,\n119,105,110,101,103,101,97,114,100,111,103,115,98,111,111,116,103,97,114,121,99,\n117,116,115,116,121,108,101,116,101,109,112,116,105,111,110,46,120,109,108,99,\n111,99,107,103,97,110,103,36,40,39,46,53,48,112,120,80,104,46,68,109,105,115,99,\n97,108,97,110,108,111,97,110,100,101,115,107,109,105,108,101,114,121,97,110,117,\n110,105,120,100,105,115,99,41,59,125,10,100,117,115,116,99,108,105,112,41,46,10,\n10,55,48,112,120,45,50,48,48,68,86,68,115,55,93,62,60,116,97,112,101,100,101,109\n,111,105,43,43,41,119,97,103,101,101,117,114,111,112,104,105,108,111,112,116,115\n,104,111,108,101,70,65,81,115,97,115,105,110,45,50,54,84,108,97,98,115,112,101,\n116,115,85,82,76,32,98,117,108,107,99,111,111,107,59,125,13,10,72,69,65,68,91,48\n,93,41,97,98,98,114,106,117,97,110,40,49,57,56,108,101,115,104,116,119,105,110,\n60,47,105,62,115,111,110,121,103,117,121,115,102,117,99,107,112,105,112,101,124,\n45,10,33,48,48,50,41,110,100,111,119,91,49,93,59,91,93,59,10,76,111,103,32,115,\n97,108,116,13,10,9,9,98,97,110,103,116,114,105,109,98,97,116,104,41,123,13,10,48\n,48,112,120,10,125,41,59,107,111,58,236,102,101,101,115,97,100,62,13,115,58,47,\n47,32,91,93,59,116,111,108,108,112,108,117,103,40,41,123,10,123,13,10,32,46,106,\n115,39,50,48,48,112,100,117,97,108,98,111,97,116,46,74,80,71,41,59,10,125,113,\n117,111,116,41,59,10,10,39,41,59,10,13,10,125,13,50,48,49,52,50,48,49,53,50,48,\n49,54,50,48,49,55,50,48,49,56,50,48,49,57,50,48,50,48,50,48,50,49,50,48,50,50,50\n,48,50,51,50,48,50,52,50,48,50,53,50,48,50,54,50,48,50,55,50,48,50,56,50,48,50,\n57,50,48,51,48,50,48,51,49,50,48,51,50,50,48,51,51,50,48,51,52,50,48,51,53,50,48\n,51,54,50,48,51,55,50,48,49,51,50,48,49,50,50,48,49,49,50,48,49,48,50,48,48,57,\n50,48,48,56,50,48,48,55,50,48,48,54,50,48,48,53,50,48,48,52,50,48,48,51,50,48,48\n,50,50,48,48,49,50,48,48,48,49,57,57,57,49,57,57,56,49,57,57,55,49,57,57,54,49,\n57,57,53,49,57,57,52,49,57,57,51,49,57,57,50,49,57,57,49,49,57,57,48,49,57,56,57\n,49,57,56,56,49,57,56,55,49,57,56,54,49,57,56,53,49,57,56,52,49,57,56,51,49,57,\n56,50,49,57,56,49,49,57,56,48,49,57,55,57,49,57,55,56,49,57,55,55,49,57,55,54,49\n,57,55,53,49,57,55,52,49,57,55,51,49,57,55,50,49,57,55,49,49,57,55,48,49,57,54,\n57,49,57,54,56,49,57,54,55,49,57,54,54,49,57,54,53,49,57,54,52,49,57,54,51,49,57\n,54,50,49,57,54,49,49,57,54,48,49,57,53,57,49,57,53,56,49,57,53,55,49,57,53,54,\n49,57,53,53,49,57,53,52,49,57,53,51,49,57,53,50,49,57,53,49,49,57,53,48,49,48,48\n,48,49,48,50,52,49,51,57,52,48,48,48,48,57,57,57,57,99,111,109,111,109,195,161,\n115,101,115,116,101,101,115,116,97,112,101,114,111,116,111,100,111,104,97,99,101\n,99,97,100,97,97,195,177,111,98,105,101,110,100,195,173,97,97,115,195,173,118,\n105,100,97,99,97,115,111,111,116,114,111,102,111,114,111,115,111,108,111,111,116\n,114,97,99,117,97,108,100,105,106,111,115,105,100,111,103,114,97,110,116,105,112\n,111,116,101,109,97,100,101,98,101,97,108,103,111,113,117,195,169,101,115,116,\n111,110,97,100,97,116,114,101,115,112,111,99,111,99,97,115,97,98,97,106,111,116,\n111,100,97,115,105,110,111,97,103,117,97,112,117,101,115,117,110,111,115,97,110,\n116,101,100,105,99,101,108,117,105,115,101,108,108,97,109,97,121,111,122,111,110\n,97,97,109,111,114,112,105,115,111,111,98,114,97,99,108,105,99,101,108,108,111,\n100,105,111,115,104,111,114,97,99,97,115,105,208,183,208,176,208,189,208,176,208\n,190,208,188,209,128,208,176,209,128,209,131,209,130,208,176,208,189,208,181,208\n,191,208,190,208,190,209,130,208,184,208,183,208,189,208,190,208,180,208,190,209\n,130,208,190,208,182,208,181,208,190,208,189,208,184,209,133,208,157,208,176,208\n,181,208,181,208,177,209,139,208,188,209,139,208,146,209,139,209,129,208,190,208\n,178,209,139,208,178,208,190,208,157,208,190,208,190,208,177,208,159,208,190,208\n,187,208,184,208,189,208,184,208,160,208,164,208,157,208,181,208,156,209,139,209\n,130,209,139,208,158,208,189,208,184,208,188,208,180,208,176,208,151,208,176,208\n,148,208,176,208,157,209,131,208,158,208,177,209,130,208,181,208,152,208,183,208\n,181,208,185,208,189,209,131,208,188,208,188,208,162,209,139,209,131,208,182,217\n,129,217,138,216,163,217,134,217,133,216,167,217,133,216,185,217,131,217,132,216\n,163,217,136,216,177,216,175,217,138,216,167,217,129,217,137,217,135,217,136,217\n,132,217,133,217,132,217,131,216,167,217,136,217,132,217,135,216,168,216,179,216\n,167,217,132,216,165,217,134,217,135,217,138,216,163,217,138,217,130,216,175,217\n,135,217,132,216,171,217,133,216,168,217,135,217,132,217,136,217,132,217,138,216\n,168,217,132,216,167,217,138,216,168,217,131,216,180,217,138,216,167,217,133,216\n,163,217,133,217,134,216,170,216,168,217,138,217,132,217,134,216,173,216,168,217\n,135,217,133,217,133,216,180,217,136,216,180,102,105,114,115,116,118,105,100,101\n,111,108,105,103,104,116,119,111,114,108,100,109,101,100,105,97,119,104,105,116,\n101,99,108,111,115,101,98,108,97,99,107,114,105,103,104,116,115,109,97,108,108,\n98,111,111,107,115,112,108,97,99,101,109,117,115,105,99,102,105,101,108,100,111,\n114,100,101,114,112,111,105,110,116,118,97,108,117,101,108,101,118,101,108,116,\n97,98,108,101,98,111,97,114,100,104,111,117,115,101,103,114,111,117,112,119,111,\n114,107,115,121,101,97,114,115,115,116,97,116,101,116,111,100,97,121,119,97,116,\n101,114,115,116,97,114,116,115,116,121,108,101,100,101,97,116,104,112,111,119,\n101,114,112,104,111,110,101,110,105,103,104,116,101,114,114,111,114,105,110,112,\n117,116,97,98,111,117,116,116,101,114,109,115,116,105,116,108,101,116,111,111,\n108,115,101,118,101,110,116,108,111,99,97,108,116,105,109,101,115,108,97,114,103\n,101,119,111,114,100,115,103,97,109,101,115,115,104,111,114,116,115,112,97,99,\n101,102,111,99,117,115,99,108,101,97,114,109,111,100,101,108,98,108,111,99,107,\n103,117,105,100,101,114,97,100,105,111,115,104,97,114,101,119,111,109,101,110,97\n,103,97,105,110,109,111,110,101,121,105,109,97,103,101,110,97,109,101,115,121,\n111,117,110,103,108,105,110,101,115,108,97,116,101,114,99,111,108,111,114,103,\n114,101,101,110,102,114,111,110,116,38,97,109,112,59,119,97,116,99,104,102,111,\n114,99,101,112,114,105,99,101,114,117,108,101,115,98,101,103,105,110,97,102,116,\n101,114,118,105,115,105,116,105,115,115,117,101,97,114,101,97,115,98,101,108,111\n,119,105,110,100,101,120,116,111,116,97,108,104,111,117,114,115,108,97,98,101,\n108,112,114,105,110,116,112,114,101,115,115,98,117,105,108,116,108,105,110,107,\n115,115,112,101,101,100,115,116,117,100,121,116,114,97,100,101,102,111,117,110,\n100,115,101,110,115,101,117,110,100,101,114,115,104,111,119,110,102,111,114,109,\n115,114,97,110,103,101,97,100,100,101,100,115,116,105,108,108,109,111,118,101,\n100,116,97,107,101,110,97,98,111,118,101,102,108,97,115,104,102,105,120,101,100,\n111,102,116,101,110,111,116,104,101,114,118,105,101,119,115,99,104,101,99,107,\n108,101,103,97,108,114,105,118,101,114,105,116,101,109,115,113,117,105,99,107,\n115,104,97,112,101,104,117,109,97,110,101,120,105,115,116,103,111,105,110,103,\n109,111,118,105,101,116,104,105,114,100,98,97,115,105,99,112,101,97,99,101,115,\n116,97,103,101,119,105,100,116,104,108,111,103,105,110,105,100,101,97,115,119,\n114,111,116,101,112,97,103,101,115,117,115,101,114,115,100,114,105,118,101,115,\n116,111,114,101,98,114,101,97,107,115,111,117,116,104,118,111,105,99,101,115,105\n,116,101,115,109,111,110,116,104,119,104,101,114,101,98,117,105,108,100,119,104,\n105,99,104,101,97,114,116,104,102,111,114,117,109,116,104,114,101,101,115,112,\n111,114,116,112,97,114,116,121,67,108,105,99,107,108,111,119,101,114,108,105,118\n,101,115,99,108,97,115,115,108,97,121,101,114,101,110,116,114,121,115,116,111,\n114,121,117,115,97,103,101,115,111,117,110,100,99,111,117,114,116,121,111,117,\n114,32,98,105,114,116,104,112,111,112,117,112,116,121,112,101,115,97,112,112,108\n,121,73,109,97,103,101,98,101,105,110,103,117,112,112,101,114,110,111,116,101,\n115,101,118,101,114,121,115,104,111,119,115,109,101,97,110,115,101,120,116,114,\n97,109,97,116,99,104,116,114,97,99,107,107,110,111,119,110,101,97,114,108,121,98\n,101,103,97,110,115,117,112,101,114,112,97,112,101,114,110,111,114,116,104,108,\n101,97,114,110,103,105,118,101,110,110,97,109,101,100,101,110,100,101,100,84,101\n,114,109,115,112,97,114,116,115,71,114,111,117,112,98,114,97,110,100,117,115,105\n,110,103,119,111,109,97,110,102,97,108,115,101,114,101,97,100,121,97,117,100,105\n,111,116,97,107,101,115,119,104,105,108,101,46,99,111,109,47,108,105,118,101,100\n,99,97,115,101,115,100,97,105,108,121,99,104,105,108,100,103,114,101,97,116,106,\n117,100,103,101,116,104,111,115,101,117,110,105,116,115,110,101,118,101,114,98,\n114,111,97,100,99,111,97,115,116,99,111,118,101,114,97,112,112,108,101,102,105,\n108,101,115,99,121,99,108,101,115,99,101,110,101,112,108,97,110,115,99,108,105,\n99,107,119,114,105,116,101,113,117,101,101,110,112,105,101,99,101,101,109,97,105\n,108,102,114,97,109,101,111,108,100,101,114,112,104,111,116,111,108,105,109,105,\n116,99,97,99,104,101,99,105,118,105,108,115,99,97,108,101,101,110,116,101,114,\n116,104,101,109,101,116,104,101,114,101,116,111,117,99,104,98,111,117,110,100,\n114,111,121,97,108,97,115,107,101,100,119,104,111,108,101,115,105,110,99,101,115\n,116,111,99,107,32,110,97,109,101,102,97,105,116,104,104,101,97,114,116,101,109,\n112,116,121,111,102,102,101,114,115,99,111,112,101,111,119,110,101,100,109,105,\n103,104,116,97,108,98,117,109,116,104,105,110,107,98,108,111,111,100,97,114,114,\n97,121,109,97,106,111,114,116,114,117,115,116,99,97,110,111,110,117,110,105,111,\n110,99,111,117,110,116,118,97,108,105,100,115,116,111,110,101,83,116,121,108,101\n,76,111,103,105,110,104,97,112,112,121,111,99,99,117,114,108,101,102,116,58,102,\n114,101,115,104,113,117,105,116,101,102,105,108,109,115,103,114,97,100,101,110,\n101,101,100,115,117,114,98,97,110,102,105,103,104,116,98,97,115,105,115,104,111,\n118,101,114,97,117,116,111,59,114,111,117,116,101,46,104,116,109,108,109,105,120\n,101,100,102,105,110,97,108,89,111,117,114,32,115,108,105,100,101,116,111,112,\n105,99,98,114,111,119,110,97,108,111,110,101,100,114,97,119,110,115,112,108,105,\n116,114,101,97,99,104,82,105,103,104,116,100,97,116,101,115,109,97,114,99,104,\n113,117,111,116,101,103,111,111,100,115,76,105,110,107,115,100,111,117,98,116,97\n,115,121,110,99,116,104,117,109,98,97,108,108,111,119,99,104,105,101,102,121,111\n,117,116,104,110,111,118,101,108,49,48,112,120,59,115,101,114,118,101,117,110,\n116,105,108,104,97,110,100,115,67,104,101,99,107,83,112,97,99,101,113,117,101,\n114,121,106,97,109,101,115,101,113,117,97,108,116,119,105,99,101,48,44,48,48,48,\n83,116,97,114,116,112,97,110,101,108,115,111,110,103,115,114,111,117,110,100,101\n,105,103,104,116,115,104,105,102,116,119,111,114,116,104,112,111,115,116,115,108\n,101,97,100,115,119,101,101,107,115,97,118,111,105,100,116,104,101,115,101,109,\n105,108,101,115,112,108,97,110,101,115,109,97,114,116,97,108,112,104,97,112,108,\n97,110,116,109,97,114,107,115,114,97,116,101,115,112,108,97,121,115,99,108,97,\n105,109,115,97,108,101,115,116,101,120,116,115,115,116,97,114,115,119,114,111,\n110,103,60,47,104,51,62,116,104,105,110,103,46,111,114,103,47,109,117,108,116,\n105,104,101,97,114,100,80,111,119,101,114,115,116,97,110,100,116,111,107,101,110\n,115,111,108,105,100,40,116,104,105,115,98,114,105,110,103,115,104,105,112,115,\n115,116,97,102,102,116,114,105,101,100,99,97,108,108,115,102,117,108,108,121,102\n,97,99,116,115,97,103,101,110,116,84,104,105,115,32,47,47,45,45,62,97,100,109,\n105,110,101,103,121,112,116,69,118,101,110,116,49,53,112,120,59,69,109,97,105,\n108,116,114,117,101,34,99,114,111,115,115,115,112,101,110,116,98,108,111,103,115\n,98,111,120,34,62,110,111,116,101,100,108,101,97,118,101,99,104,105,110,97,115,\n105,122,101,115,103,117,101,115,116,60,47,104,52,62,114,111,98,111,116,104,101,\n97,118,121,116,114,117,101,44,115,101,118,101,110,103,114,97,110,100,99,114,105,\n109,101,115,105,103,110,115,97,119,97,114,101,100,97,110,99,101,112,104,97,115,\n101,62,60,33,45,45,101,110,95,85,83,38,35,51,57,59,50,48,48,112,120,95,110,97,\n109,101,108,97,116,105,110,101,110,106,111,121,97,106,97,120,46,97,116,105,111,\n110,115,109,105,116,104,85,46,83,46,32,104,111,108,100,115,112,101,116,101,114,\n105,110,100,105,97,110,97,118,34,62,99,104,97,105,110,115,99,111,114,101,99,111,\n109,101,115,100,111,105,110,103,112,114,105,111,114,83,104,97,114,101,49,57,57,\n48,115,114,111,109,97,110,108,105,115,116,115,106,97,112,97,110,102,97,108,108,\n115,116,114,105,97,108,111,119,110,101,114,97,103,114,101,101,60,47,104,50,62,97\n,98,117,115,101,97,108,101,114,116,111,112,101,114,97,34,45,47,47,87,99,97,114,\n100,115,104,105,108,108,115,116,101,97,109,115,80,104,111,116,111,116,114,117,\n116,104,99,108,101,97,110,46,112,104,112,63,115,97,105,110,116,109,101,116,97,\n108,108,111,117,105,115,109,101,97,110,116,112,114,111,111,102,98,114,105,101,\n102,114,111,119,34,62,103,101,110,114,101,116,114,117,99,107,108,111,111,107,115\n,86,97,108,117,101,70,114,97,109,101,46,110,101,116,47,45,45,62,10,60,116,114,\n121,32,123,10,118,97,114,32,109,97,107,101,115,99,111,115,116,115,112,108,97,105\n,110,97,100,117,108,116,113,117,101,115,116,116,114,97,105,110,108,97,98,111,114\n,104,101,108,112,115,99,97,117,115,101,109,97,103,105,99,109,111,116,111,114,116\n,104,101,105,114,50,53,48,112,120,108,101,97,115,116,115,116,101,112,115,67,111,\n117,110,116,99,111,117,108,100,103,108,97,115,115,115,105,100,101,115,102,117,\n110,100,115,104,111,116,101,108,97,119,97,114,100,109,111,117,116,104,109,111,\n118,101,115,112,97,114,105,115,103,105,118,101,115,100,117,116,99,104,116,101,\n120,97,115,102,114,117,105,116,110,117,108,108,44,124,124,91,93,59,116,111,112,\n34,62,10,60,33,45,45,80,79,83,84,34,111,99,101,97,110,60,98,114,47,62,102,108,\n111,111,114,115,112,101,97,107,100,101,112,116,104,32,115,105,122,101,98,97,110,\n107,115,99,97,116,99,104,99,104,97,114,116,50,48,112,120,59,97,108,105,103,110,\n100,101,97,108,115,119,111,117,108,100,53,48,112,120,59,117,114,108,61,34,112,97\n,114,107,115,109,111,117,115,101,77,111,115,116,32,46,46,46,60,47,97,109,111,110\n,103,98,114,97,105,110,98,111,100,121,32,110,111,110,101,59,98,97,115,101,100,99\n,97,114,114,121,100,114,97,102,116,114,101,102,101,114,112,97,103,101,95,104,111\n,109,101,46,109,101,116,101,114,100,101,108,97,121,100,114,101,97,109,112,114,\n111,118,101,106,111,105,110,116,60,47,116,114,62,100,114,117,103,115,60,33,45,45\n,32,97,112,114,105,108,105,100,101,97,108,97,108,108,101,110,101,120,97,99,116,\n102,111,114,116,104,99,111,100,101,115,108,111,103,105,99,86,105,101,119,32,115,\n101,101,109,115,98,108,97,110,107,112,111,114,116,115,32,40,50,48,48,115,97,118,\n101,100,95,108,105,110,107,103,111,97,108,115,103,114,97,110,116,103,114,101,101\n,107,104,111,109,101,115,114,105,110,103,115,114,97,116,101,100,51,48,112,120,59\n,119,104,111,115,101,112,97,114,115,101,40,41,59,34,32,66,108,111,99,107,108,105\n,110,117,120,106,111,110,101,115,112,105,120,101,108,39,41,59,34,62,41,59,105,\n102,40,45,108,101,102,116,100,97,118,105,100,104,111,114,115,101,70,111,99,117,\n115,114,97,105,115,101,98,111,120,101,115,84,114,97,99,107,101,109,101,110,116,\n60,47,101,109,62,98,97,114,34,62,46,115,114,99,61,116,111,119,101,114,97,108,116\n,61,34,99,97,98,108,101,104,101,110,114,121,50,52,112,120,59,115,101,116,117,112\n,105,116,97,108,121,115,104,97,114,112,109,105,110,111,114,116,97,115,116,101,\n119,97,110,116,115,116,104,105,115,46,114,101,115,101,116,119,104,101,101,108,\n103,105,114,108,115,47,99,115,115,47,49,48,48,37,59,99,108,117,98,115,115,116,\n117,102,102,98,105,98,108,101,118,111,116,101,115,32,49,48,48,48,107,111,114,101\n,97,125,41,59,13,10,98,97,110,100,115,113,117,101,117,101,61,32,123,125,59,56,48\n,112,120,59,99,107,105,110,103,123,13,10,9,9,97,104,101,97,100,99,108,111,99,107\n,105,114,105,115,104,108,105,107,101,32,114,97,116,105,111,115,116,97,116,115,70\n,111,114,109,34,121,97,104,111,111,41,91,48,93,59,65,98,111,117,116,102,105,110,\n100,115,60,47,104,49,62,100,101,98,117,103,116,97,115,107,115,85,82,76,32,61,99,\n101,108,108,115,125,41,40,41,59,49,50,112,120,59,112,114,105,109,101,116,101,108\n,108,115,116,117,114,110,115,48,120,54,48,48,46,106,112,103,34,115,112,97,105,\n110,98,101,97,99,104,116,97,120,101,115,109,105,99,114,111,97,110,103,101,108,45\n,45,62,60,47,103,105,102,116,115,115,116,101,118,101,45,108,105,110,107,98,111,\n100,121,46,125,41,59,10,9,109,111,117,110,116,32,40,49,57,57,70,65,81,60,47,114,\n111,103,101,114,102,114,97,110,107,67,108,97,115,115,50,56,112,120,59,102,101,\n101,100,115,60,104,49,62,60,115,99,111,116,116,116,101,115,116,115,50,50,112,120\n,59,100,114,105,110,107,41,32,124,124,32,108,101,119,105,115,115,104,97,108,108,\n35,48,51,57,59,32,102,111,114,32,108,111,118,101,100,119,97,115,116,101,48,48,\n112,120,59,106,97,58,227,130,115,105,109,111,110,60,102,111,110,116,114,101,112,\n108,121,109,101,101,116,115,117,110,116,101,114,99,104,101,97,112,116,105,103,\n104,116,66,114,97,110,100,41,32,33,61,32,100,114,101,115,115,99,108,105,112,115,\n114,111,111,109,115,111,110,107,101,121,109,111,98,105,108,109,97,105,110,46,78,\n97,109,101,32,112,108,97,116,101,102,117,110,110,121,116,114,101,101,115,99,111,\n109,47,34,49,46,106,112,103,119,109,111,100,101,112,97,114,97,109,83,84,65,82,84\n,108,101,102,116,32,105,100,100,101,110,44,32,50,48,49,41,59,10,125,10,102,111,\n114,109,46,118,105,114,117,115,99,104,97,105,114,116,114,97,110,115,119,111,114,\n115,116,80,97,103,101,115,105,116,105,111,110,112,97,116,99,104,60,33,45,45,10,\n111,45,99,97,99,102,105,114,109,115,116,111,117,114,115,44,48,48,48,32,97,115,\n105,97,110,105,43,43,41,123,97,100,111,98,101,39,41,91,48,93,105,100,61,49,48,98\n,111,116,104,59,109,101,110,117,32,46,50,46,109,105,46,112,110,103,34,107,101,\n118,105,110,99,111,97,99,104,67,104,105,108,100,98,114,117,99,101,50,46,106,112,\n103,85,82,76,41,43,46,106,112,103,124,115,117,105,116,101,115,108,105,99,101,104\n,97,114,114,121,49,50,48,34,32,115,119,101,101,116,116,114,62,13,10,110,97,109,\n101,61,100,105,101,103,111,112,97,103,101,32,115,119,105,115,115,45,45,62,10,10,\n35,102,102,102,59,34,62,76,111,103,46,99,111,109,34,116,114,101,97,116,115,104,\n101,101,116,41,32,38,38,32,49,52,112,120,59,115,108,101,101,112,110,116,101,110,\n116,102,105,108,101,100,106,97,58,227,131,105,100,61,34,99,78,97,109,101,34,119,\n111,114,115,101,115,104,111,116,115,45,98,111,120,45,100,101,108,116,97,10,38,\n108,116,59,98,101,97,114,115,58,52,56,90,60,100,97,116,97,45,114,117,114,97,108,\n60,47,97,62,32,115,112,101,110,100,98,97,107,101,114,115,104,111,112,115,61,32,\n34,34,59,112,104,112,34,62,99,116,105,111,110,49,51,112,120,59,98,114,105,97,110\n,104,101,108,108,111,115,105,122,101,61,111,61,37,50,70,32,106,111,105,110,109,\n97,121,98,101,60,105,109,103,32,105,109,103,34,62,44,32,102,106,115,105,109,103,\n34,32,34,41,91,48,93,77,84,111,112,66,84,121,112,101,34,110,101,119,108,121,68,\n97,110,115,107,99,122,101,99,104,116,114,97,105,108,107,110,111,119,115,60,47,\n104,53,62,102,97,113,34,62,122,104,45,99,110,49,48,41,59,10,45,49,34,41,59,116,\n121,112,101,61,98,108,117,101,115,116,114,117,108,121,100,97,118,105,115,46,106,\n115,39,59,62,13,10,60,33,115,116,101,101,108,32,121,111,117,32,104,50,62,13,10,\n102,111,114,109,32,106,101,115,117,115,49,48,48,37,32,109,101,110,117,46,13,10,9\n,13,10,119,97,108,101,115,114,105,115,107,115,117,109,101,110,116,100,100,105,\n110,103,98,45,108,105,107,116,101,97,99,104,103,105,102,34,32,118,101,103,97,115\n,100,97,110,115,107,101,101,115,116,105,115,104,113,105,112,115,117,111,109,105,\n115,111,98,114,101,100,101,115,100,101,101,110,116,114,101,116,111,100,111,115,\n112,117,101,100,101,97,195,177,111,115,101,115,116,195,161,116,105,101,110,101,\n104,97,115,116,97,111,116,114,111,115,112,97,114,116,101,100,111,110,100,101,110\n,117,101,118,111,104,97,99,101,114,102,111,114,109,97,109,105,115,109,111,109,\n101,106,111,114,109,117,110,100,111,97,113,117,195,173,100,195,173,97,115,115,\n195,179,108,111,97,121,117,100,97,102,101,99,104,97,116,111,100,97,115,116,97,\n110,116,111,109,101,110,111,115,100,97,116,111,115,111,116,114,97,115,115,105,\n116,105,111,109,117,99,104,111,97,104,111,114,97,108,117,103,97,114,109,97,121,\n111,114,101,115,116,111,115,104,111,114,97,115,116,101,110,101,114,97,110,116,\n101,115,102,111,116,111,115,101,115,116,97,115,112,97,195,173,115,110,117,101,\n118,97,115,97,108,117,100,102,111,114,111,115,109,101,100,105,111,113,117,105,\n101,110,109,101,115,101,115,112,111,100,101,114,99,104,105,108,101,115,101,114,\n195,161,118,101,99,101,115,100,101,99,105,114,106,111,115,195,169,101,115,116,97\n,114,118,101,110,116,97,103,114,117,112,111,104,101,99,104,111,101,108,108,111,\n115,116,101,110,103,111,97,109,105,103,111,99,111,115,97,115,110,105,118,101,108\n,103,101,110,116,101,109,105,115,109,97,97,105,114,101,115,106,117,108,105,111,\n116,101,109,97,115,104,97,99,105,97,102,97,118,111,114,106,117,110,105,111,108,\n105,98,114,101,112,117,110,116,111,98,117,101,110,111,97,117,116,111,114,97,98,\n114,105,108,98,117,101,110,97,116,101,120,116,111,109,97,114,122,111,115,97,98,\n101,114,108,105,115,116,97,108,117,101,103,111,99,195,179,109,111,101,110,101,\n114,111,106,117,101,103,111,112,101,114,195,186,104,97,98,101,114,101,115,116,\n111,121,110,117,110,99,97,109,117,106,101,114,118,97,108,111,114,102,117,101,114\n,97,108,105,98,114,111,103,117,115,116,97,105,103,117,97,108,118,111,116,111,115\n,99,97,115,111,115,103,117,195,173,97,112,117,101,100,111,115,111,109,111,115,97\n,118,105,115,111,117,115,116,101,100,100,101,98,101,110,110,111,99,104,101,98,\n117,115,99,97,102,97,108,116,97,101,117,114,111,115,115,101,114,105,101,100,105,\n99,104,111,99,117,114,115,111,99,108,97,118,101,99,97,115,97,115,108,101,195,179\n,110,112,108,97,122,111,108,97,114,103,111,111,98,114,97,115,118,105,115,116,97,\n97,112,111,121,111,106,117,110,116,111,116,114,97,116,97,118,105,115,116,111,99,\n114,101,97,114,99,97,109,112,111,104,101,109,111,115,99,105,110,99,111,99,97,114\n,103,111,112,105,115,111,115,111,114,100,101,110,104,97,99,101,110,195,161,114,\n101,97,100,105,115,99,111,112,101,100,114,111,99,101,114,99,97,112,117,101,100,\n97,112,97,112,101,108,109,101,110,111,114,195,186,116,105,108,99,108,97,114,111,\n106,111,114,103,101,99,97,108,108,101,112,111,110,101,114,116,97,114,100,101,110\n,97,100,105,101,109,97,114,99,97,115,105,103,117,101,101,108,108,97,115,115,105,\n103,108,111,99,111,99,104,101,109,111,116,111,115,109,97,100,114,101,99,108,97,\n115,101,114,101,115,116,111,110,105,195,177,111,113,117,101,100,97,112,97,115,97\n,114,98,97,110,99,111,104,105,106,111,115,118,105,97,106,101,112,97,98,108,111,\n195,169,115,116,101,118,105,101,110,101,114,101,105,110,111,100,101,106,97,114,\n102,111,110,100,111,99,97,110,97,108,110,111,114,116,101,108,101,116,114,97,99,\n97,117,115,97,116,111,109,97,114,109,97,110,111,115,108,117,110,101,115,97,117,\n116,111,115,118,105,108,108,97,118,101,110,100,111,112,101,115,97,114,116,105,\n112,111,115,116,101,110,103,97,109,97,114,99,111,108,108,101,118,97,112,97,100,\n114,101,117,110,105,100,111,118,97,109,111,115,122,111,110,97,115,97,109,98,111,\n115,98,97,110,100,97,109,97,114,105,97,97,98,117,115,111,109,117,99,104,97,115,\n117,98,105,114,114,105,111,106,97,118,105,118,105,114,103,114,97,100,111,99,104,\n105,99,97,97,108,108,195,173,106,111,118,101,110,100,105,99,104,97,101,115,116,\n97,110,116,97,108,101,115,115,97,108,105,114,115,117,101,108,111,112,101,115,111\n,115,102,105,110,101,115,108,108,97,109,97,98,117,115,99,111,195,169,115,116,97,\n108,108,101,103,97,110,101,103,114,111,112,108,97,122,97,104,117,109,111,114,112\n,97,103,97,114,106,117,110,116,97,100,111,98,108,101,105,115,108,97,115,98,111,\n108,115,97,98,97,195,177,111,104,97,98,108,97,108,117,99,104,97,195,129,114,101,\n97,100,105,99,101,110,106,117,103,97,114,110,111,116,97,115,118,97,108,108,101,\n97,108,108,195,161,99,97,114,103,97,100,111,108,111,114,97,98,97,106,111,101,115\n,116,195,169,103,117,115,116,111,109,101,110,116,101,109,97,114,105,111,102,105,\n114,109,97,99,111,115,116,111,102,105,99,104,97,112,108,97,116,97,104,111,103,97\n,114,97,114,116,101,115,108,101,121,101,115,97,113,117,101,108,109,117,115,101,\n111,98,97,115,101,115,112,111,99,111,115,109,105,116,97,100,99,105,101,108,111,\n99,104,105,99,111,109,105,101,100,111,103,97,110,97,114,115,97,110,116,111,101,\n116,97,112,97,100,101,98,101,115,112,108,97,121,97,114,101,100,101,115,115,105,\n101,116,101,99,111,114,116,101,99,111,114,101,97,100,117,100,97,115,100,101,115,\n101,111,118,105,101,106,111,100,101,115,101,97,97,103,117,97,115,38,113,117,111,\n116,59,100,111,109,97,105,110,99,111,109,109,111,110,115,116,97,116,117,115,101,\n118,101,110,116,115,109,97,115,116,101,114,115,121,115,116,101,109,97,99,116,105\n,111,110,98,97,110,110,101,114,114,101,109,111,118,101,115,99,114,111,108,108,\n117,112,100,97,116,101,103,108,111,98,97,108,109,101,100,105,117,109,102,105,108\n,116,101,114,110,117,109,98,101,114,99,104,97,110,103,101,114,101,115,117,108,\n116,112,117,98,108,105,99,115,99,114,101,101,110,99,104,111,111,115,101,110,111,\n114,109,97,108,116,114,97,118,101,108,105,115,115,117,101,115,115,111,117,114,99\n,101,116,97,114,103,101,116,115,112,114,105,110,103,109,111,100,117,108,101,109,\n111,98,105,108,101,115,119,105,116,99,104,112,104,111,116,111,115,98,111,114,100\n,101,114,114,101,103,105,111,110,105,116,115,101,108,102,115,111,99,105,97,108,\n97,99,116,105,118,101,99,111,108,117,109,110,114,101,99,111,114,100,102,111,108,\n108,111,119,116,105,116,108,101,62,101,105,116,104,101,114,108,101,110,103,116,\n104,102,97,109,105,108,121,102,114,105,101,110,100,108,97,121,111,117,116,97,117\n,116,104,111,114,99,114,101,97,116,101,114,101,118,105,101,119,115,117,109,109,\n101,114,115,101,114,118,101,114,112,108,97,121,101,100,112,108,97,121,101,114,\n101,120,112,97,110,100,112,111,108,105,99,121,102,111,114,109,97,116,100,111,117\n,98,108,101,112,111,105,110,116,115,115,101,114,105,101,115,112,101,114,115,111,\n110,108,105,118,105,110,103,100,101,115,105,103,110,109,111,110,116,104,115,102,\n111,114,99,101,115,117,110,105,113,117,101,119,101,105,103,104,116,112,101,111,\n112,108,101,101,110,101,114,103,121,110,97,116,117,114,101,115,101,97,114,99,104\n,102,105,103,117,114,101,104,97,118,105,110,103,99,117,115,116,111,109,111,102,\n102,115,101,116,108,101,116,116,101,114,119,105,110,100,111,119,115,117,98,109,\n105,116,114,101,110,100,101,114,103,114,111,117,112,115,117,112,108,111,97,100,\n104,101,97,108,116,104,109,101,116,104,111,100,118,105,100,101,111,115,115,99,\n104,111,111,108,102,117,116,117,114,101,115,104,97,100,111,119,100,101,98,97,116\n,101,118,97,108,117,101,115,79,98,106,101,99,116,111,116,104,101,114,115,114,105\n,103,104,116,115,108,101,97,103,117,101,99,104,114,111,109,101,115,105,109,112,\n108,101,110,111,116,105,99,101,115,104,97,114,101,100,101,110,100,105,110,103,\n115,101,97,115,111,110,114,101,112,111,114,116,111,110,108,105,110,101,115,113,\n117,97,114,101,98,117,116,116,111,110,105,109,97,103,101,115,101,110,97,98,108,\n101,109,111,118,105,110,103,108,97,116,101,115,116,119,105,110,116,101,114,70,\n114,97,110,99,101,112,101,114,105,111,100,115,116,114,111,110,103,114,101,112,\n101,97,116,76,111,110,100,111,110,100,101,116,97,105,108,102,111,114,109,101,100\n,100,101,109,97,110,100,115,101,99,117,114,101,112,97,115,115,101,100,116,111,\n103,103,108,101,112,108,97,99,101,115,100,101,118,105,99,101,115,116,97,116,105,\n99,99,105,116,105,101,115,115,116,114,101,97,109,121,101,108,108,111,119,97,116,\n116,97,99,107,115,116,114,101,101,116,102,108,105,103,104,116,104,105,100,100,\n101,110,105,110,102,111,34,62,111,112,101,110,101,100,117,115,101,102,117,108,\n118,97,108,108,101,121,99,97,117,115,101,115,108,101,97,100,101,114,115,101,99,\n114,101,116,115,101,99,111,110,100,100,97,109,97,103,101,115,112,111,114,116,115\n,101,120,99,101,112,116,114,97,116,105,110,103,115,105,103,110,101,100,116,104,\n105,110,103,115,101,102,102,101,99,116,102,105,101,108,100,115,115,116,97,116,\n101,115,111,102,102,105,99,101,118,105,115,117,97,108,101,100,105,116,111,114,\n118,111,108,117,109,101,82,101,112,111,114,116,109,117,115,101,117,109,109,111,\n118,105,101,115,112,97,114,101,110,116,97,99,99,101,115,115,109,111,115,116,108,\n121,109,111,116,104,101,114,34,32,105,100,61,34,109,97,114,107,101,116,103,114,\n111,117,110,100,99,104,97,110,99,101,115,117,114,118,101,121,98,101,102,111,114,\n101,115,121,109,98,111,108,109,111,109,101,110,116,115,112,101,101,99,104,109,\n111,116,105,111,110,105,110,115,105,100,101,109,97,116,116,101,114,67,101,110,\n116,101,114,111,98,106,101,99,116,101,120,105,115,116,115,109,105,100,100,108,\n101,69,117,114,111,112,101,103,114,111,119,116,104,108,101,103,97,99,121,109,97,\n110,110,101,114,101,110,111,117,103,104,99,97,114,101,101,114,97,110,115,119,101\n,114,111,114,105,103,105,110,112,111,114,116,97,108,99,108,105,101,110,116,115,\n101,108,101,99,116,114,97,110,100,111,109,99,108,111,115,101,100,116,111,112,105\n,99,115,99,111,109,105,110,103,102,97,116,104,101,114,111,112,116,105,111,110,\n115,105,109,112,108,121,114,97,105,115,101,100,101,115,99,97,112,101,99,104,111,\n115,101,110,99,104,117,114,99,104,100,101,102,105,110,101,114,101,97,115,111,110\n,99,111,114,110,101,114,111,117,116,112,117,116,109,101,109,111,114,121,105,102,\n114,97,109,101,112,111,108,105,99,101,109,111,100,101,108,115,78,117,109,98,101,\n114,100,117,114,105,110,103,111,102,102,101,114,115,115,116,121,108,101,115,107,\n105,108,108,101,100,108,105,115,116,101,100,99,97,108,108,101,100,115,105,108,\n118,101,114,109,97,114,103,105,110,100,101,108,101,116,101,98,101,116,116,101,\n114,98,114,111,119,115,101,108,105,109,105,116,115,71,108,111,98,97,108,115,105,\n110,103,108,101,119,105,100,103,101,116,99,101,110,116,101,114,98,117,100,103,\n101,116,110,111,119,114,97,112,99,114,101,100,105,116,99,108,97,105,109,115,101,\n110,103,105,110,101,115,97,102,101,116,121,99,104,111,105,99,101,115,112,105,114\n,105,116,45,115,116,121,108,101,115,112,114,101,97,100,109,97,107,105,110,103,\n110,101,101,100,101,100,114,117,115,115,105,97,112,108,101,97,115,101,101,120,\n116,101,110,116,83,99,114,105,112,116,98,114,111,107,101,110,97,108,108,111,119,\n115,99,104,97,114,103,101,100,105,118,105,100,101,102,97,99,116,111,114,109,101,\n109,98,101,114,45,98,97,115,101,100,116,104,101,111,114,121,99,111,110,102,105,\n103,97,114,111,117,110,100,119,111,114,107,101,100,104,101,108,112,101,100,67,\n104,117,114,99,104,105,109,112,97,99,116,115,104,111,117,108,100,97,108,119,97,\n121,115,108,111,103,111,34,32,98,111,116,116,111,109,108,105,115,116,34,62,41,\n123,118,97,114,32,112,114,101,102,105,120,111,114,97,110,103,101,72,101,97,100,\n101,114,46,112,117,115,104,40,99,111,117,112,108,101,103,97,114,100,101,110,98,\n114,105,100,103,101,108,97,117,110,99,104,82,101,118,105,101,119,116,97,107,105,\n110,103,118,105,115,105,111,110,108,105,116,116,108,101,100,97,116,105,110,103,\n66,117,116,116,111,110,98,101,97,117,116,121,116,104,101,109,101,115,102,111,114\n,103,111,116,83,101,97,114,99,104,97,110,99,104,111,114,97,108,109,111,115,116,\n108,111,97,100,101,100,67,104,97,110,103,101,114,101,116,117,114,110,115,116,114\n,105,110,103,114,101,108,111,97,100,77,111,98,105,108,101,105,110,99,111,109,101\n,115,117,112,112,108,121,83,111,117,114,99,101,111,114,100,101,114,115,118,105,\n101,119,101,100,38,110,98,115,112,59,99,111,117,114,115,101,65,98,111,117,116,32\n,105,115,108,97,110,100,60,104,116,109,108,32,99,111,111,107,105,101,110,97,109,\n101,61,34,97,109,97,122,111,110,109,111,100,101,114,110,97,100,118,105,99,101,\n105,110,60,47,97,62,58,32,84,104,101,32,100,105,97,108,111,103,104,111,117,115,\n101,115,66,69,71,73,78,32,77,101,120,105,99,111,115,116,97,114,116,115,99,101,\n110,116,114,101,104,101,105,103,104,116,97,100,100,105,110,103,73,115,108,97,110\n,100,97,115,115,101,116,115,69,109,112,105,114,101,83,99,104,111,111,108,101,102\n,102,111,114,116,100,105,114,101,99,116,110,101,97,114,108,121,109,97,110,117,97\n,108,83,101,108,101,99,116,46,10,10,79,110,101,106,111,105,110,101,100,109,101,\n110,117,34,62,80,104,105,108,105,112,97,119,97,114,100,115,104,97,110,100,108,\n101,105,109,112,111,114,116,79,102,102,105,99,101,114,101,103,97,114,100,115,107\n,105,108,108,115,110,97,116,105,111,110,83,112,111,114,116,115,100,101,103,114,\n101,101,119,101,101,107,108,121,32,40,101,46,103,46,98,101,104,105,110,100,100,\n111,99,116,111,114,108,111,103,103,101,100,117,110,105,116,101,100,60,47,98,62,\n60,47,98,101,103,105,110,115,112,108,97,110,116,115,97,115,115,105,115,116,97,\n114,116,105,115,116,105,115,115,117,101,100,51,48,48,112,120,124,99,97,110,97,\n100,97,97,103,101,110,99,121,115,99,104,101,109,101,114,101,109,97,105,110,66,\n114,97,122,105,108,115,97,109,112,108,101,108,111,103,111,34,62,98,101,121,111,\n110,100,45,115,99,97,108,101,97,99,99,101,112,116,115,101,114,118,101,100,109,97\n,114,105,110,101,70,111,111,116,101,114,99,97,109,101,114,97,60,47,104,49,62,10,\n95,102,111,114,109,34,108,101,97,118,101,115,115,116,114,101,115,115,34,32,47,62\n,13,10,46,103,105,102,34,32,111,110,108,111,97,100,108,111,97,100,101,114,79,120\n,102,111,114,100,115,105,115,116,101,114,115,117,114,118,105,118,108,105,115,116\n,101,110,102,101,109,97,108,101,68,101,115,105,103,110,115,105,122,101,61,34,97,\n112,112,101,97,108,116,101,120,116,34,62,108,101,118,101,108,115,116,104,97,110,\n107,115,104,105,103,104,101,114,102,111,114,99,101,100,97,110,105,109,97,108,97,\n110,121,111,110,101,65,102,114,105,99,97,97,103,114,101,101,100,114,101,99,101,\n110,116,80,101,111,112,108,101,60,98,114,32,47,62,119,111,110,100,101,114,112,\n114,105,99,101,115,116,117,114,110,101,100,124,124,32,123,125,59,109,97,105,110,\n34,62,105,110,108,105,110,101,115,117,110,100,97,121,119,114,97,112,34,62,102,97\n,105,108,101,100,99,101,110,115,117,115,109,105,110,117,116,101,98,101,97,99,111\n,110,113,117,111,116,101,115,49,53,48,112,120,124,101,115,116,97,116,101,114,101\n,109,111,116,101,101,109,97,105,108,34,108,105,110,107,101,100,114,105,103,104,\n116,59,115,105,103,110,97,108,102,111,114,109,97,108,49,46,104,116,109,108,115,\n105,103,110,117,112,112,114,105,110,99,101,102,108,111,97,116,58,46,112,110,103,\n34,32,102,111,114,117,109,46,65,99,99,101,115,115,112,97,112,101,114,115,115,111\n,117,110,100,115,101,120,116,101,110,100,72,101,105,103,104,116,115,108,105,100,\n101,114,85,84,70,45,56,34,38,97,109,112,59,32,66,101,102,111,114,101,46,32,87,\n105,116,104,115,116,117,100,105,111,111,119,110,101,114,115,109,97,110,97,103,\n101,112,114,111,102,105,116,106,81,117,101,114,121,97,110,110,117,97,108,112,97,\n114,97,109,115,98,111,117,103,104,116,102,97,109,111,117,115,103,111,111,103,108\n,101,108,111,110,103,101,114,105,43,43,41,32,123,105,115,114,97,101,108,115,97,\n121,105,110,103,100,101,99,105,100,101,104,111,109,101,34,62,104,101,97,100,101,\n114,101,110,115,117,114,101,98,114,97,110,99,104,112,105,101,99,101,115,98,108,\n111,99,107,59,115,116,97,116,101,100,116,111,112,34,62,60,114,97,99,105,110,103,\n114,101,115,105,122,101,45,45,38,103,116,59,112,97,99,105,116,121,115,101,120,\n117,97,108,98,117,114,101,97,117,46,106,112,103,34,32,49,48,44,48,48,48,111,98,\n116,97,105,110,116,105,116,108,101,115,97,109,111,117,110,116,44,32,73,110,99,46\n,99,111,109,101,100,121,109,101,110,117,34,32,108,121,114,105,99,115,116,111,100\n,97,121,46,105,110,100,101,101,100,99,111,117,110,116,121,95,108,111,103,111,46,\n70,97,109,105,108,121,108,111,111,107,101,100,77,97,114,107,101,116,108,115,101,\n32,105,102,80,108,97,121,101,114,116,117,114,107,101,121,41,59,118,97,114,32,102\n,111,114,101,115,116,103,105,118,105,110,103,101,114,114,111,114,115,68,111,109,\n97,105,110,125,101,108,115,101,123,105,110,115,101,114,116,66,108,111,103,60,47,\n102,111,111,116,101,114,108,111,103,105,110,46,102,97,115,116,101,114,97,103,101\n,110,116,115,60,98,111,100,121,32,49,48,112,120,32,48,112,114,97,103,109,97,102,\n114,105,100,97,121,106,117,110,105,111,114,100,111,108,108,97,114,112,108,97,99,\n101,100,99,111,118,101,114,115,112,108,117,103,105,110,53,44,48,48,48,32,112,97,\n103,101,34,62,98,111,115,116,111,110,46,116,101,115,116,40,97,118,97,116,97,114,\n116,101,115,116,101,100,95,99,111,117,110,116,102,111,114,117,109,115,115,99,104\n,101,109,97,105,110,100,101,120,44,102,105,108,108,101,100,115,104,97,114,101,\n115,114,101,97,100,101,114,97,108,101,114,116,40,97,112,112,101,97,114,83,117,98\n,109,105,116,108,105,110,101,34,62,98,111,100,121,34,62,10,42,32,84,104,101,84,\n104,111,117,103,104,115,101,101,105,110,103,106,101,114,115,101,121,78,101,119,\n115,60,47,118,101,114,105,102,121,101,120,112,101,114,116,105,110,106,117,114,\n121,119,105,100,116,104,61,67,111,111,107,105,101,83,84,65,82,84,32,97,99,114,\n111,115,115,95,105,109,97,103,101,116,104,114,101,97,100,110,97,116,105,118,101,\n112,111,99,107,101,116,98,111,120,34,62,10,83,121,115,116,101,109,32,68,97,118,\n105,100,99,97,110,99,101,114,116,97,98,108,101,115,112,114,111,118,101,100,65,\n112,114,105,108,32,114,101,97,108,108,121,100,114,105,118,101,114,105,116,101,\n109,34,62,109,111,114,101,34,62,98,111,97,114,100,115,99,111,108,111,114,115,99,\n97,109,112,117,115,102,105,114,115,116,32,124,124,32,91,93,59,109,101,100,105,97\n,46,103,117,105,116,97,114,102,105,110,105,115,104,119,105,100,116,104,58,115,\n104,111,119,101,100,79,116,104,101,114,32,46,112,104,112,34,32,97,115,115,117,\n109,101,108,97,121,101,114,115,119,105,108,115,111,110,115,116,111,114,101,115,\n114,101,108,105,101,102,115,119,101,100,101,110,67,117,115,116,111,109,101,97,\n115,105,108,121,32,121,111,117,114,32,83,116,114,105,110,103,10,10,87,104,105,\n108,116,97,121,108,111,114,99,108,101,97,114,58,114,101,115,111,114,116,102,114,\n101,110,99,104,116,104,111,117,103,104,34,41,32,43,32,34,60,98,111,100,121,62,98\n,117,121,105,110,103,98,114,97,110,100,115,77,101,109,98,101,114,110,97,109,101,\n34,62,111,112,112,105,110,103,115,101,99,116,111,114,53,112,120,59,34,62,118,115\n,112,97,99,101,112,111,115,116,101,114,109,97,106,111,114,32,99,111,102,102,101,\n101,109,97,114,116,105,110,109,97,116,117,114,101,104,97,112,112,101,110,60,47,\n110,97,118,62,107,97,110,115,97,115,108,105,110,107,34,62,73,109,97,103,101,115,\n61,102,97,108,115,101,119,104,105,108,101,32,104,115,112,97,99,101,48,38,97,109,\n112,59,32,10,10,73,110,32,32,112,111,119,101,114,80,111,108,115,107,105,45,99,\n111,108,111,114,106,111,114,100,97,110,66,111,116,116,111,109,83,116,97,114,116,\n32,45,99,111,117,110,116,50,46,104,116,109,108,110,101,119,115,34,62,48,49,46,\n106,112,103,79,110,108,105,110,101,45,114,105,103,104,116,109,105,108,108,101,\n114,115,101,110,105,111,114,73,83,66,78,32,48,48,44,48,48,48,32,103,117,105,100,\n101,115,118,97,108,117,101,41,101,99,116,105,111,110,114,101,112,97,105,114,46,\n120,109,108,34,32,32,114,105,103,104,116,115,46,104,116,109,108,45,98,108,111,99\n,107,114,101,103,69,120,112,58,104,111,118,101,114,119,105,116,104,105,110,118,\n105,114,103,105,110,112,104,111,110,101,115,60,47,116,114,62,13,117,115,105,110,\n103,32,10,9,118,97,114,32,62,39,41,59,10,9,60,47,116,100,62,10,60,47,116,114,62,\n10,98,97,104,97,115,97,98,114,97,115,105,108,103,97,108,101,103,111,109,97,103,\n121,97,114,112,111,108,115,107,105,115,114,112,115,107,105,216,177,216,175,217,\n136,228,184,173,230,150,135,231,174,128,228,189,147,231,185,129,233,171,148,228,\n191,161,230,129,175,228,184,173,229,155,189,230,136,145,228,187,172,228,184,128,\n228,184,170,229,133,172,229,143,184,231,174,161,231,144,134,232,174,186,229,157,\n155,229,143,175,228,187,165,230,156,141,229,138,161,230,151,182,233,151,180,228,\n184,170,228,186,186,228,186,167,229,147,129,232,135,170,229,183,177,228,188,129,\n228,184,154,230,159,165,231,156,139,229,183,165,228,189,156,232,129,148,231,179,\n187,230,178,161,230,156,137,231,189,145,231,171,153,230,137,128,230,156,137,232,\n175,132,232,174,186,228,184,173,229,191,131,230,150,135,231,171,160,231,148,168,\n230,136,183,233,166,150,233,161,181,228,189,156,232,128,133,230,138,128,230,156,\n175,233,151,174,233,162,152,231,155,184,229,133,179,228,184,139,232,189,189,230,\n144,156,231,180,162,228,189,191,231,148,168,232,189,175,228,187,182,229,156,168,\n231,186,191,228,184,187,233,162,152,232,181,132,230,150,153,232,167,134,233,162,\n145,229,155,158,229,164,141,230,179,168,229,134,140,231,189,145,231,187,156,230,\n148,182,232,151,143,229,134,133,229,174,185,230,142,168,232,141,144,229,184,130,\n229,156,186,230,182,136,230,129,175,231,169,186,233,151,180,229,143,145,229,184,\n131,228,187,128,228,185,136,229,165,189,229,143,139,231,148,159,230,180,187,229,\n155,190,231,137,135,229,143,145,229,177,149,229,166,130,230,158,156,230,137,139,\n230,156,186,230,150,176,233,151,187,230,156,128,230,150,176,230,150,185,229,188,\n143,229,140,151,228,186,172,230,143,144,228,190,155,229,133,179,228,186,142,230,\n155,180,229,164,154,232,191,153,228,184,170,231,179,187,231,187,159,231,159,165,\n233,129,147,230,184,184,230,136,143,229,185,191,229,145,138,229,133,182,228,187,\n150,229,143,145,232,161,168,229,174,137,229,133,168,231,172,172,228,184,128,228,\n188,154,229,145,152,232,191,155,232,161,140,231,130,185,229,135,187,231,137,136,\n230,157,131,231,148,181,229,173,144,228,184,150,231,149,140,232,174,190,232,174,\n161,229,133,141,232,180,185,230,149,153,232,130,178,229,138,160,229,133,165,230,\n180,187,229,138,168,228,187,150,228,187,172,229,149,134,229,147,129,229,141,154,\n229,174,162,231,142,176,229,156,168,228,184,138,230,181,183,229,166,130,228,189,\n149,229,183,178,231,187,143,231,149,153,232,168,128,232,175,166,231,187,134,231,\n164,190,229,140,186,231,153,187,229,189,149,230,156,172,231,171,153,233,156,128,\n232,166,129,228,187,183,230,160,188,230,148,175,230,140,129,229,155,189,233,153,\n133,233,147,190,230,142,165,229,155,189,229,174,182,229,187,186,232,174,190,230,\n156,139,229,143,139,233,152,133,232,175,187,230,179,149,229,190,139,228,189,141,\n231,189,174,231,187,143,230,181,142,233,128,137,230,139,169,232,191,153,230,160,\n183,229,189,147,229,137,141,229,136,134,231,177,187,230,142,146,232,161,140,229,\n155,160,228,184,186,228,186,164,230,152,147,230,156,128,229,144,142,233,159,179,\n228,185,144,228,184,141,232,131,189,233,128,154,232,191,135,232,161,140,228,184,\n154,231,167,145,230,138,128,229,143,175,232,131,189,232,174,190,229,164,135,229,\n144,136,228,189,156,229,164,167,229,174,182,231,164,190,228,188,154,231,160,148,\n231,169,182,228,184,147,228,184,154,229,133,168,233,131,168,233,161,185,231,155,\n174,232,191,153,233,135,140,232,191,152,230,152,175,229,188,128,229,167,139,230,\n131,133,229,134,181,231,148,181,232,132,145,230,150,135,228,187,182,229,147,129,\n231,137,140,229,184,174,229,138,169,230,150,135,229,140,150,232,181,132,230,186,\n144,229,164,167,229,173,166,229,173,166,228,185,160,229,156,176,229,157,128,230,\n181,143,232,167,136,230,138,149,232,181,132,229,183,165,231,168,139,232,166,129,\n230,177,130,230,128,142,228,185,136,230,151,182,229,128,153,229,138,159,232,131,\n189,228,184,187,232,166,129,231,155,174,229,137,141,232,181,132,232,174,175,229,\n159,142,229,184,130,230,150,185,230,179,149,231,148,181,229,189,177,230,139,155,\n232,129,152,229,163,176,230,152,142,228,187,187,228,189,149,229,129,165,229,186,\n183,230,149,176,230,141,174,231,190,142,229,155,189,230,177,189,232,189,166,228,\n187,139,231,187,141,228,189,134,230,152,175,228,186,164,230,181,129,231,148,159,\n228,186,167,230,137,128,228,187,165,231,148,181,232,175,157,230,152,190,231,164,\n186,228,184,128,228,186,155,229,141,149,228,189,141,228,186,186,229,145,152,229,\n136,134,230,158,144,229,156,176,229,155,190,230,151,133,230,184,184,229,183,165,\n229,133,183,229,173,166,231,148,159,231,179,187,229,136,151,231,189,145,229,143,\n139,229,184,150,229,173,144,229,175,134,231,160,129,233,162,145,233,129,147,230,\n142,167,229,136,182,229,156,176,229,140,186,229,159,186,230,156,172,229,133,168,\n229,155,189,231,189,145,228,184,138,233,135,141,232,166,129,231,172,172,228,186,\n140,229,150,156,230,172,162,232,191,155,229,133,165,229,143,139,230,131,133,232,\n191,153,228,186,155,232,128,131,232,175,149,229,143,145,231,142,176,229,159,185,\n232,174,173,228,187,165,228,184,138,230,148,191,229,186,156,230,136,144,228,184,\n186,231,142,175,229,162,131,233,166,153,230,184,175,229,144,140,230,151,182,229,\n168,177,228,185,144,229,143,145,233,128,129,228,184,128,229,174,154,229,188,128,\n229,143,145,228,189,156,229,147,129,230,160,135,229,135,134,230,172,162,232,191,\n142,232,167,163,229,134,179,229,156,176,230,150,185,228,184,128,228,184,139,228,\n187,165,229,143,138,232,180,163,228,187,187,230,136,150,232,128,133,229,174,162,\n230,136,183,228,187,163,232,161,168,231,167,175,229,136,134,229,165,179,228,186,\n186,230,149,176,231,160,129,233,148,128,229,148,174,229,135,186,231,142,176,231,\n166,187,231,186,191,229,186,148,231,148,168,229,136,151,232,161,168,228,184,141,\n229,144,140,231,188,150,232,190,145,231,187,159,232,174,161,230,159,165,232,175,\n162,228,184,141,232,166,129,230,156,137,229,133,179,230,156,186,230,158,132,229,\n190,136,229,164,154,230,146,173,230,148,190,231,187,132,231,187,135,230,148,191,\n231,173,150,231,155,180,230,142,165,232,131,189,229,138,155,230,157,165,230,186,\n144,230,153,130,233,150,147,231,156,139,229,136,176,231,131,173,233,151,168,229,\n133,179,233,148,174,228,184,147,229,140,186,233,157,158,229,184,184,232,139,177,\n232,175,173,231,153,190,229,186,166,229,184,140,230,156,155,231,190,142,229,165,\n179,230,175,148,232,190,131,231,159,165,232,175,134,232,167,132,229,174,154,229,\n187,186,232,174,174,233,131,168,233,151,168,230,132,143,232,167,129,231,178,190,\n229,189,169,230,151,165,230,156,172,230,143,144,233,171,152,229,143,145,232,168,\n128,230,150,185,233,157,162,229,159,186,233,135,145,229,164,132,231,144,134,230,\n157,131,233,153,144,229,189,177,231,137,135,233,147,182,232,161,140,232,191,152,\n230,156,137,229,136,134,228,186,171,231,137,169,229,147,129,231,187,143,232,144,\n165,230,183,187,229,138,160,228,184,147,229,174,182,232,191,153,231,167,141,232,\n175,157,233,162,152,232,181,183,230,157,165,228,184,154,229,138,161,229,133,172,\n229,145,138,232,174,176,229,189,149,231,174,128,228,187,139,232,180,168,233,135,\n143,231,148,183,228,186,186,229,189,177,229,147,141,229,188,149,231,148,168,230,\n138,165,229,145,138,233,131,168,229,136,134,229,191,171,233,128,159,229,146,168,\n232,175,162,230,151,182,229,176,154,230,179,168,230,132,143,231,148,179,232,175,\n183,229,173,166,230,160,161,229,186,148,232,175,165,229,142,134,229,143,178,229,\n143,170,230,152,175,232,191,148,229,155,158,232,180,173,228,185,176,229,144,141,\n231,167,176,228,184,186,228,186,134,230,136,144,229,138,159,232,175,180,230,152,\n142,228,190,155,229,186,148,229,173,169,229,173,144,228,184,147,233,162,152,231,\n168,139,229,186,143,228,184,128,232,136,172,230,156,131,229,147,161,229,143,170,\n230,156,137,229,133,182,229,174,131,228,191,157,230,138,164,232,128,140,228,184,\n148,228,187,138,229,164,169,231,170,151,229,143,163,229,138,168,230,128,129,231,\n138,182,230,128,129,231,137,185,229,136,171,232,174,164,228,184,186,229,191,133,\n233,161,187,230,155,180,230,150,176,229,176,143,232,175,180,230,136,145,229,128,\n145,228,189,156,228,184,186,229,170,146,228,189,147,229,140,133,230,139,172,233,\n130,163,228,185,136,228,184,128,230,160,183,229,155,189,229,134,133,230,152,175,\n229,144,166,230,160,185,230,141,174,231,148,181,232,167,134,229,173,166,233,153,\n162,229,133,183,230,156,137,232,191,135,231,168,139,231,148,177,228,186,142,228,\n186,186,230,137,141,229,135,186,230,157,165,228,184,141,232,191,135,230,173,163,\n229,156,168,230,152,142,230,152,159,230,149,133,228,186,139,229,133,179,231,179,\n187,230,160,135,233,162,152,229,149,134,229,138,161,232,190,147,229,133,165,228,\n184,128,231,155,180,229,159,186,231,161,128,230,149,153,229,173,166,228,186,134,\n232,167,163,229,187,186,231,173,145,231,187,147,230,158,156,229,133,168,231,144,\n131,233,128,154,231,159,165,232,174,161,229,136,146,229,175,185,228,186,142,232,\n137,186,230,156,175,231,155,184,229,134,140,229,143,145,231,148,159,231,156,159,\n231,154,132,229,187,186,231,171,139,231,173,137,231,186,167,231,177,187,229,158,\n139,231,187,143,233,170,140,229,174,158,231,142,176,229,136,182,228,189,156,230,\n157,165,232,135,170,230,160,135,231,173,190,228,187,165,228,184,139,229,142,159,\n229,136,155,230,151,160,230,179,149,229,133,182,228,184,173,229,128,139,228,186,\n186,228,184,128,229,136,135,230,140,135,229,141,151,229,133,179,233,151,173,233,\n155,134,229,155,162,231,172,172,228,184,137,229,133,179,230,179,168,229,155,160,\n230,173,164,231,133,167,231,137,135,230,183,177,229,156,179,229,149,134,228,184,\n154,229,185,191,229,183,158,230,151,165,230,156,159,233,171,152,231,186,167,230,\n156,128,232,191,145,231,187,188,229,144,136,232,161,168,231,164,186,228,184,147,\n232,190,145,232,161,140,228,184,186,228,186,164,233,128,154,232,175,132,228,187,\n183,232,167,137,229,190,151,231,178,190,229,141,142,229,174,182,229,186,173,229,\n174,140,230,136,144,230,132,159,232,167,137,229,174,137,232,163,133,229,190,151,\n229,136,176,233,130,174,228,187,182,229,136,182,229,186,166,233,163,159,229,147,\n129,232,153,189,231,132,182,232,189,172,232,189,189,230,138,165,228,187,183,232,\n174,176,232,128,133,230,150,185,230,161,136,232,161,140,230,148,191,228,186,186,\n230,176,145,231,148,168,229,147,129,228,184,156,232,165,191,230,143,144,229,135,\n186,233,133,146,229,186,151,231,132,182,229,144,142,228,187,152,230,172,190,231,\n131,173,231,130,185,228,187,165,229,137,141,229,174,140,229,133,168,229,143,145,\n229,184,150,232,174,190,231,189,174,233,162,134,229,175,188,229,183,165,228,184,\n154,229,140,187,233,153,162,231,156,139,231,156,139,231,187,143,229,133,184,229,\n142,159,229,155,160,229,185,179,229,143,176,229,144,132,231,167,141,229,162,158,\n229,138,160,230,157,144,230,150,153,230,150,176,229,162,158,228,185,139,229,144,\n142,232,129,140,228,184,154,230,149,136,230,158,156,228,187,138,229,185,180,232,\n174,186,230,150,135,230,136,145,229,155,189,229,145,138,232,175,137,231,137,136,\n228,184,187,228,191,174,230,148,185,229,143,130,228,184,142,230,137,147,229,141,\n176,229,191,171,228,185,144,230,156,186,230,162,176,232,167,130,231,130,185,229,\n173,152,229,156,168,231,178,190,231,165,158,232,142,183,229,190,151,229,136,169,\n231,148,168,231,187,167,231,187,173,228,189,160,228,187,172,232,191,153,228,185,\n136,230,168,161,229,188,143,232,175,173,232,168,128,232,131,189,229,164,159,233,\n155,133,232,153,142,230,147,141,228,189,156,233,163,142,230,160,188,228,184,128,\n232,181,183,231,167,145,229,173,166,228,189,147,232,130,178,231,159,173,228,191,\n161,230,157,161,228,187,182,230,178,187,231,150,151,232,191,144,229,138,168,228,\n186,167,228,184,154,228,188,154,232,174,174,229,175,188,232,136,170,229,133,136,\n231,148,159,232,129,148,231,155,159,229,143,175,230,152,175,229,149,143,233,161,\n140,231,187,147,230,158,132,228,189,156,231,148,168,232,176,131,230,159,165,232,\n179,135,230,150,153,232,135,170,229,138,168,232,180,159,232,180,163,229,134,156,\n228,184,154,232,174,191,233,151,174,229,174,158,230,150,189,230,142,165,229,143,\n151,232,174,168,232,174,186,233,130,163,228,184,170,229,143,141,233,166,136,229,\n138,160,229,188,186,229,165,179,230,128,167,232,140,131,229,155,180,230,156,141,\n229,139,153,228,188,145,233,151,178,228,187,138,230,151,165,229,174,162,230,156,\n141,232,167,128,231,156,139,229,143,130,229,138,160,231,154,132,232,175,157,228,\n184,128,231,130,185,228,191,157,232,175,129,229,155,190,228,185,166,230,156,137,\n230,149,136,230,181,139,232,175,149,231,167,187,229,138,168,230,137,141,232,131,\n189,229,134,179,229,174,154,232,130,161,231,165,168,228,184,141,230,150,173,233,\n156,128,230,177,130,228,184,141,229,190,151,229,138,158,230,179,149,228,185,139,\n233,151,180,233,135,135,231,148,168,232,144,165,233,148,128,230,138,149,232,175,\n137,231,155,174,230,160,135,231,136,177,230,131,133,230,145,132,229,189,177,230,\n156,137,228,186,155,232,164,135,232,163,189,230,150,135,229,173,166,230,156,186,\n228,188,154,230,149,176,229,173,151,232,163,133,228,191,174,232,180,173,231,137,\n169,229,134,156,230,157,145,229,133,168,233,157,162,231,178,190,229,147,129,229,\n133,182,229,174,158,228,186,139,230,131,133,230,176,180,229,185,179,230,143,144,\n231,164,186,228,184,138,229,184,130,232,176,162,232,176,162,230,153,174,233,128,\n154,230,149,153,229,184,136,228,184,138,228,188,160,231,177,187,229,136,171,230,\n173,140,230,155,178,230,139,165,230,156,137,229,136,155,230,150,176,233,133,141,\n228,187,182,229,143,170,232,166,129,230,151,182,228,187,163,232,179,135,232,168,\n138,232,190,190,229,136,176,228,186,186,231,148,159,232,174,162,233,152,133,232,\n128,129,229,184,136,229,177,149,231,164,186,229,191,131,231,144,134,232,180,180,\n229,173,144,231,182,178,231,171,153,228,184,187,233,161,140,232,135,170,231,132,\n182,231,186,167,229,136,171,231,174,128,229,141,149,230,148,185,233,157,169,233,\n130,163,228,186,155,230,157,165,232,175,180,230,137,147,229,188,128,228,187,163,\n231,160,129,229,136,160,233,153,164,232,175,129,229,136,184,232,138,130,231,155,\n174,233,135,141,231,130,185,230,172,161,230,149,184,229,164,154,229,176,145,232,\n167,132,229,136,146,232,181,132,233,135,145,230,137,190,229,136,176,228,187,165,\n229,144,142,229,164,167,229,133,168,228,184,187,233,161,181,230,156,128,228,189,\n179,229,155,158,231,173,148,229,164,169,228,184,139,228,191,157,233,154,156,231,\n142,176,228,187,163,230,163,128,230,159,165,230,138,149,231,165,168,229,176,143,\n230,151,182,230,178,146,230,156,137,230,173,163,229,184,184,231,148,154,232,135,\n179,228,187,163,231,144,134,231,155,174,229,189,149,229,133,172,229,188,128,229,\n164,141,229,136,182,233,135,145,232,158,141,229,185,184,231,166,143,231,137,136,\n230,156,172,229,189,162,230,136,144,229,135,134,229,164,135,232,161,140,230,131,\n133,229,155,158,229,136,176,230,128,157,230,131,179,230,128,142,230,160,183,229,\n141,143,232,174,174,232,174,164,232,175,129,230,156,128,229,165,189,228,186,167,\n231,148,159,230,140,137,231,133,167,230,156,141,232,163,133,229,185,191,228,184,\n156,229,138,168,230,188,171,233,135,135,232,180,173,230,150,176,230,137,139,231,\n187,132,229,155,190,233,157,162,230,157,191,229,143,130,232,128,131,230,148,191,\n230,178,187,229,174,185,230,152,147,229,164,169,229,156,176,229,138,170,229,138,\n155,228,186,186,228,187,172,229,141,135,231,186,167,233,128,159,229,186,166,228,\n186,186,231,137,169,232,176,131,230,149,180,230,181,129,232,161,140,233,128,160,\n230,136,144,230,150,135,229,173,151,233,159,169,229,155,189,232,180,184,230,152,\n147,229,188,128,229,177,149,231,155,184,233,151,156,232,161,168,231,142,176,229,\n189,177,232,167,134,229,166,130,230,173,164,231,190,142,229,174,185,229,164,167,\n229,176,143,230,138,165,233,129,147,230,157,161,230,172,190,229,191,131,230,131,\n133,232,174,184,229,164,154,230,179,149,232,167,132,229,174,182,229,177,133,228,\n185,166,229,186,151,232,191,158,230,142,165,231,171,139,229,141,179,228,184,190,\n230,138,165,230,138,128,229,183,167,229,165,165,232,191,144,231,153,187,229,133,\n165,228,187,165,230,157,165,231,144,134,232,174,186,228,186,139,228,187,182,232,\n135,170,231,148,177,228,184,173,229,141,142,229,138,158,229,133,172,229,166,136,\n229,166,136,231,156,159,230,173,163,228,184,141,233,148,153,229,133,168,230,150,\n135,229,144,136,229,144,140,228,187,183,229,128,188,229,136,171,228,186,186,231,\n155,145,231,157,163,229,133,183,228,189,147,228,184,150,231,186,170,229,155,162,\n233,152,159,229,136,155,228,184,154,230,137,191,230,139,133,229,162,158,233,149,\n191,230,156,137,228,186,186,228,191,157,230,140,129,229,149,134,229,174,182,231,\n187,180,228,191,174,229,143,176,230,185,190,229,183,166,229,143,179,232,130,161,\n228,187,189,231,173,148,230,161,136,229,174,158,233,153,133,231,148,181,228,191,\n161,231,187,143,231,144,134,231,148,159,229,145,189,229,174,163,228,188,160,228,\n187,187,229,138,161,230,173,163,229,188,143,231,137,185,232,137,178,228,184,139,\n230,157,165,229,141,143,228,188,154,229,143,170,232,131,189,229,189,147,231,132,\n182,233,135,141,230,150,176,229,133,167,229,174,185,230,140,135,229,175,188,232,\n191,144,232,161,140,230,151,165,229,191,151,232,179,163,229,174,182,232,182,133,\n232,191,135,229,156,159,229,156,176,230,181,153,230,177,159,230,148,175,228,187,\n152,230,142,168,229,135,186,231,171,153,233,149,191,230,157,173,229,183,158,230,\n137,167,232,161,140,229,136,182,233,128,160,228,185,139,228,184,128,230,142,168,\n229,185,191,231,142,176,229,156,186,230,143,143,232,191,176,229,143,152,229,140,\n150,228,188,160,231,187,159,230,173,140,230,137,139,228,191,157,233,153,169,232,\n175,190,231,168,139,229,140,187,231,150,151,231,187,143,232,191,135,232,191,135,\n229,142,187,228,185,139,229,137,141,230,148,182,229,133,165,229,185,180,229,186,\n166,230,157,130,229,191,151,231,190,142,228,184,189,230,156,128,233,171,152,231,\n153,187,233,153,134,230,156,170,230,157,165,229,138,160,229,183,165,229,133,141,\n232,180,163,230,149,153,231,168,139,231,137,136,229,157,151,232,186,171,228,189,\n147,233,135,141,229,186,134,229,135,186,229,148,174,230,136,144,230,156,172,229,\n189,162,229,188,143,229,156,159,232,177,134,229,135,186,229,131,185,228,184,156,\n230,150,185,233,130,174,231,174,177,229,141,151,228,186,172,230,177,130,232,129,\n140,229,143,150,229,190,151,232,129,140,228,189,141,231,155,184,228,191,161,233,\n161,181,233,157,162,229,136,134,233,146,159,231,189,145,233,161,181,231,161,174,\n229,174,154,229,155,190,228,190,139,231,189,145,229,157,128,231,167,175,230,158,\n129,233,148,153,232,175,175,231,155,174,231,154,132,229,174,157,232,180,157,230,\n156,186,229,133,179,233,163,142,233,153,169,230,142,136,230,157,131,231,151,133,\n230,175,146,229,174,160,231,137,169,233,153,164,228,186,134,232,169,149,232,171,\n150,231,150,190,231,151,133,229,143,138,230,151,182,230,177,130,232,180,173,231,\n171,153,231,130,185,229,132,191,231,171,165,230,175,143,229,164,169,228,184,173,\n229,164,174,232,174,164,232,175,134,230,175,143,228,184,170,229,164,169,230,180,\n165,229,173,151,228,189,147,229,143,176,231,129,163,231,187,180,230,138,164,230,\n156,172,233,161,181,228,184,170,230,128,167,229,174,152,230,150,185,229,184,184,\n232,167,129,231,155,184,230,156,186,230,136,152,231,149,165,229,186,148,229,189,\n147,229,190,139,229,184,136,230,150,185,228,190,191,230,160,161,229,155,173,232,\n130,161,229,184,130,230,136,191,229,177,139,230,160,143,231,155,174,229,145,152,\n229,183,165,229,175,188,232,135,180,231,170,129,231,132,182,233,129,147,229,133,\n183,230,156,172,231,189,145,231,187,147,229,144,136,230,161,163,230,161,136,229,\n138,179,229,138,168,229,143,166,229,164,150,231,190,142,229,133,131,229,188,149,\n232,181,183,230,148,185,229,143,152,231,172,172,229,155,155,228,188,154,232,174,\n161,232,170,170,230,152,142,233,154,144,231,167,129,229,174,157,229,174,157,232,\n167,132,232,140,131,230,182,136,232,180,185,229,133,177,229,144,140,229,191,152,\n232,174,176,228,189,147,231,179,187,229,184,166,230,157,165,229,144,141,229,173,\n151,231,153,188,232,161,168,229,188,128,230,148,190,229,138,160,231,155,159,229,\n143,151,229,136,176,228,186,140,230,137,139,229,164,167,233,135,143,230,136,144,\n228,186,186,230,149,176,233,135,143,229,133,177,228,186,171,229,140,186,229,159,\n159,229,165,179,229,173,169,229,142,159,229,136,153,230,137,128,229,156,168,231,\n187,147,230,157,159,233,128,154,228,191,161,232,182,133,231,186,167,233,133,141,\n231,189,174,229,189,147,230,151,182,228,188,152,231,167,128,230,128,167,230,132,\n159,230,136,191,228,186,167,233,129,138,230,136,178,229,135,186,229,143,163,230,\n143,144,228,186,164,229,176,177,228,184,154,228,191,157,229,129,165,231,168,139,\n229,186,166,229,143,130,230,149,176,228,186,139,228,184,154,230,149,180,228,184,\n170,229,177,177,228,184,156,230,131,133,230,132,159,231,137,185,230,174,138,229,\n136,134,233,161,158,230,144,156,229,176,139,229,177,158,228,186,142,233,151,168,\n230,136,183,232,180,162,229,138,161,229,163,176,233,159,179,229,143,138,229,133,\n182,232,180,162,231,187,143,229,157,154,230,140,129,229,185,178,233,131,168,230,\n136,144,231,171,139,229,136,169,231,155,138,232,128,131,232,153,145,230,136,144,\n233,131,189,229,140,133,232,163,133,231,148,168,230,136,182,230,175,148,232,181,\n155,230,150,135,230,152,142,230,139,155,229,149,134,229,174,140,230,149,180,231,\n156,159,230,152,175,231,156,188,231,157,155,228,188,153,228,188,180,229,168,129,\n230,156,155,233,162,134,229,159,159,229,141,171,231,148,159,228,188,152,230,131,\n160,232,171,150,229,163,135,229,133,172,229,133,177,232,137,175,229,165,189,229,\n133,133,229,136,134,231,172,166,229,144,136,233,153,132,228,187,182,231,137,185,\n231,130,185,228,184,141,229,143,175,232,139,177,230,150,135,232,181,132,228,186,\n167,230,160,185,230,156,172,230,152,142,230,152,190,229,175,134,231,162,188,229,\n133,172,228,188,151,230,176,145,230,151,143,230,155,180,229,138,160,228,186,171,\n229,143,151,229,144,140,229,173,166,229,144,175,229,138,168,233,128,130,229,144,\n136,229,142,159,230,157,165,233,151,174,231,173,148,230,156,172,230,150,135,231,\n190,142,233,163,159,231,187,191,232,137,178,231,168,179,229,174,154,231,187,136,\n228,186,142,231,148,159,231,137,169,228,190,155,230,177,130,230,144,156,231,139,\n144,229,138,155,233,135,143,228,184,165,233,135,141,230,176,184,232,191,156,229,\n134,153,231,156,159,230,156,137,233,153,144,231,171,158,228,186,137,229,175,185,\n232,177,161,232,180,185,231,148,168,228,184,141,229,165,189,231,187,157,229,175,\n185,229,141,129,229,136,134,228,191,131,232,191,155,231,130,185,232,175,132,229,\n189,177,233,159,179,228,188,152,229,138,191,228,184,141,229,176,145,230,172,163,\n232,181,143,229,185,182,228,184,148,230,156,137,231,130,185,230,150,185,229,144,\n145,229,133,168,230,150,176,228,191,161,231,148,168,232,174,190,230,150,189,229,\n189,162,232,177,161,232,181,132,230,160,188,231,170,129,231,160,180,233,154,143,\n231,157,128,233,135,141,229,164,167,228,186,142,230,152,175,230,175,149,228,184,\n154,230,153,186,232,131,189,229,140,150,229,183,165,229,174,140,231,190,142,229,\n149,134,229,159,142,231,187,159,228,184,128,229,135,186,231,137,136,230,137,147,\n233,128,160,231,148,162,229,147,129,230,166,130,229,134,181,231,148,168,228,186,\n142,228,191,157,231,149,153,229,155,160,231,180,160,228,184,173,229,156,139,229,\n173,152,229,130,168,232,180,180,229,155,190,230,156,128,230,132,155,233,149,191,\n230,156,159,229,143,163,228,187,183,231,144,134,232,180,162,229,159,186,229,156,\n176,229,174,137,230,142,146,230,173,166,230,177,137,233,135,140,233,157,162,229,\n136,155,229,187,186,229,164,169,231,169,186,233,166,150,229,133,136,229,174,140,\n229,150,132,233,169,177,229,138,168,228,184,139,233,157,162,228,184,141,229,134,\n141,232,175,154,228,191,161,230,132,143,228,185,137,233,152,179,229,133,137,232,\n139,177,229,155,189,230,188,130,228,186,174,229,134,155,228,186,139,231,142,169,\n229,174,182,231,190,164,228,188,151,229,134,156,230,176,145,229,141,179,229,143,\n175,229,144,141,231,168,177,229,174,182,229,133,183,229,138,168,231,148,187,230,\n131,179,229,136,176,230,179,168,230,152,142,229,176,143,229,173,166,230,128,167,\n232,131,189,232,128,131,231,160,148,231,161,172,228,187,182,232,167,130,231,156,\n139,230,184,133,230,165,154,230,144,158,231,172,145,233,166,150,233,160,129,233,\n187,132,233,135,145,233,128,130,231,148,168,230,177,159,232,139,143,231,156,159,\n229,174,158,228,184,187,231,174,161,233,152,182,230,174,181,232,168,187,229,134,\n138,231,191,187,232,175,145,230,157,131,229,136,169,229,129,154,229,165,189,228,\n188,188,228,185,142,233,128,154,232,174,175,230,150,189,229,183,165,231,139,128,\n230,133,139,228,185,159,232,174,184,231,142,175,228,191,157,229,159,185,229,133,\n187,230,166,130,229,191,181,229,164,167,229,158,139,230,156,186,231,165,168,231,\n144,134,232,167,163,229,140,191,229,144,141,99,117,97,110,100,111,101,110,118,\n105,97,114,109,97,100,114,105,100,98,117,115,99,97,114,105,110,105,99,105,111,\n116,105,101,109,112,111,112,111,114,113,117,101,99,117,101,110,116,97,101,115,\n116,97,100,111,112,117,101,100,101,110,106,117,101,103,111,115,99,111,110,116,\n114,97,101,115,116,195,161,110,110,111,109,98,114,101,116,105,101,110,101,110,\n112,101,114,102,105,108,109,97,110,101,114,97,97,109,105,103,111,115,99,105,117,\n100,97,100,99,101,110,116,114,111,97,117,110,113,117,101,112,117,101,100,101,115\n,100,101,110,116,114,111,112,114,105,109,101,114,112,114,101,99,105,111,115,101,\n103,195,186,110,98,117,101,110,111,115,118,111,108,118,101,114,112,117,110,116,\n111,115,115,101,109,97,110,97,104,97,98,195,173,97,97,103,111,115,116,111,110,\n117,101,118,111,115,117,110,105,100,111,115,99,97,114,108,111,115,101,113,117,\n105,112,111,110,105,195,177,111,115,109,117,99,104,111,115,97,108,103,117,110,97\n,99,111,114,114,101,111,105,109,97,103,101,110,112,97,114,116,105,114,97,114,114\n,105,98,97,109,97,114,195,173,97,104,111,109,98,114,101,101,109,112,108,101,111,\n118,101,114,100,97,100,99,97,109,98,105,111,109,117,99,104,97,115,102,117,101,\n114,111,110,112,97,115,97,100,111,108,195,173,110,101,97,112,97,114,101,99,101,\n110,117,101,118,97,115,99,117,114,115,111,115,101,115,116,97,98,97,113,117,105,\n101,114,111,108,105,98,114,111,115,99,117,97,110,116,111,97,99,99,101,115,111,\n109,105,103,117,101,108,118,97,114,105,111,115,99,117,97,116,114,111,116,105,101\n,110,101,115,103,114,117,112,111,115,115,101,114,195,161,110,101,117,114,111,112\n,97,109,101,100,105,111,115,102,114,101,110,116,101,97,99,101,114,99,97,100,101,\n109,195,161,115,111,102,101,114,116,97,99,111,99,104,101,115,109,111,100,101,108\n,111,105,116,97,108,105,97,108,101,116,114,97,115,97,108,103,195,186,110,99,111,\n109,112,114,97,99,117,97,108,101,115,101,120,105,115,116,101,99,117,101,114,112,\n111,115,105,101,110,100,111,112,114,101,110,115,97,108,108,101,103,97,114,118,\n105,97,106,101,115,100,105,110,101,114,111,109,117,114,99,105,97,112,111,100,114\n,195,161,112,117,101,115,116,111,100,105,97,114,105,111,112,117,101,98,108,111,\n113,117,105,101,114,101,109,97,110,117,101,108,112,114,111,112,105,111,99,114,\n105,115,105,115,99,105,101,114,116,111,115,101,103,117,114,111,109,117,101,114,\n116,101,102,117,101,110,116,101,99,101,114,114,97,114,103,114,97,110,100,101,101\n,102,101,99,116,111,112,97,114,116,101,115,109,101,100,105,100,97,112,114,111,\n112,105,97,111,102,114,101,99,101,116,105,101,114,114,97,101,45,109,97,105,108,\n118,97,114,105,97,115,102,111,114,109,97,115,102,117,116,117,114,111,111,98,106,\n101,116,111,115,101,103,117,105,114,114,105,101,115,103,111,110,111,114,109,97,\n115,109,105,115,109,111,115,195,186,110,105,99,111,99,97,109,105,110,111,115,105\n,116,105,111,115,114,97,122,195,179,110,100,101,98,105,100,111,112,114,117,101,\n98,97,116,111,108,101,100,111,116,101,110,195,173,97,106,101,115,195,186,115,101\n,115,112,101,114,111,99,111,99,105,110,97,111,114,105,103,101,110,116,105,101,\n110,100,97,99,105,101,110,116,111,99,195,161,100,105,122,104,97,98,108,97,114,\n115,101,114,195,173,97,108,97,116,105,110,97,102,117,101,114,122,97,101,115,116,\n105,108,111,103,117,101,114,114,97,101,110,116,114,97,114,195,169,120,105,116,\n111,108,195,179,112,101,122,97,103,101,110,100,97,118,195,173,100,101,111,101,\n118,105,116,97,114,112,97,103,105,110,97,109,101,116,114,111,115,106,97,118,105,\n101,114,112,97,100,114,101,115,102,195,161,99,105,108,99,97,98,101,122,97,195,\n161,114,101,97,115,115,97,108,105,100,97,101,110,118,195,173,111,106,97,112,195,\n179,110,97,98,117,115,111,115,98,105,101,110,101,115,116,101,120,116,111,115,108\n,108,101,118,97,114,112,117,101,100,97,110,102,117,101,114,116,101,99,111,109,\n195,186,110,99,108,97,115,101,115,104,117,109,97,110,111,116,101,110,105,100,111\n,98,105,108,98,97,111,117,110,105,100,97,100,101,115,116,195,161,115,101,100,105\n,116,97,114,99,114,101,97,100,111,208,180,208,187,209,143,209,135,209,130,208,\n190,208,186,208,176,208,186,208,184,208,187,208,184,209,141,209,130,208,190,208,\n178,209,129,208,181,208,181,208,179,208,190,208,191,209,128,208,184,209,130,208,\n176,208,186,208,181,209,137,208,181,209,131,208,182,208,181,208,154,208,176,208,\n186,208,177,208,181,208,183,208,177,209,139,208,187,208,190,208,189,208,184,208,\n146,209,129,208,181,208,191,208,190,208,180,208,173,209,130,208,190,209,130,208,\n190,208,188,209,135,208,181,208,188,208,189,208,181,209,130,208,187,208,181,209,\n130,209,128,208,176,208,183,208,190,208,189,208,176,208,179,208,180,208,181,208,\n188,208,189,208,181,208,148,208,187,209,143,208,159,209,128,208,184,208,189,208,\n176,209,129,208,189,208,184,209,133,209,130,208,181,208,188,208,186,209,130,208,\n190,208,179,208,190,208,180,208,178,208,190,209,130,209,130,208,176,208,188,208,\n161,208,168,208,144,208,188,208,176,209,143,208,167,209,130,208,190,208,178,208,\n176,209,129,208,178,208,176,208,188,208,181,208,188,209,131,208,162,208,176,208,\n186,208,180,208,178,208,176,208,189,208,176,208,188,209,141,209,130,208,184,209,\n141,209,130,209,131,208,146,208,176,208,188,209,130,208,181,209,133,208,191,209,\n128,208,190,209,130,209,131,209,130,208,189,208,176,208,180,208,180,208,189,209,\n143,208,146,208,190,209,130,209,130,209,128,208,184,208,189,208,181,208,185,208,\n146,208,176,209,129,208,189,208,184,208,188,209,129,208,176,208,188,209,130,208,\n190,209,130,209,128,209,131,208,177,208,158,208,189,208,184,208,188,208,184,209,\n128,208,189,208,181,208,181,208,158,208,158,208,158,208,187,208,184,209,134,209,\n141,209,130,208,176,208,158,208,189,208,176,208,189,208,181,208,188,208,180,208,\n190,208,188,208,188,208,190,208,185,208,180,208,178,208,181,208,190,208,189,208,\n190,209,129,209,131,208,180,224,164,149,224,165,135,224,164,185,224,165,136,224,\n164,149,224,165,128,224,164,184,224,165,135,224,164,149,224,164,190,224,164,149,\n224,165,139,224,164,148,224,164,176,224,164,170,224,164,176,224,164,168,224,165,\n135,224,164,143,224,164,149,224,164,149,224,164,191,224,164,173,224,165,128,224,\n164,135,224,164,184,224,164,149,224,164,176,224,164,164,224,165,139,224,164,185,\n224,165,139,224,164,134,224,164,170,224,164,185,224,165,128,224,164,175,224,164,\n185,224,164,175,224,164,190,224,164,164,224,164,149,224,164,165,224,164,190,106,\n97,103,114,97,110,224,164,134,224,164,156,224,164,156,224,165,139,224,164,133,\n224,164,172,224,164,166,224,165,139,224,164,151,224,164,136,224,164,156,224,164,\n190,224,164,151,224,164,143,224,164,185,224,164,174,224,164,135,224,164,168,224,\n164,181,224,164,185,224,164,175,224,165,135,224,164,165,224,165,135,224,164,165,\n224,165,128,224,164,152,224,164,176,224,164,156,224,164,172,224,164,166,224,165,\n128,224,164,149,224,164,136,224,164,156,224,165,128,224,164,181,224,165,135,224,\n164,168,224,164,136,224,164,168,224,164,143,224,164,185,224,164,176,224,164,137,\n224,164,184,224,164,174,224,165,135,224,164,149,224,164,174,224,164,181,224,165,\n139,224,164,178,224,165,135,224,164,184,224,164,172,224,164,174,224,164,136,224,\n164,166,224,165,135,224,164,147,224,164,176,224,164,134,224,164,174,224,164,172,\n224,164,184,224,164,173,224,164,176,224,164,172,224,164,168,224,164,154,224,164,\n178,224,164,174,224,164,168,224,164,134,224,164,151,224,164,184,224,165,128,224,\n164,178,224,165,128,216,185,217,132,217,137,216,165,217,132,217,137,217,135,216,\n176,216,167,216,162,216,174,216,177,216,185,216,175,216,175,216,167,217,132,217,\n137,217,135,216,176,217,135,216,181,217,136,216,177,216,186,217,138,216,177,217,\n131,216,167,217,134,217,136,217,132,216,167,216,168,217,138,217,134,216,185,216,\n177,216,182,216,176,217,132,217,131,217,135,217,134,216,167,217,138,217,136,217,\n133,217,130,216,167,217,132,216,185,217,132,217,138,216,167,217,134,216,167,217,\n132,217,131,217,134,216,173,216,170,217,137,217,130,216,168,217,132,217,136,216,\n173,216,169,216,167,216,174,216,177,217,129,217,130,216,183,216,185,216,168,216,\n175,216,177,217,131,217,134,216,165,216,176,216,167,217,131,217,133,216,167,216,\n167,216,173,216,175,216,165,217,132,216,167,217,129,217,138,217,135,216,168,216,\n185,216,182,217,131,217,138,217,129,216,168,216,173,216,171,217,136,217,133,217,\n134,217,136,217,135,217,136,216,163,217,134,216,167,216,172,216,175,216,167,217,\n132,217,135,216,167,216,179,217,132,217,133,216,185,217,134,216,175,217,132,217,\n138,216,179,216,185,216,168,216,177,216,181,217,132,217,137,217,133,217,134,216,\n176,216,168,217,135,216,167,216,163,217,134,217,135,217,133,216,171,217,132,217,\n131,217,134,216,170,216,167,217,132,216,167,216,173,217,138,216,171,217,133,216,\n181,216,177,216,180,216,177,216,173,216,173,217,136,217,132,217,136,217,129,217,\n138,216,167,216,176,216,167,217,132,217,131,217,132,217,133,216,177,216,169,216,\n167,217,134,216,170,216,167,217,132,217,129,216,163,216,168,217,136,216,174,216,\n167,216,181,216,163,217,134,216,170,216,167,217,134,217,135,216,167,217,132,217,\n138,216,185,216,182,217,136,217,136,217,130,216,175,216,167,216,168,217,134,216,\n174,217,138,216,177,216,168,217,134,216,170,217,132,217,131,217,133,216,180,216,\n167,216,161,217,136,217,135,217,138,216,167,216,168,217,136,217,130,216,181,216,\n181,217,136,217,133,216,167,216,177,217,130,217,133,216,163,216,173,216,175,217,\n134,216,173,217,134,216,185,216,175,217,133,216,177,216,163,217,138,216,167,216,\n173,216,169,217,131,216,170,216,168,216,175,217,136,217,134,217,138,216,172,216,\n168,217,133,217,134,217,135,216,170,216,173,216,170,216,172,217,135,216,169,216,\n179,217,134,216,169,217,138,216,170,217,133,217,131,216,177,216,169,216,186,216,\n178,216,169,217,134,217,129,216,179,216,168,217,138,216,170,217,132,217,132,217,\n135,217,132,217,134,216,167,216,170,217,132,217,131,217,130,217,132,216,168,217,\n132,217,133,216,167,216,185,217,134,217,135,216,163,217,136,217,132,216,180,217,\n138,216,161,217,134,217,136,216,177,216,163,217,133,216,167,217,129,217,138,217,\n131,216,168,217,131,217,132,216,176,216,167,216,170,216,177,216,170,216,168,216,\n168,216,163,217,134,217,135,217,133,216,179,216,167,217,134,217,131,216,168,217,\n138,216,185,217,129,217,130,216,175,216,173,216,179,217,134,217,132,217,135,217,\n133,216,180,216,185,216,177,216,163,217,135,217,132,216,180,217,135,216,177,217,\n130,216,183,216,177,216,183,217,132,216,168,112,114,111,102,105,108,101,115,101,\n114,118,105,99,101,100,101,102,97,117,108,116,104,105,109,115,101,108,102,100,\n101,116,97,105,108,115,99,111,110,116,101,110,116,115,117,112,112,111,114,116,\n115,116,97,114,116,101,100,109,101,115,115,97,103,101,115,117,99,99,101,115,115,\n102,97,115,104,105,111,110,60,116,105,116,108,101,62,99,111,117,110,116,114,121,\n97,99,99,111,117,110,116,99,114,101,97,116,101,100,115,116,111,114,105,101,115,\n114,101,115,117,108,116,115,114,117,110,110,105,110,103,112,114,111,99,101,115,\n115,119,114,105,116,105,110,103,111,98,106,101,99,116,115,118,105,115,105,98,108\n,101,119,101,108,99,111,109,101,97,114,116,105,99,108,101,117,110,107,110,111,\n119,110,110,101,116,119,111,114,107,99,111,109,112,97,110,121,100,121,110,97,109\n,105,99,98,114,111,119,115,101,114,112,114,105,118,97,99,121,112,114,111,98,108,\n101,109,83,101,114,118,105,99,101,114,101,115,112,101,99,116,100,105,115,112,108\n,97,121,114,101,113,117,101,115,116,114,101,115,101,114,118,101,119,101,98,115,\n105,116,101,104,105,115,116,111,114,121,102,114,105,101,110,100,115,111,112,116,\n105,111,110,115,119,111,114,107,105,110,103,118,101,114,115,105,111,110,109,105,\n108,108,105,111,110,99,104,97,110,110,101,108,119,105,110,100,111,119,46,97,100,\n100,114,101,115,115,118,105,115,105,116,101,100,119,101,97,116,104,101,114,99,\n111,114,114,101,99,116,112,114,111,100,117,99,116,101,100,105,114,101,99,116,102\n,111,114,119,97,114,100,121,111,117,32,99,97,110,114,101,109,111,118,101,100,115\n,117,98,106,101,99,116,99,111,110,116,114,111,108,97,114,99,104,105,118,101,99,\n117,114,114,101,110,116,114,101,97,100,105,110,103,108,105,98,114,97,114,121,108\n,105,109,105,116,101,100,109,97,110,97,103,101,114,102,117,114,116,104,101,114,\n115,117,109,109,97,114,121,109,97,99,104,105,110,101,109,105,110,117,116,101,115\n,112,114,105,118,97,116,101,99,111,110,116,101,120,116,112,114,111,103,114,97,\n109,115,111,99,105,101,116,121,110,117,109,98,101,114,115,119,114,105,116,116,\n101,110,101,110,97,98,108,101,100,116,114,105,103,103,101,114,115,111,117,114,99\n,101,115,108,111,97,100,105,110,103,101,108,101,109,101,110,116,112,97,114,116,\n110,101,114,102,105,110,97,108,108,121,112,101,114,102,101,99,116,109,101,97,110\n,105,110,103,115,121,115,116,101,109,115,107,101,101,112,105,110,103,99,117,108,\n116,117,114,101,38,113,117,111,116,59,44,106,111,117,114,110,97,108,112,114,111,\n106,101,99,116,115,117,114,102,97,99,101,115,38,113,117,111,116,59,101,120,112,\n105,114,101,115,114,101,118,105,101,119,115,98,97,108,97,110,99,101,69,110,103,\n108,105,115,104,67,111,110,116,101,110,116,116,104,114,111,117,103,104,80,108,\n101,97,115,101,32,111,112,105,110,105,111,110,99,111,110,116,97,99,116,97,118,\n101,114,97,103,101,112,114,105,109,97,114,121,118,105,108,108,97,103,101,83,112,\n97,110,105,115,104,103,97,108,108,101,114,121,100,101,99,108,105,110,101,109,101\n,101,116,105,110,103,109,105,115,115,105,111,110,112,111,112,117,108,97,114,113,\n117,97,108,105,116,121,109,101,97,115,117,114,101,103,101,110,101,114,97,108,115\n,112,101,99,105,101,115,115,101,115,115,105,111,110,115,101,99,116,105,111,110,\n119,114,105,116,101,114,115,99,111,117,110,116,101,114,105,110,105,116,105,97,\n108,114,101,112,111,114,116,115,102,105,103,117,114,101,115,109,101,109,98,101,\n114,115,104,111,108,100,105,110,103,100,105,115,112,117,116,101,101,97,114,108,\n105,101,114,101,120,112,114,101,115,115,100,105,103,105,116,97,108,112,105,99,\n116,117,114,101,65,110,111,116,104,101,114,109,97,114,114,105,101,100,116,114,97\n,102,102,105,99,108,101,97,100,105,110,103,99,104,97,110,103,101,100,99,101,110,\n116,114,97,108,118,105,99,116,111,114,121,105,109,97,103,101,115,47,114,101,97,\n115,111,110,115,115,116,117,100,105,101,115,102,101,97,116,117,114,101,108,105,\n115,116,105,110,103,109,117,115,116,32,98,101,115,99,104,111,111,108,115,86,101,\n114,115,105,111,110,117,115,117,97,108,108,121,101,112,105,115,111,100,101,112,\n108,97,121,105,110,103,103,114,111,119,105,110,103,111,98,118,105,111,117,115,\n111,118,101,114,108,97,121,112,114,101,115,101,110,116,97,99,116,105,111,110,115\n,60,47,117,108,62,13,10,119,114,97,112,112,101,114,97,108,114,101,97,100,121,99,\n101,114,116,97,105,110,114,101,97,108,105,116,121,115,116,111,114,97,103,101,97,\n110,111,116,104,101,114,100,101,115,107,116,111,112,111,102,102,101,114,101,100,\n112,97,116,116,101,114,110,117,110,117,115,117,97,108,68,105,103,105,116,97,108,\n99,97,112,105,116,97,108,87,101,98,115,105,116,101,102,97,105,108,117,114,101,99\n,111,110,110,101,99,116,114,101,100,117,99,101,100,65,110,100,114,111,105,100,\n100,101,99,97,100,101,115,114,101,103,117,108,97,114,32,38,97,109,112,59,32,97,\n110,105,109,97,108,115,114,101,108,101,97,115,101,65,117,116,111,109,97,116,103,\n101,116,116,105,110,103,109,101,116,104,111,100,115,110,111,116,104,105,110,103,\n80,111,112,117,108,97,114,99,97,112,116,105,111,110,108,101,116,116,101,114,115,\n99,97,112,116,117,114,101,115,99,105,101,110,99,101,108,105,99,101,110,115,101,\n99,104,97,110,103,101,115,69,110,103,108,97,110,100,61,49,38,97,109,112,59,72,\n105,115,116,111,114,121,32,61,32,110,101,119,32,67,101,110,116,114,97,108,117,\n112,100,97,116,101,100,83,112,101,99,105,97,108,78,101,116,119,111,114,107,114,\n101,113,117,105,114,101,99,111,109,109,101,110,116,119,97,114,110,105,110,103,67\n,111,108,108,101,103,101,116,111,111,108,98,97,114,114,101,109,97,105,110,115,98\n,101,99,97,117,115,101,101,108,101,99,116,101,100,68,101,117,116,115,99,104,102,\n105,110,97,110,99,101,119,111,114,107,101,114,115,113,117,105,99,107,108,121,98,\n101,116,119,101,101,110,101,120,97,99,116,108,121,115,101,116,116,105,110,103,\n100,105,115,101,97,115,101,83,111,99,105,101,116,121,119,101,97,112,111,110,115,\n101,120,104,105,98,105,116,38,108,116,59,33,45,45,67,111,110,116,114,111,108,99,\n108,97,115,115,101,115,99,111,118,101,114,101,100,111,117,116,108,105,110,101,97\n,116,116,97,99,107,115,100,101,118,105,99,101,115,40,119,105,110,100,111,119,112\n,117,114,112,111,115,101,116,105,116,108,101,61,34,77,111,98,105,108,101,32,107,\n105,108,108,105,110,103,115,104,111,119,105,110,103,73,116,97,108,105,97,110,100\n,114,111,112,112,101,100,104,101,97,118,105,108,121,101,102,102,101,99,116,115,\n45,49,39,93,41,59,10,99,111,110,102,105,114,109,67,117,114,114,101,110,116,97,\n100,118,97,110,99,101,115,104,97,114,105,110,103,111,112,101,110,105,110,103,100\n,114,97,119,105,110,103,98,105,108,108,105,111,110,111,114,100,101,114,101,100,\n71,101,114,109,97,110,121,114,101,108,97,116,101,100,60,47,102,111,114,109,62,\n105,110,99,108,117,100,101,119,104,101,116,104,101,114,100,101,102,105,110,101,\n100,83,99,105,101,110,99,101,99,97,116,97,108,111,103,65,114,116,105,99,108,101,\n98,117,116,116,111,110,115,108,97,114,103,101,115,116,117,110,105,102,111,114,\n109,106,111,117,114,110,101,121,115,105,100,101,98,97,114,67,104,105,99,97,103,\n111,104,111,108,105,100,97,121,71,101,110,101,114,97,108,112,97,115,115,97,103,\n101,44,38,113,117,111,116,59,97,110,105,109,97,116,101,102,101,101,108,105,110,\n103,97,114,114,105,118,101,100,112,97,115,115,105,110,103,110,97,116,117,114,97,\n108,114,111,117,103,104,108,121,46,10,10,84,104,101,32,98,117,116,32,110,111,116\n,100,101,110,115,105,116,121,66,114,105,116,97,105,110,67,104,105,110,101,115,\n101,108,97,99,107,32,111,102,116,114,105,98,117,116,101,73,114,101,108,97,110,\n100,34,32,100,97,116,97,45,102,97,99,116,111,114,115,114,101,99,101,105,118,101,\n116,104,97,116,32,105,115,76,105,98,114,97,114,121,104,117,115,98,97,110,100,105\n,110,32,102,97,99,116,97,102,102,97,105,114,115,67,104,97,114,108,101,115,114,97\n,100,105,99,97,108,98,114,111,117,103,104,116,102,105,110,100,105,110,103,108,97\n,110,100,105,110,103,58,108,97,110,103,61,34,114,101,116,117,114,110,32,108,101,\n97,100,101,114,115,112,108,97,110,110,101,100,112,114,101,109,105,117,109,112,97\n,99,107,97,103,101,65,109,101,114,105,99,97,69,100,105,116,105,111,110,93,38,113\n,117,111,116,59,77,101,115,115,97,103,101,110,101,101,100,32,116,111,118,97,108,\n117,101,61,34,99,111,109,112,108,101,120,108,111,111,107,105,110,103,115,116,97,\n116,105,111,110,98,101,108,105,101,118,101,115,109,97,108,108,101,114,45,109,111\n,98,105,108,101,114,101,99,111,114,100,115,119,97,110,116,32,116,111,107,105,110\n,100,32,111,102,70,105,114,101,102,111,120,121,111,117,32,97,114,101,115,105,109\n,105,108,97,114,115,116,117,100,105,101,100,109,97,120,105,109,117,109,104,101,\n97,100,105,110,103,114,97,112,105,100,108,121,99,108,105,109,97,116,101,107,105,\n110,103,100,111,109,101,109,101,114,103,101,100,97,109,111,117,110,116,115,102,\n111,117,110,100,101,100,112,105,111,110,101,101,114,102,111,114,109,117,108,97,\n100,121,110,97,115,116,121,104,111,119,32,116,111,32,83,117,112,112,111,114,116,\n114,101,118,101,110,117,101,101,99,111,110,111,109,121,82,101,115,117,108,116,\n115,98,114,111,116,104,101,114,115,111,108,100,105,101,114,108,97,114,103,101,\n108,121,99,97,108,108,105,110,103,46,38,113,117,111,116,59,65,99,99,111,117,110,\n116,69,100,119,97,114,100,32,115,101,103,109,101,110,116,82,111,98,101,114,116,\n32,101,102,102,111,114,116,115,80,97,99,105,102,105,99,108,101,97,114,110,101,\n100,117,112,32,119,105,116,104,104,101,105,103,104,116,58,119,101,32,104,97,118,\n101,65,110,103,101,108,101,115,110,97,116,105,111,110,115,95,115,101,97,114,99,\n104,97,112,112,108,105,101,100,97,99,113,117,105,114,101,109,97,115,115,105,118,\n101,103,114,97,110,116,101,100,58,32,102,97,108,115,101,116,114,101,97,116,101,\n100,98,105,103,103,101,115,116,98,101,110,101,102,105,116,100,114,105,118,105,\n110,103,83,116,117,100,105,101,115,109,105,110,105,109,117,109,112,101,114,104,\n97,112,115,109,111,114,110,105,110,103,115,101,108,108,105,110,103,105,115,32,\n117,115,101,100,114,101,118,101,114,115,101,118,97,114,105,97,110,116,32,114,111\n,108,101,61,34,109,105,115,115,105,110,103,97,99,104,105,101,118,101,112,114,111\n,109,111,116,101,115,116,117,100,101,110,116,115,111,109,101,111,110,101,101,120\n,116,114,101,109,101,114,101,115,116,111,114,101,98,111,116,116,111,109,58,101,\n118,111,108,118,101,100,97,108,108,32,116,104,101,115,105,116,101,109,97,112,101\n,110,103,108,105,115,104,119,97,121,32,116,111,32,32,65,117,103,117,115,116,115,\n121,109,98,111,108,115,67,111,109,112,97,110,121,109,97,116,116,101,114,115,109,\n117,115,105,99,97,108,97,103,97,105,110,115,116,115,101,114,118,105,110,103,125,\n41,40,41,59,13,10,112,97,121,109,101,110,116,116,114,111,117,98,108,101,99,111,\n110,99,101,112,116,99,111,109,112,97,114,101,112,97,114,101,110,116,115,112,108,\n97,121,101,114,115,114,101,103,105,111,110,115,109,111,110,105,116,111,114,32,39\n,39,84,104,101,32,119,105,110,110,105,110,103,101,120,112,108,111,114,101,97,100\n,97,112,116,101,100,71,97,108,108,101,114,121,112,114,111,100,117,99,101,97,98,\n105,108,105,116,121,101,110,104,97,110,99,101,99,97,114,101,101,114,115,41,46,32\n,84,104,101,32,99,111,108,108,101,99,116,83,101,97,114,99,104,32,97,110,99,105,\n101,110,116,101,120,105,115,116,101,100,102,111,111,116,101,114,32,104,97,110,\n100,108,101,114,112,114,105,110,116,101,100,99,111,110,115,111,108,101,69,97,115\n,116,101,114,110,101,120,112,111,114,116,115,119,105,110,100,111,119,115,67,104,\n97,110,110,101,108,105,108,108,101,103,97,108,110,101,117,116,114,97,108,115,117\n,103,103,101,115,116,95,104,101,97,100,101,114,115,105,103,110,105,110,103,46,\n104,116,109,108,34,62,115,101,116,116,108,101,100,119,101,115,116,101,114,110,99\n,97,117,115,105,110,103,45,119,101,98,107,105,116,99,108,97,105,109,101,100,74,\n117,115,116,105,99,101,99,104,97,112,116,101,114,118,105,99,116,105,109,115,84,\n104,111,109,97,115,32,109,111,122,105,108,108,97,112,114,111,109,105,115,101,112\n,97,114,116,105,101,115,101,100,105,116,105,111,110,111,117,116,115,105,100,101,\n58,102,97,108,115,101,44,104,117,110,100,114,101,100,79,108,121,109,112,105,99,\n95,98,117,116,116,111,110,97,117,116,104,111,114,115,114,101,97,99,104,101,100,\n99,104,114,111,110,105,99,100,101,109,97,110,100,115,115,101,99,111,110,100,115,\n112,114,111,116,101,99,116,97,100,111,112,116,101,100,112,114,101,112,97,114,101\n,110,101,105,116,104,101,114,103,114,101,97,116,108,121,103,114,101,97,116,101,\n114,111,118,101,114,97,108,108,105,109,112,114,111,118,101,99,111,109,109,97,110\n,100,115,112,101,99,105,97,108,115,101,97,114,99,104,46,119,111,114,115,104,105,\n112,102,117,110,100,105,110,103,116,104,111,117,103,104,116,104,105,103,104,101,\n115,116,105,110,115,116,101,97,100,117,116,105,108,105,116,121,113,117,97,114,\n116,101,114,67,117,108,116,117,114,101,116,101,115,116,105,110,103,99,108,101,97\n,114,108,121,101,120,112,111,115,101,100,66,114,111,119,115,101,114,108,105,98,\n101,114,97,108,125,32,99,97,116,99,104,80,114,111,106,101,99,116,101,120,97,109,\n112,108,101,104,105,100,101,40,41,59,70,108,111,114,105,100,97,97,110,115,119,\n101,114,115,97,108,108,111,119,101,100,69,109,112,101,114,111,114,100,101,102,\n101,110,115,101,115,101,114,105,111,117,115,102,114,101,101,100,111,109,83,101,\n118,101,114,97,108,45,98,117,116,116,111,110,70,117,114,116,104,101,114,111,117,\n116,32,111,102,32,33,61,32,110,117,108,108,116,114,97,105,110,101,100,68,101,110\n,109,97,114,107,118,111,105,100,40,48,41,47,97,108,108,46,106,115,112,114,101,\n118,101,110,116,82,101,113,117,101,115,116,83,116,101,112,104,101,110,10,10,87,\n104,101,110,32,111,98,115,101,114,118,101,60,47,104,50,62,13,10,77,111,100,101,\n114,110,32,112,114,111,118,105,100,101,34,32,97,108,116,61,34,98,111,114,100,101\n,114,115,46,10,10,70,111,114,32,10,10,77,97,110,121,32,97,114,116,105,115,116,\n115,112,111,119,101,114,101,100,112,101,114,102,111,114,109,102,105,99,116,105,\n111,110,116,121,112,101,32,111,102,109,101,100,105,99,97,108,116,105,99,107,101,\n116,115,111,112,112,111,115,101,100,67,111,117,110,99,105,108,119,105,116,110,\n101,115,115,106,117,115,116,105,99,101,71,101,111,114,103,101,32,66,101,108,103,\n105,117,109,46,46,46,60,47,97,62,116,119,105,116,116,101,114,110,111,116,97,98,\n108,121,119,97,105,116,105,110,103,119,97,114,102,97,114,101,32,79,116,104,101,\n114,32,114,97,110,107,105,110,103,112,104,114,97,115,101,115,109,101,110,116,105\n,111,110,115,117,114,118,105,118,101,115,99,104,111,108,97,114,60,47,112,62,13,\n10,32,67,111,117,110,116,114,121,105,103,110,111,114,101,100,108,111,115,115,32,\n111,102,106,117,115,116,32,97,115,71,101,111,114,103,105,97,115,116,114,97,110,\n103,101,60,104,101,97,100,62,60,115,116,111,112,112,101,100,49,39,93,41,59,13,10\n,105,115,108,97,110,100,115,110,111,116,97,98,108,101,98,111,114,100,101,114,58,\n108,105,115,116,32,111,102,99,97,114,114,105,101,100,49,48,48,44,48,48,48,60,47,\n104,51,62,10,32,115,101,118,101,114,97,108,98,101,99,111,109,101,115,115,101,108\n,101,99,116,32,119,101,100,100,105,110,103,48,48,46,104,116,109,108,109,111,110,\n97,114,99,104,111,102,102,32,116,104,101,116,101,97,99,104,101,114,104,105,103,\n104,108,121,32,98,105,111,108,111,103,121,108,105,102,101,32,111,102,111,114,32,\n101,118,101,110,114,105,115,101,32,111,102,38,114,97,113,117,111,59,112,108,117,\n115,111,110,101,104,117,110,116,105,110,103,40,116,104,111,117,103,104,68,111,\n117,103,108,97,115,106,111,105,110,105,110,103,99,105,114,99,108,101,115,70,111,\n114,32,116,104,101,65,110,99,105,101,110,116,86,105,101,116,110,97,109,118,101,\n104,105,99,108,101,115,117,99,104,32,97,115,99,114,121,115,116,97,108,118,97,108\n,117,101,32,61,87,105,110,100,111,119,115,101,110,106,111,121,101,100,97,32,115,\n109,97,108,108,97,115,115,117,109,101,100,60,97,32,105,100,61,34,102,111,114,101\n,105,103,110,32,65,108,108,32,114,105,104,111,119,32,116,104,101,68,105,115,112,\n108,97,121,114,101,116,105,114,101,100,104,111,119,101,118,101,114,104,105,100,\n100,101,110,59,98,97,116,116,108,101,115,115,101,101,107,105,110,103,99,97,98,\n105,110,101,116,119,97,115,32,110,111,116,108,111,111,107,32,97,116,99,111,110,\n100,117,99,116,103,101,116,32,116,104,101,74,97,110,117,97,114,121,104,97,112,\n112,101,110,115,116,117,114,110,105,110,103,97,58,104,111,118,101,114,79,110,108\n,105,110,101,32,70,114,101,110,99,104,32,108,97,99,107,105,110,103,116,121,112,\n105,99,97,108,101,120,116,114,97,99,116,101,110,101,109,105,101,115,101,118,101,\n110,32,105,102,103,101,110,101,114,97,116,100,101,99,105,100,101,100,97,114,101,\n32,110,111,116,47,115,101,97,114,99,104,98,101,108,105,101,102,115,45,105,109,97\n,103,101,58,108,111,99,97,116,101,100,115,116,97,116,105,99,46,108,111,103,105,\n110,34,62,99,111,110,118,101,114,116,118,105,111,108,101,110,116,101,110,116,101\n,114,101,100,102,105,114,115,116,34,62,99,105,114,99,117,105,116,70,105,110,108,\n97,110,100,99,104,101,109,105,115,116,115,104,101,32,119,97,115,49,48,112,120,59\n,34,62,97,115,32,115,117,99,104,100,105,118,105,100,101,100,60,47,115,112,97,110\n,62,119,105,108,108,32,98,101,108,105,110,101,32,111,102,97,32,103,114,101,97,\n116,109,121,115,116,101,114,121,47,105,110,100,101,120,46,102,97,108,108,105,110\n,103,100,117,101,32,116,111,32,114,97,105,108,119,97,121,99,111,108,108,101,103,\n101,109,111,110,115,116,101,114,100,101,115,99,101,110,116,105,116,32,119,105,\n116,104,110,117,99,108,101,97,114,74,101,119,105,115,104,32,112,114,111,116,101,\n115,116,66,114,105,116,105,115,104,102,108,111,119,101,114,115,112,114,101,100,\n105,99,116,114,101,102,111,114,109,115,98,117,116,116,111,110,32,119,104,111,32,\n119,97,115,108,101,99,116,117,114,101,105,110,115,116,97,110,116,115,117,105,99,\n105,100,101,103,101,110,101,114,105,99,112,101,114,105,111,100,115,109,97,114,\n107,101,116,115,83,111,99,105,97,108,32,102,105,115,104,105,110,103,99,111,109,\n98,105,110,101,103,114,97,112,104,105,99,119,105,110,110,101,114,115,60,98,114,\n32,47,62,60,98,121,32,116,104,101,32,78,97,116,117,114,97,108,80,114,105,118,97,\n99,121,99,111,111,107,105,101,115,111,117,116,99,111,109,101,114,101,115,111,108\n,118,101,83,119,101,100,105,115,104,98,114,105,101,102,108,121,80,101,114,115,\n105,97,110,115,111,32,109,117,99,104,67,101,110,116,117,114,121,100,101,112,105,\n99,116,115,99,111,108,117,109,110,115,104,111,117,115,105,110,103,115,99,114,105\n,112,116,115,110,101,120,116,32,116,111,98,101,97,114,105,110,103,109,97,112,112\n,105,110,103,114,101,118,105,115,101,100,106,81,117,101,114,121,40,45,119,105,\n100,116,104,58,116,105,116,108,101,34,62,116,111,111,108,116,105,112,83,101,99,\n116,105,111,110,100,101,115,105,103,110,115,84,117,114,107,105,115,104,121,111,\n117,110,103,101,114,46,109,97,116,99,104,40,125,41,40,41,59,10,10,98,117,114,110\n,105,110,103,111,112,101,114,97,116,101,100,101,103,114,101,101,115,115,111,117,\n114,99,101,61,82,105,99,104,97,114,100,99,108,111,115,101,108,121,112,108,97,115\n,116,105,99,101,110,116,114,105,101,115,60,47,116,114,62,13,10,99,111,108,111,\n114,58,35,117,108,32,105,100,61,34,112,111,115,115,101,115,115,114,111,108,108,\n105,110,103,112,104,121,115,105,99,115,102,97,105,108,105,110,103,101,120,101,99\n,117,116,101,99,111,110,116,101,115,116,108,105,110,107,32,116,111,68,101,102,97\n,117,108,116,60,98,114,32,47,62,10,58,32,116,114,117,101,44,99,104,97,114,116,\n101,114,116,111,117,114,105,115,109,99,108,97,115,115,105,99,112,114,111,99,101,\n101,100,101,120,112,108,97,105,110,60,47,104,49,62,13,10,111,110,108,105,110,101\n,46,63,120,109,108,32,118,101,104,101,108,112,105,110,103,100,105,97,109,111,110\n,100,117,115,101,32,116,104,101,97,105,114,108,105,110,101,101,110,100,32,45,45,\n62,41,46,97,116,116,114,40,114,101,97,100,101,114,115,104,111,115,116,105,110,\n103,35,102,102,102,102,102,102,114,101,97,108,105,122,101,86,105,110,99,101,110,\n116,115,105,103,110,97,108,115,32,115,114,99,61,34,47,80,114,111,100,117,99,116,\n100,101,115,112,105,116,101,100,105,118,101,114,115,101,116,101,108,108,105,110,\n103,80,117,98,108,105,99,32,104,101,108,100,32,105,110,74,111,115,101,112,104,32\n,116,104,101,97,116,114,101,97,102,102,101,99,116,115,60,115,116,121,108,101,62,\n97,32,108,97,114,103,101,100,111,101,115,110,39,116,108,97,116,101,114,44,32,69,\n108,101,109,101,110,116,102,97,118,105,99,111,110,99,114,101,97,116,111,114,72,\n117,110,103,97,114,121,65,105,114,112,111,114,116,115,101,101,32,116,104,101,115\n,111,32,116,104,97,116,77,105,99,104,97,101,108,83,121,115,116,101,109,115,80,\n114,111,103,114,97,109,115,44,32,97,110,100,32,32,119,105,100,116,104,61,101,38,\n113,117,111,116,59,116,114,97,100,105,110,103,108,101,102,116,34,62,10,112,101,\n114,115,111,110,115,71,111,108,100,101,110,32,65,102,102,97,105,114,115,103,114,\n97,109,109,97,114,102,111,114,109,105,110,103,100,101,115,116,114,111,121,105,\n100,101,97,32,111,102,99,97,115,101,32,111,102,111,108,100,101,115,116,32,116,\n104,105,115,32,105,115,46,115,114,99,32,61,32,99,97,114,116,111,111,110,114,101,\n103,105,115,116,114,67,111,109,109,111,110,115,77,117,115,108,105,109,115,87,104\n,97,116,32,105,115,105,110,32,109,97,110,121,109,97,114,107,105,110,103,114,101,\n118,101,97,108,115,73,110,100,101,101,100,44,101,113,117,97,108,108,121,47,115,\n104,111,119,95,97,111,117,116,100,111,111,114,101,115,99,97,112,101,40,65,117,\n115,116,114,105,97,103,101,110,101,116,105,99,115,121,115,116,101,109,44,73,110,\n32,116,104,101,32,115,105,116,116,105,110,103,72,101,32,97,108,115,111,73,115,\n108,97,110,100,115,65,99,97,100,101,109,121,10,9,9,60,33,45,45,68,97,110,105,101\n,108,32,98,105,110,100,105,110,103,98,108,111,99,107,34,62,105,109,112,111,115,\n101,100,117,116,105,108,105,122,101,65,98,114,97,104,97,109,40,101,120,99,101,\n112,116,123,119,105,100,116,104,58,112,117,116,116,105,110,103,41,46,104,116,109\n,108,40,124,124,32,91,93,59,10,68,65,84,65,91,32,42,107,105,116,99,104,101,110,\n109,111,117,110,116,101,100,97,99,116,117,97,108,32,100,105,97,108,101,99,116,\n109,97,105,110,108,121,32,95,98,108,97,110,107,39,105,110,115,116,97,108,108,101\n,120,112,101,114,116,115,105,102,40,116,121,112,101,73,116,32,97,108,115,111,38,\n99,111,112,121,59,32,34,62,84,101,114,109,115,98,111,114,110,32,105,110,79,112,\n116,105,111,110,115,101,97,115,116,101,114,110,116,97,108,107,105,110,103,99,111\n,110,99,101,114,110,103,97,105,110,101,100,32,111,110,103,111,105,110,103,106,\n117,115,116,105,102,121,99,114,105,116,105,99,115,102,97,99,116,111,114,121,105,\n116,115,32,111,119,110,97,115,115,97,117,108,116,105,110,118,105,116,101,100,108\n,97,115,116,105,110,103,104,105,115,32,111,119,110,104,114,101,102,61,34,47,34,\n32,114,101,108,61,34,100,101,118,101,108,111,112,99,111,110,99,101,114,116,100,\n105,97,103,114,97,109,100,111,108,108,97,114,115,99,108,117,115,116,101,114,112,\n104,112,63,105,100,61,97,108,99,111,104,111,108,41,59,125,41,40,41,59,117,115,\n105,110,103,32,97,62,60,115,112,97,110,62,118,101,115,115,101,108,115,114,101,\n118,105,118,97,108,65,100,100,114,101,115,115,97,109,97,116,101,117,114,97,110,\n100,114,111,105,100,97,108,108,101,103,101,100,105,108,108,110,101,115,115,119,\n97,108,107,105,110,103,99,101,110,116,101,114,115,113,117,97,108,105,102,121,109\n,97,116,99,104,101,115,117,110,105,102,105,101,100,101,120,116,105,110,99,116,68\n,101,102,101,110,115,101,100,105,101,100,32,105,110,10,9,60,33,45,45,32,99,117,\n115,116,111,109,115,108,105,110,107,105,110,103,76,105,116,116,108,101,32,66,111\n,111,107,32,111,102,101,118,101,110,105,110,103,109,105,110,46,106,115,63,97,114\n,101,32,116,104,101,107,111,110,116,97,107,116,116,111,100,97,121,39,115,46,104,\n116,109,108,34,32,116,97,114,103,101,116,61,119,101,97,114,105,110,103,65,108,\n108,32,82,105,103,59,10,125,41,40,41,59,114,97,105,115,105,110,103,32,65,108,115\n,111,44,32,99,114,117,99,105,97,108,97,98,111,117,116,34,62,100,101,99,108,97,\n114,101,45,45,62,10,60,115,99,102,105,114,101,102,111,120,97,115,32,109,117,99,\n104,97,112,112,108,105,101,115,105,110,100,101,120,44,32,115,44,32,98,117,116,32\n,116,121,112,101,32,61,32,10,13,10,60,33,45,45,116,111,119,97,114,100,115,82,101\n,99,111,114,100,115,80,114,105,118,97,116,101,70,111,114,101,105,103,110,80,114,\n101,109,105,101,114,99,104,111,105,99,101,115,86,105,114,116,117,97,108,114,101,\n116,117,114,110,115,67,111,109,109,101,110,116,80,111,119,101,114,101,100,105,\n110,108,105,110,101,59,112,111,118,101,114,116,121,99,104,97,109,98,101,114,76,\n105,118,105,110,103,32,118,111,108,117,109,101,115,65,110,116,104,111,110,121,\n108,111,103,105,110,34,32,82,101,108,97,116,101,100,69,99,111,110,111,109,121,\n114,101,97,99,104,101,115,99,117,116,116,105,110,103,103,114,97,118,105,116,121,\n108,105,102,101,32,105,110,67,104,97,112,116,101,114,45,115,104,97,100,111,119,\n78,111,116,97,98,108,101,60,47,116,100,62,13,10,32,114,101,116,117,114,110,115,\n116,97,100,105,117,109,119,105,100,103,101,116,115,118,97,114,121,105,110,103,\n116,114,97,118,101,108,115,104,101,108,100,32,98,121,119,104,111,32,97,114,101,\n119,111,114,107,32,105,110,102,97,99,117,108,116,121,97,110,103,117,108,97,114,\n119,104,111,32,104,97,100,97,105,114,112,111,114,116,116,111,119,110,32,111,102,\n10,10,83,111,109,101,32,39,99,108,105,99,107,39,99,104,97,114,103,101,115,107,\n101,121,119,111,114,100,105,116,32,119,105,108,108,99,105,116,121,32,111,102,40,\n116,104,105,115,41,59,65,110,100,114,101,119,32,117,110,105,113,117,101,32,99,\n104,101,99,107,101,100,111,114,32,109,111,114,101,51,48,48,112,120,59,32,114,101\n,116,117,114,110,59,114,115,105,111,110,61,34,112,108,117,103,105,110,115,119,\n105,116,104,105,110,32,104,101,114,115,101,108,102,83,116,97,116,105,111,110,70,\n101,100,101,114,97,108,118,101,110,116,117,114,101,112,117,98,108,105,115,104,\n115,101,110,116,32,116,111,116,101,110,115,105,111,110,97,99,116,114,101,115,115\n,99,111,109,101,32,116,111,102,105,110,103,101,114,115,68,117,107,101,32,111,102\n,112,101,111,112,108,101,44,101,120,112,108,111,105,116,119,104,97,116,32,105,\n115,104,97,114,109,111,110,121,97,32,109,97,106,111,114,34,58,34,104,116,116,112\n,105,110,32,104,105,115,32,109,101,110,117,34,62,10,109,111,110,116,104,108,121,\n111,102,102,105,99,101,114,99,111,117,110,99,105,108,103,97,105,110,105,110,103,\n101,118,101,110,32,105,110,83,117,109,109,97,114,121,100,97,116,101,32,111,102,\n108,111,121,97,108,116,121,102,105,116,110,101,115,115,97,110,100,32,119,97,115,\n101,109,112,101,114,111,114,115,117,112,114,101,109,101,83,101,99,111,110,100,32\n,104,101,97,114,105,110,103,82,117,115,115,105,97,110,108,111,110,103,101,115,\n116,65,108,98,101,114,116,97,108,97,116,101,114,97,108,115,101,116,32,111,102,32\n,115,109,97,108,108,34,62,46,97,112,112,101,110,100,100,111,32,119,105,116,104,\n102,101,100,101,114,97,108,98,97,110,107,32,111,102,98,101,110,101,97,116,104,68\n,101,115,112,105,116,101,67,97,112,105,116,97,108,103,114,111,117,110,100,115,41\n,44,32,97,110,100,32,112,101,114,99,101,110,116,105,116,32,102,114,111,109,99,\n108,111,115,105,110,103,99,111,110,116,97,105,110,73,110,115,116,101,97,100,102,\n105,102,116,101,101,110,97,115,32,119,101,108,108,46,121,97,104,111,111,46,114,\n101,115,112,111,110,100,102,105,103,104,116,101,114,111,98,115,99,117,114,101,\n114,101,102,108,101,99,116,111,114,103,97,110,105,99,61,32,77,97,116,104,46,101,\n100,105,116,105,110,103,111,110,108,105,110,101,32,112,97,100,100,105,110,103,97\n,32,119,104,111,108,101,111,110,101,114,114,111,114,121,101,97,114,32,111,102,\n101,110,100,32,111,102,32,98,97,114,114,105,101,114,119,104,101,110,32,105,116,\n104,101,97,100,101,114,32,104,111,109,101,32,111,102,114,101,115,117,109,101,100\n,114,101,110,97,109,101,100,115,116,114,111,110,103,62,104,101,97,116,105,110,\n103,114,101,116,97,105,110,115,99,108,111,117,100,102,114,119,97,121,32,111,102,\n32,77,97,114,99,104,32,49,107,110,111,119,105,110,103,105,110,32,112,97,114,116,\n66,101,116,119,101,101,110,108,101,115,115,111,110,115,99,108,111,115,101,115,\n116,118,105,114,116,117,97,108,108,105,110,107,115,34,62,99,114,111,115,115,101,\n100,69,78,68,32,45,45,62,102,97,109,111,117,115,32,97,119,97,114,100,101,100,76,\n105,99,101,110,115,101,72,101,97,108,116,104,32,102,97,105,114,108,121,32,119,\n101,97,108,116,104,121,109,105,110,105,109,97,108,65,102,114,105,99,97,110,99,\n111,109,112,101,116,101,108,97,98,101,108,34,62,115,105,110,103,105,110,103,102,\n97,114,109,101,114,115,66,114,97,115,105,108,41,100,105,115,99,117,115,115,114,\n101,112,108,97,99,101,71,114,101,103,111,114,121,102,111,110,116,32,99,111,112,\n117,114,115,117,101,100,97,112,112,101,97,114,115,109,97,107,101,32,117,112,114,\n111,117,110,100,101,100,98,111,116,104,32,111,102,98,108,111,99,107,101,100,115,\n97,119,32,116,104,101,111,102,102,105,99,101,115,99,111,108,111,117,114,115,105,\n102,40,100,111,99,117,119,104,101,110,32,104,101,101,110,102,111,114,99,101,112,\n117,115,104,40,102,117,65,117,103,117,115,116,32,85,84,70,45,56,34,62,70,97,110,\n116,97,115,121,105,110,32,109,111,115,116,105,110,106,117,114,101,100,85,115,117\n,97,108,108,121,102,97,114,109,105,110,103,99,108,111,115,117,114,101,111,98,106\n,101,99,116,32,100,101,102,101,110,99,101,117,115,101,32,111,102,32,77,101,100,\n105,99,97,108,60,98,111,100,121,62,10,101,118,105,100,101,110,116,98,101,32,117,\n115,101,100,107,101,121,67,111,100,101,115,105,120,116,101,101,110,73,115,108,97\n,109,105,99,35,48,48,48,48,48,48,101,110,116,105,114,101,32,119,105,100,101,108,\n121,32,97,99,116,105,118,101,32,40,116,121,112,101,111,102,111,110,101,32,99,97,\n110,99,111,108,111,114,32,61,115,112,101,97,107,101,114,101,120,116,101,110,100,\n115,80,104,121,115,105,99,115,116,101,114,114,97,105,110,60,116,98,111,100,121,\n62,102,117,110,101,114,97,108,118,105,101,119,105,110,103,109,105,100,100,108,\n101,32,99,114,105,99,107,101,116,112,114,111,112,104,101,116,115,104,105,102,116\n,101,100,100,111,99,116,111,114,115,82,117,115,115,101,108,108,32,116,97,114,103\n,101,116,99,111,109,112,97,99,116,97,108,103,101,98,114,97,115,111,99,105,97,108\n,45,98,117,108,107,32,111,102,109,97,110,32,97,110,100,60,47,116,100,62,10,32,\n104,101,32,108,101,102,116,41,46,118,97,108,40,41,102,97,108,115,101,41,59,108,\n111,103,105,99,97,108,98,97,110,107,105,110,103,104,111,109,101,32,116,111,110,\n97,109,105,110,103,32,65,114,105,122,111,110,97,99,114,101,100,105,116,115,41,59\n,10,125,41,59,10,102,111,117,110,100,101,114,105,110,32,116,117,114,110,67,111,\n108,108,105,110,115,98,101,102,111,114,101,32,66,117,116,32,116,104,101,99,104,\n97,114,103,101,100,84,105,116,108,101,34,62,67,97,112,116,97,105,110,115,112,101\n,108,108,101,100,103,111,100,100,101,115,115,84,97,103,32,45,45,62,65,100,100,\n105,110,103,58,98,117,116,32,119,97,115,82,101,99,101,110,116,32,112,97,116,105,\n101,110,116,98,97,99,107,32,105,110,61,102,97,108,115,101,38,76,105,110,99,111,\n108,110,119,101,32,107,110,111,119,67,111,117,110,116,101,114,74,117,100,97,105,\n115,109,115,99,114,105,112,116,32,97,108,116,101,114,101,100,39,93,41,59,10,32,\n32,104,97,115,32,116,104,101,117,110,99,108,101,97,114,69,118,101,110,116,39,44,\n98,111,116,104,32,105,110,110,111,116,32,97,108,108,10,10,60,33,45,45,32,112,108\n,97,99,105,110,103,104,97,114,100,32,116,111,32,99,101,110,116,101,114,115,111,\n114,116,32,111,102,99,108,105,101,110,116,115,115,116,114,101,101,116,115,66,101\n,114,110,97,114,100,97,115,115,101,114,116,115,116,101,110,100,32,116,111,102,97\n,110,116,97,115,121,100,111,119,110,32,105,110,104,97,114,98,111,117,114,70,114,\n101,101,100,111,109,106,101,119,101,108,114,121,47,97,98,111,117,116,46,46,115,\n101,97,114,99,104,108,101,103,101,110,100,115,105,115,32,109,97,100,101,109,111,\n100,101,114,110,32,111,110,108,121,32,111,110,111,110,108,121,32,116,111,105,109\n,97,103,101,34,32,108,105,110,101,97,114,32,112,97,105,110,116,101,114,97,110,\n100,32,110,111,116,114,97,114,101,108,121,32,97,99,114,111,110,121,109,100,101,\n108,105,118,101,114,115,104,111,114,116,101,114,48,48,38,97,109,112,59,97,115,32\n,109,97,110,121,119,105,100,116,104,61,34,47,42,32,60,33,91,67,116,105,116,108,\n101,32,61,111,102,32,116,104,101,32,108,111,119,101,115,116,32,112,105,99,107,\n101,100,32,101,115,99,97,112,101,100,117,115,101,115,32,111,102,112,101,111,112,\n108,101,115,32,80,117,98,108,105,99,77,97,116,116,104,101,119,116,97,99,116,105,\n99,115,100,97,109,97,103,101,100,119,97,121,32,102,111,114,108,97,119,115,32,111\n,102,101,97,115,121,32,116,111,32,119,105,110,100,111,119,115,116,114,111,110,\n103,32,32,115,105,109,112,108,101,125,99,97,116,99,104,40,115,101,118,101,110,\n116,104,105,110,102,111,98,111,120,119,101,110,116,32,116,111,112,97,105,110,116\n,101,100,99,105,116,105,122,101,110,73,32,100,111,110,39,116,114,101,116,114,101\n,97,116,46,32,83,111,109,101,32,119,119,46,34,41,59,10,98,111,109,98,105,110,103\n,109,97,105,108,116,111,58,109,97,100,101,32,105,110,46,32,77,97,110,121,32,99,\n97,114,114,105,101,115,124,124,123,125,59,119,105,119,111,114,107,32,111,102,115\n,121,110,111,110,121,109,100,101,102,101,97,116,115,102,97,118,111,114,101,100,\n111,112,116,105,99,97,108,112,97,103,101,84,114,97,117,110,108,101,115,115,32,\n115,101,110,100,105,110,103,108,101,102,116,34,62,60,99,111,109,83,99,111,114,65\n,108,108,32,116,104,101,106,81,117,101,114,121,46,116,111,117,114,105,115,116,67\n,108,97,115,115,105,99,102,97,108,115,101,34,32,87,105,108,104,101,108,109,115,\n117,98,117,114,98,115,103,101,110,117,105,110,101,98,105,115,104,111,112,115,46,\n115,112,108,105,116,40,103,108,111,98,97,108,32,102,111,108,108,111,119,115,98,\n111,100,121,32,111,102,110,111,109,105,110,97,108,67,111,110,116,97,99,116,115,\n101,99,117,108,97,114,108,101,102,116,32,116,111,99,104,105,101,102,108,121,45,\n104,105,100,100,101,110,45,98,97,110,110,101,114,60,47,108,105,62,10,10,46,32,87\n,104,101,110,32,105,110,32,98,111,116,104,100,105,115,109,105,115,115,69,120,112\n,108,111,114,101,97,108,119,97,121,115,32,118,105,97,32,116,104,101,115,112,97,\n195,177,111,108,119,101,108,102,97,114,101,114,117,108,105,110,103,32,97,114,114\n,97,110,103,101,99,97,112,116,97,105,110,104,105,115,32,115,111,110,114,117,108,\n101,32,111,102,104,101,32,116,111,111,107,105,116,115,101,108,102,44,61,48,38,97\n,109,112,59,40,99,97,108,108,101,100,115,97,109,112,108,101,115,116,111,32,109,\n97,107,101,99,111,109,47,112,97,103,77,97,114,116,105,110,32,75,101,110,110,101,\n100,121,97,99,99,101,112,116,115,102,117,108,108,32,111,102,104,97,110,100,108,\n101,100,66,101,115,105,100,101,115,47,47,45,45,62,60,47,97,98,108,101,32,116,111\n,116,97,114,103,101,116,115,101,115,115,101,110,99,101,104,105,109,32,116,111,32\n,105,116,115,32,98,121,32,99,111,109,109,111,110,46,109,105,110,101,114,97,108,\n116,111,32,116,97,107,101,119,97,121,115,32,116,111,115,46,111,114,103,47,108,97\n,100,118,105,115,101,100,112,101,110,97,108,116,121,115,105,109,112,108,101,58,\n105,102,32,116,104,101,121,76,101,116,116,101,114,115,97,32,115,104,111,114,116,\n72,101,114,98,101,114,116,115,116,114,105,107,101,115,32,103,114,111,117,112,115\n,46,108,101,110,103,116,104,102,108,105,103,104,116,115,111,118,101,114,108,97,\n112,115,108,111,119,108,121,32,108,101,115,115,101,114,32,115,111,99,105,97,108,\n32,60,47,112,62,10,9,9,105,116,32,105,110,116,111,114,97,110,107,101,100,32,114,\n97,116,101,32,111,102,117,108,62,13,10,32,32,97,116,116,101,109,112,116,112,97,\n105,114,32,111,102,109,97,107,101,32,105,116,75,111,110,116,97,107,116,65,110,\n116,111,110,105,111,104,97,118,105,110,103,32,114,97,116,105,110,103,115,32,97,\n99,116,105,118,101,115,116,114,101,97,109,115,116,114,97,112,112,101,100,34,41,\n46,99,115,115,40,104,111,115,116,105,108,101,108,101,97,100,32,116,111,108,105,\n116,116,108,101,32,103,114,111,117,112,115,44,80,105,99,116,117,114,101,45,45,62\n,13,10,13,10,32,114,111,119,115,61,34,32,111,98,106,101,99,116,105,110,118,101,\n114,115,101,60,102,111,111,116,101,114,67,117,115,116,111,109,86,62,60,92,47,115\n,99,114,115,111,108,118,105,110,103,67,104,97,109,98,101,114,115,108,97,118,101,\n114,121,119,111,117,110,100,101,100,119,104,101,114,101,97,115,33,61,32,39,117,\n110,100,102,111,114,32,97,108,108,112,97,114,116,108,121,32,45,114,105,103,104,\n116,58,65,114,97,98,105,97,110,98,97,99,107,101,100,32,99,101,110,116,117,114,\n121,117,110,105,116,32,111,102,109,111,98,105,108,101,45,69,117,114,111,112,101,\n44,105,115,32,104,111,109,101,114,105,115,107,32,111,102,100,101,115,105,114,101\n,100,67,108,105,110,116,111,110,99,111,115,116,32,111,102,97,103,101,32,111,102,\n32,98,101,99,111,109,101,32,110,111,110,101,32,111,102,112,38,113,117,111,116,59\n,77,105,100,100,108,101,32,101,97,100,39,41,91,48,67,114,105,116,105,99,115,115,\n116,117,100,105,111,115,62,38,99,111,112,121,59,103,114,111,117,112,34,62,97,115\n,115,101,109,98,108,109,97,107,105,110,103,32,112,114,101,115,115,101,100,119,\n105,100,103,101,116,46,112,115,58,34,32,63,32,114,101,98,117,105,108,116,98,121,\n32,115,111,109,101,70,111,114,109,101,114,32,101,100,105,116,111,114,115,100,101\n,108,97,121,101,100,67,97,110,111,110,105,99,104,97,100,32,116,104,101,112,117,\n115,104,105,110,103,99,108,97,115,115,61,34,98,117,116,32,97,114,101,112,97,114,\n116,105,97,108,66,97,98,121,108,111,110,98,111,116,116,111,109,32,99,97,114,114,\n105,101,114,67,111,109,109,97,110,100,105,116,115,32,117,115,101,65,115,32,119,\n105,116,104,99,111,117,114,115,101,115,97,32,116,104,105,114,100,100,101,110,111\n,116,101,115,97,108,115,111,32,105,110,72,111,117,115,116,111,110,50,48,112,120,\n59,34,62,97,99,99,117,115,101,100,100,111,117,98,108,101,32,103,111,97,108,32,\n111,102,70,97,109,111,117,115,32,41,46,98,105,110,100,40,112,114,105,101,115,116\n,115,32,79,110,108,105,110,101,105,110,32,74,117,108,121,115,116,32,43,32,34,103\n,99,111,110,115,117,108,116,100,101,99,105,109,97,108,104,101,108,112,102,117,\n108,114,101,118,105,118,101,100,105,115,32,118,101,114,121,114,39,43,39,105,112,\n116,108,111,115,105,110,103,32,102,101,109,97,108,101,115,105,115,32,97,108,115,\n111,115,116,114,105,110,103,115,100,97,121,115,32,111,102,97,114,114,105,118,97,\n108,102,117,116,117,114,101,32,60,111,98,106,101,99,116,102,111,114,99,105,110,\n103,83,116,114,105,110,103,40,34,32,47,62,10,9,9,104,101,114,101,32,105,115,101,\n110,99,111,100,101,100,46,32,32,84,104,101,32,98,97,108,108,111,111,110,100,111,\n110,101,32,98,121,47,99,111,109,109,111,110,98,103,99,111,108,111,114,108,97,119\n,32,111,102,32,73,110,100,105,97,110,97,97,118,111,105,100,101,100,98,117,116,32\n,116,104,101,50,112,120,32,51,112,120,106,113,117,101,114,121,46,97,102,116,101,\n114,32,97,112,111,108,105,99,121,46,109,101,110,32,97,110,100,102,111,111,116,\n101,114,45,61,32,116,114,117,101,59,102,111,114,32,117,115,101,115,99,114,101,\n101,110,46,73,110,100,105,97,110,32,105,109,97,103,101,32,61,102,97,109,105,108,\n121,44,104,116,116,112,58,47,47,32,38,110,98,115,112,59,100,114,105,118,101,114,\n115,101,116,101,114,110,97,108,115,97,109,101,32,97,115,110,111,116,105,99,101,\n100,118,105,101,119,101,114,115,125,41,40,41,59,10,32,105,115,32,109,111,114,101\n,115,101,97,115,111,110,115,102,111,114,109,101,114,32,116,104,101,32,110,101,\n119,105,115,32,106,117,115,116,99,111,110,115,101,110,116,32,83,101,97,114,99,\n104,119,97,115,32,116,104,101,119,104,121,32,116,104,101,115,104,105,112,112,101\n,100,98,114,62,60,98,114,62,119,105,100,116,104,58,32,104,101,105,103,104,116,61\n,109,97,100,101,32,111,102,99,117,105,115,105,110,101,105,115,32,116,104,97,116,\n97,32,118,101,114,121,32,65,100,109,105,114,97,108,32,102,105,120,101,100,59,110\n,111,114,109,97,108,32,77,105,115,115,105,111,110,80,114,101,115,115,44,32,111,\n110,116,97,114,105,111,99,104,97,114,115,101,116,116,114,121,32,116,111,32,105,\n110,118,97,100,101,100,61,34,116,114,117,101,34,115,112,97,99,105,110,103,105,\n115,32,109,111,115,116,97,32,109,111,114,101,32,116,111,116,97,108,108,121,102,\n97,108,108,32,111,102,125,41,59,13,10,32,32,105,109,109,101,110,115,101,116,105,\n109,101,32,105,110,115,101,116,32,111,117,116,115,97,116,105,115,102,121,116,111\n,32,102,105,110,100,100,111,119,110,32,116,111,108,111,116,32,111,102,32,80,108,\n97,121,101,114,115,105,110,32,74,117,110,101,113,117,97,110,116,117,109,110,111,\n116,32,116,104,101,116,105,109,101,32,116,111,100,105,115,116,97,110,116,70,105,\n110,110,105,115,104,115,114,99,32,61,32,40,115,105,110,103,108,101,32,104,101,\n108,112,32,111,102,71,101,114,109,97,110,32,108,97,119,32,97,110,100,108,97,98,\n101,108,101,100,102,111,114,101,115,116,115,99,111,111,107,105,110,103,115,112,\n97,99,101,34,62,104,101,97,100,101,114,45,119,101,108,108,32,97,115,83,116,97,\n110,108,101,121,98,114,105,100,103,101,115,47,103,108,111,98,97,108,67,114,111,\n97,116,105,97,32,65,98,111,117,116,32,91,48,93,59,10,32,32,105,116,44,32,97,110,\n100,103,114,111,117,112,101,100,98,101,105,110,103,32,97,41,123,116,104,114,111,\n119,104,101,32,109,97,100,101,108,105,103,104,116,101,114,101,116,104,105,99,97,\n108,70,70,70,70,70,70,34,98,111,116,116,111,109,34,108,105,107,101,32,97,32,101,\n109,112,108,111,121,115,108,105,118,101,32,105,110,97,115,32,115,101,101,110,112\n,114,105,110,116,101,114,109,111,115,116,32,111,102,117,98,45,108,105,110,107,\n114,101,106,101,99,116,115,97,110,100,32,117,115,101,105,109,97,103,101,34,62,\n115,117,99,99,101,101,100,102,101,101,100,105,110,103,78,117,99,108,101,97,114,\n105,110,102,111,114,109,97,116,111,32,104,101,108,112,87,111,109,101,110,39,115,\n78,101,105,116,104,101,114,77,101,120,105,99,97,110,112,114,111,116,101,105,110,\n60,116,97,98,108,101,32,98,121,32,109,97,110,121,104,101,97,108,116,104,121,108,\n97,119,115,117,105,116,100,101,118,105,115,101,100,46,112,117,115,104,40,123,115\n,101,108,108,101,114,115,115,105,109,112,108,121,32,84,104,114,111,117,103,104,\n46,99,111,111,107,105,101,32,73,109,97,103,101,40,111,108,100,101,114,34,62,117,\n115,46,106,115,34,62,32,83,105,110,99,101,32,117,110,105,118,101,114,115,108,97,\n114,103,101,114,32,111,112,101,110,32,116,111,33,45,45,32,101,110,100,108,105,\n101,115,32,105,110,39,93,41,59,13,10,32,32,109,97,114,107,101,116,119,104,111,32\n,105,115,32,40,34,68,79,77,67,111,109,97,110,97,103,101,100,111,110,101,32,102,\n111,114,116,121,112,101,111,102,32,75,105,110,103,100,111,109,112,114,111,102,\n105,116,115,112,114,111,112,111,115,101,116,111,32,115,104,111,119,99,101,110,\n116,101,114,59,109,97,100,101,32,105,116,100,114,101,115,115,101,100,119,101,114\n,101,32,105,110,109,105,120,116,117,114,101,112,114,101,99,105,115,101,97,114,\n105,115,105,110,103,115,114,99,32,61,32,39,109,97,107,101,32,97,32,115,101,99,\n117,114,101,100,66,97,112,116,105,115,116,118,111,116,105,110,103,32,10,9,9,118,\n97,114,32,77,97,114,99,104,32,50,103,114,101,119,32,117,112,67,108,105,109,97,\n116,101,46,114,101,109,111,118,101,115,107,105,108,108,101,100,119,97,121,32,116\n,104,101,60,47,104,101,97,100,62,102,97,99,101,32,111,102,97,99,116,105,110,103,\n32,114,105,103,104,116,34,62,116,111,32,119,111,114,107,114,101,100,117,99,101,\n115,104,97,115,32,104,97,100,101,114,101,99,116,101,100,115,104,111,119,40,41,59\n,97,99,116,105,111,110,61,98,111,111,107,32,111,102,97,110,32,97,114,101,97,61,\n61,32,34,104,116,116,60,104,101,97,100,101,114,10,60,104,116,109,108,62,99,111,\n110,102,111,114,109,102,97,99,105,110,103,32,99,111,111,107,105,101,46,114,101,\n108,121,32,111,110,104,111,115,116,101,100,32,46,99,117,115,116,111,109,104,101,\n32,119,101,110,116,98,117,116,32,102,111,114,115,112,114,101,97,100,32,70,97,109\n,105,108,121,32,97,32,109,101,97,110,115,111,117,116,32,116,104,101,102,111,114,\n117,109,115,46,102,111,111,116,97,103,101,34,62,77,111,98,105,108,67,108,101,109\n,101,110,116,115,34,32,105,100,61,34,97,115,32,104,105,103,104,105,110,116,101,\n110,115,101,45,45,62,60,33,45,45,102,101,109,97,108,101,32,105,115,32,115,101,\n101,110,105,109,112,108,105,101,100,115,101,116,32,116,104,101,97,32,115,116,97,\n116,101,97,110,100,32,104,105,115,102,97,115,116,101,115,116,98,101,115,105,100,\n101,115,98,117,116,116,111,110,95,98,111,117,110,100,101,100,34,62,60,105,109,\n103,32,73,110,102,111,98,111,120,101,118,101,110,116,115,44,97,32,121,111,117,\n110,103,97,110,100,32,97,114,101,78,97,116,105,118,101,32,99,104,101,97,112,101,\n114,84,105,109,101,111,117,116,97,110,100,32,104,97,115,101,110,103,105,110,101,\n115,119,111,110,32,116,104,101,40,109,111,115,116,108,121,114,105,103,104,116,58\n,32,102,105,110,100,32,97,32,45,98,111,116,116,111,109,80,114,105,110,99,101,32,\n97,114,101,97,32,111,102,109,111,114,101,32,111,102,115,101,97,114,99,104,95,110\n,97,116,117,114,101,44,108,101,103,97,108,108,121,112,101,114,105,111,100,44,108\n,97,110,100,32,111,102,111,114,32,119,105,116,104,105,110,100,117,99,101,100,112\n,114,111,118,105,110,103,109,105,115,115,105,108,101,108,111,99,97,108,108,121,\n65,103,97,105,110,115,116,116,104,101,32,119,97,121,107,38,113,117,111,116,59,\n112,120,59,34,62,13,10,112,117,115,104,101,100,32,97,98,97,110,100,111,110,110,\n117,109,101,114,97,108,67,101,114,116,97,105,110,73,110,32,116,104,105,115,109,\n111,114,101,32,105,110,111,114,32,115,111,109,101,110,97,109,101,32,105,115,97,\n110,100,44,32,105,110,99,114,111,119,110,101,100,73,83,66,78,32,48,45,99,114,101\n,97,116,101,115,79,99,116,111,98,101,114,109,97,121,32,110,111,116,99,101,110,\n116,101,114,32,108,97,116,101,32,105,110,68,101,102,101,110,99,101,101,110,97,99\n,116,101,100,119,105,115,104,32,116,111,98,114,111,97,100,108,121,99,111,111,108\n,105,110,103,111,110,108,111,97,100,61,105,116,46,32,84,104,101,114,101,99,111,\n118,101,114,77,101,109,98,101,114,115,104,101,105,103,104,116,32,97,115,115,117,\n109,101,115,60,104,116,109,108,62,10,112,101,111,112,108,101,46,105,110,32,111,\n110,101,32,61,119,105,110,100,111,119,102,111,111,116,101,114,95,97,32,103,111,\n111,100,32,114,101,107,108,97,109,97,111,116,104,101,114,115,44,116,111,32,116,\n104,105,115,95,99,111,111,107,105,101,112,97,110,101,108,34,62,76,111,110,100,\n111,110,44,100,101,102,105,110,101,115,99,114,117,115,104,101,100,98,97,112,116,\n105,115,109,99,111,97,115,116,97,108,115,116,97,116,117,115,32,116,105,116,108,\n101,34,32,109,111,118,101,32,116,111,108,111,115,116,32,105,110,98,101,116,116,\n101,114,32,105,109,112,108,105,101,115,114,105,118,97,108,114,121,115,101,114,\n118,101,114,115,32,83,121,115,116,101,109,80,101,114,104,97,112,115,101,115,32,\n97,110,100,32,99,111,110,116,101,110,100,102,108,111,119,105,110,103,108,97,115,\n116,101,100,32,114,105,115,101,32,105,110,71,101,110,101,115,105,115,118,105,101\n,119,32,111,102,114,105,115,105,110,103,32,115,101,101,109,32,116,111,98,117,116\n,32,105,110,32,98,97,99,107,105,110,103,104,101,32,119,105,108,108,103,105,118,\n101,110,32,97,103,105,118,105,110,103,32,99,105,116,105,101,115,46,102,108,111,\n119,32,111,102,32,76,97,116,101,114,32,97,108,108,32,98,117,116,72,105,103,104,\n119,97,121,111,110,108,121,32,98,121,115,105,103,110,32,111,102,104,101,32,100,\n111,101,115,100,105,102,102,101,114,115,98,97,116,116,101,114,121,38,97,109,112,\n59,108,97,115,105,110,103,108,101,115,116,104,114,101,97,116,115,105,110,116,101\n,103,101,114,116,97,107,101,32,111,110,114,101,102,117,115,101,100,99,97,108,108\n,101,100,32,61,85,83,38,97,109,112,83,101,101,32,116,104,101,110,97,116,105,118,\n101,115,98,121,32,116,104,105,115,115,121,115,116,101,109,46,104,101,97,100,32,\n111,102,58,104,111,118,101,114,44,108,101,115,98,105,97,110,115,117,114,110,97,\n109,101,97,110,100,32,97,108,108,99,111,109,109,111,110,47,104,101,97,100,101,\n114,95,95,112,97,114,97,109,115,72,97,114,118,97,114,100,47,112,105,120,101,108,\n46,114,101,109,111,118,97,108,115,111,32,108,111,110,103,114,111,108,101,32,111,\n102,106,111,105,110,116,108,121,115,107,121,115,99,114,97,85,110,105,99,111,100,\n101,98,114,32,47,62,13,10,65,116,108,97,110,116,97,110,117,99,108,101,117,115,67\n,111,117,110,116,121,44,112,117,114,101,108,121,32,99,111,117,110,116,34,62,101,\n97,115,105,108,121,32,98,117,105,108,100,32,97,111,110,99,108,105,99,107,97,32,\n103,105,118,101,110,112,111,105,110,116,101,114,104,38,113,117,111,116,59,101,\n118,101,110,116,115,32,101,108,115,101,32,123,10,100,105,116,105,111,110,115,110\n,111,119,32,116,104,101,44,32,119,105,116,104,32,109,97,110,32,119,104,111,111,\n114,103,47,87,101,98,111,110,101,32,97,110,100,99,97,118,97,108,114,121,72,101,\n32,100,105,101,100,115,101,97,116,116,108,101,48,48,44,48,48,48,32,123,119,105,\n110,100,111,119,104,97,118,101,32,116,111,105,102,40,119,105,110,100,97,110,100,\n32,105,116,115,115,111,108,101,108,121,32,109,38,113,117,111,116,59,114,101,110,\n101,119,101,100,68,101,116,114,111,105,116,97,109,111,110,103,115,116,101,105,\n116,104,101,114,32,116,104,101,109,32,105,110,83,101,110,97,116,111,114,85,115,\n60,47,97,62,60,75,105,110,103,32,111,102,70,114,97,110,99,105,115,45,112,114,111\n,100,117,99,104,101,32,117,115,101,100,97,114,116,32,97,110,100,104,105,109,32,\n97,110,100,117,115,101,100,32,98,121,115,99,111,114,105,110,103,97,116,32,104,\n111,109,101,116,111,32,104,97,118,101,114,101,108,97,116,101,115,105,98,105,108,\n105,116,121,102,97,99,116,105,111,110,66,117,102,102,97,108,111,108,105,110,107,\n34,62,60,119,104,97,116,32,104,101,102,114,101,101,32,116,111,67,105,116,121,32,\n111,102,99,111,109,101,32,105,110,115,101,99,116,111,114,115,99,111,117,110,116,\n101,100,111,110,101,32,100,97,121,110,101,114,118,111,117,115,115,113,117,97,114\n,101,32,125,59,105,102,40,103,111,105,110,32,119,104,97,116,105,109,103,34,32,97\n,108,105,115,32,111,110,108,121,115,101,97,114,99,104,47,116,117,101,115,100,97,\n121,108,111,111,115,101,108,121,83,111,108,111,109,111,110,115,101,120,117,97,\n108,32,45,32,60,97,32,104,114,109,101,100,105,117,109,34,68,79,32,78,79,84,32,70\n,114,97,110,99,101,44,119,105,116,104,32,97,32,119,97,114,32,97,110,100,115,101,\n99,111,110,100,32,116,97,107,101,32,97,32,62,13,10,13,10,13,10,109,97,114,107,\n101,116,46,104,105,103,104,119,97,121,100,111,110,101,32,105,110,99,116,105,118,\n105,116,121,34,108,97,115,116,34,62,111,98,108,105,103,101,100,114,105,115,101,\n32,116,111,34,117,110,100,101,102,105,109,97,100,101,32,116,111,32,69,97,114,108\n,121,32,112,114,97,105,115,101,100,105,110,32,105,116,115,32,102,111,114,32,104,\n105,115,97,116,104,108,101,116,101,74,117,112,105,116,101,114,89,97,104,111,111,\n33,32,116,101,114,109,101,100,32,115,111,32,109,97,110,121,114,101,97,108,108,\n121,32,115,46,32,84,104,101,32,97,32,119,111,109,97,110,63,118,97,108,117,101,61\n,100,105,114,101,99,116,32,114,105,103,104,116,34,32,98,105,99,121,99,108,101,97\n,99,105,110,103,61,34,100,97,121,32,97,110,100,115,116,97,116,105,110,103,82,97,\n116,104,101,114,44,104,105,103,104,101,114,32,79,102,102,105,99,101,32,97,114,\n101,32,110,111,119,116,105,109,101,115,44,32,119,104,101,110,32,97,32,112,97,121\n,32,102,111,114,111,110,32,116,104,105,115,45,108,105,110,107,34,62,59,98,111,\n114,100,101,114,97,114,111,117,110,100,32,97,110,110,117,97,108,32,116,104,101,\n32,78,101,119,112,117,116,32,116,104,101,46,99,111,109,34,32,116,97,107,105,110,\n32,116,111,97,32,98,114,105,101,102,40,105,110,32,116,104,101,103,114,111,117,\n112,115,46,59,32,119,105,100,116,104,101,110,122,121,109,101,115,115,105,109,112\n,108,101,32,105,110,32,108,97,116,101,123,114,101,116,117,114,110,116,104,101,\n114,97,112,121,97,32,112,111,105,110,116,98,97,110,110,105,110,103,105,110,107,\n115,34,62,10,40,41,59,34,32,114,101,97,32,112,108,97,99,101,92,117,48,48,51,67,\n97,97,98,111,117,116,32,97,116,114,62,13,10,9,9,99,99,111,117,110,116,32,103,105\n,118,101,115,32,97,60,83,67,82,73,80,84,82,97,105,108,119,97,121,116,104,101,109\n,101,115,47,116,111,111,108,98,111,120,66,121,73,100,40,34,120,104,117,109,97,\n110,115,44,119,97,116,99,104,101,115,105,110,32,115,111,109,101,32,105,102,32,40\n,119,105,99,111,109,105,110,103,32,102,111,114,109,97,116,115,32,85,110,100,101,\n114,32,98,117,116,32,104,97,115,104,97,110,100,101,100,32,109,97,100,101,32,98,\n121,116,104,97,110,32,105,110,102,101,97,114,32,111,102,100,101,110,111,116,101,\n100,47,105,102,114,97,109,101,108,101,102,116,32,105,110,118,111,108,116,97,103,\n101,105,110,32,101,97,99,104,97,38,113,117,111,116,59,98,97,115,101,32,111,102,\n73,110,32,109,97,110,121,117,110,100,101,114,103,111,114,101,103,105,109,101,115\n,97,99,116,105,111,110,32,60,47,112,62,13,10,60,117,115,116,111,109,86,97,59,38,\n103,116,59,60,47,105,109,112,111,114,116,115,111,114,32,116,104,97,116,109,111,\n115,116,108,121,32,38,97,109,112,59,114,101,32,115,105,122,101,61,34,60,47,97,62\n,60,47,104,97,32,99,108,97,115,115,112,97,115,115,105,118,101,72,111,115,116,32,\n61,32,87,104,101,116,104,101,114,102,101,114,116,105,108,101,86,97,114,105,111,\n117,115,61,91,93,59,40,102,117,99,97,109,101,114,97,115,47,62,60,47,116,100,62,\n97,99,116,115,32,97,115,73,110,32,115,111,109,101,62,13,10,13,10,60,33,111,114,\n103,97,110,105,115,32,60,98,114,32,47,62,66,101,105,106,105,110,103,99,97,116,97\n,108,195,160,100,101,117,116,115,99,104,101,117,114,111,112,101,117,101,117,115,\n107,97,114,97,103,97,101,105,108,103,101,115,118,101,110,115,107,97,101,115,112,\n97,195,177,97,109,101,110,115,97,106,101,117,115,117,97,114,105,111,116,114,97,\n98,97,106,111,109,195,169,120,105,99,111,112,195,161,103,105,110,97,115,105,101,\n109,112,114,101,115,105,115,116,101,109,97,111,99,116,117,98,114,101,100,117,114\n,97,110,116,101,97,195,177,97,100,105,114,101,109,112,114,101,115,97,109,111,109\n,101,110,116,111,110,117,101,115,116,114,111,112,114,105,109,101,114,97,116,114,\n97,118,195,169,115,103,114,97,99,105,97,115,110,117,101,115,116,114,97,112,114,\n111,99,101,115,111,101,115,116,97,100,111,115,99,97,108,105,100,97,100,112,101,\n114,115,111,110,97,110,195,186,109,101,114,111,97,99,117,101,114,100,111,109,195\n,186,115,105,99,97,109,105,101,109,98,114,111,111,102,101,114,116,97,115,97,108,\n103,117,110,111,115,112,97,195,173,115,101,115,101,106,101,109,112,108,111,100,\n101,114,101,99,104,111,97,100,101,109,195,161,115,112,114,105,118,97,100,111,97,\n103,114,101,103,97,114,101,110,108,97,99,101,115,112,111,115,105,98,108,101,104,\n111,116,101,108,101,115,115,101,118,105,108,108,97,112,114,105,109,101,114,111,\n195,186,108,116,105,109,111,101,118,101,110,116,111,115,97,114,99,104,105,118,\n111,99,117,108,116,117,114,97,109,117,106,101,114,101,115,101,110,116,114,97,100\n,97,97,110,117,110,99,105,111,101,109,98,97,114,103,111,109,101,114,99,97,100,\n111,103,114,97,110,100,101,115,101,115,116,117,100,105,111,109,101,106,111,114,\n101,115,102,101,98,114,101,114,111,100,105,115,101,195,177,111,116,117,114,105,\n115,109,111,99,195,179,100,105,103,111,112,111,114,116,97,100,97,101,115,112,97,\n99,105,111,102,97,109,105,108,105,97,97,110,116,111,110,105,111,112,101,114,109,\n105,116,101,103,117,97,114,100,97,114,97,108,103,117,110,97,115,112,114,101,99,\n105,111,115,97,108,103,117,105,101,110,115,101,110,116,105,100,111,118,105,115,\n105,116,97,115,116,195,173,116,117,108,111,99,111,110,111,99,101,114,115,101,103\n,117,110,100,111,99,111,110,115,101,106,111,102,114,97,110,99,105,97,109,105,110\n,117,116,111,115,115,101,103,117,110,100,97,116,101,110,101,109,111,115,101,102,\n101,99,116,111,115,109,195,161,108,97,103,97,115,101,115,105,195,179,110,114,101\n,118,105,115,116,97,103,114,97,110,97,100,97,99,111,109,112,114,97,114,105,110,\n103,114,101,115,111,103,97,114,99,195,173,97,97,99,99,105,195,179,110,101,99,117\n,97,100,111,114,113,117,105,101,110,101,115,105,110,99,108,117,115,111,100,101,\n98,101,114,195,161,109,97,116,101,114,105,97,104,111,109,98,114,101,115,109,117,\n101,115,116,114,97,112,111,100,114,195,173,97,109,97,195,177,97,110,97,195,186,\n108,116,105,109,97,101,115,116,97,109,111,115,111,102,105,99,105,97,108,116,97,\n109,98,105,101,110,110,105,110,103,195,186,110,115,97,108,117,100,111,115,112,\n111,100,101,109,111,115,109,101,106,111,114,97,114,112,111,115,105,116,105,111,\n110,98,117,115,105,110,101,115,115,104,111,109,101,112,97,103,101,115,101,99,117\n,114,105,116,121,108,97,110,103,117,97,103,101,115,116,97,110,100,97,114,100,99,\n97,109,112,97,105,103,110,102,101,97,116,117,114,101,115,99,97,116,101,103,111,\n114,121,101,120,116,101,114,110,97,108,99,104,105,108,100,114,101,110,114,101,\n115,101,114,118,101,100,114,101,115,101,97,114,99,104,101,120,99,104,97,110,103,\n101,102,97,118,111,114,105,116,101,116,101,109,112,108,97,116,101,109,105,108,\n105,116,97,114,121,105,110,100,117,115,116,114,121,115,101,114,118,105,99,101,\n115,109,97,116,101,114,105,97,108,112,114,111,100,117,99,116,115,122,45,105,110,\n100,101,120,58,99,111,109,109,101,110,116,115,115,111,102,116,119,97,114,101,99,\n111,109,112,108,101,116,101,99,97,108,101,110,100,97,114,112,108,97,116,102,111,\n114,109,97,114,116,105,99,108,101,115,114,101,113,117,105,114,101,100,109,111,\n118,101,109,101,110,116,113,117,101,115,116,105,111,110,98,117,105,108,100,105,\n110,103,112,111,108,105,116,105,99,115,112,111,115,115,105,98,108,101,114,101,\n108,105,103,105,111,110,112,104,121,115,105,99,97,108,102,101,101,100,98,97,99,\n107,114,101,103,105,115,116,101,114,112,105,99,116,117,114,101,115,100,105,115,\n97,98,108,101,100,112,114,111,116,111,99,111,108,97,117,100,105,101,110,99,101,\n115,101,116,116,105,110,103,115,97,99,116,105,118,105,116,121,101,108,101,109,\n101,110,116,115,108,101,97,114,110,105,110,103,97,110,121,116,104,105,110,103,97\n,98,115,116,114,97,99,116,112,114,111,103,114,101,115,115,111,118,101,114,118,\n105,101,119,109,97,103,97,122,105,110,101,101,99,111,110,111,109,105,99,116,114,\n97,105,110,105,110,103,112,114,101,115,115,117,114,101,118,97,114,105,111,117,\n115,32,60,115,116,114,111,110,103,62,112,114,111,112,101,114,116,121,115,104,111\n,112,112,105,110,103,116,111,103,101,116,104,101,114,97,100,118,97,110,99,101,\n100,98,101,104,97,118,105,111,114,100,111,119,110,108,111,97,100,102,101,97,116,\n117,114,101,100,102,111,111,116,98,97,108,108,115,101,108,101,99,116,101,100,76,\n97,110,103,117,97,103,101,100,105,115,116,97,110,99,101,114,101,109,101,109,98,\n101,114,116,114,97,99,107,105,110,103,112,97,115,115,119,111,114,100,109,111,100\n,105,102,105,101,100,115,116,117,100,101,110,116,115,100,105,114,101,99,116,108,\n121,102,105,103,104,116,105,110,103,110,111,114,116,104,101,114,110,100,97,116,\n97,98,97,115,101,102,101,115,116,105,118,97,108,98,114,101,97,107,105,110,103,\n108,111,99,97,116,105,111,110,105,110,116,101,114,110,101,116,100,114,111,112,\n100,111,119,110,112,114,97,99,116,105,99,101,101,118,105,100,101,110,99,101,102,\n117,110,99,116,105,111,110,109,97,114,114,105,97,103,101,114,101,115,112,111,110\n,115,101,112,114,111,98,108,101,109,115,110,101,103,97,116,105,118,101,112,114,\n111,103,114,97,109,115,97,110,97,108,121,115,105,115,114,101,108,101,97,115,101,\n100,98,97,110,110,101,114,34,62,112,117,114,99,104,97,115,101,112,111,108,105,99\n,105,101,115,114,101,103,105,111,110,97,108,99,114,101,97,116,105,118,101,97,114\n,103,117,109,101,110,116,98,111,111,107,109,97,114,107,114,101,102,101,114,114,\n101,114,99,104,101,109,105,99,97,108,100,105,118,105,115,105,111,110,99,97,108,\n108,98,97,99,107,115,101,112,97,114,97,116,101,112,114,111,106,101,99,116,115,99\n,111,110,102,108,105,99,116,104,97,114,100,119,97,114,101,105,110,116,101,114,\n101,115,116,100,101,108,105,118,101,114,121,109,111,117,110,116,97,105,110,111,\n98,116,97,105,110,101,100,61,32,102,97,108,115,101,59,102,111,114,40,118,97,114,\n32,97,99,99,101,112,116,101,100,99,97,112,97,99,105,116,121,99,111,109,112,117,\n116,101,114,105,100,101,110,116,105,116,121,97,105,114,99,114,97,102,116,101,109\n,112,108,111,121,101,100,112,114,111,112,111,115,101,100,100,111,109,101,115,116\n,105,99,105,110,99,108,117,100,101,115,112,114,111,118,105,100,101,100,104,111,\n115,112,105,116,97,108,118,101,114,116,105,99,97,108,99,111,108,108,97,112,115,\n101,97,112,112,114,111,97,99,104,112,97,114,116,110,101,114,115,108,111,103,111,\n34,62,60,97,100,97,117,103,104,116,101,114,97,117,116,104,111,114,34,32,99,117,\n108,116,117,114,97,108,102,97,109,105,108,105,101,115,47,105,109,97,103,101,115,\n47,97,115,115,101,109,98,108,121,112,111,119,101,114,102,117,108,116,101,97,99,\n104,105,110,103,102,105,110,105,115,104,101,100,100,105,115,116,114,105,99,116,\n99,114,105,116,105,99,97,108,99,103,105,45,98,105,110,47,112,117,114,112,111,115\n,101,115,114,101,113,117,105,114,101,115,101,108,101,99,116,105,111,110,98,101,\n99,111,109,105,110,103,112,114,111,118,105,100,101,115,97,99,97,100,101,109,105,\n99,101,120,101,114,99,105,115,101,97,99,116,117,97,108,108,121,109,101,100,105,\n99,105,110,101,99,111,110,115,116,97,110,116,97,99,99,105,100,101,110,116,77,97,\n103,97,122,105,110,101,100,111,99,117,109,101,110,116,115,116,97,114,116,105,110\n,103,98,111,116,116,111,109,34,62,111,98,115,101,114,118,101,100,58,32,38,113,\n117,111,116,59,101,120,116,101,110,100,101,100,112,114,101,118,105,111,117,115,\n83,111,102,116,119,97,114,101,99,117,115,116,111,109,101,114,100,101,99,105,115,\n105,111,110,115,116,114,101,110,103,116,104,100,101,116,97,105,108,101,100,115,\n108,105,103,104,116,108,121,112,108,97,110,110,105,110,103,116,101,120,116,97,\n114,101,97,99,117,114,114,101,110,99,121,101,118,101,114,121,111,110,101,115,116\n,114,97,105,103,104,116,116,114,97,110,115,102,101,114,112,111,115,105,116,105,\n118,101,112,114,111,100,117,99,101,100,104,101,114,105,116,97,103,101,115,104,\n105,112,112,105,110,103,97,98,115,111,108,117,116,101,114,101,99,101,105,118,101\n,100,114,101,108,101,118,97,110,116,98,117,116,116,111,110,34,32,118,105,111,108\n,101,110,99,101,97,110,121,119,104,101,114,101,98,101,110,101,102,105,116,115,\n108,97,117,110,99,104,101,100,114,101,99,101,110,116,108,121,97,108,108,105,97,\n110,99,101,102,111,108,108,111,119,101,100,109,117,108,116,105,112,108,101,98,\n117,108,108,101,116,105,110,105,110,99,108,117,100,101,100,111,99,99,117,114,114\n,101,100,105,110,116,101,114,110,97,108,36,40,116,104,105,115,41,46,114,101,112,\n117,98,108,105,99,62,60,116,114,62,60,116,100,99,111,110,103,114,101,115,115,114\n,101,99,111,114,100,101,100,117,108,116,105,109,97,116,101,115,111,108,117,116,\n105,111,110,60,117,108,32,105,100,61,34,100,105,115,99,111,118,101,114,72,111,\n109,101,60,47,97,62,119,101,98,115,105,116,101,115,110,101,116,119,111,114,107,\n115,97,108,116,104,111,117,103,104,101,110,116,105,114,101,108,121,109,101,109,\n111,114,105,97,108,109,101,115,115,97,103,101,115,99,111,110,116,105,110,117,101\n,97,99,116,105,118,101,34,62,115,111,109,101,119,104,97,116,118,105,99,116,111,\n114,105,97,87,101,115,116,101,114,110,32,32,116,105,116,108,101,61,34,76,111,99,\n97,116,105,111,110,99,111,110,116,114,97,99,116,118,105,115,105,116,111,114,115,\n68,111,119,110,108,111,97,100,119,105,116,104,111,117,116,32,114,105,103,104,116\n,34,62,10,109,101,97,115,117,114,101,115,119,105,100,116,104,32,61,32,118,97,114\n,105,97,98,108,101,105,110,118,111,108,118,101,100,118,105,114,103,105,110,105,\n97,110,111,114,109,97,108,108,121,104,97,112,112,101,110,101,100,97,99,99,111,\n117,110,116,115,115,116,97,110,100,105,110,103,110,97,116,105,111,110,97,108,82,\n101,103,105,115,116,101,114,112,114,101,112,97,114,101,100,99,111,110,116,114,\n111,108,115,97,99,99,117,114,97,116,101,98,105,114,116,104,100,97,121,115,116,\n114,97,116,101,103,121,111,102,102,105,99,105,97,108,103,114,97,112,104,105,99,\n115,99,114,105,109,105,110,97,108,112,111,115,115,105,98,108,121,99,111,110,115,\n117,109,101,114,80,101,114,115,111,110,97,108,115,112,101,97,107,105,110,103,118\n,97,108,105,100,97,116,101,97,99,104,105,101,118,101,100,46,106,112,103,34,32,47\n,62,109,97,99,104,105,110,101,115,60,47,104,50,62,10,32,32,107,101,121,119,111,\n114,100,115,102,114,105,101,110,100,108,121,98,114,111,116,104,101,114,115,99,\n111,109,98,105,110,101,100,111,114,105,103,105,110,97,108,99,111,109,112,111,115\n,101,100,101,120,112,101,99,116,101,100,97,100,101,113,117,97,116,101,112,97,107\n,105,115,116,97,110,102,111,108,108,111,119,34,32,118,97,108,117,97,98,108,101,\n60,47,108,97,98,101,108,62,114,101,108,97,116,105,118,101,98,114,105,110,103,105\n,110,103,105,110,99,114,101,97,115,101,103,111,118,101,114,110,111,114,112,108,\n117,103,105,110,115,47,76,105,115,116,32,111,102,32,72,101,97,100,101,114,34,62,\n34,32,110,97,109,101,61,34,32,40,38,113,117,111,116,59,103,114,97,100,117,97,116\n,101,60,47,104,101,97,100,62,10,99,111,109,109,101,114,99,101,109,97,108,97,121,\n115,105,97,100,105,114,101,99,116,111,114,109,97,105,110,116,97,105,110,59,104,\n101,105,103,104,116,58,115,99,104,101,100,117,108,101,99,104,97,110,103,105,110,\n103,98,97,99,107,32,116,111,32,99,97,116,104,111,108,105,99,112,97,116,116,101,\n114,110,115,99,111,108,111,114,58,32,35,103,114,101,97,116,101,115,116,115,117,\n112,112,108,105,101,115,114,101,108,105,97,98,108,101,60,47,117,108,62,10,9,9,60\n,115,101,108,101,99,116,32,99,105,116,105,122,101,110,115,99,108,111,116,104,105\n,110,103,119,97,116,99,104,105,110,103,60,108,105,32,105,100,61,34,115,112,101,\n99,105,102,105,99,99,97,114,114,121,105,110,103,115,101,110,116,101,110,99,101,\n60,99,101,110,116,101,114,62,99,111,110,116,114,97,115,116,116,104,105,110,107,\n105,110,103,99,97,116,99,104,40,101,41,115,111,117,116,104,101,114,110,77,105,99\n,104,97,101,108,32,109,101,114,99,104,97,110,116,99,97,114,111,117,115,101,108,\n112,97,100,100,105,110,103,58,105,110,116,101,114,105,111,114,46,115,112,108,105\n,116,40,34,108,105,122,97,116,105,111,110,79,99,116,111,98,101,114,32,41,123,114\n,101,116,117,114,110,105,109,112,114,111,118,101,100,45,45,38,103,116,59,10,10,\n99,111,118,101,114,97,103,101,99,104,97,105,114,109,97,110,46,112,110,103,34,32,\n47,62,115,117,98,106,101,99,116,115,82,105,99,104,97,114,100,32,119,104,97,116,\n101,118,101,114,112,114,111,98,97,98,108,121,114,101,99,111,118,101,114,121,98,\n97,115,101,98,97,108,108,106,117,100,103,109,101,110,116,99,111,110,110,101,99,\n116,46,46,99,115,115,34,32,47,62,32,119,101,98,115,105,116,101,114,101,112,111,\n114,116,101,100,100,101,102,97,117,108,116,34,47,62,60,47,97,62,13,10,101,108,\n101,99,116,114,105,99,115,99,111,116,108,97,110,100,99,114,101,97,116,105,111,\n110,113,117,97,110,116,105,116,121,46,32,73,83,66,78,32,48,100,105,100,32,110,\n111,116,32,105,110,115,116,97,110,99,101,45,115,101,97,114,99,104,45,34,32,108,\n97,110,103,61,34,115,112,101,97,107,101,114,115,67,111,109,112,117,116,101,114,\n99,111,110,116,97,105,110,115,97,114,99,104,105,118,101,115,109,105,110,105,115,\n116,101,114,114,101,97,99,116,105,111,110,100,105,115,99,111,117,110,116,73,116,\n97,108,105,97,110,111,99,114,105,116,101,114,105,97,115,116,114,111,110,103,108,\n121,58,32,39,104,116,116,112,58,39,115,99,114,105,112,116,39,99,111,118,101,114,\n105,110,103,111,102,102,101,114,105,110,103,97,112,112,101,97,114,101,100,66,114\n,105,116,105,115,104,32,105,100,101,110,116,105,102,121,70,97,99,101,98,111,111,\n107,110,117,109,101,114,111,117,115,118,101,104,105,99,108,101,115,99,111,110,99\n,101,114,110,115,65,109,101,114,105,99,97,110,104,97,110,100,108,105,110,103,100\n,105,118,32,105,100,61,34,87,105,108,108,105,97,109,32,112,114,111,118,105,100,\n101,114,95,99,111,110,116,101,110,116,97,99,99,117,114,97,99,121,115,101,99,116,\n105,111,110,32,97,110,100,101,114,115,111,110,102,108,101,120,105,98,108,101,67,\n97,116,101,103,111,114,121,108,97,119,114,101,110,99,101,60,115,99,114,105,112,\n116,62,108,97,121,111,117,116,61,34,97,112,112,114,111,118,101,100,32,109,97,120\n,105,109,117,109,104,101,97,100,101,114,34,62,60,47,116,97,98,108,101,62,83,101,\n114,118,105,99,101,115,104,97,109,105,108,116,111,110,99,117,114,114,101,110,116\n,32,99,97,110,97,100,105,97,110,99,104,97,110,110,101,108,115,47,116,104,101,109\n,101,115,47,47,97,114,116,105,99,108,101,111,112,116,105,111,110,97,108,112,111,\n114,116,117,103,97,108,118,97,108,117,101,61,34,34,105,110,116,101,114,118,97,\n108,119,105,114,101,108,101,115,115,101,110,116,105,116,108,101,100,97,103,101,\n110,99,105,101,115,83,101,97,114,99,104,34,32,109,101,97,115,117,114,101,100,116\n,104,111,117,115,97,110,100,115,112,101,110,100,105,110,103,38,104,101,108,108,\n105,112,59,110,101,119,32,68,97,116,101,34,32,115,105,122,101,61,34,112,97,103,\n101,78,97,109,101,109,105,100,100,108,101,34,32,34,32,47,62,60,47,97,62,104,105,\n100,100,101,110,34,62,115,101,113,117,101,110,99,101,112,101,114,115,111,110,97,\n108,111,118,101,114,102,108,111,119,111,112,105,110,105,111,110,115,105,108,108,\n105,110,111,105,115,108,105,110,107,115,34,62,10,9,60,116,105,116,108,101,62,118\n,101,114,115,105,111,110,115,115,97,116,117,114,100,97,121,116,101,114,109,105,\n110,97,108,105,116,101,109,112,114,111,112,101,110,103,105,110,101,101,114,115,\n101,99,116,105,111,110,115,100,101,115,105,103,110,101,114,112,114,111,112,111,\n115,97,108,61,34,102,97,108,115,101,34,69,115,112,97,195,177,111,108,114,101,108\n,101,97,115,101,115,115,117,98,109,105,116,34,32,101,114,38,113,117,111,116,59,\n97,100,100,105,116,105,111,110,115,121,109,112,116,111,109,115,111,114,105,101,\n110,116,101,100,114,101,115,111,117,114,99,101,114,105,103,104,116,34,62,60,112,\n108,101,97,115,117,114,101,115,116,97,116,105,111,110,115,104,105,115,116,111,\n114,121,46,108,101,97,118,105,110,103,32,32,98,111,114,100,101,114,61,99,111,110\n,116,101,110,116,115,99,101,110,116,101,114,34,62,46,10,10,83,111,109,101,32,100\n,105,114,101,99,116,101,100,115,117,105,116,97,98,108,101,98,117,108,103,97,114,\n105,97,46,115,104,111,119,40,41,59,100,101,115,105,103,110,101,100,71,101,110,\n101,114,97,108,32,99,111,110,99,101,112,116,115,69,120,97,109,112,108,101,115,\n119,105,108,108,105,97,109,115,79,114,105,103,105,110,97,108,34,62,60,115,112,97\n,110,62,115,101,97,114,99,104,34,62,111,112,101,114,97,116,111,114,114,101,113,\n117,101,115,116,115,97,32,38,113,117,111,116,59,97,108,108,111,119,105,110,103,\n68,111,99,117,109,101,110,116,114,101,118,105,115,105,111,110,46,32,10,10,84,104\n,101,32,121,111,117,114,115,101,108,102,67,111,110,116,97,99,116,32,109,105,99,\n104,105,103,97,110,69,110,103,108,105,115,104,32,99,111,108,117,109,98,105,97,\n112,114,105,111,114,105,116,121,112,114,105,110,116,105,110,103,100,114,105,110,\n107,105,110,103,102,97,99,105,108,105,116,121,114,101,116,117,114,110,101,100,67\n,111,110,116,101,110,116,32,111,102,102,105,99,101,114,115,82,117,115,115,105,97\n,110,32,103,101,110,101,114,97,116,101,45,56,56,53,57,45,49,34,105,110,100,105,\n99,97,116,101,102,97,109,105,108,105,97,114,32,113,117,97,108,105,116,121,109,97\n,114,103,105,110,58,48,32,99,111,110,116,101,110,116,118,105,101,119,112,111,114\n,116,99,111,110,116,97,99,116,115,45,116,105,116,108,101,34,62,112,111,114,116,\n97,98,108,101,46,108,101,110,103,116,104,32,101,108,105,103,105,98,108,101,105,\n110,118,111,108,118,101,115,97,116,108,97,110,116,105,99,111,110,108,111,97,100,\n61,34,100,101,102,97,117,108,116,46,115,117,112,112,108,105,101,100,112,97,121,\n109,101,110,116,115,103,108,111,115,115,97,114,121,10,10,65,102,116,101,114,32,\n103,117,105,100,97,110,99,101,60,47,116,100,62,60,116,100,101,110,99,111,100,105\n,110,103,109,105,100,100,108,101,34,62,99,97,109,101,32,116,111,32,100,105,115,\n112,108,97,121,115,115,99,111,116,116,105,115,104,106,111,110,97,116,104,97,110,\n109,97,106,111,114,105,116,121,119,105,100,103,101,116,115,46,99,108,105,110,105\n,99,97,108,116,104,97,105,108,97,110,100,116,101,97,99,104,101,114,115,60,104,\n101,97,100,62,10,9,97,102,102,101,99,116,101,100,115,117,112,112,111,114,116,115\n,112,111,105,110,116,101,114,59,116,111,83,116,114,105,110,103,60,47,115,109,97,\n108,108,62,111,107,108,97,104,111,109,97,119,105,108,108,32,98,101,32,105,110,\n118,101,115,116,111,114,48,34,32,97,108,116,61,34,104,111,108,105,100,97,121,115\n,82,101,115,111,117,114,99,101,108,105,99,101,110,115,101,100,32,40,119,104,105,\n99,104,32,46,32,65,102,116,101,114,32,99,111,110,115,105,100,101,114,118,105,115\n,105,116,105,110,103,101,120,112,108,111,114,101,114,112,114,105,109,97,114,121,\n32,115,101,97,114,99,104,34,32,97,110,100,114,111,105,100,34,113,117,105,99,107,\n108,121,32,109,101,101,116,105,110,103,115,101,115,116,105,109,97,116,101,59,114\n,101,116,117,114,110,32,59,99,111,108,111,114,58,35,32,104,101,105,103,104,116,\n61,97,112,112,114,111,118,97,108,44,32,38,113,117,111,116,59,32,99,104,101,99,\n107,101,100,46,109,105,110,46,106,115,34,109,97,103,110,101,116,105,99,62,60,47,\n97,62,60,47,104,102,111,114,101,99,97,115,116,46,32,87,104,105,108,101,32,116,\n104,117,114,115,100,97,121,100,118,101,114,116,105,115,101,38,101,97,99,117,116,\n101,59,104,97,115,67,108,97,115,115,101,118,97,108,117,97,116,101,111,114,100,\n101,114,105,110,103,101,120,105,115,116,105,110,103,112,97,116,105,101,110,116,\n115,32,79,110,108,105,110,101,32,99,111,108,111,114,97,100,111,79,112,116,105,\n111,110,115,34,99,97,109,112,98,101,108,108,60,33,45,45,32,101,110,100,60,47,115\n,112,97,110,62,60,60,98,114,32,47,62,13,10,95,112,111,112,117,112,115,124,115,99\n,105,101,110,99,101,115,44,38,113,117,111,116,59,32,113,117,97,108,105,116,121,\n32,87,105,110,100,111,119,115,32,97,115,115,105,103,110,101,100,104,101,105,103,\n104,116,58,32,60,98,32,99,108,97,115,115,108,101,38,113,117,111,116,59,32,118,97\n,108,117,101,61,34,32,67,111,109,112,97,110,121,101,120,97,109,112,108,101,115,\n60,105,102,114,97,109,101,32,98,101,108,105,101,118,101,115,112,114,101,115,101,\n110,116,115,109,97,114,115,104,97,108,108,112,97,114,116,32,111,102,32,112,114,\n111,112,101,114,108,121,41,46,10,10,84,104,101,32,116,97,120,111,110,111,109,121\n,109,117,99,104,32,111,102,32,60,47,115,112,97,110,62,10,34,32,100,97,116,97,45,\n115,114,116,117,103,117,195,170,115,115,99,114,111,108,108,84,111,32,112,114,111\n,106,101,99,116,60,104,101,97,100,62,13,10,97,116,116,111,114,110,101,121,101,\n109,112,104,97,115,105,115,115,112,111,110,115,111,114,115,102,97,110,99,121,98,\n111,120,119,111,114,108,100,39,115,32,119,105,108,100,108,105,102,101,99,104,101\n,99,107,101,100,61,115,101,115,115,105,111,110,115,112,114,111,103,114,97,109,\n109,112,120,59,102,111,110,116,45,32,80,114,111,106,101,99,116,106,111,117,114,\n110,97,108,115,98,101,108,105,101,118,101,100,118,97,99,97,116,105,111,110,116,\n104,111,109,112,115,111,110,108,105,103,104,116,105,110,103,97,110,100,32,116,\n104,101,32,115,112,101,99,105,97,108,32,98,111,114,100,101,114,61,48,99,104,101,\n99,107,105,110,103,60,47,116,98,111,100,121,62,60,98,117,116,116,111,110,32,67,\n111,109,112,108,101,116,101,99,108,101,97,114,102,105,120,10,60,104,101,97,100,\n62,10,97,114,116,105,99,108,101,32,60,115,101,99,116,105,111,110,102,105,110,100\n,105,110,103,115,114,111,108,101,32,105,110,32,112,111,112,117,108,97,114,32,32,\n79,99,116,111,98,101,114,119,101,98,115,105,116,101,32,101,120,112,111,115,117,\n114,101,117,115,101,100,32,116,111,32,32,99,104,97,110,103,101,115,111,112,101,\n114,97,116,101,100,99,108,105,99,107,105,110,103,101,110,116,101,114,105,110,103\n,99,111,109,109,97,110,100,115,105,110,102,111,114,109,101,100,32,110,117,109,98\n,101,114,115,32,32,60,47,100,105,118,62,99,114,101,97,116,105,110,103,111,110,83\n,117,98,109,105,116,109,97,114,121,108,97,110,100,99,111,108,108,101,103,101,115\n,97,110,97,108,121,116,105,99,108,105,115,116,105,110,103,115,99,111,110,116,97,\n99,116,46,108,111,103,103,101,100,73,110,97,100,118,105,115,111,114,121,115,105,\n98,108,105,110,103,115,99,111,110,116,101,110,116,34,115,38,113,117,111,116,59,\n41,115,46,32,84,104,105,115,32,112,97,99,107,97,103,101,115,99,104,101,99,107,98\n,111,120,115,117,103,103,101,115,116,115,112,114,101,103,110,97,110,116,116,111,\n109,111,114,114,111,119,115,112,97,99,105,110,103,61,105,99,111,110,46,112,110,\n103,106,97,112,97,110,101,115,101,99,111,100,101,98,97,115,101,98,117,116,116,\n111,110,34,62,103,97,109,98,108,105,110,103,115,117,99,104,32,97,115,32,44,32,\n119,104,105,108,101,32,60,47,115,112,97,110,62,32,109,105,115,115,111,117,114,\n105,115,112,111,114,116,105,110,103,116,111,112,58,49,112,120,32,46,60,47,115,\n112,97,110,62,116,101,110,115,105,111,110,115,119,105,100,116,104,61,34,50,108,\n97,122,121,108,111,97,100,110,111,118,101,109,98,101,114,117,115,101,100,32,105,\n110,32,104,101,105,103,104,116,61,34,99,114,105,112,116,34,62,10,38,110,98,115,\n112,59,60,47,60,116,114,62,60,116,100,32,104,101,105,103,104,116,58,50,47,112,\n114,111,100,117,99,116,99,111,117,110,116,114,121,32,105,110,99,108,117,100,101,\n32,102,111,111,116,101,114,34,32,38,108,116,59,33,45,45,32,116,105,116,108,101,\n34,62,60,47,106,113,117,101,114,121,46,60,47,102,111,114,109,62,10,40,231,174,\n128,228,189,147,41,40,231,185,129,233,171,148,41,104,114,118,97,116,115,107,105,\n105,116,97,108,105,97,110,111,114,111,109,195,162,110,196,131,116,195,188,114,\n107,195,167,101,216,167,216,177,216,175,217,136,116,97,109,98,105,195,169,110,\n110,111,116,105,99,105,97,115,109,101,110,115,97,106,101,115,112,101,114,115,111\n,110,97,115,100,101,114,101,99,104,111,115,110,97,99,105,111,110,97,108,115,101,\n114,118,105,99,105,111,99,111,110,116,97,99,116,111,117,115,117,97,114,105,111,\n115,112,114,111,103,114,97,109,97,103,111,98,105,101,114,110,111,101,109,112,114\n,101,115,97,115,97,110,117,110,99,105,111,115,118,97,108,101,110,99,105,97,99,\n111,108,111,109,98,105,97,100,101,115,112,117,195,169,115,100,101,112,111,114,\n116,101,115,112,114,111,121,101,99,116,111,112,114,111,100,117,99,116,111,112,\n195,186,98,108,105,99,111,110,111,115,111,116,114,111,115,104,105,115,116,111,\n114,105,97,112,114,101,115,101,110,116,101,109,105,108,108,111,110,101,115,109,\n101,100,105,97,110,116,101,112,114,101,103,117,110,116,97,97,110,116,101,114,105\n,111,114,114,101,99,117,114,115,111,115,112,114,111,98,108,101,109,97,115,97,110\n,116,105,97,103,111,110,117,101,115,116,114,111,115,111,112,105,110,105,195,179,\n110,105,109,112,114,105,109,105,114,109,105,101,110,116,114,97,115,97,109,195,\n169,114,105,99,97,118,101,110,100,101,100,111,114,115,111,99,105,101,100,97,100,\n114,101,115,112,101,99,116,111,114,101,97,108,105,122,97,114,114,101,103,105,115\n,116,114,111,112,97,108,97,98,114,97,115,105,110,116,101,114,195,169,115,101,110\n,116,111,110,99,101,115,101,115,112,101,99,105,97,108,109,105,101,109,98,114,111\n,115,114,101,97,108,105,100,97,100,99,195,179,114,100,111,98,97,122,97,114,97,\n103,111,122,97,112,195,161,103,105,110,97,115,115,111,99,105,97,108,101,115,98,\n108,111,113,117,101,97,114,103,101,115,116,105,195,179,110,97,108,113,117,105,\n108,101,114,115,105,115,116,101,109,97,115,99,105,101,110,99,105,97,115,99,111,\n109,112,108,101,116,111,118,101,114,115,105,195,179,110,99,111,109,112,108,101,\n116,97,101,115,116,117,100,105,111,115,112,195,186,98,108,105,99,97,111,98,106,\n101,116,105,118,111,97,108,105,99,97,110,116,101,98,117,115,99,97,100,111,114,99\n,97,110,116,105,100,97,100,101,110,116,114,97,100,97,115,97,99,99,105,111,110,\n101,115,97,114,99,104,105,118,111,115,115,117,112,101,114,105,111,114,109,97,121\n,111,114,195,173,97,97,108,101,109,97,110,105,97,102,117,110,99,105,195,179,110,\n195,186,108,116,105,109,111,115,104,97,99,105,101,110,100,111,97,113,117,101,108\n,108,111,115,101,100,105,99,105,195,179,110,102,101,114,110,97,110,100,111,97,\n109,98,105,101,110,116,101,102,97,99,101,98,111,111,107,110,117,101,115,116,114,\n97,115,99,108,105,101,110,116,101,115,112,114,111,99,101,115,111,115,98,97,115,\n116,97,110,116,101,112,114,101,115,101,110,116,97,114,101,112,111,114,116,97,114\n,99,111,110,103,114,101,115,111,112,117,98,108,105,99,97,114,99,111,109,101,114,\n99,105,111,99,111,110,116,114,97,116,111,106,195,179,118,101,110,101,115,100,105\n,115,116,114,105,116,111,116,195,169,99,110,105,99,97,99,111,110,106,117,110,116\n,111,101,110,101,114,103,195,173,97,116,114,97,98,97,106,97,114,97,115,116,117,\n114,105,97,115,114,101,99,105,101,110,116,101,117,116,105,108,105,122,97,114,98,\n111,108,101,116,195,173,110,115,97,108,118,97,100,111,114,99,111,114,114,101,99,\n116,97,116,114,97,98,97,106,111,115,112,114,105,109,101,114,111,115,110,101,103,\n111,99,105,111,115,108,105,98,101,114,116,97,100,100,101,116,97,108,108,101,115,\n112,97,110,116,97,108,108,97,112,114,195,179,120,105,109,111,97,108,109,101,114,\n195,173,97,97,110,105,109,97,108,101,115,113,117,105,195,169,110,101,115,99,111,\n114,97,122,195,179,110,115,101,99,99,105,195,179,110,98,117,115,99,97,110,100,\n111,111,112,99,105,111,110,101,115,101,120,116,101,114,105,111,114,99,111,110,99\n,101,112,116,111,116,111,100,97,118,195,173,97,103,97,108,101,114,195,173,97,101\n,115,99,114,105,98,105,114,109,101,100,105,99,105,110,97,108,105,99,101,110,99,\n105,97,99,111,110,115,117,108,116,97,97,115,112,101,99,116,111,115,99,114,195,\n173,116,105,99,97,100,195,179,108,97,114,101,115,106,117,115,116,105,99,105,97,\n100,101,98,101,114,195,161,110,112,101,114,195,173,111,100,111,110,101,99,101,\n115,105,116,97,109,97,110,116,101,110,101,114,112,101,113,117,101,195,177,111,\n114,101,99,105,98,105,100,97,116,114,105,98,117,110,97,108,116,101,110,101,114,\n105,102,101,99,97,110,99,105,195,179,110,99,97,110,97,114,105,97,115,100,101,115\n,99,97,114,103,97,100,105,118,101,114,115,111,115,109,97,108,108,111,114,99,97,\n114,101,113,117,105,101,114,101,116,195,169,99,110,105,99,111,100,101,98,101,114\n,195,173,97,118,105,118,105,101,110,100,97,102,105,110,97,110,122,97,115,97,100,\n101,108,97,110,116,101,102,117,110,99,105,111,110,97,99,111,110,115,101,106,111,\n115,100,105,102,195,173,99,105,108,99,105,117,100,97,100,101,115,97,110,116,105,\n103,117,97,115,97,118,97,110,122,97,100,97,116,195,169,114,109,105,110,111,117,\n110,105,100,97,100,101,115,115,195,161,110,99,104,101,122,99,97,109,112,97,195,\n177,97,115,111,102,116,111,110,105,99,114,101,118,105,115,116,97,115,99,111,110,\n116,105,101,110,101,115,101,99,116,111,114,101,115,109,111,109,101,110,116,111,\n115,102,97,99,117,108,116,97,100,99,114,195,169,100,105,116,111,100,105,118,101,\n114,115,97,115,115,117,112,117,101,115,116,111,102,97,99,116,111,114,101,115,115\n,101,103,117,110,100,111,115,112,101,113,117,101,195,177,97,208,179,208,190,208,\n180,208,176,208,181,209,129,208,187,208,184,208,181,209,129,209,130,209,140,208,\n177,209,139,208,187,208,190,208,177,209,139,209,130,209,140,209,141,209,130,208,\n190,208,188,208,149,209,129,208,187,208,184,209,130,208,190,208,179,208,190,208,\n188,208,181,208,189,209,143,208,178,209,129,208,181,209,133,209,141,209,130,208,\n190,208,185,208,180,208,176,208,182,208,181,208,177,209,139,208,187,208,184,208,\n179,208,190,208,180,209,131,208,180,208,181,208,189,209,140,209,141,209,130,208,\n190,209,130,208,177,209,139,208,187,208,176,209,129,208,181,208,177,209,143,208,\n190,208,180,208,184,208,189,209,129,208,181,208,177,208,181,208,189,208,176,208,\n180,208,190,209,129,208,176,208,185,209,130,209,132,208,190,209,130,208,190,208,\n189,208,181,208,179,208,190,209,129,208,178,208,190,208,184,209,129,208,178,208,\n190,208,185,208,184,208,179,209,128,209,139,209,130,208,190,208,182,208,181,208,\n178,209,129,208,181,208,188,209,129,208,178,208,190,209,142,208,187,208,184,209,\n136,209,140,209,141,209,130,208,184,209,133,208,191,208,190,208,186,208,176,208,\n180,208,189,208,181,208,185,208,180,208,190,208,188,208,176,208,188,208,184,209,\n128,208,176,208,187,208,184,208,177,208,190,209,130,208,181,208,188,209,131,209,\n133,208,190,209,130,209,143,208,180,208,178,209,131,209,133,209,129,208,181,209,\n130,208,184,208,187,209,142,208,180,208,184,208,180,208,181,208,187,208,190,208,\n188,208,184,209,128,208,181,209,130,208,181,208,177,209,143,209,129,208,178,208,\n190,208,181,208,178,208,184,208,180,208,181,209,135,208,181,208,179,208,190,209,\n141,209,130,208,184,208,188,209,129,209,135,208,181,209,130,209,130,208,181,208,\n188,209,139,209,134,208,181,208,189,209,139,209,129,209,130,208,176,208,187,208,\n178,208,181,208,180,209,140,209,130,208,181,208,188,208,181,208,178,208,190,208,\n180,209,139,209,130,208,181,208,177,208,181,208,178,209,139,209,136,208,181,208,\n189,208,176,208,188,208,184,209,130,208,184,208,191,208,176,209,130,208,190,208,\n188,209,131,208,191,209,128,208,176,208,178,208,187,208,184,209,134,208,176,208,\n190,208,180,208,189,208,176,208,179,208,190,208,180,209,139,208,183,208,189,208,\n176,209,142,208,188,208,190,208,179,209,131,208,180,209,128,209,131,208,179,208,\n178,209,129,208,181,208,185,208,184,208,180,208,181,209,130,208,186,208,184,208,\n189,208,190,208,190,208,180,208,189,208,190,208,180,208,181,208,187,208,176,208,\n180,208,181,208,187,208,181,209,129,209,128,208,190,208,186,208,184,209,142,208,\n189,209,143,208,178,208,181,209,129,209,140,208,149,209,129,209,130,209,140,209,\n128,208,176,208,183,208,176,208,189,208,176,209,136,208,184,216,167,217,132,217,\n132,217,135,216,167,217,132,216,170,217,138,216,172,217,133,217,138,216,185,216,\n174,216,167,216,181,216,169,216,167,217,132,216,176,217,138,216,185,217,132,217,\n138,217,135,216,172,216,175,217,138,216,175,216,167,217,132,216,162,217,134,216,\n167,217,132,216,177,216,175,216,170,216,173,217,131,217,133,216,181,217,129,216,\n173,216,169,217,131,216,167,217,134,216,170,216,167,217,132,217,132,217,138,217,\n138,217,131,217,136,217,134,216,180,216,168,217,131,216,169,217,129,217,138,217,\n135,216,167,216,168,217,134,216,167,216,170,216,173,217,136,216,167,216,161,216,\n163,217,131,216,171,216,177,216,174,217,132,216,167,217,132,216,167,217,132,216,\n173,216,168,216,175,217,132,217,138,217,132,216,175,216,177,217,136,216,179,216,\n167,216,182,216,186,216,183,216,170,217,131,217,136,217,134,217,135,217,134,216,\n167,217,131,216,179,216,167,216,173,216,169,217,134,216,167,216,175,217,138,216,\n167,217,132,216,183,216,168,216,185,217,132,217,138,217,131,216,180,217,131,216,\n177,216,167,217,138,217,133,217,131,217,134,217,133,217,134,217,135,216,167,216,\n180,216,177,217,131,216,169,216,177,216,166,217,138,216,179,217,134,216,180,217,\n138,216,183,217,133,216,167,216,176,216,167,216,167,217,132,217,129,217,134,216,\n180,216,168,216,167,216,168,216,170,216,185,216,168,216,177,216,177,216,173,217,\n133,216,169,217,131,216,167,217,129,216,169,217,138,217,130,217,136,217,132,217,\n133,216,177,217,131,216,178,217,131,217,132,217,133,216,169,216,163,216,173,217,\n133,216,175,217,130,217,132,216,168,217,138,217,138,216,185,217,134,217,138,216,\n181,217,136,216,177,216,169,216,183,216,177,217,138,217,130,216,180,216,167,216,\n177,217,131,216,172,217,136,216,167,217,132,216,163,216,174,216,177,217,137,217,\n133,216,185,217,134,216,167,216,167,216,168,216,173,216,171,216,185,216,177,217,\n136,216,182,216,168,216,180,217,131,217,132,217,133,216,179,216,172,217,132,216,\n168,217,134,216,167,217,134,216,174,216,167,217,132,216,175,217,131,216,170,216,\n167,216,168,217,131,217,132,217,138,216,169,216,168,216,175,217,136,217,134,216,\n163,217,138,216,182,216,167,217,138,217,136,216,172,216,175,217,129,216,177,217,\n138,217,130,217,131,216,170,216,168,216,170,216,163,217,129,216,182,217,132,217,\n133,216,183,216,168,216,174,216,167,217,131,216,171,216,177,216,168,216,167,216,\n177,217,131,216,167,217,129,216,182,217,132,216,167,216,173,217,132,217,137,217,\n134,217,129,216,179,217,135,216,163,217,138,216,167,217,133,216,177,216,175,217,\n136,216,175,216,163,217,134,217,135,216,167,216,175,217,138,217,134,216,167,216,\n167,217,132,216,167,217,134,217,133,216,185,216,177,216,182,216,170,216,185,217,\n132,217,133,216,175,216,167,216,174,217,132,217,133,217,133,217,131,217,134,0,0,\n0,0,0,0,0,0,1,0,1,0,1,0,1,0,2,0,2,0,2,0,2,0,4,0,4,0,4,0,4,0,0,1,2,3,4,5,6,7,7,6,\n5,4,3,2,1,0,8,9,10,11,12,13,14,15,15,14,13,12,11,10,9,8,16,17,18,19,20,21,22,23,\n23,22,21,20,19,18,17,16,24,25,26,27,28,29,30,31,31,30,29,28,27,26,25,24,255,255,\n255,255,0,0,0,0,0,0,0,0,255,255,255,255,1,0,0,0,2,0,0,0,2,0,0,0,1,0,0,0,1,0,0,0,\n3,0,0,0,255,255,0,1,0,0,0,1,0,0,255,255,0,1,0,0,0,8,0,8,0,8,0,8,0,0,0,1,0,2,0,3,\n0,4,0,5,0,6,0,7,114,101,115,111,117,114,99,101,115,99,111,117,110,116,114,105,\n101,115,113,117,101,115,116,105,111,110,115,101,113,117,105,112,109,101,110,116,\n99,111,109,109,117,110,105,116,121,97,118,97,105,108,97,98,108,101,104,105,103,\n104,108,105,103,104,116,68,84,68,47,120,104,116,109,108,109,97,114,107,101,116,\n105,110,103,107,110,111,119,108,101,100,103,101,115,111,109,101,116,104,105,110,\n103,99,111,110,116,97,105,110,101,114,100,105,114,101,99,116,105,111,110,115,117\n,98,115,99,114,105,98,101,97,100,118,101,114,116,105,115,101,99,104,97,114,97,99\n,116,101,114,34,32,118,97,108,117,101,61,34,60,47,115,101,108,101,99,116,62,65,\n117,115,116,114,97,108,105,97,34,32,99,108,97,115,115,61,34,115,105,116,117,97,\n116,105,111,110,97,117,116,104,111,114,105,116,121,102,111,108,108,111,119,105,\n110,103,112,114,105,109,97,114,105,108,121,111,112,101,114,97,116,105,111,110,99\n,104,97,108,108,101,110,103,101,100,101,118,101,108,111,112,101,100,97,110,111,\n110,121,109,111,117,115,102,117,110,99,116,105,111,110,32,102,117,110,99,116,105\n,111,110,115,99,111,109,112,97,110,105,101,115,115,116,114,117,99,116,117,114,\n101,97,103,114,101,101,109,101,110,116,34,32,116,105,116,108,101,61,34,112,111,\n116,101,110,116,105,97,108,101,100,117,99,97,116,105,111,110,97,114,103,117,109,\n101,110,116,115,115,101,99,111,110,100,97,114,121,99,111,112,121,114,105,103,104\n,116,108,97,110,103,117,97,103,101,115,101,120,99,108,117,115,105,118,101,99,111\n,110,100,105,116,105,111,110,60,47,102,111,114,109,62,13,10,115,116,97,116,101,\n109,101,110,116,97,116,116,101,110,116,105,111,110,66,105,111,103,114,97,112,104\n,121,125,32,101,108,115,101,32,123,10,115,111,108,117,116,105,111,110,115,119,\n104,101,110,32,116,104,101,32,65,110,97,108,121,116,105,99,115,116,101,109,112,\n108,97,116,101,115,100,97,110,103,101,114,111,117,115,115,97,116,101,108,108,105\n,116,101,100,111,99,117,109,101,110,116,115,112,117,98,108,105,115,104,101,114,\n105,109,112,111,114,116,97,110,116,112,114,111,116,111,116,121,112,101,105,110,\n102,108,117,101,110,99,101,38,114,97,113,117,111,59,60,47,101,102,102,101,99,116\n,105,118,101,103,101,110,101,114,97,108,108,121,116,114,97,110,115,102,111,114,\n109,98,101,97,117,116,105,102,117,108,116,114,97,110,115,112,111,114,116,111,114\n,103,97,110,105,122,101,100,112,117,98,108,105,115,104,101,100,112,114,111,109,\n105,110,101,110,116,117,110,116,105,108,32,116,104,101,116,104,117,109,98,110,97\n,105,108,78,97,116,105,111,110,97,108,32,46,102,111,99,117,115,40,41,59,111,118,\n101,114,32,116,104,101,32,109,105,103,114,97,116,105,111,110,97,110,110,111,117,\n110,99,101,100,102,111,111,116,101,114,34,62,10,101,120,99,101,112,116,105,111,\n110,108,101,115,115,32,116,104,97,110,101,120,112,101,110,115,105,118,101,102,\n111,114,109,97,116,105,111,110,102,114,97,109,101,119,111,114,107,116,101,114,\n114,105,116,111,114,121,110,100,105,99,97,116,105,111,110,99,117,114,114,101,110\n,116,108,121,99,108,97,115,115,78,97,109,101,99,114,105,116,105,99,105,115,109,\n116,114,97,100,105,116,105,111,110,101,108,115,101,119,104,101,114,101,65,108,\n101,120,97,110,100,101,114,97,112,112,111,105,110,116,101,100,109,97,116,101,114\n,105,97,108,115,98,114,111,97,100,99,97,115,116,109,101,110,116,105,111,110,101,\n100,97,102,102,105,108,105,97,116,101,60,47,111,112,116,105,111,110,62,116,114,\n101,97,116,109,101,110,116,100,105,102,102,101,114,101,110,116,47,100,101,102,97\n,117,108,116,46,80,114,101,115,105,100,101,110,116,111,110,99,108,105,99,107,61,\n34,98,105,111,103,114,97,112,104,121,111,116,104,101,114,119,105,115,101,112,101\n,114,109,97,110,101,110,116,70,114,97,110,195,167,97,105,115,72,111,108,108,121,\n119,111,111,100,101,120,112,97,110,115,105,111,110,115,116,97,110,100,97,114,100\n,115,60,47,115,116,121,108,101,62,10,114,101,100,117,99,116,105,111,110,68,101,\n99,101,109,98,101,114,32,112,114,101,102,101,114,114,101,100,67,97,109,98,114,\n105,100,103,101,111,112,112,111,110,101,110,116,115,66,117,115,105,110,101,115,\n115,32,99,111,110,102,117,115,105,111,110,62,10,60,116,105,116,108,101,62,112,\n114,101,115,101,110,116,101,100,101,120,112,108,97,105,110,101,100,100,111,101,\n115,32,110,111,116,32,119,111,114,108,100,119,105,100,101,105,110,116,101,114,\n102,97,99,101,112,111,115,105,116,105,111,110,115,110,101,119,115,112,97,112,101\n,114,60,47,116,97,98,108,101,62,10,109,111,117,110,116,97,105,110,115,108,105,\n107,101,32,116,104,101,32,101,115,115,101,110,116,105,97,108,102,105,110,97,110,\n99,105,97,108,115,101,108,101,99,116,105,111,110,97,99,116,105,111,110,61,34,47,\n97,98,97,110,100,111,110,101,100,69,100,117,99,97,116,105,111,110,112,97,114,115\n,101,73,110,116,40,115,116,97,98,105,108,105,116,121,117,110,97,98,108,101,32,\n116,111,60,47,116,105,116,108,101,62,10,114,101,108,97,116,105,111,110,115,78,\n111,116,101,32,116,104,97,116,101,102,102,105,99,105,101,110,116,112,101,114,102\n,111,114,109,101,100,116,119,111,32,121,101,97,114,115,83,105,110,99,101,32,116,\n104,101,116,104,101,114,101,102,111,114,101,119,114,97,112,112,101,114,34,62,97,\n108,116,101,114,110,97,116,101,105,110,99,114,101,97,115,101,100,66,97,116,116,\n108,101,32,111,102,112,101,114,99,101,105,118,101,100,116,114,121,105,110,103,32\n,116,111,110,101,99,101,115,115,97,114,121,112,111,114,116,114,97,121,101,100,\n101,108,101,99,116,105,111,110,115,69,108,105,122,97,98,101,116,104,60,47,105,\n102,114,97,109,101,62,100,105,115,99,111,118,101,114,121,105,110,115,117,114,97,\n110,99,101,115,46,108,101,110,103,116,104,59,108,101,103,101,110,100,97,114,121,\n71,101,111,103,114,97,112,104,121,99,97,110,100,105,100,97,116,101,99,111,114,\n112,111,114,97,116,101,115,111,109,101,116,105,109,101,115,115,101,114,118,105,\n99,101,115,46,105,110,104,101,114,105,116,101,100,60,47,115,116,114,111,110,103,\n62,67,111,109,109,117,110,105,116,121,114,101,108,105,103,105,111,117,115,108,\n111,99,97,116,105,111,110,115,67,111,109,109,105,116,116,101,101,98,117,105,108,\n100,105,110,103,115,116,104,101,32,119,111,114,108,100,110,111,32,108,111,110,\n103,101,114,98,101,103,105,110,110,105,110,103,114,101,102,101,114,101,110,99,\n101,99,97,110,110,111,116,32,98,101,102,114,101,113,117,101,110,99,121,116,121,\n112,105,99,97,108,108,121,105,110,116,111,32,116,104,101,32,114,101,108,97,116,\n105,118,101,59,114,101,99,111,114,100,105,110,103,112,114,101,115,105,100,101,\n110,116,105,110,105,116,105,97,108,108,121,116,101,99,104,110,105,113,117,101,\n116,104,101,32,111,116,104,101,114,105,116,32,99,97,110,32,98,101,101,120,105,\n115,116,101,110,99,101,117,110,100,101,114,108,105,110,101,116,104,105,115,32,\n116,105,109,101,116,101,108,101,112,104,111,110,101,105,116,101,109,115,99,111,\n112,101,112,114,97,99,116,105,99,101,115,97,100,118,97,110,116,97,103,101,41,59,\n114,101,116,117,114,110,32,70,111,114,32,111,116,104,101,114,112,114,111,118,105\n,100,105,110,103,100,101,109,111,99,114,97,99,121,98,111,116,104,32,116,104,101,\n32,101,120,116,101,110,115,105,118,101,115,117,102,102,101,114,105,110,103,115,\n117,112,112,111,114,116,101,100,99,111,109,112,117,116,101,114,115,32,102,117,\n110,99,116,105,111,110,112,114,97,99,116,105,99,97,108,115,97,105,100,32,116,104\n,97,116,105,116,32,109,97,121,32,98,101,69,110,103,108,105,115,104,60,47,102,114\n,111,109,32,116,104,101,32,115,99,104,101,100,117,108,101,100,100,111,119,110,\n108,111,97,100,115,60,47,108,97,98,101,108,62,10,115,117,115,112,101,99,116,101,\n100,109,97,114,103,105,110,58,32,48,115,112,105,114,105,116,117,97,108,60,47,104\n,101,97,100,62,10,10,109,105,99,114,111,115,111,102,116,103,114,97,100,117,97,\n108,108,121,100,105,115,99,117,115,115,101,100,104,101,32,98,101,99,97,109,101,\n101,120,101,99,117,116,105,118,101,106,113,117,101,114,121,46,106,115,104,111,\n117,115,101,104,111,108,100,99,111,110,102,105,114,109,101,100,112,117,114,99,\n104,97,115,101,100,108,105,116,101,114,97,108,108,121,100,101,115,116,114,111,\n121,101,100,117,112,32,116,111,32,116,104,101,118,97,114,105,97,116,105,111,110,\n114,101,109,97,105,110,105,110,103,105,116,32,105,115,32,110,111,116,99,101,110,\n116,117,114,105,101,115,74,97,112,97,110,101,115,101,32,97,109,111,110,103,32,\n116,104,101,99,111,109,112,108,101,116,101,100,97,108,103,111,114,105,116,104,\n109,105,110,116,101,114,101,115,116,115,114,101,98,101,108,108,105,111,110,117,\n110,100,101,102,105,110,101,100,101,110,99,111,117,114,97,103,101,114,101,115,\n105,122,97,98,108,101,105,110,118,111,108,118,105,110,103,115,101,110,115,105,\n116,105,118,101,117,110,105,118,101,114,115,97,108,112,114,111,118,105,115,105,\n111,110,40,97,108,116,104,111,117,103,104,102,101,97,116,117,114,105,110,103,99,\n111,110,100,117,99,116,101,100,41,44,32,119,104,105,99,104,32,99,111,110,116,105\n,110,117,101,100,45,104,101,97,100,101,114,34,62,70,101,98,114,117,97,114,121,32\n,110,117,109,101,114,111,117,115,32,111,118,101,114,102,108,111,119,58,99,111,\n109,112,111,110,101,110,116,102,114,97,103,109,101,110,116,115,101,120,99,101,\n108,108,101,110,116,99,111,108,115,112,97,110,61,34,116,101,99,104,110,105,99,97\n,108,110,101,97,114,32,116,104,101,32,65,100,118,97,110,99,101,100,32,115,111,\n117,114,99,101,32,111,102,101,120,112,114,101,115,115,101,100,72,111,110,103,32,\n75,111,110,103,32,70,97,99,101,98,111,111,107,109,117,108,116,105,112,108,101,32\n,109,101,99,104,97,110,105,115,109,101,108,101,118,97,116,105,111,110,111,102,\n102,101,110,115,105,118,101,60,47,102,111,114,109,62,10,9,115,112,111,110,115,\n111,114,101,100,100,111,99,117,109,101,110,116,46,111,114,32,38,113,117,111,116,\n59,116,104,101,114,101,32,97,114,101,116,104,111,115,101,32,119,104,111,109,111,\n118,101,109,101,110,116,115,112,114,111,99,101,115,115,101,115,100,105,102,102,\n105,99,117,108,116,115,117,98,109,105,116,116,101,100,114,101,99,111,109,109,101\n,110,100,99,111,110,118,105,110,99,101,100,112,114,111,109,111,116,105,110,103,\n34,32,119,105,100,116,104,61,34,46,114,101,112,108,97,99,101,40,99,108,97,115,\n115,105,99,97,108,99,111,97,108,105,116,105,111,110,104,105,115,32,102,105,114,\n115,116,100,101,99,105,115,105,111,110,115,97,115,115,105,115,116,97,110,116,105\n,110,100,105,99,97,116,101,100,101,118,111,108,117,116,105,111,110,45,119,114,97\n,112,112,101,114,34,101,110,111,117,103,104,32,116,111,97,108,111,110,103,32,116\n,104,101,100,101,108,105,118,101,114,101,100,45,45,62,13,10,60,33,45,45,65,109,\n101,114,105,99,97,110,32,112,114,111,116,101,99,116,101,100,78,111,118,101,109,\n98,101,114,32,60,47,115,116,121,108,101,62,60,102,117,114,110,105,116,117,114,\n101,73,110,116,101,114,110,101,116,32,32,111,110,98,108,117,114,61,34,115,117,\n115,112,101,110,100,101,100,114,101,99,105,112,105,101,110,116,98,97,115,101,100\n,32,111,110,32,77,111,114,101,111,118,101,114,44,97,98,111,108,105,115,104,101,\n100,99,111,108,108,101,99,116,101,100,119,101,114,101,32,109,97,100,101,101,109,\n111,116,105,111,110,97,108,101,109,101,114,103,101,110,99,121,110,97,114,114,97,\n116,105,118,101,97,100,118,111,99,97,116,101,115,112,120,59,98,111,114,100,101,\n114,99,111,109,109,105,116,116,101,100,100,105,114,61,34,108,116,114,34,101,109,\n112,108,111,121,101,101,115,114,101,115,101,97,114,99,104,46,32,115,101,108,101,\n99,116,101,100,115,117,99,99,101,115,115,111,114,99,117,115,116,111,109,101,114,\n115,100,105,115,112,108,97,121,101,100,83,101,112,116,101,109,98,101,114,97,100,\n100,67,108,97,115,115,40,70,97,99,101,98,111,111,107,32,115,117,103,103,101,115,\n116,101,100,97,110,100,32,108,97,116,101,114,111,112,101,114,97,116,105,110,103,\n101,108,97,98,111,114,97,116,101,83,111,109,101,116,105,109,101,115,73,110,115,\n116,105,116,117,116,101,99,101,114,116,97,105,110,108,121,105,110,115,116,97,108\n,108,101,100,102,111,108,108,111,119,101,114,115,74,101,114,117,115,97,108,101,\n109,116,104,101,121,32,104,97,118,101,99,111,109,112,117,116,105,110,103,103,101\n,110,101,114,97,116,101,100,112,114,111,118,105,110,99,101,115,103,117,97,114,97\n,110,116,101,101,97,114,98,105,116,114,97,114,121,114,101,99,111,103,110,105,122\n,101,119,97,110,116,101,100,32,116,111,112,120,59,119,105,100,116,104,58,116,104\n,101,111,114,121,32,111,102,98,101,104,97,118,105,111,117,114,87,104,105,108,101\n,32,116,104,101,101,115,116,105,109,97,116,101,100,98,101,103,97,110,32,116,111,\n32,105,116,32,98,101,99,97,109,101,109,97,103,110,105,116,117,100,101,109,117,\n115,116,32,104,97,118,101,109,111,114,101,32,116,104,97,110,68,105,114,101,99,\n116,111,114,121,101,120,116,101,110,115,105,111,110,115,101,99,114,101,116,97,\n114,121,110,97,116,117,114,97,108,108,121,111,99,99,117,114,114,105,110,103,118,\n97,114,105,97,98,108,101,115,103,105,118,101,110,32,116,104,101,112,108,97,116,\n102,111,114,109,46,60,47,108,97,98,101,108,62,60,102,97,105,108,101,100,32,116,\n111,99,111,109,112,111,117,110,100,115,107,105,110,100,115,32,111,102,32,115,111\n,99,105,101,116,105,101,115,97,108,111,110,103,115,105,100,101,32,45,45,38,103,\n116,59,10,10,115,111,117,116,104,119,101,115,116,116,104,101,32,114,105,103,104,\n116,114,97,100,105,97,116,105,111,110,109,97,121,32,104,97,118,101,32,117,110,\n101,115,99,97,112,101,40,115,112,111,107,101,110,32,105,110,34,32,104,114,101,\n102,61,34,47,112,114,111,103,114,97,109,109,101,111,110,108,121,32,116,104,101,\n32,99,111,109,101,32,102,114,111,109,100,105,114,101,99,116,111,114,121,98,117,\n114,105,101,100,32,105,110,97,32,115,105,109,105,108,97,114,116,104,101,121,32,\n119,101,114,101,60,47,102,111,110,116,62,60,47,78,111,114,119,101,103,105,97,110\n,115,112,101,99,105,102,105,101,100,112,114,111,100,117,99,105,110,103,112,97,\n115,115,101,110,103,101,114,40,110,101,119,32,68,97,116,101,116,101,109,112,111,\n114,97,114,121,102,105,99,116,105,111,110,97,108,65,102,116,101,114,32,116,104,\n101,101,113,117,97,116,105,111,110,115,100,111,119,110,108,111,97,100,46,114,101\n,103,117,108,97,114,108,121,100,101,118,101,108,111,112,101,114,97,98,111,118,\n101,32,116,104,101,108,105,110,107,101,100,32,116,111,112,104,101,110,111,109,\n101,110,97,112,101,114,105,111,100,32,111,102,116,111,111,108,116,105,112,34,62,\n115,117,98,115,116,97,110,99,101,97,117,116,111,109,97,116,105,99,97,115,112,101\n,99,116,32,111,102,65,109,111,110,103,32,116,104,101,99,111,110,110,101,99,116,\n101,100,101,115,116,105,109,97,116,101,115,65,105,114,32,70,111,114,99,101,115,\n121,115,116,101,109,32,111,102,111,98,106,101,99,116,105,118,101,105,109,109,101\n,100,105,97,116,101,109,97,107,105,110,103,32,105,116,112,97,105,110,116,105,110\n,103,115,99,111,110,113,117,101,114,101,100,97,114,101,32,115,116,105,108,108,\n112,114,111,99,101,100,117,114,101,103,114,111,119,116,104,32,111,102,104,101,97\n,100,101,100,32,98,121,69,117,114,111,112,101,97,110,32,100,105,118,105,115,105,\n111,110,115,109,111,108,101,99,117,108,101,115,102,114,97,110,99,104,105,115,101\n,105,110,116,101,110,116,105,111,110,97,116,116,114,97,99,116,101,100,99,104,105\n,108,100,104,111,111,100,97,108,115,111,32,117,115,101,100,100,101,100,105,99,97\n,116,101,100,115,105,110,103,97,112,111,114,101,100,101,103,114,101,101,32,111,\n102,102,97,116,104,101,114,32,111,102,99,111,110,102,108,105,99,116,115,60,47,97\n,62,60,47,112,62,10,99,97,109,101,32,102,114,111,109,119,101,114,101,32,117,115,\n101,100,110,111,116,101,32,116,104,97,116,114,101,99,101,105,118,105,110,103,69,\n120,101,99,117,116,105,118,101,101,118,101,110,32,109,111,114,101,97,99,99,101,\n115,115,32,116,111,99,111,109,109,97,110,100,101,114,80,111,108,105,116,105,99,\n97,108,109,117,115,105,99,105,97,110,115,100,101,108,105,99,105,111,117,115,112,\n114,105,115,111,110,101,114,115,97,100,118,101,110,116,32,111,102,85,84,70,45,56\n,34,32,47,62,60,33,91,67,68,65,84,65,91,34,62,67,111,110,116,97,99,116,83,111,\n117,116,104,101,114,110,32,98,103,99,111,108,111,114,61,34,115,101,114,105,101,\n115,32,111,102,46,32,73,116,32,119,97,115,32,105,110,32,69,117,114,111,112,101,\n112,101,114,109,105,116,116,101,100,118,97,108,105,100,97,116,101,46,97,112,112,\n101,97,114,105,110,103,111,102,102,105,99,105,97,108,115,115,101,114,105,111,117\n,115,108,121,45,108,97,110,103,117,97,103,101,105,110,105,116,105,97,116,101,100\n,101,120,116,101,110,100,105,110,103,108,111,110,103,45,116,101,114,109,105,110,\n102,108,97,116,105,111,110,115,117,99,104,32,116,104,97,116,103,101,116,67,111,\n111,107,105,101,109,97,114,107,101,100,32,98,121,60,47,98,117,116,116,111,110,62\n,105,109,112,108,101,109,101,110,116,98,117,116,32,105,116,32,105,115,105,110,99\n,114,101,97,115,101,115,100,111,119,110,32,116,104,101,32,114,101,113,117,105,\n114,105,110,103,100,101,112,101,110,100,101,110,116,45,45,62,10,60,33,45,45,32,\n105,110,116,101,114,118,105,101,119,87,105,116,104,32,116,104,101,32,99,111,112,\n105,101,115,32,111,102,99,111,110,115,101,110,115,117,115,119,97,115,32,98,117,\n105,108,116,86,101,110,101,122,117,101,108,97,40,102,111,114,109,101,114,108,121\n,116,104,101,32,115,116,97,116,101,112,101,114,115,111,110,110,101,108,115,116,\n114,97,116,101,103,105,99,102,97,118,111,117,114,32,111,102,105,110,118,101,110,\n116,105,111,110,87,105,107,105,112,101,100,105,97,99,111,110,116,105,110,101,110\n,116,118,105,114,116,117,97,108,108,121,119,104,105,99,104,32,119,97,115,112,114\n,105,110,99,105,112,108,101,67,111,109,112,108,101,116,101,32,105,100,101,110,\n116,105,99,97,108,115,104,111,119,32,116,104,97,116,112,114,105,109,105,116,105,\n118,101,97,119,97,121,32,102,114,111,109,109,111,108,101,99,117,108,97,114,112,\n114,101,99,105,115,101,108,121,100,105,115,115,111,108,118,101,100,85,110,100,\n101,114,32,116,104,101,118,101,114,115,105,111,110,61,34,62,38,110,98,115,112,59\n,60,47,73,116,32,105,115,32,116,104,101,32,84,104,105,115,32,105,115,32,119,105,\n108,108,32,104,97,118,101,111,114,103,97,110,105,115,109,115,115,111,109,101,32,\n116,105,109,101,70,114,105,101,100,114,105,99,104,119,97,115,32,102,105,114,115,\n116,116,104,101,32,111,110,108,121,32,102,97,99,116,32,116,104,97,116,102,111,\n114,109,32,105,100,61,34,112,114,101,99,101,100,105,110,103,84,101,99,104,110,\n105,99,97,108,112,104,121,115,105,99,105,115,116,111,99,99,117,114,115,32,105,\n110,110,97,118,105,103,97,116,111,114,115,101,99,116,105,111,110,34,62,115,112,\n97,110,32,105,100,61,34,115,111,117,103,104,116,32,116,111,98,101,108,111,119,32\n,116,104,101,115,117,114,118,105,118,105,110,103,125,60,47,115,116,121,108,101,\n62,104,105,115,32,100,101,97,116,104,97,115,32,105,110,32,116,104,101,99,97,117,\n115,101,100,32,98,121,112,97,114,116,105,97,108,108,121,101,120,105,115,116,105,\n110,103,32,117,115,105,110,103,32,116,104,101,119,97,115,32,103,105,118,101,110,\n97,32,108,105,115,116,32,111,102,108,101,118,101,108,115,32,111,102,110,111,116,\n105,111,110,32,111,102,79,102,102,105,99,105,97,108,32,100,105,115,109,105,115,\n115,101,100,115,99,105,101,110,116,105,115,116,114,101,115,101,109,98,108,101,\n115,100,117,112,108,105,99,97,116,101,101,120,112,108,111,115,105,118,101,114,\n101,99,111,118,101,114,101,100,97,108,108,32,111,116,104,101,114,103,97,108,108,\n101,114,105,101,115,123,112,97,100,100,105,110,103,58,112,101,111,112,108,101,32\n,111,102,114,101,103,105,111,110,32,111,102,97,100,100,114,101,115,115,101,115,\n97,115,115,111,99,105,97,116,101,105,109,103,32,97,108,116,61,34,105,110,32,109,\n111,100,101,114,110,115,104,111,117,108,100,32,98,101,109,101,116,104,111,100,32\n,111,102,114,101,112,111,114,116,105,110,103,116,105,109,101,115,116,97,109,112,\n110,101,101,100,101,100,32,116,111,116,104,101,32,71,114,101,97,116,114,101,103,\n97,114,100,105,110,103,115,101,101,109,101,100,32,116,111,118,105,101,119,101,\n100,32,97,115,105,109,112,97,99,116,32,111,110,105,100,101,97,32,116,104,97,116,\n116,104,101,32,87,111,114,108,100,104,101,105,103,104,116,32,111,102,101,120,112\n,97,110,100,105,110,103,84,104,101,115,101,32,97,114,101,99,117,114,114,101,110,\n116,34,62,99,97,114,101,102,117,108,108,121,109,97,105,110,116,97,105,110,115,99\n,104,97,114,103,101,32,111,102,67,108,97,115,115,105,99,97,108,97,100,100,114,\n101,115,115,101,100,112,114,101,100,105,99,116,101,100,111,119,110,101,114,115,\n104,105,112,60,100,105,118,32,105,100,61,34,114,105,103,104,116,34,62,13,10,114,\n101,115,105,100,101,110,99,101,108,101,97,118,101,32,116,104,101,99,111,110,116,\n101,110,116,34,62,97,114,101,32,111,102,116,101,110,32,32,125,41,40,41,59,13,10,\n112,114,111,98,97,98,108,121,32,80,114,111,102,101,115,115,111,114,45,98,117,116\n,116,111,110,34,32,114,101,115,112,111,110,100,101,100,115,97,121,115,32,116,104\n,97,116,104,97,100,32,116,111,32,98,101,112,108,97,99,101,100,32,105,110,72,117,\n110,103,97,114,105,97,110,115,116,97,116,117,115,32,111,102,115,101,114,118,101,\n115,32,97,115,85,110,105,118,101,114,115,97,108,101,120,101,99,117,116,105,111,\n110,97,103,103,114,101,103,97,116,101,102,111,114,32,119,104,105,99,104,105,110,\n102,101,99,116,105,111,110,97,103,114,101,101,100,32,116,111,104,111,119,101,118\n,101,114,44,32,112,111,112,117,108,97,114,34,62,112,108,97,99,101,100,32,111,110\n,99,111,110,115,116,114,117,99,116,101,108,101,99,116,111,114,97,108,115,121,109\n,98,111,108,32,111,102,105,110,99,108,117,100,105,110,103,114,101,116,117,114,\n110,32,116,111,97,114,99,104,105,116,101,99,116,67,104,114,105,115,116,105,97,\n110,112,114,101,118,105,111,117,115,32,108,105,118,105,110,103,32,105,110,101,97\n,115,105,101,114,32,116,111,112,114,111,102,101,115,115,111,114,10,38,108,116,59\n,33,45,45,32,101,102,102,101,99,116,32,111,102,97,110,97,108,121,116,105,99,115,\n119,97,115,32,116,97,107,101,110,119,104,101,114,101,32,116,104,101,116,111,111,\n107,32,111,118,101,114,98,101,108,105,101,102,32,105,110,65,102,114,105,107,97,\n97,110,115,97,115,32,102,97,114,32,97,115,112,114,101,118,101,110,116,101,100,\n119,111,114,107,32,119,105,116,104,97,32,115,112,101,99,105,97,108,60,102,105,\n101,108,100,115,101,116,67,104,114,105,115,116,109,97,115,82,101,116,114,105,101\n,118,101,100,10,10,73,110,32,116,104,101,32,98,97,99,107,32,105,110,116,111,110,\n111,114,116,104,101,97,115,116,109,97,103,97,122,105,110,101,115,62,60,115,116,\n114,111,110,103,62,99,111,109,109,105,116,116,101,101,103,111,118,101,114,110,\n105,110,103,103,114,111,117,112,115,32,111,102,115,116,111,114,101,100,32,105,\n110,101,115,116,97,98,108,105,115,104,97,32,103,101,110,101,114,97,108,105,116,\n115,32,102,105,114,115,116,116,104,101,105,114,32,111,119,110,112,111,112,117,\n108,97,116,101,100,97,110,32,111,98,106,101,99,116,67,97,114,105,98,98,101,97,\n110,97,108,108,111,119,32,116,104,101,100,105,115,116,114,105,99,116,115,119,105\n,115,99,111,110,115,105,110,108,111,99,97,116,105,111,110,46,59,32,119,105,100,\n116,104,58,32,105,110,104,97,98,105,116,101,100,83,111,99,105,97,108,105,115,116\n,74,97,110,117,97,114,121,32,49,60,47,102,111,111,116,101,114,62,115,105,109,105\n,108,97,114,108,121,99,104,111,105,99,101,32,111,102,116,104,101,32,115,97,109,\n101,32,115,112,101,99,105,102,105,99,32,98,117,115,105,110,101,115,115,32,84,104\n,101,32,102,105,114,115,116,46,108,101,110,103,116,104,59,32,100,101,115,105,114\n,101,32,116,111,100,101,97,108,32,119,105,116,104,115,105,110,99,101,32,116,104,\n101,117,115,101,114,65,103,101,110,116,99,111,110,99,101,105,118,101,100,105,110\n,100,101,120,46,112,104,112,97,115,32,38,113,117,111,116,59,101,110,103,97,103,\n101,32,105,110,114,101,99,101,110,116,108,121,44,102,101,119,32,121,101,97,114,\n115,119,101,114,101,32,97,108,115,111,10,60,104,101,97,100,62,10,60,101,100,105,\n116,101,100,32,98,121,97,114,101,32,107,110,111,119,110,99,105,116,105,101,115,\n32,105,110,97,99,99,101,115,115,107,101,121,99,111,110,100,101,109,110,101,100,\n97,108,115,111,32,104,97,118,101,115,101,114,118,105,99,101,115,44,102,97,109,\n105,108,121,32,111,102,83,99,104,111,111,108,32,111,102,99,111,110,118,101,114,\n116,101,100,110,97,116,117,114,101,32,111,102,32,108,97,110,103,117,97,103,101,\n109,105,110,105,115,116,101,114,115,60,47,111,98,106,101,99,116,62,116,104,101,\n114,101,32,105,115,32,97,32,112,111,112,117,108,97,114,115,101,113,117,101,110,\n99,101,115,97,100,118,111,99,97,116,101,100,84,104,101,121,32,119,101,114,101,97\n,110,121,32,111,116,104,101,114,108,111,99,97,116,105,111,110,61,101,110,116,101\n,114,32,116,104,101,109,117,99,104,32,109,111,114,101,114,101,102,108,101,99,116\n,101,100,119,97,115,32,110,97,109,101,100,111,114,105,103,105,110,97,108,32,97,\n32,116,121,112,105,99,97,108,119,104,101,110,32,116,104,101,121,101,110,103,105,\n110,101,101,114,115,99,111,117,108,100,32,110,111,116,114,101,115,105,100,101,\n110,116,115,119,101,100,110,101,115,100,97,121,116,104,101,32,116,104,105,114,\n100,32,112,114,111,100,117,99,116,115,74,97,110,117,97,114,121,32,50,119,104,97,\n116,32,116,104,101,121,97,32,99,101,114,116,97,105,110,114,101,97,99,116,105,111\n,110,115,112,114,111,99,101,115,115,111,114,97,102,116,101,114,32,104,105,115,\n116,104,101,32,108,97,115,116,32,99,111,110,116,97,105,110,101,100,34,62,60,47,\n100,105,118,62,10,60,47,97,62,60,47,116,100,62,100,101,112,101,110,100,32,111,\n110,115,101,97,114,99,104,34,62,10,112,105,101,99,101,115,32,111,102,99,111,109,\n112,101,116,105,110,103,82,101,102,101,114,101,110,99,101,116,101,110,110,101,\n115,115,101,101,119,104,105,99,104,32,104,97,115,32,118,101,114,115,105,111,110,\n61,60,47,115,112,97,110,62,32,60,60,47,104,101,97,100,101,114,62,103,105,118,101\n,115,32,116,104,101,104,105,115,116,111,114,105,97,110,118,97,108,117,101,61,34,\n34,62,112,97,100,100,105,110,103,58,48,118,105,101,119,32,116,104,97,116,116,111\n,103,101,116,104,101,114,44,116,104,101,32,109,111,115,116,32,119,97,115,32,102,\n111,117,110,100,115,117,98,115,101,116,32,111,102,97,116,116,97,99,107,32,111,\n110,99,104,105,108,100,114,101,110,44,112,111,105,110,116,115,32,111,102,112,101\n,114,115,111,110,97,108,32,112,111,115,105,116,105,111,110,58,97,108,108,101,103\n,101,100,108,121,67,108,101,118,101,108,97,110,100,119,97,115,32,108,97,116,101,\n114,97,110,100,32,97,102,116,101,114,97,114,101,32,103,105,118,101,110,119,97,\n115,32,115,116,105,108,108,115,99,114,111,108,108,105,110,103,100,101,115,105,\n103,110,32,111,102,109,97,107,101,115,32,116,104,101,109,117,99,104,32,108,101,\n115,115,65,109,101,114,105,99,97,110,115,46,10,10,65,102,116,101,114,32,44,32,98\n,117,116,32,116,104,101,77,117,115,101,117,109,32,111,102,108,111,117,105,115,\n105,97,110,97,40,102,114,111,109,32,116,104,101,109,105,110,110,101,115,111,116,\n97,112,97,114,116,105,99,108,101,115,97,32,112,114,111,99,101,115,115,68,111,109\n,105,110,105,99,97,110,118,111,108,117,109,101,32,111,102,114,101,116,117,114,\n110,105,110,103,100,101,102,101,110,115,105,118,101,48,48,112,120,124,114,105,\n103,104,109,97,100,101,32,102,114,111,109,109,111,117,115,101,111,118,101,114,34\n,32,115,116,121,108,101,61,34,115,116,97,116,101,115,32,111,102,40,119,104,105,\n99,104,32,105,115,99,111,110,116,105,110,117,101,115,70,114,97,110,99,105,115,99\n,111,98,117,105,108,100,105,110,103,32,119,105,116,104,111,117,116,32,97,119,105\n,116,104,32,115,111,109,101,119,104,111,32,119,111,117,108,100,97,32,102,111,114\n,109,32,111,102,97,32,112,97,114,116,32,111,102,98,101,102,111,114,101,32,105,\n116,107,110,111,119,110,32,97,115,32,32,83,101,114,118,105,99,101,115,108,111,99\n,97,116,105,111,110,32,97,110,100,32,111,102,116,101,110,109,101,97,115,117,114,\n105,110,103,97,110,100,32,105,116,32,105,115,112,97,112,101,114,98,97,99,107,118\n,97,108,117,101,115,32,111,102,13,10,60,116,105,116,108,101,62,61,32,119,105,110\n,100,111,119,46,100,101,116,101,114,109,105,110,101,101,114,38,113,117,111,116,\n59,32,112,108,97,121,101,100,32,98,121,97,110,100,32,101,97,114,108,121,60,47,99\n,101,110,116,101,114,62,102,114,111,109,32,116,104,105,115,116,104,101,32,116,\n104,114,101,101,112,111,119,101,114,32,97,110,100,111,102,32,38,113,117,111,116,\n59,105,110,110,101,114,72,84,77,76,60,97,32,104,114,101,102,61,34,121,58,105,110\n,108,105,110,101,59,67,104,117,114,99,104,32,111,102,116,104,101,32,101,118,101,\n110,116,118,101,114,121,32,104,105,103,104,111,102,102,105,99,105,97,108,32,45,\n104,101,105,103,104,116,58,32,99,111,110,116,101,110,116,61,34,47,99,103,105,45,\n98,105,110,47,116,111,32,99,114,101,97,116,101,97,102,114,105,107,97,97,110,115,\n101,115,112,101,114,97,110,116,111,102,114,97,110,195,167,97,105,115,108,97,116,\n118,105,101,197,161,117,108,105,101,116,117,118,105,197,179,196,140,101,197,161,\n116,105,110,97,196,141,101,197,161,116,105,110,97,224,185,132,224,184,151,224,\n184,162,230,151,165,230,156,172,232,170,158,231,174,128,228,189,147,229,173,151,\n231,185,129,233,171,148,229,173,151,237,149,156,234,181,173,236,150,180,228,184,\n186,228,187,128,228,185,136,232,174,161,231,174,151,230,156,186,231,172,148,232,\n174,176,230,156,172,232,168,142,232,171,150,229,141,128,230,156,141,229,138,161,\n229,153,168,228,186,146,232,129,148,231,189,145,230,136,191,229,156,176,228,186,\n167,228,191,177,228,185,144,233,131,168,229,135,186,231,137,136,231,164,190,230,\n142,146,232,161,140,230,166,156,233,131,168,232,144,189,230,160,188,232,191,155,\n228,184,128,230,173,165,230,148,175,228,187,152,229,174,157,233,170,140,232,175,\n129,231,160,129,229,167,148,229,145,152,228,188,154,230,149,176,230,141,174,229,\n186,147,230,182,136,232,180,185,232,128,133,229,138,158,229,133,172,229,174,164,\n232,174,168,232,174,186,229,140,186,230,183,177,229,156,179,229,184,130,230,146,\n173,230,148,190,229,153,168,229,140,151,228,186,172,229,184,130,229,164,167,229,\n173,166,231,148,159,232,182,138,230,157,165,232,182,138,231,174,161,231,144,134,\n229,145,152,228,191,161,230,129,175,231,189,145,115,101,114,118,105,99,105,111,\n115,97,114,116,195,173,99,117,108,111,97,114,103,101,110,116,105,110,97,98,97,\n114,99,101,108,111,110,97,99,117,97,108,113,117,105,101,114,112,117,98,108,105,\n99,97,100,111,112,114,111,100,117,99,116,111,115,112,111,108,195,173,116,105,99,\n97,114,101,115,112,117,101,115,116,97,119,105,107,105,112,101,100,105,97,115,105\n,103,117,105,101,110,116,101,98,195,186,115,113,117,101,100,97,99,111,109,117,\n110,105,100,97,100,115,101,103,117,114,105,100,97,100,112,114,105,110,99,105,112\n,97,108,112,114,101,103,117,110,116,97,115,99,111,110,116,101,110,105,100,111,\n114,101,115,112,111,110,100,101,114,118,101,110,101,122,117,101,108,97,112,114,\n111,98,108,101,109,97,115,100,105,99,105,101,109,98,114,101,114,101,108,97,99,\n105,195,179,110,110,111,118,105,101,109,98,114,101,115,105,109,105,108,97,114,\n101,115,112,114,111,121,101,99,116,111,115,112,114,111,103,114,97,109,97,115,105\n,110,115,116,105,116,117,116,111,97,99,116,105,118,105,100,97,100,101,110,99,117\n,101,110,116,114,97,101,99,111,110,111,109,195,173,97,105,109,195,161,103,101,\n110,101,115,99,111,110,116,97,99,116,97,114,100,101,115,99,97,114,103,97,114,110\n,101,99,101,115,97,114,105,111,97,116,101,110,99,105,195,179,110,116,101,108,195\n,169,102,111,110,111,99,111,109,105,115,105,195,179,110,99,97,110,99,105,111,110\n,101,115,99,97,112,97,99,105,100,97,100,101,110,99,111,110,116,114,97,114,97,110\n,195,161,108,105,115,105,115,102,97,118,111,114,105,116,111,115,116,195,169,114,\n109,105,110,111,115,112,114,111,118,105,110,99,105,97,101,116,105,113,117,101,\n116,97,115,101,108,101,109,101,110,116,111,115,102,117,110,99,105,111,110,101,\n115,114,101,115,117,108,116,97,100,111,99,97,114,195,161,99,116,101,114,112,114,\n111,112,105,101,100,97,100,112,114,105,110,99,105,112,105,111,110,101,99,101,115\n,105,100,97,100,109,117,110,105,99,105,112,97,108,99,114,101,97,99,105,195,179,\n110,100,101,115,99,97,114,103,97,115,112,114,101,115,101,110,99,105,97,99,111,\n109,101,114,99,105,97,108,111,112,105,110,105,111,110,101,115,101,106,101,114,99\n,105,99,105,111,101,100,105,116,111,114,105,97,108,115,97,108,97,109,97,110,99,\n97,103,111,110,122,195,161,108,101,122,100,111,99,117,109,101,110,116,111,112,\n101,108,195,173,99,117,108,97,114,101,99,105,101,110,116,101,115,103,101,110,101\n,114,97,108,101,115,116,97,114,114,97,103,111,110,97,112,114,195,161,99,116,105,\n99,97,110,111,118,101,100,97,100,101,115,112,114,111,112,117,101,115,116,97,112,\n97,99,105,101,110,116,101,115,116,195,169,99,110,105,99,97,115,111,98,106,101,\n116,105,118,111,115,99,111,110,116,97,99,116,111,115,224,164,174,224,165,135,224\n,164,130,224,164,178,224,164,191,224,164,143,224,164,185,224,165,136,224,164,130\n,224,164,151,224,164,175,224,164,190,224,164,184,224,164,190,224,164,165,224,164\n,143,224,164,181,224,164,130,224,164,176,224,164,185,224,165,135,224,164,149,224\n,165,139,224,164,136,224,164,149,224,165,129,224,164,155,224,164,176,224,164,185\n,224,164,190,224,164,172,224,164,190,224,164,166,224,164,149,224,164,185,224,164\n,190,224,164,184,224,164,173,224,165,128,224,164,185,224,165,129,224,164,143,224\n,164,176,224,164,185,224,165,128,224,164,174,224,165,136,224,164,130,224,164,166\n,224,164,191,224,164,168,224,164,172,224,164,190,224,164,164,100,105,112,108,111\n,100,111,99,115,224,164,184,224,164,174,224,164,175,224,164,176,224,165,130,224,\n164,170,224,164,168,224,164,190,224,164,174,224,164,170,224,164,164,224,164,190,\n224,164,171,224,164,191,224,164,176,224,164,148,224,164,184,224,164,164,224,164,\n164,224,164,176,224,164,185,224,164,178,224,165,139,224,164,151,224,164,185,224,\n165,129,224,164,134,224,164,172,224,164,190,224,164,176,224,164,166,224,165,135,\n224,164,182,224,164,185,224,165,129,224,164,136,224,164,150,224,165,135,224,164,\n178,224,164,175,224,164,166,224,164,191,224,164,149,224,164,190,224,164,174,224,\n164,181,224,165,135,224,164,172,224,164,164,224,165,128,224,164,168,224,164,172,\n224,165,128,224,164,154,224,164,174,224,165,140,224,164,164,224,164,184,224,164,\n190,224,164,178,224,164,178,224,165,135,224,164,150,224,164,156,224,165,137,224,\n164,172,224,164,174,224,164,166,224,164,166,224,164,164,224,164,165,224,164,190,\n224,164,168,224,164,185,224,165,128,224,164,182,224,164,185,224,164,176,224,164,\n133,224,164,178,224,164,151,224,164,149,224,164,173,224,165,128,224,164,168,224,\n164,151,224,164,176,224,164,170,224,164,190,224,164,184,224,164,176,224,164,190,\n224,164,164,224,164,149,224,164,191,224,164,143,224,164,137,224,164,184,224,165,\n135,224,164,151,224,164,175,224,165,128,224,164,185,224,165,130,224,164,129,224,\n164,134,224,164,151,224,165,135,224,164,159,224,165,128,224,164,174,224,164,150,\n224,165,139,224,164,156,224,164,149,224,164,190,224,164,176,224,164,133,224,164,\n173,224,165,128,224,164,151,224,164,175,224,165,135,224,164,164,224,165,129,224,\n164,174,224,164,181,224,165,139,224,164,159,224,164,166,224,165,135,224,164,130,\n224,164,133,224,164,151,224,164,176,224,164,144,224,164,184,224,165,135,224,164,\n174,224,165,135,224,164,178,224,164,178,224,164,151,224,164,190,224,164,185,224,\n164,190,224,164,178,224,164,138,224,164,170,224,164,176,224,164,154,224,164,190,\n224,164,176,224,164,144,224,164,184,224,164,190,224,164,166,224,165,135,224,164,\n176,224,164,156,224,164,191,224,164,184,224,164,166,224,164,191,224,164,178,224,\n164,172,224,164,130,224,164,166,224,164,172,224,164,168,224,164,190,224,164,185,\n224,165,130,224,164,130,224,164,178,224,164,190,224,164,150,224,164,156,224,165,\n128,224,164,164,224,164,172,224,164,159,224,164,168,224,164,174,224,164,191,224,\n164,178,224,164,135,224,164,184,224,165,135,224,164,134,224,164,168,224,165,135,\n224,164,168,224,164,175,224,164,190,224,164,149,224,165,129,224,164,178,224,164,\n178,224,165,137,224,164,151,224,164,173,224,164,190,224,164,151,224,164,176,224,\n165,135,224,164,178,224,164,156,224,164,151,224,164,185,224,164,176,224,164,190,\n224,164,174,224,164,178,224,164,151,224,165,135,224,164,170,224,165,135,224,164,\n156,224,164,185,224,164,190,224,164,165,224,164,135,224,164,184,224,165,128,224,\n164,184,224,164,185,224,165,128,224,164,149,224,164,178,224,164,190,224,164,160,\n224,165,128,224,164,149,224,164,185,224,164,190,224,164,129,224,164,166,224,165,\n130,224,164,176,224,164,164,224,164,185,224,164,164,224,164,184,224,164,190,224,\n164,164,224,164,175,224,164,190,224,164,166,224,164,134,224,164,175,224,164,190,\n224,164,170,224,164,190,224,164,149,224,164,149,224,165,140,224,164,168,224,164,\n182,224,164,190,224,164,174,224,164,166,224,165,135,224,164,150,224,164,175,224,\n164,185,224,165,128,224,164,176,224,164,190,224,164,175,224,164,150,224,165,129,\n224,164,166,224,164,178,224,164,151,224,165,128,99,97,116,101,103,111,114,105,\n101,115,101,120,112,101,114,105,101,110,99,101,60,47,116,105,116,108,101,62,13,\n10,67,111,112,121,114,105,103,104,116,32,106,97,118,97,115,99,114,105,112,116,99\n,111,110,100,105,116,105,111,110,115,101,118,101,114,121,116,104,105,110,103,60,\n112,32,99,108,97,115,115,61,34,116,101,99,104,110,111,108,111,103,121,98,97,99,\n107,103,114,111,117,110,100,60,97,32,99,108,97,115,115,61,34,109,97,110,97,103,\n101,109,101,110,116,38,99,111,112,121,59,32,50,48,49,106,97,118,97,83,99,114,105\n,112,116,99,104,97,114,97,99,116,101,114,115,98,114,101,97,100,99,114,117,109,98\n,116,104,101,109,115,101,108,118,101,115,104,111,114,105,122,111,110,116,97,108,\n103,111,118,101,114,110,109,101,110,116,67,97,108,105,102,111,114,110,105,97,97,\n99,116,105,118,105,116,105,101,115,100,105,115,99,111,118,101,114,101,100,78,97,\n118,105,103,97,116,105,111,110,116,114,97,110,115,105,116,105,111,110,99,111,110\n,110,101,99,116,105,111,110,110,97,118,105,103,97,116,105,111,110,97,112,112,101\n,97,114,97,110,99,101,60,47,116,105,116,108,101,62,60,109,99,104,101,99,107,98,\n111,120,34,32,116,101,99,104,110,105,113,117,101,115,112,114,111,116,101,99,116,\n105,111,110,97,112,112,97,114,101,110,116,108,121,97,115,32,119,101,108,108,32,\n97,115,117,110,116,39,44,32,39,85,65,45,114,101,115,111,108,117,116,105,111,110,\n111,112,101,114,97,116,105,111,110,115,116,101,108,101,118,105,115,105,111,110,\n116,114,97,110,115,108,97,116,101,100,87,97,115,104,105,110,103,116,111,110,110,\n97,118,105,103,97,116,111,114,46,32,61,32,119,105,110,100,111,119,46,105,109,112\n,114,101,115,115,105,111,110,38,108,116,59,98,114,38,103,116,59,108,105,116,101,\n114,97,116,117,114,101,112,111,112,117,108,97,116,105,111,110,98,103,99,111,108,\n111,114,61,34,35,101,115,112,101,99,105,97,108,108,121,32,99,111,110,116,101,110\n,116,61,34,112,114,111,100,117,99,116,105,111,110,110,101,119,115,108,101,116,\n116,101,114,112,114,111,112,101,114,116,105,101,115,100,101,102,105,110,105,116,\n105,111,110,108,101,97,100,101,114,115,104,105,112,84,101,99,104,110,111,108,111\n,103,121,80,97,114,108,105,97,109,101,110,116,99,111,109,112,97,114,105,115,111,\n110,117,108,32,99,108,97,115,115,61,34,46,105,110,100,101,120,79,102,40,34,99,\n111,110,99,108,117,115,105,111,110,100,105,115,99,117,115,115,105,111,110,99,111\n,109,112,111,110,101,110,116,115,98,105,111,108,111,103,105,99,97,108,82,101,118\n,111,108,117,116,105,111,110,95,99,111,110,116,97,105,110,101,114,117,110,100,\n101,114,115,116,111,111,100,110,111,115,99,114,105,112,116,62,60,112,101,114,109\n,105,115,115,105,111,110,101,97,99,104,32,111,116,104,101,114,97,116,109,111,115\n,112,104,101,114,101,32,111,110,102,111,99,117,115,61,34,60,102,111,114,109,32,\n105,100,61,34,112,114,111,99,101,115,115,105,110,103,116,104,105,115,46,118,97,\n108,117,101,103,101,110,101,114,97,116,105,111,110,67,111,110,102,101,114,101,\n110,99,101,115,117,98,115,101,113,117,101,110,116,119,101,108,108,45,107,110,111\n,119,110,118,97,114,105,97,116,105,111,110,115,114,101,112,117,116,97,116,105,\n111,110,112,104,101,110,111,109,101,110,111,110,100,105,115,99,105,112,108,105,\n110,101,108,111,103,111,46,112,110,103,34,32,40,100,111,99,117,109,101,110,116,\n44,98,111,117,110,100,97,114,105,101,115,101,120,112,114,101,115,115,105,111,110\n,115,101,116,116,108,101,109,101,110,116,66,97,99,107,103,114,111,117,110,100,\n111,117,116,32,111,102,32,116,104,101,101,110,116,101,114,112,114,105,115,101,40\n,34,104,116,116,112,115,58,34,32,117,110,101,115,99,97,112,101,40,34,112,97,115,\n115,119,111,114,100,34,32,100,101,109,111,99,114,97,116,105,99,60,97,32,104,114,\n101,102,61,34,47,119,114,97,112,112,101,114,34,62,10,109,101,109,98,101,114,115,\n104,105,112,108,105,110,103,117,105,115,116,105,99,112,120,59,112,97,100,100,105\n,110,103,112,104,105,108,111,115,111,112,104,121,97,115,115,105,115,116,97,110,\n99,101,117,110,105,118,101,114,115,105,116,121,102,97,99,105,108,105,116,105,101\n,115,114,101,99,111,103,110,105,122,101,100,112,114,101,102,101,114,101,110,99,\n101,105,102,32,40,116,121,112,101,111,102,109,97,105,110,116,97,105,110,101,100,\n118,111,99,97,98,117,108,97,114,121,104,121,112,111,116,104,101,115,105,115,46,\n115,117,98,109,105,116,40,41,59,38,97,109,112,59,110,98,115,112,59,97,110,110,\n111,116,97,116,105,111,110,98,101,104,105,110,100,32,116,104,101,70,111,117,110,\n100,97,116,105,111,110,112,117,98,108,105,115,104,101,114,34,97,115,115,117,109,\n112,116,105,111,110,105,110,116,114,111,100,117,99,101,100,99,111,114,114,117,\n112,116,105,111,110,115,99,105,101,110,116,105,115,116,115,101,120,112,108,105,\n99,105,116,108,121,105,110,115,116,101,97,100,32,111,102,100,105,109,101,110,115\n,105,111,110,115,32,111,110,67,108,105,99,107,61,34,99,111,110,115,105,100,101,\n114,101,100,100,101,112,97,114,116,109,101,110,116,111,99,99,117,112,97,116,105,\n111,110,115,111,111,110,32,97,102,116,101,114,105,110,118,101,115,116,109,101,\n110,116,112,114,111,110,111,117,110,99,101,100,105,100,101,110,116,105,102,105,\n101,100,101,120,112,101,114,105,109,101,110,116,77,97,110,97,103,101,109,101,110\n,116,103,101,111,103,114,97,112,104,105,99,34,32,104,101,105,103,104,116,61,34,\n108,105,110,107,32,114,101,108,61,34,46,114,101,112,108,97,99,101,40,47,100,101,\n112,114,101,115,115,105,111,110,99,111,110,102,101,114,101,110,99,101,112,117,\n110,105,115,104,109,101,110,116,101,108,105,109,105,110,97,116,101,100,114,101,\n115,105,115,116,97,110,99,101,97,100,97,112,116,97,116,105,111,110,111,112,112,\n111,115,105,116,105,111,110,119,101,108,108,32,107,110,111,119,110,115,117,112,\n112,108,101,109,101,110,116,100,101,116,101,114,109,105,110,101,100,104,49,32,99\n,108,97,115,115,61,34,48,112,120,59,109,97,114,103,105,110,109,101,99,104,97,110\n,105,99,97,108,115,116,97,116,105,115,116,105,99,115,99,101,108,101,98,114,97,\n116,101,100,71,111,118,101,114,110,109,101,110,116,10,10,68,117,114,105,110,103,\n32,116,100,101,118,101,108,111,112,101,114,115,97,114,116,105,102,105,99,105,97,\n108,101,113,117,105,118,97,108,101,110,116,111,114,105,103,105,110,97,116,101,\n100,67,111,109,109,105,115,115,105,111,110,97,116,116,97,99,104,109,101,110,116,\n60,115,112,97,110,32,105,100,61,34,116,104,101,114,101,32,119,101,114,101,78,101\n,100,101,114,108,97,110,100,115,98,101,121,111,110,100,32,116,104,101,114,101,\n103,105,115,116,101,114,101,100,106,111,117,114,110,97,108,105,115,116,102,114,\n101,113,117,101,110,116,108,121,97,108,108,32,111,102,32,116,104,101,108,97,110,\n103,61,34,101,110,34,32,60,47,115,116,121,108,101,62,13,10,97,98,115,111,108,117\n,116,101,59,32,115,117,112,112,111,114,116,105,110,103,101,120,116,114,101,109,\n101,108,121,32,109,97,105,110,115,116,114,101,97,109,60,47,115,116,114,111,110,\n103,62,32,112,111,112,117,108,97,114,105,116,121,101,109,112,108,111,121,109,101\n,110,116,60,47,116,97,98,108,101,62,13,10,32,99,111,108,115,112,97,110,61,34,60,\n47,102,111,114,109,62,10,32,32,99,111,110,118,101,114,115,105,111,110,97,98,111,\n117,116,32,116,104,101,32,60,47,112,62,60,47,100,105,118,62,105,110,116,101,103,\n114,97,116,101,100,34,32,108,97,110,103,61,34,101,110,80,111,114,116,117,103,117\n,101,115,101,115,117,98,115,116,105,116,117,116,101,105,110,100,105,118,105,100,\n117,97,108,105,109,112,111,115,115,105,98,108,101,109,117,108,116,105,109,101,\n100,105,97,97,108,109,111,115,116,32,97,108,108,112,120,32,115,111,108,105,100,\n32,35,97,112,97,114,116,32,102,114,111,109,115,117,98,106,101,99,116,32,116,111,\n105,110,32,69,110,103,108,105,115,104,99,114,105,116,105,99,105,122,101,100,101,\n120,99,101,112,116,32,102,111,114,103,117,105,100,101,108,105,110,101,115,111,\n114,105,103,105,110,97,108,108,121,114,101,109,97,114,107,97,98,108,101,116,104,\n101,32,115,101,99,111,110,100,104,50,32,99,108,97,115,115,61,34,60,97,32,116,105\n,116,108,101,61,34,40,105,110,99,108,117,100,105,110,103,112,97,114,97,109,101,\n116,101,114,115,112,114,111,104,105,98,105,116,101,100,61,32,34,104,116,116,112,\n58,47,47,100,105,99,116,105,111,110,97,114,121,112,101,114,99,101,112,116,105,\n111,110,114,101,118,111,108,117,116,105,111,110,102,111,117,110,100,97,116,105,\n111,110,112,120,59,104,101,105,103,104,116,58,115,117,99,99,101,115,115,102,117,\n108,115,117,112,112,111,114,116,101,114,115,109,105,108,108,101,110,110,105,117,\n109,104,105,115,32,102,97,116,104,101,114,116,104,101,32,38,113,117,111,116,59,\n110,111,45,114,101,112,101,97,116,59,99,111,109,109,101,114,99,105,97,108,105,\n110,100,117,115,116,114,105,97,108,101,110,99,111,117,114,97,103,101,100,97,109,\n111,117,110,116,32,111,102,32,117,110,111,102,102,105,99,105,97,108,101,102,102,\n105,99,105,101,110,99,121,82,101,102,101,114,101,110,99,101,115,99,111,111,114,\n100,105,110,97,116,101,100,105,115,99,108,97,105,109,101,114,101,120,112,101,100\n,105,116,105,111,110,100,101,118,101,108,111,112,105,110,103,99,97,108,99,117,\n108,97,116,101,100,115,105,109,112,108,105,102,105,101,100,108,101,103,105,116,\n105,109,97,116,101,115,117,98,115,116,114,105,110,103,40,48,34,32,99,108,97,115,\n115,61,34,99,111,109,112,108,101,116,101,108,121,105,108,108,117,115,116,114,97,\n116,101,102,105,118,101,32,121,101,97,114,115,105,110,115,116,114,117,109,101,\n110,116,80,117,98,108,105,115,104,105,110,103,49,34,32,99,108,97,115,115,61,34,\n112,115,121,99,104,111,108,111,103,121,99,111,110,102,105,100,101,110,99,101,110\n,117,109,98,101,114,32,111,102,32,97,98,115,101,110,99,101,32,111,102,102,111,99\n,117,115,101,100,32,111,110,106,111,105,110,101,100,32,116,104,101,115,116,114,\n117,99,116,117,114,101,115,112,114,101,118,105,111,117,115,108,121,62,60,47,105,\n102,114,97,109,101,62,111,110,99,101,32,97,103,97,105,110,98,117,116,32,114,97,\n116,104,101,114,105,109,109,105,103,114,97,110,116,115,111,102,32,99,111,117,114\n,115,101,44,97,32,103,114,111,117,112,32,111,102,76,105,116,101,114,97,116,117,\n114,101,85,110,108,105,107,101,32,116,104,101,60,47,97,62,38,110,98,115,112,59,\n10,102,117,110,99,116,105,111,110,32,105,116,32,119,97,115,32,116,104,101,67,111\n,110,118,101,110,116,105,111,110,97,117,116,111,109,111,98,105,108,101,80,114,\n111,116,101,115,116,97,110,116,97,103,103,114,101,115,115,105,118,101,97,102,116\n,101,114,32,116,104,101,32,83,105,109,105,108,97,114,108,121,44,34,32,47,62,60,\n47,100,105,118,62,99,111,108,108,101,99,116,105,111,110,13,10,102,117,110,99,116\n,105,111,110,118,105,115,105,98,105,108,105,116,121,116,104,101,32,117,115,101,\n32,111,102,118,111,108,117,110,116,101,101,114,115,97,116,116,114,97,99,116,105,\n111,110,117,110,100,101,114,32,116,104,101,32,116,104,114,101,97,116,101,110,101\n,100,42,60,33,91,67,68,65,84,65,91,105,109,112,111,114,116,97,110,99,101,105,110\n,32,103,101,110,101,114,97,108,116,104,101,32,108,97,116,116,101,114,60,47,102,\n111,114,109,62,10,60,47,46,105,110,100,101,120,79,102,40,39,105,32,61,32,48,59,\n32,105,32,60,100,105,102,102,101,114,101,110,99,101,100,101,118,111,116,101,100,\n32,116,111,116,114,97,100,105,116,105,111,110,115,115,101,97,114,99,104,32,102,\n111,114,117,108,116,105,109,97,116,101,108,121,116,111,117,114,110,97,109,101,\n110,116,97,116,116,114,105,98,117,116,101,115,115,111,45,99,97,108,108,101,100,\n32,125,10,60,47,115,116,121,108,101,62,101,118,97,108,117,97,116,105,111,110,101\n,109,112,104,97,115,105,122,101,100,97,99,99,101,115,115,105,98,108,101,60,47,\n115,101,99,116,105,111,110,62,115,117,99,99,101,115,115,105,111,110,97,108,111,\n110,103,32,119,105,116,104,77,101,97,110,119,104,105,108,101,44,105,110,100,117,\n115,116,114,105,101,115,60,47,97,62,60,98,114,32,47,62,104,97,115,32,98,101,99,\n111,109,101,97,115,112,101,99,116,115,32,111,102,84,101,108,101,118,105,115,105,\n111,110,115,117,102,102,105,99,105,101,110,116,98,97,115,107,101,116,98,97,108,\n108,98,111,116,104,32,115,105,100,101,115,99,111,110,116,105,110,117,105,110,103\n,97,110,32,97,114,116,105,99,108,101,60,105,109,103,32,97,108,116,61,34,97,100,\n118,101,110,116,117,114,101,115,104,105,115,32,109,111,116,104,101,114,109,97,\n110,99,104,101,115,116,101,114,112,114,105,110,99,105,112,108,101,115,112,97,114\n,116,105,99,117,108,97,114,99,111,109,109,101,110,116,97,114,121,101,102,102,101\n,99,116,115,32,111,102,100,101,99,105,100,101,100,32,116,111,34,62,60,115,116,\n114,111,110,103,62,112,117,98,108,105,115,104,101,114,115,74,111,117,114,110,97,\n108,32,111,102,100,105,102,102,105,99,117,108,116,121,102,97,99,105,108,105,116,\n97,116,101,97,99,99,101,112,116,97,98,108,101,115,116,121,108,101,46,99,115,115,\n34,9,102,117,110,99,116,105,111,110,32,105,110,110,111,118,97,116,105,111,110,62\n,67,111,112,121,114,105,103,104,116,115,105,116,117,97,116,105,111,110,115,119,\n111,117,108,100,32,104,97,118,101,98,117,115,105,110,101,115,115,101,115,68,105,\n99,116,105,111,110,97,114,121,115,116,97,116,101,109,101,110,116,115,111,102,116\n,101,110,32,117,115,101,100,112,101,114,115,105,115,116,101,110,116,105,110,32,\n74,97,110,117,97,114,121,99,111,109,112,114,105,115,105,110,103,60,47,116,105,\n116,108,101,62,10,9,100,105,112,108,111,109,97,116,105,99,99,111,110,116,97,105,\n110,105,110,103,112,101,114,102,111,114,109,105,110,103,101,120,116,101,110,115,\n105,111,110,115,109,97,121,32,110,111,116,32,98,101,99,111,110,99,101,112,116,32\n,111,102,32,111,110,99,108,105,99,107,61,34,73,116,32,105,115,32,97,108,115,111,\n102,105,110,97,110,99,105,97,108,32,109,97,107,105,110,103,32,116,104,101,76,117\n,120,101,109,98,111,117,114,103,97,100,100,105,116,105,111,110,97,108,97,114,101\n,32,99,97,108,108,101,100,101,110,103,97,103,101,100,32,105,110,34,115,99,114,\n105,112,116,34,41,59,98,117,116,32,105,116,32,119,97,115,101,108,101,99,116,114,\n111,110,105,99,111,110,115,117,98,109,105,116,61,34,10,60,33,45,45,32,69,110,100\n,32,101,108,101,99,116,114,105,99,97,108,111,102,102,105,99,105,97,108,108,121,\n115,117,103,103,101,115,116,105,111,110,116,111,112,32,111,102,32,116,104,101,\n117,110,108,105,107,101,32,116,104,101,65,117,115,116,114,97,108,105,97,110,79,\n114,105,103,105,110,97,108,108,121,114,101,102,101,114,101,110,99,101,115,10,60,\n47,104,101,97,100,62,13,10,114,101,99,111,103,110,105,115,101,100,105,110,105,\n116,105,97,108,105,122,101,108,105,109,105,116,101,100,32,116,111,65,108,101,120\n,97,110,100,114,105,97,114,101,116,105,114,101,109,101,110,116,65,100,118,101,\n110,116,117,114,101,115,102,111,117,114,32,121,101,97,114,115,10,10,38,108,116,\n59,33,45,45,32,105,110,99,114,101,97,115,105,110,103,100,101,99,111,114,97,116,\n105,111,110,104,51,32,99,108,97,115,115,61,34,111,114,105,103,105,110,115,32,111\n,102,111,98,108,105,103,97,116,105,111,110,114,101,103,117,108,97,116,105,111,\n110,99,108,97,115,115,105,102,105,101,100,40,102,117,110,99,116,105,111,110,40,\n97,100,118,97,110,116,97,103,101,115,98,101,105,110,103,32,116,104,101,32,104,\n105,115,116,111,114,105,97,110,115,60,98,97,115,101,32,104,114,101,102,114,101,\n112,101,97,116,101,100,108,121,119,105,108,108,105,110,103,32,116,111,99,111,109\n,112,97,114,97,98,108,101,100,101,115,105,103,110,97,116,101,100,110,111,109,105\n,110,97,116,105,111,110,102,117,110,99,116,105,111,110,97,108,105,110,115,105,\n100,101,32,116,104,101,114,101,118,101,108,97,116,105,111,110,101,110,100,32,111\n,102,32,116,104,101,115,32,102,111,114,32,116,104,101,32,97,117,116,104,111,114,\n105,122,101,100,114,101,102,117,115,101,100,32,116,111,116,97,107,101,32,112,108\n,97,99,101,97,117,116,111,110,111,109,111,117,115,99,111,109,112,114,111,109,105\n,115,101,112,111,108,105,116,105,99,97,108,32,114,101,115,116,97,117,114,97,110,\n116,116,119,111,32,111,102,32,116,104,101,70,101,98,114,117,97,114,121,32,50,113\n,117,97,108,105,116,121,32,111,102,115,119,102,111,98,106,101,99,116,46,117,110,\n100,101,114,115,116,97,110,100,110,101,97,114,108,121,32,97,108,108,119,114,105,\n116,116,101,110,32,98,121,105,110,116,101,114,118,105,101,119,115,34,32,119,105,\n100,116,104,61,34,49,119,105,116,104,100,114,97,119,97,108,102,108,111,97,116,58\n,108,101,102,116,105,115,32,117,115,117,97,108,108,121,99,97,110,100,105,100,97,\n116,101,115,110,101,119,115,112,97,112,101,114,115,109,121,115,116,101,114,105,\n111,117,115,68,101,112,97,114,116,109,101,110,116,98,101,115,116,32,107,110,111,\n119,110,112,97,114,108,105,97,109,101,110,116,115,117,112,112,114,101,115,115,\n101,100,99,111,110,118,101,110,105,101,110,116,114,101,109,101,109,98,101,114,\n101,100,100,105,102,102,101,114,101,110,116,32,115,121,115,116,101,109,97,116,\n105,99,104,97,115,32,108,101,100,32,116,111,112,114,111,112,97,103,97,110,100,97\n,99,111,110,116,114,111,108,108,101,100,105,110,102,108,117,101,110,99,101,115,\n99,101,114,101,109,111,110,105,97,108,112,114,111,99,108,97,105,109,101,100,80,\n114,111,116,101,99,116,105,111,110,108,105,32,99,108,97,115,115,61,34,83,99,105,\n101,110,116,105,102,105,99,99,108,97,115,115,61,34,110,111,45,116,114,97,100,101\n,109,97,114,107,115,109,111,114,101,32,116,104,97,110,32,119,105,100,101,115,112\n,114,101,97,100,76,105,98,101,114,97,116,105,111,110,116,111,111,107,32,112,108,\n97,99,101,100,97,121,32,111,102,32,116,104,101,97,115,32,108,111,110,103,32,97,\n115,105,109,112,114,105,115,111,110,101,100,65,100,100,105,116,105,111,110,97,\n108,10,60,104,101,97,100,62,10,60,109,76,97,98,111,114,97,116,111,114,121,78,111\n,118,101,109,98,101,114,32,50,101,120,99,101,112,116,105,111,110,115,73,110,100,\n117,115,116,114,105,97,108,118,97,114,105,101,116,121,32,111,102,102,108,111,97,\n116,58,32,108,101,102,68,117,114,105,110,103,32,116,104,101,97,115,115,101,115,\n115,109,101,110,116,104,97,118,101,32,98,101,101,110,32,100,101,97,108,115,32,\n119,105,116,104,83,116,97,116,105,115,116,105,99,115,111,99,99,117,114,114,101,\n110,99,101,47,117,108,62,60,47,100,105,118,62,99,108,101,97,114,102,105,120,34,\n62,116,104,101,32,112,117,98,108,105,99,109,97,110,121,32,121,101,97,114,115,119\n,104,105,99,104,32,119,101,114,101,111,118,101,114,32,116,105,109,101,44,115,121\n,110,111,110,121,109,111,117,115,99,111,110,116,101,110,116,34,62,10,112,114,101\n,115,117,109,97,98,108,121,104,105,115,32,102,97,109,105,108,121,117,115,101,114\n,65,103,101,110,116,46,117,110,101,120,112,101,99,116,101,100,105,110,99,108,117\n,100,105,110,103,32,99,104,97,108,108,101,110,103,101,100,97,32,109,105,110,111,\n114,105,116,121,117,110,100,101,102,105,110,101,100,34,98,101,108,111,110,103,\n115,32,116,111,116,97,107,101,110,32,102,114,111,109,105,110,32,79,99,116,111,98\n,101,114,112,111,115,105,116,105,111,110,58,32,115,97,105,100,32,116,111,32,98,\n101,114,101,108,105,103,105,111,117,115,32,70,101,100,101,114,97,116,105,111,110\n,32,114,111,119,115,112,97,110,61,34,111,110,108,121,32,97,32,102,101,119,109,\n101,97,110,116,32,116,104,97,116,108,101,100,32,116,111,32,116,104,101,45,45,62,\n13,10,60,100,105,118,32,60,102,105,101,108,100,115,101,116,62,65,114,99,104,98,\n105,115,104,111,112,32,99,108,97,115,115,61,34,110,111,98,101,105,110,103,32,117\n,115,101,100,97,112,112,114,111,97,99,104,101,115,112,114,105,118,105,108,101,\n103,101,115,110,111,115,99,114,105,112,116,62,10,114,101,115,117,108,116,115,32,\n105,110,109,97,121,32,98,101,32,116,104,101,69,97,115,116,101,114,32,101,103,103\n,109,101,99,104,97,110,105,115,109,115,114,101,97,115,111,110,97,98,108,101,80,\n111,112,117,108,97,116,105,111,110,67,111,108,108,101,99,116,105,111,110,115,101\n,108,101,99,116,101,100,34,62,110,111,115,99,114,105,112,116,62,13,47,105,110,\n100,101,120,46,112,104,112,97,114,114,105,118,97,108,32,111,102,45,106,115,115,\n100,107,39,41,41,59,109,97,110,97,103,101,100,32,116,111,105,110,99,111,109,112,\n108,101,116,101,99,97,115,117,97,108,116,105,101,115,99,111,109,112,108,101,116,\n105,111,110,67,104,114,105,115,116,105,97,110,115,83,101,112,116,101,109,98,101,\n114,32,97,114,105,116,104,109,101,116,105,99,112,114,111,99,101,100,117,114,101,\n115,109,105,103,104,116,32,104,97,118,101,80,114,111,100,117,99,116,105,111,110,\n105,116,32,97,112,112,101,97,114,115,80,104,105,108,111,115,111,112,104,121,102,\n114,105,101,110,100,115,104,105,112,108,101,97,100,105,110,103,32,116,111,103,\n105,118,105,110,103,32,116,104,101,116,111,119,97,114,100,32,116,104,101,103,117\n,97,114,97,110,116,101,101,100,100,111,99,117,109,101,110,116,101,100,99,111,108\n,111,114,58,35,48,48,48,118,105,100,101,111,32,103,97,109,101,99,111,109,109,105\n,115,115,105,111,110,114,101,102,108,101,99,116,105,110,103,99,104,97,110,103,\n101,32,116,104,101,97,115,115,111,99,105,97,116,101,100,115,97,110,115,45,115,\n101,114,105,102,111,110,107,101,121,112,114,101,115,115,59,32,112,97,100,100,105\n,110,103,58,72,101,32,119,97,115,32,116,104,101,117,110,100,101,114,108,121,105,\n110,103,116,121,112,105,99,97,108,108,121,32,44,32,97,110,100,32,116,104,101,32,\n115,114,99,69,108,101,109,101,110,116,115,117,99,99,101,115,115,105,118,101,115,\n105,110,99,101,32,116,104,101,32,115,104,111,117,108,100,32,98,101,32,110,101,\n116,119,111,114,107,105,110,103,97,99,99,111,117,110,116,105,110,103,117,115,101\n,32,111,102,32,116,104,101,108,111,119,101,114,32,116,104,97,110,115,104,111,119\n,115,32,116,104,97,116,60,47,115,112,97,110,62,10,9,9,99,111,109,112,108,97,105,\n110,116,115,99,111,110,116,105,110,117,111,117,115,113,117,97,110,116,105,116,\n105,101,115,97,115,116,114,111,110,111,109,101,114,104,101,32,100,105,100,32,110\n,111,116,100,117,101,32,116,111,32,105,116,115,97,112,112,108,105,101,100,32,116\n,111,97,110,32,97,118,101,114,97,103,101,101,102,102,111,114,116,115,32,116,111,\n116,104,101,32,102,117,116,117,114,101,97,116,116,101,109,112,116,32,116,111,84,\n104,101,114,101,102,111,114,101,44,99,97,112,97,98,105,108,105,116,121,82,101,\n112,117,98,108,105,99,97,110,119,97,115,32,102,111,114,109,101,100,69,108,101,99\n,116,114,111,110,105,99,107,105,108,111,109,101,116,101,114,115,99,104,97,108,\n108,101,110,103,101,115,112,117,98,108,105,115,104,105,110,103,116,104,101,32,\n102,111,114,109,101,114,105,110,100,105,103,101,110,111,117,115,100,105,114,101,\n99,116,105,111,110,115,115,117,98,115,105,100,105,97,114,121,99,111,110,115,112,\n105,114,97,99,121,100,101,116,97,105,108,115,32,111,102,97,110,100,32,105,110,32\n,116,104,101,97,102,102,111,114,100,97,98,108,101,115,117,98,115,116,97,110,99,\n101,115,114,101,97,115,111,110,32,102,111,114,99,111,110,118,101,110,116,105,111\n,110,105,116,101,109,116,121,112,101,61,34,97,98,115,111,108,117,116,101,108,121\n,115,117,112,112,111,115,101,100,108,121,114,101,109,97,105,110,101,100,32,97,97\n,116,116,114,97,99,116,105,118,101,116,114,97,118,101,108,108,105,110,103,115,\n101,112,97,114,97,116,101,108,121,102,111,99,117,115,101,115,32,111,110,101,108,\n101,109,101,110,116,97,114,121,97,112,112,108,105,99,97,98,108,101,102,111,117,\n110,100,32,116,104,97,116,115,116,121,108,101,115,104,101,101,116,109,97,110,117\n,115,99,114,105,112,116,115,116,97,110,100,115,32,102,111,114,32,110,111,45,114,\n101,112,101,97,116,40,115,111,109,101,116,105,109,101,115,67,111,109,109,101,114\n,99,105,97,108,105,110,32,65,109,101,114,105,99,97,117,110,100,101,114,116,97,\n107,101,110,113,117,97,114,116,101,114,32,111,102,97,110,32,101,120,97,109,112,\n108,101,112,101,114,115,111,110,97,108,108,121,105,110,100,101,120,46,112,104,\n112,63,60,47,98,117,116,116,111,110,62,10,112,101,114,99,101,110,116,97,103,101,\n98,101,115,116,45,107,110,111,119,110,99,114,101,97,116,105,110,103,32,97,34,32,\n100,105,114,61,34,108,116,114,76,105,101,117,116,101,110,97,110,116,10,60,100,\n105,118,32,105,100,61,34,116,104,101,121,32,119,111,117,108,100,97,98,105,108,\n105,116,121,32,111,102,109,97,100,101,32,117,112,32,111,102,110,111,116,101,100,\n32,116,104,97,116,99,108,101,97,114,32,116,104,97,116,97,114,103,117,101,32,116,\n104,97,116,116,111,32,97,110,111,116,104,101,114,99,104,105,108,100,114,101,110,\n39,115,112,117,114,112,111,115,101,32,111,102,102,111,114,109,117,108,97,116,101\n,100,98,97,115,101,100,32,117,112,111,110,116,104,101,32,114,101,103,105,111,110\n,115,117,98,106,101,99,116,32,111,102,112,97,115,115,101,110,103,101,114,115,112\n,111,115,115,101,115,115,105,111,110,46,10,10,73,110,32,116,104,101,32,66,101,\n102,111,114,101,32,116,104,101,97,102,116,101,114,119,97,114,100,115,99,117,114,\n114,101,110,116,108,121,32,97,99,114,111,115,115,32,116,104,101,115,99,105,101,\n110,116,105,102,105,99,99,111,109,109,117,110,105,116,121,46,99,97,112,105,116,\n97,108,105,115,109,105,110,32,71,101,114,109,97,110,121,114,105,103,104,116,45,\n119,105,110,103,116,104,101,32,115,121,115,116,101,109,83,111,99,105,101,116,121\n,32,111,102,112,111,108,105,116,105,99,105,97,110,100,105,114,101,99,116,105,111\n,110,58,119,101,110,116,32,111,110,32,116,111,114,101,109,111,118,97,108,32,111,\n102,32,78,101,119,32,89,111,114,107,32,97,112,97,114,116,109,101,110,116,115,105\n,110,100,105,99,97,116,105,111,110,100,117,114,105,110,103,32,116,104,101,117,\n110,108,101,115,115,32,116,104,101,104,105,115,116,111,114,105,99,97,108,104,97,\n100,32,98,101,101,110,32,97,100,101,102,105,110,105,116,105,118,101,105,110,103,\n114,101,100,105,101,110,116,97,116,116,101,110,100,97,110,99,101,67,101,110,116,\n101,114,32,102,111,114,112,114,111,109,105,110,101,110,99,101,114,101,97,100,121\n,83,116,97,116,101,115,116,114,97,116,101,103,105,101,115,98,117,116,32,105,110,\n32,116,104,101,97,115,32,112,97,114,116,32,111,102,99,111,110,115,116,105,116,\n117,116,101,99,108,97,105,109,32,116,104,97,116,108,97,98,111,114,97,116,111,114\n,121,99,111,109,112,97,116,105,98,108,101,102,97,105,108,117,114,101,32,111,102,\n44,32,115,117,99,104,32,97,115,32,98,101,103,97,110,32,119,105,116,104,117,115,\n105,110,103,32,116,104,101,32,116,111,32,112,114,111,118,105,100,101,102,101,97,\n116,117,114,101,32,111,102,102,114,111,109,32,119,104,105,99,104,47,34,32,99,108\n,97,115,115,61,34,103,101,111,108,111,103,105,99,97,108,115,101,118,101,114,97,\n108,32,111,102,100,101,108,105,98,101,114,97,116,101,105,109,112,111,114,116,97,\n110,116,32,104,111,108,100,115,32,116,104,97,116,105,110,103,38,113,117,111,116,\n59,32,118,97,108,105,103,110,61,116,111,112,116,104,101,32,71,101,114,109,97,110\n,111,117,116,115,105,100,101,32,111,102,110,101,103,111,116,105,97,116,101,100,\n104,105,115,32,99,97,114,101,101,114,115,101,112,97,114,97,116,105,111,110,105,\n100,61,34,115,101,97,114,99,104,119,97,115,32,99,97,108,108,101,100,116,104,101,\n32,102,111,117,114,116,104,114,101,99,114,101,97,116,105,111,110,111,116,104,101\n,114,32,116,104,97,110,112,114,101,118,101,110,116,105,111,110,119,104,105,108,\n101,32,116,104,101,32,101,100,117,99,97,116,105,111,110,44,99,111,110,110,101,99\n,116,105,110,103,97,99,99,117,114,97,116,101,108,121,119,101,114,101,32,98,117,\n105,108,116,119,97,115,32,107,105,108,108,101,100,97,103,114,101,101,109,101,110\n,116,115,109,117,99,104,32,109,111,114,101,32,68,117,101,32,116,111,32,116,104,\n101,119,105,100,116,104,58,32,49,48,48,115,111,109,101,32,111,116,104,101,114,75\n,105,110,103,100,111,109,32,111,102,116,104,101,32,101,110,116,105,114,101,102,\n97,109,111,117,115,32,102,111,114,116,111,32,99,111,110,110,101,99,116,111,98,\n106,101,99,116,105,118,101,115,116,104,101,32,70,114,101,110,99,104,112,101,111,\n112,108,101,32,97,110,100,102,101,97,116,117,114,101,100,34,62,105,115,32,115,97\n,105,100,32,116,111,115,116,114,117,99,116,117,114,97,108,114,101,102,101,114,\n101,110,100,117,109,109,111,115,116,32,111,102,116,101,110,97,32,115,101,112,97,\n114,97,116,101,45,62,10,60,100,105,118,32,105,100,32,79,102,102,105,99,105,97,\n108,32,119,111,114,108,100,119,105,100,101,46,97,114,105,97,45,108,97,98,101,108\n,116,104,101,32,112,108,97,110,101,116,97,110,100,32,105,116,32,119,97,115,100,\n34,32,118,97,108,117,101,61,34,108,111,111,107,105,110,103,32,97,116,98,101,110,\n101,102,105,99,105,97,108,97,114,101,32,105,110,32,116,104,101,109,111,110,105,\n116,111,114,105,110,103,114,101,112,111,114,116,101,100,108,121,116,104,101,32,\n109,111,100,101,114,110,119,111,114,107,105,110,103,32,111,110,97,108,108,111,\n119,101,100,32,116,111,119,104,101,114,101,32,116,104,101,32,105,110,110,111,118\n,97,116,105,118,101,60,47,97,62,60,47,100,105,118,62,115,111,117,110,100,116,114\n,97,99,107,115,101,97,114,99,104,70,111,114,109,116,101,110,100,32,116,111,32,98\n,101,105,110,112,117,116,32,105,100,61,34,111,112,101,110,105,110,103,32,111,102\n,114,101,115,116,114,105,99,116,101,100,97,100,111,112,116,101,100,32,98,121,97,\n100,100,114,101,115,115,105,110,103,116,104,101,111,108,111,103,105,97,110,109,\n101,116,104,111,100,115,32,111,102,118,97,114,105,97,110,116,32,111,102,67,104,\n114,105,115,116,105,97,110,32,118,101,114,121,32,108,97,114,103,101,97,117,116,\n111,109,111,116,105,118,101,98,121,32,102,97,114,32,116,104,101,114,97,110,103,\n101,32,102,114,111,109,112,117,114,115,117,105,116,32,111,102,102,111,108,108,\n111,119,32,116,104,101,98,114,111,117,103,104,116,32,116,111,105,110,32,69,110,\n103,108,97,110,100,97,103,114,101,101,32,116,104,97,116,97,99,99,117,115,101,100\n,32,111,102,99,111,109,101,115,32,102,114,111,109,112,114,101,118,101,110,116,\n105,110,103,100,105,118,32,115,116,121,108,101,61,104,105,115,32,111,114,32,104,\n101,114,116,114,101,109,101,110,100,111,117,115,102,114,101,101,100,111,109,32,\n111,102,99,111,110,99,101,114,110,105,110,103,48,32,49,101,109,32,49,101,109,59,\n66,97,115,107,101,116,98,97,108,108,47,115,116,121,108,101,46,99,115,115,97,110,\n32,101,97,114,108,105,101,114,101,118,101,110,32,97,102,116,101,114,47,34,32,116\n,105,116,108,101,61,34,46,99,111,109,47,105,110,100,101,120,116,97,107,105,110,\n103,32,116,104,101,112,105,116,116,115,98,117,114,103,104,99,111,110,116,101,110\n,116,34,62,13,60,115,99,114,105,112,116,62,40,102,116,117,114,110,101,100,32,111\n,117,116,104,97,118,105,110,103,32,116,104,101,60,47,115,112,97,110,62,13,10,32,\n111,99,99,97,115,105,111,110,97,108,98,101,99,97,117,115,101,32,105,116,115,116,\n97,114,116,101,100,32,116,111,112,104,121,115,105,99,97,108,108,121,62,60,47,100\n,105,118,62,10,32,32,99,114,101,97,116,101,100,32,98,121,67,117,114,114,101,110,\n116,108,121,44,32,98,103,99,111,108,111,114,61,34,116,97,98,105,110,100,101,120,\n61,34,100,105,115,97,115,116,114,111,117,115,65,110,97,108,121,116,105,99,115,32\n,97,108,115,111,32,104,97,115,32,97,62,60,100,105,118,32,105,100,61,34,60,47,115\n,116,121,108,101,62,10,60,99,97,108,108,101,100,32,102,111,114,115,105,110,103,\n101,114,32,97,110,100,46,115,114,99,32,61,32,34,47,47,118,105,111,108,97,116,105\n,111,110,115,116,104,105,115,32,112,111,105,110,116,99,111,110,115,116,97,110,\n116,108,121,105,115,32,108,111,99,97,116,101,100,114,101,99,111,114,100,105,110,\n103,115,100,32,102,114,111,109,32,116,104,101,110,101,100,101,114,108,97,110,100\n,115,112,111,114,116,117,103,117,195,170,115,215,162,215,145,215,168,215,153,215\n,170,217,129,216,167,216,177,216,179,219,140,100,101,115,97,114,114,111,108,108,\n111,99,111,109,101,110,116,97,114,105,111,101,100,117,99,97,99,105,195,179,110,\n115,101,112,116,105,101,109,98,114,101,114,101,103,105,115,116,114,97,100,111,\n100,105,114,101,99,99,105,195,179,110,117,98,105,99,97,99,105,195,179,110,112,\n117,98,108,105,99,105,100,97,100,114,101,115,112,117,101,115,116,97,115,114,101,\n115,117,108,116,97,100,111,115,105,109,112,111,114,116,97,110,116,101,114,101,\n115,101,114,118,97,100,111,115,97,114,116,195,173,99,117,108,111,115,100,105,102\n,101,114,101,110,116,101,115,115,105,103,117,105,101,110,116,101,115,114,101,112\n,195,186,98,108,105,99,97,115,105,116,117,97,99,105,195,179,110,109,105,110,105,\n115,116,101,114,105,111,112,114,105,118,97,99,105,100,97,100,100,105,114,101,99,\n116,111,114,105,111,102,111,114,109,97,99,105,195,179,110,112,111,98,108,97,99,\n105,195,179,110,112,114,101,115,105,100,101,110,116,101,99,111,110,116,101,110,\n105,100,111,115,97,99,99,101,115,111,114,105,111,115,116,101,99,104,110,111,114,\n97,116,105,112,101,114,115,111,110,97,108,101,115,99,97,116,101,103,111,114,195,\n173,97,101,115,112,101,99,105,97,108,101,115,100,105,115,112,111,110,105,98,108,\n101,97,99,116,117,97,108,105,100,97,100,114,101,102,101,114,101,110,99,105,97,\n118,97,108,108,97,100,111,108,105,100,98,105,98,108,105,111,116,101,99,97,114,\n101,108,97,99,105,111,110,101,115,99,97,108,101,110,100,97,114,105,111,112,111,\n108,195,173,116,105,99,97,115,97,110,116,101,114,105,111,114,101,115,100,111,99,\n117,109,101,110,116,111,115,110,97,116,117,114,97,108,101,122,97,109,97,116,101,\n114,105,97,108,101,115,100,105,102,101,114,101,110,99,105,97,101,99,111,110,195,\n179,109,105,99,97,116,114,97,110,115,112,111,114,116,101,114,111,100,114,195,173\n,103,117,101,122,112,97,114,116,105,99,105,112,97,114,101,110,99,117,101,110,116\n,114,97,110,100,105,115,99,117,115,105,195,179,110,101,115,116,114,117,99,116,\n117,114,97,102,117,110,100,97,99,105,195,179,110,102,114,101,99,117,101,110,116,\n101,115,112,101,114,109,97,110,101,110,116,101,116,111,116,97,108,109,101,110,\n116,101,208,188,208,190,208,182,208,189,208,190,208,177,209,131,208,180,208,181,\n209,130,208,188,208,190,208,182,208,181,209,130,208,178,209,128,208,181,208,188,\n209,143,209,130,208,176,208,186,208,182,208,181,209,135,209,130,208,190,208,177,\n209,139,208,177,208,190,208,187,208,181,208,181,208,190,209,135,208,181,208,189,\n209,140,209,141,209,130,208,190,208,179,208,190,208,186,208,190,208,179,208,180,\n208,176,208,191,208,190,209,129,208,187,208,181,208,178,209,129,208,181,208,179,\n208,190,209,129,208,176,208,185,209,130,208,181,209,135,208,181,209,128,208,181,\n208,183,208,188,208,190,208,179,209,131,209,130,209,129,208,176,208,185,209,130,\n208,176,208,182,208,184,208,183,208,189,208,184,208,188,208,181,208,182,208,180,\n209,131,208,177,209,131,208,180,209,131,209,130,208,159,208,190,208,184,209,129,\n208,186,208,183,208,180,208,181,209,129,209,140,208,178,208,184,208,180,208,181,\n208,190,209,129,208,178,209,143,208,183,208,184,208,189,209,131,208,182,208,189,\n208,190,209,129,208,178,208,190,208,181,208,185,208,187,209,142,208,180,208,181,\n208,185,208,191,208,190,209,128,208,189,208,190,208,188,208,189,208,190,208,179,\n208,190,208,180,208,181,209,130,208,181,208,185,209,129,208,178,208,190,208,184,\n209,133,208,191,209,128,208,176,208,178,208,176,209,130,208,176,208,186,208,190,\n208,185,208,188,208,181,209,129,209,130,208,190,208,184,208,188,208,181,208,181,\n209,130,208,182,208,184,208,183,208,189,209,140,208,190,208,180,208,189,208,190,\n208,185,208,187,209,131,209,135,209,136,208,181,208,191,208,181,209,128,208,181,\n208,180,209,135,208,176,209,129,209,130,208,184,209,135,208,176,209,129,209,130,\n209,140,209,128,208,176,208,177,208,190,209,130,208,189,208,190,208,178,209,139,\n209,133,208,191,209,128,208,176,208,178,208,190,209,129,208,190,208,177,208,190,\n208,185,208,191,208,190,209,130,208,190,208,188,208,188,208,181,208,189,208,181,\n208,181,209,135,208,184,209,129,208,187,208,181,208,189,208,190,208,178,209,139,\n208,181,209,131,209,129,208,187,209,131,208,179,208,190,208,186,208,190,208,187,\n208,190,208,189,208,176,208,183,208,176,208,180,209,130,208,176,208,186,208,190,\n208,181,209,130,208,190,208,179,208,180,208,176,208,191,208,190,209,135,209,130,\n208,184,208,159,208,190,209,129,208,187,208,181,209,130,208,176,208,186,208,184,\n208,181,208,189,208,190,208,178,209,139,208,185,209,129,209,130,208,190,208,184,\n209,130,209,130,208,176,208,186,208,184,209,133,209,129,209,128,208,176,208,183,\n209,131,208,161,208,176,208,189,208,186,209,130,209,132,208,190,209,128,209,131,\n208,188,208,154,208,190,208,179,208,180,208,176,208,186,208,189,208,184,208,179,\n208,184,209,129,208,187,208,190,208,178,208,176,208,189,208,176,209,136,208,181,\n208,185,208,189,208,176,208,185,209,130,208,184,209,129,208,178,208,190,208,184,\n208,188,209,129,208,178,209,143,208,183,209,140,208,187,209,142,208,177,208,190,\n208,185,209,135,208,176,209,129,209,130,208,190,209,129,209,128,208,181,208,180,\n208,184,208,154,209,128,208,190,208,188,208,181,208,164,208,190,209,128,209,131,\n208,188,209,128,209,139,208,189,208,186,208,181,209,129,209,130,208,176,208,187,\n208,184,208,191,208,190,208,184,209,129,208,186,209,130,209,139,209,129,209,143,\n209,135,208,188,208,181,209,129,209,143,209,134,209,134,208,181,208,189,209,130,\n209,128,209,130,209,128,209,131,208,180,208,176,209,129,208,176,208,188,209,139,\n209,133,209,128,209,139,208,189,208,186,208,176,208,157,208,190,208,178,209,139,\n208,185,209,135,208,176,209,129,208,190,208,178,208,188,208,181,209,129,209,130,\n208,176,209,132,208,184,208,187,209,140,208,188,208,188,208,176,209,128,209,130,\n208,176,209,129,209,130,209,128,208,176,208,189,208,188,208,181,209,129,209,130,\n208,181,209,130,208,181,208,186,209,129,209,130,208,189,208,176,209,136,208,184,\n209,133,208,188,208,184,208,189,209,131,209,130,208,184,208,188,208,181,208,189,\n208,184,208,184,208,188,208,181,209,142,209,130,208,189,208,190,208,188,208,181,\n209,128,208,179,208,190,209,128,208,190,208,180,209,129,208,176,208,188,208,190,\n208,188,209,141,209,130,208,190,208,188,209,131,208,186,208,190,208,189,209,134,\n208,181,209,129,208,178,208,190,208,181,208,188,208,186,208,176,208,186,208,190,\n208,185,208,144,209,128,209,133,208,184,208,178,217,133,217,134,216,170,216,175,\n217,137,216,165,216,177,216,179,216,167,217,132,216,177,216,179,216,167,217,132,\n216,169,216,167,217,132,216,185,216,167,217,133,217,131,216,170,216,168,217,135,\n216,167,216,168,216,177,216,167,217,133,216,172,216,167,217,132,217,138,217,136,\n217,133,216,167,217,132,216,181,217,136,216,177,216,172,216,175,217,138,216,175,\n216,169,216,167,217,132,216,185,216,182,217,136,216,165,216,182,216,167,217,129,\n216,169,216,167,217,132,217,130,216,179,217,133,216,167,217,132,216,185,216,167,\n216,168,216,170,216,173,217,133,217,138,217,132,217,133,217,132,217,129,216,167,\n216,170,217,133,217,132,216,170,217,130,217,137,216,170,216,185,216,175,217,138,\n217,132,216,167,217,132,216,180,216,185,216,177,216,163,216,174,216,168,216,167,\n216,177,216,170,216,183,217,136,217,138,216,177,216,185,217,132,217,138,217,131,\n217,133,216,165,216,177,217,129,216,167,217,130,216,183,217,132,216,168,216,167,\n216,170,216,167,217,132,217,132,216,186,216,169,216,170,216,177,216,170,217,138,\n216,168,216,167,217,132,217,134,216,167,216,179,216,167,217,132,216,180,217,138,\n216,174,217,133,217,134,216,170,216,175,217,138,216,167,217,132,216,185,216,177,\n216,168,216,167,217,132,217,130,216,181,216,181,216,167,217,129,217,132,216,167,\n217,133,216,185,217,132,217,138,217,135,216,167,216,170,216,173,216,175,217,138,\n216,171,216,167,217,132,217,132,217,135,217,133,216,167,217,132,216,185,217,133,\n217,132,217,133,217,131,216,170,216,168,216,169,217,138,217,133,217,131,217,134,\n217,131,216,167,217,132,216,183,217,129,217,132,217,129,217,138,216,175,217,138,\n217,136,216,165,216,175,216,167,216,177,216,169,216,170,216,167,216,177,217,138,\n216,174,216,167,217,132,216,181,216,173,216,169,216,170,216,179,216,172,217,138,\n217,132,216,167,217,132,217,136,217,130,216,170,216,185,217,134,216,175,217,133,\n216,167,217,133,216,175,217,138,217,134,216,169,216,170,216,181,217,133,217,138,\n217,133,216,163,216,177,216,180,217,138,217,129,216,167,217,132,216,176,217,138,\n217,134,216,185,216,177,216,168,217,138,216,169,216,168,217,136,216,167,216,168,\n216,169,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,179,217,129,\n216,177,217,133,216,180,216,167,217,131,217,132,216,170,216,185,216,167,217,132,\n217,137,216,167,217,132,216,163,217,136,217,132,216,167,217,132,216,179,217,134,\n216,169,216,172,216,167,217,133,216,185,216,169,216,167,217,132,216,181,216,173,\n217,129,216,167,217,132,216,175,217,138,217,134,217,131,217,132,217,133,216,167,\n216,170,216,167,217,132,216,174,216,167,216,181,216,167,217,132,217,133,217,132,\n217,129,216,163,216,185,216,182,216,167,216,161,217,131,216,170,216,167,216,168,\n216,169,216,167,217,132,216,174,217,138,216,177,216,177,216,179,216,167,216,166,\n217,132,216,167,217,132,217,130,217,132,216,168,216,167,217,132,216,163,216,175,\n216,168,217,133,217,130,216,167,216,183,216,185,217,133,216,177,216,167,216,179,\n217,132,217,133,217,134,216,183,217,130,216,169,216,167,217,132,217,131,216,170,\n216,168,216,167,217,132,216,177,216,172,217,132,216,167,216,180,216,170,216,177,\n217,131,216,167,217,132,217,130,216,175,217,133,217,138,216,185,216,183,217,138,\n217,131,115,66,121,84,97,103,78,97,109,101,40,46,106,112,103,34,32,97,108,116,61\n,34,49,112,120,32,115,111,108,105,100,32,35,46,103,105,102,34,32,97,108,116,61,\n34,116,114,97,110,115,112,97,114,101,110,116,105,110,102,111,114,109,97,116,105,\n111,110,97,112,112,108,105,99,97,116,105,111,110,34,32,111,110,99,108,105,99,107\n,61,34,101,115,116,97,98,108,105,115,104,101,100,97,100,118,101,114,116,105,115,\n105,110,103,46,112,110,103,34,32,97,108,116,61,34,101,110,118,105,114,111,110,\n109,101,110,116,112,101,114,102,111,114,109,97,110,99,101,97,112,112,114,111,112\n,114,105,97,116,101,38,97,109,112,59,109,100,97,115,104,59,105,109,109,101,100,\n105,97,116,101,108,121,60,47,115,116,114,111,110,103,62,60,47,114,97,116,104,101\n,114,32,116,104,97,110,116,101,109,112,101,114,97,116,117,114,101,100,101,118,\n101,108,111,112,109,101,110,116,99,111,109,112,101,116,105,116,105,111,110,112,\n108,97,99,101,104,111,108,100,101,114,118,105,115,105,98,105,108,105,116,121,58,\n99,111,112,121,114,105,103,104,116,34,62,48,34,32,104,101,105,103,104,116,61,34,\n101,118,101,110,32,116,104,111,117,103,104,114,101,112,108,97,99,101,109,101,110\n,116,100,101,115,116,105,110,97,116,105,111,110,67,111,114,112,111,114,97,116,\n105,111,110,60,117,108,32,99,108,97,115,115,61,34,65,115,115,111,99,105,97,116,\n105,111,110,105,110,100,105,118,105,100,117,97,108,115,112,101,114,115,112,101,\n99,116,105,118,101,115,101,116,84,105,109,101,111,117,116,40,117,114,108,40,104,\n116,116,112,58,47,47,109,97,116,104,101,109,97,116,105,99,115,109,97,114,103,105\n,110,45,116,111,112,58,101,118,101,110,116,117,97,108,108,121,32,100,101,115,99,\n114,105,112,116,105,111,110,41,32,110,111,45,114,101,112,101,97,116,99,111,108,\n108,101,99,116,105,111,110,115,46,74,80,71,124,116,104,117,109,98,124,112,97,114\n,116,105,99,105,112,97,116,101,47,104,101,97,100,62,60,98,111,100,121,102,108,\n111,97,116,58,108,101,102,116,59,60,108,105,32,99,108,97,115,115,61,34,104,117,\n110,100,114,101,100,115,32,111,102,10,10,72,111,119,101,118,101,114,44,32,99,111\n,109,112,111,115,105,116,105,111,110,99,108,101,97,114,58,98,111,116,104,59,99,\n111,111,112,101,114,97,116,105,111,110,119,105,116,104,105,110,32,116,104,101,32\n,108,97,98,101,108,32,102,111,114,61,34,98,111,114,100,101,114,45,116,111,112,58\n,78,101,119,32,90,101,97,108,97,110,100,114,101,99,111,109,109,101,110,100,101,\n100,112,104,111,116,111,103,114,97,112,104,121,105,110,116,101,114,101,115,116,\n105,110,103,38,108,116,59,115,117,112,38,103,116,59,99,111,110,116,114,111,118,\n101,114,115,121,78,101,116,104,101,114,108,97,110,100,115,97,108,116,101,114,110\n,97,116,105,118,101,109,97,120,108,101,110,103,116,104,61,34,115,119,105,116,122\n,101,114,108,97,110,100,68,101,118,101,108,111,112,109,101,110,116,101,115,115,\n101,110,116,105,97,108,108,121,10,10,65,108,116,104,111,117,103,104,32,60,47,116\n,101,120,116,97,114,101,97,62,116,104,117,110,100,101,114,98,105,114,100,114,101\n,112,114,101,115,101,110,116,101,100,38,97,109,112,59,110,100,97,115,104,59,115,\n112,101,99,117,108,97,116,105,111,110,99,111,109,109,117,110,105,116,105,101,115\n,108,101,103,105,115,108,97,116,105,111,110,101,108,101,99,116,114,111,110,105,\n99,115,10,9,60,100,105,118,32,105,100,61,34,105,108,108,117,115,116,114,97,116,\n101,100,101,110,103,105,110,101,101,114,105,110,103,116,101,114,114,105,116,111,\n114,105,101,115,97,117,116,104,111,114,105,116,105,101,115,100,105,115,116,114,\n105,98,117,116,101,100,54,34,32,104,101,105,103,104,116,61,34,115,97,110,115,45,\n115,101,114,105,102,59,99,97,112,97,98,108,101,32,111,102,32,100,105,115,97,112,\n112,101,97,114,101,100,105,110,116,101,114,97,99,116,105,118,101,108,111,111,107\n,105,110,103,32,102,111,114,105,116,32,119,111,117,108,100,32,98,101,65,102,103,\n104,97,110,105,115,116,97,110,119,97,115,32,99,114,101,97,116,101,100,77,97,116,\n104,46,102,108,111,111,114,40,115,117,114,114,111,117,110,100,105,110,103,99,97,\n110,32,97,108,115,111,32,98,101,111,98,115,101,114,118,97,116,105,111,110,109,97\n,105,110,116,101,110,97,110,99,101,101,110,99,111,117,110,116,101,114,101,100,60\n,104,50,32,99,108,97,115,115,61,34,109,111,114,101,32,114,101,99,101,110,116,105\n,116,32,104,97,115,32,98,101,101,110,105,110,118,97,115,105,111,110,32,111,102,\n41,46,103,101,116,84,105,109,101,40,41,102,117,110,100,97,109,101,110,116,97,108\n,68,101,115,112,105,116,101,32,116,104,101,34,62,60,100,105,118,32,105,100,61,34\n,105,110,115,112,105,114,97,116,105,111,110,101,120,97,109,105,110,97,116,105,\n111,110,112,114,101,112,97,114,97,116,105,111,110,101,120,112,108,97,110,97,116,\n105,111,110,60,105,110,112,117,116,32,105,100,61,34,60,47,97,62,60,47,115,112,97\n,110,62,118,101,114,115,105,111,110,115,32,111,102,105,110,115,116,114,117,109,\n101,110,116,115,98,101,102,111,114,101,32,116,104,101,32,32,61,32,39,104,116,116\n,112,58,47,47,68,101,115,99,114,105,112,116,105,111,110,114,101,108,97,116,105,\n118,101,108,121,32,46,115,117,98,115,116,114,105,110,103,40,101,97,99,104,32,111\n,102,32,116,104,101,101,120,112,101,114,105,109,101,110,116,115,105,110,102,108,\n117,101,110,116,105,97,108,105,110,116,101,103,114,97,116,105,111,110,109,97,110\n,121,32,112,101,111,112,108,101,100,117,101,32,116,111,32,116,104,101,32,99,111,\n109,98,105,110,97,116,105,111,110,100,111,32,110,111,116,32,104,97,118,101,77,\n105,100,100,108,101,32,69,97,115,116,60,110,111,115,99,114,105,112,116,62,60,99,\n111,112,121,114,105,103,104,116,34,32,112,101,114,104,97,112,115,32,116,104,101,\n105,110,115,116,105,116,117,116,105,111,110,105,110,32,68,101,99,101,109,98,101,\n114,97,114,114,97,110,103,101,109,101,110,116,109,111,115,116,32,102,97,109,111,\n117,115,112,101,114,115,111,110,97,108,105,116,121,99,114,101,97,116,105,111,110\n,32,111,102,108,105,109,105,116,97,116,105,111,110,115,101,120,99,108,117,115,\n105,118,101,108,121,115,111,118,101,114,101,105,103,110,116,121,45,99,111,110,\n116,101,110,116,34,62,10,60,116,100,32,99,108,97,115,115,61,34,117,110,100,101,\n114,103,114,111,117,110,100,112,97,114,97,108,108,101,108,32,116,111,100,111,99,\n116,114,105,110,101,32,111,102,111,99,99,117,112,105,101,100,32,98,121,116,101,\n114,109,105,110,111,108,111,103,121,82,101,110,97,105,115,115,97,110,99,101,97,\n32,110,117,109,98,101,114,32,111,102,115,117,112,112,111,114,116,32,102,111,114,\n101,120,112,108,111,114,97,116,105,111,110,114,101,99,111,103,110,105,116,105,\n111,110,112,114,101,100,101,99,101,115,115,111,114,60,105,109,103,32,115,114,99,\n61,34,47,60,104,49,32,99,108,97,115,115,61,34,112,117,98,108,105,99,97,116,105,\n111,110,109,97,121,32,97,108,115,111,32,98,101,115,112,101,99,105,97,108,105,122\n,101,100,60,47,102,105,101,108,100,115,101,116,62,112,114,111,103,114,101,115,\n115,105,118,101,109,105,108,108,105,111,110,115,32,111,102,115,116,97,116,101,\n115,32,116,104,97,116,101,110,102,111,114,99,101,109,101,110,116,97,114,111,117,\n110,100,32,116,104,101,32,111,110,101,32,97,110,111,116,104,101,114,46,112,97,\n114,101,110,116,78,111,100,101,97,103,114,105,99,117,108,116,117,114,101,65,108,\n116,101,114,110,97,116,105,118,101,114,101,115,101,97,114,99,104,101,114,115,116\n,111,119,97,114,100,115,32,116,104,101,77,111,115,116,32,111,102,32,116,104,101,\n109,97,110,121,32,111,116,104,101,114,32,40,101,115,112,101,99,105,97,108,108,\n121,60,116,100,32,119,105,100,116,104,61,34,59,119,105,100,116,104,58,49,48,48,\n37,105,110,100,101,112,101,110,100,101,110,116,60,104,51,32,99,108,97,115,115,61\n,34,32,111,110,99,104,97,110,103,101,61,34,41,46,97,100,100,67,108,97,115,115,40\n,105,110,116,101,114,97,99,116,105,111,110,79,110,101,32,111,102,32,116,104,101,\n32,100,97,117,103,104,116,101,114,32,111,102,97,99,99,101,115,115,111,114,105,\n101,115,98,114,97,110,99,104,101,115,32,111,102,13,10,60,100,105,118,32,105,100,\n61,34,116,104,101,32,108,97,114,103,101,115,116,100,101,99,108,97,114,97,116,105\n,111,110,114,101,103,117,108,97,116,105,111,110,115,73,110,102,111,114,109,97,\n116,105,111,110,116,114,97,110,115,108,97,116,105,111,110,100,111,99,117,109,101\n,110,116,97,114,121,105,110,32,111,114,100,101,114,32,116,111,34,62,10,60,104,\n101,97,100,62,10,60,34,32,104,101,105,103,104,116,61,34,49,97,99,114,111,115,115\n,32,116,104,101,32,111,114,105,101,110,116,97,116,105,111,110,41,59,60,47,115,99\n,114,105,112,116,62,105,109,112,108,101,109,101,110,116,101,100,99,97,110,32,98,\n101,32,115,101,101,110,116,104,101,114,101,32,119,97,115,32,97,100,101,109,111,\n110,115,116,114,97,116,101,99,111,110,116,97,105,110,101,114,34,62,99,111,110,\n110,101,99,116,105,111,110,115,116,104,101,32,66,114,105,116,105,115,104,119,97,\n115,32,119,114,105,116,116,101,110,33,105,109,112,111,114,116,97,110,116,59,112,\n120,59,32,109,97,114,103,105,110,45,102,111,108,108,111,119,101,100,32,98,121,97\n,98,105,108,105,116,121,32,116,111,32,99,111,109,112,108,105,99,97,116,101,100,\n100,117,114,105,110,103,32,116,104,101,32,105,109,109,105,103,114,97,116,105,111\n,110,97,108,115,111,32,99,97,108,108,101,100,60,104,52,32,99,108,97,115,115,61,\n34,100,105,115,116,105,110,99,116,105,111,110,114,101,112,108,97,99,101,100,32,\n98,121,103,111,118,101,114,110,109,101,110,116,115,108,111,99,97,116,105,111,110\n,32,111,102,105,110,32,78,111,118,101,109,98,101,114,119,104,101,116,104,101,114\n,32,116,104,101,60,47,112,62,10,60,47,100,105,118,62,97,99,113,117,105,115,105,\n116,105,111,110,99,97,108,108,101,100,32,116,104,101,32,112,101,114,115,101,99,\n117,116,105,111,110,100,101,115,105,103,110,97,116,105,111,110,123,102,111,110,\n116,45,115,105,122,101,58,97,112,112,101,97,114,101,100,32,105,110,105,110,118,\n101,115,116,105,103,97,116,101,101,120,112,101,114,105,101,110,99,101,100,109,\n111,115,116,32,108,105,107,101,108,121,119,105,100,101,108,121,32,117,115,101,\n100,100,105,115,99,117,115,115,105,111,110,115,112,114,101,115,101,110,99,101,32\n,111,102,32,40,100,111,99,117,109,101,110,116,46,101,120,116,101,110,115,105,118\n,101,108,121,73,116,32,104,97,115,32,98,101,101,110,105,116,32,100,111,101,115,\n32,110,111,116,99,111,110,116,114,97,114,121,32,116,111,105,110,104,97,98,105,\n116,97,110,116,115,105,109,112,114,111,118,101,109,101,110,116,115,99,104,111,\n108,97,114,115,104,105,112,99,111,110,115,117,109,112,116,105,111,110,105,110,\n115,116,114,117,99,116,105,111,110,102,111,114,32,101,120,97,109,112,108,101,111\n,110,101,32,111,114,32,109,111,114,101,112,120,59,32,112,97,100,100,105,110,103,\n116,104,101,32,99,117,114,114,101,110,116,97,32,115,101,114,105,101,115,32,111,\n102,97,114,101,32,117,115,117,97,108,108,121,114,111,108,101,32,105,110,32,116,\n104,101,112,114,101,118,105,111,117,115,108,121,32,100,101,114,105,118,97,116,\n105,118,101,115,101,118,105,100,101,110,99,101,32,111,102,101,120,112,101,114,\n105,101,110,99,101,115,99,111,108,111,114,115,99,104,101,109,101,115,116,97,116,\n101,100,32,116,104,97,116,99,101,114,116,105,102,105,99,97,116,101,60,47,97,62,\n60,47,100,105,118,62,10,32,115,101,108,101,99,116,101,100,61,34,104,105,103,104,\n32,115,99,104,111,111,108,114,101,115,112,111,110,115,101,32,116,111,99,111,109,\n102,111,114,116,97,98,108,101,97,100,111,112,116,105,111,110,32,111,102,116,104,\n114,101,101,32,121,101,97,114,115,116,104,101,32,99,111,117,110,116,114,121,105,\n110,32,70,101,98,114,117,97,114,121,115,111,32,116,104,97,116,32,116,104,101,112\n,101,111,112,108,101,32,119,104,111,32,112,114,111,118,105,100,101,100,32,98,121\n,60,112,97,114,97,109,32,110,97,109,101,97,102,102,101,99,116,101,100,32,98,121,\n105,110,32,116,101,114,109,115,32,111,102,97,112,112,111,105,110,116,109,101,110\n,116,73,83,79,45,56,56,53,57,45,49,34,119,97,115,32,98,111,114,110,32,105,110,\n104,105,115,116,111,114,105,99,97,108,32,114,101,103,97,114,100,101,100,32,97,\n115,109,101,97,115,117,114,101,109,101,110,116,105,115,32,98,97,115,101,100,32,\n111,110,32,97,110,100,32,111,116,104,101,114,32,58,32,102,117,110,99,116,105,111\n,110,40,115,105,103,110,105,102,105,99,97,110,116,99,101,108,101,98,114,97,116,\n105,111,110,116,114,97,110,115,109,105,116,116,101,100,47,106,115,47,106,113,117\n,101,114,121,46,105,115,32,107,110,111,119,110,32,97,115,116,104,101,111,114,101\n,116,105,99,97,108,32,116,97,98,105,110,100,101,120,61,34,105,116,32,99,111,117,\n108,100,32,98,101,60,110,111,115,99,114,105,112,116,62,10,104,97,118,105,110,103\n,32,98,101,101,110,13,10,60,104,101,97,100,62,13,10,60,32,38,113,117,111,116,59,\n84,104,101,32,99,111,109,112,105,108,97,116,105,111,110,104,101,32,104,97,100,32\n,98,101,101,110,112,114,111,100,117,99,101,100,32,98,121,112,104,105,108,111,115\n,111,112,104,101,114,99,111,110,115,116,114,117,99,116,101,100,105,110,116,101,\n110,100,101,100,32,116,111,97,109,111,110,103,32,111,116,104,101,114,99,111,109,\n112,97,114,101,100,32,116,111,116,111,32,115,97,121,32,116,104,97,116,69,110,103\n,105,110,101,101,114,105,110,103,97,32,100,105,102,102,101,114,101,110,116,114,\n101,102,101,114,114,101,100,32,116,111,100,105,102,102,101,114,101,110,99,101,\n115,98,101,108,105,101,102,32,116,104,97,116,112,104,111,116,111,103,114,97,112,\n104,115,105,100,101,110,116,105,102,121,105,110,103,72,105,115,116,111,114,121,\n32,111,102,32,82,101,112,117,98,108,105,99,32,111,102,110,101,99,101,115,115,97,\n114,105,108,121,112,114,111,98,97,98,105,108,105,116,121,116,101,99,104,110,105,\n99,97,108,108,121,108,101,97,118,105,110,103,32,116,104,101,115,112,101,99,116,\n97,99,117,108,97,114,102,114,97,99,116,105,111,110,32,111,102,101,108,101,99,116\n,114,105,99,105,116,121,104,101,97,100,32,111,102,32,116,104,101,114,101,115,116\n,97,117,114,97,110,116,115,112,97,114,116,110,101,114,115,104,105,112,101,109,\n112,104,97,115,105,115,32,111,110,109,111,115,116,32,114,101,99,101,110,116,115,\n104,97,114,101,32,119,105,116,104,32,115,97,121,105,110,103,32,116,104,97,116,\n102,105,108,108,101,100,32,119,105,116,104,100,101,115,105,103,110,101,100,32,\n116,111,105,116,32,105,115,32,111,102,116,101,110,34,62,60,47,105,102,114,97,109\n,101,62,97,115,32,102,111,108,108,111,119,115,58,109,101,114,103,101,100,32,119,\n105,116,104,116,104,114,111,117,103,104,32,116,104,101,99,111,109,109,101,114,99\n,105,97,108,32,112,111,105,110,116,101,100,32,111,117,116,111,112,112,111,114,\n116,117,110,105,116,121,118,105,101,119,32,111,102,32,116,104,101,114,101,113,\n117,105,114,101,109,101,110,116,100,105,118,105,115,105,111,110,32,111,102,112,\n114,111,103,114,97,109,109,105,110,103,104,101,32,114,101,99,101,105,118,101,100\n,115,101,116,73,110,116,101,114,118,97,108,34,62,60,47,115,112,97,110,62,60,47,\n105,110,32,78,101,119,32,89,111,114,107,97,100,100,105,116,105,111,110,97,108,32\n,99,111,109,112,114,101,115,115,105,111,110,10,10,60,100,105,118,32,105,100,61,\n34,105,110,99,111,114,112,111,114,97,116,101,59,60,47,115,99,114,105,112,116,62,\n60,97,116,116,97,99,104,69,118,101,110,116,98,101,99,97,109,101,32,116,104,101,\n32,34,32,116,97,114,103,101,116,61,34,95,99,97,114,114,105,101,100,32,111,117,\n116,83,111,109,101,32,111,102,32,116,104,101,115,99,105,101,110,99,101,32,97,110\n,100,116,104,101,32,116,105,109,101,32,111,102,67,111,110,116,97,105,110,101,114\n,34,62,109,97,105,110,116,97,105,110,105,110,103,67,104,114,105,115,116,111,112,\n104,101,114,77,117,99,104,32,111,102,32,116,104,101,119,114,105,116,105,110,103,\n115,32,111,102,34,32,104,101,105,103,104,116,61,34,50,115,105,122,101,32,111,102\n,32,116,104,101,118,101,114,115,105,111,110,32,111,102,32,109,105,120,116,117,\n114,101,32,111,102,32,98,101,116,119,101,101,110,32,116,104,101,69,120,97,109,\n112,108,101,115,32,111,102,101,100,117,99,97,116,105,111,110,97,108,99,111,109,\n112,101,116,105,116,105,118,101,32,111,110,115,117,98,109,105,116,61,34,100,105,\n114,101,99,116,111,114,32,111,102,100,105,115,116,105,110,99,116,105,118,101,47,\n68,84,68,32,88,72,84,77,76,32,114,101,108,97,116,105,110,103,32,116,111,116,101,\n110,100,101,110,99,121,32,116,111,112,114,111,118,105,110,99,101,32,111,102,119,\n104,105,99,104,32,119,111,117,108,100,100,101,115,112,105,116,101,32,116,104,101\n,115,99,105,101,110,116,105,102,105,99,32,108,101,103,105,115,108,97,116,117,114\n,101,46,105,110,110,101,114,72,84,77,76,32,97,108,108,101,103,97,116,105,111,110\n,115,65,103,114,105,99,117,108,116,117,114,101,119,97,115,32,117,115,101,100,32,\n105,110,97,112,112,114,111,97,99,104,32,116,111,105,110,116,101,108,108,105,103,\n101,110,116,121,101,97,114,115,32,108,97,116,101,114,44,115,97,110,115,45,115,\n101,114,105,102,100,101,116,101,114,109,105,110,105,110,103,80,101,114,102,111,\n114,109,97,110,99,101,97,112,112,101,97,114,97,110,99,101,115,44,32,119,104,105,\n99,104,32,105,115,32,102,111,117,110,100,97,116,105,111,110,115,97,98,98,114,101\n,118,105,97,116,101,100,104,105,103,104,101,114,32,116,104,97,110,115,32,102,114\n,111,109,32,116,104,101,32,105,110,100,105,118,105,100,117,97,108,32,99,111,109,\n112,111,115,101,100,32,111,102,115,117,112,112,111,115,101,100,32,116,111,99,108\n,97,105,109,115,32,116,104,97,116,97,116,116,114,105,98,117,116,105,111,110,102,\n111,110,116,45,115,105,122,101,58,49,101,108,101,109,101,110,116,115,32,111,102,\n72,105,115,116,111,114,105,99,97,108,32,104,105,115,32,98,114,111,116,104,101,\n114,97,116,32,116,104,101,32,116,105,109,101,97,110,110,105,118,101,114,115,97,\n114,121,103,111,118,101,114,110,101,100,32,98,121,114,101,108,97,116,101,100,32,\n116,111,32,117,108,116,105,109,97,116,101,108,121,32,105,110,110,111,118,97,116,\n105,111,110,115,105,116,32,105,115,32,115,116,105,108,108,99,97,110,32,111,110,\n108,121,32,98,101,100,101,102,105,110,105,116,105,111,110,115,116,111,71,77,84,\n83,116,114,105,110,103,65,32,110,117,109,98,101,114,32,111,102,105,109,103,32,99\n,108,97,115,115,61,34,69,118,101,110,116,117,97,108,108,121,44,119,97,115,32,99,\n104,97,110,103,101,100,111,99,99,117,114,114,101,100,32,105,110,110,101,105,103,\n104,98,111,114,105,110,103,100,105,115,116,105,110,103,117,105,115,104,119,104,\n101,110,32,104,101,32,119,97,115,105,110,116,114,111,100,117,99,105,110,103,116,\n101,114,114,101,115,116,114,105,97,108,77,97,110,121,32,111,102,32,116,104,101,\n97,114,103,117,101,115,32,116,104,97,116,97,110,32,65,109,101,114,105,99,97,110,\n99,111,110,113,117,101,115,116,32,111,102,119,105,100,101,115,112,114,101,97,100\n,32,119,101,114,101,32,107,105,108,108,101,100,115,99,114,101,101,110,32,97,110,\n100,32,73,110,32,111,114,100,101,114,32,116,111,101,120,112,101,99,116,101,100,\n32,116,111,100,101,115,99,101,110,100,97,110,116,115,97,114,101,32,108,111,99,97\n,116,101,100,108,101,103,105,115,108,97,116,105,118,101,103,101,110,101,114,97,\n116,105,111,110,115,32,98,97,99,107,103,114,111,117,110,100,109,111,115,116,32,\n112,101,111,112,108,101,121,101,97,114,115,32,97,102,116,101,114,116,104,101,114\n,101,32,105,115,32,110,111,116,104,101,32,104,105,103,104,101,115,116,102,114,\n101,113,117,101,110,116,108,121,32,116,104,101,121,32,100,111,32,110,111,116,97,\n114,103,117,101,100,32,116,104,97,116,115,104,111,119,101,100,32,116,104,97,116,\n112,114,101,100,111,109,105,110,97,110,116,116,104,101,111,108,111,103,105,99,97\n,108,98,121,32,116,104,101,32,116,105,109,101,99,111,110,115,105,100,101,114,105\n,110,103,115,104,111,114,116,45,108,105,118,101,100,60,47,115,112,97,110,62,60,\n47,97,62,99,97,110,32,98,101,32,117,115,101,100,118,101,114,121,32,108,105,116,\n116,108,101,111,110,101,32,111,102,32,116,104,101,32,104,97,100,32,97,108,114,\n101,97,100,121,105,110,116,101,114,112,114,101,116,101,100,99,111,109,109,117,\n110,105,99,97,116,101,102,101,97,116,117,114,101,115,32,111,102,103,111,118,101,\n114,110,109,101,110,116,44,60,47,110,111,115,99,114,105,112,116,62,101,110,116,\n101,114,101,100,32,116,104,101,34,32,104,101,105,103,104,116,61,34,51,73,110,100\n,101,112,101,110,100,101,110,116,112,111,112,117,108,97,116,105,111,110,115,108,\n97,114,103,101,45,115,99,97,108,101,46,32,65,108,116,104,111,117,103,104,32,117,\n115,101,100,32,105,110,32,116,104,101,100,101,115,116,114,117,99,116,105,111,110\n,112,111,115,115,105,98,105,108,105,116,121,115,116,97,114,116,105,110,103,32,\n105,110,116,119,111,32,111,114,32,109,111,114,101,101,120,112,114,101,115,115,\n105,111,110,115,115,117,98,111,114,100,105,110,97,116,101,108,97,114,103,101,114\n,32,116,104,97,110,104,105,115,116,111,114,121,32,97,110,100,60,47,111,112,116,\n105,111,110,62,13,10,67,111,110,116,105,110,101,110,116,97,108,101,108,105,109,\n105,110,97,116,105,110,103,119,105,108,108,32,110,111,116,32,98,101,112,114,97,\n99,116,105,99,101,32,111,102,105,110,32,102,114,111,110,116,32,111,102,115,105,\n116,101,32,111,102,32,116,104,101,101,110,115,117,114,101,32,116,104,97,116,116,\n111,32,99,114,101,97,116,101,32,97,109,105,115,115,105,115,115,105,112,112,105,\n112,111,116,101,110,116,105,97,108,108,121,111,117,116,115,116,97,110,100,105,\n110,103,98,101,116,116,101,114,32,116,104,97,110,119,104,97,116,32,105,115,32,\n110,111,119,115,105,116,117,97,116,101,100,32,105,110,109,101,116,97,32,110,97,\n109,101,61,34,84,114,97,100,105,116,105,111,110,97,108,115,117,103,103,101,115,\n116,105,111,110,115,84,114,97,110,115,108,97,116,105,111,110,116,104,101,32,102,\n111,114,109,32,111,102,97,116,109,111,115,112,104,101,114,105,99,105,100,101,111\n,108,111,103,105,99,97,108,101,110,116,101,114,112,114,105,115,101,115,99,97,108\n,99,117,108,97,116,105,110,103,101,97,115,116,32,111,102,32,116,104,101,114,101,\n109,110,97,110,116,115,32,111,102,112,108,117,103,105,110,115,112,97,103,101,47,\n105,110,100,101,120,46,112,104,112,63,114,101,109,97,105,110,101,100,32,105,110,\n116,114,97,110,115,102,111,114,109,101,100,72,101,32,119,97,115,32,97,108,115,\n111,119,97,115,32,97,108,114,101,97,100,121,115,116,97,116,105,115,116,105,99,97\n,108,105,110,32,102,97,118,111,114,32,111,102,77,105,110,105,115,116,114,121,32,\n111,102,109,111,118,101,109,101,110,116,32,111,102,102,111,114,109,117,108,97,\n116,105,111,110,105,115,32,114,101,113,117,105,114,101,100,60,108,105,110,107,32\n,114,101,108,61,34,84,104,105,115,32,105,115,32,116,104,101,32,60,97,32,104,114,\n101,102,61,34,47,112,111,112,117,108,97,114,105,122,101,100,105,110,118,111,108,\n118,101,100,32,105,110,97,114,101,32,117,115,101,100,32,116,111,97,110,100,32,\n115,101,118,101,114,97,108,109,97,100,101,32,98,121,32,116,104,101,115,101,101,\n109,115,32,116,111,32,98,101,108,105,107,101,108,121,32,116,104,97,116,80,97,108\n,101,115,116,105,110,105,97,110,110,97,109,101,100,32,97,102,116,101,114,105,116\n,32,104,97,100,32,98,101,101,110,109,111,115,116,32,99,111,109,109,111,110,116,\n111,32,114,101,102,101,114,32,116,111,98,117,116,32,116,104,105,115,32,105,115,\n99,111,110,115,101,99,117,116,105,118,101,116,101,109,112,111,114,97,114,105,108\n,121,73,110,32,103,101,110,101,114,97,108,44,99,111,110,118,101,110,116,105,111,\n110,115,116,97,107,101,115,32,112,108,97,99,101,115,117,98,100,105,118,105,115,\n105,111,110,116,101,114,114,105,116,111,114,105,97,108,111,112,101,114,97,116,\n105,111,110,97,108,112,101,114,109,97,110,101,110,116,108,121,119,97,115,32,108,\n97,114,103,101,108,121,111,117,116,98,114,101,97,107,32,111,102,105,110,32,116,\n104,101,32,112,97,115,116,102,111,108,108,111,119,105,110,103,32,97,32,120,109,\n108,110,115,58,111,103,61,34,62,60,97,32,99,108,97,115,115,61,34,99,108,97,115,\n115,61,34,116,101,120,116,67,111,110,118,101,114,115,105,111,110,32,109,97,121,\n32,98,101,32,117,115,101,100,109,97,110,117,102,97,99,116,117,114,101,97,102,116\n,101,114,32,98,101,105,110,103,99,108,101,97,114,102,105,120,34,62,10,113,117,\n101,115,116,105,111,110,32,111,102,119,97,115,32,101,108,101,99,116,101,100,116,\n111,32,98,101,99,111,109,101,32,97,98,101,99,97,117,115,101,32,111,102,32,115,\n111,109,101,32,112,101,111,112,108,101,105,110,115,112,105,114,101,100,32,98,121\n,115,117,99,99,101,115,115,102,117,108,32,97,32,116,105,109,101,32,119,104,101,\n110,109,111,114,101,32,99,111,109,109,111,110,97,109,111,110,103,115,116,32,116,\n104,101,97,110,32,111,102,102,105,99,105,97,108,119,105,100,116,104,58,49,48,48,\n37,59,116,101,99,104,110,111,108,111,103,121,44,119,97,115,32,97,100,111,112,116\n,101,100,116,111,32,107,101,101,112,32,116,104,101,115,101,116,116,108,101,109,\n101,110,116,115,108,105,118,101,32,98,105,114,116,104,115,105,110,100,101,120,46\n,104,116,109,108,34,67,111,110,110,101,99,116,105,99,117,116,97,115,115,105,103,\n110,101,100,32,116,111,38,97,109,112,59,116,105,109,101,115,59,97,99,99,111,117,\n110,116,32,102,111,114,97,108,105,103,110,61,114,105,103,104,116,116,104,101,32,\n99,111,109,112,97,110,121,97,108,119,97,121,115,32,98,101,101,110,114,101,116,\n117,114,110,101,100,32,116,111,105,110,118,111,108,118,101,109,101,110,116,66,\n101,99,97,117,115,101,32,116,104,101,116,104,105,115,32,112,101,114,105,111,100,\n34,32,110,97,109,101,61,34,113,34,32,99,111,110,102,105,110,101,100,32,116,111,\n97,32,114,101,115,117,108,116,32,111,102,118,97,108,117,101,61,34,34,32,47,62,\n105,115,32,97,99,116,117,97,108,108,121,69,110,118,105,114,111,110,109,101,110,\n116,13,10,60,47,104,101,97,100,62,13,10,67,111,110,118,101,114,115,101,108,121,\n44,62,10,60,100,105,118,32,105,100,61,34,48,34,32,119,105,100,116,104,61,34,49,\n105,115,32,112,114,111,98,97,98,108,121,104,97,118,101,32,98,101,99,111,109,101,\n99,111,110,116,114,111,108,108,105,110,103,116,104,101,32,112,114,111,98,108,101\n,109,99,105,116,105,122,101,110,115,32,111,102,112,111,108,105,116,105,99,105,97\n,110,115,114,101,97,99,104,101,100,32,116,104,101,97,115,32,101,97,114,108,121,\n32,97,115,58,110,111,110,101,59,32,111,118,101,114,60,116,97,98,108,101,32,99,\n101,108,108,118,97,108,105,100,105,116,121,32,111,102,100,105,114,101,99,116,108\n,121,32,116,111,111,110,109,111,117,115,101,100,111,119,110,119,104,101,114,101,\n32,105,116,32,105,115,119,104,101,110,32,105,116,32,119,97,115,109,101,109,98,\n101,114,115,32,111,102,32,114,101,108,97,116,105,111,110,32,116,111,97,99,99,111\n,109,109,111,100,97,116,101,97,108,111,110,103,32,119,105,116,104,32,73,110,32,\n116,104,101,32,108,97,116,101,116,104,101,32,69,110,103,108,105,115,104,100,101,\n108,105,99,105,111,117,115,34,62,116,104,105,115,32,105,115,32,110,111,116,116,\n104,101,32,112,114,101,115,101,110,116,105,102,32,116,104,101,121,32,97,114,101,\n97,110,100,32,102,105,110,97,108,108,121,97,32,109,97,116,116,101,114,32,111,102\n,13,10,9,60,47,100,105,118,62,13,10,13,10,60,47,115,99,114,105,112,116,62,102,97\n,115,116,101,114,32,116,104,97,110,109,97,106,111,114,105,116,121,32,111,102,97,\n102,116,101,114,32,119,104,105,99,104,99,111,109,112,97,114,97,116,105,118,101,\n116,111,32,109,97,105,110,116,97,105,110,105,109,112,114,111,118,101,32,116,104,\n101,97,119,97,114,100,101,100,32,116,104,101,101,114,34,32,99,108,97,115,115,61,\n34,102,114,97,109,101,98,111,114,100,101,114,114,101,115,116,111,114,97,116,105,\n111,110,105,110,32,116,104,101,32,115,97,109,101,97,110,97,108,121,115,105,115,\n32,111,102,116,104,101,105,114,32,102,105,114,115,116,68,117,114,105,110,103,32,\n116,104,101,32,99,111,110,116,105,110,101,110,116,97,108,115,101,113,117,101,110\n,99,101,32,111,102,102,117,110,99,116,105,111,110,40,41,123,102,111,110,116,45,\n115,105,122,101,58,32,119,111,114,107,32,111,110,32,116,104,101,60,47,115,99,114\n,105,112,116,62,10,60,98,101,103,105,110,115,32,119,105,116,104,106,97,118,97,\n115,99,114,105,112,116,58,99,111,110,115,116,105,116,117,101,110,116,119,97,115,\n32,102,111,117,110,100,101,100,101,113,117,105,108,105,98,114,105,117,109,97,115\n,115,117,109,101,32,116,104,97,116,105,115,32,103,105,118,101,110,32,98,121,110,\n101,101,100,115,32,116,111,32,98,101,99,111,111,114,100,105,110,97,116,101,115,\n116,104,101,32,118,97,114,105,111,117,115,97,114,101,32,112,97,114,116,32,111,\n102,111,110,108,121,32,105,110,32,116,104,101,115,101,99,116,105,111,110,115,32,\n111,102,105,115,32,97,32,99,111,109,109,111,110,116,104,101,111,114,105,101,115,\n32,111,102,100,105,115,99,111,118,101,114,105,101,115,97,115,115,111,99,105,97,\n116,105,111,110,101,100,103,101,32,111,102,32,116,104,101,115,116,114,101,110,\n103,116,104,32,111,102,112,111,115,105,116,105,111,110,32,105,110,112,114,101,\n115,101,110,116,45,100,97,121,117,110,105,118,101,114,115,97,108,108,121,116,111\n,32,102,111,114,109,32,116,104,101,98,117,116,32,105,110,115,116,101,97,100,99,\n111,114,112,111,114,97,116,105,111,110,97,116,116,97,99,104,101,100,32,116,111,\n105,115,32,99,111,109,109,111,110,108,121,114,101,97,115,111,110,115,32,102,111,\n114,32,38,113,117,111,116,59,116,104,101,32,99,97,110,32,98,101,32,109,97,100,\n101,119,97,115,32,97,98,108,101,32,116,111,119,104,105,99,104,32,109,101,97,110,\n115,98,117,116,32,100,105,100,32,110,111,116,111,110,77,111,117,115,101,79,118,\n101,114,97,115,32,112,111,115,115,105,98,108,101,111,112,101,114,97,116,101,100,\n32,98,121,99,111,109,105,110,103,32,102,114,111,109,116,104,101,32,112,114,105,\n109,97,114,121,97,100,100,105,116,105,111,110,32,111,102,102,111,114,32,115,101,\n118,101,114,97,108,116,114,97,110,115,102,101,114,114,101,100,97,32,112,101,114,\n105,111,100,32,111,102,97,114,101,32,97,98,108,101,32,116,111,104,111,119,101,\n118,101,114,44,32,105,116,115,104,111,117,108,100,32,104,97,118,101,109,117,99,\n104,32,108,97,114,103,101,114,10,9,60,47,115,99,114,105,112,116,62,97,100,111,\n112,116,101,100,32,116,104,101,112,114,111,112,101,114,116,121,32,111,102,100,\n105,114,101,99,116,101,100,32,98,121,101,102,102,101,99,116,105,118,101,108,121,\n119,97,115,32,98,114,111,117,103,104,116,99,104,105,108,100,114,101,110,32,111,\n102,80,114,111,103,114,97,109,109,105,110,103,108,111,110,103,101,114,32,116,104\n,97,110,109,97,110,117,115,99,114,105,112,116,115,119,97,114,32,97,103,97,105,\n110,115,116,98,121,32,109,101,97,110,115,32,111,102,97,110,100,32,109,111,115,\n116,32,111,102,115,105,109,105,108,97,114,32,116,111,32,112,114,111,112,114,105,\n101,116,97,114,121,111,114,105,103,105,110,97,116,105,110,103,112,114,101,115,\n116,105,103,105,111,117,115,103,114,97,109,109,97,116,105,99,97,108,101,120,112,\n101,114,105,101,110,99,101,46,116,111,32,109,97,107,101,32,116,104,101,73,116,32\n,119,97,115,32,97,108,115,111,105,115,32,102,111,117,110,100,32,105,110,99,111,\n109,112,101,116,105,116,111,114,115,105,110,32,116,104,101,32,85,46,83,46,114,\n101,112,108,97,99,101,32,116,104,101,98,114,111,117,103,104,116,32,116,104,101,\n99,97,108,99,117,108,97,116,105,111,110,102,97,108,108,32,111,102,32,116,104,101\n,116,104,101,32,103,101,110,101,114,97,108,112,114,97,99,116,105,99,97,108,108,\n121,105,110,32,104,111,110,111,114,32,111,102,114,101,108,101,97,115,101,100,32,\n105,110,114,101,115,105,100,101,110,116,105,97,108,97,110,100,32,115,111,109,101\n,32,111,102,107,105,110,103,32,111,102,32,116,104,101,114,101,97,99,116,105,111,\n110,32,116,111,49,115,116,32,69,97,114,108,32,111,102,99,117,108,116,117,114,101\n,32,97,110,100,112,114,105,110,99,105,112,97,108,108,121,60,47,116,105,116,108,\n101,62,10,32,32,116,104,101,121,32,99,97,110,32,98,101,98,97,99,107,32,116,111,\n32,116,104,101,115,111,109,101,32,111,102,32,104,105,115,101,120,112,111,115,117\n,114,101,32,116,111,97,114,101,32,115,105,109,105,108,97,114,102,111,114,109,32,\n111,102,32,116,104,101,97,100,100,70,97,118,111,114,105,116,101,99,105,116,105,\n122,101,110,115,104,105,112,112,97,114,116,32,105,110,32,116,104,101,112,101,111\n,112,108,101,32,119,105,116,104,105,110,32,112,114,97,99,116,105,99,101,116,111,\n32,99,111,110,116,105,110,117,101,38,97,109,112,59,109,105,110,117,115,59,97,112\n,112,114,111,118,101,100,32,98,121,32,116,104,101,32,102,105,114,115,116,32,97,\n108,108,111,119,101,100,32,116,104,101,97,110,100,32,102,111,114,32,116,104,101,\n102,117,110,99,116,105,111,110,105,110,103,112,108,97,121,105,110,103,32,116,104\n,101,115,111,108,117,116,105,111,110,32,116,111,104,101,105,103,104,116,61,34,48\n,34,32,105,110,32,104,105,115,32,98,111,111,107,109,111,114,101,32,116,104,97,\n110,32,97,102,111,108,108,111,119,115,32,116,104,101,99,114,101,97,116,101,100,\n32,116,104,101,112,114,101,115,101,110,99,101,32,105,110,38,110,98,115,112,59,60\n,47,116,100,62,110,97,116,105,111,110,97,108,105,115,116,116,104,101,32,105,100,\n101,97,32,111,102,97,32,99,104,97,114,97,99,116,101,114,119,101,114,101,32,102,\n111,114,99,101,100,32,99,108,97,115,115,61,34,98,116,110,100,97,121,115,32,111,\n102,32,116,104,101,102,101,97,116,117,114,101,100,32,105,110,115,104,111,119,105\n,110,103,32,116,104,101,105,110,116,101,114,101,115,116,32,105,110,105,110,32,\n112,108,97,99,101,32,111,102,116,117,114,110,32,111,102,32,116,104,101,116,104,\n101,32,104,101,97,100,32,111,102,76,111,114,100,32,111,102,32,116,104,101,112,\n111,108,105,116,105,99,97,108,108,121,104,97,115,32,105,116,115,32,111,119,110,\n69,100,117,99,97,116,105,111,110,97,108,97,112,112,114,111,118,97,108,32,111,102\n,115,111,109,101,32,111,102,32,116,104,101,101,97,99,104,32,111,116,104,101,114,\n44,98,101,104,97,118,105,111,114,32,111,102,97,110,100,32,98,101,99,97,117,115,\n101,97,110,100,32,97,110,111,116,104,101,114,97,112,112,101,97,114,101,100,32,\n111,110,114,101,99,111,114,100,101,100,32,105,110,98,108,97,99,107,38,113,117,\n111,116,59,109,97,121,32,105,110,99,108,117,100,101,116,104,101,32,119,111,114,\n108,100,39,115,99,97,110,32,108,101,97,100,32,116,111,114,101,102,101,114,115,32\n,116,111,32,97,98,111,114,100,101,114,61,34,48,34,32,103,111,118,101,114,110,109\n,101,110,116,32,119,105,110,110,105,110,103,32,116,104,101,114,101,115,117,108,\n116,101,100,32,105,110,32,119,104,105,108,101,32,116,104,101,32,87,97,115,104,\n105,110,103,116,111,110,44,116,104,101,32,115,117,98,106,101,99,116,99,105,116,\n121,32,105,110,32,116,104,101,62,60,47,100,105,118,62,13,10,9,9,114,101,102,108,\n101,99,116,32,116,104,101,116,111,32,99,111,109,112,108,101,116,101,98,101,99,97\n,109,101,32,109,111,114,101,114,97,100,105,111,97,99,116,105,118,101,114,101,106\n,101,99,116,101,100,32,98,121,119,105,116,104,111,117,116,32,97,110,121,104,105,\n115,32,102,97,116,104,101,114,44,119,104,105,99,104,32,99,111,117,108,100,99,111\n,112,121,32,111,102,32,116,104,101,116,111,32,105,110,100,105,99,97,116,101,97,\n32,112,111,108,105,116,105,99,97,108,97,99,99,111,117,110,116,115,32,111,102,99,\n111,110,115,116,105,116,117,116,101,115,119,111,114,107,101,100,32,119,105,116,\n104,101,114,60,47,97,62,60,47,108,105,62,111,102,32,104,105,115,32,108,105,102,\n101,97,99,99,111,109,112,97,110,105,101,100,99,108,105,101,110,116,87,105,100,\n116,104,112,114,101,118,101,110,116,32,116,104,101,76,101,103,105,115,108,97,116\n,105,118,101,100,105,102,102,101,114,101,110,116,108,121,116,111,103,101,116,104\n,101,114,32,105,110,104,97,115,32,115,101,118,101,114,97,108,102,111,114,32,97,\n110,111,116,104,101,114,116,101,120,116,32,111,102,32,116,104,101,102,111,117,\n110,100,101,100,32,116,104,101,101,32,119,105,116,104,32,116,104,101,32,105,115,\n32,117,115,101,100,32,102,111,114,99,104,97,110,103,101,100,32,116,104,101,117,\n115,117,97,108,108,121,32,116,104,101,112,108,97,99,101,32,119,104,101,114,101,\n119,104,101,114,101,97,115,32,116,104,101,62,32,60,97,32,104,114,101,102,61,34,\n34,62,60,97,32,104,114,101,102,61,34,116,104,101,109,115,101,108,118,101,115,44,\n97,108,116,104,111,117,103,104,32,104,101,116,104,97,116,32,99,97,110,32,98,101,\n116,114,97,100,105,116,105,111,110,97,108,114,111,108,101,32,111,102,32,116,104,\n101,97,115,32,97,32,114,101,115,117,108,116,114,101,109,111,118,101,67,104,105,\n108,100,100,101,115,105,103,110,101,100,32,98,121,119,101,115,116,32,111,102,32,\n116,104,101,83,111,109,101,32,112,101,111,112,108,101,112,114,111,100,117,99,116\n,105,111,110,44,115,105,100,101,32,111,102,32,116,104,101,110,101,119,115,108,\n101,116,116,101,114,115,117,115,101,100,32,98,121,32,116,104,101,100,111,119,110\n,32,116,111,32,116,104,101,97,99,99,101,112,116,101,100,32,98,121,108,105,118,\n101,32,105,110,32,116,104,101,97,116,116,101,109,112,116,115,32,116,111,111,117,\n116,115,105,100,101,32,116,104,101,102,114,101,113,117,101,110,99,105,101,115,72\n,111,119,101,118,101,114,44,32,105,110,112,114,111,103,114,97,109,109,101,114,\n115,97,116,32,108,101,97,115,116,32,105,110,97,112,112,114,111,120,105,109,97,\n116,101,97,108,116,104,111,117,103,104,32,105,116,119,97,115,32,112,97,114,116,\n32,111,102,97,110,100,32,118,97,114,105,111,117,115,71,111,118,101,114,110,111,\n114,32,111,102,116,104,101,32,97,114,116,105,99,108,101,116,117,114,110,101,100,\n32,105,110,116,111,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,101,99,\n111,110,111,109,121,105,115,32,116,104,101,32,109,111,115,116,109,111,115,116,32\n,119,105,100,101,108,121,119,111,117,108,100,32,108,97,116,101,114,97,110,100,32\n,112,101,114,104,97,112,115,114,105,115,101,32,116,111,32,116,104,101,111,99,99,\n117,114,115,32,119,104,101,110,117,110,100,101,114,32,119,104,105,99,104,99,111,\n110,100,105,116,105,111,110,115,46,116,104,101,32,119,101,115,116,101,114,110,\n116,104,101,111,114,121,32,116,104,97,116,105,115,32,112,114,111,100,117,99,101,\n100,116,104,101,32,99,105,116,121,32,111,102,105,110,32,119,104,105,99,104,32,\n104,101,115,101,101,110,32,105,110,32,116,104,101,116,104,101,32,99,101,110,116,\n114,97,108,98,117,105,108,100,105,110,103,32,111,102,109,97,110,121,32,111,102,\n32,104,105,115,97,114,101,97,32,111,102,32,116,104,101,105,115,32,116,104,101,32\n,111,110,108,121,109,111,115,116,32,111,102,32,116,104,101,109,97,110,121,32,111\n,102,32,116,104,101,116,104,101,32,87,101,115,116,101,114,110,84,104,101,114,101\n,32,105,115,32,110,111,101,120,116,101,110,100,101,100,32,116,111,83,116,97,116,\n105,115,116,105,99,97,108,99,111,108,115,112,97,110,61,50,32,124,115,104,111,114\n,116,32,115,116,111,114,121,112,111,115,115,105,98,108,101,32,116,111,116,111,\n112,111,108,111,103,105,99,97,108,99,114,105,116,105,99,97,108,32,111,102,114,\n101,112,111,114,116,101,100,32,116,111,97,32,67,104,114,105,115,116,105,97,110,\n100,101,99,105,115,105,111,110,32,116,111,105,115,32,101,113,117,97,108,32,116,\n111,112,114,111,98,108,101,109,115,32,111,102,84,104,105,115,32,99,97,110,32,98,\n101,109,101,114,99,104,97,110,100,105,115,101,102,111,114,32,109,111,115,116,32,\n111,102,110,111,32,101,118,105,100,101,110,99,101,101,100,105,116,105,111,110,\n115,32,111,102,101,108,101,109,101,110,116,115,32,105,110,38,113,117,111,116,59,\n46,32,84,104,101,99,111,109,47,105,109,97,103,101,115,47,119,104,105,99,104,32,\n109,97,107,101,115,116,104,101,32,112,114,111,99,101,115,115,114,101,109,97,105,\n110,115,32,116,104,101,108,105,116,101,114,97,116,117,114,101,44,105,115,32,97,\n32,109,101,109,98,101,114,116,104,101,32,112,111,112,117,108,97,114,116,104,101,\n32,97,110,99,105,101,110,116,112,114,111,98,108,101,109,115,32,105,110,116,105,\n109,101,32,111,102,32,116,104,101,100,101,102,101,97,116,101,100,32,98,121,98,\n111,100,121,32,111,102,32,116,104,101,97,32,102,101,119,32,121,101,97,114,115,\n109,117,99,104,32,111,102,32,116,104,101,116,104,101,32,119,111,114,107,32,111,\n102,67,97,108,105,102,111,114,110,105,97,44,115,101,114,118,101,100,32,97,115,32\n,97,103,111,118,101,114,110,109,101,110,116,46,99,111,110,99,101,112,116,115,32,\n111,102,109,111,118,101,109,101,110,116,32,105,110,9,9,60,100,105,118,32,105,100\n,61,34,105,116,34,32,118,97,108,117,101,61,34,108,97,110,103,117,97,103,101,32,\n111,102,97,115,32,116,104,101,121,32,97,114,101,112,114,111,100,117,99,101,100,\n32,105,110,105,115,32,116,104,97,116,32,116,104,101,101,120,112,108,97,105,110,\n32,116,104,101,100,105,118,62,60,47,100,105,118,62,10,72,111,119,101,118,101,114\n,32,116,104,101,108,101,97,100,32,116,111,32,116,104,101,9,60,97,32,104,114,101,\n102,61,34,47,119,97,115,32,103,114,97,110,116,101,100,112,101,111,112,108,101,32\n,104,97,118,101,99,111,110,116,105,110,117,97,108,108,121,119,97,115,32,115,101,\n101,110,32,97,115,97,110,100,32,114,101,108,97,116,101,100,116,104,101,32,114,\n111,108,101,32,111,102,112,114,111,112,111,115,101,100,32,98,121,111,102,32,116,\n104,101,32,98,101,115,116,101,97,99,104,32,111,116,104,101,114,46,67,111,110,115\n,116,97,110,116,105,110,101,112,101,111,112,108,101,32,102,114,111,109,100,105,\n97,108,101,99,116,115,32,111,102,116,111,32,114,101,118,105,115,105,111,110,119,\n97,115,32,114,101,110,97,109,101,100,97,32,115,111,117,114,99,101,32,111,102,116\n,104,101,32,105,110,105,116,105,97,108,108,97,117,110,99,104,101,100,32,105,110,\n112,114,111,118,105,100,101,32,116,104,101,116,111,32,116,104,101,32,119,101,115\n,116,119,104,101,114,101,32,116,104,101,114,101,97,110,100,32,115,105,109,105,\n108,97,114,98,101,116,119,101,101,110,32,116,119,111,105,115,32,97,108,115,111,\n32,116,104,101,69,110,103,108,105,115,104,32,97,110,100,99,111,110,100,105,116,\n105,111,110,115,44,116,104,97,116,32,105,116,32,119,97,115,101,110,116,105,116,\n108,101,100,32,116,111,116,104,101,109,115,101,108,118,101,115,46,113,117,97,110\n,116,105,116,121,32,111,102,114,97,110,115,112,97,114,101,110,99,121,116,104,101\n,32,115,97,109,101,32,97,115,116,111,32,106,111,105,110,32,116,104,101,99,111,\n117,110,116,114,121,32,97,110,100,116,104,105,115,32,105,115,32,116,104,101,84,\n104,105,115,32,108,101,100,32,116,111,97,32,115,116,97,116,101,109,101,110,116,\n99,111,110,116,114,97,115,116,32,116,111,108,97,115,116,73,110,100,101,120,79,\n102,116,104,114,111,117,103,104,32,104,105,115,105,115,32,100,101,115,105,103,\n110,101,100,116,104,101,32,116,101,114,109,32,105,115,105,115,32,112,114,111,118\n,105,100,101,100,112,114,111,116,101,99,116,32,116,104,101,110,103,60,47,97,62,\n60,47,108,105,62,84,104,101,32,99,117,114,114,101,110,116,116,104,101,32,115,105\n,116,101,32,111,102,115,117,98,115,116,97,110,116,105,97,108,101,120,112,101,114\n,105,101,110,99,101,44,105,110,32,116,104,101,32,87,101,115,116,116,104,101,121,\n32,115,104,111,117,108,100,115,108,111,118,101,110,196,141,105,110,97,99,111,109\n,101,110,116,97,114,105,111,115,117,110,105,118,101,114,115,105,100,97,100,99,\n111,110,100,105,99,105,111,110,101,115,97,99,116,105,118,105,100,97,100,101,115,\n101,120,112,101,114,105,101,110,99,105,97,116,101,99,110,111,108,111,103,195,173\n,97,112,114,111,100,117,99,99,105,195,179,110,112,117,110,116,117,97,99,105,195,\n179,110,97,112,108,105,99,97,99,105,195,179,110,99,111,110,116,114,97,115,101,\n195,177,97,99,97,116,101,103,111,114,195,173,97,115,114,101,103,105,115,116,114,\n97,114,115,101,112,114,111,102,101,115,105,111,110,97,108,116,114,97,116,97,109,\n105,101,110,116,111,114,101,103,195,173,115,116,114,97,116,101,115,101,99,114,\n101,116,97,114,195,173,97,112,114,105,110,99,105,112,97,108,101,115,112,114,111,\n116,101,99,99,105,195,179,110,105,109,112,111,114,116,97,110,116,101,115,105,109\n,112,111,114,116,97,110,99,105,97,112,111,115,105,98,105,108,105,100,97,100,105,\n110,116,101,114,101,115,97,110,116,101,99,114,101,99,105,109,105,101,110,116,111\n,110,101,99,101,115,105,100,97,100,101,115,115,117,115,99,114,105,98,105,114,115\n,101,97,115,111,99,105,97,99,105,195,179,110,100,105,115,112,111,110,105,98,108,\n101,115,101,118,97,108,117,97,99,105,195,179,110,101,115,116,117,100,105,97,110,\n116,101,115,114,101,115,112,111,110,115,97,98,108,101,114,101,115,111,108,117,99\n,105,195,179,110,103,117,97,100,97,108,97,106,97,114,97,114,101,103,105,115,116,\n114,97,100,111,115,111,112,111,114,116,117,110,105,100,97,100,99,111,109,101,114\n,99,105,97,108,101,115,102,111,116,111,103,114,97,102,195,173,97,97,117,116,111,\n114,105,100,97,100,101,115,105,110,103,101,110,105,101,114,195,173,97,116,101,\n108,101,118,105,115,105,195,179,110,99,111,109,112,101,116,101,110,99,105,97,111\n,112,101,114,97,99,105,111,110,101,115,101,115,116,97,98,108,101,99,105,100,111,\n115,105,109,112,108,101,109,101,110,116,101,97,99,116,117,97,108,109,101,110,116\n,101,110,97,118,101,103,97,99,105,195,179,110,99,111,110,102,111,114,109,105,100\n,97,100,108,105,110,101,45,104,101,105,103,104,116,58,102,111,110,116,45,102,97,\n109,105,108,121,58,34,32,58,32,34,104,116,116,112,58,47,47,97,112,112,108,105,99\n,97,116,105,111,110,115,108,105,110,107,34,32,104,114,101,102,61,34,115,112,101,\n99,105,102,105,99,97,108,108,121,47,47,60,33,91,67,68,65,84,65,91,10,79,114,103,\n97,110,105,122,97,116,105,111,110,100,105,115,116,114,105,98,117,116,105,111,110\n,48,112,120,59,32,104,101,105,103,104,116,58,114,101,108,97,116,105,111,110,115,\n104,105,112,100,101,118,105,99,101,45,119,105,100,116,104,60,100,105,118,32,99,\n108,97,115,115,61,34,60,108,97,98,101,108,32,102,111,114,61,34,114,101,103,105,\n115,116,114,97,116,105,111,110,60,47,110,111,115,99,114,105,112,116,62,10,47,105\n,110,100,101,120,46,104,116,109,108,34,119,105,110,100,111,119,46,111,112,101,\n110,40,32,33,105,109,112,111,114,116,97,110,116,59,97,112,112,108,105,99,97,116,\n105,111,110,47,105,110,100,101,112,101,110,100,101,110,99,101,47,47,119,119,119,\n46,103,111,111,103,108,101,111,114,103,97,110,105,122,97,116,105,111,110,97,117,\n116,111,99,111,109,112,108,101,116,101,114,101,113,117,105,114,101,109,101,110,\n116,115,99,111,110,115,101,114,118,97,116,105,118,101,60,102,111,114,109,32,110,\n97,109,101,61,34,105,110,116,101,108,108,101,99,116,117,97,108,109,97,114,103,\n105,110,45,108,101,102,116,58,49,56,116,104,32,99,101,110,116,117,114,121,97,110\n,32,105,109,112,111,114,116,97,110,116,105,110,115,116,105,116,117,116,105,111,\n110,115,97,98,98,114,101,118,105,97,116,105,111,110,60,105,109,103,32,99,108,97,\n115,115,61,34,111,114,103,97,110,105,115,97,116,105,111,110,99,105,118,105,108,\n105,122,97,116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,97,114,99\n,104,105,116,101,99,116,117,114,101,105,110,99,111,114,112,111,114,97,116,101,\n100,50,48,116,104,32,99,101,110,116,117,114,121,45,99,111,110,116,97,105,110,101\n,114,34,62,109,111,115,116,32,110,111,116,97,98,108,121,47,62,60,47,97,62,60,47,\n100,105,118,62,110,111,116,105,102,105,99,97,116,105,111,110,39,117,110,100,101,\n102,105,110,101,100,39,41,70,117,114,116,104,101,114,109,111,114,101,44,98,101,\n108,105,101,118,101,32,116,104,97,116,105,110,110,101,114,72,84,77,76,32,61,32,\n112,114,105,111,114,32,116,111,32,116,104,101,100,114,97,109,97,116,105,99,97,\n108,108,121,114,101,102,101,114,114,105,110,103,32,116,111,110,101,103,111,116,\n105,97,116,105,111,110,115,104,101,97,100,113,117,97,114,116,101,114,115,83,111,\n117,116,104,32,65,102,114,105,99,97,117,110,115,117,99,99,101,115,115,102,117,\n108,80,101,110,110,115,121,108,118,97,110,105,97,65,115,32,97,32,114,101,115,117\n,108,116,44,60,104,116,109,108,32,108,97,110,103,61,34,38,108,116,59,47,115,117,\n112,38,103,116,59,100,101,97,108,105,110,103,32,119,105,116,104,112,104,105,108,\n97,100,101,108,112,104,105,97,104,105,115,116,111,114,105,99,97,108,108,121,41,\n59,60,47,115,99,114,105,112,116,62,10,112,97,100,100,105,110,103,45,116,111,112,\n58,101,120,112,101,114,105,109,101,110,116,97,108,103,101,116,65,116,116,114,105\n,98,117,116,101,105,110,115,116,114,117,99,116,105,111,110,115,116,101,99,104,\n110,111,108,111,103,105,101,115,112,97,114,116,32,111,102,32,116,104,101,32,61,\n102,117,110,99,116,105,111,110,40,41,123,115,117,98,115,99,114,105,112,116,105,\n111,110,108,46,100,116,100,34,62,13,10,60,104,116,103,101,111,103,114,97,112,104\n,105,99,97,108,67,111,110,115,116,105,116,117,116,105,111,110,39,44,32,102,117,\n110,99,116,105,111,110,40,115,117,112,112,111,114,116,101,100,32,98,121,97,103,\n114,105,99,117,108,116,117,114,97,108,99,111,110,115,116,114,117,99,116,105,111,\n110,112,117,98,108,105,99,97,116,105,111,110,115,102,111,110,116,45,115,105,122,\n101,58,32,49,97,32,118,97,114,105,101,116,121,32,111,102,60,100,105,118,32,115,\n116,121,108,101,61,34,69,110,99,121,99,108,111,112,101,100,105,97,105,102,114,97\n,109,101,32,115,114,99,61,34,100,101,109,111,110,115,116,114,97,116,101,100,97,\n99,99,111,109,112,108,105,115,104,101,100,117,110,105,118,101,114,115,105,116,\n105,101,115,68,101,109,111,103,114,97,112,104,105,99,115,41,59,60,47,115,99,114,\n105,112,116,62,60,100,101,100,105,99,97,116,101,100,32,116,111,107,110,111,119,\n108,101,100,103,101,32,111,102,115,97,116,105,115,102,97,99,116,105,111,110,112,\n97,114,116,105,99,117,108,97,114,108,121,60,47,100,105,118,62,60,47,100,105,118,\n62,69,110,103,108,105,115,104,32,40,85,83,41,97,112,112,101,110,100,67,104,105,\n108,100,40,116,114,97,110,115,109,105,115,115,105,111,110,115,46,32,72,111,119,\n101,118,101,114,44,32,105,110,116,101,108,108,105,103,101,110,99,101,34,32,116,\n97,98,105,110,100,101,120,61,34,102,108,111,97,116,58,114,105,103,104,116,59,67,\n111,109,109,111,110,119,101,97,108,116,104,114,97,110,103,105,110,103,32,102,114\n,111,109,105,110,32,119,104,105,99,104,32,116,104,101,97,116,32,108,101,97,115,\n116,32,111,110,101,114,101,112,114,111,100,117,99,116,105,111,110,101,110,99,121\n,99,108,111,112,101,100,105,97,59,102,111,110,116,45,115,105,122,101,58,49,106,\n117,114,105,115,100,105,99,116,105,111,110,97,116,32,116,104,97,116,32,116,105,\n109,101,34,62,60,97,32,99,108,97,115,115,61,34,73,110,32,97,100,100,105,116,105,\n111,110,44,100,101,115,99,114,105,112,116,105,111,110,43,99,111,110,118,101,114,\n115,97,116,105,111,110,99,111,110,116,97,99,116,32,119,105,116,104,105,115,32,\n103,101,110,101,114,97,108,108,121,114,34,32,99,111,110,116,101,110,116,61,34,\n114,101,112,114,101,115,101,110,116,105,110,103,38,108,116,59,109,97,116,104,38,\n103,116,59,112,114,101,115,101,110,116,97,116,105,111,110,111,99,99,97,115,105,\n111,110,97,108,108,121,60,105,109,103,32,119,105,100,116,104,61,34,110,97,118,\n105,103,97,116,105,111,110,34,62,99,111,109,112,101,110,115,97,116,105,111,110,\n99,104,97,109,112,105,111,110,115,104,105,112,109,101,100,105,97,61,34,97,108,\n108,34,32,118,105,111,108,97,116,105,111,110,32,111,102,114,101,102,101,114,101,\n110,99,101,32,116,111,114,101,116,117,114,110,32,116,114,117,101,59,83,116,114,\n105,99,116,47,47,69,78,34,32,116,114,97,110,115,97,99,116,105,111,110,115,105,\n110,116,101,114,118,101,110,116,105,111,110,118,101,114,105,102,105,99,97,116,\n105,111,110,73,110,102,111,114,109,97,116,105,111,110,32,100,105,102,102,105,99,\n117,108,116,105,101,115,67,104,97,109,112,105,111,110,115,104,105,112,99,97,112,\n97,98,105,108,105,116,105,101,115,60,33,91,101,110,100,105,102,93,45,45,62,125,\n10,60,47,115,99,114,105,112,116,62,10,67,104,114,105,115,116,105,97,110,105,116,\n121,102,111,114,32,101,120,97,109,112,108,101,44,80,114,111,102,101,115,115,105,\n111,110,97,108,114,101,115,116,114,105,99,116,105,111,110,115,115,117,103,103,\n101,115,116,32,116,104,97,116,119,97,115,32,114,101,108,101,97,115,101,100,40,\n115,117,99,104,32,97,115,32,116,104,101,114,101,109,111,118,101,67,108,97,115,\n115,40,117,110,101,109,112,108,111,121,109,101,110,116,116,104,101,32,65,109,101\n,114,105,99,97,110,115,116,114,117,99,116,117,114,101,32,111,102,47,105,110,100,\n101,120,46,104,116,109,108,32,112,117,98,108,105,115,104,101,100,32,105,110,115,\n112,97,110,32,99,108,97,115,115,61,34,34,62,60,97,32,104,114,101,102,61,34,47,\n105,110,116,114,111,100,117,99,116,105,111,110,98,101,108,111,110,103,105,110,\n103,32,116,111,99,108,97,105,109,101,100,32,116,104,97,116,99,111,110,115,101,\n113,117,101,110,99,101,115,60,109,101,116,97,32,110,97,109,101,61,34,71,117,105,\n100,101,32,116,111,32,116,104,101,111,118,101,114,119,104,101,108,109,105,110,\n103,97,103,97,105,110,115,116,32,116,104,101,32,99,111,110,99,101,110,116,114,97\n,116,101,100,44,10,46,110,111,110,116,111,117,99,104,32,111,98,115,101,114,118,\n97,116,105,111,110,115,60,47,97,62,10,60,47,100,105,118,62,10,102,32,40,100,111,\n99,117,109,101,110,116,46,98,111,114,100,101,114,58,32,49,112,120,32,123,102,111\n,110,116,45,115,105,122,101,58,49,116,114,101,97,116,109,101,110,116,32,111,102,\n48,34,32,104,101,105,103,104,116,61,34,49,109,111,100,105,102,105,99,97,116,105,\n111,110,73,110,100,101,112,101,110,100,101,110,99,101,100,105,118,105,100,101,\n100,32,105,110,116,111,103,114,101,97,116,101,114,32,116,104,97,110,97,99,104,\n105,101,118,101,109,101,110,116,115,101,115,116,97,98,108,105,115,104,105,110,\n103,74,97,118,97,83,99,114,105,112,116,34,32,110,101,118,101,114,116,104,101,108\n,101,115,115,115,105,103,110,105,102,105,99,97,110,99,101,66,114,111,97,100,99,\n97,115,116,105,110,103,62,38,110,98,115,112,59,60,47,116,100,62,99,111,110,116,\n97,105,110,101,114,34,62,10,115,117,99,104,32,97,115,32,116,104,101,32,105,110,\n102,108,117,101,110,99,101,32,111,102,97,32,112,97,114,116,105,99,117,108,97,114\n,115,114,99,61,39,104,116,116,112,58,47,47,110,97,118,105,103,97,116,105,111,110\n,34,32,104,97,108,102,32,111,102,32,116,104,101,32,115,117,98,115,116,97,110,116\n,105,97,108,32,38,110,98,115,112,59,60,47,100,105,118,62,97,100,118,97,110,116,\n97,103,101,32,111,102,100,105,115,99,111,118,101,114,121,32,111,102,102,117,110,\n100,97,109,101,110,116,97,108,32,109,101,116,114,111,112,111,108,105,116,97,110,\n116,104,101,32,111,112,112,111,115,105,116,101,34,32,120,109,108,58,108,97,110,\n103,61,34,100,101,108,105,98,101,114,97,116,101,108,121,97,108,105,103,110,61,99\n,101,110,116,101,114,101,118,111,108,117,116,105,111,110,32,111,102,112,114,101,\n115,101,114,118,97,116,105,111,110,105,109,112,114,111,118,101,109,101,110,116,\n115,98,101,103,105,110,110,105,110,103,32,105,110,74,101,115,117,115,32,67,104,\n114,105,115,116,80,117,98,108,105,99,97,116,105,111,110,115,100,105,115,97,103,\n114,101,101,109,101,110,116,116,101,120,116,45,97,108,105,103,110,58,114,44,32,\n102,117,110,99,116,105,111,110,40,41,115,105,109,105,108,97,114,105,116,105,101,\n115,98,111,100,121,62,60,47,104,116,109,108,62,105,115,32,99,117,114,114,101,110\n,116,108,121,97,108,112,104,97,98,101,116,105,99,97,108,105,115,32,115,111,109,\n101,116,105,109,101,115,116,121,112,101,61,34,105,109,97,103,101,47,109,97,110,\n121,32,111,102,32,116,104,101,32,102,108,111,119,58,104,105,100,100,101,110,59,\n97,118,97,105,108,97,98,108,101,32,105,110,100,101,115,99,114,105,98,101,32,116,\n104,101,101,120,105,115,116,101,110,99,101,32,111,102,97,108,108,32,111,118,101,\n114,32,116,104,101,116,104,101,32,73,110,116,101,114,110,101,116,9,60,117,108,32\n,99,108,97,115,115,61,34,105,110,115,116,97,108,108,97,116,105,111,110,110,101,\n105,103,104,98,111,114,104,111,111,100,97,114,109,101,100,32,102,111,114,99,101,\n115,114,101,100,117,99,105,110,103,32,116,104,101,99,111,110,116,105,110,117,101\n,115,32,116,111,78,111,110,101,116,104,101,108,101,115,115,44,116,101,109,112,\n101,114,97,116,117,114,101,115,10,9,9,60,97,32,104,114,101,102,61,34,99,108,111,\n115,101,32,116,111,32,116,104,101,101,120,97,109,112,108,101,115,32,111,102,32,\n105,115,32,97,98,111,117,116,32,116,104,101,40,115,101,101,32,98,101,108,111,119\n,41,46,34,32,105,100,61,34,115,101,97,114,99,104,112,114,111,102,101,115,115,105\n,111,110,97,108,105,115,32,97,118,97,105,108,97,98,108,101,116,104,101,32,111,\n102,102,105,99,105,97,108,9,9,60,47,115,99,114,105,112,116,62,10,10,9,9,60,100,\n105,118,32,105,100,61,34,97,99,99,101,108,101,114,97,116,105,111,110,116,104,114\n,111,117,103,104,32,116,104,101,32,72,97,108,108,32,111,102,32,70,97,109,101,100\n,101,115,99,114,105,112,116,105,111,110,115,116,114,97,110,115,108,97,116,105,\n111,110,115,105,110,116,101,114,102,101,114,101,110,99,101,32,116,121,112,101,61\n,39,116,101,120,116,47,114,101,99,101,110,116,32,121,101,97,114,115,105,110,32,\n116,104,101,32,119,111,114,108,100,118,101,114,121,32,112,111,112,117,108,97,114\n,123,98,97,99,107,103,114,111,117,110,100,58,116,114,97,100,105,116,105,111,110,\n97,108,32,115,111,109,101,32,111,102,32,116,104,101,32,99,111,110,110,101,99,116\n,101,100,32,116,111,101,120,112,108,111,105,116,97,116,105,111,110,101,109,101,\n114,103,101,110,99,101,32,111,102,99,111,110,115,116,105,116,117,116,105,111,110\n,65,32,72,105,115,116,111,114,121,32,111,102,115,105,103,110,105,102,105,99,97,\n110,116,32,109,97,110,117,102,97,99,116,117,114,101,100,101,120,112,101,99,116,\n97,116,105,111,110,115,62,60,110,111,115,99,114,105,112,116,62,60,99,97,110,32,\n98,101,32,102,111,117,110,100,98,101,99,97,117,115,101,32,116,104,101,32,104,97,\n115,32,110,111,116,32,98,101,101,110,110,101,105,103,104,98,111,117,114,105,110,\n103,119,105,116,104,111,117,116,32,116,104,101,32,97,100,100,101,100,32,116,111,\n32,116,104,101,9,60,108,105,32,99,108,97,115,115,61,34,105,110,115,116,114,117,\n109,101,110,116,97,108,83,111,118,105,101,116,32,85,110,105,111,110,97,99,107,\n110,111,119,108,101,100,103,101,100,119,104,105,99,104,32,99,97,110,32,98,101,\n110,97,109,101,32,102,111,114,32,116,104,101,97,116,116,101,110,116,105,111,110,\n32,116,111,97,116,116,101,109,112,116,115,32,116,111,32,100,101,118,101,108,111,\n112,109,101,110,116,115,73,110,32,102,97,99,116,44,32,116,104,101,60,108,105,32,\n99,108,97,115,115,61,34,97,105,109,112,108,105,99,97,116,105,111,110,115,115,117\n,105,116,97,98,108,101,32,102,111,114,109,117,99,104,32,111,102,32,116,104,101,\n32,99,111,108,111,110,105,122,97,116,105,111,110,112,114,101,115,105,100,101,110\n,116,105,97,108,99,97,110,99,101,108,66,117,98,98,108,101,32,73,110,102,111,114,\n109,97,116,105,111,110,109,111,115,116,32,111,102,32,116,104,101,32,105,115,32,\n100,101,115,99,114,105,98,101,100,114,101,115,116,32,111,102,32,116,104,101,32,\n109,111,114,101,32,111,114,32,108,101,115,115,105,110,32,83,101,112,116,101,109,\n98,101,114,73,110,116,101,108,108,105,103,101,110,99,101,115,114,99,61,34,104,\n116,116,112,58,47,47,112,120,59,32,104,101,105,103,104,116,58,32,97,118,97,105,\n108,97,98,108,101,32,116,111,109,97,110,117,102,97,99,116,117,114,101,114,104,\n117,109,97,110,32,114,105,103,104,116,115,108,105,110,107,32,104,114,101,102,61,\n34,47,97,118,97,105,108,97,98,105,108,105,116,121,112,114,111,112,111,114,116,\n105,111,110,97,108,111,117,116,115,105,100,101,32,116,104,101,32,97,115,116,114,\n111,110,111,109,105,99,97,108,104,117,109,97,110,32,98,101,105,110,103,115,110,\n97,109,101,32,111,102,32,116,104,101,32,97,114,101,32,102,111,117,110,100,32,105\n,110,97,114,101,32,98,97,115,101,100,32,111,110,115,109,97,108,108,101,114,32,\n116,104,97,110,97,32,112,101,114,115,111,110,32,119,104,111,101,120,112,97,110,\n115,105,111,110,32,111,102,97,114,103,117,105,110,103,32,116,104,97,116,110,111,\n119,32,107,110,111,119,110,32,97,115,73,110,32,116,104,101,32,101,97,114,108,121\n,105,110,116,101,114,109,101,100,105,97,116,101,100,101,114,105,118,101,100,32,\n102,114,111,109,83,99,97,110,100,105,110,97,118,105,97,110,60,47,97,62,60,47,100\n,105,118,62,13,10,99,111,110,115,105,100,101,114,32,116,104,101,97,110,32,101,\n115,116,105,109,97,116,101,100,116,104,101,32,78,97,116,105,111,110,97,108,60,\n100,105,118,32,105,100,61,34,112,97,103,114,101,115,117,108,116,105,110,103,32,\n105,110,99,111,109,109,105,115,115,105,111,110,101,100,97,110,97,108,111,103,111\n,117,115,32,116,111,97,114,101,32,114,101,113,117,105,114,101,100,47,117,108,62,\n10,60,47,100,105,118,62,10,119,97,115,32,98,97,115,101,100,32,111,110,97,110,100\n,32,98,101,99,97,109,101,32,97,38,110,98,115,112,59,38,110,98,115,112,59,116,34,\n32,118,97,108,117,101,61,34,34,32,119,97,115,32,99,97,112,116,117,114,101,100,\n110,111,32,109,111,114,101,32,116,104,97,110,114,101,115,112,101,99,116,105,118,\n101,108,121,99,111,110,116,105,110,117,101,32,116,111,32,62,13,10,60,104,101,97,\n100,62,13,10,60,119,101,114,101,32,99,114,101,97,116,101,100,109,111,114,101,32,\n103,101,110,101,114,97,108,105,110,102,111,114,109,97,116,105,111,110,32,117,115\n,101,100,32,102,111,114,32,116,104,101,105,110,100,101,112,101,110,100,101,110,\n116,32,116,104,101,32,73,109,112,101,114,105,97,108,99,111,109,112,111,110,101,\n110,116,32,111,102,116,111,32,116,104,101,32,110,111,114,116,104,105,110,99,108,\n117,100,101,32,116,104,101,32,67,111,110,115,116,114,117,99,116,105,111,110,115,\n105,100,101,32,111,102,32,116,104,101,32,119,111,117,108,100,32,110,111,116,32,\n98,101,102,111,114,32,105,110,115,116,97,110,99,101,105,110,118,101,110,116,105,\n111,110,32,111,102,109,111,114,101,32,99,111,109,112,108,101,120,99,111,108,108,\n101,99,116,105,118,101,108,121,98,97,99,107,103,114,111,117,110,100,58,32,116,\n101,120,116,45,97,108,105,103,110,58,32,105,116,115,32,111,114,105,103,105,110,\n97,108,105,110,116,111,32,97,99,99,111,117,110,116,116,104,105,115,32,112,114,\n111,99,101,115,115,97,110,32,101,120,116,101,110,115,105,118,101,104,111,119,101\n,118,101,114,44,32,116,104,101,116,104,101,121,32,97,114,101,32,110,111,116,114,\n101,106,101,99,116,101,100,32,116,104,101,99,114,105,116,105,99,105,115,109,32,\n111,102,100,117,114,105,110,103,32,119,104,105,99,104,112,114,111,98,97,98,108,\n121,32,116,104,101,116,104,105,115,32,97,114,116,105,99,108,101,40,102,117,110,\n99,116,105,111,110,40,41,123,73,116,32,115,104,111,117,108,100,32,98,101,97,110,\n32,97,103,114,101,101,109,101,110,116,97,99,99,105,100,101,110,116,97,108,108,\n121,100,105,102,102,101,114,115,32,102,114,111,109,65,114,99,104,105,116,101,99,\n116,117,114,101,98,101,116,116,101,114,32,107,110,111,119,110,97,114,114,97,110,\n103,101,109,101,110,116,115,105,110,102,108,117,101,110,99,101,32,111,110,97,116\n,116,101,110,100,101,100,32,116,104,101,105,100,101,110,116,105,99,97,108,32,116\n,111,115,111,117,116,104,32,111,102,32,116,104,101,112,97,115,115,32,116,104,114\n,111,117,103,104,120,109,108,34,32,116,105,116,108,101,61,34,119,101,105,103,104\n,116,58,98,111,108,100,59,99,114,101,97,116,105,110,103,32,116,104,101,100,105,\n115,112,108,97,121,58,110,111,110,101,114,101,112,108,97,99,101,100,32,116,104,\n101,60,105,109,103,32,115,114,99,61,34,47,105,104,116,116,112,115,58,47,47,119,\n119,119,46,87,111,114,108,100,32,87,97,114,32,73,73,116,101,115,116,105,109,111,\n110,105,97,108,115,102,111,117,110,100,32,105,110,32,116,104,101,114,101,113,117\n,105,114,101,100,32,116,111,32,97,110,100,32,116,104,97,116,32,116,104,101,98,\n101,116,119,101,101,110,32,116,104,101,32,119,97,115,32,100,101,115,105,103,110,\n101,100,99,111,110,115,105,115,116,115,32,111,102,32,99,111,110,115,105,100,101,\n114,97,98,108,121,112,117,98,108,105,115,104,101,100,32,98,121,116,104,101,32,\n108,97,110,103,117,97,103,101,67,111,110,115,101,114,118,97,116,105,111,110,99,\n111,110,115,105,115,116,101,100,32,111,102,114,101,102,101,114,32,116,111,32,116\n,104,101,98,97,99,107,32,116,111,32,116,104,101,32,99,115,115,34,32,109,101,100,\n105,97,61,34,80,101,111,112,108,101,32,102,114,111,109,32,97,118,97,105,108,97,\n98,108,101,32,111,110,112,114,111,118,101,100,32,116,111,32,98,101,115,117,103,\n103,101,115,116,105,111,110,115,34,119,97,115,32,107,110,111,119,110,32,97,115,\n118,97,114,105,101,116,105,101,115,32,111,102,108,105,107,101,108,121,32,116,111\n,32,98,101,99,111,109,112,114,105,115,101,100,32,111,102,115,117,112,112,111,114\n,116,32,116,104,101,32,104,97,110,100,115,32,111,102,32,116,104,101,99,111,117,\n112,108,101,100,32,119,105,116,104,99,111,110,110,101,99,116,32,97,110,100,32,98\n,111,114,100,101,114,58,110,111,110,101,59,112,101,114,102,111,114,109,97,110,99\n,101,115,98,101,102,111,114,101,32,98,101,105,110,103,108,97,116,101,114,32,98,\n101,99,97,109,101,99,97,108,99,117,108,97,116,105,111,110,115,111,102,116,101,\n110,32,99,97,108,108,101,100,114,101,115,105,100,101,110,116,115,32,111,102,109,\n101,97,110,105,110,103,32,116,104,97,116,62,60,108,105,32,99,108,97,115,115,61,\n34,101,118,105,100,101,110,99,101,32,102,111,114,101,120,112,108,97,110,97,116,\n105,111,110,115,101,110,118,105,114,111,110,109,101,110,116,115,34,62,60,47,97,\n62,60,47,100,105,118,62,119,104,105,99,104,32,97,108,108,111,119,115,73,110,116,\n114,111,100,117,99,116,105,111,110,100,101,118,101,108,111,112,101,100,32,98,121\n,97,32,119,105,100,101,32,114,97,110,103,101,111,110,32,98,101,104,97,108,102,32\n,111,102,118,97,108,105,103,110,61,34,116,111,112,34,112,114,105,110,99,105,112,\n108,101,32,111,102,97,116,32,116,104,101,32,116,105,109,101,44,60,47,110,111,115\n,99,114,105,112,116,62,13,115,97,105,100,32,116,111,32,104,97,118,101,105,110,32\n,116,104,101,32,102,105,114,115,116,119,104,105,108,101,32,111,116,104,101,114,\n115,104,121,112,111,116,104,101,116,105,99,97,108,112,104,105,108,111,115,111,\n112,104,101,114,115,112,111,119,101,114,32,111,102,32,116,104,101,99,111,110,116\n,97,105,110,101,100,32,105,110,112,101,114,102,111,114,109,101,100,32,98,121,105\n,110,97,98,105,108,105,116,121,32,116,111,119,101,114,101,32,119,114,105,116,116\n,101,110,115,112,97,110,32,115,116,121,108,101,61,34,105,110,112,117,116,32,110,\n97,109,101,61,34,116,104,101,32,113,117,101,115,116,105,111,110,105,110,116,101,\n110,100,101,100,32,102,111,114,114,101,106,101,99,116,105,111,110,32,111,102,105\n,109,112,108,105,101,115,32,116,104,97,116,105,110,118,101,110,116,101,100,32,\n116,104,101,116,104,101,32,115,116,97,110,100,97,114,100,119,97,115,32,112,114,\n111,98,97,98,108,121,108,105,110,107,32,98,101,116,119,101,101,110,112,114,111,\n102,101,115,115,111,114,32,111,102,105,110,116,101,114,97,99,116,105,111,110,115\n,99,104,97,110,103,105,110,103,32,116,104,101,73,110,100,105,97,110,32,79,99,101\n,97,110,32,99,108,97,115,115,61,34,108,97,115,116,119,111,114,107,105,110,103,32\n,119,105,116,104,39,104,116,116,112,58,47,47,119,119,119,46,121,101,97,114,115,\n32,98,101,102,111,114,101,84,104,105,115,32,119,97,115,32,116,104,101,114,101,99\n,114,101,97,116,105,111,110,97,108,101,110,116,101,114,105,110,103,32,116,104,\n101,109,101,97,115,117,114,101,109,101,110,116,115,97,110,32,101,120,116,114,101\n,109,101,108,121,118,97,108,117,101,32,111,102,32,116,104,101,115,116,97,114,116\n,32,111,102,32,116,104,101,10,60,47,115,99,114,105,112,116,62,10,10,97,110,32,\n101,102,102,111,114,116,32,116,111,105,110,99,114,101,97,115,101,32,116,104,101,\n116,111,32,116,104,101,32,115,111,117,116,104,115,112,97,99,105,110,103,61,34,48\n,34,62,115,117,102,102,105,99,105,101,110,116,108,121,116,104,101,32,69,117,114,\n111,112,101,97,110,99,111,110,118,101,114,116,101,100,32,116,111,99,108,101,97,\n114,84,105,109,101,111,117,116,100,105,100,32,110,111,116,32,104,97,118,101,99,\n111,110,115,101,113,117,101,110,116,108,121,102,111,114,32,116,104,101,32,110,\n101,120,116,101,120,116,101,110,115,105,111,110,32,111,102,101,99,111,110,111,\n109,105,99,32,97,110,100,97,108,116,104,111,117,103,104,32,116,104,101,97,114,\n101,32,112,114,111,100,117,99,101,100,97,110,100,32,119,105,116,104,32,116,104,\n101,105,110,115,117,102,102,105,99,105,101,110,116,103,105,118,101,110,32,98,121\n,32,116,104,101,115,116,97,116,105,110,103,32,116,104,97,116,101,120,112,101,110\n,100,105,116,117,114,101,115,60,47,115,112,97,110,62,60,47,97,62,10,116,104,111,\n117,103,104,116,32,116,104,97,116,111,110,32,116,104,101,32,98,97,115,105,115,99\n,101,108,108,112,97,100,100,105,110,103,61,105,109,97,103,101,32,111,102,32,116,\n104,101,114,101,116,117,114,110,105,110,103,32,116,111,105,110,102,111,114,109,\n97,116,105,111,110,44,115,101,112,97,114,97,116,101,100,32,98,121,97,115,115,97,\n115,115,105,110,97,116,101,100,115,34,32,99,111,110,116,101,110,116,61,34,97,117\n,116,104,111,114,105,116,121,32,111,102,110,111,114,116,104,119,101,115,116,101,\n114,110,60,47,100,105,118,62,10,60,100,105,118,32,34,62,60,47,100,105,118,62,13,\n10,32,32,99,111,110,115,117,108,116,97,116,105,111,110,99,111,109,109,117,110,\n105,116,121,32,111,102,116,104,101,32,110,97,116,105,111,110,97,108,105,116,32,\n115,104,111,117,108,100,32,98,101,112,97,114,116,105,99,105,112,97,110,116,115,\n32,97,108,105,103,110,61,34,108,101,102,116,116,104,101,32,103,114,101,97,116,\n101,115,116,115,101,108,101,99,116,105,111,110,32,111,102,115,117,112,101,114,\n110,97,116,117,114,97,108,100,101,112,101,110,100,101,110,116,32,111,110,105,115\n,32,109,101,110,116,105,111,110,101,100,97,108,108,111,119,105,110,103,32,116,\n104,101,119,97,115,32,105,110,118,101,110,116,101,100,97,99,99,111,109,112,97,\n110,121,105,110,103,104,105,115,32,112,101,114,115,111,110,97,108,97,118,97,105,\n108,97,98,108,101,32,97,116,115,116,117,100,121,32,111,102,32,116,104,101,111,\n110,32,116,104,101,32,111,116,104,101,114,101,120,101,99,117,116,105,111,110,32,\n111,102,72,117,109,97,110,32,82,105,103,104,116,115,116,101,114,109,115,32,111,\n102,32,116,104,101,97,115,115,111,99,105,97,116,105,111,110,115,114,101,115,101,\n97,114,99,104,32,97,110,100,115,117,99,99,101,101,100,101,100,32,98,121,100,101,\n102,101,97,116,101,100,32,116,104,101,97,110,100,32,102,114,111,109,32,116,104,\n101,98,117,116,32,116,104,101,121,32,97,114,101,99,111,109,109,97,110,100,101,\n114,32,111,102,115,116,97,116,101,32,111,102,32,116,104,101,121,101,97,114,115,\n32,111,102,32,97,103,101,116,104,101,32,115,116,117,100,121,32,111,102,60,117,\n108,32,99,108,97,115,115,61,34,115,112,108,97,99,101,32,105,110,32,116,104,101,\n119,104,101,114,101,32,104,101,32,119,97,115,60,108,105,32,99,108,97,115,115,61,\n34,102,116,104,101,114,101,32,97,114,101,32,110,111,119,104,105,99,104,32,98,101\n,99,97,109,101,104,101,32,112,117,98,108,105,115,104,101,100,101,120,112,114,101\n,115,115,101,100,32,105,110,116,111,32,119,104,105,99,104,32,116,104,101,99,111,\n109,109,105,115,115,105,111,110,101,114,102,111,110,116,45,119,101,105,103,104,\n116,58,116,101,114,114,105,116,111,114,121,32,111,102,101,120,116,101,110,115,\n105,111,110,115,34,62,82,111,109,97,110,32,69,109,112,105,114,101,101,113,117,97\n,108,32,116,111,32,116,104,101,73,110,32,99,111,110,116,114,97,115,116,44,104,\n111,119,101,118,101,114,44,32,97,110,100,105,115,32,116,121,112,105,99,97,108,\n108,121,97,110,100,32,104,105,115,32,119,105,102,101,40,97,108,115,111,32,99,97,\n108,108,101,100,62,60,117,108,32,99,108,97,115,115,61,34,101,102,102,101,99,116,\n105,118,101,108,121,32,101,118,111,108,118,101,100,32,105,110,116,111,115,101,\n101,109,32,116,111,32,104,97,118,101,119,104,105,99,104,32,105,115,32,116,104,\n101,116,104,101,114,101,32,119,97,115,32,110,111,97,110,32,101,120,99,101,108,\n108,101,110,116,97,108,108,32,111,102,32,116,104,101,115,101,100,101,115,99,114,\n105,98,101,100,32,98,121,73,110,32,112,114,97,99,116,105,99,101,44,98,114,111,97\n,100,99,97,115,116,105,110,103,99,104,97,114,103,101,100,32,119,105,116,104,114,\n101,102,108,101,99,116,101,100,32,105,110,115,117,98,106,101,99,116,101,100,32,\n116,111,109,105,108,105,116,97,114,121,32,97,110,100,116,111,32,116,104,101,32,\n112,111,105,110,116,101,99,111,110,111,109,105,99,97,108,108,121,115,101,116,84,\n97,114,103,101,116,105,110,103,97,114,101,32,97,99,116,117,97,108,108,121,118,\n105,99,116,111,114,121,32,111,118,101,114,40,41,59,60,47,115,99,114,105,112,116,\n62,99,111,110,116,105,110,117,111,117,115,108,121,114,101,113,117,105,114,101,\n100,32,102,111,114,101,118,111,108,117,116,105,111,110,97,114,121,97,110,32,101,\n102,102,101,99,116,105,118,101,110,111,114,116,104,32,111,102,32,116,104,101,44,\n32,119,104,105,99,104,32,119,97,115,32,102,114,111,110,116,32,111,102,32,116,104\n,101,111,114,32,111,116,104,101,114,119,105,115,101,115,111,109,101,32,102,111,\n114,109,32,111,102,104,97,100,32,110,111,116,32,98,101,101,110,103,101,110,101,\n114,97,116,101,100,32,98,121,105,110,102,111,114,109,97,116,105,111,110,46,112,\n101,114,109,105,116,116,101,100,32,116,111,105,110,99,108,117,100,101,115,32,116\n,104,101,100,101,118,101,108,111,112,109,101,110,116,44,101,110,116,101,114,101,\n100,32,105,110,116,111,116,104,101,32,112,114,101,118,105,111,117,115,99,111,110\n,115,105,115,116,101,110,116,108,121,97,114,101,32,107,110,111,119,110,32,97,115\n,116,104,101,32,102,105,101,108,100,32,111,102,116,104,105,115,32,116,121,112,\n101,32,111,102,103,105,118,101,110,32,116,111,32,116,104,101,116,104,101,32,116,\n105,116,108,101,32,111,102,99,111,110,116,97,105,110,115,32,116,104,101,105,110,\n115,116,97,110,99,101,115,32,111,102,105,110,32,116,104,101,32,110,111,114,116,\n104,100,117,101,32,116,111,32,116,104,101,105,114,97,114,101,32,100,101,115,105,\n103,110,101,100,99,111,114,112,111,114,97,116,105,111,110,115,119,97,115,32,116,\n104,97,116,32,116,104,101,111,110,101,32,111,102,32,116,104,101,115,101,109,111,\n114,101,32,112,111,112,117,108,97,114,115,117,99,99,101,101,100,101,100,32,105,\n110,115,117,112,112,111,114,116,32,102,114,111,109,105,110,32,100,105,102,102,\n101,114,101,110,116,100,111,109,105,110,97,116,101,100,32,98,121,100,101,115,105\n,103,110,101,100,32,102,111,114,111,119,110,101,114,115,104,105,112,32,111,102,\n97,110,100,32,112,111,115,115,105,98,108,121,115,116,97,110,100,97,114,100,105,\n122,101,100,114,101,115,112,111,110,115,101,84,101,120,116,119,97,115,32,105,110\n,116,101,110,100,101,100,114,101,99,101,105,118,101,100,32,116,104,101,97,115,\n115,117,109,101,100,32,116,104,97,116,97,114,101,97,115,32,111,102,32,116,104,\n101,112,114,105,109,97,114,105,108,121,32,105,110,116,104,101,32,98,97,115,105,\n115,32,111,102,105,110,32,116,104,101,32,115,101,110,115,101,97,99,99,111,117,\n110,116,115,32,102,111,114,100,101,115,116,114,111,121,101,100,32,98,121,97,116,\n32,108,101,97,115,116,32,116,119,111,119,97,115,32,100,101,99,108,97,114,101,100\n,99,111,117,108,100,32,110,111,116,32,98,101,83,101,99,114,101,116,97,114,121,32\n,111,102,97,112,112,101,97,114,32,116,111,32,98,101,109,97,114,103,105,110,45,\n116,111,112,58,49,47,94,92,115,43,124,92,115,43,36,47,103,101,41,123,116,104,114\n,111,119,32,101,125,59,116,104,101,32,115,116,97,114,116,32,111,102,116,119,111,\n32,115,101,112,97,114,97,116,101,108,97,110,103,117,97,103,101,32,97,110,100,119\n,104,111,32,104,97,100,32,98,101,101,110,111,112,101,114,97,116,105,111,110,32,\n111,102,100,101,97,116,104,32,111,102,32,116,104,101,114,101,97,108,32,110,117,\n109,98,101,114,115,9,60,108,105,110,107,32,114,101,108,61,34,112,114,111,118,105\n,100,101,100,32,116,104,101,116,104,101,32,115,116,111,114,121,32,111,102,99,111\n,109,112,101,116,105,116,105,111,110,115,101,110,103,108,105,115,104,32,40,85,75\n,41,101,110,103,108,105,115,104,32,40,85,83,41,208,156,208,190,208,189,208,179,\n208,190,208,187,208,161,209,128,208,191,209,129,208,186,208,184,209,129,209,128,\n208,191,209,129,208,186,208,184,209,129,209,128,208,191,209,129,208,186,208,190,\n217,132,216,185,216,177,216,168,217,138,216,169,230,173,163,233,171,148,228,184,\n173,230,150,135,231,174,128,228,189,147,228,184,173,230,150,135,231,185,129,228,\n189,147,228,184,173,230,150,135,230,156,137,233,153,144,229,133,172,229,143,184,\n228,186,186,230,176,145,230,148,191,229,186,156,233,152,191,233,135,140,229,183,\n180,229,183,180,231,164,190,228,188,154,228,184,187,228,185,137,230,147,141,228,\n189,156,231,179,187,231,187,159,230,148,191,231,173,150,230,179,149,232,167,132,\n105,110,102,111,114,109,97,99,105,195,179,110,104,101,114,114,97,109,105,101,110\n,116,97,115,101,108,101,99,116,114,195,179,110,105,99,111,100,101,115,99,114,105\n,112,99,105,195,179,110,99,108,97,115,105,102,105,99,97,100,111,115,99,111,110,\n111,99,105,109,105,101,110,116,111,112,117,98,108,105,99,97,99,105,195,179,110,\n114,101,108,97,99,105,111,110,97,100,97,115,105,110,102,111,114,109,195,161,116,\n105,99,97,114,101,108,97,99,105,111,110,97,100,111,115,100,101,112,97,114,116,97\n,109,101,110,116,111,116,114,97,98,97,106,97,100,111,114,101,115,100,105,114,101\n,99,116,97,109,101,110,116,101,97,121,117,110,116,97,109,105,101,110,116,111,109\n,101,114,99,97,100,111,76,105,98,114,101,99,111,110,116,195,161,99,116,101,110,\n111,115,104,97,98,105,116,97,99,105,111,110,101,115,99,117,109,112,108,105,109,\n105,101,110,116,111,114,101,115,116,97,117,114,97,110,116,101,115,100,105,115,\n112,111,115,105,99,105,195,179,110,99,111,110,115,101,99,117,101,110,99,105,97,\n101,108,101,99,116,114,195,179,110,105,99,97,97,112,108,105,99,97,99,105,111,110\n,101,115,100,101,115,99,111,110,101,99,116,97,100,111,105,110,115,116,97,108,97,\n99,105,195,179,110,114,101,97,108,105,122,97,99,105,195,179,110,117,116,105,108,\n105,122,97,99,105,195,179,110,101,110,99,105,99,108,111,112,101,100,105,97,101,\n110,102,101,114,109,101,100,97,100,101,115,105,110,115,116,114,117,109,101,110,\n116,111,115,101,120,112,101,114,105,101,110,99,105,97,115,105,110,115,116,105,\n116,117,99,105,195,179,110,112,97,114,116,105,99,117,108,97,114,101,115,115,117,\n98,99,97,116,101,103,111,114,105,97,209,130,208,190,208,187,209,140,208,186,208,\n190,208,160,208,190,209,129,209,129,208,184,208,184,209,128,208,176,208,177,208,\n190,209,130,209,139,208,177,208,190,208,187,209,140,209,136,208,181,208,191,209,\n128,208,190,209,129,209,130,208,190,208,188,208,190,208,182,208,181,209,130,208,\n181,208,180,209,128,209,131,208,179,208,184,209,133,209,129,208,187,209,131,209,\n135,208,176,208,181,209,129,208,181,208,185,209,135,208,176,209,129,208,178,209,\n129,208,181,208,179,208,180,208,176,208,160,208,190,209,129,209,129,208,184,209,\n143,208,156,208,190,209,129,208,186,208,178,208,181,208,180,209,128,209,131,208,\n179,208,184,208,181,208,179,208,190,209,128,208,190,208,180,208,176,208,178,208,\n190,208,191,209,128,208,190,209,129,208,180,208,176,208,189,208,189,209,139,209,\n133,208,180,208,190,208,187,208,182,208,189,209,139,208,184,208,188,208,181,208,\n189,208,189,208,190,208,156,208,190,209,129,208,186,208,178,209,139,209,128,209,\n131,208,177,208,187,208,181,208,185,208,156,208,190,209,129,208,186,208,178,208,\n176,209,129,209,130,209,128,208,176,208,189,209,139,208,189,208,184,209,135,208,\n181,208,179,208,190,209,128,208,176,208,177,208,190,209,130,208,181,208,180,208,\n190,208,187,208,182,208,181,208,189,209,131,209,129,208,187,209,131,208,179,208,\n184,209,130,208,181,208,191,208,181,209,128,209,140,208,158,208,180,208,189,208,\n176,208,186,208,190,208,191,208,190,209,130,208,190,208,188,209,131,209,128,208,\n176,208,177,208,190,209,130,209,131,208,176,208,191,209,128,208,181,208,187,209,\n143,208,178,208,190,208,190,208,177,209,137,208,181,208,190,208,180,208,189,208,\n190,208,179,208,190,209,129,208,178,208,190,208,181,208,179,208,190,209,129,209,\n130,208,176,209,130,209,140,208,184,208,180,209,128,209,131,208,179,208,190,208,\n185,209,132,208,190,209,128,209,131,208,188,208,181,209,133,208,190,209,128,208,\n190,209,136,208,190,208,191,209,128,208,190,209,130,208,184,208,178,209,129,209,\n129,209,139,208,187,208,186,208,176,208,186,208,176,208,182,208,180,209,139,208,\n185,208,178,208,187,208,176,209,129,209,130,208,184,208,179,209,128,209,131,208,\n191,208,191,209,139,208,178,208,188,208,181,209,129,209,130,208,181,209,128,208,\n176,208,177,208,190,209,130,208,176,209,129,208,186,208,176,208,183,208,176,208,\n187,208,191,208,181,209,128,208,178,209,139,208,185,208,180,208,181,208,187,208,\n176,209,130,209,140,208,180,208,181,208,189,209,140,208,179,208,184,208,191,208,\n181,209,128,208,184,208,190,208,180,208,177,208,184,208,183,208,189,208,181,209,\n129,208,190,209,129,208,189,208,190,208,178,208,181,208,188,208,190,208,188,208,\n181,208,189,209,130,208,186,209,131,208,191,208,184,209,130,209,140,208,180,208,\n190,208,187,208,182,208,189,208,176,209,128,208,176,208,188,208,186,208,176,209,\n133,208,189,208,176,209,135,208,176,208,187,208,190,208,160,208,176,208,177,208,\n190,209,130,208,176,208,162,208,190,208,187,209,140,208,186,208,190,209,129,208,\n190,208,178,209,129,208,181,208,188,208,178,209,130,208,190,209,128,208,190,208,\n185,208,189,208,176,209,135,208,176,208,187,208,176,209,129,208,191,208,184,209,\n129,208,190,208,186,209,129,208,187,209,131,208,182,208,177,209,139,209,129,208,\n184,209,129,209,130,208,181,208,188,208,191,208,181,209,135,208,176,209,130,208,\n184,208,189,208,190,208,178,208,190,208,179,208,190,208,191,208,190,208,188,208,\n190,209,137,208,184,209,129,208,176,208,185,209,130,208,190,208,178,208,191,208,\n190,209,135,208,181,208,188,209,131,208,191,208,190,208,188,208,190,209,137,209,\n140,208,180,208,190,208,187,208,182,208,189,208,190,209,129,209,129,209,139,208,\n187,208,186,208,184,208,177,209,139,209,129,209,130,209,128,208,190,208,180,208,\n176,208,189,208,189,209,139,208,181,208,188,208,189,208,190,208,179,208,184,208,\n181,208,191,209,128,208,190,208,181,208,186,209,130,208,161,208,181,208,185,209,\n135,208,176,209,129,208,188,208,190,208,180,208,181,208,187,208,184,209,130,208,\n176,208,186,208,190,208,179,208,190,208,190,208,189,208,187,208,176,208,185,208,\n189,208,179,208,190,209,128,208,190,208,180,208,181,208,178,208,181,209,128,209,\n129,208,184,209,143,209,129,209,130,209,128,208,176,208,189,208,181,209,132,208,\n184,208,187,209,140,208,188,209,139,209,131,209,128,208,190,208,178,208,189,209,\n143,209,128,208,176,208,183,208,189,209,139,209,133,208,184,209,129,208,186,208,\n176,209,130,209,140,208,189,208,181,208,180,208,181,208,187,209,142,209,143,208,\n189,208,178,208,176,209,128,209,143,208,188,208,181,208,189,209,140,209,136,208,\n181,208,188,208,189,208,190,208,179,208,184,209,133,208,180,208,176,208,189,208,\n189,208,190,208,185,208,183,208,189,208,176,209,135,208,184,209,130,208,189,208,\n181,208,187,209,140,208,183,209,143,209,132,208,190,209,128,209,131,208,188,208,\n176,208,162,208,181,208,191,208,181,209,128,209,140,208,188,208,181,209,129,209,\n143,209,134,208,176,208,183,208,176,209,137,208,184,209,130,209,139,208,155,209,\n131,209,135,209,136,208,184,208,181,224,164,168,224,164,185,224,165,128,224,164,\n130,224,164,149,224,164,176,224,164,168,224,165,135,224,164,133,224,164,170,224,\n164,168,224,165,135,224,164,149,224,164,191,224,164,175,224,164,190,224,164,149,\n224,164,176,224,165,135,224,164,130,224,164,133,224,164,168,224,165,141,224,164,\n175,224,164,149,224,165,141,224,164,175,224,164,190,224,164,151,224,164,190,224,\n164,135,224,164,161,224,164,172,224,164,190,224,164,176,224,165,135,224,164,149,\n224,164,191,224,164,184,224,165,128,224,164,166,224,164,191,224,164,175,224,164,\n190,224,164,170,224,164,185,224,164,178,224,165,135,224,164,184,224,164,191,224,\n164,130,224,164,185,224,164,173,224,164,190,224,164,176,224,164,164,224,164,133,\n224,164,170,224,164,168,224,165,128,224,164,181,224,164,190,224,164,178,224,165,\n135,224,164,184,224,165,135,224,164,181,224,164,190,224,164,149,224,164,176,224,\n164,164,224,165,135,224,164,174,224,165,135,224,164,176,224,165,135,224,164,185,\n224,165,139,224,164,168,224,165,135,224,164,184,224,164,149,224,164,164,224,165,\n135,224,164,172,224,164,185,224,165,129,224,164,164,224,164,184,224,164,190,224,\n164,135,224,164,159,224,164,185,224,165,139,224,164,151,224,164,190,224,164,156,\n224,164,190,224,164,168,224,165,135,224,164,174,224,164,191,224,164,168,224,164,\n159,224,164,149,224,164,176,224,164,164,224,164,190,224,164,149,224,164,176,224,\n164,168,224,164,190,224,164,137,224,164,168,224,164,149,224,165,135,224,164,175,\n224,164,185,224,164,190,224,164,129,224,164,184,224,164,172,224,164,184,224,165,\n135,224,164,173,224,164,190,224,164,183,224,164,190,224,164,134,224,164,170,224,\n164,149,224,165,135,224,164,178,224,164,191,224,164,175,224,165,135,224,164,182,\n224,165,129,224,164,176,224,165,130,224,164,135,224,164,184,224,164,149,224,165,\n135,224,164,152,224,164,130,224,164,159,224,165,135,224,164,174,224,165,135,224,\n164,176,224,165,128,224,164,184,224,164,149,224,164,164,224,164,190,224,164,174,\n224,165,135,224,164,176,224,164,190,224,164,178,224,165,135,224,164,149,224,164,\n176,224,164,133,224,164,167,224,164,191,224,164,149,224,164,133,224,164,170,224,\n164,168,224,164,190,224,164,184,224,164,174,224,164,190,224,164,156,224,164,174,\n224,165,129,224,164,157,224,165,135,224,164,149,224,164,190,224,164,176,224,164,\n163,224,164,185,224,165,139,224,164,164,224,164,190,224,164,149,224,164,161,224,\n164,188,224,165,128,224,164,175,224,164,185,224,164,190,224,164,130,224,164,185,\n224,165,139,224,164,159,224,164,178,224,164,182,224,164,172,224,165,141,224,164,\n166,224,164,178,224,164,191,224,164,175,224,164,190,224,164,156,224,165,128,224,\n164,181,224,164,168,224,164,156,224,164,190,224,164,164,224,164,190,224,164,149,\n224,165,136,224,164,184,224,165,135,224,164,134,224,164,170,224,164,149,224,164,\n190,224,164,181,224,164,190,224,164,178,224,165,128,224,164,166,224,165,135,224,\n164,168,224,165,135,224,164,170,224,165,130,224,164,176,224,165,128,224,164,170,\n224,164,190,224,164,168,224,165,128,224,164,137,224,164,184,224,164,149,224,165,\n135,224,164,185,224,165,139,224,164,151,224,165,128,224,164,172,224,165,136,224,\n164,160,224,164,149,224,164,134,224,164,170,224,164,149,224,165,128,224,164,181,\n224,164,176,224,165,141,224,164,183,224,164,151,224,164,190,224,164,130,224,164,\n181,224,164,134,224,164,170,224,164,149,224,165,139,224,164,156,224,164,191,224,\n164,178,224,164,190,224,164,156,224,164,190,224,164,168,224,164,190,224,164,184,\n224,164,185,224,164,174,224,164,164,224,164,185,224,164,174,224,165,135,224,164,\n130,224,164,137,224,164,168,224,164,149,224,165,128,224,164,175,224,164,190,224,\n164,185,224,165,130,224,164,166,224,164,176,224,165,141,224,164,156,224,164,184,\n224,165,130,224,164,154,224,165,128,224,164,170,224,164,184,224,164,130,224,164,\n166,224,164,184,224,164,181,224,164,190,224,164,178,224,164,185,224,165,139,224,\n164,168,224,164,190,224,164,185,224,165,139,224,164,164,224,165,128,224,164,156,\n224,165,136,224,164,184,224,165,135,224,164,181,224,164,190,224,164,170,224,164,\n184,224,164,156,224,164,168,224,164,164,224,164,190,224,164,168,224,165,135,224,\n164,164,224,164,190,224,164,156,224,164,190,224,164,176,224,165,128,224,164,152,\n224,164,190,224,164,175,224,164,178,224,164,156,224,164,191,224,164,178,224,165,\n135,224,164,168,224,165,128,224,164,154,224,165,135,224,164,156,224,164,190,224,\n164,130,224,164,154,224,164,170,224,164,164,224,165,141,224,164,176,224,164,151,\n224,165,130,224,164,151,224,164,178,224,164,156,224,164,190,224,164,164,224,165,\n135,224,164,172,224,164,190,224,164,185,224,164,176,224,164,134,224,164,170,224,\n164,168,224,165,135,224,164,181,224,164,190,224,164,185,224,164,168,224,164,135,\n224,164,184,224,164,149,224,164,190,224,164,184,224,165,129,224,164,172,224,164,\n185,224,164,176,224,164,185,224,164,168,224,165,135,224,164,135,224,164,184,224,\n164,184,224,165,135,224,164,184,224,164,185,224,164,191,224,164,164,224,164,172,\n224,164,161,224,164,188,224,165,135,224,164,152,224,164,159,224,164,168,224,164,\n190,224,164,164,224,164,178,224,164,190,224,164,182,224,164,170,224,164,190,224,\n164,130,224,164,154,224,164,182,224,165,141,224,164,176,224,165,128,224,164,172,\n224,164,161,224,164,188,224,165,128,224,164,185,224,165,139,224,164,164,224,165,\n135,224,164,184,224,164,190,224,164,136,224,164,159,224,164,182,224,164,190,224,\n164,175,224,164,166,224,164,184,224,164,149,224,164,164,224,165,128,224,164,156,\n224,164,190,224,164,164,224,165,128,224,164,181,224,164,190,224,164,178,224,164,\n190,224,164,185,224,164,156,224,164,190,224,164,176,224,164,170,224,164,159,224,\n164,168,224,164,190,224,164,176,224,164,150,224,164,168,224,165,135,224,164,184,\n224,164,161,224,164,188,224,164,149,224,164,174,224,164,191,224,164,178,224,164,\n190,224,164,137,224,164,184,224,164,149,224,165,128,224,164,149,224,165,135,224,\n164,181,224,164,178,224,164,178,224,164,151,224,164,164,224,164,190,224,164,150,\n224,164,190,224,164,168,224,164,190,224,164,133,224,164,176,224,165,141,224,164,\n165,224,164,156,224,164,185,224,164,190,224,164,130,224,164,166,224,165,135,224,\n164,150,224,164,190,224,164,170,224,164,185,224,164,178,224,165,128,224,164,168,\n224,164,191,224,164,175,224,164,174,224,164,172,224,164,191,224,164,168,224,164,\n190,224,164,172,224,165,136,224,164,130,224,164,149,224,164,149,224,164,185,224,\n165,128,224,164,130,224,164,149,224,164,185,224,164,168,224,164,190,224,164,166,\n224,165,135,224,164,164,224,164,190,224,164,185,224,164,174,224,164,178,224,165,\n135,224,164,149,224,164,190,224,164,171,224,165,128,224,164,156,224,164,172,224,\n164,149,224,164,191,224,164,164,224,165,129,224,164,176,224,164,164,224,164,174,\n224,164,190,224,164,130,224,164,151,224,164,181,224,164,185,224,165,128,224,164,\n130,224,164,176,224,165,139,224,164,156,224,164,188,224,164,174,224,164,191,224,\n164,178,224,165,128,224,164,134,224,164,176,224,165,139,224,164,170,224,164,184,\n224,165,135,224,164,168,224,164,190,224,164,175,224,164,190,224,164,166,224,164,\n181,224,164,178,224,165,135,224,164,168,224,165,135,224,164,150,224,164,190,224,\n164,164,224,164,190,224,164,149,224,164,176,224,165,128,224,164,172,224,164,137,\n224,164,168,224,164,149,224,164,190,224,164,156,224,164,181,224,164,190,224,164,\n172,224,164,170,224,165,130,224,164,176,224,164,190,224,164,172,224,164,161,224,\n164,188,224,164,190,224,164,184,224,165,140,224,164,166,224,164,190,224,164,182,\n224,165,135,224,164,175,224,164,176,224,164,149,224,164,191,224,164,175,224,165,\n135,224,164,149,224,164,185,224,164,190,224,164,130,224,164,133,224,164,149,224,\n164,184,224,164,176,224,164,172,224,164,168,224,164,190,224,164,143,224,164,181,\n224,164,185,224,164,190,224,164,130,224,164,184,224,165,141,224,164,165,224,164,\n178,224,164,174,224,164,191,224,164,178,224,165,135,224,164,178,224,165,135,224,\n164,150,224,164,149,224,164,181,224,164,191,224,164,183,224,164,175,224,164,149,\n224,165,141,224,164,176,224,164,130,224,164,184,224,164,174,224,165,130,224,164,\n185,224,164,165,224,164,190,224,164,168,224,164,190,216,170,216,179,216,170,216,\n183,217,138,216,185,217,133,216,180,216,167,216,177,217,131,216,169,216,168,217,\n136,216,167,216,179,216,183,216,169,216,167,217,132,216,181,217,129,216,173,216,\n169,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,174,216,\n167,216,181,216,169,216,167,217,132,217,133,216,178,217,138,216,175,216,167,217,\n132,216,185,216,167,217,133,216,169,216,167,217,132,217,131,216,167,216,170,216,\n168,216,167,217,132,216,177,216,175,217,136,216,175,216,168,216,177,217,134,216,\n167,217,133,216,172,216,167,217,132,216,175,217,136,217,132,216,169,216,167,217,\n132,216,185,216,167,217,132,217,133,216,167,217,132,217,133,217,136,217,130,216,\n185,216,167,217,132,216,185,216,177,216,168,217,138,216,167,217,132,216,179,216,\n177,217,138,216,185,216,167,217,132,216,172,217,136,216,167,217,132,216,167,217,\n132,216,176,217,135,216,167,216,168,216,167,217,132,216,173,217,138,216,167,216,\n169,216,167,217,132,216,173,217,130,217,136,217,130,216,167,217,132,217,131,216,\n177,217,138,217,133,216,167,217,132,216,185,216,177,216,167,217,130,217,133,216,\n173,217,129,217,136,216,184,216,169,216,167,217,132,216,171,216,167,217,134,217,\n138,217,133,216,180,216,167,217,135,216,175,216,169,216,167,217,132,217,133,216,\n177,216,163,216,169,216,167,217,132,217,130,216,177,216,162,217,134,216,167,217,\n132,216,180,216,168,216,167,216,168,216,167,217,132,216,173,217,136,216,167,216,\n177,216,167,217,132,216,172,216,175,217,138,216,175,216,167,217,132,216,163,216,\n179,216,177,216,169,216,167,217,132,216,185,217,132,217,136,217,133,217,133,216,\n172,217,133,217,136,216,185,216,169,216,167,217,132,216,177,216,173,217,133,217,\n134,216,167,217,132,217,134,217,130,216,167,216,183,217,129,217,132,216,179,216,\n183,217,138,217,134,216,167,217,132,217,131,217,136,217,138,216,170,216,167,217,\n132,216,175,217,134,217,138,216,167,216,168,216,177,217,131,216,167,216,170,217,\n135,216,167,217,132,216,177,217,138,216,167,216,182,216,170,216,173,217,138,216,\n167,216,170,217,138,216,168,216,170,217,136,217,130,217,138,216,170,216,167,217,\n132,216,163,217,136,217,132,217,137,216,167,217,132,216,168,216,177,217,138,216,\n175,216,167,217,132,217,131,217,132,216,167,217,133,216,167,217,132,216,177,216,\n167,216,168,216,183,216,167,217,132,216,180,216,174,216,181,217,138,216,179,217,\n138,216,167,216,177,216,167,216,170,216,167,217,132,216,171,216,167,217,132,216,\n171,216,167,217,132,216,181,217,132,216,167,216,169,216,167,217,132,216,173,216,\n175,217,138,216,171,216,167,217,132,216,178,217,136,216,167,216,177,216,167,217,\n132,216,174,217,132,217,138,216,172,216,167,217,132,216,172,217,133,217,138,216,\n185,216,167,217,132,216,185,216,167,217,133,217,135,216,167,217,132,216,172,217,\n133,216,167,217,132,216,167,217,132,216,179,216,167,216,185,216,169,217,133,216,\n180,216,167,217,135,216,175,217,135,216,167,217,132,216,177,216,166,217,138,216,\n179,216,167,217,132,216,175,216,174,217,136,217,132,216,167,217,132,217,129,217,\n134,217,138,216,169,216,167,217,132,217,131,216,170,216,167,216,168,216,167,217,\n132,216,175,217,136,216,177,217,138,216,167,217,132,216,175,216,177,217,136,216,\n179,216,167,216,179,216,170,216,186,216,177,217,130,216,170,216,181,216,167,217,\n133,217,138,217,133,216,167,217,132,216,168,217,134,216,167,216,170,216,167,217,\n132,216,185,216,184,217,138,217,133,101,110,116,101,114,116,97,105,110,109,101,\n110,116,117,110,100,101,114,115,116,97,110,100,105,110,103,32,61,32,102,117,110,\n99,116,105,111,110,40,41,46,106,112,103,34,32,119,105,100,116,104,61,34,99,111,\n110,102,105,103,117,114,97,116,105,111,110,46,112,110,103,34,32,119,105,100,116,\n104,61,34,60,98,111,100,121,32,99,108,97,115,115,61,34,77,97,116,104,46,114,97,\n110,100,111,109,40,41,99,111,110,116,101,109,112,111,114,97,114,121,32,85,110,\n105,116,101,100,32,83,116,97,116,101,115,99,105,114,99,117,109,115,116,97,110,99\n,101,115,46,97,112,112,101,110,100,67,104,105,108,100,40,111,114,103,97,110,105,\n122,97,116,105,111,110,115,60,115,112,97,110,32,99,108,97,115,115,61,34,34,62,60\n,105,109,103,32,115,114,99,61,34,47,100,105,115,116,105,110,103,117,105,115,104,\n101,100,116,104,111,117,115,97,110,100,115,32,111,102,32,99,111,109,109,117,110,\n105,99,97,116,105,111,110,99,108,101,97,114,34,62,60,47,100,105,118,62,105,110,\n118,101,115,116,105,103,97,116,105,111,110,102,97,118,105,99,111,110,46,105,99,\n111,34,32,109,97,114,103,105,110,45,114,105,103,104,116,58,98,97,115,101,100,32,\n111,110,32,116,104,101,32,77,97,115,115,97,99,104,117,115,101,116,116,115,116,97\n,98,108,101,32,98,111,114,100,101,114,61,105,110,116,101,114,110,97,116,105,111,\n110,97,108,97,108,115,111,32,107,110,111,119,110,32,97,115,112,114,111,110,117,\n110,99,105,97,116,105,111,110,98,97,99,107,103,114,111,117,110,100,58,35,102,112\n,97,100,100,105,110,103,45,108,101,102,116,58,70,111,114,32,101,120,97,109,112,\n108,101,44,32,109,105,115,99,101,108,108,97,110,101,111,117,115,38,108,116,59,47\n,109,97,116,104,38,103,116,59,112,115,121,99,104,111,108,111,103,105,99,97,108,\n105,110,32,112,97,114,116,105,99,117,108,97,114,101,97,114,99,104,34,32,116,121,\n112,101,61,34,102,111,114,109,32,109,101,116,104,111,100,61,34,97,115,32,111,112\n,112,111,115,101,100,32,116,111,83,117,112,114,101,109,101,32,67,111,117,114,116\n,111,99,99,97,115,105,111,110,97,108,108,121,32,65,100,100,105,116,105,111,110,\n97,108,108,121,44,78,111,114,116,104,32,65,109,101,114,105,99,97,112,120,59,98,\n97,99,107,103,114,111,117,110,100,111,112,112,111,114,116,117,110,105,116,105,\n101,115,69,110,116,101,114,116,97,105,110,109,101,110,116,46,116,111,76,111,119,\n101,114,67,97,115,101,40,109,97,110,117,102,97,99,116,117,114,105,110,103,112,\n114,111,102,101,115,115,105,111,110,97,108,32,99,111,109,98,105,110,101,100,32,\n119,105,116,104,70,111,114,32,105,110,115,116,97,110,99,101,44,99,111,110,115,\n105,115,116,105,110,103,32,111,102,34,32,109,97,120,108,101,110,103,116,104,61,\n34,114,101,116,117,114,110,32,102,97,108,115,101,59,99,111,110,115,99,105,111,\n117,115,110,101,115,115,77,101,100,105,116,101,114,114,97,110,101,97,110,101,120\n,116,114,97,111,114,100,105,110,97,114,121,97,115,115,97,115,115,105,110,97,116,\n105,111,110,115,117,98,115,101,113,117,101,110,116,108,121,32,98,117,116,116,111\n,110,32,116,121,112,101,61,34,116,104,101,32,110,117,109,98,101,114,32,111,102,\n116,104,101,32,111,114,105,103,105,110,97,108,32,99,111,109,112,114,101,104,101,\n110,115,105,118,101,114,101,102,101,114,115,32,116,111,32,116,104,101,60,47,117,\n108,62,10,60,47,100,105,118,62,10,112,104,105,108,111,115,111,112,104,105,99,97,\n108,108,111,99,97,116,105,111,110,46,104,114,101,102,119,97,115,32,112,117,98,\n108,105,115,104,101,100,83,97,110,32,70,114,97,110,99,105,115,99,111,40,102,117,\n110,99,116,105,111,110,40,41,123,10,60,100,105,118,32,105,100,61,34,109,97,105,\n110,115,111,112,104,105,115,116,105,99,97,116,101,100,109,97,116,104,101,109,97,\n116,105,99,97,108,32,47,104,101,97,100,62,13,10,60,98,111,100,121,115,117,103,\n103,101,115,116,115,32,116,104,97,116,100,111,99,117,109,101,110,116,97,116,105,\n111,110,99,111,110,99,101,110,116,114,97,116,105,111,110,114,101,108,97,116,105,\n111,110,115,104,105,112,115,109,97,121,32,104,97,118,101,32,98,101,101,110,40,\n102,111,114,32,101,120,97,109,112,108,101,44,84,104,105,115,32,97,114,116,105,99\n,108,101,32,105,110,32,115,111,109,101,32,99,97,115,101,115,112,97,114,116,115,\n32,111,102,32,116,104,101,32,100,101,102,105,110,105,116,105,111,110,32,111,102,\n71,114,101,97,116,32,66,114,105,116,97,105,110,32,99,101,108,108,112,97,100,100,\n105,110,103,61,101,113,117,105,118,97,108,101,110,116,32,116,111,112,108,97,99,\n101,104,111,108,100,101,114,61,34,59,32,102,111,110,116,45,115,105,122,101,58,32\n,106,117,115,116,105,102,105,99,97,116,105,111,110,98,101,108,105,101,118,101,\n100,32,116,104,97,116,115,117,102,102,101,114,101,100,32,102,114,111,109,97,116,\n116,101,109,112,116,101,100,32,116,111,32,108,101,97,100,101,114,32,111,102,32,\n116,104,101,99,114,105,112,116,34,32,115,114,99,61,34,47,40,102,117,110,99,116,\n105,111,110,40,41,32,123,97,114,101,32,97,118,97,105,108,97,98,108,101,10,9,60,\n108,105,110,107,32,114,101,108,61,34,32,115,114,99,61,39,104,116,116,112,58,47,\n47,105,110,116,101,114,101,115,116,101,100,32,105,110,99,111,110,118,101,110,116\n,105,111,110,97,108,32,34,32,97,108,116,61,34,34,32,47,62,60,47,97,114,101,32,\n103,101,110,101,114,97,108,108,121,104,97,115,32,97,108,115,111,32,98,101,101,\n110,109,111,115,116,32,112,111,112,117,108,97,114,32,99,111,114,114,101,115,112,\n111,110,100,105,110,103,99,114,101,100,105,116,101,100,32,119,105,116,104,116,\n121,108,101,61,34,98,111,114,100,101,114,58,60,47,97,62,60,47,115,112,97,110,62,\n60,47,46,103,105,102,34,32,119,105,100,116,104,61,34,60,105,102,114,97,109,101,\n32,115,114,99,61,34,116,97,98,108,101,32,99,108,97,115,115,61,34,105,110,108,105\n,110,101,45,98,108,111,99,107,59,97,99,99,111,114,100,105,110,103,32,116,111,32,\n116,111,103,101,116,104,101,114,32,119,105,116,104,97,112,112,114,111,120,105,\n109,97,116,101,108,121,112,97,114,108,105,97,109,101,110,116,97,114,121,109,111,\n114,101,32,97,110,100,32,109,111,114,101,100,105,115,112,108,97,121,58,110,111,\n110,101,59,116,114,97,100,105,116,105,111,110,97,108,108,121,112,114,101,100,111\n,109,105,110,97,110,116,108,121,38,110,98,115,112,59,124,38,110,98,115,112,59,38\n,110,98,115,112,59,60,47,115,112,97,110,62,32,99,101,108,108,115,112,97,99,105,\n110,103,61,60,105,110,112,117,116,32,110,97,109,101,61,34,111,114,34,32,99,111,\n110,116,101,110,116,61,34,99,111,110,116,114,111,118,101,114,115,105,97,108,112,\n114,111,112,101,114,116,121,61,34,111,103,58,47,120,45,115,104,111,99,107,119,97\n,118,101,45,100,101,109,111,110,115,116,114,97,116,105,111,110,115,117,114,114,\n111,117,110,100,101,100,32,98,121,78,101,118,101,114,116,104,101,108,101,115,115\n,44,119,97,115,32,116,104,101,32,102,105,114,115,116,99,111,110,115,105,100,101,\n114,97,98,108,101,32,65,108,116,104,111,117,103,104,32,116,104,101,32,99,111,108\n,108,97,98,111,114,97,116,105,111,110,115,104,111,117,108,100,32,110,111,116,32,\n98,101,112,114,111,112,111,114,116,105,111,110,32,111,102,60,115,112,97,110,32,\n115,116,121,108,101,61,34,107,110,111,119,110,32,97,115,32,116,104,101,32,115,\n104,111,114,116,108,121,32,97,102,116,101,114,102,111,114,32,105,110,115,116,97,\n110,99,101,44,100,101,115,99,114,105,98,101,100,32,97,115,32,47,104,101,97,100,\n62,10,60,98,111,100,121,32,115,116,97,114,116,105,110,103,32,119,105,116,104,105\n,110,99,114,101,97,115,105,110,103,108,121,32,116,104,101,32,102,97,99,116,32,\n116,104,97,116,100,105,115,99,117,115,115,105,111,110,32,111,102,109,105,100,100\n,108,101,32,111,102,32,116,104,101,97,110,32,105,110,100,105,118,105,100,117,97,\n108,100,105,102,102,105,99,117,108,116,32,116,111,32,112,111,105,110,116,32,111,\n102,32,118,105,101,119,104,111,109,111,115,101,120,117,97,108,105,116,121,97,99,\n99,101,112,116,97,110,99,101,32,111,102,60,47,115,112,97,110,62,60,47,100,105,\n118,62,109,97,110,117,102,97,99,116,117,114,101,114,115,111,114,105,103,105,110,\n32,111,102,32,116,104,101,99,111,109,109,111,110,108,121,32,117,115,101,100,105,\n109,112,111,114,116,97,110,99,101,32,111,102,100,101,110,111,109,105,110,97,116,\n105,111,110,115,98,97,99,107,103,114,111,117,110,100,58,32,35,108,101,110,103,\n116,104,32,111,102,32,116,104,101,100,101,116,101,114,109,105,110,97,116,105,111\n,110,97,32,115,105,103,110,105,102,105,99,97,110,116,34,32,98,111,114,100,101,\n114,61,34,48,34,62,114,101,118,111,108,117,116,105,111,110,97,114,121,112,114,\n105,110,99,105,112,108,101,115,32,111,102,105,115,32,99,111,110,115,105,100,101,\n114,101,100,119,97,115,32,100,101,118,101,108,111,112,101,100,73,110,100,111,45,\n69,117,114,111,112,101,97,110,118,117,108,110,101,114,97,98,108,101,32,116,111,\n112,114,111,112,111,110,101,110,116,115,32,111,102,97,114,101,32,115,111,109,101\n,116,105,109,101,115,99,108,111,115,101,114,32,116,111,32,116,104,101,78,101,119\n,32,89,111,114,107,32,67,105,116,121,32,110,97,109,101,61,34,115,101,97,114,99,\n104,97,116,116,114,105,98,117,116,101,100,32,116,111,99,111,117,114,115,101,32,\n111,102,32,116,104,101,109,97,116,104,101,109,97,116,105,99,105,97,110,98,121,32\n,116,104,101,32,101,110,100,32,111,102,97,116,32,116,104,101,32,101,110,100,32,\n111,102,34,32,98,111,114,100,101,114,61,34,48,34,32,116,101,99,104,110,111,108,\n111,103,105,99,97,108,46,114,101,109,111,118,101,67,108,97,115,115,40,98,114,97,\n110,99,104,32,111,102,32,116,104,101,101,118,105,100,101,110,99,101,32,116,104,\n97,116,33,91,101,110,100,105,102,93,45,45,62,13,10,73,110,115,116,105,116,117,\n116,101,32,111,102,32,105,110,116,111,32,97,32,115,105,110,103,108,101,114,101,\n115,112,101,99,116,105,118,101,108,121,46,97,110,100,32,116,104,101,114,101,102,\n111,114,101,112,114,111,112,101,114,116,105,101,115,32,111,102,105,115,32,108,\n111,99,97,116,101,100,32,105,110,115,111,109,101,32,111,102,32,119,104,105,99,\n104,84,104,101,114,101,32,105,115,32,97,108,115,111,99,111,110,116,105,110,117,\n101,100,32,116,111,32,97,112,112,101,97,114,97,110,99,101,32,111,102,32,38,97,\n109,112,59,110,100,97,115,104,59,32,100,101,115,99,114,105,98,101,115,32,116,104\n,101,99,111,110,115,105,100,101,114,97,116,105,111,110,97,117,116,104,111,114,32\n,111,102,32,116,104,101,105,110,100,101,112,101,110,100,101,110,116,108,121,101,\n113,117,105,112,112,101,100,32,119,105,116,104,100,111,101,115,32,110,111,116,32\n,104,97,118,101,60,47,97,62,60,97,32,104,114,101,102,61,34,99,111,110,102,117,\n115,101,100,32,119,105,116,104,60,108,105,110,107,32,104,114,101,102,61,34,47,97\n,116,32,116,104,101,32,97,103,101,32,111,102,97,112,112,101,97,114,32,105,110,32\n,116,104,101,84,104,101,115,101,32,105,110,99,108,117,100,101,114,101,103,97,114\n,100,108,101,115,115,32,111,102,99,111,117,108,100,32,98,101,32,117,115,101,100,\n32,115,116,121,108,101,61,38,113,117,111,116,59,115,101,118,101,114,97,108,32,\n116,105,109,101,115,114,101,112,114,101,115,101,110,116,32,116,104,101,98,111,\n100,121,62,10,60,47,104,116,109,108,62,116,104,111,117,103,104,116,32,116,111,32\n,98,101,112,111,112,117,108,97,116,105,111,110,32,111,102,112,111,115,115,105,98\n,105,108,105,116,105,101,115,112,101,114,99,101,110,116,97,103,101,32,111,102,97\n,99,99,101,115,115,32,116,111,32,116,104,101,97,110,32,97,116,116,101,109,112,\n116,32,116,111,112,114,111,100,117,99,116,105,111,110,32,111,102,106,113,117,101\n,114,121,47,106,113,117,101,114,121,116,119,111,32,100,105,102,102,101,114,101,\n110,116,98,101,108,111,110,103,32,116,111,32,116,104,101,101,115,116,97,98,108,\n105,115,104,109,101,110,116,114,101,112,108,97,99,105,110,103,32,116,104,101,100\n,101,115,99,114,105,112,116,105,111,110,34,32,100,101,116,101,114,109,105,110,\n101,32,116,104,101,97,118,97,105,108,97,98,108,101,32,102,111,114,65,99,99,111,\n114,100,105,110,103,32,116,111,32,119,105,100,101,32,114,97,110,103,101,32,111,\n102,9,60,100,105,118,32,99,108,97,115,115,61,34,109,111,114,101,32,99,111,109,\n109,111,110,108,121,111,114,103,97,110,105,115,97,116,105,111,110,115,102,117,\n110,99,116,105,111,110,97,108,105,116,121,119,97,115,32,99,111,109,112,108,101,\n116,101,100,32,38,97,109,112,59,109,100,97,115,104,59,32,112,97,114,116,105,99,\n105,112,97,116,105,111,110,116,104,101,32,99,104,97,114,97,99,116,101,114,97,110\n,32,97,100,100,105,116,105,111,110,97,108,97,112,112,101,97,114,115,32,116,111,\n32,98,101,102,97,99,116,32,116,104,97,116,32,116,104,101,97,110,32,101,120,97,\n109,112,108,101,32,111,102,115,105,103,110,105,102,105,99,97,110,116,108,121,111\n,110,109,111,117,115,101,111,118,101,114,61,34,98,101,99,97,117,115,101,32,116,\n104,101,121,32,97,115,121,110,99,32,61,32,116,114,117,101,59,112,114,111,98,108,\n101,109,115,32,119,105,116,104,115,101,101,109,115,32,116,111,32,104,97,118,101,\n116,104,101,32,114,101,115,117,108,116,32,111,102,32,115,114,99,61,34,104,116,\n116,112,58,47,47,102,97,109,105,108,105,97,114,32,119,105,116,104,112,111,115,\n115,101,115,115,105,111,110,32,111,102,102,117,110,99,116,105,111,110,32,40,41,\n32,123,116,111,111,107,32,112,108,97,99,101,32,105,110,97,110,100,32,115,111,109\n,101,116,105,109,101,115,115,117,98,115,116,97,110,116,105,97,108,108,121,60,115\n,112,97,110,62,60,47,115,112,97,110,62,105,115,32,111,102,116,101,110,32,117,115\n,101,100,105,110,32,97,110,32,97,116,116,101,109,112,116,103,114,101,97,116,32,\n100,101,97,108,32,111,102,69,110,118,105,114,111,110,109,101,110,116,97,108,115,\n117,99,99,101,115,115,102,117,108,108,121,32,118,105,114,116,117,97,108,108,121,\n32,97,108,108,50,48,116,104,32,99,101,110,116,117,114,121,44,112,114,111,102,101\n,115,115,105,111,110,97,108,115,110,101,99,101,115,115,97,114,121,32,116,111,32,\n100,101,116,101,114,109,105,110,101,100,32,98,121,99,111,109,112,97,116,105,98,\n105,108,105,116,121,98,101,99,97,117,115,101,32,105,116,32,105,115,68,105,99,116\n,105,111,110,97,114,121,32,111,102,109,111,100,105,102,105,99,97,116,105,111,110\n,115,84,104,101,32,102,111,108,108,111,119,105,110,103,109,97,121,32,114,101,102\n,101,114,32,116,111,58,67,111,110,115,101,113,117,101,110,116,108,121,44,73,110,\n116,101,114,110,97,116,105,111,110,97,108,97,108,116,104,111,117,103,104,32,115,\n111,109,101,116,104,97,116,32,119,111,117,108,100,32,98,101,119,111,114,108,100,\n39,115,32,102,105,114,115,116,99,108,97,115,115,105,102,105,101,100,32,97,115,98\n,111,116,116,111,109,32,111,102,32,116,104,101,40,112,97,114,116,105,99,117,108,\n97,114,108,121,97,108,105,103,110,61,34,108,101,102,116,34,32,109,111,115,116,32\n,99,111,109,109,111,110,108,121,98,97,115,105,115,32,102,111,114,32,116,104,101,\n102,111,117,110,100,97,116,105,111,110,32,111,102,99,111,110,116,114,105,98,117,\n116,105,111,110,115,112,111,112,117,108,97,114,105,116,121,32,111,102,99,101,110\n,116,101,114,32,111,102,32,116,104,101,116,111,32,114,101,100,117,99,101,32,116,\n104,101,106,117,114,105,115,100,105,99,116,105,111,110,115,97,112,112,114,111,\n120,105,109,97,116,105,111,110,32,111,110,109,111,117,115,101,111,117,116,61,34,\n78,101,119,32,84,101,115,116,97,109,101,110,116,99,111,108,108,101,99,116,105,\n111,110,32,111,102,60,47,115,112,97,110,62,60,47,97,62,60,47,105,110,32,116,104,\n101,32,85,110,105,116,101,100,102,105,108,109,32,100,105,114,101,99,116,111,114,\n45,115,116,114,105,99,116,46,100,116,100,34,62,104,97,115,32,98,101,101,110,32,\n117,115,101,100,114,101,116,117,114,110,32,116,111,32,116,104,101,97,108,116,104\n,111,117,103,104,32,116,104,105,115,99,104,97,110,103,101,32,105,110,32,116,104,\n101,115,101,118,101,114,97,108,32,111,116,104,101,114,98,117,116,32,116,104,101,\n114,101,32,97,114,101,117,110,112,114,101,99,101,100,101,110,116,101,100,105,115\n,32,115,105,109,105,108,97,114,32,116,111,101,115,112,101,99,105,97,108,108,121,\n32,105,110,119,101,105,103,104,116,58,32,98,111,108,100,59,105,115,32,99,97,108,\n108,101,100,32,116,104,101,99,111,109,112,117,116,97,116,105,111,110,97,108,105,\n110,100,105,99,97,116,101,32,116,104,97,116,114,101,115,116,114,105,99,116,101,\n100,32,116,111,9,60,109,101,116,97,32,110,97,109,101,61,34,97,114,101,32,116,121\n,112,105,99,97,108,108,121,99,111,110,102,108,105,99,116,32,119,105,116,104,72,\n111,119,101,118,101,114,44,32,116,104,101,32,65,110,32,101,120,97,109,112,108,\n101,32,111,102,99,111,109,112,97,114,101,100,32,119,105,116,104,113,117,97,110,\n116,105,116,105,101,115,32,111,102,114,97,116,104,101,114,32,116,104,97,110,32,\n97,99,111,110,115,116,101,108,108,97,116,105,111,110,110,101,99,101,115,115,97,\n114,121,32,102,111,114,114,101,112,111,114,116,101,100,32,116,104,97,116,115,112\n,101,99,105,102,105,99,97,116,105,111,110,112,111,108,105,116,105,99,97,108,32,\n97,110,100,38,110,98,115,112,59,38,110,98,115,112,59,60,114,101,102,101,114,101,\n110,99,101,115,32,116,111,116,104,101,32,115,97,109,101,32,121,101,97,114,71,111\n,118,101,114,110,109,101,110,116,32,111,102,103,101,110,101,114,97,116,105,111,\n110,32,111,102,104,97,118,101,32,110,111,116,32,98,101,101,110,115,101,118,101,\n114,97,108,32,121,101,97,114,115,99,111,109,109,105,116,109,101,110,116,32,116,\n111,9,9,60,117,108,32,99,108,97,115,115,61,34,118,105,115,117,97,108,105,122,97,\n116,105,111,110,49,57,116,104,32,99,101,110,116,117,114,121,44,112,114,97,99,116\n,105,116,105,111,110,101,114,115,116,104,97,116,32,104,101,32,119,111,117,108,\n100,97,110,100,32,99,111,110,116,105,110,117,101,100,111,99,99,117,112,97,116,\n105,111,110,32,111,102,105,115,32,100,101,102,105,110,101,100,32,97,115,99,101,\n110,116,114,101,32,111,102,32,116,104,101,116,104,101,32,97,109,111,117,110,116,\n32,111,102,62,60,100,105,118,32,115,116,121,108,101,61,34,101,113,117,105,118,97\n,108,101,110,116,32,111,102,100,105,102,102,101,114,101,110,116,105,97,116,101,\n98,114,111,117,103,104,116,32,97,98,111,117,116,109,97,114,103,105,110,45,108,\n101,102,116,58,32,97,117,116,111,109,97,116,105,99,97,108,108,121,116,104,111,\n117,103,104,116,32,111,102,32,97,115,83,111,109,101,32,111,102,32,116,104,101,\n115,101,10,60,100,105,118,32,99,108,97,115,115,61,34,105,110,112,117,116,32,99,\n108,97,115,115,61,34,114,101,112,108,97,99,101,100,32,119,105,116,104,105,115,32\n,111,110,101,32,111,102,32,116,104,101,101,100,117,99,97,116,105,111,110,32,97,\n110,100,105,110,102,108,117,101,110,99,101,100,32,98,121,114,101,112,117,116,97,\n116,105,111,110,32,97,115,10,60,109,101,116,97,32,110,97,109,101,61,34,97,99,99,\n111,109,109,111,100,97,116,105,111,110,60,47,100,105,118,62,10,60,47,100,105,118\n,62,108,97,114,103,101,32,112,97,114,116,32,111,102,73,110,115,116,105,116,117,\n116,101,32,102,111,114,116,104,101,32,115,111,45,99,97,108,108,101,100,32,97,103\n,97,105,110,115,116,32,116,104,101,32,73,110,32,116,104,105,115,32,99,97,115,101\n,44,119,97,115,32,97,112,112,111,105,110,116,101,100,99,108,97,105,109,101,100,\n32,116,111,32,98,101,72,111,119,101,118,101,114,44,32,116,104,105,115,68,101,112\n,97,114,116,109,101,110,116,32,111,102,116,104,101,32,114,101,109,97,105,110,105\n,110,103,101,102,102,101,99,116,32,111,110,32,116,104,101,112,97,114,116,105,99,\n117,108,97,114,108,121,32,100,101,97,108,32,119,105,116,104,32,116,104,101,10,60\n,100,105,118,32,115,116,121,108,101,61,34,97,108,109,111,115,116,32,97,108,119,\n97,121,115,97,114,101,32,99,117,114,114,101,110,116,108,121,101,120,112,114,101,\n115,115,105,111,110,32,111,102,112,104,105,108,111,115,111,112,104,121,32,111,\n102,102,111,114,32,109,111,114,101,32,116,104,97,110,99,105,118,105,108,105,122,\n97,116,105,111,110,115,111,110,32,116,104,101,32,105,115,108,97,110,100,115,101,\n108,101,99,116,101,100,73,110,100,101,120,99,97,110,32,114,101,115,117,108,116,\n32,105,110,34,32,118,97,108,117,101,61,34,34,32,47,62,116,104,101,32,115,116,114\n,117,99,116,117,114,101,32,47,62,60,47,97,62,60,47,100,105,118,62,77,97,110,121,\n32,111,102,32,116,104,101,115,101,99,97,117,115,101,100,32,98,121,32,116,104,101\n,111,102,32,116,104,101,32,85,110,105,116,101,100,115,112,97,110,32,99,108,97,\n115,115,61,34,109,99,97,110,32,98,101,32,116,114,97,99,101,100,105,115,32,114,\n101,108,97,116,101,100,32,116,111,98,101,99,97,109,101,32,111,110,101,32,111,102\n,105,115,32,102,114,101,113,117,101,110,116,108,121,108,105,118,105,110,103,32,\n105,110,32,116,104,101,116,104,101,111,114,101,116,105,99,97,108,108,121,70,111,\n108,108,111,119,105,110,103,32,116,104,101,82,101,118,111,108,117,116,105,111,\n110,97,114,121,103,111,118,101,114,110,109,101,110,116,32,105,110,105,115,32,100\n,101,116,101,114,109,105,110,101,100,116,104,101,32,112,111,108,105,116,105,99,\n97,108,105,110,116,114,111,100,117,99,101,100,32,105,110,115,117,102,102,105,99,\n105,101,110,116,32,116,111,100,101,115,99,114,105,112,116,105,111,110,34,62,115,\n104,111,114,116,32,115,116,111,114,105,101,115,115,101,112,97,114,97,116,105,111\n,110,32,111,102,97,115,32,116,111,32,119,104,101,116,104,101,114,107,110,111,119\n,110,32,102,111,114,32,105,116,115,119,97,115,32,105,110,105,116,105,97,108,108,\n121,100,105,115,112,108,97,121,58,98,108,111,99,107,105,115,32,97,110,32,101,120\n,97,109,112,108,101,116,104,101,32,112,114,105,110,99,105,112,97,108,99,111,110,\n115,105,115,116,115,32,111,102,32,97,114,101,99,111,103,110,105,122,101,100,32,\n97,115,47,98,111,100,121,62,60,47,104,116,109,108,62,97,32,115,117,98,115,116,97\n,110,116,105,97,108,114,101,99,111,110,115,116,114,117,99,116,101,100,104,101,97\n,100,32,111,102,32,115,116,97,116,101,114,101,115,105,115,116,97,110,99,101,32,\n116,111,117,110,100,101,114,103,114,97,100,117,97,116,101,84,104,101,114,101,32,\n97,114,101,32,116,119,111,103,114,97,118,105,116,97,116,105,111,110,97,108,97,\n114,101,32,100,101,115,99,114,105,98,101,100,105,110,116,101,110,116,105,111,110\n,97,108,108,121,115,101,114,118,101,100,32,97,115,32,116,104,101,99,108,97,115,\n115,61,34,104,101,97,100,101,114,111,112,112,111,115,105,116,105,111,110,32,116,\n111,102,117,110,100,97,109,101,110,116,97,108,108,121,100,111,109,105,110,97,116\n,101,100,32,116,104,101,97,110,100,32,116,104,101,32,111,116,104,101,114,97,108,\n108,105,97,110,99,101,32,119,105,116,104,119,97,115,32,102,111,114,99,101,100,32\n,116,111,114,101,115,112,101,99,116,105,118,101,108,121,44,97,110,100,32,112,111\n,108,105,116,105,99,97,108,105,110,32,115,117,112,112,111,114,116,32,111,102,112\n,101,111,112,108,101,32,105,110,32,116,104,101,50,48,116,104,32,99,101,110,116,\n117,114,121,46,97,110,100,32,112,117,98,108,105,115,104,101,100,108,111,97,100,\n67,104,97,114,116,98,101,97,116,116,111,32,117,110,100,101,114,115,116,97,110,\n100,109,101,109,98,101,114,32,115,116,97,116,101,115,101,110,118,105,114,111,110\n,109,101,110,116,97,108,102,105,114,115,116,32,104,97,108,102,32,111,102,99,111,\n117,110,116,114,105,101,115,32,97,110,100,97,114,99,104,105,116,101,99,116,117,\n114,97,108,98,101,32,99,111,110,115,105,100,101,114,101,100,99,104,97,114,97,99,\n116,101,114,105,122,101,100,99,108,101,97,114,73,110,116,101,114,118,97,108,97,\n117,116,104,111,114,105,116,97,116,105,118,101,70,101,100,101,114,97,116,105,111\n,110,32,111,102,119,97,115,32,115,117,99,99,101,101,100,101,100,97,110,100,32,\n116,104,101,114,101,32,97,114,101,97,32,99,111,110,115,101,113,117,101,110,99,\n101,116,104,101,32,80,114,101,115,105,100,101,110,116,97,108,115,111,32,105,110,\n99,108,117,100,101,100,102,114,101,101,32,115,111,102,116,119,97,114,101,115,117\n,99,99,101,115,115,105,111,110,32,111,102,100,101,118,101,108,111,112,101,100,32\n,116,104,101,119,97,115,32,100,101,115,116,114,111,121,101,100,97,119,97,121,32,\n102,114,111,109,32,116,104,101,59,10,60,47,115,99,114,105,112,116,62,10,60,97,\n108,116,104,111,117,103,104,32,116,104,101,121,102,111,108,108,111,119,101,100,\n32,98,121,32,97,109,111,114,101,32,112,111,119,101,114,102,117,108,114,101,115,\n117,108,116,101,100,32,105,110,32,97,85,110,105,118,101,114,115,105,116,121,32,\n111,102,72,111,119,101,118,101,114,44,32,109,97,110,121,116,104,101,32,112,114,\n101,115,105,100,101,110,116,72,111,119,101,118,101,114,44,32,115,111,109,101,105\n,115,32,116,104,111,117,103,104,116,32,116,111,117,110,116,105,108,32,116,104,\n101,32,101,110,100,119,97,115,32,97,110,110,111,117,110,99,101,100,97,114,101,32\n,105,109,112,111,114,116,97,110,116,97,108,115,111,32,105,110,99,108,117,100,101\n,115,62,60,105,110,112,117,116,32,116,121,112,101,61,116,104,101,32,99,101,110,\n116,101,114,32,111,102,32,68,79,32,78,79,84,32,65,76,84,69,82,117,115,101,100,32\n,116,111,32,114,101,102,101,114,116,104,101,109,101,115,47,63,115,111,114,116,61\n,116,104,97,116,32,104,97,100,32,98,101,101,110,116,104,101,32,98,97,115,105,115\n,32,102,111,114,104,97,115,32,100,101,118,101,108,111,112,101,100,105,110,32,116\n,104,101,32,115,117,109,109,101,114,99,111,109,112,97,114,97,116,105,118,101,108\n,121,100,101,115,99,114,105,98,101,100,32,116,104,101,115,117,99,104,32,97,115,\n32,116,104,111,115,101,116,104,101,32,114,101,115,117,108,116,105,110,103,105,\n115,32,105,109,112,111,115,115,105,98,108,101,118,97,114,105,111,117,115,32,111,\n116,104,101,114,83,111,117,116,104,32,65,102,114,105,99,97,110,104,97,118,101,32\n,116,104,101,32,115,97,109,101,101,102,102,101,99,116,105,118,101,110,101,115,\n115,105,110,32,119,104,105,99,104,32,99,97,115,101,59,32,116,101,120,116,45,97,\n108,105,103,110,58,115,116,114,117,99,116,117,114,101,32,97,110,100,59,32,98,97,\n99,107,103,114,111,117,110,100,58,114,101,103,97,114,100,105,110,103,32,116,104,\n101,115,117,112,112,111,114,116,101,100,32,116,104,101,105,115,32,97,108,115,111\n,32,107,110,111,119,110,115,116,121,108,101,61,34,109,97,114,103,105,110,105,110\n,99,108,117,100,105,110,103,32,116,104,101,98,97,104,97,115,97,32,77,101,108,97,\n121,117,110,111,114,115,107,32,98,111,107,109,195,165,108,110,111,114,115,107,32\n,110,121,110,111,114,115,107,115,108,111,118,101,110,197,161,196,141,105,110,97,\n105,110,116,101,114,110,97,99,105,111,110,97,108,99,97,108,105,102,105,99,97,99,\n105,195,179,110,99,111,109,117,110,105,99,97,99,105,195,179,110,99,111,110,115,\n116,114,117,99,99,105,195,179,110,34,62,60,100,105,118,32,99,108,97,115,115,61,\n34,100,105,115,97,109,98,105,103,117,97,116,105,111,110,68,111,109,97,105,110,78\n,97,109,101,39,44,32,39,97,100,109,105,110,105,115,116,114,97,116,105,111,110,\n115,105,109,117,108,116,97,110,101,111,117,115,108,121,116,114,97,110,115,112,\n111,114,116,97,116,105,111,110,73,110,116,101,114,110,97,116,105,111,110,97,108,\n32,109,97,114,103,105,110,45,98,111,116,116,111,109,58,114,101,115,112,111,110,\n115,105,98,105,108,105,116,121,60,33,91,101,110,100,105,102,93,45,45,62,10,60,47\n,62,60,109,101,116,97,32,110,97,109,101,61,34,105,109,112,108,101,109,101,110,\n116,97,116,105,111,110,105,110,102,114,97,115,116,114,117,99,116,117,114,101,114\n,101,112,114,101,115,101,110,116,97,116,105,111,110,98,111,114,100,101,114,45,98\n,111,116,116,111,109,58,60,47,104,101,97,100,62,10,60,98,111,100,121,62,61,104,\n116,116,112,37,51,65,37,50,70,37,50,70,60,102,111,114,109,32,109,101,116,104,111\n,100,61,34,109,101,116,104,111,100,61,34,112,111,115,116,34,32,47,102,97,118,105\n,99,111,110,46,105,99,111,34,32,125,41,59,10,60,47,115,99,114,105,112,116,62,10,\n46,115,101,116,65,116,116,114,105,98,117,116,101,40,65,100,109,105,110,105,115,\n116,114,97,116,105,111,110,61,32,110,101,119,32,65,114,114,97,121,40,41,59,60,33\n,91,101,110,100,105,102,93,45,45,62,13,10,100,105,115,112,108,97,121,58,98,108,\n111,99,107,59,85,110,102,111,114,116,117,110,97,116,101,108,121,44,34,62,38,110,\n98,115,112,59,60,47,100,105,118,62,47,102,97,118,105,99,111,110,46,105,99,111,34\n,62,61,39,115,116,121,108,101,115,104,101,101,116,39,32,105,100,101,110,116,105,\n102,105,99,97,116,105,111,110,44,32,102,111,114,32,101,120,97,109,112,108,101,44\n,60,108,105,62,60,97,32,104,114,101,102,61,34,47,97,110,32,97,108,116,101,114,\n110,97,116,105,118,101,97,115,32,97,32,114,101,115,117,108,116,32,111,102,112,\n116,34,62,60,47,115,99,114,105,112,116,62,10,116,121,112,101,61,34,115,117,98,\n109,105,116,34,32,10,40,102,117,110,99,116,105,111,110,40,41,32,123,114,101,99,\n111,109,109,101,110,100,97,116,105,111,110,102,111,114,109,32,97,99,116,105,111,\n110,61,34,47,116,114,97,110,115,102,111,114,109,97,116,105,111,110,114,101,99,\n111,110,115,116,114,117,99,116,105,111,110,46,115,116,121,108,101,46,100,105,115\n,112,108,97,121,32,65,99,99,111,114,100,105,110,103,32,116,111,32,104,105,100,\n100,101,110,34,32,110,97,109,101,61,34,97,108,111,110,103,32,119,105,116,104,32,\n116,104,101,100,111,99,117,109,101,110,116,46,98,111,100,121,46,97,112,112,114,\n111,120,105,109,97,116,101,108,121,32,67,111,109,109,117,110,105,99,97,116,105,\n111,110,115,112,111,115,116,34,32,97,99,116,105,111,110,61,34,109,101,97,110,105\n,110,103,32,38,113,117,111,116,59,45,45,60,33,91,101,110,100,105,102,93,45,45,62\n,80,114,105,109,101,32,77,105,110,105,115,116,101,114,99,104,97,114,97,99,116,\n101,114,105,115,116,105,99,60,47,97,62,32,60,97,32,99,108,97,115,115,61,116,104,\n101,32,104,105,115,116,111,114,121,32,111,102,32,111,110,109,111,117,115,101,111\n,118,101,114,61,34,116,104,101,32,103,111,118,101,114,110,109,101,110,116,104,\n114,101,102,61,34,104,116,116,112,115,58,47,47,119,97,115,32,111,114,105,103,105\n,110,97,108,108,121,119,97,115,32,105,110,116,114,111,100,117,99,101,100,99,108,\n97,115,115,105,102,105,99,97,116,105,111,110,114,101,112,114,101,115,101,110,116\n,97,116,105,118,101,97,114,101,32,99,111,110,115,105,100,101,114,101,100,60,33,\n91,101,110,100,105,102,93,45,45,62,10,10,100,101,112,101,110,100,115,32,111,110,\n32,116,104,101,85,110,105,118,101,114,115,105,116,121,32,111,102,32,105,110,32,\n99,111,110,116,114,97,115,116,32,116,111,32,112,108,97,99,101,104,111,108,100,\n101,114,61,34,105,110,32,116,104,101,32,99,97,115,101,32,111,102,105,110,116,101\n,114,110,97,116,105,111,110,97,108,32,99,111,110,115,116,105,116,117,116,105,111\n,110,97,108,115,116,121,108,101,61,34,98,111,114,100,101,114,45,58,32,102,117,\n110,99,116,105,111,110,40,41,32,123,66,101,99,97,117,115,101,32,111,102,32,116,\n104,101,45,115,116,114,105,99,116,46,100,116,100,34,62,10,60,116,97,98,108,101,\n32,99,108,97,115,115,61,34,97,99,99,111,109,112,97,110,105,101,100,32,98,121,97,\n99,99,111,117,110,116,32,111,102,32,116,104,101,60,115,99,114,105,112,116,32,115\n,114,99,61,34,47,110,97,116,117,114,101,32,111,102,32,116,104,101,32,116,104,101\n,32,112,101,111,112,108,101,32,105,110,32,105,110,32,97,100,100,105,116,105,111,\n110,32,116,111,115,41,59,32,106,115,46,105,100,32,61,32,105,100,34,32,119,105,\n100,116,104,61,34,49,48,48,37,34,114,101,103,97,114,100,105,110,103,32,116,104,\n101,32,82,111,109,97,110,32,67,97,116,104,111,108,105,99,97,110,32,105,110,100,\n101,112,101,110,100,101,110,116,102,111,108,108,111,119,105,110,103,32,116,104,\n101,32,46,103,105,102,34,32,119,105,100,116,104,61,34,49,116,104,101,32,102,111,\n108,108,111,119,105,110,103,32,100,105,115,99,114,105,109,105,110,97,116,105,111\n,110,97,114,99,104,97,101,111,108,111,103,105,99,97,108,112,114,105,109,101,32,\n109,105,110,105,115,116,101,114,46,106,115,34,62,60,47,115,99,114,105,112,116,62\n,99,111,109,98,105,110,97,116,105,111,110,32,111,102,32,109,97,114,103,105,110,\n119,105,100,116,104,61,34,99,114,101,97,116,101,69,108,101,109,101,110,116,40,\n119,46,97,116,116,97,99,104,69,118,101,110,116,40,60,47,97,62,60,47,116,100,62,\n60,47,116,114,62,115,114,99,61,34,104,116,116,112,115,58,47,47,97,73,110,32,112,\n97,114,116,105,99,117,108,97,114,44,32,97,108,105,103,110,61,34,108,101,102,116,\n34,32,67,122,101,99,104,32,82,101,112,117,98,108,105,99,85,110,105,116,101,100,\n32,75,105,110,103,100,111,109,99,111,114,114,101,115,112,111,110,100,101,110,99,\n101,99,111,110,99,108,117,100,101,100,32,116,104,97,116,46,104,116,109,108,34,32\n,116,105,116,108,101,61,34,40,102,117,110,99,116,105,111,110,32,40,41,32,123,99,\n111,109,101,115,32,102,114,111,109,32,116,104,101,97,112,112,108,105,99,97,116,\n105,111,110,32,111,102,60,115,112,97,110,32,99,108,97,115,115,61,34,115,98,101,\n108,105,101,118,101,100,32,116,111,32,98,101,101,109,101,110,116,40,39,115,99,\n114,105,112,116,39,60,47,97,62,10,60,47,108,105,62,10,60,108,105,118,101,114,121\n,32,100,105,102,102,101,114,101,110,116,62,60,115,112,97,110,32,99,108,97,115,\n115,61,34,111,112,116,105,111,110,32,118,97,108,117,101,61,34,40,97,108,115,111,\n32,107,110,111,119,110,32,97,115,9,60,108,105,62,60,97,32,104,114,101,102,61,34,\n62,60,105,110,112,117,116,32,110,97,109,101,61,34,115,101,112,97,114,97,116,101,\n100,32,102,114,111,109,114,101,102,101,114,114,101,100,32,116,111,32,97,115,32,\n118,97,108,105,103,110,61,34,116,111,112,34,62,102,111,117,110,100,101,114,32,\n111,102,32,116,104,101,97,116,116,101,109,112,116,105,110,103,32,116,111,32,99,\n97,114,98,111,110,32,100,105,111,120,105,100,101,10,10,60,100,105,118,32,99,108,\n97,115,115,61,34,99,108,97,115,115,61,34,115,101,97,114,99,104,45,47,98,111,100,\n121,62,10,60,47,104,116,109,108,62,111,112,112,111,114,116,117,110,105,116,121,\n32,116,111,99,111,109,109,117,110,105,99,97,116,105,111,110,115,60,47,104,101,97\n,100,62,13,10,60,98,111,100,121,32,115,116,121,108,101,61,34,119,105,100,116,104\n,58,84,105,225,186,191,110,103,32,86,105,225,187,135,116,99,104,97,110,103,101,\n115,32,105,110,32,116,104,101,98,111,114,100,101,114,45,99,111,108,111,114,58,35\n,48,34,32,98,111,114,100,101,114,61,34,48,34,32,60,47,115,112,97,110,62,60,47,\n100,105,118,62,60,119,97,115,32,100,105,115,99,111,118,101,114,101,100,34,32,116\n,121,112,101,61,34,116,101,120,116,34,32,41,59,10,60,47,115,99,114,105,112,116,\n62,10,10,68,101,112,97,114,116,109,101,110,116,32,111,102,32,101,99,99,108,101,\n115,105,97,115,116,105,99,97,108,116,104,101,114,101,32,104,97,115,32,98,101,101\n,110,114,101,115,117,108,116,105,110,103,32,102,114,111,109,60,47,98,111,100,121\n,62,60,47,104,116,109,108,62,104,97,115,32,110,101,118,101,114,32,98,101,101,110\n,116,104,101,32,102,105,114,115,116,32,116,105,109,101,105,110,32,114,101,115,\n112,111,110,115,101,32,116,111,97,117,116,111,109,97,116,105,99,97,108,108,121,\n32,60,47,100,105,118,62,10,10,60,100,105,118,32,105,119,97,115,32,99,111,110,115\n,105,100,101,114,101,100,112,101,114,99,101,110,116,32,111,102,32,116,104,101,34\n,32,47,62,60,47,97,62,60,47,100,105,118,62,99,111,108,108,101,99,116,105,111,110\n,32,111,102,32,100,101,115,99,101,110,100,101,100,32,102,114,111,109,115,101,99,\n116,105,111,110,32,111,102,32,116,104,101,97,99,99,101,112,116,45,99,104,97,114,\n115,101,116,116,111,32,98,101,32,99,111,110,102,117,115,101,100,109,101,109,98,\n101,114,32,111,102,32,116,104,101,32,112,97,100,100,105,110,103,45,114,105,103,\n104,116,58,116,114,97,110,115,108,97,116,105,111,110,32,111,102,105,110,116,101,\n114,112,114,101,116,97,116,105,111,110,32,104,114,101,102,61,39,104,116,116,112,\n58,47,47,119,104,101,116,104,101,114,32,111,114,32,110,111,116,84,104,101,114,\n101,32,97,114,101,32,97,108,115,111,116,104,101,114,101,32,97,114,101,32,109,97,\n110,121,97,32,115,109,97,108,108,32,110,117,109,98,101,114,111,116,104,101,114,\n32,112,97,114,116,115,32,111,102,105,109,112,111,115,115,105,98,108,101,32,116,\n111,32,32,99,108,97,115,115,61,34,98,117,116,116,111,110,108,111,99,97,116,101,\n100,32,105,110,32,116,104,101,46,32,72,111,119,101,118,101,114,44,32,116,104,101\n,97,110,100,32,101,118,101,110,116,117,97,108,108,121,65,116,32,116,104,101,32,\n101,110,100,32,111,102,32,98,101,99,97,117,115,101,32,111,102,32,105,116,115,114\n,101,112,114,101,115,101,110,116,115,32,116,104,101,60,102,111,114,109,32,97,99,\n116,105,111,110,61,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,105,\n116,32,105,115,32,112,111,115,115,105,98,108,101,109,111,114,101,32,108,105,107,\n101,108,121,32,116,111,97,110,32,105,110,99,114,101,97,115,101,32,105,110,104,97\n,118,101,32,97,108,115,111,32,98,101,101,110,99,111,114,114,101,115,112,111,110,\n100,115,32,116,111,97,110,110,111,117,110,99,101,100,32,116,104,97,116,97,108,\n105,103,110,61,34,114,105,103,104,116,34,62,109,97,110,121,32,99,111,117,110,116\n,114,105,101,115,102,111,114,32,109,97,110,121,32,121,101,97,114,115,101,97,114,\n108,105,101,115,116,32,107,110,111,119,110,98,101,99,97,117,115,101,32,105,116,\n32,119,97,115,112,116,34,62,60,47,115,99,114,105,112,116,62,13,32,118,97,108,105\n,103,110,61,34,116,111,112,34,32,105,110,104,97,98,105,116,97,110,116,115,32,111\n,102,102,111,108,108,111,119,105,110,103,32,121,101,97,114,13,10,60,100,105,118,\n32,99,108,97,115,115,61,34,109,105,108,108,105,111,110,32,112,101,111,112,108,\n101,99,111,110,116,114,111,118,101,114,115,105,97,108,32,99,111,110,99,101,114,\n110,105,110,103,32,116,104,101,97,114,103,117,101,32,116,104,97,116,32,116,104,\n101,103,111,118,101,114,110,109,101,110,116,32,97,110,100,97,32,114,101,102,101,\n114,101,110,99,101,32,116,111,116,114,97,110,115,102,101,114,114,101,100,32,116,\n111,100,101,115,99,114,105,98,105,110,103,32,116,104,101,32,115,116,121,108,101,\n61,34,99,111,108,111,114,58,97,108,116,104,111,117,103,104,32,116,104,101,114,\n101,98,101,115,116,32,107,110,111,119,110,32,102,111,114,115,117,98,109,105,116,\n34,32,110,97,109,101,61,34,109,117,108,116,105,112,108,105,99,97,116,105,111,110\n,109,111,114,101,32,116,104,97,110,32,111,110,101,32,114,101,99,111,103,110,105,\n116,105,111,110,32,111,102,67,111,117,110,99,105,108,32,111,102,32,116,104,101,\n101,100,105,116,105,111,110,32,111,102,32,116,104,101,32,32,60,109,101,116,97,32\n,110,97,109,101,61,34,69,110,116,101,114,116,97,105,110,109,101,110,116,32,97,\n119,97,121,32,102,114,111,109,32,116,104,101,32,59,109,97,114,103,105,110,45,114\n,105,103,104,116,58,97,116,32,116,104,101,32,116,105,109,101,32,111,102,105,110,\n118,101,115,116,105,103,97,116,105,111,110,115,99,111,110,110,101,99,116,101,100\n,32,119,105,116,104,97,110,100,32,109,97,110,121,32,111,116,104,101,114,97,108,\n116,104,111,117,103,104,32,105,116,32,105,115,98,101,103,105,110,110,105,110,103\n,32,119,105,116,104,32,60,115,112,97,110,32,99,108,97,115,115,61,34,100,101,115,\n99,101,110,100,97,110,116,115,32,111,102,60,115,112,97,110,32,99,108,97,115,115,\n61,34,105,32,97,108,105,103,110,61,34,114,105,103,104,116,34,60,47,104,101,97,\n100,62,10,60,98,111,100,121,32,97,115,112,101,99,116,115,32,111,102,32,116,104,\n101,104,97,115,32,115,105,110,99,101,32,98,101,101,110,69,117,114,111,112,101,97\n,110,32,85,110,105,111,110,114,101,109,105,110,105,115,99,101,110,116,32,111,102\n,109,111,114,101,32,100,105,102,102,105,99,117,108,116,86,105,99,101,32,80,114,\n101,115,105,100,101,110,116,99,111,109,112,111,115,105,116,105,111,110,32,111,\n102,112,97,115,115,101,100,32,116,104,114,111,117,103,104,109,111,114,101,32,105\n,109,112,111,114,116,97,110,116,102,111,110,116,45,115,105,122,101,58,49,49,112,\n120,101,120,112,108,97,110,97,116,105,111,110,32,111,102,116,104,101,32,99,111,\n110,99,101,112,116,32,111,102,119,114,105,116,116,101,110,32,105,110,32,116,104,\n101,9,60,115,112,97,110,32,99,108,97,115,115,61,34,105,115,32,111,110,101,32,111\n,102,32,116,104,101,32,114,101,115,101,109,98,108,97,110,99,101,32,116,111,111,\n110,32,116,104,101,32,103,114,111,117,110,100,115,119,104,105,99,104,32,99,111,\n110,116,97,105,110,115,105,110,99,108,117,100,105,110,103,32,116,104,101,32,100,\n101,102,105,110,101,100,32,98,121,32,116,104,101,112,117,98,108,105,99,97,116,\n105,111,110,32,111,102,109,101,97,110,115,32,116,104,97,116,32,116,104,101,111,\n117,116,115,105,100,101,32,111,102,32,116,104,101,115,117,112,112,111,114,116,32\n,111,102,32,116,104,101,60,105,110,112,117,116,32,99,108,97,115,115,61,34,60,115\n,112,97,110,32,99,108,97,115,115,61,34,116,40,77,97,116,104,46,114,97,110,100,\n111,109,40,41,109,111,115,116,32,112,114,111,109,105,110,101,110,116,100,101,115\n,99,114,105,112,116,105,111,110,32,111,102,67,111,110,115,116,97,110,116,105,110\n,111,112,108,101,119,101,114,101,32,112,117,98,108,105,115,104,101,100,60,100,\n105,118,32,99,108,97,115,115,61,34,115,101,97,112,112,101,97,114,115,32,105,110,\n32,116,104,101,49,34,32,104,101,105,103,104,116,61,34,49,34,32,109,111,115,116,\n32,105,109,112,111,114,116,97,110,116,119,104,105,99,104,32,105,110,99,108,117,\n100,101,115,119,104,105,99,104,32,104,97,100,32,98,101,101,110,100,101,115,116,\n114,117,99,116,105,111,110,32,111,102,116,104,101,32,112,111,112,117,108,97,116,\n105,111,110,10,9,60,100,105,118,32,99,108,97,115,115,61,34,112,111,115,115,105,\n98,105,108,105,116,121,32,111,102,115,111,109,101,116,105,109,101,115,32,117,115\n,101,100,97,112,112,101,97,114,32,116,111,32,104,97,118,101,115,117,99,99,101,\n115,115,32,111,102,32,116,104,101,105,110,116,101,110,100,101,100,32,116,111,32,\n98,101,112,114,101,115,101,110,116,32,105,110,32,116,104,101,115,116,121,108,101\n,61,34,99,108,101,97,114,58,98,13,10,60,47,115,99,114,105,112,116,62,13,10,60,\n119,97,115,32,102,111,117,110,100,101,100,32,105,110,105,110,116,101,114,118,105\n,101,119,32,119,105,116,104,95,105,100,34,32,99,111,110,116,101,110,116,61,34,99\n,97,112,105,116,97,108,32,111,102,32,116,104,101,13,10,60,108,105,110,107,32,114\n,101,108,61,34,115,114,101,108,101,97,115,101,32,111,102,32,116,104,101,112,111,\n105,110,116,32,111,117,116,32,116,104,97,116,120,77,76,72,116,116,112,82,101,113\n,117,101,115,116,97,110,100,32,115,117,98,115,101,113,117,101,110,116,115,101,99\n,111,110,100,32,108,97,114,103,101,115,116,118,101,114,121,32,105,109,112,111,\n114,116,97,110,116,115,112,101,99,105,102,105,99,97,116,105,111,110,115,115,117,\n114,102,97,99,101,32,111,102,32,116,104,101,97,112,112,108,105,101,100,32,116,\n111,32,116,104,101,102,111,114,101,105,103,110,32,112,111,108,105,99,121,95,115,\n101,116,68,111,109,97,105,110,78,97,109,101,101,115,116,97,98,108,105,115,104,\n101,100,32,105,110,105,115,32,98,101,108,105,101,118,101,100,32,116,111,73,110,\n32,97,100,100,105,116,105,111,110,32,116,111,109,101,97,110,105,110,103,32,111,\n102,32,116,104,101,105,115,32,110,97,109,101,100,32,97,102,116,101,114,116,111,\n32,112,114,111,116,101,99,116,32,116,104,101,105,115,32,114,101,112,114,101,115,\n101,110,116,101,100,68,101,99,108,97,114,97,116,105,111,110,32,111,102,109,111,\n114,101,32,101,102,102,105,99,105,101,110,116,67,108,97,115,115,105,102,105,99,\n97,116,105,111,110,111,116,104,101,114,32,102,111,114,109,115,32,111,102,104,101\n,32,114,101,116,117,114,110,101,100,32,116,111,60,115,112,97,110,32,99,108,97,\n115,115,61,34,99,112,101,114,102,111,114,109,97,110,99,101,32,111,102,40,102,117\n,110,99,116,105,111,110,40,41,32,123,13,105,102,32,97,110,100,32,111,110,108,121\n,32,105,102,114,101,103,105,111,110,115,32,111,102,32,116,104,101,108,101,97,100\n,105,110,103,32,116,111,32,116,104,101,114,101,108,97,116,105,111,110,115,32,119\n,105,116,104,85,110,105,116,101,100,32,78,97,116,105,111,110,115,115,116,121,108\n,101,61,34,104,101,105,103,104,116,58,111,116,104,101,114,32,116,104,97,110,32,\n116,104,101,121,112,101,34,32,99,111,110,116,101,110,116,61,34,65,115,115,111,99\n,105,97,116,105,111,110,32,111,102,10,60,47,104,101,97,100,62,10,60,98,111,100,\n121,108,111,99,97,116,101,100,32,111,110,32,116,104,101,105,115,32,114,101,102,\n101,114,114,101,100,32,116,111,40,105,110,99,108,117,100,105,110,103,32,116,104,\n101,99,111,110,99,101,110,116,114,97,116,105,111,110,115,116,104,101,32,105,110,\n100,105,118,105,100,117,97,108,97,109,111,110,103,32,116,104,101,32,109,111,115,\n116,116,104,97,110,32,97,110,121,32,111,116,104,101,114,47,62,10,60,108,105,110,\n107,32,114,101,108,61,34,32,114,101,116,117,114,110,32,102,97,108,115,101,59,116\n,104,101,32,112,117,114,112,111,115,101,32,111,102,116,104,101,32,97,98,105,108,\n105,116,121,32,116,111,59,99,111,108,111,114,58,35,102,102,102,125,10,46,10,60,\n115,112,97,110,32,99,108,97,115,115,61,34,116,104,101,32,115,117,98,106,101,99,\n116,32,111,102,100,101,102,105,110,105,116,105,111,110,115,32,111,102,62,13,10,\n60,108,105,110,107,32,114,101,108,61,34,99,108,97,105,109,32,116,104,97,116,32,\n116,104,101,104,97,118,101,32,100,101,118,101,108,111,112,101,100,60,116,97,98,\n108,101,32,119,105,100,116,104,61,34,99,101,108,101,98,114,97,116,105,111,110,32\n,111,102,70,111,108,108,111,119,105,110,103,32,116,104,101,32,116,111,32,100,105\n,115,116,105,110,103,117,105,115,104,60,115,112,97,110,32,99,108,97,115,115,61,\n34,98,116,97,107,101,115,32,112,108,97,99,101,32,105,110,117,110,100,101,114,32,\n116,104,101,32,110,97,109,101,110,111,116,101,100,32,116,104,97,116,32,116,104,\n101,62,60,33,91,101,110,100,105,102,93,45,45,62,10,115,116,121,108,101,61,34,109\n,97,114,103,105,110,45,105,110,115,116,101,97,100,32,111,102,32,116,104,101,105,\n110,116,114,111,100,117,99,101,100,32,116,104,101,116,104,101,32,112,114,111,99,\n101,115,115,32,111,102,105,110,99,114,101,97,115,105,110,103,32,116,104,101,100,\n105,102,102,101,114,101,110,99,101,115,32,105,110,101,115,116,105,109,97,116,101\n,100,32,116,104,97,116,101,115,112,101,99,105,97,108,108,121,32,116,104,101,47,\n100,105,118,62,60,100,105,118,32,105,100,61,34,119,97,115,32,101,118,101,110,116\n,117,97,108,108,121,116,104,114,111,117,103,104,111,117,116,32,104,105,115,116,\n104,101,32,100,105,102,102,101,114,101,110,99,101,115,111,109,101,116,104,105,\n110,103,32,116,104,97,116,115,112,97,110,62,60,47,115,112,97,110,62,60,47,115,\n105,103,110,105,102,105,99,97,110,116,108,121,32,62,60,47,115,99,114,105,112,116\n,62,13,10,13,10,101,110,118,105,114,111,110,109,101,110,116,97,108,32,116,111,32\n,112,114,101,118,101,110,116,32,116,104,101,104,97,118,101,32,98,101,101,110,32,\n117,115,101,100,101,115,112,101,99,105,97,108,108,121,32,102,111,114,117,110,100\n,101,114,115,116,97,110,100,32,116,104,101,105,115,32,101,115,115,101,110,116,\n105,97,108,108,121,119,101,114,101,32,116,104,101,32,102,105,114,115,116,105,115\n,32,116,104,101,32,108,97,114,103,101,115,116,104,97,118,101,32,98,101,101,110,\n32,109,97,100,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,105,110,116,\n101,114,112,114,101,116,101,100,32,97,115,115,101,99,111,110,100,32,104,97,108,\n102,32,111,102,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,115,32,99,\n111,109,112,111,115,101,100,32,111,102,73,73,44,32,72,111,108,121,32,82,111,109,\n97,110,105,115,32,101,120,112,101,99,116,101,100,32,116,111,104,97,118,101,32,\n116,104,101,105,114,32,111,119,110,100,101,102,105,110,101,100,32,97,115,32,116,\n104,101,116,114,97,100,105,116,105,111,110,97,108,108,121,32,104,97,118,101,32,\n100,105,102,102,101,114,101,110,116,97,114,101,32,111,102,116,101,110,32,117,115\n,101,100,116,111,32,101,110,115,117,114,101,32,116,104,97,116,97,103,114,101,101\n,109,101,110,116,32,119,105,116,104,99,111,110,116,97,105,110,105,110,103,32,116\n,104,101,97,114,101,32,102,114,101,113,117,101,110,116,108,121,105,110,102,111,\n114,109,97,116,105,111,110,32,111,110,101,120,97,109,112,108,101,32,105,115,32,\n116,104,101,114,101,115,117,108,116,105,110,103,32,105,110,32,97,60,47,97,62,60,\n47,108,105,62,60,47,117,108,62,32,99,108,97,115,115,61,34,102,111,111,116,101,\n114,97,110,100,32,101,115,112,101,99,105,97,108,108,121,116,121,112,101,61,34,98\n,117,116,116,111,110,34,32,60,47,115,112,97,110,62,60,47,115,112,97,110,62,119,\n104,105,99,104,32,105,110,99,108,117,100,101,100,62,10,60,109,101,116,97,32,110,\n97,109,101,61,34,99,111,110,115,105,100,101,114,101,100,32,116,104,101,99,97,114\n,114,105,101,100,32,111,117,116,32,98,121,72,111,119,101,118,101,114,44,32,105,\n116,32,105,115,98,101,99,97,109,101,32,112,97,114,116,32,111,102,105,110,32,114,\n101,108,97,116,105,111,110,32,116,111,112,111,112,117,108,97,114,32,105,110,32,\n116,104,101,116,104,101,32,99,97,112,105,116,97,108,32,111,102,119,97,115,32,111\n,102,102,105,99,105,97,108,108,121,119,104,105,99,104,32,104,97,115,32,98,101,\n101,110,116,104,101,32,72,105,115,116,111,114,121,32,111,102,97,108,116,101,114,\n110,97,116,105,118,101,32,116,111,100,105,102,102,101,114,101,110,116,32,102,114\n,111,109,116,111,32,115,117,112,112,111,114,116,32,116,104,101,115,117,103,103,\n101,115,116,101,100,32,116,104,97,116,105,110,32,116,104,101,32,112,114,111,99,\n101,115,115,32,32,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,102,\n111,117,110,100,97,116,105,111,110,98,101,99,97,117,115,101,32,111,102,32,104,\n105,115,99,111,110,99,101,114,110,101,100,32,119,105,116,104,116,104,101,32,117,\n110,105,118,101,114,115,105,116,121,111,112,112,111,115,101,100,32,116,111,32,\n116,104,101,116,104,101,32,99,111,110,116,101,120,116,32,111,102,60,115,112,97,\n110,32,99,108,97,115,115,61,34,112,116,101,120,116,34,32,110,97,109,101,61,34,\n113,34,9,9,60,100,105,118,32,99,108,97,115,115,61,34,116,104,101,32,115,99,105,\n101,110,116,105,102,105,99,114,101,112,114,101,115,101,110,116,101,100,32,98,121\n,109,97,116,104,101,109,97,116,105,99,105,97,110,115,101,108,101,99,116,101,100,\n32,98,121,32,116,104,101,116,104,97,116,32,104,97,118,101,32,98,101,101,110,62,\n60,100,105,118,32,99,108,97,115,115,61,34,99,100,105,118,32,105,100,61,34,104,\n101,97,100,101,114,105,110,32,112,97,114,116,105,99,117,108,97,114,44,99,111,110\n,118,101,114,116,101,100,32,105,110,116,111,41,59,10,60,47,115,99,114,105,112,\n116,62,10,60,112,104,105,108,111,115,111,112,104,105,99,97,108,32,115,114,112,\n115,107,111,104,114,118,97,116,115,107,105,116,105,225,186,191,110,103,32,86,105\n,225,187,135,116,208,160,209,131,209,129,209,129,208,186,208,184,208,185,209,128\n,209,131,209,129,209,129,208,186,208,184,208,185,105,110,118,101,115,116,105,103\n,97,99,105,195,179,110,112,97,114,116,105,99,105,112,97,99,105,195,179,110,208,\n186,208,190,209,130,208,190,209,128,209,139,208,181,208,190,208,177,208,187,208,\n176,209,129,209,130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,208,\n185,209,135,208,181,208,187,208,190,208,178,208,181,208,186,209,129,208,184,209,\n129,209,130,208,181,208,188,209,139,208,157,208,190,208,178,208,190,209,129,209,\n130,208,184,208,186,208,190,209,130,208,190,209,128,209,139,209,133,208,190,208,\n177,208,187,208,176,209,129,209,130,209,140,208,178,209,128,208,181,208,188,208,\n181,208,189,208,184,208,186,208,190,209,130,208,190,209,128,208,176,209,143,209,\n129,208,181,208,179,208,190,208,180,208,189,209,143,209,129,208,186,208,176,209,\n135,208,176,209,130,209,140,208,189,208,190,208,178,208,190,209,129,209,130,208,\n184,208,163,208,186,209,128,208,176,208,184,208,189,209,139,208,178,208,190,208,\n191,209,128,208,190,209,129,209,139,208,186,208,190,209,130,208,190,209,128,208,\n190,208,185,209,129,208,180,208,181,208,187,208,176,209,130,209,140,208,191,208,\n190,208,188,208,190,209,137,209,140,209,142,209,129,209,128,208,181,208,180,209,\n129,209,130,208,178,208,190,208,177,209,128,208,176,208,183,208,190,208,188,209,\n129,209,130,208,190,209,128,208,190,208,189,209,139,209,131,209,135,208,176,209,\n129,209,130,208,184,208,181,209,130,208,181,209,135,208,181,208,189,208,184,208,\n181,208,147,208,187,208,176,208,178,208,189,208,176,209,143,208,184,209,129,209,\n130,208,190,209,128,208,184,208,184,209,129,208,184,209,129,209,130,208,181,208,\n188,208,176,209,128,208,181,209,136,208,181,208,189,208,184,209,143,208,161,208,\n186,208,176,209,135,208,176,209,130,209,140,208,191,208,190,209,141,209,130,208,\n190,208,188,209,131,209,129,208,187,208,181,208,180,209,131,208,181,209,130,209,\n129,208,186,208,176,208,183,208,176,209,130,209,140,209,130,208,190,208,178,208,\n176,209,128,208,190,208,178,208,186,208,190,208,189,208,181,209,135,208,189,208,\n190,209,128,208,181,209,136,208,181,208,189,208,184,208,181,208,186,208,190,209,\n130,208,190,209,128,208,190,208,181,208,190,209,128,208,179,208,176,208,189,208,\n190,208,178,208,186,208,190,209,130,208,190,209,128,208,190,208,188,208,160,208,\n181,208,186,208,187,208,176,208,188,208,176,216,167,217,132,217,133,217,134,216,\n170,216,175,217,137,217,133,217,134,216,170,216,175,217,138,216,167,216,170,216,\n167,217,132,217,133,217,136,216,182,217,136,216,185,216,167,217,132,216,168,216,\n177,216,167,217,133,216,172,216,167,217,132,217,133,217,136,216,167,217,130,216,\n185,216,167,217,132,216,177,216,179,216,167,216,166,217,132,217,133,216,180,216,\n167,216,177,217,131,216,167,216,170,216,167,217,132,216,163,216,185,216,182,216,\n167,216,161,216,167,217,132,216,177,217,138,216,167,216,182,216,169,216,167,217,\n132,216,170,216,181,217,133,217,138,217,133,216,167,217,132,216,167,216,185,216,\n182,216,167,216,161,216,167,217,132,217,134,216,170,216,167,216,166,216,172,216,\n167,217,132,216,163,217,132,216,185,216,167,216,168,216,167,217,132,216,170,216,\n179,216,172,217,138,217,132,216,167,217,132,216,163,217,130,216,179,216,167,217,\n133,216,167,217,132,216,182,216,186,216,183,216,167,216,170,216,167,217,132,217,\n129,217,138,216,175,217,138,217,136,216,167,217,132,216,170,216,177,216,173,217,\n138,216,168,216,167,217,132,216,172,216,175,217,138,216,175,216,169,216,167,217,\n132,216,170,216,185,217,132,217,138,217,133,216,167,217,132,216,163,216,174,216,\n168,216,167,216,177,216,167,217,132,216,167,217,129,217,132,216,167,217,133,216,\n167,217,132,216,163,217,129,217,132,216,167,217,133,216,167,217,132,216,170,216,\n167,216,177,217,138,216,174,216,167,217,132,216,170,217,130,217,134,217,138,216,\n169,216,167,217,132,216,167,217,132,216,185,216,167,216,168,216,167,217,132,216,\n174,217,136,216,167,216,183,216,177,216,167,217,132,217,133,216,172,216,170,217,\n133,216,185,216,167,217,132,216,175,217,138,217,131,217,136,216,177,216,167,217,\n132,216,179,217,138,216,167,216,173,216,169,216,185,216,168,216,175,216,167,217,\n132,217,132,217,135,216,167,217,132,216,170,216,177,216,168,217,138,216,169,216,\n167,217,132,216,177,217,136,216,167,216,168,216,183,216,167,217,132,216,163,216,\n175,216,168,217,138,216,169,216,167,217,132,216,167,216,174,216,168,216,167,216,\n177,216,167,217,132,217,133,216,170,216,173,216,175,216,169,216,167,217,132,216,\n167,216,186,216,167,217,134,217,138,99,117,114,115,111,114,58,112,111,105,110,\n116,101,114,59,60,47,116,105,116,108,101,62,10,60,109,101,116,97,32,34,32,104,\n114,101,102,61,34,104,116,116,112,58,47,47,34,62,60,115,112,97,110,32,99,108,97,\n115,115,61,34,109,101,109,98,101,114,115,32,111,102,32,116,104,101,32,119,105,\n110,100,111,119,46,108,111,99,97,116,105,111,110,118,101,114,116,105,99,97,108,\n45,97,108,105,103,110,58,47,97,62,32,124,32,60,97,32,104,114,101,102,61,34,60,33\n,100,111,99,116,121,112,101,32,104,116,109,108,62,109,101,100,105,97,61,34,115,\n99,114,101,101,110,34,32,60,111,112,116,105,111,110,32,118,97,108,117,101,61,34,\n102,97,118,105,99,111,110,46,105,99,111,34,32,47,62,10,9,9,60,100,105,118,32,99,\n108,97,115,115,61,34,99,104,97,114,97,99,116,101,114,105,115,116,105,99,115,34,\n32,109,101,116,104,111,100,61,34,103,101,116,34,32,47,98,111,100,121,62,10,60,47\n,104,116,109,108,62,10,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,\n100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,112,97,100,100,105,110,\n103,45,98,111,116,116,111,109,58,114,101,112,114,101,115,101,110,116,97,116,105,\n118,101,115,115,117,98,109,105,116,34,32,118,97,108,117,101,61,34,97,108,105,103\n,110,61,34,99,101,110,116,101,114,34,32,116,104,114,111,117,103,104,111,117,116,\n32,116,104,101,32,115,99,105,101,110,99,101,32,102,105,99,116,105,111,110,10,32,\n32,60,100,105,118,32,99,108,97,115,115,61,34,115,117,98,109,105,116,34,32,99,108\n,97,115,115,61,34,111,110,101,32,111,102,32,116,104,101,32,109,111,115,116,32,\n118,97,108,105,103,110,61,34,116,111,112,34,62,60,119,97,115,32,101,115,116,97,\n98,108,105,115,104,101,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10,114\n,101,116,117,114,110,32,102,97,108,115,101,59,34,62,41,46,115,116,121,108,101,46\n,100,105,115,112,108,97,121,98,101,99,97,117,115,101,32,111,102,32,116,104,101,\n32,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,60,102,111,114,109,\n32,97,99,116,105,111,110,61,34,47,125,98,111,100,121,123,109,97,114,103,105,110,\n58,48,59,69,110,99,121,99,108,111,112,101,100,105,97,32,111,102,118,101,114,115,\n105,111,110,32,111,102,32,116,104,101,32,46,99,114,101,97,116,101,69,108,101,109\n,101,110,116,40,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,60,47,100,\n105,118,62,10,60,47,100,105,118,62,10,10,97,100,109,105,110,105,115,116,114,97,\n116,105,118,101,32,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,104,105,\n115,116,111,114,121,32,111,102,32,116,104,101,32,34,62,60,105,110,112,117,116,32\n,116,121,112,101,61,34,112,111,114,116,105,111,110,32,111,102,32,116,104,101,32,\n97,115,32,112,97,114,116,32,111,102,32,116,104,101,32,38,110,98,115,112,59,60,97\n,32,104,114,101,102,61,34,111,116,104,101,114,32,99,111,117,110,116,114,105,101,\n115,34,62,10,60,100,105,118,32,99,108,97,115,115,61,34,60,47,115,112,97,110,62,\n60,47,115,112,97,110,62,60,73,110,32,111,116,104,101,114,32,119,111,114,100,115,\n44,100,105,115,112,108,97,121,58,32,98,108,111,99,107,59,99,111,110,116,114,111,\n108,32,111,102,32,116,104,101,32,105,110,116,114,111,100,117,99,116,105,111,110,\n32,111,102,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,97,115,32,119,101,\n108,108,32,97,115,32,116,104,101,32,105,110,32,114,101,99,101,110,116,32,121,101\n,97,114,115,13,10,9,60,100,105,118,32,99,108,97,115,115,61,34,60,47,100,105,118,\n62,10,9,60,47,100,105,118,62,10,105,110,115,112,105,114,101,100,32,98,121,32,116\n,104,101,116,104,101,32,101,110,100,32,111,102,32,116,104,101,32,99,111,109,112,\n97,116,105,98,108,101,32,119,105,116,104,98,101,99,97,109,101,32,107,110,111,119\n,110,32,97,115,32,115,116,121,108,101,61,34,109,97,114,103,105,110,58,46,106,115\n,34,62,60,47,115,99,114,105,112,116,62,60,32,73,110,116,101,114,110,97,116,105,\n111,110,97,108,32,116,104,101,114,101,32,104,97,118,101,32,98,101,101,110,71,101\n,114,109,97,110,32,108,97,110,103,117,97,103,101,32,115,116,121,108,101,61,34,99\n,111,108,111,114,58,35,67,111,109,109,117,110,105,115,116,32,80,97,114,116,121,\n99,111,110,115,105,115,116,101,110,116,32,119,105,116,104,98,111,114,100,101,114\n,61,34,48,34,32,99,101,108,108,32,109,97,114,103,105,110,104,101,105,103,104,116\n,61,34,116,104,101,32,109,97,106,111,114,105,116,121,32,111,102,34,32,97,108,105\n,103,110,61,34,99,101,110,116,101,114,114,101,108,97,116,101,100,32,116,111,32,\n116,104,101,32,109,97,110,121,32,100,105,102,102,101,114,101,110,116,32,79,114,\n116,104,111,100,111,120,32,67,104,117,114,99,104,115,105,109,105,108,97,114,32,\n116,111,32,116,104,101,32,47,62,10,60,108,105,110,107,32,114,101,108,61,34,115,\n119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,117,110,116,105,108,32,\n104,105,115,32,100,101,97,116,104,125,41,40,41,59,10,60,47,115,99,114,105,112,\n116,62,111,116,104,101,114,32,108,97,110,103,117,97,103,101,115,99,111,109,112,\n97,114,101,100,32,116,111,32,116,104,101,112,111,114,116,105,111,110,115,32,111,\n102,32,116,104,101,116,104,101,32,78,101,116,104,101,114,108,97,110,100,115,116,\n104,101,32,109,111,115,116,32,99,111,109,109,111,110,98,97,99,107,103,114,111,\n117,110,100,58,117,114,108,40,97,114,103,117,101,100,32,116,104,97,116,32,116,\n104,101,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,105,110,99,108,\n117,100,101,100,32,105,110,32,116,104,101,78,111,114,116,104,32,65,109,101,114,\n105,99,97,110,32,116,104,101,32,110,97,109,101,32,111,102,32,116,104,101,105,110\n,116,101,114,112,114,101,116,97,116,105,111,110,115,116,104,101,32,116,114,97,\n100,105,116,105,111,110,97,108,100,101,118,101,108,111,112,109,101,110,116,32,\n111,102,32,102,114,101,113,117,101,110,116,108,121,32,117,115,101,100,97,32,99,\n111,108,108,101,99,116,105,111,110,32,111,102,118,101,114,121,32,115,105,109,105\n,108,97,114,32,116,111,115,117,114,114,111,117,110,100,105,110,103,32,116,104,\n101,101,120,97,109,112,108,101,32,111,102,32,116,104,105,115,97,108,105,103,110,\n61,34,99,101,110,116,101,114,34,62,119,111,117,108,100,32,104,97,118,101,32,98,\n101,101,110,105,109,97,103,101,95,99,97,112,116,105,111,110,32,61,97,116,116,97,\n99,104,101,100,32,116,111,32,116,104,101,115,117,103,103,101,115,116,105,110,103\n,32,116,104,97,116,105,110,32,116,104,101,32,102,111,114,109,32,111,102,32,105,\n110,118,111,108,118,101,100,32,105,110,32,116,104,101,105,115,32,100,101,114,105\n,118,101,100,32,102,114,111,109,110,97,109,101,100,32,97,102,116,101,114,32,116,\n104,101,73,110,116,114,111,100,117,99,116,105,111,110,32,116,111,114,101,115,116\n,114,105,99,116,105,111,110,115,32,111,110,32,115,116,121,108,101,61,34,119,105,\n100,116,104,58,32,99,97,110,32,98,101,32,117,115,101,100,32,116,111,32,116,104,\n101,32,99,114,101,97,116,105,111,110,32,111,102,109,111,115,116,32,105,109,112,\n111,114,116,97,110,116,32,105,110,102,111,114,109,97,116,105,111,110,32,97,110,\n100,114,101,115,117,108,116,101,100,32,105,110,32,116,104,101,99,111,108,108,97,\n112,115,101,32,111,102,32,116,104,101,84,104,105,115,32,109,101,97,110,115,32,\n116,104,97,116,101,108,101,109,101,110,116,115,32,111,102,32,116,104,101,119,97,\n115,32,114,101,112,108,97,99,101,100,32,98,121,97,110,97,108,121,115,105,115,32,\n111,102,32,116,104,101,105,110,115,112,105,114,97,116,105,111,110,32,102,111,114\n,114,101,103,97,114,100,101,100,32,97,115,32,116,104,101,109,111,115,116,32,115,\n117,99,99,101,115,115,102,117,108,107,110,111,119,110,32,97,115,32,38,113,117,\n111,116,59,97,32,99,111,109,112,114,101,104,101,110,115,105,118,101,72,105,115,\n116,111,114,121,32,111,102,32,116,104,101,32,119,101,114,101,32,99,111,110,115,\n105,100,101,114,101,100,114,101,116,117,114,110,101,100,32,116,111,32,116,104,\n101,97,114,101,32,114,101,102,101,114,114,101,100,32,116,111,85,110,115,111,117,\n114,99,101,100,32,105,109,97,103,101,62,10,9,60,100,105,118,32,99,108,97,115,115\n,61,34,99,111,110,115,105,115,116,115,32,111,102,32,116,104,101,115,116,111,112,\n80,114,111,112,97,103,97,116,105,111,110,105,110,116,101,114,101,115,116,32,105,\n110,32,116,104,101,97,118,97,105,108,97,98,105,108,105,116,121,32,111,102,97,112\n,112,101,97,114,115,32,116,111,32,104,97,118,101,101,108,101,99,116,114,111,109,\n97,103,110,101,116,105,99,101,110,97,98,108,101,83,101,114,118,105,99,101,115,40\n,102,117,110,99,116,105,111,110,32,111,102,32,116,104,101,73,116,32,105,115,32,\n105,109,112,111,114,116,97,110,116,60,47,115,99,114,105,112,116,62,60,47,100,105\n,118,62,102,117,110,99,116,105,111,110,40,41,123,118,97,114,32,114,101,108,97,\n116,105,118,101,32,116,111,32,116,104,101,97,115,32,97,32,114,101,115,117,108,\n116,32,111,102,32,116,104,101,32,112,111,115,105,116,105,111,110,32,111,102,70,\n111,114,32,101,120,97,109,112,108,101,44,32,105,110,32,109,101,116,104,111,100,\n61,34,112,111,115,116,34,32,119,97,115,32,102,111,108,108,111,119,101,100,32,98,\n121,38,97,109,112,59,109,100,97,115,104,59,32,116,104,101,116,104,101,32,97,112,\n112,108,105,99,97,116,105,111,110,106,115,34,62,60,47,115,99,114,105,112,116,62,\n13,10,117,108,62,60,47,100,105,118,62,60,47,100,105,118,62,97,102,116,101,114,32\n,116,104,101,32,100,101,97,116,104,119,105,116,104,32,114,101,115,112,101,99,116\n,32,116,111,115,116,121,108,101,61,34,112,97,100,100,105,110,103,58,105,115,32,\n112,97,114,116,105,99,117,108,97,114,108,121,100,105,115,112,108,97,121,58,105,\n110,108,105,110,101,59,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,105\n,115,32,100,105,118,105,100,101,100,32,105,110,116,111,228,184,173,230,150,135,\n32,40,231,174,128,228,189,147,41,114,101,115,112,111,110,115,97,98,105,108,105,\n100,97,100,97,100,109,105,110,105,115,116,114,97,99,105,195,179,110,105,110,116,\n101,114,110,97,99,105,111,110,97,108,101,115,99,111,114,114,101,115,112,111,110,\n100,105,101,110,116,101,224,164,137,224,164,170,224,164,175,224,165,139,224,164,\n151,224,164,170,224,165,130,224,164,176,224,165,141,224,164,181,224,164,185,224,\n164,174,224,164,190,224,164,176,224,165,135,224,164,178,224,165,139,224,164,151,\n224,165,139,224,164,130,224,164,154,224,165,129,224,164,168,224,164,190,224,164,\n181,224,164,178,224,165,135,224,164,149,224,164,191,224,164,168,224,164,184,224,\n164,176,224,164,149,224,164,190,224,164,176,224,164,170,224,165,129,224,164,178,\n224,164,191,224,164,184,224,164,150,224,165,139,224,164,156,224,165,135,224,164,\n130,224,164,154,224,164,190,224,164,185,224,164,191,224,164,143,224,164,173,224,\n165,135,224,164,156,224,165,135,224,164,130,224,164,182,224,164,190,224,164,174,\n224,164,191,224,164,178,224,164,185,224,164,174,224,164,190,224,164,176,224,165,\n128,224,164,156,224,164,190,224,164,151,224,164,176,224,164,163,224,164,172,224,\n164,168,224,164,190,224,164,168,224,165,135,224,164,149,224,165,129,224,164,174,\n224,164,190,224,164,176,224,164,172,224,165,141,224,164,178,224,165,137,224,164,\n151,224,164,174,224,164,190,224,164,178,224,164,191,224,164,149,224,164,174,224,\n164,185,224,164,191,224,164,178,224,164,190,224,164,170,224,165,131,224,164,183,\n224,165,141,224,164,160,224,164,172,224,164,162,224,164,188,224,164,164,224,165,\n135,224,164,173,224,164,190,224,164,156,224,164,170,224,164,190,224,164,149,224,\n165,141,224,164,178,224,164,191,224,164,149,224,164,159,224,165,141,224,164,176,\n224,165,135,224,164,168,224,164,150,224,164,191,224,164,178,224,164,190,224,164,\n171,224,164,166,224,165,140,224,164,176,224,164,190,224,164,168,224,164,174,224,\n164,190,224,164,174,224,164,178,224,165,135,224,164,174,224,164,164,224,164,166,\n224,164,190,224,164,168,224,164,172,224,164,190,224,164,156,224,164,190,224,164,\n176,224,164,181,224,164,191,224,164,149,224,164,190,224,164,184,224,164,149,224,\n165,141,224,164,175,224,165,139,224,164,130,224,164,154,224,164,190,224,164,185,\n224,164,164,224,165,135,224,164,170,224,164,185,224,165,129,224,164,129,224,164,\n154,224,164,172,224,164,164,224,164,190,224,164,175,224,164,190,224,164,184,224,\n164,130,224,164,181,224,164,190,224,164,166,224,164,166,224,165,135,224,164,150,\n224,164,168,224,165,135,224,164,170,224,164,191,224,164,155,224,164,178,224,165,\n135,224,164,181,224,164,191,224,164,182,224,165,135,224,164,183,224,164,176,224,\n164,190,224,164,156,224,165,141,224,164,175,224,164,137,224,164,164,224,165,141,\n224,164,164,224,164,176,224,164,174,224,165,129,224,164,130,224,164,172,224,164,\n136,224,164,166,224,165,139,224,164,168,224,165,139,224,164,130,224,164,137,224,\n164,170,224,164,149,224,164,176,224,164,163,224,164,170,224,164,162,224,164,188,\n224,165,135,224,164,130,224,164,184,224,165,141,224,164,165,224,164,191,224,164,\n164,224,164,171,224,164,191,224,164,178,224,165,141,224,164,174,224,164,174,224,\n165,129,224,164,150,224,165,141,224,164,175,224,164,133,224,164,154,224,165,141,\n224,164,155,224,164,190,224,164,155,224,165,130,224,164,159,224,164,164,224,165,\n128,224,164,184,224,164,130,224,164,151,224,165,128,224,164,164,224,164,156,224,\n164,190,224,164,143,224,164,151,224,164,190,224,164,181,224,164,191,224,164,173,\n224,164,190,224,164,151,224,164,152,224,164,163,224,165,141,224,164,159,224,165,\n135,224,164,166,224,165,130,224,164,184,224,164,176,224,165,135,224,164,166,224,\n164,191,224,164,168,224,165,139,224,164,130,224,164,185,224,164,164,224,165,141,\n224,164,175,224,164,190,224,164,184,224,165,135,224,164,149,224,165,141,224,164,\n184,224,164,151,224,164,190,224,164,130,224,164,167,224,165,128,224,164,181,224,\n164,191,224,164,182,224,165,141,224,164,181,224,164,176,224,164,190,224,164,164,\n224,165,135,224,164,130,224,164,166,224,165,136,224,164,159,224,165,141,224,164,\n184,224,164,168,224,164,149,224,165,141,224,164,182,224,164,190,224,164,184,224,\n164,190,224,164,174,224,164,168,224,165,135,224,164,133,224,164,166,224,164,190,\n224,164,178,224,164,164,224,164,172,224,164,191,224,164,156,224,164,178,224,165,\n128,224,164,170,224,165,129,224,164,176,224,165,130,224,164,183,224,164,185,224,\n164,191,224,164,130,224,164,166,224,165,128,224,164,174,224,164,191,224,164,164,\n224,165,141,224,164,176,224,164,149,224,164,181,224,164,191,224,164,164,224,164,\n190,224,164,176,224,165,129,224,164,170,224,164,175,224,165,135,224,164,184,224,\n165,141,224,164,165,224,164,190,224,164,168,224,164,149,224,164,176,224,165,139,\n224,164,161,224,164,188,224,164,174,224,165,129,224,164,149,224,165,141,224,164,\n164,224,164,175,224,165,139,224,164,156,224,164,168,224,164,190,224,164,149,224,\n165,131,224,164,170,224,164,175,224,164,190,224,164,170,224,165,139,224,164,184,\n224,165,141,224,164,159,224,164,152,224,164,176,224,165,135,224,164,178,224,165,\n130,224,164,149,224,164,190,224,164,176,224,165,141,224,164,175,224,164,181,224,\n164,191,224,164,154,224,164,190,224,164,176,224,164,184,224,165,130,224,164,154,\n224,164,168,224,164,190,224,164,174,224,165,130,224,164,178,224,165,141,224,164,\n175,224,164,166,224,165,135,224,164,150,224,165,135,224,164,130,224,164,185,224,\n164,174,224,165,135,224,164,182,224,164,190,224,164,184,224,165,141,224,164,149,\n224,165,130,224,164,178,224,164,174,224,165,136,224,164,130,224,164,168,224,165,\n135,224,164,164,224,165,136,224,164,175,224,164,190,224,164,176,224,164,156,224,\n164,191,224,164,184,224,164,149,224,165,135,114,115,115,43,120,109,108,34,32,116\n,105,116,108,101,61,34,45,116,121,112,101,34,32,99,111,110,116,101,110,116,61,34\n,116,105,116,108,101,34,32,99,111,110,116,101,110,116,61,34,97,116,32,116,104,\n101,32,115,97,109,101,32,116,105,109,101,46,106,115,34,62,60,47,115,99,114,105,\n112,116,62,10,60,34,32,109,101,116,104,111,100,61,34,112,111,115,116,34,32,60,47\n,115,112,97,110,62,60,47,97,62,60,47,108,105,62,118,101,114,116,105,99,97,108,45\n,97,108,105,103,110,58,116,47,106,113,117,101,114,121,46,109,105,110,46,106,115,\n34,62,46,99,108,105,99,107,40,102,117,110,99,116,105,111,110,40,32,115,116,121,\n108,101,61,34,112,97,100,100,105,110,103,45,125,41,40,41,59,10,60,47,115,99,114,\n105,112,116,62,10,60,47,115,112,97,110,62,60,97,32,104,114,101,102,61,34,60,97,\n32,104,114,101,102,61,34,104,116,116,112,58,47,47,41,59,32,114,101,116,117,114,\n110,32,102,97,108,115,101,59,116,101,120,116,45,100,101,99,111,114,97,116,105,\n111,110,58,32,115,99,114,111,108,108,105,110,103,61,34,110,111,34,32,98,111,114,\n100,101,114,45,99,111,108,108,97,112,115,101,58,97,115,115,111,99,105,97,116,101\n,100,32,119,105,116,104,32,66,97,104,97,115,97,32,73,110,100,111,110,101,115,105\n,97,69,110,103,108,105,115,104,32,108,97,110,103,117,97,103,101,60,116,101,120,\n116,32,120,109,108,58,115,112,97,99,101,61,46,103,105,102,34,32,98,111,114,100,\n101,114,61,34,48,34,60,47,98,111,100,121,62,10,60,47,104,116,109,108,62,10,111,\n118,101,114,102,108,111,119,58,104,105,100,100,101,110,59,105,109,103,32,115,114\n,99,61,34,104,116,116,112,58,47,47,97,100,100,69,118,101,110,116,76,105,115,116,\n101,110,101,114,114,101,115,112,111,110,115,105,98,108,101,32,102,111,114,32,115\n,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,47,102,97,118,105,99,111,\n110,46,105,99,111,34,32,47,62,111,112,101,114,97,116,105,110,103,32,115,121,115,\n116,101,109,34,32,115,116,121,108,101,61,34,119,105,100,116,104,58,49,116,97,114\n,103,101,116,61,34,95,98,108,97,110,107,34,62,83,116,97,116,101,32,85,110,105,\n118,101,114,115,105,116,121,116,101,120,116,45,97,108,105,103,110,58,108,101,102\n,116,59,10,100,111,99,117,109,101,110,116,46,119,114,105,116,101,40,44,32,105,\n110,99,108,117,100,105,110,103,32,116,104,101,32,97,114,111,117,110,100,32,116,\n104,101,32,119,111,114,108,100,41,59,13,10,60,47,115,99,114,105,112,116,62,13,10\n,60,34,32,115,116,121,108,101,61,34,104,101,105,103,104,116,58,59,111,118,101,\n114,102,108,111,119,58,104,105,100,100,101,110,109,111,114,101,32,105,110,102,\n111,114,109,97,116,105,111,110,97,110,32,105,110,116,101,114,110,97,116,105,111,\n110,97,108,97,32,109,101,109,98,101,114,32,111,102,32,116,104,101,32,111,110,101\n,32,111,102,32,116,104,101,32,102,105,114,115,116,99,97,110,32,98,101,32,102,111\n,117,110,100,32,105,110,32,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,\n100,105,115,112,108,97,121,58,32,110,111,110,101,59,34,62,34,32,47,62,10,60,108,\n105,110,107,32,114,101,108,61,34,10,32,32,40,102,117,110,99,116,105,111,110,40,\n41,32,123,116,104,101,32,49,53,116,104,32,99,101,110,116,117,114,121,46,112,114,\n101,118,101,110,116,68,101,102,97,117,108,116,40,108,97,114,103,101,32,110,117,\n109,98,101,114,32,111,102,32,66,121,122,97,110,116,105,110,101,32,69,109,112,105\n,114,101,46,106,112,103,124,116,104,117,109,98,124,108,101,102,116,124,118,97,\n115,116,32,109,97,106,111,114,105,116,121,32,111,102,109,97,106,111,114,105,116,\n121,32,111,102,32,116,104,101,32,32,97,108,105,103,110,61,34,99,101,110,116,101,\n114,34,62,85,110,105,118,101,114,115,105,116,121,32,80,114,101,115,115,100,111,\n109,105,110,97,116,101,100,32,98,121,32,116,104,101,83,101,99,111,110,100,32,87,\n111,114,108,100,32,87,97,114,100,105,115,116,114,105,98,117,116,105,111,110,32,\n111,102,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,116,104,\n101,32,114,101,115,116,32,111,102,32,116,104,101,32,99,104,97,114,97,99,116,101,\n114,105,122,101,100,32,98,121,32,114,101,108,61,34,110,111,102,111,108,108,111,\n119,34,62,100,101,114,105,118,101,115,32,102,114,111,109,32,116,104,101,114,97,\n116,104,101,114,32,116,104,97,110,32,116,104,101,32,97,32,99,111,109,98,105,110,\n97,116,105,111,110,32,111,102,115,116,121,108,101,61,34,119,105,100,116,104,58,\n49,48,48,69,110,103,108,105,115,104,45,115,112,101,97,107,105,110,103,99,111,109\n,112,117,116,101,114,32,115,99,105,101,110,99,101,98,111,114,100,101,114,61,34,\n48,34,32,97,108,116,61,34,116,104,101,32,101,120,105,115,116,101,110,99,101,32,\n111,102,68,101,109,111,99,114,97,116,105,99,32,80,97,114,116,121,34,32,115,116,\n121,108,101,61,34,109,97,114,103,105,110,45,70,111,114,32,116,104,105,115,32,114\n,101,97,115,111,110,44,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,9,115\n,66,121,84,97,103,78,97,109,101,40,115,41,91,48,93,106,115,34,62,60,47,115,99,\n114,105,112,116,62,13,10,60,46,106,115,34,62,60,47,115,99,114,105,112,116,62,13,\n10,108,105,110,107,32,114,101,108,61,34,105,99,111,110,34,32,39,32,97,108,116,61\n,39,39,32,99,108,97,115,115,61,39,102,111,114,109,97,116,105,111,110,32,111,102,\n32,116,104,101,118,101,114,115,105,111,110,115,32,111,102,32,116,104,101,32,60,\n47,97,62,60,47,100,105,118,62,60,47,100,105,118,62,47,112,97,103,101,62,10,32,32\n,60,112,97,103,101,62,10,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,\n116,98,101,99,97,109,101,32,116,104,101,32,102,105,114,115,116,98,97,104,97,115,\n97,32,73,110,100,111,110,101,115,105,97,101,110,103,108,105,115,104,32,40,115,\n105,109,112,108,101,41,206,149,206,187,206,187,206,183,206,189,206,185,206,186,\n206,172,209,133,209,128,208,178,208,176,209,130,209,129,208,186,208,184,208,186,\n208,190,208,188,208,191,208,176,208,189,208,184,208,184,209,143,208,178,208,187,\n209,143,208,181,209,130,209,129,209,143,208,148,208,190,208,177,208,176,208,178,\n208,184,209,130,209,140,209,135,208,181,208,187,208,190,208,178,208,181,208,186,\n208,176,209,128,208,176,208,183,208,178,208,184,209,130,208,184,209,143,208,152,\n208,189,209,130,208,181,209,128,208,189,208,181,209,130,208,158,209,130,208,178,\n208,181,209,130,208,184,209,130,209,140,208,189,208,176,208,191,209,128,208,184,\n208,188,208,181,209,128,208,184,208,189,209,130,208,181,209,128,208,189,208,181,\n209,130,208,186,208,190,209,130,208,190,209,128,208,190,208,179,208,190,209,129,\n209,130,209,128,208,176,208,189,208,184,209,134,209,139,208,186,208,176,209,135,\n208,181,209,129,209,130,208,178,208,181,209,131,209,129,208,187,208,190,208,178,\n208,184,209,143,209,133,208,191,209,128,208,190,208,177,208,187,208,181,208,188,\n209,139,208,191,208,190,208,187,209,131,209,135,208,184,209,130,209,140,209,143,\n208,178,208,187,209,143,209,142,209,130,209,129,209,143,208,189,208,176,208,184,\n208,177,208,190,208,187,208,181,208,181,208,186,208,190,208,188,208,191,208,176,\n208,189,208,184,209,143,208,178,208,189,208,184,208,188,208,176,208,189,208,184,\n208,181,209,129,209,128,208,181,208,180,209,129,209,130,208,178,208,176,216,167,\n217,132,217,133,217,136,216,167,216,182,217,138,216,185,216,167,217,132,216,177,\n216,166,217,138,216,179,217,138,216,169,216,167,217,132,216,167,217,134,216,170,\n217,130,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216,167,216,170,\n217,131,216,167,217,132,216,179,217,138,216,167,216,177,216,167,216,170,216,167,\n217,132,217,133,217,131,216,170,217,136,216,168,216,169,216,167,217,132,216,179,\n216,185,217,136,216,175,217,138,216,169,216,167,216,173,216,181,216,167,216,166,\n217,138,216,167,216,170,216,167,217,132,216,185,216,167,217,132,217,133,217,138,\n216,169,216,167,217,132,216,181,217,136,216,170,217,138,216,167,216,170,216,167,\n217,132,216,167,217,134,216,170,216,177,217,134,216,170,216,167,217,132,216,170,\n216,181,216,167,217,133,217,138,217,133,216,167,217,132,216,165,216,179,217,132,\n216,167,217,133,217,138,216,167,217,132,217,133,216,180,216,167,216,177,217,131,\n216,169,216,167,217,132,217,133,216,177,216,166,217,138,216,167,216,170,114,111,\n98,111,116,115,34,32,99,111,110,116,101,110,116,61,34,60,100,105,118,32,105,100,\n61,34,102,111,111,116,101,114,34,62,116,104,101,32,85,110,105,116,101,100,32,83,\n116,97,116,101,115,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,\n46,106,112,103,124,114,105,103,104,116,124,116,104,117,109,98,124,46,106,115,34,\n62,60,47,115,99,114,105,112,116,62,13,10,60,108,111,99,97,116,105,111,110,46,112\n,114,111,116,111,99,111,108,102,114,97,109,101,98,111,114,100,101,114,61,34,48,\n34,32,115,34,32,47,62,10,60,109,101,116,97,32,110,97,109,101,61,34,60,47,97,62,\n60,47,100,105,118,62,60,47,100,105,118,62,60,102,111,110,116,45,119,101,105,103,\n104,116,58,98,111,108,100,59,38,113,117,111,116,59,32,97,110,100,32,38,113,117,\n111,116,59,100,101,112,101,110,100,105,110,103,32,111,110,32,116,104,101,32,109,\n97,114,103,105,110,58,48,59,112,97,100,100,105,110,103,58,34,32,114,101,108,61,\n34,110,111,102,111,108,108,111,119,34,32,80,114,101,115,105,100,101,110,116,32,\n111,102,32,116,104,101,32,116,119,101,110,116,105,101,116,104,32,99,101,110,116,\n117,114,121,101,118,105,115,105,111,110,62,10,32,32,60,47,112,97,103,101,73,110,\n116,101,114,110,101,116,32,69,120,112,108,111,114,101,114,97,46,97,115,121,110,\n99,32,61,32,116,114,117,101,59,13,10,105,110,102,111,114,109,97,116,105,111,110,\n32,97,98,111,117,116,60,100,105,118,32,105,100,61,34,104,101,97,100,101,114,34,\n62,34,32,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,60,97,32,104,114,\n101,102,61,34,104,116,116,112,115,58,47,47,60,100,105,118,32,105,100,61,34,99,\n111,110,116,101,110,116,34,60,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10\n,60,100,101,114,105,118,101,100,32,102,114,111,109,32,116,104,101,32,60,105,109,\n103,32,115,114,99,61,39,104,116,116,112,58,47,47,97,99,99,111,114,100,105,110,\n103,32,116,111,32,116,104,101,32,10,60,47,98,111,100,121,62,10,60,47,104,116,109\n,108,62,10,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,115,\n99,114,105,112,116,32,108,97,110,103,117,97,103,101,61,34,65,114,105,97,108,44,\n32,72,101,108,118,101,116,105,99,97,44,60,47,97,62,60,115,112,97,110,32,99,108,\n97,115,115,61,34,60,47,115,99,114,105,112,116,62,60,115,99,114,105,112,116,32,\n112,111,108,105,116,105,99,97,108,32,112,97,114,116,105,101,115,116,100,62,60,47\n,116,114,62,60,47,116,97,98,108,101,62,60,104,114,101,102,61,34,104,116,116,112,\n58,47,47,119,119,119,46,105,110,116,101,114,112,114,101,116,97,116,105,111,110,\n32,111,102,114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,100,\n111,99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,99,104,97,114,115,101\n,116,61,34,117,116,102,45,56,34,62,10,98,101,103,105,110,110,105,110,103,32,111,\n102,32,116,104,101,32,114,101,118,101,97,108,101,100,32,116,104,97,116,32,116,\n104,101,116,101,108,101,118,105,115,105,111,110,32,115,101,114,105,101,115,34,32\n,114,101,108,61,34,110,111,102,111,108,108,111,119,34,62,32,116,97,114,103,101,\n116,61,34,95,98,108,97,110,107,34,62,99,108,97,105,109,105,110,103,32,116,104,97\n,116,32,116,104,101,104,116,116,112,37,51,65,37,50,70,37,50,70,119,119,119,46,\n109,97,110,105,102,101,115,116,97,116,105,111,110,115,32,111,102,80,114,105,109,\n101,32,77,105,110,105,115,116,101,114,32,111,102,105,110,102,108,117,101,110,99,\n101,100,32,98,121,32,116,104,101,99,108,97,115,115,61,34,99,108,101,97,114,102,\n105,120,34,62,47,100,105,118,62,13,10,60,47,100,105,118,62,13,10,13,10,116,104,\n114,101,101,45,100,105,109,101,110,115,105,111,110,97,108,67,104,117,114,99,104,\n32,111,102,32,69,110,103,108,97,110,100,111,102,32,78,111,114,116,104,32,67,97,\n114,111,108,105,110,97,115,113,117,97,114,101,32,107,105,108,111,109,101,116,114\n,101,115,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,101,114,100,105\n,115,116,105,110,99,116,32,102,114,111,109,32,116,104,101,99,111,109,109,111,110\n,108,121,32,107,110,111,119,110,32,97,115,80,104,111,110,101,116,105,99,32,65,\n108,112,104,97,98,101,116,100,101,99,108,97,114,101,100,32,116,104,97,116,32,116\n,104,101,99,111,110,116,114,111,108,108,101,100,32,98,121,32,116,104,101,66,101,\n110,106,97,109,105,110,32,70,114,97,110,107,108,105,110,114,111,108,101,45,112,\n108,97,121,105,110,103,32,103,97,109,101,116,104,101,32,85,110,105,118,101,114,\n115,105,116,121,32,111,102,105,110,32,87,101,115,116,101,114,110,32,69,117,114,\n111,112,101,112,101,114,115,111,110,97,108,32,99,111,109,112,117,116,101,114,80,\n114,111,106,101,99,116,32,71,117,116,101,110,98,101,114,103,114,101,103,97,114,\n100,108,101,115,115,32,111,102,32,116,104,101,104,97,115,32,98,101,101,110,32,\n112,114,111,112,111,115,101,100,116,111,103,101,116,104,101,114,32,119,105,116,\n104,32,116,104,101,62,60,47,108,105,62,60,108,105,32,99,108,97,115,115,61,34,105\n,110,32,115,111,109,101,32,99,111,117,110,116,114,105,101,115,109,105,110,46,106\n,115,34,62,60,47,115,99,114,105,112,116,62,111,102,32,116,104,101,32,112,111,112\n,117,108,97,116,105,111,110,111,102,102,105,99,105,97,108,32,108,97,110,103,117,\n97,103,101,60,105,109,103,32,115,114,99,61,34,105,109,97,103,101,115,47,105,100,\n101,110,116,105,102,105,101,100,32,98,121,32,116,104,101,110,97,116,117,114,97,\n108,32,114,101,115,111,117,114,99,101,115,99,108,97,115,115,105,102,105,99,97,\n116,105,111,110,32,111,102,99,97,110,32,98,101,32,99,111,110,115,105,100,101,114\n,101,100,113,117,97,110,116,117,109,32,109,101,99,104,97,110,105,99,115,78,101,\n118,101,114,116,104,101,108,101,115,115,44,32,116,104,101,109,105,108,108,105,\n111,110,32,121,101,97,114,115,32,97,103,111,60,47,98,111,100,121,62,13,10,60,47,\n104,116,109,108,62,13,206,149,206,187,206,187,206,183,206,189,206,185,206,186,\n206,172,10,116,97,107,101,32,97,100,118,97,110,116,97,103,101,32,111,102,97,110,\n100,44,32,97,99,99,111,114,100,105,110,103,32,116,111,97,116,116,114,105,98,117,\n116,101,100,32,116,111,32,116,104,101,77,105,99,114,111,115,111,102,116,32,87,\n105,110,100,111,119,115,116,104,101,32,102,105,114,115,116,32,99,101,110,116,117\n,114,121,117,110,100,101,114,32,116,104,101,32,99,111,110,116,114,111,108,100,\n105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,115,104,111,114,116,\n108,121,32,97,102,116,101,114,32,116,104,101,110,111,116,97,98,108,101,32,101,\n120,99,101,112,116,105,111,110,116,101,110,115,32,111,102,32,116,104,111,117,115\n,97,110,100,115,115,101,118,101,114,97,108,32,100,105,102,102,101,114,101,110,\n116,97,114,111,117,110,100,32,116,104,101,32,119,111,114,108,100,46,114,101,97,\n99,104,105,110,103,32,109,105,108,105,116,97,114,121,105,115,111,108,97,116,101,\n100,32,102,114,111,109,32,116,104,101,111,112,112,111,115,105,116,105,111,110,32\n,116,111,32,116,104,101,116,104,101,32,79,108,100,32,84,101,115,116,97,109,101,\n110,116,65,102,114,105,99,97,110,32,65,109,101,114,105,99,97,110,115,105,110,115\n,101,114,116,101,100,32,105,110,116,111,32,116,104,101,115,101,112,97,114,97,116\n,101,32,102,114,111,109,32,116,104,101,109,101,116,114,111,112,111,108,105,116,\n97,110,32,97,114,101,97,109,97,107,101,115,32,105,116,32,112,111,115,115,105,98,\n108,101,97,99,107,110,111,119,108,101,100,103,101,100,32,116,104,97,116,97,114,\n103,117,97,98,108,121,32,116,104,101,32,109,111,115,116,116,121,112,101,61,34,\n116,101,120,116,47,99,115,115,34,62,10,116,104,101,32,73,110,116,101,114,110,97,\n116,105,111,110,97,108,65,99,99,111,114,100,105,110,103,32,116,111,32,116,104,\n101,32,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,99,111,105,110\n,99,105,100,101,32,119,105,116,104,32,116,104,101,116,119,111,45,116,104,105,114\n,100,115,32,111,102,32,116,104,101,68,117,114,105,110,103,32,116,104,105,115,32,\n116,105,109,101,44,100,117,114,105,110,103,32,116,104,101,32,112,101,114,105,111\n,100,97,110,110,111,117,110,99,101,100,32,116,104,97,116,32,104,101,116,104,101,\n32,105,110,116,101,114,110,97,116,105,111,110,97,108,97,110,100,32,109,111,114,\n101,32,114,101,99,101,110,116,108,121,98,101,108,105,101,118,101,100,32,116,104,\n97,116,32,116,104,101,99,111,110,115,99,105,111,117,115,110,101,115,115,32,97,\n110,100,102,111,114,109,101,114,108,121,32,107,110,111,119,110,32,97,115,115,117\n,114,114,111,117,110,100,101,100,32,98,121,32,116,104,101,102,105,114,115,116,32\n,97,112,112,101,97,114,101,100,32,105,110,111,99,99,97,115,105,111,110,97,108,\n108,121,32,117,115,101,100,112,111,115,105,116,105,111,110,58,97,98,115,111,108,\n117,116,101,59,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,112\n,111,115,105,116,105,111,110,58,114,101,108,97,116,105,118,101,59,116,101,120,\n116,45,97,108,105,103,110,58,99,101,110,116,101,114,59,106,97,120,47,108,105,98,\n115,47,106,113,117,101,114,121,47,49,46,98,97,99,107,103,114,111,117,110,100,45,\n99,111,108,111,114,58,35,116,121,112,101,61,34,97,112,112,108,105,99,97,116,105,\n111,110,47,97,110,103,117,97,103,101,34,32,99,111,110,116,101,110,116,61,34,60,\n109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,80,114,105,118,97\n,99,121,32,80,111,108,105,99,121,60,47,97,62,101,40,34,37,51,67,115,99,114,105,\n112,116,32,115,114,99,61,39,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,\n107,34,62,79,110,32,116,104,101,32,111,116,104,101,114,32,104,97,110,100,44,46,\n106,112,103,124,116,104,117,109,98,124,114,105,103,104,116,124,50,60,47,100,105,\n118,62,60,100,105,118,32,99,108,97,115,115,61,34,60,100,105,118,32,115,116,121,\n108,101,61,34,102,108,111,97,116,58,110,105,110,101,116,101,101,110,116,104,32,\n99,101,110,116,117,114,121,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,\n62,13,10,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,115,59,116,\n101,120,116,45,97,108,105,103,110,58,99,101,110,116,101,114,102,111,110,116,45,\n119,101,105,103,104,116,58,32,98,111,108,100,59,32,65,99,99,111,114,100,105,110,\n103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,32,98,\n101,116,119,101,101,110,34,32,102,114,97,109,101,98,111,114,100,101,114,61,34,48\n,34,32,34,32,115,116,121,108,101,61,34,112,111,115,105,116,105,111,110,58,108,\n105,110,107,32,104,114,101,102,61,34,104,116,116,112,58,47,47,104,116,109,108,52\n,47,108,111,111,115,101,46,100,116,100,34,62,10,100,117,114,105,110,103,32,116,\n104,105,115,32,112,101,114,105,111,100,60,47,116,100,62,60,47,116,114,62,60,47,\n116,97,98,108,101,62,99,108,111,115,101,108,121,32,114,101,108,97,116,101,100,32\n,116,111,102,111,114,32,116,104,101,32,102,105,114,115,116,32,116,105,109,101,59\n,102,111,110,116,45,119,101,105,103,104,116,58,98,111,108,100,59,105,110,112,117\n,116,32,116,121,112,101,61,34,116,101,120,116,34,32,60,115,112,97,110,32,115,116\n,121,108,101,61,34,102,111,110,116,45,111,110,114,101,97,100,121,115,116,97,116,\n101,99,104,97,110,103,101,9,60,100,105,118,32,99,108,97,115,115,61,34,99,108,101\n,97,114,100,111,99,117,109,101,110,116,46,108,111,99,97,116,105,111,110,46,32,70\n,111,114,32,101,120,97,109,112,108,101,44,32,116,104,101,32,97,32,119,105,100,\n101,32,118,97,114,105,101,116,121,32,111,102,32,60,33,68,79,67,84,89,80,69,32,\n104,116,109,108,62,13,10,60,38,110,98,115,112,59,38,110,98,115,112,59,38,110,98,\n115,112,59,34,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,115,116\n,121,108,101,61,34,102,108,111,97,116,58,108,101,102,116,59,99,111,110,99,101,\n114,110,101,100,32,119,105,116,104,32,116,104,101,61,104,116,116,112,37,51,65,37\n,50,70,37,50,70,119,119,119,46,105,110,32,112,111,112,117,108,97,114,32,99,117,\n108,116,117,114,101,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,47\n,62,105,116,32,105,115,32,112,111,115,115,105,98,108,101,32,116,111,32,72,97,114\n,118,97,114,100,32,85,110,105,118,101,114,115,105,116,121,116,121,108,101,115,\n104,101,101,116,34,32,104,114,101,102,61,34,47,116,104,101,32,109,97,105,110,32,\n99,104,97,114,97,99,116,101,114,79,120,102,111,114,100,32,85,110,105,118,101,114\n,115,105,116,121,32,32,110,97,109,101,61,34,107,101,121,119,111,114,100,115,34,\n32,99,115,116,121,108,101,61,34,116,101,120,116,45,97,108,105,103,110,58,116,104\n,101,32,85,110,105,116,101,100,32,75,105,110,103,100,111,109,102,101,100,101,114\n,97,108,32,103,111,118,101,114,110,109,101,110,116,60,100,105,118,32,115,116,121\n,108,101,61,34,109,97,114,103,105,110,32,100,101,112,101,110,100,105,110,103,32,\n111,110,32,116,104,101,32,100,101,115,99,114,105,112,116,105,111,110,32,111,102,\n32,116,104,101,60,100,105,118,32,99,108,97,115,115,61,34,104,101,97,100,101,114,\n46,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,100,101,115,116,\n114,117,99,116,105,111,110,32,111,102,32,116,104,101,115,108,105,103,104,116,108\n,121,32,100,105,102,102,101,114,101,110,116,105,110,32,97,99,99,111,114,100,97,\n110,99,101,32,119,105,116,104,116,101,108,101,99,111,109,109,117,110,105,99,97,\n116,105,111,110,115,105,110,100,105,99,97,116,101,115,32,116,104,97,116,32,116,\n104,101,115,104,111,114,116,108,121,32,116,104,101,114,101,97,102,116,101,114,\n101,115,112,101,99,105,97,108,108,121,32,105,110,32,116,104,101,32,69,117,114,\n111,112,101,97,110,32,99,111,117,110,116,114,105,101,115,72,111,119,101,118,101,\n114,44,32,116,104,101,114,101,32,97,114,101,115,114,99,61,34,104,116,116,112,58,\n47,47,115,116,97,116,105,99,115,117,103,103,101,115,116,101,100,32,116,104,97,\n116,32,116,104,101,34,32,115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,\n46,97,32,108,97,114,103,101,32,110,117,109,98,101,114,32,111,102,32,84,101,108,\n101,99,111,109,109,117,110,105,99,97,116,105,111,110,115,34,32,114,101,108,61,34\n,110,111,102,111,108,108,111,119,34,32,116,72,111,108,121,32,82,111,109,97,110,\n32,69,109,112,101,114,111,114,97,108,109,111,115,116,32,101,120,99,108,117,115,\n105,118,101,108,121,34,32,98,111,114,100,101,114,61,34,48,34,32,97,108,116,61,34\n,83,101,99,114,101,116,97,114,121,32,111,102,32,83,116,97,116,101,99,117,108,109\n,105,110,97,116,105,110,103,32,105,110,32,116,104,101,67,73,65,32,87,111,114,108\n,100,32,70,97,99,116,98,111,111,107,116,104,101,32,109,111,115,116,32,105,109,\n112,111,114,116,97,110,116,97,110,110,105,118,101,114,115,97,114,121,32,111,102,\n32,116,104,101,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45\n,60,108,105,62,60,101,109,62,60,97,32,104,114,101,102,61,34,47,116,104,101,32,65\n,116,108,97,110,116,105,99,32,79,99,101,97,110,115,116,114,105,99,116,108,121,32\n,115,112,101,97,107,105,110,103,44,115,104,111,114,116,108,121,32,98,101,102,111\n,114,101,32,116,104,101,100,105,102,102,101,114,101,110,116,32,116,121,112,101,\n115,32,111,102,116,104,101,32,79,116,116,111,109,97,110,32,69,109,112,105,114,\n101,62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,65,110,32,73,\n110,116,114,111,100,117,99,116,105,111,110,32,116,111,99,111,110,115,101,113,117\n,101,110,99,101,32,111,102,32,116,104,101,100,101,112,97,114,116,117,114,101,32,\n102,114,111,109,32,116,104,101,67,111,110,102,101,100,101,114,97,116,101,32,83,\n116,97,116,101,115,105,110,100,105,103,101,110,111,117,115,32,112,101,111,112,\n108,101,115,80,114,111,99,101,101,100,105,110,103,115,32,111,102,32,116,104,101,\n105,110,102,111,114,109,97,116,105,111,110,32,111,110,32,116,104,101,116,104,101\n,111,114,105,101,115,32,104,97,118,101,32,98,101,101,110,105,110,118,111,108,118\n,101,109,101,110,116,32,105,110,32,116,104,101,100,105,118,105,100,101,100,32,\n105,110,116,111,32,116,104,114,101,101,97,100,106,97,99,101,110,116,32,99,111,\n117,110,116,114,105,101,115,105,115,32,114,101,115,112,111,110,115,105,98,108,\n101,32,102,111,114,100,105,115,115,111,108,117,116,105,111,110,32,111,102,32,116\n,104,101,99,111,108,108,97,98,111,114,97,116,105,111,110,32,119,105,116,104,119,\n105,100,101,108,121,32,114,101,103,97,114,100,101,100,32,97,115,104,105,115,32,\n99,111,110,116,101,109,112,111,114,97,114,105,101,115,102,111,117,110,100,105,\n110,103,32,109,101,109,98,101,114,32,111,102,68,111,109,105,110,105,99,97,110,32\n,82,101,112,117,98,108,105,99,103,101,110,101,114,97,108,108,121,32,97,99,99,101\n,112,116,101,100,116,104,101,32,112,111,115,115,105,98,105,108,105,116,121,32,\n111,102,97,114,101,32,97,108,115,111,32,97,118,97,105,108,97,98,108,101,117,110,\n100,101,114,32,99,111,110,115,116,114,117,99,116,105,111,110,114,101,115,116,111\n,114,97,116,105,111,110,32,111,102,32,116,104,101,116,104,101,32,103,101,110,101\n,114,97,108,32,112,117,98,108,105,99,105,115,32,97,108,109,111,115,116,32,101,\n110,116,105,114,101,108,121,112,97,115,115,101,115,32,116,104,114,111,117,103,\n104,32,116,104,101,104,97,115,32,98,101,101,110,32,115,117,103,103,101,115,116,\n101,100,99,111,109,112,117,116,101,114,32,97,110,100,32,118,105,100,101,111,71,\n101,114,109,97,110,105,99,32,108,97,110,103,117,97,103,101,115,32,97,99,99,111,\n114,100,105,110,103,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110\n,116,32,102,114,111,109,32,116,104,101,115,104,111,114,116,108,121,32,97,102,116\n,101,114,119,97,114,100,115,104,114,101,102,61,34,104,116,116,112,115,58,47,47,\n119,119,119,46,114,101,99,101,110,116,32,100,101,118,101,108,111,112,109,101,110\n,116,66,111,97,114,100,32,111,102,32,68,105,114,101,99,116,111,114,115,60,100,\n105,118,32,99,108,97,115,115,61,34,115,101,97,114,99,104,124,32,60,97,32,104,114\n,101,102,61,34,104,116,116,112,58,47,47,73,110,32,112,97,114,116,105,99,117,108,\n97,114,44,32,116,104,101,77,117,108,116,105,112,108,101,32,102,111,111,116,110,\n111,116,101,115,111,114,32,111,116,104,101,114,32,115,117,98,115,116,97,110,99,\n101,116,104,111,117,115,97,110,100,115,32,111,102,32,121,101,97,114,115,116,114,\n97,110,115,108,97,116,105,111,110,32,111,102,32,116,104,101,60,47,100,105,118,62\n,13,10,60,47,100,105,118,62,13,10,13,10,60,97,32,104,114,101,102,61,34,105,110,\n100,101,120,46,112,104,112,119,97,115,32,101,115,116,97,98,108,105,115,104,101,\n100,32,105,110,109,105,110,46,106,115,34,62,60,47,115,99,114,105,112,116,62,10,\n112,97,114,116,105,99,105,112,97,116,101,32,105,110,32,116,104,101,97,32,115,116\n,114,111,110,103,32,105,110,102,108,117,101,110,99,101,115,116,121,108,101,61,34\n,109,97,114,103,105,110,45,116,111,112,58,114,101,112,114,101,115,101,110,116,\n101,100,32,98,121,32,116,104,101,103,114,97,100,117,97,116,101,100,32,102,114,\n111,109,32,116,104,101,84,114,97,100,105,116,105,111,110,97,108,108,121,44,32,\n116,104,101,69,108,101,109,101,110,116,40,34,115,99,114,105,112,116,34,41,59,72,\n111,119,101,118,101,114,44,32,115,105,110,99,101,32,116,104,101,47,100,105,118,\n62,10,60,47,100,105,118,62,10,60,100,105,118,32,108,101,102,116,59,32,109,97,114\n,103,105,110,45,108,101,102,116,58,112,114,111,116,101,99,116,105,111,110,32,97,\n103,97,105,110,115,116,48,59,32,118,101,114,116,105,99,97,108,45,97,108,105,103,\n110,58,85,110,102,111,114,116,117,110,97,116,101,108,121,44,32,116,104,101,116,\n121,112,101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,47,100,105,118,62,\n10,60,100,105,118,32,99,108,97,115,115,61,34,32,99,108,97,115,115,61,34,99,108,\n101,97,114,102,105,120,34,62,60,100,105,118,32,99,108,97,115,115,61,34,102,111,\n111,116,101,114,9,9,60,47,100,105,118,62,10,9,9,60,47,100,105,118,62,10,116,104,\n101,32,109,111,116,105,111,110,32,112,105,99,116,117,114,101,208,145,209,138,208\n,187,208,179,208,176,209,128,209,129,208,186,208,184,208,177,209,138,208,187,208\n,179,208,176,209,128,209,129,208,186,208,184,208,164,208,181,208,180,208,181,209\n,128,208,176,209,134,208,184,208,184,208,189,208,181,209,129,208,186,208,190,208\n,187,209,140,208,186,208,190,209,129,208,190,208,190,208,177,209,137,208,181,208\n,189,208,184,208,181,209,129,208,190,208,190,208,177,209,137,208,181,208,189,208\n,184,209,143,208,191,209,128,208,190,208,179,209,128,208,176,208,188,208,188,209\n,139,208,158,209,130,208,191,209,128,208,176,208,178,208,184,209,130,209,140,208\n,177,208,181,209,129,208,191,208,187,208,176,209,130,208,189,208,190,208,188,208\n,176,209,130,208,181,209,128,208,184,208,176,208,187,209,139,208,191,208,190,208\n,183,208,178,208,190,208,187,209,143,208,181,209,130,208,191,208,190,209,129,208\n,187,208,181,208,180,208,189,208,184,208,181,209,128,208,176,208,183,208,187,208\n,184,209,135,208,189,209,139,209,133,208,191,209,128,208,190,208,180,209,131,208\n,186,209,134,208,184,208,184,208,191,209,128,208,190,208,179,209,128,208,176,208\n,188,208,188,208,176,208,191,208,190,208,187,208,189,208,190,209,129,209,130,209\n,140,209,142,208,189,208,176,209,133,208,190,208,180,208,184,209,130,209,129,209\n,143,208,184,208,183,208,177,209,128,208,176,208,189,208,189,208,190,208,181,208\n,189,208,176,209,129,208,181,208,187,208,181,208,189,208,184,209,143,208,184,208\n,183,208,188,208,181,208,189,208,181,208,189,208,184,209,143,208,186,208,176,209\n,130,208,181,208,179,208,190,209,128,208,184,208,184,208,144,208,187,208,181,208\n,186,209,129,208,176,208,189,208,180,209,128,224,164,166,224,165,141,224,164,181\n,224,164,190,224,164,176,224,164,190,224,164,174,224,165,136,224,164,168,224,165\n,129,224,164,133,224,164,178,224,164,170,224,165,141,224,164,176,224,164,166,224\n,164,190,224,164,168,224,164,173,224,164,190,224,164,176,224,164,164,224,165,128\n,224,164,175,224,164,133,224,164,168,224,165,129,224,164,166,224,165,135,224,164\n,182,224,164,185,224,164,191,224,164,168,224,165,141,224,164,166,224,165,128,224\n,164,135,224,164,130,224,164,161,224,164,191,224,164,175,224,164,190,224,164,166\n,224,164,191,224,164,178,224,165,141,224,164,178,224,165,128,224,164,133,224,164\n,167,224,164,191,224,164,149,224,164,190,224,164,176,224,164,181,224,165,128,224\n,164,161,224,164,191,224,164,175,224,165,139,224,164,154,224,164,191,224,164,159\n,224,165,141,224,164,160,224,165,135,224,164,184,224,164,174,224,164,190,224,164\n,154,224,164,190,224,164,176,224,164,156,224,164,130,224,164,149,224,165,141,224\n,164,182,224,164,168,224,164,166,224,165,129,224,164,168,224,164,191,224,164,175\n,224,164,190,224,164,170,224,165,141,224,164,176,224,164,175,224,165,139,224,164\n,151,224,164,133,224,164,168,224,165,129,224,164,184,224,164,190,224,164,176,224\n,164,145,224,164,168,224,164,178,224,164,190,224,164,135,224,164,168,224,164,170\n,224,164,190,224,164,176,224,165,141,224,164,159,224,165,128,224,164,182,224,164\n,176,224,165,141,224,164,164,224,165,139,224,164,130,224,164,178,224,165,139,224\n,164,149,224,164,184,224,164,173,224,164,190,224,164,171,224,164,188,224,165,141\n,224,164,178,224,165,136,224,164,182,224,164,182,224,164,176,224,165,141,224,164\n,164,224,165,135,224,164,130,224,164,170,224,165,141,224,164,176,224,164,166,224\n,165,135,224,164,182,224,164,170,224,165,141,224,164,178,224,165,135,224,164,175\n,224,164,176,224,164,149,224,165,135,224,164,130,224,164,166,224,165,141,224,164\n,176,224,164,184,224,165,141,224,164,165,224,164,191,224,164,164,224,164,191,224\n,164,137,224,164,164,224,165,141,224,164,170,224,164,190,224,164,166,224,164,137\n,224,164,168,224,165,141,224,164,185,224,165,135,224,164,130,224,164,154,224,164\n,191,224,164,159,224,165,141,224,164,160,224,164,190,224,164,175,224,164,190,224\n,164,164,224,165,141,224,164,176,224,164,190,224,164,156,224,165,141,224,164,175\n,224,164,190,224,164,166,224,164,190,224,164,170,224,165,129,224,164,176,224,164\n,190,224,164,168,224,165,135,224,164,156,224,165,139,224,164,161,224,164,188,224\n,165,135,224,164,130,224,164,133,224,164,168,224,165,129,224,164,181,224,164,190\n,224,164,166,224,164,182,224,165,141,224,164,176,224,165,135,224,164,163,224,165\n,128,224,164,182,224,164,191,224,164,149,224,165,141,224,164,183,224,164,190,224\n,164,184,224,164,176,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184\n,224,164,130,224,164,151,224,165,141,224,164,176,224,164,185,224,164,170,224,164\n,176,224,164,191,224,164,163,224,164,190,224,164,174,224,164,172,224,165,141,224\n,164,176,224,164,190,224,164,130,224,164,161,224,164,172,224,164,154,224,165,141\n,224,164,154,224,165,139,224,164,130,224,164,137,224,164,170,224,164,178,224,164\n,172,224,165,141,224,164,167,224,164,174,224,164,130,224,164,164,224,165,141,224\n,164,176,224,165,128,224,164,184,224,164,130,224,164,170,224,164,176,224,165,141\n,224,164,149,224,164,137,224,164,174,224,165,141,224,164,174,224,165,128,224,164\n,166,224,164,174,224,164,190,224,164,167,224,165,141,224,164,175,224,164,174,224\n,164,184,224,164,185,224,164,190,224,164,175,224,164,164,224,164,190,224,164,182\n,224,164,172,224,165,141,224,164,166,224,165,139,224,164,130,224,164,174,224,165\n,128,224,164,161,224,164,191,224,164,175,224,164,190,224,164,134,224,164,136,224\n,164,170,224,165,128,224,164,143,224,164,178,224,164,174,224,165,139,224,164,172\n,224,164,190,224,164,135,224,164,178,224,164,184,224,164,130,224,164,150,224,165\n,141,224,164,175,224,164,190,224,164,134,224,164,170,224,164,176,224,165,135,224\n,164,182,224,164,168,224,164,133,224,164,168,224,165,129,224,164,172,224,164,130\n,224,164,167,224,164,172,224,164,190,224,164,156,224,164,188,224,164,190,224,164\n,176,224,164,168,224,164,181,224,165,128,224,164,168,224,164,164,224,164,174,224\n,164,170,224,165,141,224,164,176,224,164,174,224,165,129,224,164,150,224,164,170\n,224,165,141,224,164,176,224,164,182,224,165,141,224,164,168,224,164,170,224,164\n,176,224,164,191,224,164,181,224,164,190,224,164,176,224,164,168,224,165,129,224\n,164,149,224,164,184,224,164,190,224,164,168,224,164,184,224,164,174,224,164,176\n,224,165,141,224,164,165,224,164,168,224,164,134,224,164,175,224,165,139,224,164\n,156,224,164,191,224,164,164,224,164,184,224,165,139,224,164,174,224,164,181,224\n,164,190,224,164,176,216,167,217,132,217,133,216,180,216,167,216,177,217,131,216\n,167,216,170,216,167,217,132,217,133,217,134,216,170,216,175,217,138,216,167,216\n,170,216,167,217,132,217,131,217,133,216,168,217,138,217,136,216,170,216,177,216\n,167,217,132,217,133,216,180,216,167,217,135,216,175,216,167,216,170,216,185,216\n,175,216,175,216,167,217,132,216,178,217,136,216,167,216,177,216,185,216,175,216\n,175,216,167,217,132,216,177,216,175,217,136,216,175,216,167,217,132,216,165,216\n,179,217,132,216,167,217,133,217,138,216,169,216,167,217,132,217,129,217,136,216\n,170,217,136,216,180,217,136,216,168,216,167,217,132,217,133,216,179,216,167,216\n,168,217,130,216,167,216,170,216,167,217,132,217,133,216,185,217,132,217,136,217\n,133,216,167,216,170,216,167,217,132,217,133,216,179,217,132,216,179,217,132,216\n,167,216,170,216,167,217,132,216,172,216,177,216,167,217,129,217,138,217,131,216\n,179,216,167,217,132,216,167,216,179,217,132,216,167,217,133,217,138,216,169,216\n,167,217,132,216,167,216,170,216,181,216,167,217,132,216,167,216,170,107,101,121\n,119,111,114,100,115,34,32,99,111,110,116,101,110,116,61,34,119,51,46,111,114,\n103,47,49,57,57,57,47,120,104,116,109,108,34,62,60,97,32,116,97,114,103,101,116,\n61,34,95,98,108,97,110,107,34,32,116,101,120,116,47,104,116,109,108,59,32,99,104\n,97,114,115,101,116,61,34,32,116,97,114,103,101,116,61,34,95,98,108,97,110,107,\n34,62,60,116,97,98,108,101,32,99,101,108,108,112,97,100,100,105,110,103,61,34,97\n,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,116,101,120,\n116,45,97,108,105,103,110,58,32,99,101,110,116,101,114,59,116,111,32,108,97,115,\n116,32,118,101,114,115,105,111,110,32,98,121,32,98,97,99,107,103,114,111,117,110\n,100,45,99,111,108,111,114,58,32,35,34,32,104,114,101,102,61,34,104,116,116,112,\n58,47,47,119,119,119,46,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,32\n,105,100,61,60,97,32,104,114,101,102,61,34,35,34,32,99,108,97,115,115,61,34,34,\n62,60,105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,99,114,105,112,\n116,34,32,115,114,99,61,34,104,116,116,112,58,47,47,10,60,115,99,114,105,112,116\n,32,108,97,110,103,117,97,103,101,61,34,47,47,69,78,34,32,34,104,116,116,112,58,\n47,47,119,119,119,46,119,101,110,99,111,100,101,85,82,73,67,111,109,112,111,110,\n101,110,116,40,34,32,104,114,101,102,61,34,106,97,118,97,115,99,114,105,112,116,\n58,60,100,105,118,32,99,108,97,115,115,61,34,99,111,110,116,101,110,116,100,111,\n99,117,109,101,110,116,46,119,114,105,116,101,40,39,60,115,99,112,111,115,105,\n116,105,111,110,58,32,97,98,115,111,108,117,116,101,59,115,99,114,105,112,116,32\n,115,114,99,61,34,104,116,116,112,58,47,47,32,115,116,121,108,101,61,34,109,97,\n114,103,105,110,45,116,111,112,58,46,109,105,110,46,106,115,34,62,60,47,115,99,\n114,105,112,116,62,10,60,47,100,105,118,62,10,60,100,105,118,32,99,108,97,115,\n115,61,34,119,51,46,111,114,103,47,49,57,57,57,47,120,104,116,109,108,34,32,10,\n13,10,60,47,98,111,100,121,62,13,10,60,47,104,116,109,108,62,100,105,115,116,105\n,110,99,116,105,111,110,32,98,101,116,119,101,101,110,47,34,32,116,97,114,103,\n101,116,61,34,95,98,108,97,110,107,34,62,60,108,105,110,107,32,104,114,101,102,\n61,34,104,116,116,112,58,47,47,101,110,99,111,100,105,110,103,61,34,117,116,102,\n45,56,34,63,62,10,119,46,97,100,100,69,118,101,110,116,76,105,115,116,101,110,\n101,114,63,97,99,116,105,111,110,61,34,104,116,116,112,58,47,47,119,119,119,46,\n105,99,111,110,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,32,115,116,\n121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,58,116,121,112,101,61,34,\n116,101,120,116,47,99,115,115,34,32,47,62,10,109,101,116,97,32,112,114,111,112,\n101,114,116,121,61,34,111,103,58,116,60,105,110,112,117,116,32,116,121,112,101,\n61,34,116,101,120,116,34,32,32,115,116,121,108,101,61,34,116,101,120,116,45,97,\n108,105,103,110,58,116,104,101,32,100,101,118,101,108,111,112,109,101,110,116,32\n,111,102,32,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116,\n101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,105,115\n,32,99,111,110,115,105,100,101,114,101,100,32,116,111,32,98,101,116,97,98,108,\n101,32,119,105,100,116,104,61,34,49,48,48,37,34,32,73,110,32,97,100,100,105,116,\n105,111,110,32,116,111,32,116,104,101,32,99,111,110,116,114,105,98,117,116,101,\n100,32,116,111,32,116,104,101,32,100,105,102,102,101,114,101,110,99,101,115,32,\n98,101,116,119,101,101,110,100,101,118,101,108,111,112,109,101,110,116,32,111,\n102,32,116,104,101,32,73,116,32,105,115,32,105,109,112,111,114,116,97,110,116,32\n,116,111,32,60,47,115,99,114,105,112,116,62,10,10,60,115,99,114,105,112,116,32,\n32,115,116,121,108,101,61,34,102,111,110,116,45,115,105,122,101,58,49,62,60,47,\n115,112,97,110,62,60,115,112,97,110,32,105,100,61,103,98,76,105,98,114,97,114,\n121,32,111,102,32,67,111,110,103,114,101,115,115,60,105,109,103,32,115,114,99,61\n,34,104,116,116,112,58,47,47,105,109,69,110,103,108,105,115,104,32,116,114,97,\n110,115,108,97,116,105,111,110,65,99,97,100,101,109,121,32,111,102,32,83,99,105,\n101,110,99,101,115,100,105,118,32,115,116,121,108,101,61,34,100,105,115,112,108,\n97,121,58,99,111,110,115,116,114,117,99,116,105,111,110,32,111,102,32,116,104,\n101,46,103,101,116,69,108,101,109,101,110,116,66,121,73,100,40,105,100,41,105,\n110,32,99,111,110,106,117,110,99,116,105,111,110,32,119,105,116,104,69,108,101,\n109,101,110,116,40,39,115,99,114,105,112,116,39,41,59,32,60,109,101,116,97,32,\n112,114,111,112,101,114,116,121,61,34,111,103,58,208,145,209,138,208,187,208,179\n,208,176,209,128,209,129,208,186,208,184,10,32,116,121,112,101,61,34,116,101,120\n,116,34,32,110,97,109,101,61,34,62,80,114,105,118,97,99,121,32,80,111,108,105,99\n,121,60,47,97,62,97,100,109,105,110,105,115,116,101,114,101,100,32,98,121,32,116\n,104,101,101,110,97,98,108,101,83,105,110,103,108,101,82,101,113,117,101,115,116\n,115,116,121,108,101,61,38,113,117,111,116,59,109,97,114,103,105,110,58,60,47,\n100,105,118,62,60,47,100,105,118,62,60,47,100,105,118,62,60,62,60,105,109,103,32\n,115,114,99,61,34,104,116,116,112,58,47,47,105,32,115,116,121,108,101,61,38,113,\n117,111,116,59,102,108,111,97,116,58,114,101,102,101,114,114,101,100,32,116,111,\n32,97,115,32,116,104,101,32,116,111,116,97,108,32,112,111,112,117,108,97,116,105\n,111,110,32,111,102,105,110,32,87,97,115,104,105,110,103,116,111,110,44,32,68,46\n,67,46,32,115,116,121,108,101,61,34,98,97,99,107,103,114,111,117,110,100,45,97,\n109,111,110,103,32,111,116,104,101,114,32,116,104,105,110,103,115,44,111,114,103\n,97,110,105,122,97,116,105,111,110,32,111,102,32,116,104,101,112,97,114,116,105,\n99,105,112,97,116,101,100,32,105,110,32,116,104,101,116,104,101,32,105,110,116,\n114,111,100,117,99,116,105,111,110,32,111,102,105,100,101,110,116,105,102,105,\n101,100,32,119,105,116,104,32,116,104,101,102,105,99,116,105,111,110,97,108,32,\n99,104,97,114,97,99,116,101,114,32,79,120,102,111,114,100,32,85,110,105,118,101,\n114,115,105,116,121,32,109,105,115,117,110,100,101,114,115,116,97,110,100,105,\n110,103,32,111,102,84,104,101,114,101,32,97,114,101,44,32,104,111,119,101,118,\n101,114,44,115,116,121,108,101,115,104,101,101,116,34,32,104,114,101,102,61,34,\n47,67,111,108,117,109,98,105,97,32,85,110,105,118,101,114,115,105,116,121,101,\n120,112,97,110,100,101,100,32,116,111,32,105,110,99,108,117,100,101,117,115,117,\n97,108,108,121,32,114,101,102,101,114,114,101,100,32,116,111,105,110,100,105,99,\n97,116,105,110,103,32,116,104,97,116,32,116,104,101,104,97,118,101,32,115,117,\n103,103,101,115,116,101,100,32,116,104,97,116,97,102,102,105,108,105,97,116,101,\n100,32,119,105,116,104,32,116,104,101,99,111,114,114,101,108,97,116,105,111,110,\n32,98,101,116,119,101,101,110,110,117,109,98,101,114,32,111,102,32,100,105,102,\n102,101,114,101,110,116,62,60,47,116,100,62,60,47,116,114,62,60,47,116,97,98,108\n,101,62,82,101,112,117,98,108,105,99,32,111,102,32,73,114,101,108,97,110,100,10,\n60,47,115,99,114,105,112,116,62,10,60,115,99,114,105,112,116,32,117,110,100,101,\n114,32,116,104,101,32,105,110,102,108,117,101,110,99,101,99,111,110,116,114,105,\n98,117,116,105,111,110,32,116,111,32,116,104,101,79,102,102,105,99,105,97,108,32\n,119,101,98,115,105,116,101,32,111,102,104,101,97,100,113,117,97,114,116,101,114\n,115,32,111,102,32,116,104,101,99,101,110,116,101,114,101,100,32,97,114,111,117,\n110,100,32,116,104,101,105,109,112,108,105,99,97,116,105,111,110,115,32,111,102,\n32,116,104,101,104,97,118,101,32,98,101,101,110,32,100,101,118,101,108,111,112,\n101,100,70,101,100,101,114,97,108,32,82,101,112,117,98,108,105,99,32,111,102,98,\n101,99,97,109,101,32,105,110,99,114,101,97,115,105,110,103,108,121,99,111,110,\n116,105,110,117,97,116,105,111,110,32,111,102,32,116,104,101,78,111,116,101,44,\n32,104,111,119,101,118,101,114,44,32,116,104,97,116,115,105,109,105,108,97,114,\n32,116,111,32,116,104,97,116,32,111,102,32,99,97,112,97,98,105,108,105,116,105,\n101,115,32,111,102,32,116,104,101,97,99,99,111,114,100,97,110,99,101,32,119,105,\n116,104,32,116,104,101,112,97,114,116,105,99,105,112,97,110,116,115,32,105,110,\n32,116,104,101,102,117,114,116,104,101,114,32,100,101,118,101,108,111,112,109,\n101,110,116,117,110,100,101,114,32,116,104,101,32,100,105,114,101,99,116,105,111\n,110,105,115,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,101,100,\n104,105,115,32,121,111,117,110,103,101,114,32,98,114,111,116,104,101,114,60,47,\n116,100,62,60,47,116,114,62,60,47,116,97,98,108,101,62,60,97,32,104,116,116,112,\n45,101,113,117,105,118,61,34,88,45,85,65,45,112,104,121,115,105,99,97,108,32,112\n,114,111,112,101,114,116,105,101,115,111,102,32,66,114,105,116,105,115,104,32,67\n,111,108,117,109,98,105,97,104,97,115,32,98,101,101,110,32,99,114,105,116,105,99\n,105,122,101,100,40,119,105,116,104,32,116,104,101,32,101,120,99,101,112,116,105\n,111,110,113,117,101,115,116,105,111,110,115,32,97,98,111,117,116,32,116,104,101\n,112,97,115,115,105,110,103,32,116,104,114,111,117,103,104,32,116,104,101,48,34,\n32,99,101,108,108,112,97,100,100,105,110,103,61,34,48,34,32,116,104,111,117,115,\n97,110,100,115,32,111,102,32,112,101,111,112,108,101,114,101,100,105,114,101,99,\n116,115,32,104,101,114,101,46,32,70,111,114,104,97,118,101,32,99,104,105,108,100\n,114,101,110,32,117,110,100,101,114,37,51,69,37,51,67,47,115,99,114,105,112,116,\n37,51,69,34,41,41,59,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119\n,119,119,46,60,108,105,62,60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,\n47,115,105,116,101,95,110,97,109,101,34,32,99,111,110,116,101,110,116,61,34,116,\n101,120,116,45,100,101,99,111,114,97,116,105,111,110,58,110,111,110,101,115,116,\n121,108,101,61,34,100,105,115,112,108,97,121,58,32,110,111,110,101,60,109,101,\n116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,88,45,110,101,119,32,68,\n97,116,101,40,41,46,103,101,116,84,105,109,101,40,41,32,116,121,112,101,61,34,\n105,109,97,103,101,47,120,45,105,99,111,110,34,60,47,115,112,97,110,62,60,115,\n112,97,110,32,99,108,97,115,115,61,34,108,97,110,103,117,97,103,101,61,34,106,97\n,118,97,115,99,114,105,112,116,119,105,110,100,111,119,46,108,111,99,97,116,105,\n111,110,46,104,114,101,102,60,97,32,104,114,101,102,61,34,106,97,118,97,115,99,\n114,105,112,116,58,45,45,62,13,10,60,115,99,114,105,112,116,32,116,121,112,101,\n61,34,116,60,97,32,104,114,101,102,61,39,104,116,116,112,58,47,47,119,119,119,46\n,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,114,101,102,61,34,60,47,\n100,105,118,62,13,10,60,100,105,118,32,99,108,97,115,115,61,34,60,115,99,114,105\n,112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,34,32,114,101,108,61,34,\n115,116,121,108,101,115,104,101,101,116,34,32,116,60,47,100,105,118,62,10,60,115\n,99,114,105,112,116,32,116,121,112,101,61,47,97,62,32,60,97,32,104,114,101,102,\n61,34,104,116,116,112,58,47,47,32,97,108,108,111,119,84,114,97,110,115,112,97,\n114,101,110,99,121,61,34,88,45,85,65,45,67,111,109,112,97,116,105,98,108,101,34,\n32,99,111,110,114,101,108,97,116,105,111,110,115,104,105,112,32,98,101,116,119,\n101,101,110,10,60,47,115,99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,\n32,60,47,97,62,60,47,108,105,62,60,47,117,108,62,60,47,100,105,118,62,97,115,115\n,111,99,105,97,116,101,100,32,119,105,116,104,32,116,104,101,32,112,114,111,103,\n114,97,109,109,105,110,103,32,108,97,110,103,117,97,103,101,60,47,97,62,60,97,32\n,104,114,101,102,61,34,104,116,116,112,58,47,47,60,47,97,62,60,47,108,105,62,60,\n108,105,32,99,108,97,115,115,61,34,102,111,114,109,32,97,99,116,105,111,110,61,\n34,104,116,116,112,58,47,47,60,100,105,118,32,115,116,121,108,101,61,34,100,105,\n115,112,108,97,121,58,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101\n,61,34,113,34,60,116,97,98,108,101,32,119,105,100,116,104,61,34,49,48,48,37,34,\n32,98,97,99,107,103,114,111,117,110,100,45,112,111,115,105,116,105,111,110,58,34\n,32,98,111,114,100,101,114,61,34,48,34,32,119,105,100,116,104,61,34,114,101,108,\n61,34,115,104,111,114,116,99,117,116,32,105,99,111,110,34,32,104,54,62,60,117,\n108,62,60,108,105,62,60,97,32,104,114,101,102,61,34,32,32,60,109,101,116,97,32,\n104,116,116,112,45,101,113,117,105,118,61,34,99,115,115,34,32,109,101,100,105,97\n,61,34,115,99,114,101,101,110,34,32,114,101,115,112,111,110,115,105,98,108,101,\n32,102,111,114,32,116,104,101,32,34,32,116,121,112,101,61,34,97,112,112,108,105,\n99,97,116,105,111,110,47,34,32,115,116,121,108,101,61,34,98,97,99,107,103,114,\n111,117,110,100,45,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,\n102,45,56,34,32,97,108,108,111,119,116,114,97,110,115,112,97,114,101,110,99,121,\n61,34,115,116,121,108,101,115,104,101,101,116,34,32,116,121,112,101,61,34,116,\n101,13,10,60,109,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,62,\n60,47,115,112,97,110,62,60,115,112,97,110,32,99,108,97,115,115,61,34,48,34,32,99\n,101,108,108,115,112,97,99,105,110,103,61,34,48,34,62,59,10,60,47,115,99,114,105\n,112,116,62,10,60,115,99,114,105,112,116,32,115,111,109,101,116,105,109,101,115,\n32,99,97,108,108,101,100,32,116,104,101,100,111,101,115,32,110,111,116,32,110,\n101,99,101,115,115,97,114,105,108,121,70,111,114,32,109,111,114,101,32,105,110,\n102,111,114,109,97,116,105,111,110,97,116,32,116,104,101,32,98,101,103,105,110,\n110,105,110,103,32,111,102,32,60,33,68,79,67,84,89,80,69,32,104,116,109,108,62,\n60,104,116,109,108,112,97,114,116,105,99,117,108,97,114,108,121,32,105,110,32,\n116,104,101,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,97,109,\n101,61,34,106,97,118,97,115,99,114,105,112,116,58,118,111,105,100,40,48,41,59,34\n,101,102,102,101,99,116,105,118,101,110,101,115,115,32,111,102,32,116,104,101,32\n,97,117,116,111,99,111,109,112,108,101,116,101,61,34,111,102,102,34,32,103,101,\n110,101,114,97,108,108,121,32,99,111,110,115,105,100,101,114,101,100,62,60,105,\n110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,34,62,60,47,115,\n99,114,105,112,116,62,13,10,60,115,99,114,105,112,116,116,104,114,111,117,103,\n104,111,117,116,32,116,104,101,32,119,111,114,108,100,99,111,109,109,111,110,32,\n109,105,115,99,111,110,99,101,112,116,105,111,110,97,115,115,111,99,105,97,116,\n105,111,110,32,119,105,116,104,32,116,104,101,60,47,100,105,118,62,10,60,47,100,\n105,118,62,10,60,100,105,118,32,99,100,117,114,105,110,103,32,104,105,115,32,108\n,105,102,101,116,105,109,101,44,99,111,114,114,101,115,112,111,110,100,105,110,\n103,32,116,111,32,116,104,101,116,121,112,101,61,34,105,109,97,103,101,47,120,45\n,105,99,111,110,34,32,97,110,32,105,110,99,114,101,97,115,105,110,103,32,110,117\n,109,98,101,114,100,105,112,108,111,109,97,116,105,99,32,114,101,108,97,116,105,\n111,110,115,97,114,101,32,111,102,116,101,110,32,99,111,110,115,105,100,101,114,\n101,100,109,101,116,97,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,\n32,60,105,110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,101,120\n,97,109,112,108,101,115,32,105,110,99,108,117,100,101,32,116,104,101,34,62,60,\n105,109,103,32,115,114,99,61,34,104,116,116,112,58,47,47,105,112,97,114,116,105,\n99,105,112,97,116,105,111,110,32,105,110,32,116,104,101,116,104,101,32,101,115,\n116,97,98,108,105,115,104,109,101,110,116,32,111,102,10,60,47,100,105,118,62,10,\n60,100,105,118,32,99,108,97,115,115,61,34,38,97,109,112,59,110,98,115,112,59,38,\n97,109,112,59,110,98,115,112,59,116,111,32,100,101,116,101,114,109,105,110,101,\n32,119,104,101,116,104,101,114,113,117,105,116,101,32,100,105,102,102,101,114,\n101,110,116,32,102,114,111,109,109,97,114,107,101,100,32,116,104,101,32,98,101,\n103,105,110,110,105,110,103,100,105,115,116,97,110,99,101,32,98,101,116,119,101,\n101,110,32,116,104,101,99,111,110,116,114,105,98,117,116,105,111,110,115,32,116,\n111,32,116,104,101,99,111,110,102,108,105,99,116,32,98,101,116,119,101,101,110,\n32,116,104,101,119,105,100,101,108,121,32,99,111,110,115,105,100,101,114,101,100\n,32,116,111,119,97,115,32,111,110,101,32,111,102,32,116,104,101,32,102,105,114,\n115,116,119,105,116,104,32,118,97,114,121,105,110,103,32,100,101,103,114,101,101\n,115,104,97,118,101,32,115,112,101,99,117,108,97,116,101,100,32,116,104,97,116,\n40,100,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,112,\n97,114,116,105,99,105,112,97,116,105,110,103,32,105,110,32,116,104,101,111,114,\n105,103,105,110,97,108,108,121,32,100,101,118,101,108,111,112,101,100,101,116,97\n,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,32,116,121,112,101,\n61,34,116,101,120,116,47,99,115,115,34,32,47,62,10,105,110,116,101,114,99,104,97\n,110,103,101,97,98,108,121,32,119,105,116,104,109,111,114,101,32,99,108,111,115,\n101,108,121,32,114,101,108,97,116,101,100,115,111,99,105,97,108,32,97,110,100,32\n,112,111,108,105,116,105,99,97,108,116,104,97,116,32,119,111,117,108,100,32,111,\n116,104,101,114,119,105,115,101,112,101,114,112,101,110,100,105,99,117,108,97,\n114,32,116,111,32,116,104,101,115,116,121,108,101,32,116,121,112,101,61,34,116,\n101,120,116,47,99,115,115,116,121,112,101,61,34,115,117,98,109,105,116,34,32,110\n,97,109,101,61,34,102,97,109,105,108,105,101,115,32,114,101,115,105,100,105,110,\n103,32,105,110,100,101,118,101,108,111,112,105,110,103,32,99,111,117,110,116,114\n,105,101,115,99,111,109,112,117,116,101,114,32,112,114,111,103,114,97,109,109,\n105,110,103,101,99,111,110,111,109,105,99,32,100,101,118,101,108,111,112,109,101\n,110,116,100,101,116,101,114,109,105,110,97,116,105,111,110,32,111,102,32,116,\n104,101,102,111,114,32,109,111,114,101,32,105,110,102,111,114,109,97,116,105,111\n,110,111,110,32,115,101,118,101,114,97,108,32,111,99,99,97,115,105,111,110,115,\n112,111,114,116,117,103,117,195,170,115,32,40,69,117,114,111,112,101,117,41,208,\n163,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,209,\n131,208,186,209,128,208,176,209,151,208,189,209,129,209,140,208,186,208,176,208,\n160,208,190,209,129,209,129,208,184,208,185,209,129,208,186,208,190,208,185,208,\n188,208,176,209,130,208,181,209,128,208,184,208,176,208,187,208,190,208,178,208,\n184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,208,184,209,\n131,208,191,209,128,208,176,208,178,208,187,208,181,208,189,208,184,209,143,208,\n189,208,181,208,190,208,177,209,133,208,190,208,180,208,184,208,188,208,190,208,\n184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208,\n152,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,143,208,\n160,208,181,209,129,208,191,209,131,208,177,208,187,208,184,208,186,208,184,208,\n186,208,190,208,187,208,184,209,135,208,181,209,129,209,130,208,178,208,190,208,\n184,208,189,209,132,208,190,209,128,208,188,208,176,209,134,208,184,209,142,209,\n130,208,181,209,128,209,128,208,184,209,130,208,190,209,128,208,184,208,184,208,\n180,208,190,209,129,209,130,208,176,209,130,208,190,209,135,208,189,208,190,216,\n167,217,132,217,133,216,170,217,136,216,167,216,172,216,175,217,136,217,134,216,\n167,217,132,216,167,216,180,216,170,216,177,216,167,217,131,216,167,216,170,216,\n167,217,132,216,167,217,130,216,170,216,177,216,167,216,173,216,167,216,170,104,\n116,109,108,59,32,99,104,97,114,115,101,116,61,85,84,70,45,56,34,32,115,101,116,\n84,105,109,101,111,117,116,40,102,117,110,99,116,105,111,110,40,41,100,105,115,\n112,108,97,121,58,105,110,108,105,110,101,45,98,108,111,99,107,59,60,105,110,112\n,117,116,32,116,121,112,101,61,34,115,117,98,109,105,116,34,32,116,121,112,101,\n32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,60,105,109,103,32,\n115,114,99,61,34,104,116,116,112,58,47,47,119,119,119,46,34,32,34,104,116,116,\n112,58,47,47,119,119,119,46,119,51,46,111,114,103,47,115,104,111,114,116,99,117,\n116,32,105,99,111,110,34,32,104,114,101,102,61,34,34,32,97,117,116,111,99,111,\n109,112,108,101,116,101,61,34,111,102,102,34,32,60,47,97,62,60,47,100,105,118,62\n,60,100,105,118,32,99,108,97,115,115,61,60,47,97,62,60,47,108,105,62,10,60,108,\n105,32,99,108,97,115,115,61,34,99,115,115,34,32,116,121,112,101,61,34,116,101,\n120,116,47,99,115,115,34,32,60,102,111,114,109,32,97,99,116,105,111,110,61,34,\n104,116,116,112,58,47,47,120,116,47,99,115,115,34,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,108,105,110,107,32,114,101,108,61,34,97,108,116,101,114,110\n,97,116,101,34,32,13,10,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,\n101,120,116,47,32,111,110,99,108,105,99,107,61,34,106,97,118,97,115,99,114,105,\n112,116,58,40,110,101,119,32,68,97,116,101,41,46,103,101,116,84,105,109,101,40,\n41,125,104,101,105,103,104,116,61,34,49,34,32,119,105,100,116,104,61,34,49,34,32\n,80,101,111,112,108,101,39,115,32,82,101,112,117,98,108,105,99,32,111,102,32,32,\n60,97,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,116,101,\n120,116,45,100,101,99,111,114,97,116,105,111,110,58,117,110,100,101,114,116,104,\n101,32,98,101,103,105,110,110,105,110,103,32,111,102,32,116,104,101,32,60,47,100\n,105,118,62,10,60,47,100,105,118,62,10,60,47,100,105,118,62,10,101,115,116,97,98\n,108,105,115,104,109,101,110,116,32,111,102,32,116,104,101,32,60,47,100,105,118,\n62,60,47,100,105,118,62,60,47,100,105,118,62,60,47,100,35,118,105,101,119,112,\n111,114,116,123,109,105,110,45,104,101,105,103,104,116,58,10,60,115,99,114,105,\n112,116,32,115,114,99,61,34,104,116,116,112,58,47,47,111,112,116,105,111,110,62,\n60,111,112,116,105,111,110,32,118,97,108,117,101,61,111,102,116,101,110,32,114,\n101,102,101,114,114,101,100,32,116,111,32,97,115,32,47,111,112,116,105,111,110,\n62,10,60,111,112,116,105,111,110,32,118,97,108,117,60,33,68,79,67,84,89,80,69,32\n,104,116,109,108,62,10,60,33,45,45,91,73,110,116,101,114,110,97,116,105,111,110,\n97,108,32,65,105,114,112,111,114,116,62,10,60,97,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,119,119,119,60,47,97,62,60,97,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,119,224,184,160,224,184,178,224,184,169,224,184,178,224,185\n,132,224,184,151,224,184,162,225,131,165,225,131,144,225,131,160,225,131,151,225\n,131,163,225,131,154,225,131,152,230,173,163,233,171,148,228,184,173,230,150,135\n,32,40,231,185,129,233,171,148,41,224,164,168,224,164,191,224,164,176,224,165,\n141,224,164,166,224,165,135,224,164,182,224,164,161,224,164,190,224,164,137,224,\n164,168,224,164,178,224,165,139,224,164,161,224,164,149,224,165,141,224,164,183,\n224,165,135,224,164,164,224,165,141,224,164,176,224,164,156,224,164,190,224,164,\n168,224,164,149,224,164,190,224,164,176,224,165,128,224,164,184,224,164,130,224,\n164,172,224,164,130,224,164,167,224,164,191,224,164,164,224,164,184,224,165,141,\n224,164,165,224,164,190,224,164,170,224,164,168,224,164,190,224,164,184,224,165,\n141,224,164,181,224,165,128,224,164,149,224,164,190,224,164,176,224,164,184,224,\n164,130,224,164,184,224,165,141,224,164,149,224,164,176,224,164,163,224,164,184,\n224,164,190,224,164,174,224,164,151,224,165,141,224,164,176,224,165,128,224,164,\n154,224,164,191,224,164,159,224,165,141,224,164,160,224,165,139,224,164,130,224,\n164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164,168,\n224,164,133,224,164,174,224,165,135,224,164,176,224,164,191,224,164,149,224,164,\n190,224,164,181,224,164,191,224,164,173,224,164,191,224,164,168,224,165,141,224,\n164,168,224,164,151,224,164,190,224,164,161,224,164,191,224,164,175,224,164,190,\n224,164,129,224,164,149,224,165,141,224,164,175,224,165,139,224,164,130,224,164,\n149,224,164,191,224,164,184,224,165,129,224,164,176,224,164,149,224,165,141,224,\n164,183,224,164,190,224,164,170,224,164,185,224,165,129,224,164,129,224,164,154,\n224,164,164,224,165,128,224,164,170,224,165,141,224,164,176,224,164,172,224,164,\n130,224,164,167,224,164,168,224,164,159,224,164,191,224,164,170,224,165,141,224,\n164,170,224,164,163,224,165,128,224,164,149,224,165,141,224,164,176,224,164,191,\n224,164,149,224,165,135,224,164,159,224,164,170,224,165,141,224,164,176,224,164,\n190,224,164,176,224,164,130,224,164,173,224,164,170,224,165,141,224,164,176,224,\n164,190,224,164,170,224,165,141,224,164,164,224,164,174,224,164,190,224,164,178,\n224,164,191,224,164,149,224,165,139,224,164,130,224,164,176,224,164,171,224,164,\n188,224,165,141,224,164,164,224,164,190,224,164,176,224,164,168,224,164,191,224,\n164,176,224,165,141,224,164,174,224,164,190,224,164,163,224,164,178,224,164,191,\n224,164,174,224,164,191,224,164,159,224,165,135,224,164,161,100,101,115,99,114,\n105,112,116,105,111,110,34,32,99,111,110,116,101,110,116,61,34,100,111,99,117,\n109,101,110,116,46,108,111,99,97,116,105,111,110,46,112,114,111,116,46,103,101,\n116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,60,33,68,79\n,67,84,89,80,69,32,104,116,109,108,62,10,60,104,116,109,108,32,60,109,101,116,97\n,32,99,104,97,114,115,101,116,61,34,117,116,102,45,56,34,62,58,117,114,108,34,32\n,99,111,110,116,101,110,116,61,34,104,116,116,112,58,47,47,46,99,115,115,34,32,\n114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,115,116,121,108,101\n,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,62,116,121,112,101,61\n,34,116,101,120,116,47,99,115,115,34,32,104,114,101,102,61,34,119,51,46,111,114,\n103,47,49,57,57,57,47,120,104,116,109,108,34,32,120,109,108,116,121,112,101,61,\n34,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,34,32,109,101,116,104\n,111,100,61,34,103,101,116,34,32,97,99,116,105,111,110,61,34,108,105,110,107,32,\n114,101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,32,61,32,100,111\n,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,116,121,112,\n101,61,34,105,109,97,103,101,47,120,45,105,99,111,110,34,32,47,62,99,101,108,108\n,112,97,100,100,105,110,103,61,34,48,34,32,99,101,108,108,115,112,46,99,115,115,\n34,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34,32,60,47,97,62,60,\n47,108,105,62,60,108,105,62,60,97,32,104,114,101,102,61,34,34,32,119,105,100,116\n,104,61,34,49,34,32,104,101,105,103,104,116,61,34,49,34,34,62,60,97,32,104,114,\n101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,115,116,121,108,101,61,34,\n100,105,115,112,108,97,121,58,110,111,110,101,59,34,62,97,108,116,101,114,110,97\n,116,101,34,32,116,121,112,101,61,34,97,112,112,108,105,45,47,47,87,51,67,47,47,\n68,84,68,32,88,72,84,77,76,32,49,46,48,32,101,108,108,115,112,97,99,105,110,103,\n61,34,48,34,32,99,101,108,108,112,97,100,32,116,121,112,101,61,34,104,105,100,\n100,101,110,34,32,118,97,108,117,101,61,34,47,97,62,38,110,98,115,112,59,60,115,\n112,97,110,32,114,111,108,101,61,34,115,10,60,105,110,112,117,116,32,116,121,112\n,101,61,34,104,105,100,100,101,110,34,32,108,97,110,103,117,97,103,101,61,34,74,\n97,118,97,83,99,114,105,112,116,34,32,32,100,111,99,117,109,101,110,116,46,103,\n101,116,69,108,101,109,101,110,116,115,66,103,61,34,48,34,32,99,101,108,108,115,\n112,97,99,105,110,103,61,34,48,34,32,121,112,101,61,34,116,101,120,116,47,99,115\n,115,34,32,109,101,100,105,97,61,34,116,121,112,101,61,39,116,101,120,116,47,106\n,97,118,97,115,99,114,105,112,116,39,119,105,116,104,32,116,104,101,32,101,120,\n99,101,112,116,105,111,110,32,111,102,32,121,112,101,61,34,116,101,120,116,47,99\n,115,115,34,32,114,101,108,61,34,115,116,32,104,101,105,103,104,116,61,34,49,34,\n32,119,105,100,116,104,61,34,49,34,32,61,39,43,101,110,99,111,100,101,85,82,73,\n67,111,109,112,111,110,101,110,116,40,60,108,105,110,107,32,114,101,108,61,34,97\n,108,116,101,114,110,97,116,101,34,32,10,98,111,100,121,44,32,116,114,44,32,105,\n110,112,117,116,44,32,116,101,120,116,109,101,116,97,32,110,97,109,101,61,34,114\n,111,98,111,116,115,34,32,99,111,110,109,101,116,104,111,100,61,34,112,111,115,\n116,34,32,97,99,116,105,111,110,61,34,62,10,60,97,32,104,114,101,102,61,34,104,\n116,116,112,58,47,47,119,119,119,46,99,115,115,34,32,114,101,108,61,34,115,116,\n121,108,101,115,104,101,101,116,34,32,60,47,100,105,118,62,60,47,100,105,118,62,\n60,100,105,118,32,99,108,97,115,115,108,97,110,103,117,97,103,101,61,34,106,97,\n118,97,115,99,114,105,112,116,34,62,97,114,105,97,45,104,105,100,100,101,110,61,\n34,116,114,117,101,34,62,194,183,60,114,105,112,116,34,32,116,121,112,101,61,34,\n116,101,120,116,47,106,97,118,97,115,108,61,48,59,125,41,40,41,59,10,40,102,117,\n110,99,116,105,111,110,40,41,123,98,97,99,107,103,114,111,117,110,100,45,105,109\n,97,103,101,58,32,117,114,108,40,47,97,62,60,47,108,105,62,60,108,105,62,60,97,\n32,104,114,101,102,61,34,104,9,9,60,108,105,62,60,97,32,104,114,101,102,61,34,\n104,116,116,112,58,47,47,97,116,111,114,34,32,97,114,105,97,45,104,105,100,100,\n101,110,61,34,116,114,117,62,32,60,97,32,104,114,101,102,61,34,104,116,116,112,\n58,47,47,119,119,119,46,108,97,110,103,117,97,103,101,61,34,106,97,118,97,115,99\n,114,105,112,116,34,32,47,111,112,116,105,111,110,62,10,60,111,112,116,105,111,\n110,32,118,97,108,117,101,47,100,105,118,62,60,47,100,105,118,62,60,100,105,118,\n32,99,108,97,115,115,61,114,97,116,111,114,34,32,97,114,105,97,45,104,105,100,\n100,101,110,61,34,116,114,101,61,40,110,101,119,32,68,97,116,101,41,46,103,101,\n116,84,105,109,101,40,41,112,111,114,116,117,103,117,195,170,115,32,40,100,111,\n32,66,114,97,115,105,108,41,208,190,209,128,208,179,208,176,208,189,208,184,208,\n183,208,176,209,134,208,184,208,184,208,178,208,190,208,183,208,188,208,190,208,\n182,208,189,208,190,209,129,209,130,209,140,208,190,208,177,209,128,208,176,208,\n183,208,190,208,178,208,176,208,189,208,184,209,143,209,128,208,181,208,179,208,\n184,209,129,209,130,209,128,208,176,209,134,208,184,208,184,208,178,208,190,208,\n183,208,188,208,190,208,182,208,189,208,190,209,129,209,130,208,184,208,190,208,\n177,209,143,208,183,208,176,209,130,208,181,208,187,209,140,208,189,208,176,60,\n33,68,79,67,84,89,80,69,32,104,116,109,108,32,80,85,66,76,73,67,32,34,110,116,45\n,84,121,112,101,34,32,99,111,110,116,101,110,116,61,34,116,101,120,116,47,60,109\n,101,116,97,32,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,116,101,\n114,97,110,115,105,116,105,111,110,97,108,47,47,69,78,34,32,34,104,116,116,112,\n58,60,104,116,109,108,32,120,109,108,110,115,61,34,104,116,116,112,58,47,47,119,\n119,119,45,47,47,87,51,67,47,47,68,84,68,32,88,72,84,77,76,32,49,46,48,32,84,68,\n84,68,47,120,104,116,109,108,49,45,116,114,97,110,115,105,116,105,111,110,97,108\n,47,47,119,119,119,46,119,51,46,111,114,103,47,84,82,47,120,104,116,109,108,49,\n47,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,\n39,59,60,109,101,116,97,32,110,97,109,101,61,34,100,101,115,99,114,105,112,116,\n105,111,110,112,97,114,101,110,116,78,111,100,101,46,105,110,115,101,114,116,66,\n101,102,111,114,101,60,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,\n100,101,110,34,32,110,97,106,115,34,32,116,121,112,101,61,34,116,101,120,116,47,\n106,97,118,97,115,99,114,105,40,100,111,99,117,109,101,110,116,41,46,114,101,97,\n100,121,40,102,117,110,99,116,105,115,99,114,105,112,116,32,116,121,112,101,61,\n34,116,101,120,116,47,106,97,118,97,115,105,109,97,103,101,34,32,99,111,110,116,\n101,110,116,61,34,104,116,116,112,58,47,47,85,65,45,67,111,109,112,97,116,105,98\n,108,101,34,32,99,111,110,116,101,110,116,61,116,109,108,59,32,99,104,97,114,115\n,101,116,61,117,116,102,45,56,34,32,47,62,10,108,105,110,107,32,114,101,108,61,\n34,115,104,111,114,116,99,117,116,32,105,99,111,110,60,108,105,110,107,32,114,\n101,108,61,34,115,116,121,108,101,115,104,101,101,116,34,32,60,47,115,99,114,105\n,112,116,62,10,60,115,99,114,105,112,116,32,116,121,112,101,61,61,32,100,111,99,\n117,109,101,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,60,97,32,116\n,97,114,103,101,116,61,34,95,98,108,97,110,107,34,32,104,114,101,102,61,32,100,\n111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,105,\n110,112,117,116,32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61\n,97,46,116,121,112,101,32,61,32,39,116,101,120,116,47,106,97,118,97,115,99,114,\n105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,34,32,110,\n97,109,101,104,116,109,108,59,32,99,104,97,114,115,101,116,61,117,116,102,45,56,\n34,32,47,62,100,116,100,34,62,10,60,104,116,109,108,32,120,109,108,110,115,61,34\n,104,116,116,112,45,47,47,87,51,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,\n32,84,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,115,99,114,105,112,\n116,39,41,105,110,112,117,116,32,116,121,112,101,61,34,104,105,100,100,101,110,\n34,32,110,97,109,60,115,99,114,105,112,116,32,116,121,112,101,61,34,116,101,120,\n116,47,106,97,118,97,115,34,32,115,116,121,108,101,61,34,100,105,115,112,108,97,\n121,58,110,111,110,101,59,34,62,100,111,99,117,109,101,110,116,46,103,101,116,69\n,108,101,109,101,110,116,66,121,73,100,40,61,100,111,99,117,109,101,110,116,46,\n99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,32,116,121,112,101,61,39,\n116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,105,110,112,117,116,\n32,116,121,112,101,61,34,116,101,120,116,34,32,110,97,109,101,61,34,100,46,103,\n101,116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,115,110\n,105,99,97,108,34,32,104,114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,\n46,67,47,47,68,84,68,32,72,84,77,76,32,52,46,48,49,32,84,114,97,110,115,105,116,\n60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,115,115,34\n,62,10,10,60,115,116,121,108,101,32,116,121,112,101,61,34,116,101,120,116,47,99,\n115,115,34,62,105,111,110,97,108,46,100,116,100,34,62,10,60,104,116,109,108,32,\n120,109,108,110,115,61,104,116,116,112,45,101,113,117,105,118,61,34,67,111,110,\n116,101,110,116,45,84,121,112,101,100,105,110,103,61,34,48,34,32,99,101,108,108,\n115,112,97,99,105,110,103,61,34,48,34,104,116,109,108,59,32,99,104,97,114,115,\n101,116,61,117,116,102,45,56,34,32,47,62,10,32,115,116,121,108,101,61,34,100,105\n,115,112,108,97,121,58,110,111,110,101,59,34,62,60,60,108,105,62,60,97,32,104,\n114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,32,116,121,112,101,61,\n39,116,101,120,116,47,106,97,118,97,115,99,114,105,112,116,39,62,208,180,208,181\n,209,143,209,130,208,181,208,187,209,140,208,189,208,190,209,129,209,130,208,184\n,209,129,208,190,208,190,209,130,208,178,208,181,209,130,209,129,209,130,208,178\n,208,184,208,184,208,191,209,128,208,190,208,184,208,183,208,178,208,190,208,180\n,209,129,209,130,208,178,208,176,208,177,208,181,208,183,208,190,208,191,208,176\n,209,129,208,189,208,190,209,129,209,130,208,184,224,164,170,224,165,129,224,164\n,184,224,165,141,224,164,164,224,164,191,224,164,149,224,164,190,224,164,149,224\n,164,190,224,164,130,224,164,151,224,165,141,224,164,176,224,165,135,224,164,184\n,224,164,137,224,164,168,224,165,141,224,164,185,224,165,139,224,164,130,224,164\n,168,224,165,135,224,164,181,224,164,191,224,164,167,224,164,190,224,164,168,224\n,164,184,224,164,173,224,164,190,224,164,171,224,164,191,224,164,149,224,165,141\n,224,164,184,224,164,191,224,164,130,224,164,151,224,164,184,224,165,129,224,164\n,176,224,164,149,224,165,141,224,164,183,224,164,191,224,164,164,224,164,149,224\n,165,137,224,164,170,224,165,128,224,164,176,224,164,190,224,164,135,224,164,159\n,224,164,181,224,164,191,224,164,156,224,165,141,224,164,158,224,164,190,224,164\n,170,224,164,168,224,164,149,224,164,190,224,164,176,224,165,141,224,164,176,224\n,164,181,224,164,190,224,164,136,224,164,184,224,164,149,224,165,141,224,164,176\n,224,164,191,224,164,175,224,164,164,224,164,190\n}\n/* GENERATED CODE END */\n;\n#endif  /* !BROTLI_EXTERNAL_DICTIONARY_DATA */\n\n#if !defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\nstatic const BrotliDictionary kBrotliDictionary = {\n#else\nstatic BrotliDictionary kBrotliDictionary = {\n#endif\n  /* size_bits_by_length */\n  {\n    0, 0, 0, 0, 10, 10, 11, 11,\n    10, 10, 10, 10, 10, 9, 9, 8,\n    7, 7, 8, 7, 7, 6, 6, 5,\n    5, 0, 0, 0, 0, 0, 0, 0\n  },\n\n  /* offsets_by_length */\n  {\n    0, 0, 0, 0, 0, 4096, 9216, 21504,\n    35840, 44032, 53248, 63488, 74752, 87040, 93696, 100864,\n    104704, 106752, 108928, 113536, 115968, 118528, 119872, 121280,\n    122016, 122784, 122784, 122784, 122784, 122784, 122784, 122784\n  },\n\n  /* data_size ==  sizeof(kBrotliDictionaryData) */\n  122784,\n\n  /* data */\n#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\n  NULL\n#else\n  kBrotliDictionaryData\n#endif\n};\n\nconst BrotliDictionary* BrotliGetDictionary(void) {\n  return &kBrotliDictionary;\n}\n\nvoid BrotliSetDictionaryData(const uint8_t* data) {\n#if defined(BROTLI_EXTERNAL_DICTIONARY_DATA)\n  if (!!data && !kBrotliDictionary.data) {\n    kBrotliDictionary.data = data;\n  }\n#else\n  BROTLI_UNUSED(data);  // Appease -Werror=unused-parameter\n#endif\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/common/dictionary.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Collection of static dictionary words. */\n\n#ifndef BROTLI_COMMON_DICTIONARY_H_\n#define BROTLI_COMMON_DICTIONARY_H_\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BrotliDictionary {\n  /**\n   * Number of bits to encode index of dictionary word in a bucket.\n   *\n   * Specification: Appendix A. Static Dictionary Data\n   *\n   * Words in a dictionary are bucketed by length.\n   * @c 0 means that there are no words of a given length.\n   * Dictionary consists of words with length of [4..24] bytes.\n   * Values at [0..3] and [25..31] indices should not be addressed.\n   */\n  uint8_t size_bits_by_length[32];\n\n  /* assert(offset[i + 1] == offset[i] + (bits[i] ? (i << bits[i]) : 0)) */\n  uint32_t offsets_by_length[32];\n\n  /* assert(data_size == offsets_by_length[31]) */\n  size_t data_size;\n\n  /* Data array is not bound, and should obey to size_bits_by_length values.\n     Specified size matches default (RFC 7932) dictionary. Its size is\n     defined by data_size */\n  const uint8_t* data;\n} BrotliDictionary;\n\nBROTLI_COMMON_API const BrotliDictionary* BrotliGetDictionary(void);\n\n/**\n * Sets dictionary data.\n *\n * When dictionary data is already set / present, this method is no-op.\n *\n * Dictionary data MUST be provided before BrotliGetDictionary is invoked.\n * This method is used ONLY in multi-client environment (e.g. C + Java),\n * to reduce storage by sharing single dictionary between implementations.\n */\nBROTLI_COMMON_API void BrotliSetDictionaryData(const uint8_t* data);\n\n#define BROTLI_MIN_DICTIONARY_WORD_LENGTH 4\n#define BROTLI_MAX_DICTIONARY_WORD_LENGTH 24\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_DICTIONARY_H_ */\n"
  },
  {
    "path": "third-party/brotli/common/platform.c",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include <stdlib.h>\n\n#include <brotli/types.h>\n\n#include \"platform.h\"\n\n/* Default brotli_alloc_func */\nvoid* BrotliDefaultAllocFunc(void* opaque, size_t size) {\n  BROTLI_UNUSED(opaque);\n  return malloc(size);\n}\n\n/* Default brotli_free_func */\nvoid BrotliDefaultFreeFunc(void* opaque, void* address) {\n  BROTLI_UNUSED(opaque);\n  free(address);\n}\n"
  },
  {
    "path": "third-party/brotli/common/platform.h",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Macros for compiler / platform specific features and build options.\n\n   Build options are:\n    * BROTLI_BUILD_32_BIT disables 64-bit optimizations\n    * BROTLI_BUILD_64_BIT forces to use 64-bit optimizations\n    * BROTLI_BUILD_BIG_ENDIAN forces to use big-endian optimizations\n    * BROTLI_BUILD_ENDIAN_NEUTRAL disables endian-aware optimizations\n    * BROTLI_BUILD_LITTLE_ENDIAN forces to use little-endian optimizations\n    * BROTLI_BUILD_NO_RBIT disables \"rbit\" optimization for ARM CPUs\n    * BROTLI_BUILD_NO_UNALIGNED_READ_FAST forces off the fast-unaligned-read\n      optimizations (mainly for testing purposes)\n    * BROTLI_DEBUG dumps file name and line number when decoder detects stream\n      or memory error\n    * BROTLI_ENABLE_LOG enables asserts and dumps various state information\n    * BROTLI_ENABLE_DUMP overrides default \"dump\" behaviour\n*/\n\n#ifndef BROTLI_COMMON_PLATFORM_H_\n#define BROTLI_COMMON_PLATFORM_H_\n\n#include <string.h>  /* memcpy */\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\n#if defined(OS_LINUX) || defined(OS_CYGWIN) || defined(__EMSCRIPTEN__)\n#include <endian.h>\n#elif defined(OS_FREEBSD)\n#include <machine/endian.h>\n#elif defined(OS_MACOSX)\n#include <machine/endian.h>\n/* Let's try and follow the Linux convention */\n#define BROTLI_X_BYTE_ORDER BYTE_ORDER\n#define BROTLI_X_LITTLE_ENDIAN LITTLE_ENDIAN\n#define BROTLI_X_BIG_ENDIAN BIG_ENDIAN\n#endif\n\n#if BROTLI_MSVC_VERSION_CHECK(18, 0, 0)\n#include <intrin.h>\n#endif\n\n#if defined(BROTLI_ENABLE_LOG) || defined(BROTLI_DEBUG)\n#include <assert.h>\n#include <stdio.h>\n#endif\n\n/* The following macros were borrowed from https://github.com/nemequ/hedley\n * with permission of original author - Evan Nemerson <evan@nemerson.com> */\n\n/* >>> >>> >>> hedley macros */\n\n/* Define \"BROTLI_PREDICT_TRUE\" and \"BROTLI_PREDICT_FALSE\" macros for capable\n   compilers.\n\nTo apply compiler hint, enclose the branching condition into macros, like this:\n\n  if (BROTLI_PREDICT_TRUE(zero == 0)) {\n    // main execution path\n  } else {\n    // compiler should place this code outside of main execution path\n  }\n\nOR:\n\n  if (BROTLI_PREDICT_FALSE(something_rare_or_unexpected_happens)) {\n    // compiler should place this code outside of main execution path\n  }\n\n*/\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_expect, 3, 0, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||               \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 15, 0) ||              \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                  \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                 \\\n    BROTLI_TI_VERSION_CHECK(7, 3, 0) ||                   \\\n    BROTLI_TINYC_VERSION_CHECK(0, 9, 27)\n#define BROTLI_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))\n#define BROTLI_PREDICT_FALSE(x) (__builtin_expect(x, 0))\n#else\n#define BROTLI_PREDICT_FALSE(x) (x)\n#define BROTLI_PREDICT_TRUE(x) (x)\n#endif\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \\\n    !defined(__cplusplus)\n#define BROTLI_RESTRICT restrict\n#elif BROTLI_GNUC_VERSION_CHECK(3, 1, 0) ||                         \\\n    BROTLI_MSVC_VERSION_CHECK(14, 0, 0) ||                          \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                         \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                            \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                           \\\n    BROTLI_PGI_VERSION_CHECK(17, 10, 0) ||                          \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                             \\\n    BROTLI_IAR_VERSION_CHECK(8, 0, 0) ||                            \\\n    (BROTLI_SUNPRO_VERSION_CHECK(5, 14, 0) && defined(__cplusplus))\n#define BROTLI_RESTRICT __restrict\n#elif BROTLI_SUNPRO_VERSION_CHECK(5, 3, 0) && !defined(__cplusplus)\n#define BROTLI_RESTRICT _Restrict\n#else\n#define BROTLI_RESTRICT\n#endif\n\n#if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \\\n    (defined(__cplusplus) && (__cplusplus >= 199711L))\n#define BROTLI_MAYBE_INLINE inline\n#elif defined(__GNUC_STDC_INLINE__) || defined(__GNUC_GNU_INLINE__) || \\\n    BROTLI_ARM_VERSION_CHECK(6, 2, 0)\n#define BROTLI_MAYBE_INLINE __inline__\n#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0) || \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) || BROTLI_TI_VERSION_CHECK(8, 0, 0)\n#define BROTLI_MAYBE_INLINE __inline\n#else\n#define BROTLI_MAYBE_INLINE\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(always_inline, 4, 0, 0) ||                       \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                                    \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                                   \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                                       \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                                      \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE __attribute__((__always_inline__))\n#elif BROTLI_MSVC_VERSION_CHECK(12, 0, 0)\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE __forceinline\n#elif BROTLI_TI_VERSION_CHECK(7, 0, 0) && defined(__cplusplus)\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma(\"FUNC_ALWAYS_INLINE;\")\n#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0)\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE _Pragma(\"inline=forced\")\n#else\n#define BROTLI_INLINE BROTLI_MAYBE_INLINE\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(noinline, 4, 0, 0) ||                            \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                                    \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                                   \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                                       \\\n    BROTLI_IBM_VERSION_CHECK(10, 1, 0) ||                                      \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__))\n#define BROTLI_NOINLINE __attribute__((__noinline__))\n#elif BROTLI_MSVC_VERSION_CHECK(13, 10, 0)\n#define BROTLI_NOINLINE __declspec(noinline)\n#elif BROTLI_PGI_VERSION_CHECK(10, 2, 0)\n#define BROTLI_NOINLINE _Pragma(\"noinline\")\n#elif BROTLI_TI_VERSION_CHECK(6, 0, 0) && defined(__cplusplus)\n#define BROTLI_NOINLINE _Pragma(\"FUNC_CANNOT_INLINE;\")\n#elif BROTLI_IAR_VERSION_CHECK(8, 0, 0)\n#define BROTLI_NOINLINE _Pragma(\"inline=never\")\n#else\n#define BROTLI_NOINLINE\n#endif\n\n/* <<< <<< <<< end of hedley macros. */\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(unused, 2, 7, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE __attribute__ ((unused))\n#else\n#define BROTLI_UNUSED_FUNCTION static BROTLI_INLINE\n#endif\n\n#if BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0)\n#define BROTLI_ALIGNED(N) __attribute__((aligned(N)))\n#else\n#define BROTLI_ALIGNED(N)\n#endif\n\n#if (defined(__ARM_ARCH) && (__ARM_ARCH == 7)) || \\\n    (defined(M_ARM) && (M_ARM == 7))\n#define BROTLI_TARGET_ARMV7\n#endif  /* ARMv7 */\n\n#if (defined(__ARM_ARCH) && (__ARM_ARCH == 8)) || \\\n    defined(__aarch64__) || defined(__ARM64_ARCH_8__)\n#define BROTLI_TARGET_ARMV8_ANY\n\n#if defined(__ARM_32BIT_STATE)\n#define BROTLI_TARGET_ARMV8_32\n#elif defined(__ARM_64BIT_STATE)\n#define BROTLI_TARGET_ARMV8_64\n#endif\n\n#endif  /* ARMv8 */\n\n#if defined(__ARM_NEON__) || defined(__ARM_NEON)\n#define BROTLI_TARGET_NEON\n#endif\n\n#if defined(__i386) || defined(_M_IX86)\n#define BROTLI_TARGET_X86\n#endif\n\n#if defined(__x86_64__) || defined(_M_X64)\n#define BROTLI_TARGET_X64\n#endif\n\n#if defined(__PPC64__)\n#define BROTLI_TARGET_POWERPC64\n#endif\n\n#if defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64\n#define BROTLI_TARGET_RISCV64\n#endif\n\n#if defined(__loongarch_lp64)\n#define BROTLI_TARGET_LOONGARCH64\n#endif\n\n#if defined(BROTLI_TARGET_X64) || defined(BROTLI_TARGET_ARMV8_64) || \\\n    defined(BROTLI_TARGET_POWERPC64) || defined(BROTLI_TARGET_RISCV64) || \\\n    defined(BROTLI_TARGET_LOONGARCH64)\n#define BROTLI_TARGET_64_BITS 1\n#else\n#define BROTLI_TARGET_64_BITS 0\n#endif\n\n#if defined(BROTLI_BUILD_64_BIT)\n#define BROTLI_64_BITS 1\n#elif defined(BROTLI_BUILD_32_BIT)\n#define BROTLI_64_BITS 0\n#else\n#define BROTLI_64_BITS BROTLI_TARGET_64_BITS\n#endif\n\n#if (BROTLI_64_BITS)\n#define brotli_reg_t uint64_t\n#else\n#define brotli_reg_t uint32_t\n#endif\n\n#if defined(BROTLI_BUILD_BIG_ENDIAN)\n#define BROTLI_BIG_ENDIAN 1\n#elif defined(BROTLI_BUILD_LITTLE_ENDIAN)\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(BROTLI_BUILD_ENDIAN_NEUTRAL)\n/* Just break elif chain. */\n#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(_WIN32) || defined(BROTLI_TARGET_X64)\n/* Win32 & x64 can currently always be assumed to be little endian */\n#define BROTLI_LITTLE_ENDIAN 1\n#elif defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)\n#define BROTLI_BIG_ENDIAN 1\n#elif defined(BROTLI_X_BYTE_ORDER)\n#if BROTLI_X_BYTE_ORDER == BROTLI_X_LITTLE_ENDIAN\n#define BROTLI_LITTLE_ENDIAN 1\n#elif BROTLI_X_BYTE_ORDER == BROTLI_X_BIG_ENDIAN\n#define BROTLI_BIG_ENDIAN 1\n#endif\n#endif  /* BROTLI_X_BYTE_ORDER */\n\n#if !defined(BROTLI_LITTLE_ENDIAN)\n#define BROTLI_LITTLE_ENDIAN 0\n#endif\n\n#if !defined(BROTLI_BIG_ENDIAN)\n#define BROTLI_BIG_ENDIAN 0\n#endif\n\n#if defined(BROTLI_X_BYTE_ORDER)\n#undef BROTLI_X_BYTE_ORDER\n#undef BROTLI_X_LITTLE_ENDIAN\n#undef BROTLI_X_BIG_ENDIAN\n#endif\n\n#if defined(BROTLI_BUILD_NO_UNALIGNED_READ_FAST)\n#define BROTLI_UNALIGNED_READ_FAST (!!0)\n#elif defined(BROTLI_TARGET_X86) || defined(BROTLI_TARGET_X64) ||       \\\n    defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY) || \\\n    defined(BROTLI_TARGET_RISCV64) || defined(BROTLI_TARGET_LOONGARCH64)\n/* These targets are known to generate efficient code for unaligned reads\n * (e.g. a single instruction, not multiple 1-byte loads, shifted and or'd\n * together). */\n#define BROTLI_UNALIGNED_READ_FAST (!!1)\n#else\n#define BROTLI_UNALIGNED_READ_FAST (!!0)\n#endif\n\n/* Portable unaligned memory access: read / write values via memcpy. */\nstatic BROTLI_INLINE uint16_t BrotliUnalignedRead16(const void* p) {\n  uint16_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE uint32_t BrotliUnalignedRead32(const void* p) {\n  uint32_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE uint64_t BrotliUnalignedRead64(const void* p) {\n  uint64_t t;\n  memcpy(&t, p, sizeof t);\n  return t;\n}\nstatic BROTLI_INLINE void BrotliUnalignedWrite64(void* p, uint64_t v) {\n  memcpy(p, &v, sizeof v);\n}\n\n#if BROTLI_LITTLE_ENDIAN\n/* Straight endianness. Just read / write values. */\n#define BROTLI_UNALIGNED_LOAD16LE BrotliUnalignedRead16\n#define BROTLI_UNALIGNED_LOAD32LE BrotliUnalignedRead32\n#define BROTLI_UNALIGNED_LOAD64LE BrotliUnalignedRead64\n#define BROTLI_UNALIGNED_STORE64LE BrotliUnalignedWrite64\n#elif BROTLI_BIG_ENDIAN  /* BROTLI_LITTLE_ENDIAN */\n/* Explain compiler to byte-swap values. */\n#define BROTLI_BSWAP16_(V) ((uint16_t)( \\\n  (((V) & 0xFFU) << 8) | \\\n  (((V) >> 8) & 0xFFU)))\nstatic BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {\n  uint16_t value = BrotliUnalignedRead16(p);\n  return BROTLI_BSWAP16_(value);\n}\n#define BROTLI_BSWAP32_(V) ( \\\n  (((V) & 0xFFU) << 24) | (((V) & 0xFF00U) << 8) | \\\n  (((V) >> 8) & 0xFF00U) | (((V) >> 24) & 0xFFU))\nstatic BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {\n  uint32_t value = BrotliUnalignedRead32(p);\n  return BROTLI_BSWAP32_(value);\n}\n#define BROTLI_BSWAP64_(V) ( \\\n  (((V) & 0xFFU) << 56) | (((V) & 0xFF00U) << 40) | \\\n  (((V) & 0xFF0000U) << 24) | (((V) & 0xFF000000U) << 8) | \\\n  (((V) >> 8) & 0xFF000000U) | (((V) >> 24) & 0xFF0000U) | \\\n  (((V) >> 40) & 0xFF00U) | (((V) >> 56) & 0xFFU))\nstatic BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) {\n  uint64_t value = BrotliUnalignedRead64(p);\n  return BROTLI_BSWAP64_(value);\n}\nstatic BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {\n  uint64_t value = BROTLI_BSWAP64_(v);\n  BrotliUnalignedWrite64(p, value);\n}\n#else  /* BROTLI_LITTLE_ENDIAN */\n/* Read / store values byte-wise; hopefully compiler will understand. */\nstatic BROTLI_INLINE uint16_t BROTLI_UNALIGNED_LOAD16LE(const void* p) {\n  const uint8_t* in = (const uint8_t*)p;\n  return (uint16_t)(in[0] | (in[1] << 8));\n}\nstatic BROTLI_INLINE uint32_t BROTLI_UNALIGNED_LOAD32LE(const void* p) {\n  const uint8_t* in = (const uint8_t*)p;\n  uint32_t value = (uint32_t)(in[0]);\n  value |= (uint32_t)(in[1]) << 8;\n  value |= (uint32_t)(in[2]) << 16;\n  value |= (uint32_t)(in[3]) << 24;\n  return value;\n}\nstatic BROTLI_INLINE uint64_t BROTLI_UNALIGNED_LOAD64LE(const void* p) {\n  const uint8_t* in = (const uint8_t*)p;\n  uint64_t value = (uint64_t)(in[0]);\n  value |= (uint64_t)(in[1]) << 8;\n  value |= (uint64_t)(in[2]) << 16;\n  value |= (uint64_t)(in[3]) << 24;\n  value |= (uint64_t)(in[4]) << 32;\n  value |= (uint64_t)(in[5]) << 40;\n  value |= (uint64_t)(in[6]) << 48;\n  value |= (uint64_t)(in[7]) << 56;\n  return value;\n}\nstatic BROTLI_INLINE void BROTLI_UNALIGNED_STORE64LE(void* p, uint64_t v) {\n  uint8_t* out = (uint8_t*)p;\n  out[0] = (uint8_t)v;\n  out[1] = (uint8_t)(v >> 8);\n  out[2] = (uint8_t)(v >> 16);\n  out[3] = (uint8_t)(v >> 24);\n  out[4] = (uint8_t)(v >> 32);\n  out[5] = (uint8_t)(v >> 40);\n  out[6] = (uint8_t)(v >> 48);\n  out[7] = (uint8_t)(v >> 56);\n}\n#endif  /* BROTLI_LITTLE_ENDIAN */\n\nstatic BROTLI_INLINE void* BROTLI_UNALIGNED_LOAD_PTR(const void* p) {\n  void* v;\n  memcpy(&v, p, sizeof(void*));\n  return v;\n}\n\nstatic BROTLI_INLINE void BROTLI_UNALIGNED_STORE_PTR(void* p, const void* v) {\n  memcpy(p, &v, sizeof(void*));\n}\n\n/* BROTLI_IS_CONSTANT macros returns true for compile-time constants. */\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_constant_p, 3, 0, 1) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_IS_CONSTANT(x) (!!__builtin_constant_p(x))\n#else\n#define BROTLI_IS_CONSTANT(x) (!!0)\n#endif\n\n#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)\n#define BROTLI_HAS_UBFX (!!1)\n#else\n#define BROTLI_HAS_UBFX (!!0)\n#endif\n\n#if defined(BROTLI_ENABLE_LOG)\n#define BROTLI_LOG(x) printf x\n#else\n#define BROTLI_LOG(x)\n#endif\n\n#if defined(BROTLI_DEBUG) || defined(BROTLI_ENABLE_LOG)\n#define BROTLI_ENABLE_DUMP_DEFAULT 1\n#define BROTLI_DCHECK(x) assert(x)\n#else\n#define BROTLI_ENABLE_DUMP_DEFAULT 0\n#define BROTLI_DCHECK(x)\n#endif\n\n#if !defined(BROTLI_ENABLE_DUMP)\n#define BROTLI_ENABLE_DUMP BROTLI_ENABLE_DUMP_DEFAULT\n#endif\n\n#if BROTLI_ENABLE_DUMP\nstatic BROTLI_INLINE void BrotliDump(const char* f, int l, const char* fn) {\n  fprintf(stderr, \"%s:%d (%s)\\n\", f, l, fn);\n  fflush(stderr);\n}\n#define BROTLI_DUMP() BrotliDump(__FILE__, __LINE__, __FUNCTION__)\n#else\n#define BROTLI_DUMP() (void)(0)\n#endif\n\n/* BrotliRBit assumes brotli_reg_t fits native CPU register type. */\n#if (BROTLI_64_BITS == BROTLI_TARGET_64_BITS)\n/* TODO(eustas): add appropriate icc/sunpro/arm/ibm/ti checks. */\n#if (BROTLI_GNUC_VERSION_CHECK(3, 0, 0) || defined(__llvm__)) && \\\n    !defined(BROTLI_BUILD_NO_RBIT)\n#if defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_ANY)\n/* TODO(eustas): detect ARMv6T2 and enable this code for it. */\nstatic BROTLI_INLINE brotli_reg_t BrotliRBit(brotli_reg_t input) {\n  brotli_reg_t output;\n  __asm__(\"rbit %0, %1\\n\" : \"=r\"(output) : \"r\"(input));\n  return output;\n}\n#define BROTLI_RBIT(x) BrotliRBit(x)\n#endif  /* armv7 / armv8 */\n#endif  /* gcc || clang */\n#endif  /* brotli_reg_t is native */\n#if !defined(BROTLI_RBIT)\nstatic BROTLI_INLINE void BrotliRBit(void) { /* Should break build if used. */ }\n#endif  /* BROTLI_RBIT */\n\n#define BROTLI_REPEAT_4(X) {X; X; X; X;}\n#define BROTLI_REPEAT_5(X) {X; X; X; X; X;}\n#define BROTLI_REPEAT_6(X) {X; X; X; X; X; X;}\n\n#define BROTLI_UNUSED(X) (void)(X)\n\n#define BROTLI_MIN_MAX(T)                                                      \\\n  static BROTLI_INLINE T brotli_min_ ## T (T a, T b) { return a < b ? a : b; } \\\n  static BROTLI_INLINE T brotli_max_ ## T (T a, T b) { return a > b ? a : b; }\nBROTLI_MIN_MAX(double) BROTLI_MIN_MAX(float) BROTLI_MIN_MAX(int)\nBROTLI_MIN_MAX(size_t) BROTLI_MIN_MAX(uint32_t) BROTLI_MIN_MAX(uint8_t)\n#undef BROTLI_MIN_MAX\n#define BROTLI_MIN(T, A, B) (brotli_min_ ## T((A), (B)))\n#define BROTLI_MAX(T, A, B) (brotli_max_ ## T((A), (B)))\n\n#define BROTLI_SWAP(T, A, I, J) { \\\n  T __brotli_swap_tmp = (A)[(I)]; \\\n  (A)[(I)] = (A)[(J)];            \\\n  (A)[(J)] = __brotli_swap_tmp;   \\\n}\n\n#if BROTLI_64_BITS\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_ctzll, 3, 4, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_TZCNT64 __builtin_ctzll\n#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)\n#if defined(BROTLI_TARGET_X64)\n#define BROTLI_TZCNT64 _tzcnt_u64\n#else /* BROTLI_TARGET_X64 */\nstatic BROTLI_INLINE uint32_t BrotliBsf64Msvc(uint64_t x) {\n  uint32_t lsb;\n  _BitScanForward64(&lsb, x);\n  return lsb;\n}\n#define BROTLI_TZCNT64 BrotliBsf64Msvc\n#endif /* BROTLI_TARGET_X64 */\n#endif /* __builtin_ctzll */\n#endif /* BROTLI_64_BITS */\n\n#if BROTLI_GNUC_HAS_BUILTIN(__builtin_clz, 3, 4, 0) || \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0)\n#define BROTLI_BSR32(x) (31u ^ (uint32_t)__builtin_clz(x))\n#elif BROTLI_MSVC_VERSION_CHECK(18, 0, 0)\nstatic BROTLI_INLINE uint32_t BrotliBsr32Msvc(uint32_t x) {\n  unsigned long msb;\n  _BitScanReverse(&msb, x);\n  return (uint32_t)msb;\n}\n#define BROTLI_BSR32 BrotliBsr32Msvc\n#endif /* __builtin_clz */\n\n/* Default brotli_alloc_func */\nBROTLI_COMMON_API void* BrotliDefaultAllocFunc(void* opaque, size_t size);\n\n/* Default brotli_free_func */\nBROTLI_COMMON_API void BrotliDefaultFreeFunc(void* opaque, void* address);\n\nBROTLI_UNUSED_FUNCTION void BrotliSuppressUnusedFunctions(void) {\n  BROTLI_UNUSED(&BrotliSuppressUnusedFunctions);\n  BROTLI_UNUSED(&BrotliUnalignedRead16);\n  BROTLI_UNUSED(&BrotliUnalignedRead32);\n  BROTLI_UNUSED(&BrotliUnalignedRead64);\n  BROTLI_UNUSED(&BrotliUnalignedWrite64);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD16LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD32LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD64LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE64LE);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_LOAD_PTR);\n  BROTLI_UNUSED(&BROTLI_UNALIGNED_STORE_PTR);\n  BROTLI_UNUSED(&BrotliRBit);\n  BROTLI_UNUSED(&brotli_min_double);\n  BROTLI_UNUSED(&brotli_max_double);\n  BROTLI_UNUSED(&brotli_min_float);\n  BROTLI_UNUSED(&brotli_max_float);\n  BROTLI_UNUSED(&brotli_min_int);\n  BROTLI_UNUSED(&brotli_max_int);\n  BROTLI_UNUSED(&brotli_min_size_t);\n  BROTLI_UNUSED(&brotli_max_size_t);\n  BROTLI_UNUSED(&brotli_min_uint32_t);\n  BROTLI_UNUSED(&brotli_max_uint32_t);\n  BROTLI_UNUSED(&brotli_min_uint8_t);\n  BROTLI_UNUSED(&brotli_max_uint8_t);\n  BROTLI_UNUSED(&BrotliDefaultAllocFunc);\n  BROTLI_UNUSED(&BrotliDefaultFreeFunc);\n#if BROTLI_ENABLE_DUMP\n  BROTLI_UNUSED(&BrotliDump);\n#endif\n}\n\n#endif  /* BROTLI_COMMON_PLATFORM_H_ */\n"
  },
  {
    "path": "third-party/brotli/common/shared_dictionary.c",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Shared Dictionary definition and utilities. */\n\n#include <brotli/shared_dictionary.h>\n\n#include <memory.h>\n#include <stdlib.h>  /* malloc, free */\n#include <stdio.h>\n\n#include \"dictionary.h\"\n#include \"platform.h\"\n#include \"shared_dictionary_internal.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if defined(BROTLI_EXPERIMENTAL)\n\n#define BROTLI_NUM_ENCODED_LENGTHS (SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH \\\n    - SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH + 1)\n\n/* Max allowed by spec */\n#define BROTLI_MAX_SIZE_BITS 15u\n\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadBool(const uint8_t* encoded, size_t size, size_t* pos,\n    BROTLI_BOOL* result) {\n  uint8_t value;\n  size_t position = *pos;\n  if (position >= size) return BROTLI_FALSE;  /* past file end */\n  value = encoded[position++];\n  if (value > 1) return BROTLI_FALSE;  /* invalid bool */\n  *result = TO_BROTLI_BOOL(value);\n  *pos = position;\n  return BROTLI_TRUE;  /* success */\n}\n\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadUint8(const uint8_t* encoded, size_t size, size_t* pos,\n    uint8_t* result) {\n  size_t position = *pos;\n  if (position + sizeof(uint8_t) > size) return BROTLI_FALSE;\n  *result = encoded[position++];\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadUint16(const uint8_t* encoded, size_t size, size_t* pos,\n    uint16_t* result) {\n  size_t position = *pos;\n  if (position + sizeof(uint16_t) > size) return BROTLI_FALSE;\n  *result = BROTLI_UNALIGNED_LOAD16LE(&encoded[position]);\n  position += 2;\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\n/* Reads a varint into a uint32_t, and returns error if it's too large */\n/* Returns BROTLI_TRUE on success, BROTLI_FALSE on failure. */\nstatic BROTLI_BOOL ReadVarint32(const uint8_t* encoded, size_t size,\n    size_t* pos, uint32_t* result) {\n  int num = 0;\n  uint8_t byte;\n  *result = 0;\n  for (;;) {\n    if (*pos >= size) return BROTLI_FALSE;\n    byte = encoded[(*pos)++];\n    if (num == 4 && byte > 15) return BROTLI_FALSE;\n    *result |= (uint32_t)(byte & 127) << (num * 7);\n    if (byte < 128) return BROTLI_TRUE;\n    num++;\n  }\n}\n\n/* Returns the total length of word list. */\nstatic size_t BrotliSizeBitsToOffsets(const uint8_t* size_bits_by_length,\n    uint32_t* offsets_by_length) {\n  uint32_t pos = 0;\n  uint32_t i;\n  for (i = 0; i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {\n    offsets_by_length[i] = pos;\n    if (size_bits_by_length[i] != 0) {\n      pos += i << size_bits_by_length[i];\n    }\n  }\n  return pos;\n}\n\nstatic BROTLI_BOOL ParseWordList(size_t size, const uint8_t* encoded,\n    size_t* pos, BrotliDictionary* out) {\n  size_t offset;\n  size_t i;\n  size_t position = *pos;\n  if (position + BROTLI_NUM_ENCODED_LENGTHS > size) {\n    return BROTLI_FALSE;\n  }\n\n  memset(out->size_bits_by_length, 0, SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH);\n  memcpy(out->size_bits_by_length + SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH,\n      &encoded[position], BROTLI_NUM_ENCODED_LENGTHS);\n  for (i = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;\n      i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; i++) {\n    if (out->size_bits_by_length[i] > BROTLI_MAX_SIZE_BITS) {\n      return BROTLI_FALSE;\n    }\n  }\n  position += BROTLI_NUM_ENCODED_LENGTHS;\n  offset = BrotliSizeBitsToOffsets(\n      out->size_bits_by_length, out->offsets_by_length);\n\n  out->data = &encoded[position];\n  out->data_size = offset;\n  position += offset;\n  if (position > size) return BROTLI_FALSE;\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\n/* Computes the cutOffTransforms of a BrotliTransforms which already has the\n   transforms data correctly filled in. */\nstatic void ComputeCutoffTransforms(BrotliTransforms* transforms) {\n  uint32_t i;\n  for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {\n    transforms->cutOffTransforms[i] = -1;\n  }\n  for (i = 0; i < transforms->num_transforms; i++) {\n    const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, i);\n    uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, i);\n    const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, i);\n    if (type <= BROTLI_TRANSFORM_OMIT_LAST_9 && *prefix == 0 && *suffix == 0 &&\n        transforms->cutOffTransforms[type] == -1) {\n      transforms->cutOffTransforms[type] = (int16_t)i;\n    }\n  }\n}\n\nstatic BROTLI_BOOL ParsePrefixSuffixTable(size_t size, const uint8_t* encoded,\n    size_t* pos, BrotliTransforms* out, uint16_t* out_table,\n    size_t* out_table_size) {\n  size_t position = *pos;\n  size_t offset = 0;\n  size_t stringlet_count = 0;  /* NUM_PREFIX_SUFFIX */\n  size_t data_length = 0;\n\n  /* PREFIX_SUFFIX_LENGTH */\n  if (!ReadUint16(encoded, size, &position, &out->prefix_suffix_size)) {\n    return BROTLI_FALSE;\n  }\n  data_length = out->prefix_suffix_size;\n\n  /* Must at least have space for null terminator. */\n  if (data_length < 1) return BROTLI_FALSE;\n  out->prefix_suffix = &encoded[position];\n  if (position + data_length >= size) return BROTLI_FALSE;\n  while (BROTLI_TRUE) {\n    /* STRING_LENGTH */\n    size_t stringlet_len = encoded[position + offset];\n    out_table[stringlet_count] = (uint16_t)offset;\n    stringlet_count++;\n    offset++;\n    if (stringlet_len == 0) {\n      if (offset == data_length) {\n        break;\n      } else {\n        return BROTLI_FALSE;\n      }\n    }\n    if (stringlet_count > 255) return BROTLI_FALSE;\n    offset += stringlet_len;\n    if (offset >= data_length) return BROTLI_FALSE;\n  }\n\n  position += data_length;\n  *pos = position;\n  *out_table_size = (uint16_t)stringlet_count;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL ParseTransformsList(size_t size, const uint8_t* encoded,\n    size_t* pos, BrotliTransforms* out, uint16_t* prefix_suffix_table,\n    size_t* prefix_suffix_count) {\n  uint32_t i;\n  BROTLI_BOOL has_params = BROTLI_FALSE;\n  BROTLI_BOOL prefix_suffix_ok = BROTLI_FALSE;\n  size_t position = *pos;\n  size_t stringlet_cnt = 0;\n  if (position >= size) return BROTLI_FALSE;\n\n  prefix_suffix_ok = ParsePrefixSuffixTable(\n      size, encoded, &position, out, prefix_suffix_table, &stringlet_cnt);\n  if (!prefix_suffix_ok) return BROTLI_FALSE;\n  out->prefix_suffix_map = prefix_suffix_table;\n  *prefix_suffix_count = stringlet_cnt;\n\n  out->num_transforms = encoded[position++];\n  out->transforms = &encoded[position];\n  position += (size_t)out->num_transforms * 3;\n  if (position > size) return BROTLI_FALSE;\n  /* Check for errors and read extra parameters. */\n  for (i = 0; i < out->num_transforms; i++) {\n    uint8_t prefix_id = BROTLI_TRANSFORM_PREFIX_ID(out, i);\n    uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);\n    uint8_t suffix_id = BROTLI_TRANSFORM_SUFFIX_ID(out, i);\n    if (prefix_id >= stringlet_cnt) return BROTLI_FALSE;\n    if (type >= BROTLI_NUM_TRANSFORM_TYPES) return BROTLI_FALSE;\n    if (suffix_id >= stringlet_cnt) return BROTLI_FALSE;\n    if (type == BROTLI_TRANSFORM_SHIFT_FIRST ||\n        type == BROTLI_TRANSFORM_SHIFT_ALL) {\n      has_params = BROTLI_TRUE;\n    }\n  }\n  if (has_params) {\n    out->params = &encoded[position];\n    position += (size_t)out->num_transforms * 2;\n    if (position > size) return BROTLI_FALSE;\n    for (i = 0; i < out->num_transforms; i++) {\n      uint8_t type = BROTLI_TRANSFORM_TYPE(out, i);\n      if (type != BROTLI_TRANSFORM_SHIFT_FIRST &&\n          type != BROTLI_TRANSFORM_SHIFT_ALL) {\n        if (out->params[i * 2] != 0 || out->params[i * 2 + 1] != 0) {\n          return BROTLI_FALSE;\n        }\n      }\n    }\n  } else {\n    out->params = NULL;\n  }\n  ComputeCutoffTransforms(out);\n  *pos = position;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL DryParseDictionary(const uint8_t* encoded,\n    size_t size, uint32_t* num_prefix, BROTLI_BOOL* is_custom_static_dict) {\n  size_t pos = 0;\n  uint32_t chunk_size = 0;\n  uint8_t num_word_lists;\n  uint8_t num_transform_lists;\n  *is_custom_static_dict = BROTLI_FALSE;\n  *num_prefix = 0;\n\n  /* Skip magic header bytes. */\n  pos += 2;\n\n  /* LZ77_DICTIONARY_LENGTH */\n  if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;\n  if (chunk_size != 0) {\n    /* This limitation is not specified but the 32-bit Brotli decoder for now */\n    if (chunk_size > 1073741823) return BROTLI_FALSE;\n    *num_prefix = 1;\n    if (pos + chunk_size > size) return BROTLI_FALSE;\n    pos += chunk_size;\n  }\n\n  if (!ReadUint8(encoded, size, &pos, &num_word_lists)) {\n    return BROTLI_FALSE;\n  }\n  if (!ReadUint8(encoded, size, &pos, &num_transform_lists)) {\n    return BROTLI_FALSE;\n  }\n\n  if (num_word_lists > 0 || num_transform_lists > 0) {\n    *is_custom_static_dict = BROTLI_TRUE;\n  }\n\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL ParseDictionary(const uint8_t* encoded, size_t size,\n    BrotliSharedDictionary* dict) {\n  uint32_t i;\n  size_t pos = 0;\n  uint32_t chunk_size = 0;\n  size_t total_prefix_suffix_count = 0;\n  size_t trasform_list_start[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n  uint16_t temporary_prefix_suffix_table[256];\n\n  /* Skip magic header bytes. */\n  pos += 2;\n\n  /* LZ77_DICTIONARY_LENGTH */\n  if (!ReadVarint32(encoded, size, &pos, &chunk_size)) return BROTLI_FALSE;\n  if (chunk_size != 0) {\n    if (pos + chunk_size > size) return BROTLI_FALSE;\n    dict->prefix_size[dict->num_prefix] = chunk_size;\n    dict->prefix[dict->num_prefix] = &encoded[pos];\n    dict->num_prefix++;\n    /* LZ77_DICTIONARY_LENGTH bytes. */\n    pos += chunk_size;\n  }\n\n  /* NUM_WORD_LISTS */\n  if (!ReadUint8(encoded, size, &pos, &dict->num_word_lists)) {\n    return BROTLI_FALSE;\n  }\n  if (dict->num_word_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {\n    return BROTLI_FALSE;\n  }\n\n  if (dict->num_word_lists != 0) {\n    dict->words_instances = (BrotliDictionary*)dict->alloc_func(\n        dict->memory_manager_opaque,\n        dict->num_word_lists * sizeof(*dict->words_instances));\n    if (!dict->words_instances) return BROTLI_FALSE;  /* OOM */\n  }\n  for (i = 0; i < dict->num_word_lists; i++) {\n    if (!ParseWordList(size, encoded, &pos, &dict->words_instances[i])) {\n      return BROTLI_FALSE;\n    }\n  }\n\n  /* NUM_TRANSFORM_LISTS */\n  if (!ReadUint8(encoded, size, &pos, &dict->num_transform_lists)) {\n    return BROTLI_FALSE;\n  }\n  if (dict->num_transform_lists > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {\n    return BROTLI_FALSE;\n  }\n\n  if (dict->num_transform_lists != 0) {\n    dict->transforms_instances = (BrotliTransforms*)dict->alloc_func(\n        dict->memory_manager_opaque,\n        dict->num_transform_lists * sizeof(*dict->transforms_instances));\n    if (!dict->transforms_instances) return BROTLI_FALSE;  /* OOM */\n  }\n  for (i = 0; i < dict->num_transform_lists; i++) {\n    BROTLI_BOOL ok = BROTLI_FALSE;\n    size_t prefix_suffix_count = 0;\n    trasform_list_start[i] = pos;\n    dict->transforms_instances[i].prefix_suffix_map =\n        temporary_prefix_suffix_table;\n    ok = ParseTransformsList(\n        size, encoded, &pos, &dict->transforms_instances[i],\n        temporary_prefix_suffix_table, &prefix_suffix_count);\n    if (!ok) return BROTLI_FALSE;\n    total_prefix_suffix_count += prefix_suffix_count;\n  }\n  if (total_prefix_suffix_count != 0) {\n    dict->prefix_suffix_maps = (uint16_t*)dict->alloc_func(\n        dict->memory_manager_opaque,\n        total_prefix_suffix_count * sizeof(*dict->prefix_suffix_maps));\n    if (!dict->prefix_suffix_maps) return BROTLI_FALSE;  /* OOM */\n  }\n  total_prefix_suffix_count = 0;\n  for (i = 0; i < dict->num_transform_lists; i++) {\n    size_t prefix_suffix_count = 0;\n    size_t position = trasform_list_start[i];\n    uint16_t* prefix_suffix_map =\n      &dict->prefix_suffix_maps[total_prefix_suffix_count];\n    BROTLI_BOOL ok = ParsePrefixSuffixTable(\n        size, encoded, &position, &dict->transforms_instances[i],\n        prefix_suffix_map, &prefix_suffix_count);\n    if (!ok) return BROTLI_FALSE;\n    dict->transforms_instances[i].prefix_suffix_map = prefix_suffix_map;\n    total_prefix_suffix_count += prefix_suffix_count;\n  }\n\n  if (dict->num_word_lists != 0 || dict->num_transform_lists != 0) {\n    if (!ReadUint8(encoded, size, &pos, &dict->num_dictionaries)) {\n      return BROTLI_FALSE;\n    }\n    if (dict->num_dictionaries == 0 ||\n        dict->num_dictionaries > SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS) {\n      return BROTLI_FALSE;\n    }\n    for (i = 0; i < dict->num_dictionaries; i++) {\n      uint8_t words_index;\n      uint8_t transforms_index;\n      if (!ReadUint8(encoded, size, &pos, &words_index)) {\n        return BROTLI_FALSE;\n      }\n      if (words_index > dict->num_word_lists) return BROTLI_FALSE;\n      if (!ReadUint8(encoded, size, &pos, &transforms_index)) {\n        return BROTLI_FALSE;\n      }\n      if (transforms_index > dict->num_transform_lists) return BROTLI_FALSE;\n      dict->words[i] = words_index == dict->num_word_lists ?\n          BrotliGetDictionary() : &dict->words_instances[words_index];\n      dict->transforms[i] = transforms_index == dict->num_transform_lists ?\n          BrotliGetTransforms(): &dict->transforms_instances[transforms_index];\n    }\n    /* CONTEXT_ENABLED */\n    if (!ReadBool(encoded, size, &pos, &dict->context_based)) {\n      return BROTLI_FALSE;\n    }\n\n    /* CONTEXT_MAP */\n    if (dict->context_based) {\n      for (i = 0; i < SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS; i++) {\n        if (!ReadUint8(encoded, size, &pos, &dict->context_map[i])) {\n          return BROTLI_FALSE;\n        }\n        if (dict->context_map[i] >= dict->num_dictionaries) {\n          return BROTLI_FALSE;\n        }\n      }\n    }\n  } else {\n    dict->context_based = BROTLI_FALSE;\n    dict->num_dictionaries = 1;\n    dict->words[0] = BrotliGetDictionary();\n    dict->transforms[0] = BrotliGetTransforms();\n  }\n\n  return BROTLI_TRUE;\n}\n\n/* Decodes shared dictionary and verifies correctness.\n   Returns BROTLI_TRUE if dictionary is valid, BROTLI_FALSE otherwise.\n   The BrotliSharedDictionary must already have been initialized. If the\n   BrotliSharedDictionary already contains data, compound dictionaries\n   will be appended, but an error will be returned if it already has\n   custom words or transforms.\n   TODO(lode): link to RFC for shared brotli once published. */\nstatic BROTLI_BOOL DecodeSharedDictionary(\n    const uint8_t* encoded, size_t size, BrotliSharedDictionary* dict) {\n  uint32_t num_prefix = 0;\n  BROTLI_BOOL is_custom_static_dict = BROTLI_FALSE;\n  BROTLI_BOOL has_custom_static_dict =\n      dict->num_word_lists > 0 || dict->num_transform_lists > 0;\n\n  /* Check magic header bytes. */\n  if (size < 2) return BROTLI_FALSE;\n  if (encoded[0] != 0x91 || encoded[1] != 0) return BROTLI_FALSE;\n\n  if (!DryParseDictionary(encoded, size, &num_prefix, &is_custom_static_dict)) {\n    return BROTLI_FALSE;\n  }\n\n  if (num_prefix + dict->num_prefix > SHARED_BROTLI_MAX_COMPOUND_DICTS) {\n    return BROTLI_FALSE;\n  }\n\n  /* Cannot combine different static dictionaries, only prefix dictionaries */\n  if (has_custom_static_dict && is_custom_static_dict) return BROTLI_FALSE;\n\n  return ParseDictionary(encoded, size, dict);\n}\n\n#endif  /* BROTLI_EXPERIMENTAL */\n\nvoid BrotliSharedDictionaryDestroyInstance(\n    BrotliSharedDictionary* dict) {\n  if (!dict) {\n    return;\n  } else {\n    brotli_free_func free_func = dict->free_func;\n    void* opaque = dict->memory_manager_opaque;\n    /* Cleanup. */\n    free_func(opaque, dict->words_instances);\n    free_func(opaque, dict->transforms_instances);\n    free_func(opaque, dict->prefix_suffix_maps);\n    /* Self-destruction. */\n    free_func(opaque, dict);\n  }\n}\n\nBROTLI_BOOL BrotliSharedDictionaryAttach(\n    BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {\n  if (!dict) {\n    return BROTLI_FALSE;\n  }\n#if defined(BROTLI_EXPERIMENTAL)\n  if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {\n    return DecodeSharedDictionary(data, data_size, dict);\n  }\n#endif  /* BROTLI_EXPERIMENTAL */\n  if (type == BROTLI_SHARED_DICTIONARY_RAW) {\n    if (dict->num_prefix >= SHARED_BROTLI_MAX_COMPOUND_DICTS) {\n      return BROTLI_FALSE;\n    }\n    dict->prefix_size[dict->num_prefix] = data_size;\n    dict->prefix[dict->num_prefix] = data;\n    dict->num_prefix++;\n    return BROTLI_TRUE;\n  }\n  return BROTLI_FALSE;\n}\n\nBrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BrotliSharedDictionary* dict = 0;\n  if (!alloc_func && !free_func) {\n    dict = (BrotliSharedDictionary*)malloc(sizeof(BrotliSharedDictionary));\n  } else if (alloc_func && free_func) {\n    dict = (BrotliSharedDictionary*)alloc_func(\n        opaque, sizeof(BrotliSharedDictionary));\n  }\n  if (dict == 0) {\n    return 0;\n  }\n\n  /* TODO(eustas): explicitly initialize all the fields? */\n  memset(dict, 0, sizeof(BrotliSharedDictionary));\n\n  dict->context_based = BROTLI_FALSE;\n  dict->num_dictionaries = 1;\n  dict->num_word_lists = 0;\n  dict->num_transform_lists = 0;\n\n  dict->words[0] = BrotliGetDictionary();\n  dict->transforms[0] = BrotliGetTransforms();\n\n  dict->alloc_func = alloc_func ? alloc_func : BrotliDefaultAllocFunc;\n  dict->free_func = free_func ? free_func : BrotliDefaultFreeFunc;\n  dict->memory_manager_opaque = opaque;\n\n  return dict;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/common/shared_dictionary_internal.h",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* (Transparent) Shared Dictionary definition. */\n\n#ifndef BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_\n#define BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_\n\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#include \"dictionary.h\"\n#include \"transform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstruct BrotliSharedDictionaryStruct {\n  /* LZ77 prefixes (compound dictionary). */\n  uint32_t num_prefix;  /* max SHARED_BROTLI_MAX_COMPOUND_DICTS */\n  size_t prefix_size[SHARED_BROTLI_MAX_COMPOUND_DICTS];\n  const uint8_t* prefix[SHARED_BROTLI_MAX_COMPOUND_DICTS];\n\n  /* If set, the context map is used to select word and transform list from 64\n     contexts, if not set, the context map is not used and only words[0] and\n     transforms[0] are to be used. */\n  BROTLI_BOOL context_based;\n\n  uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* Amount of word_list+transform_list combinations. */\n  uint8_t num_dictionaries;\n\n  /* Must use num_dictionaries values. */\n  const BrotliDictionary* words[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* Must use num_dictionaries values. */\n  const BrotliTransforms* transforms[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* Amount of custom word lists. May be 0 if only Brotli's built-in is used */\n  uint8_t num_word_lists;\n\n  /* Contents of the custom words lists. Must be NULL if num_word_lists is 0. */\n  BrotliDictionary* words_instances;\n\n  /* Amount of custom transform lists. May be 0 if only Brotli's built-in is\n     used */\n  uint8_t num_transform_lists;\n\n  /* Contents of the custom transform lists. Must be NULL if num_transform_lists\n     is 0. */\n  BrotliTransforms* transforms_instances;\n\n  /* Concatenated prefix_suffix_maps of the custom transform lists. Must be NULL\n     if num_transform_lists is 0. */\n  uint16_t* prefix_suffix_maps;\n\n  /* Memory management */\n  brotli_alloc_func alloc_func;\n  brotli_free_func free_func;\n  void* memory_manager_opaque;\n};\n\ntypedef struct BrotliSharedDictionaryStruct BrotliSharedDictionaryInternal;\n#define BrotliSharedDictionary BrotliSharedDictionaryInternal\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_SHARED_DICTIONARY_INTERNAL_H_ */\n"
  },
  {
    "path": "third-party/brotli/common/transform.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"transform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* RFC 7932 transforms string data */\nstatic const char kPrefixSuffix[217] =\n      \"\\1 \\2, \\10 of the \\4 of \\2s \\1.\\5 and \\4 \"\n/* 0x  _0 _2  __5        _E    _3  _6 _8     _E */\n      \"in \\1\\\"\\4 to \\2\\\">\\1\\n\\2. \\1]\\5 for \\3 a \\6 \"\n/* 2x     _3_ _5    _A_  _D_ _F  _2 _4     _A   _E */\n      \"that \\1\\'\\6 with \\6 from \\4 by \\1(\\6. T\"\n/* 4x       _5_ _7      _E      _5    _A _C */\n      \"he \\4 on \\4 as \\4 is \\4ing \\2\\n\\t\\1:\\3ed \"\n/* 6x     _3    _8    _D    _2    _7_ _ _A _C */\n      \"\\2=\\\"\\4 at \\3ly \\1,\\2=\\'\\5.com/\\7. This \\5\"\n/* 8x  _0 _ _3    _8   _C _E _ _1     _7       _F */\n      \" not \\3er \\3al \\4ful \\4ive \\5less \\4es\"\n/* Ax       _5   _9   _D    _2    _7     _D */\n      \"t \\4ize \\2\\xc2\\xa0\\4ous \\5 the \\2e \"; /* \\0 - implicit trailing zero. */\n/* Cx    _2    _7___ ___ _A    _F     _5        _8 */\n\nstatic const uint16_t kPrefixSuffixMap[50] = {\n  0x00, 0x02, 0x05, 0x0E, 0x13, 0x16, 0x18, 0x1E, 0x23, 0x25,\n  0x2A, 0x2D, 0x2F, 0x32, 0x34, 0x3A, 0x3E, 0x45, 0x47, 0x4E,\n  0x55, 0x5A, 0x5C, 0x63, 0x68, 0x6D, 0x72, 0x77, 0x7A, 0x7C,\n  0x80, 0x83, 0x88, 0x8C, 0x8E, 0x91, 0x97, 0x9F, 0xA5, 0xA9,\n  0xAD, 0xB2, 0xB7, 0xBD, 0xC2, 0xC7, 0xCA, 0xCF, 0xD5, 0xD8\n};\n\n/* RFC 7932 transforms */\nstatic const uint8_t kTransformsData[] = {\n  49, BROTLI_TRANSFORM_IDENTITY, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 0,\n   0, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_1, 49,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 47,\n   0, BROTLI_TRANSFORM_IDENTITY, 49,\n   4, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 3,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 6,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_2, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_1, 49,\n   1, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 1,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 7,\n  49, BROTLI_TRANSFORM_IDENTITY, 9,\n  48, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 8,\n  49, BROTLI_TRANSFORM_IDENTITY, 5,\n  49, BROTLI_TRANSFORM_IDENTITY, 10,\n  49, BROTLI_TRANSFORM_IDENTITY, 11,\n  49, BROTLI_TRANSFORM_OMIT_LAST_3, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 13,\n  49, BROTLI_TRANSFORM_IDENTITY, 14,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_3, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_2, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 15,\n  49, BROTLI_TRANSFORM_IDENTITY, 16,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 12,\n   5, BROTLI_TRANSFORM_IDENTITY, 49,\n   0, BROTLI_TRANSFORM_IDENTITY, 1,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_4, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 18,\n  49, BROTLI_TRANSFORM_IDENTITY, 17,\n  49, BROTLI_TRANSFORM_IDENTITY, 19,\n  49, BROTLI_TRANSFORM_IDENTITY, 20,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_5, 49,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_6, 49,\n  47, BROTLI_TRANSFORM_IDENTITY, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_4, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 22,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 23,\n  49, BROTLI_TRANSFORM_IDENTITY, 24,\n  49, BROTLI_TRANSFORM_IDENTITY, 25,\n  49, BROTLI_TRANSFORM_OMIT_LAST_7, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_1, 26,\n  49, BROTLI_TRANSFORM_IDENTITY, 27,\n  49, BROTLI_TRANSFORM_IDENTITY, 28,\n   0, BROTLI_TRANSFORM_IDENTITY, 12,\n  49, BROTLI_TRANSFORM_IDENTITY, 29,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_9, 49,\n  49, BROTLI_TRANSFORM_OMIT_FIRST_7, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_6, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1,\n  49, BROTLI_TRANSFORM_OMIT_LAST_8, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 31,\n  49, BROTLI_TRANSFORM_IDENTITY, 32,\n  47, BROTLI_TRANSFORM_IDENTITY, 3,\n  49, BROTLI_TRANSFORM_OMIT_LAST_5, 49,\n  49, BROTLI_TRANSFORM_OMIT_LAST_9, 49,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 1,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 8,\n   5, BROTLI_TRANSFORM_IDENTITY, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 0,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 10,\n  49, BROTLI_TRANSFORM_IDENTITY, 30,\n   0, BROTLI_TRANSFORM_IDENTITY, 5,\n  35, BROTLI_TRANSFORM_IDENTITY, 49,\n  47, BROTLI_TRANSFORM_IDENTITY, 2,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 17,\n  49, BROTLI_TRANSFORM_IDENTITY, 36,\n  49, BROTLI_TRANSFORM_IDENTITY, 33,\n   5, BROTLI_TRANSFORM_IDENTITY, 0,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5,\n  49, BROTLI_TRANSFORM_IDENTITY, 37,\n   0, BROTLI_TRANSFORM_IDENTITY, 30,\n  49, BROTLI_TRANSFORM_IDENTITY, 38,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 0,\n  49, BROTLI_TRANSFORM_IDENTITY, 39,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 49,\n  49, BROTLI_TRANSFORM_IDENTITY, 34,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 8,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12,\n   0, BROTLI_TRANSFORM_IDENTITY, 21,\n  49, BROTLI_TRANSFORM_IDENTITY, 40,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 12,\n  49, BROTLI_TRANSFORM_IDENTITY, 41,\n  49, BROTLI_TRANSFORM_IDENTITY, 42,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 17,\n  49, BROTLI_TRANSFORM_IDENTITY, 43,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 5,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 10,\n   0, BROTLI_TRANSFORM_IDENTITY, 34,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33,\n  49, BROTLI_TRANSFORM_IDENTITY, 44,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 5,\n  45, BROTLI_TRANSFORM_IDENTITY, 49,\n   0, BROTLI_TRANSFORM_IDENTITY, 33,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 30,\n  49, BROTLI_TRANSFORM_IDENTITY, 46,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 1,\n  49, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 33,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 30,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 1,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 33,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 21,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 12,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 5,\n  49, BROTLI_TRANSFORM_UPPERCASE_ALL, 34,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 12,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 30,\n   0, BROTLI_TRANSFORM_UPPERCASE_ALL, 34,\n   0, BROTLI_TRANSFORM_UPPERCASE_FIRST, 34,\n};\n\nstatic const BrotliTransforms kBrotliTransforms = {\n  sizeof(kPrefixSuffix),\n  (const uint8_t*)kPrefixSuffix,\n  kPrefixSuffixMap,\n  sizeof(kTransformsData) / (3 * sizeof(kTransformsData[0])),\n  kTransformsData,\n  NULL,  /* no extra parameters */\n  {0, 12, 27, 23, 42, 63, 56, 48, 59, 64}\n};\n\nconst BrotliTransforms* BrotliGetTransforms(void) {\n  return &kBrotliTransforms;\n}\n\nstatic int ToUpperCase(uint8_t* p) {\n  if (p[0] < 0xC0) {\n    if (p[0] >= 'a' && p[0] <= 'z') {\n      p[0] ^= 32;\n    }\n    return 1;\n  }\n  /* An overly simplified uppercasing model for UTF-8. */\n  if (p[0] < 0xE0) {\n    p[1] ^= 32;\n    return 2;\n  }\n  /* An arbitrary transform for three byte characters. */\n  p[2] ^= 5;\n  return 3;\n}\n\nstatic int Shift(uint8_t* word, int word_len, uint16_t parameter) {\n  /* Limited sign extension: scalar < (1 << 24). */\n  uint32_t scalar =\n      (parameter & 0x7FFFu) + (0x1000000u - (parameter & 0x8000u));\n  if (word[0] < 0x80) {\n    /* 1-byte rune / 0sssssss / 7 bit scalar (ASCII). */\n    scalar += (uint32_t)word[0];\n    word[0] = (uint8_t)(scalar & 0x7Fu);\n    return 1;\n  } else if (word[0] < 0xC0) {\n    /* Continuation / 10AAAAAA. */\n    return 1;\n  } else if (word[0] < 0xE0) {\n    /* 2-byte rune / 110sssss AAssssss / 11 bit scalar. */\n    if (word_len < 2) return 1;\n    scalar += (uint32_t)((word[1] & 0x3Fu) | ((word[0] & 0x1Fu) << 6u));\n    word[0] = (uint8_t)(0xC0 | ((scalar >> 6u) & 0x1F));\n    word[1] = (uint8_t)((word[1] & 0xC0) | (scalar & 0x3F));\n    return 2;\n  } else if (word[0] < 0xF0) {\n    /* 3-byte rune / 1110ssss AAssssss BBssssss / 16 bit scalar. */\n    if (word_len < 3) return word_len;\n    scalar += (uint32_t)((word[2] & 0x3Fu) | ((word[1] & 0x3Fu) << 6u) |\n        ((word[0] & 0x0Fu) << 12u));\n    word[0] = (uint8_t)(0xE0 | ((scalar >> 12u) & 0x0F));\n    word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 6u) & 0x3F));\n    word[2] = (uint8_t)((word[2] & 0xC0) | (scalar & 0x3F));\n    return 3;\n  } else if (word[0] < 0xF8) {\n    /* 4-byte rune / 11110sss AAssssss BBssssss CCssssss / 21 bit scalar. */\n    if (word_len < 4) return word_len;\n    scalar += (uint32_t)((word[3] & 0x3Fu) | ((word[2] & 0x3Fu) << 6u) |\n        ((word[1] & 0x3Fu) << 12u) | ((word[0] & 0x07u) << 18u));\n    word[0] = (uint8_t)(0xF0 | ((scalar >> 18u) & 0x07));\n    word[1] = (uint8_t)((word[1] & 0xC0) | ((scalar >> 12u) & 0x3F));\n    word[2] = (uint8_t)((word[2] & 0xC0) | ((scalar >> 6u) & 0x3F));\n    word[3] = (uint8_t)((word[3] & 0xC0) | (scalar & 0x3F));\n    return 4;\n  }\n  return 1;\n}\n\nint BrotliTransformDictionaryWord(uint8_t* dst, const uint8_t* word, int len,\n    const BrotliTransforms* transforms, int transform_idx) {\n  int idx = 0;\n  const uint8_t* prefix = BROTLI_TRANSFORM_PREFIX(transforms, transform_idx);\n  uint8_t type = BROTLI_TRANSFORM_TYPE(transforms, transform_idx);\n  const uint8_t* suffix = BROTLI_TRANSFORM_SUFFIX(transforms, transform_idx);\n  {\n    int prefix_len = *prefix++;\n    while (prefix_len--) { dst[idx++] = *prefix++; }\n  }\n  {\n    const int t = type;\n    int i = 0;\n    if (t <= BROTLI_TRANSFORM_OMIT_LAST_9) {\n      len -= t;\n    } else if (t >= BROTLI_TRANSFORM_OMIT_FIRST_1\n        && t <= BROTLI_TRANSFORM_OMIT_FIRST_9) {\n      int skip = t - (BROTLI_TRANSFORM_OMIT_FIRST_1 - 1);\n      word += skip;\n      len -= skip;\n    }\n    while (i < len) { dst[idx++] = word[i++]; }\n    if (t == BROTLI_TRANSFORM_UPPERCASE_FIRST) {\n      ToUpperCase(&dst[idx - len]);\n    } else if (t == BROTLI_TRANSFORM_UPPERCASE_ALL) {\n      uint8_t* uppercase = &dst[idx - len];\n      while (len > 0) {\n        int step = ToUpperCase(uppercase);\n        uppercase += step;\n        len -= step;\n      }\n    } else if (t == BROTLI_TRANSFORM_SHIFT_FIRST) {\n      uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]\n          + (transforms->params[transform_idx * 2 + 1] << 8u));\n      Shift(&dst[idx - len], len, param);\n    } else if (t == BROTLI_TRANSFORM_SHIFT_ALL) {\n      uint16_t param = (uint16_t)(transforms->params[transform_idx * 2]\n          + (transforms->params[transform_idx * 2 + 1] << 8u));\n      uint8_t* shift = &dst[idx - len];\n      while (len > 0) {\n        int step = Shift(shift, len, param);\n        shift += step;\n        len -= step;\n      }\n    }\n  }\n  {\n    int suffix_len = *suffix++;\n    while (suffix_len--) { dst[idx++] = *suffix++; }\n    return idx;\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/common/transform.h",
    "content": "/* transforms is a part of ABI, but not API.\n\n   It means that there are some functions that are supposed to be in \"common\"\n   library, but header itself is not placed into include/brotli. This way,\n   aforementioned functions will be available only to brotli internals.\n */\n\n#ifndef BROTLI_COMMON_TRANSFORM_H_\n#define BROTLI_COMMON_TRANSFORM_H_\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nenum BrotliWordTransformType {\n  BROTLI_TRANSFORM_IDENTITY = 0,\n  BROTLI_TRANSFORM_OMIT_LAST_1 = 1,\n  BROTLI_TRANSFORM_OMIT_LAST_2 = 2,\n  BROTLI_TRANSFORM_OMIT_LAST_3 = 3,\n  BROTLI_TRANSFORM_OMIT_LAST_4 = 4,\n  BROTLI_TRANSFORM_OMIT_LAST_5 = 5,\n  BROTLI_TRANSFORM_OMIT_LAST_6 = 6,\n  BROTLI_TRANSFORM_OMIT_LAST_7 = 7,\n  BROTLI_TRANSFORM_OMIT_LAST_8 = 8,\n  BROTLI_TRANSFORM_OMIT_LAST_9 = 9,\n  BROTLI_TRANSFORM_UPPERCASE_FIRST = 10,\n  BROTLI_TRANSFORM_UPPERCASE_ALL = 11,\n  BROTLI_TRANSFORM_OMIT_FIRST_1 = 12,\n  BROTLI_TRANSFORM_OMIT_FIRST_2 = 13,\n  BROTLI_TRANSFORM_OMIT_FIRST_3 = 14,\n  BROTLI_TRANSFORM_OMIT_FIRST_4 = 15,\n  BROTLI_TRANSFORM_OMIT_FIRST_5 = 16,\n  BROTLI_TRANSFORM_OMIT_FIRST_6 = 17,\n  BROTLI_TRANSFORM_OMIT_FIRST_7 = 18,\n  BROTLI_TRANSFORM_OMIT_FIRST_8 = 19,\n  BROTLI_TRANSFORM_OMIT_FIRST_9 = 20,\n  BROTLI_TRANSFORM_SHIFT_FIRST = 21,\n  BROTLI_TRANSFORM_SHIFT_ALL = 22,\n  BROTLI_NUM_TRANSFORM_TYPES  /* Counts transforms, not a transform itself. */\n};\n\n#define BROTLI_TRANSFORMS_MAX_CUT_OFF BROTLI_TRANSFORM_OMIT_LAST_9\n\ntypedef struct BrotliTransforms {\n  uint16_t prefix_suffix_size;\n  /* Last character must be null, so prefix_suffix_size must be at least 1. */\n  const uint8_t* prefix_suffix;\n  const uint16_t* prefix_suffix_map;\n  uint32_t num_transforms;\n  /* Each entry is a [prefix_id, transform, suffix_id] triplet. */\n  const uint8_t* transforms;\n  /* Shift for BROTLI_TRANSFORM_SHIFT_FIRST and BROTLI_TRANSFORM_SHIFT_ALL,\n     must be NULL if and only if no such transforms are present. */\n  const uint8_t* params;\n  /* Indices of transforms like [\"\", BROTLI_TRANSFORM_OMIT_LAST_#, \"\"].\n     0-th element corresponds to [\"\", BROTLI_TRANSFORM_IDENTITY, \"\"].\n     -1, if cut-off transform does not exist. */\n  int16_t cutOffTransforms[BROTLI_TRANSFORMS_MAX_CUT_OFF + 1];\n} BrotliTransforms;\n\n/* T is BrotliTransforms*; result is uint8_t. */\n#define BROTLI_TRANSFORM_PREFIX_ID(T, I) ((T)->transforms[((I) * 3) + 0])\n#define BROTLI_TRANSFORM_TYPE(T, I)      ((T)->transforms[((I) * 3) + 1])\n#define BROTLI_TRANSFORM_SUFFIX_ID(T, I) ((T)->transforms[((I) * 3) + 2])\n\n/* T is BrotliTransforms*; result is const uint8_t*. */\n#define BROTLI_TRANSFORM_PREFIX(T, I) (&(T)->prefix_suffix[ \\\n    (T)->prefix_suffix_map[BROTLI_TRANSFORM_PREFIX_ID(T, I)]])\n#define BROTLI_TRANSFORM_SUFFIX(T, I) (&(T)->prefix_suffix[ \\\n    (T)->prefix_suffix_map[BROTLI_TRANSFORM_SUFFIX_ID(T, I)]])\n\nBROTLI_COMMON_API const BrotliTransforms* BrotliGetTransforms(void);\n\nBROTLI_COMMON_API int BrotliTransformDictionaryWord(\n    uint8_t* dst, const uint8_t* word, int len,\n    const BrotliTransforms* transforms, int transform_idx);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_TRANSFORM_H_ */\n"
  },
  {
    "path": "third-party/brotli/common/version.h",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Version definition. */\n\n#ifndef BROTLI_COMMON_VERSION_H_\n#define BROTLI_COMMON_VERSION_H_\n\n/* Compose 3 components into a single number. In a hexadecimal representation\n   B and C components occupy exactly 3 digits. */\n#define BROTLI_MAKE_HEX_VERSION(A, B, C) ((A << 24) | (B << 12) | C)\n\n/* Those macros should only be used when library is compiled together with\n   the client. If library is dynamically linked, use BrotliDecoderVersion and\n   BrotliEncoderVersion methods. */\n\n#define BROTLI_VERSION_MAJOR 1\n#define BROTLI_VERSION_MINOR 1\n#define BROTLI_VERSION_PATCH 0\n\n#define BROTLI_VERSION BROTLI_MAKE_HEX_VERSION(                     \\\n  BROTLI_VERSION_MAJOR, BROTLI_VERSION_MINOR, BROTLI_VERSION_PATCH)\n\n/* This macro is used by build system to produce Libtool-friendly soname. See\n   https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html\n   Version evolution rules:\n    - interfaces added (or change is compatible)      -> current+1:0:age+1\n    - interfaces removed (or changed is incompatible) -> current+1:0:0\n    - interfaces not changed                          -> current:revision+1:age\n */\n\n#define BROTLI_ABI_CURRENT  2\n#define BROTLI_ABI_REVISION 0\n#define BROTLI_ABI_AGE      1\n\n#if BROTLI_VERSION_MAJOR != (BROTLI_ABI_CURRENT - BROTLI_ABI_AGE)\n#error ABI/API version inconsistency\n#endif\n\n#if BROTLI_VERSION_MINOR != BROTLI_ABI_AGE\n#error ABI/API version inconsistency\n#endif\n\n#if BROTLI_VERSION_PATCH != BROTLI_ABI_REVISION\n#error ABI/API version inconsistency\n#endif\n\n#endif  /* BROTLI_COMMON_VERSION_H_ */\n"
  },
  {
    "path": "third-party/brotli/dec/bit_reader.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Bit reading helpers */\n\n#include \"bit_reader.h\"\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nconst brotli_reg_t kBrotliBitMask[33] = {   0x00000000,\n    0x00000001, 0x00000003, 0x00000007, 0x0000000F,\n    0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF,\n    0x000001FF, 0x000003FF, 0x000007FF, 0x00000FFF,\n    0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF,\n    0x0001FFFF, 0x0003FFFF, 0x0007FFFF, 0x000FFFFF,\n    0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF,\n    0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF,\n    0x1FFFFFFF, 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF\n};\n\nvoid BrotliInitBitReader(BrotliBitReader* const br) {\n  br->val_ = 0;\n  br->bit_pos_ = 0;\n}\n\nBROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* const br) {\n  size_t aligned_read_mask = (sizeof(br->val_) >> 1) - 1;\n  /* Fixing alignment after unaligned BrotliFillWindow would result accumulator\n     overflow. If unalignment is caused by BrotliSafeReadBits, then there is\n     enough space in accumulator to fix alignment. */\n  if (BROTLI_UNALIGNED_READ_FAST) {\n    aligned_read_mask = 0;\n  }\n  if (BrotliGetAvailableBits(br) == 0) {\n    br->val_ = 0;\n    if (!BrotliPullByte(br)) {\n      return BROTLI_FALSE;\n    }\n  }\n\n  while ((((size_t)br->next_in) & aligned_read_mask) != 0) {\n    if (!BrotliPullByte(br)) {\n      /* If we consumed all the input, we don't care about the alignment. */\n      return BROTLI_TRUE;\n    }\n  }\n  return BROTLI_TRUE;\n}\n\nBROTLI_BOOL BrotliSafeReadBits32Slow(BrotliBitReader* const br,\n    brotli_reg_t n_bits, brotli_reg_t* val) {\n  brotli_reg_t low_val;\n  brotli_reg_t high_val;\n  BrotliBitReaderState memento;\n  BROTLI_DCHECK(n_bits <= 32);\n  BROTLI_DCHECK(n_bits > 24);\n  BrotliBitReaderSaveState(br, &memento);\n  if (!BrotliSafeReadBits(br, 16, &low_val) ||\n      !BrotliSafeReadBits(br, n_bits - 16, &high_val)) {\n    BrotliBitReaderRestoreState(br, &memento);\n    return BROTLI_FALSE;\n  }\n  *val = low_val | (high_val << 16);\n  return BROTLI_TRUE;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/dec/bit_reader.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Bit reading helpers */\n\n#ifndef BROTLI_DEC_BIT_READER_H_\n#define BROTLI_DEC_BIT_READER_H_\n\n#include <string.h>  /* memcpy */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_SHORT_FILL_BIT_WINDOW_READ (sizeof(brotli_reg_t) >> 1)\n\n/* 162 bits + 7 bytes */\n#define BROTLI_FAST_INPUT_SLACK 28\n\nBROTLI_INTERNAL extern const brotli_reg_t kBrotliBitMask[33];\n\nstatic BROTLI_INLINE brotli_reg_t BitMask(brotli_reg_t n) {\n  if (BROTLI_IS_CONSTANT(n) || BROTLI_HAS_UBFX) {\n    /* Masking with this expression turns to a single\n       \"Unsigned Bit Field Extract\" UBFX instruction on ARM. */\n    return ~(~((brotli_reg_t)0) << n);\n  } else {\n    return kBrotliBitMask[n];\n  }\n}\n\ntypedef struct {\n  brotli_reg_t val_;       /* pre-fetched bits */\n  brotli_reg_t bit_pos_;   /* current bit-reading position in val_ */\n  const uint8_t* next_in;  /* the byte we're reading from */\n  const uint8_t* guard_in; /* position from which \"fast-path\" is prohibited */\n  const uint8_t* last_in;  /* == next_in + avail_in */\n} BrotliBitReader;\n\ntypedef struct {\n  brotli_reg_t val_;\n  brotli_reg_t bit_pos_;\n  const uint8_t* next_in;\n  size_t avail_in;\n} BrotliBitReaderState;\n\n/* Initializes the BrotliBitReader fields. */\nBROTLI_INTERNAL void BrotliInitBitReader(BrotliBitReader* br);\n\n/* Ensures that accumulator is not empty.\n   May consume up to sizeof(brotli_reg_t) - 1 bytes of input.\n   Returns BROTLI_FALSE if data is required but there is no input available.\n   For !BROTLI_UNALIGNED_READ_FAST this function also prepares bit reader for\n   aligned reading. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliWarmupBitReader(BrotliBitReader* br);\n\n/* Fallback for BrotliSafeReadBits32. Extracted as noninlined method to unburden\n   the main code-path. Never called for RFC brotli streams, required only for\n   \"large-window\" mode and other extensions. */\nBROTLI_INTERNAL BROTLI_NOINLINE BROTLI_BOOL BrotliSafeReadBits32Slow(\n    BrotliBitReader* br, brotli_reg_t n_bits, brotli_reg_t* val);\n\nstatic BROTLI_INLINE size_t\nBrotliBitReaderGetAvailIn(BrotliBitReader* const br) {\n  return (size_t)(br->last_in - br->next_in);\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderSaveState(\n    BrotliBitReader* const from, BrotliBitReaderState* to) {\n  to->val_ = from->val_;\n  to->bit_pos_ = from->bit_pos_;\n  to->next_in = from->next_in;\n  to->avail_in = BrotliBitReaderGetAvailIn(from);\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderSetInput(\n    BrotliBitReader* const br, const uint8_t* next_in, size_t avail_in) {\n  br->next_in = next_in;\n  br->last_in = (avail_in == 0) ? next_in : (next_in + avail_in);\n  if (avail_in + 1 > BROTLI_FAST_INPUT_SLACK) {\n    br->guard_in = next_in + (avail_in + 1 - BROTLI_FAST_INPUT_SLACK);\n  } else {\n    br->guard_in = next_in;\n  }\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderRestoreState(\n    BrotliBitReader* const to, BrotliBitReaderState* from) {\n  to->val_ = from->val_;\n  to->bit_pos_ = from->bit_pos_;\n  to->next_in = from->next_in;\n  BrotliBitReaderSetInput(to, from->next_in, from->avail_in);\n}\n\nstatic BROTLI_INLINE brotli_reg_t BrotliGetAvailableBits(\n    const BrotliBitReader* br) {\n  return br->bit_pos_;\n}\n\n/* Returns amount of unread bytes the bit reader still has buffered from the\n   BrotliInput, including whole bytes in br->val_. Result is capped with\n   maximal ring-buffer size (larger number won't be utilized anyway). */\nstatic BROTLI_INLINE size_t BrotliGetRemainingBytes(BrotliBitReader* br) {\n  static const size_t kCap = (size_t)1 << BROTLI_LARGE_MAX_WBITS;\n  size_t avail_in = BrotliBitReaderGetAvailIn(br);\n  if (avail_in > kCap) return kCap;\n  return avail_in + (BrotliGetAvailableBits(br) >> 3);\n}\n\n/* Checks if there is at least |num| bytes left in the input ring-buffer\n   (excluding the bits remaining in br->val_). */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliCheckInputAmount(\n    BrotliBitReader* const br) {\n  return TO_BROTLI_BOOL(br->next_in < br->guard_in);\n}\n\n/* Load more bits into accumulator. */\nstatic BROTLI_INLINE brotli_reg_t BrotliBitReaderLoadBits(brotli_reg_t val,\n                                                          brotli_reg_t new_bits,\n                                                          brotli_reg_t count,\n                                                          brotli_reg_t offset) {\n  BROTLI_DCHECK(\n      !((val >> offset) & ~new_bits & ~(~((brotli_reg_t)0) << count)));\n  (void)count;\n  return val | (new_bits << offset);\n}\n\n/* Guarantees that there are at least |n_bits| + 1 bits in accumulator.\n   Precondition: accumulator contains at least 1 bit.\n   |n_bits| should be in the range [1..24] for regular build. For portable\n   non-64-bit little-endian build only 16 bits are safe to request. */\nstatic BROTLI_INLINE void BrotliFillBitWindow(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n#if (BROTLI_64_BITS)\n  if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&\n      (n_bits <= 8)) {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 8) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          BROTLI_UNALIGNED_LOAD64LE(br->next_in), 56, bit_pos);\n      br->bit_pos_ = bit_pos + 56;\n      br->next_in += 7;\n    }\n  } else if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&\n             (n_bits <= 16)) {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 16) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          BROTLI_UNALIGNED_LOAD64LE(br->next_in), 48, bit_pos);\n      br->bit_pos_ = bit_pos + 48;\n      br->next_in += 6;\n    }\n  } else {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 32) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          (uint64_t)BROTLI_UNALIGNED_LOAD32LE(br->next_in), 32, bit_pos);\n      br->bit_pos_ = bit_pos + 32;\n      br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;\n    }\n  }\n#else\n  if (BROTLI_UNALIGNED_READ_FAST && BROTLI_IS_CONSTANT(n_bits) &&\n      (n_bits <= 8)) {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 8) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          BROTLI_UNALIGNED_LOAD32LE(br->next_in), 24, bit_pos);\n      br->bit_pos_ = bit_pos + 24;\n      br->next_in += 3;\n    }\n  } else {\n    brotli_reg_t bit_pos = br->bit_pos_;\n    if (bit_pos <= 16) {\n      br->val_ = BrotliBitReaderLoadBits(br->val_,\n          (uint32_t)BROTLI_UNALIGNED_LOAD16LE(br->next_in), 16, bit_pos);\n      br->bit_pos_ = bit_pos + 16;\n      br->next_in += BROTLI_SHORT_FILL_BIT_WINDOW_READ;\n    }\n  }\n#endif\n}\n\n/* Mostly like BrotliFillBitWindow, but guarantees only 16 bits and reads no\n   more than BROTLI_SHORT_FILL_BIT_WINDOW_READ bytes of input. */\nstatic BROTLI_INLINE void BrotliFillBitWindow16(BrotliBitReader* const br) {\n  BrotliFillBitWindow(br, 17);\n}\n\n/* Tries to pull one byte of input to accumulator.\n   Returns BROTLI_FALSE if there is no input available. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliPullByte(BrotliBitReader* const br) {\n  if (br->next_in == br->last_in) {\n    return BROTLI_FALSE;\n  }\n  br->val_ = BrotliBitReaderLoadBits(br->val_,\n      (brotli_reg_t)*br->next_in, 8, br->bit_pos_);\n  br->bit_pos_ += 8;\n  ++br->next_in;\n  return BROTLI_TRUE;\n}\n\n/* Returns currently available bits.\n   The number of valid bits could be calculated by BrotliGetAvailableBits. */\nstatic BROTLI_INLINE brotli_reg_t BrotliGetBitsUnmasked(\n    BrotliBitReader* const br) {\n  return br->val_;\n}\n\n/* Like BrotliGetBits, but does not mask the result.\n   The result contains at least 16 valid bits. */\nstatic BROTLI_INLINE brotli_reg_t BrotliGet16BitsUnmasked(\n    BrotliBitReader* const br) {\n  BrotliFillBitWindow(br, 16);\n  return (brotli_reg_t)BrotliGetBitsUnmasked(br);\n}\n\n/* Returns the specified number of bits from |br| without advancing bit\n   position. */\nstatic BROTLI_INLINE brotli_reg_t BrotliGetBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  BrotliFillBitWindow(br, n_bits);\n  return BrotliGetBitsUnmasked(br) & BitMask(n_bits);\n}\n\n/* Tries to peek the specified amount of bits. Returns BROTLI_FALSE, if there\n   is not enough input. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliSafeGetBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  while (BrotliGetAvailableBits(br) < n_bits) {\n    if (!BrotliPullByte(br)) {\n      return BROTLI_FALSE;\n    }\n  }\n  *val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);\n  return BROTLI_TRUE;\n}\n\n/* Advances the bit pos by |n_bits|. */\nstatic BROTLI_INLINE void BrotliDropBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  br->bit_pos_ -= n_bits;\n  br->val_ >>= n_bits;\n}\n\n/* Make sure that there are no spectre bits in accumulator.\n   This is important for the cases when some bytes are skipped\n   (i.e. never placed into accumulator). */\nstatic BROTLI_INLINE void BrotliBitReaderNormalize(BrotliBitReader* br) {\n  /* Actually, it is enough to normalize when br->bit_pos_ == 0 */\n  if (br->bit_pos_ < (sizeof(brotli_reg_t) << 3u)) {\n    br->val_ &= (((brotli_reg_t)1) << br->bit_pos_) - 1;\n  }\n}\n\nstatic BROTLI_INLINE void BrotliBitReaderUnload(BrotliBitReader* br) {\n  brotli_reg_t unused_bytes = BrotliGetAvailableBits(br) >> 3;\n  brotli_reg_t unused_bits = unused_bytes << 3;\n  br->next_in =\n      (unused_bytes == 0) ? br->next_in : (br->next_in - unused_bytes);\n  br->bit_pos_ -= unused_bits;\n  BrotliBitReaderNormalize(br);\n}\n\n/* Reads the specified number of bits from |br| and advances the bit pos.\n   Precondition: accumulator MUST contain at least |n_bits|. */\nstatic BROTLI_INLINE void BrotliTakeBits(BrotliBitReader* const br,\n                                         brotli_reg_t n_bits,\n                                         brotli_reg_t* val) {\n  *val = BrotliGetBitsUnmasked(br) & BitMask(n_bits);\n  BROTLI_LOG((\"[BrotliTakeBits]  %d %d %d val: %6x\\n\",\n              (int)BrotliBitReaderGetAvailIn(br), (int)br->bit_pos_,\n              (int)n_bits, (int)*val));\n  BrotliDropBits(br, n_bits);\n}\n\n/* Reads the specified number of bits from |br| and advances the bit pos.\n   Assumes that there is enough input to perform BrotliFillBitWindow.\n   Up to 24 bits are allowed to be requested from this method. */\nstatic BROTLI_INLINE brotli_reg_t BrotliReadBits24(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  BROTLI_DCHECK(n_bits <= 24);\n  if (BROTLI_64_BITS || (n_bits <= 16)) {\n    brotli_reg_t val;\n    BrotliFillBitWindow(br, n_bits);\n    BrotliTakeBits(br, n_bits, &val);\n    return val;\n  } else {\n    brotli_reg_t low_val;\n    brotli_reg_t high_val;\n    BrotliFillBitWindow(br, 16);\n    BrotliTakeBits(br, 16, &low_val);\n    BrotliFillBitWindow(br, 8);\n    BrotliTakeBits(br, n_bits - 16, &high_val);\n    return low_val | (high_val << 16);\n  }\n}\n\n/* Same as BrotliReadBits24, but allows reading up to 32 bits. */\nstatic BROTLI_INLINE brotli_reg_t BrotliReadBits32(\n    BrotliBitReader* const br, brotli_reg_t n_bits) {\n  BROTLI_DCHECK(n_bits <= 32);\n  if (BROTLI_64_BITS || (n_bits <= 16)) {\n    brotli_reg_t val;\n    BrotliFillBitWindow(br, n_bits);\n    BrotliTakeBits(br, n_bits, &val);\n    return val;\n  } else {\n    brotli_reg_t low_val;\n    brotli_reg_t high_val;\n    BrotliFillBitWindow(br, 16);\n    BrotliTakeBits(br, 16, &low_val);\n    BrotliFillBitWindow(br, 16);\n    BrotliTakeBits(br, n_bits - 16, &high_val);\n    return low_val | (high_val << 16);\n  }\n}\n\n/* Tries to read the specified amount of bits. Returns BROTLI_FALSE, if there\n   is not enough input. |n_bits| MUST be positive.\n   Up to 24 bits are allowed to be requested from this method. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  BROTLI_DCHECK(n_bits <= 24);\n  while (BrotliGetAvailableBits(br) < n_bits) {\n    if (!BrotliPullByte(br)) {\n      return BROTLI_FALSE;\n    }\n  }\n  BrotliTakeBits(br, n_bits, val);\n  return BROTLI_TRUE;\n}\n\n/* Same as BrotliSafeReadBits, but allows reading up to 32 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliSafeReadBits32(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  BROTLI_DCHECK(n_bits <= 32);\n  if (BROTLI_64_BITS || (n_bits <= 24)) {\n    while (BrotliGetAvailableBits(br) < n_bits) {\n      if (!BrotliPullByte(br)) {\n        return BROTLI_FALSE;\n      }\n    }\n    BrotliTakeBits(br, n_bits, val);\n    return BROTLI_TRUE;\n  } else {\n    return BrotliSafeReadBits32Slow(br, n_bits, val);\n  }\n}\n\n/* Advances the bit reader position to the next byte boundary and verifies\n   that any skipped bits are set to zero. */\nstatic BROTLI_INLINE BROTLI_BOOL BrotliJumpToByteBoundary(BrotliBitReader* br) {\n  brotli_reg_t pad_bits_count = BrotliGetAvailableBits(br) & 0x7;\n  brotli_reg_t pad_bits = 0;\n  if (pad_bits_count != 0) {\n    BrotliTakeBits(br, pad_bits_count, &pad_bits);\n  }\n  BrotliBitReaderNormalize(br);\n  return TO_BROTLI_BOOL(pad_bits == 0);\n}\n\nstatic BROTLI_INLINE void BrotliDropBytes(BrotliBitReader* br, size_t num) {\n  /* Check detour is legal: accumulator must to be empty. */\n  BROTLI_DCHECK(br->bit_pos_ == 0);\n  BROTLI_DCHECK(br->val_ == 0);\n  br->next_in += num;\n}\n\n/* Copies remaining input bytes stored in the bit reader to the output. Value\n   |num| may not be larger than BrotliGetRemainingBytes. The bit reader must be\n   warmed up again after this. */\nstatic BROTLI_INLINE void BrotliCopyBytes(uint8_t* dest,\n                                          BrotliBitReader* br, size_t num) {\n  while (BrotliGetAvailableBits(br) >= 8 && num > 0) {\n    *dest = (uint8_t)BrotliGetBitsUnmasked(br);\n    BrotliDropBits(br, 8);\n    ++dest;\n    --num;\n  }\n  BrotliBitReaderNormalize(br);\n  if (num > 0) {\n    memcpy(dest, br->next_in, num);\n    BrotliDropBytes(br, num);\n  }\n}\n\nBROTLI_UNUSED_FUNCTION void BrotliBitReaderSuppressUnusedFunctions(void) {\n  BROTLI_UNUSED(&BrotliBitReaderSuppressUnusedFunctions);\n\n  BROTLI_UNUSED(&BrotliBitReaderGetAvailIn);\n  BROTLI_UNUSED(&BrotliBitReaderLoadBits);\n  BROTLI_UNUSED(&BrotliBitReaderRestoreState);\n  BROTLI_UNUSED(&BrotliBitReaderSaveState);\n  BROTLI_UNUSED(&BrotliBitReaderSetInput);\n  BROTLI_UNUSED(&BrotliBitReaderUnload);\n  BROTLI_UNUSED(&BrotliCheckInputAmount);\n  BROTLI_UNUSED(&BrotliCopyBytes);\n  BROTLI_UNUSED(&BrotliFillBitWindow16);\n  BROTLI_UNUSED(&BrotliGet16BitsUnmasked);\n  BROTLI_UNUSED(&BrotliGetBits);\n  BROTLI_UNUSED(&BrotliGetRemainingBytes);\n  BROTLI_UNUSED(&BrotliJumpToByteBoundary);\n  BROTLI_UNUSED(&BrotliReadBits24);\n  BROTLI_UNUSED(&BrotliReadBits32);\n  BROTLI_UNUSED(&BrotliSafeGetBits);\n  BROTLI_UNUSED(&BrotliSafeReadBits);\n  BROTLI_UNUSED(&BrotliSafeReadBits32);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_BIT_READER_H_ */\n"
  },
  {
    "path": "third-party/brotli/dec/decode.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include <brotli/decode.h>\n\n#include <stdlib.h>  /* free, malloc */\n#include <string.h>  /* memcpy, memset */\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/shared_dictionary_internal.h\"\n#include \"../common/transform.h\"\n#include \"../common/version.h\"\n#include \"bit_reader.h\"\n#include \"huffman.h\"\n#include \"prefix.h\"\n#include \"state.h\"\n\n#if defined(BROTLI_TARGET_NEON)\n#include <arm_neon.h>\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_FAILURE(CODE) (BROTLI_DUMP(), CODE)\n\n#define BROTLI_LOG_UINT(name)                                       \\\n  BROTLI_LOG((\"[%s] %s = %lu\\n\", __func__, #name, (unsigned long)(name)))\n#define BROTLI_LOG_ARRAY_INDEX(array_name, idx)                     \\\n  BROTLI_LOG((\"[%s] %s[%lu] = %lu\\n\", __func__, #array_name,        \\\n         (unsigned long)(idx), (unsigned long)array_name[idx]))\n\n#define HUFFMAN_TABLE_BITS 8U\n#define HUFFMAN_TABLE_MASK 0xFF\n\n/* We need the slack region for the following reasons:\n    - doing up to two 16-byte copies for fast backward copying\n    - inserting transformed dictionary word:\n        255 prefix + 32 base + 255 suffix */\nstatic const brotli_reg_t kRingBufferWriteAheadSlack = 542;\n\nstatic const uint8_t kCodeLengthCodeOrder[BROTLI_CODE_LENGTH_CODES] = {\n  1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15,\n};\n\n/* Static prefix code for the complex code length code lengths. */\nstatic const uint8_t kCodeLengthPrefixLength[16] = {\n  2, 2, 2, 3, 2, 2, 2, 4, 2, 2, 2, 3, 2, 2, 2, 4,\n};\n\nstatic const uint8_t kCodeLengthPrefixValue[16] = {\n  0, 4, 3, 2, 0, 4, 3, 1, 0, 4, 3, 2, 0, 4, 3, 5,\n};\n\nBROTLI_BOOL BrotliDecoderSetParameter(\n    BrotliDecoderState* state, BrotliDecoderParameter p, uint32_t value) {\n  if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;\n  switch (p) {\n    case BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION:\n      state->canny_ringbuffer_allocation = !!value ? 0 : 1;\n      return BROTLI_TRUE;\n\n    case BROTLI_DECODER_PARAM_LARGE_WINDOW:\n      state->large_window = TO_BROTLI_BOOL(!!value);\n      return BROTLI_TRUE;\n\n    default: return BROTLI_FALSE;\n  }\n}\n\nBrotliDecoderState* BrotliDecoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BrotliDecoderState* state = 0;\n  if (!alloc_func && !free_func) {\n    state = (BrotliDecoderState*)malloc(sizeof(BrotliDecoderState));\n  } else if (alloc_func && free_func) {\n    state = (BrotliDecoderState*)alloc_func(opaque, sizeof(BrotliDecoderState));\n  }\n  if (state == 0) {\n    BROTLI_DUMP();\n    return 0;\n  }\n  if (!BrotliDecoderStateInit(state, alloc_func, free_func, opaque)) {\n    BROTLI_DUMP();\n    if (!alloc_func && !free_func) {\n      free(state);\n    } else if (alloc_func && free_func) {\n      free_func(opaque, state);\n    }\n    return 0;\n  }\n  return state;\n}\n\n/* Deinitializes and frees BrotliDecoderState instance. */\nvoid BrotliDecoderDestroyInstance(BrotliDecoderState* state) {\n  if (!state) {\n    return;\n  } else {\n    brotli_free_func free_func = state->free_func;\n    void* opaque = state->memory_manager_opaque;\n    BrotliDecoderStateCleanup(state);\n    free_func(opaque, state);\n  }\n}\n\n/* Saves error code and converts it to BrotliDecoderResult. */\nstatic BROTLI_NOINLINE BrotliDecoderResult SaveErrorCode(\n    BrotliDecoderState* s, BrotliDecoderErrorCode e, size_t consumed_input) {\n  s->error_code = (int)e;\n  s->used_input += consumed_input;\n  if ((s->buffer_length != 0) && (s->br.next_in == s->br.last_in)) {\n    /* If internal buffer is depleted at last, reset it. */\n    s->buffer_length = 0;\n  }\n  switch (e) {\n    case BROTLI_DECODER_SUCCESS:\n      return BROTLI_DECODER_RESULT_SUCCESS;\n\n    case BROTLI_DECODER_NEEDS_MORE_INPUT:\n      return BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT;\n\n    case BROTLI_DECODER_NEEDS_MORE_OUTPUT:\n      return BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT;\n\n    default:\n      return BROTLI_DECODER_RESULT_ERROR;\n  }\n}\n\n/* Decodes WBITS by reading 1 - 7 bits, or 0x11 for \"Large Window Brotli\".\n   Precondition: bit-reader accumulator has at least 8 bits. */\nstatic BrotliDecoderErrorCode DecodeWindowBits(BrotliDecoderState* s,\n                                               BrotliBitReader* br) {\n  brotli_reg_t n;\n  BROTLI_BOOL large_window = s->large_window;\n  s->large_window = BROTLI_FALSE;\n  BrotliTakeBits(br, 1, &n);\n  if (n == 0) {\n    s->window_bits = 16;\n    return BROTLI_DECODER_SUCCESS;\n  }\n  BrotliTakeBits(br, 3, &n);\n  if (n != 0) {\n    s->window_bits = (17u + n) & 63u;\n    return BROTLI_DECODER_SUCCESS;\n  }\n  BrotliTakeBits(br, 3, &n);\n  if (n == 1) {\n    if (large_window) {\n      BrotliTakeBits(br, 1, &n);\n      if (n == 1) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);\n      }\n      s->large_window = BROTLI_TRUE;\n      return BROTLI_DECODER_SUCCESS;\n    } else {\n      return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);\n    }\n  }\n  if (n != 0) {\n    s->window_bits = (8u + n) & 63u;\n    return BROTLI_DECODER_SUCCESS;\n  }\n  s->window_bits = 17;\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic BROTLI_INLINE void memmove16(uint8_t* dst, uint8_t* src) {\n#if defined(BROTLI_TARGET_NEON)\n  vst1q_u8(dst, vld1q_u8(src));\n#else\n  uint32_t buffer[4];\n  memcpy(buffer, src, 16);\n  memcpy(dst, buffer, 16);\n#endif\n}\n\n/* Decodes a number in the range [0..255], by reading 1 - 11 bits. */\nstatic BROTLI_NOINLINE BrotliDecoderErrorCode DecodeVarLenUint8(\n    BrotliDecoderState* s, BrotliBitReader* br, brotli_reg_t* value) {\n  brotli_reg_t bits;\n  switch (s->substate_decode_uint8) {\n    case BROTLI_STATE_DECODE_UINT8_NONE:\n      if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 1, &bits))) {\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if (bits == 0) {\n        *value = 0;\n        return BROTLI_DECODER_SUCCESS;\n      }\n    /* Fall through. */\n\n    case BROTLI_STATE_DECODE_UINT8_SHORT:\n      if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, 3, &bits))) {\n        s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_SHORT;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if (bits == 0) {\n        *value = 1;\n        s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;\n        return BROTLI_DECODER_SUCCESS;\n      }\n      /* Use output value as a temporary storage. It MUST be persisted. */\n      *value = bits;\n    /* Fall through. */\n\n    case BROTLI_STATE_DECODE_UINT8_LONG:\n      if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, *value, &bits))) {\n        s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_LONG;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      *value = (1U << *value) + bits;\n      s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;\n      return BROTLI_DECODER_SUCCESS;\n\n    default:\n      return\n          BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n  }\n}\n\n/* Decodes a metablock length and flags by reading 2 - 31 bits. */\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE DecodeMetaBlockLength(\n    BrotliDecoderState* s, BrotliBitReader* br) {\n  brotli_reg_t bits;\n  int i;\n  for (;;) {\n    switch (s->substate_metablock_header) {\n      case BROTLI_STATE_METABLOCK_HEADER_NONE:\n        if (!BrotliSafeReadBits(br, 1, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        s->is_last_metablock = bits ? 1 : 0;\n        s->meta_block_remaining_len = 0;\n        s->is_uncompressed = 0;\n        s->is_metadata = 0;\n        if (!s->is_last_metablock) {\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;\n          break;\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_EMPTY;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_EMPTY:\n        if (!BrotliSafeReadBits(br, 1, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        if (bits) {\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n          return BROTLI_DECODER_SUCCESS;\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NIBBLES;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_NIBBLES:\n        if (!BrotliSafeReadBits(br, 2, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        s->size_nibbles = (uint8_t)(bits + 4);\n        s->loop_counter = 0;\n        if (bits == 3) {\n          s->is_metadata = 1;\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_RESERVED;\n          break;\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_SIZE;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_SIZE:\n        i = s->loop_counter;\n        for (; i < (int)s->size_nibbles; ++i) {\n          if (!BrotliSafeReadBits(br, 4, &bits)) {\n            s->loop_counter = i;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 4 &&\n              bits == 0) {\n            return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE);\n          }\n          s->meta_block_remaining_len |= (int)(bits << (i * 4));\n        }\n        s->substate_metablock_header =\n            BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED:\n        if (!s->is_last_metablock) {\n          if (!BrotliSafeReadBits(br, 1, &bits)) {\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          s->is_uncompressed = bits ? 1 : 0;\n        }\n        ++s->meta_block_remaining_len;\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n        return BROTLI_DECODER_SUCCESS;\n\n      case BROTLI_STATE_METABLOCK_HEADER_RESERVED:\n        if (!BrotliSafeReadBits(br, 1, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        if (bits != 0) {\n          return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_RESERVED);\n        }\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_BYTES;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_BYTES:\n        if (!BrotliSafeReadBits(br, 2, &bits)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        if (bits == 0) {\n          s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n          return BROTLI_DECODER_SUCCESS;\n        }\n        s->size_nibbles = (uint8_t)bits;\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_METADATA;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER_METADATA:\n        i = s->loop_counter;\n        for (; i < (int)s->size_nibbles; ++i) {\n          if (!BrotliSafeReadBits(br, 8, &bits)) {\n            s->loop_counter = i;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          if (i + 1 == (int)s->size_nibbles && s->size_nibbles > 1 &&\n              bits == 0) {\n            return BROTLI_FAILURE(\n                BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE);\n          }\n          s->meta_block_remaining_len |= (int)(bits << (i * 8));\n        }\n        ++s->meta_block_remaining_len;\n        s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n        return BROTLI_DECODER_SUCCESS;\n\n      default:\n        return\n            BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n    }\n  }\n}\n\n/* Decodes the Huffman code.\n   This method doesn't read data from the bit reader, BUT drops the amount of\n   bits that correspond to the decoded symbol.\n   bits MUST contain at least 15 (BROTLI_HUFFMAN_MAX_CODE_LENGTH) valid bits. */\nstatic BROTLI_INLINE brotli_reg_t DecodeSymbol(brotli_reg_t bits,\n                                               const HuffmanCode* table,\n                                               BrotliBitReader* br) {\n  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, bits & HUFFMAN_TABLE_MASK);\n  if (BROTLI_HC_FAST_LOAD_BITS(table) > HUFFMAN_TABLE_BITS) {\n    brotli_reg_t nbits = BROTLI_HC_FAST_LOAD_BITS(table) - HUFFMAN_TABLE_BITS;\n    BrotliDropBits(br, HUFFMAN_TABLE_BITS);\n    BROTLI_HC_ADJUST_TABLE_INDEX(table,\n        BROTLI_HC_FAST_LOAD_VALUE(table) +\n        ((bits >> HUFFMAN_TABLE_BITS) & BitMask(nbits)));\n  }\n  BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));\n  return BROTLI_HC_FAST_LOAD_VALUE(table);\n}\n\n/* Reads and decodes the next Huffman code from bit-stream.\n   This method peeks 16 bits of input and drops 0 - 15 of them. */\nstatic BROTLI_INLINE brotli_reg_t ReadSymbol(const HuffmanCode* table,\n                                             BrotliBitReader* br) {\n  return DecodeSymbol(BrotliGet16BitsUnmasked(br), table, br);\n}\n\n/* Same as DecodeSymbol, but it is known that there is less than 15 bits of\n   input are currently available. */\nstatic BROTLI_NOINLINE BROTLI_BOOL SafeDecodeSymbol(\n    const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {\n  brotli_reg_t val;\n  brotli_reg_t available_bits = BrotliGetAvailableBits(br);\n  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n  if (available_bits == 0) {\n    if (BROTLI_HC_FAST_LOAD_BITS(table) == 0) {\n      *result = BROTLI_HC_FAST_LOAD_VALUE(table);\n      return BROTLI_TRUE;\n    }\n    return BROTLI_FALSE;  /* No valid bits at all. */\n  }\n  val = BrotliGetBitsUnmasked(br);\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, val & HUFFMAN_TABLE_MASK);\n  if (BROTLI_HC_FAST_LOAD_BITS(table) <= HUFFMAN_TABLE_BITS) {\n    if (BROTLI_HC_FAST_LOAD_BITS(table) <= available_bits) {\n      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(table));\n      *result = BROTLI_HC_FAST_LOAD_VALUE(table);\n      return BROTLI_TRUE;\n    } else {\n      return BROTLI_FALSE;  /* Not enough bits for the first level. */\n    }\n  }\n  if (available_bits <= HUFFMAN_TABLE_BITS) {\n    return BROTLI_FALSE;  /* Not enough bits to move to the second level. */\n  }\n\n  /* Speculatively drop HUFFMAN_TABLE_BITS. */\n  val = (val & BitMask(BROTLI_HC_FAST_LOAD_BITS(table))) >> HUFFMAN_TABLE_BITS;\n  available_bits -= HUFFMAN_TABLE_BITS;\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, BROTLI_HC_FAST_LOAD_VALUE(table) + val);\n  if (available_bits < BROTLI_HC_FAST_LOAD_BITS(table)) {\n    return BROTLI_FALSE;  /* Not enough bits for the second level. */\n  }\n\n  BrotliDropBits(br, HUFFMAN_TABLE_BITS + BROTLI_HC_FAST_LOAD_BITS(table));\n  *result = BROTLI_HC_FAST_LOAD_VALUE(table);\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadSymbol(\n    const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {\n  brotli_reg_t val;\n  if (BROTLI_PREDICT_TRUE(BrotliSafeGetBits(br, 15, &val))) {\n    *result = DecodeSymbol(val, table, br);\n    return BROTLI_TRUE;\n  }\n  return SafeDecodeSymbol(table, br, result);\n}\n\n/* Makes a look-up in first level Huffman table. Peeks 8 bits. */\nstatic BROTLI_INLINE void PreloadSymbol(int safe,\n                                        const HuffmanCode* table,\n                                        BrotliBitReader* br,\n                                        brotli_reg_t* bits,\n                                        brotli_reg_t* value) {\n  if (safe) {\n    return;\n  }\n  BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n  BROTLI_HC_ADJUST_TABLE_INDEX(table, BrotliGetBits(br, HUFFMAN_TABLE_BITS));\n  *bits = BROTLI_HC_FAST_LOAD_BITS(table);\n  *value = BROTLI_HC_FAST_LOAD_VALUE(table);\n}\n\n/* Decodes the next Huffman code using data prepared by PreloadSymbol.\n   Reads 0 - 15 bits. Also peeks 8 following bits. */\nstatic BROTLI_INLINE brotli_reg_t ReadPreloadedSymbol(const HuffmanCode* table,\n                                                  BrotliBitReader* br,\n                                                  brotli_reg_t* bits,\n                                                  brotli_reg_t* value) {\n  brotli_reg_t result = *value;\n  if (BROTLI_PREDICT_FALSE(*bits > HUFFMAN_TABLE_BITS)) {\n    brotli_reg_t val = BrotliGet16BitsUnmasked(br);\n    const HuffmanCode* ext = table + (val & HUFFMAN_TABLE_MASK) + *value;\n    brotli_reg_t mask = BitMask((*bits - HUFFMAN_TABLE_BITS));\n    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(ext);\n    BrotliDropBits(br, HUFFMAN_TABLE_BITS);\n    BROTLI_HC_ADJUST_TABLE_INDEX(ext, (val >> HUFFMAN_TABLE_BITS) & mask);\n    BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(ext));\n    result = BROTLI_HC_FAST_LOAD_VALUE(ext);\n  } else {\n    BrotliDropBits(br, *bits);\n  }\n  PreloadSymbol(0, table, br, bits, value);\n  return result;\n}\n\nstatic BROTLI_INLINE brotli_reg_t Log2Floor(brotli_reg_t x) {\n  brotli_reg_t result = 0;\n  while (x) {\n    x >>= 1;\n    ++result;\n  }\n  return result;\n}\n\n/* Reads (s->symbol + 1) symbols.\n   Totally 1..4 symbols are read, 1..11 bits each.\n   The list of symbols MUST NOT contain duplicates. */\nstatic BrotliDecoderErrorCode ReadSimpleHuffmanSymbols(\n    brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,\n    BrotliDecoderState* s) {\n  /* max_bits == 1..11; symbol == 0..3; 1..44 bits will be read. */\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  brotli_reg_t max_bits = Log2Floor(alphabet_size_max - 1);\n  brotli_reg_t i = h->sub_loop_counter;\n  brotli_reg_t num_symbols = h->symbol;\n  while (i <= num_symbols) {\n    brotli_reg_t v;\n    if (BROTLI_PREDICT_FALSE(!BrotliSafeReadBits(br, max_bits, &v))) {\n      h->sub_loop_counter = i;\n      h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_READ;\n      return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    }\n    if (v >= alphabet_size_limit) {\n      return\n          BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET);\n    }\n    h->symbols_lists_array[i] = (uint16_t)v;\n    BROTLI_LOG_UINT(h->symbols_lists_array[i]);\n    ++i;\n  }\n\n  for (i = 0; i < num_symbols; ++i) {\n    brotli_reg_t k = i + 1;\n    for (; k <= num_symbols; ++k) {\n      if (h->symbols_lists_array[i] == h->symbols_lists_array[k]) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME);\n      }\n    }\n  }\n\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Process single decoded symbol code length:\n    A) reset the repeat variable\n    B) remember code length (if it is not 0)\n    C) extend corresponding index-chain\n    D) reduce the Huffman space\n    E) update the histogram */\nstatic BROTLI_INLINE void ProcessSingleCodeLength(brotli_reg_t code_len,\n    brotli_reg_t* symbol, brotli_reg_t* repeat, brotli_reg_t* space,\n    brotli_reg_t* prev_code_len, uint16_t* symbol_lists,\n    uint16_t* code_length_histo, int* next_symbol) {\n  *repeat = 0;\n  if (code_len != 0) {  /* code_len == 1..15 */\n    symbol_lists[next_symbol[code_len]] = (uint16_t)(*symbol);\n    next_symbol[code_len] = (int)(*symbol);\n    *prev_code_len = code_len;\n    *space -= 32768U >> code_len;\n    code_length_histo[code_len]++;\n    BROTLI_LOG((\"[ReadHuffmanCode] code_length[%d] = %d\\n\",\n        (int)*symbol, (int)code_len));\n  }\n  (*symbol)++;\n}\n\n/* Process repeated symbol code length.\n    A) Check if it is the extension of previous repeat sequence; if the decoded\n       value is not BROTLI_REPEAT_PREVIOUS_CODE_LENGTH, then it is a new\n       symbol-skip\n    B) Update repeat variable\n    C) Check if operation is feasible (fits alphabet)\n    D) For each symbol do the same operations as in ProcessSingleCodeLength\n\n   PRECONDITION: code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH or\n                 code_len == BROTLI_REPEAT_ZERO_CODE_LENGTH */\nstatic BROTLI_INLINE void ProcessRepeatedCodeLength(brotli_reg_t code_len,\n    brotli_reg_t repeat_delta, brotli_reg_t alphabet_size, brotli_reg_t* symbol,\n    brotli_reg_t* repeat, brotli_reg_t* space, brotli_reg_t* prev_code_len,\n    brotli_reg_t* repeat_code_len, uint16_t* symbol_lists,\n    uint16_t* code_length_histo, int* next_symbol) {\n  brotli_reg_t old_repeat;\n  brotli_reg_t extra_bits = 3;  /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */\n  brotli_reg_t new_len = 0;  /* for BROTLI_REPEAT_ZERO_CODE_LENGTH */\n  if (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {\n    new_len = *prev_code_len;\n    extra_bits = 2;\n  }\n  if (*repeat_code_len != new_len) {\n    *repeat = 0;\n    *repeat_code_len = new_len;\n  }\n  old_repeat = *repeat;\n  if (*repeat > 0) {\n    *repeat -= 2;\n    *repeat <<= extra_bits;\n  }\n  *repeat += repeat_delta + 3U;\n  repeat_delta = *repeat - old_repeat;\n  if (*symbol + repeat_delta > alphabet_size) {\n    BROTLI_DUMP();\n    *symbol = alphabet_size;\n    *space = 0xFFFFF;\n    return;\n  }\n  BROTLI_LOG((\"[ReadHuffmanCode] code_length[%d..%d] = %d\\n\",\n      (int)*symbol, (int)(*symbol + repeat_delta - 1), (int)*repeat_code_len));\n  if (*repeat_code_len != 0) {\n    brotli_reg_t last = *symbol + repeat_delta;\n    int next = next_symbol[*repeat_code_len];\n    do {\n      symbol_lists[next] = (uint16_t)*symbol;\n      next = (int)*symbol;\n    } while (++(*symbol) != last);\n    next_symbol[*repeat_code_len] = next;\n    *space -= repeat_delta << (15 - *repeat_code_len);\n    code_length_histo[*repeat_code_len] =\n        (uint16_t)(code_length_histo[*repeat_code_len] + repeat_delta);\n  } else {\n    *symbol += repeat_delta;\n  }\n}\n\n/* Reads and decodes symbol codelengths. */\nstatic BrotliDecoderErrorCode ReadSymbolCodeLengths(\n    brotli_reg_t alphabet_size, BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  brotli_reg_t symbol = h->symbol;\n  brotli_reg_t repeat = h->repeat;\n  brotli_reg_t space = h->space;\n  brotli_reg_t prev_code_len = h->prev_code_len;\n  brotli_reg_t repeat_code_len = h->repeat_code_len;\n  uint16_t* symbol_lists = h->symbol_lists;\n  uint16_t* code_length_histo = h->code_length_histo;\n  int* next_symbol = h->next_symbol;\n  if (!BrotliWarmupBitReader(br)) {\n    return BROTLI_DECODER_NEEDS_MORE_INPUT;\n  }\n  while (symbol < alphabet_size && space > 0) {\n    const HuffmanCode* p = h->table;\n    brotli_reg_t code_len;\n    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);\n    if (!BrotliCheckInputAmount(br)) {\n      h->symbol = symbol;\n      h->repeat = repeat;\n      h->prev_code_len = prev_code_len;\n      h->repeat_code_len = repeat_code_len;\n      h->space = space;\n      return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    }\n    BrotliFillBitWindow16(br);\n    BROTLI_HC_ADJUST_TABLE_INDEX(p, BrotliGetBitsUnmasked(br) &\n        BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));\n    BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));  /* Use 1..5 bits. */\n    code_len = BROTLI_HC_FAST_LOAD_VALUE(p);  /* code_len == 0..17 */\n    if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {\n      ProcessSingleCodeLength(code_len, &symbol, &repeat, &space,\n          &prev_code_len, symbol_lists, code_length_histo, next_symbol);\n    } else {  /* code_len == 16..17, extra_bits == 2..3 */\n      brotli_reg_t extra_bits =\n          (code_len == BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) ? 2 : 3;\n      brotli_reg_t repeat_delta =\n          BrotliGetBitsUnmasked(br) & BitMask(extra_bits);\n      BrotliDropBits(br, extra_bits);\n      ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,\n          &symbol, &repeat, &space, &prev_code_len, &repeat_code_len,\n          symbol_lists, code_length_histo, next_symbol);\n    }\n  }\n  h->space = space;\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic BrotliDecoderErrorCode SafeReadSymbolCodeLengths(\n    brotli_reg_t alphabet_size, BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  BROTLI_BOOL get_byte = BROTLI_FALSE;\n  while (h->symbol < alphabet_size && h->space > 0) {\n    const HuffmanCode* p = h->table;\n    brotli_reg_t code_len;\n    brotli_reg_t available_bits;\n    brotli_reg_t bits = 0;\n    BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(p);\n    if (get_byte && !BrotliPullByte(br)) return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    get_byte = BROTLI_FALSE;\n    available_bits = BrotliGetAvailableBits(br);\n    if (available_bits != 0) {\n      bits = (uint32_t)BrotliGetBitsUnmasked(br);\n    }\n    BROTLI_HC_ADJUST_TABLE_INDEX(p,\n        bits & BitMask(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH));\n    if (BROTLI_HC_FAST_LOAD_BITS(p) > available_bits) {\n      get_byte = BROTLI_TRUE;\n      continue;\n    }\n    code_len = BROTLI_HC_FAST_LOAD_VALUE(p);  /* code_len == 0..17 */\n    if (code_len < BROTLI_REPEAT_PREVIOUS_CODE_LENGTH) {\n      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p));\n      ProcessSingleCodeLength(code_len, &h->symbol, &h->repeat, &h->space,\n          &h->prev_code_len, h->symbol_lists, h->code_length_histo,\n          h->next_symbol);\n    } else {  /* code_len == 16..17, extra_bits == 2..3 */\n      brotli_reg_t extra_bits = code_len - 14U;\n      brotli_reg_t repeat_delta = (bits >> BROTLI_HC_FAST_LOAD_BITS(p)) &\n          BitMask(extra_bits);\n      if (available_bits < BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits) {\n        get_byte = BROTLI_TRUE;\n        continue;\n      }\n      BrotliDropBits(br, BROTLI_HC_FAST_LOAD_BITS(p) + extra_bits);\n      ProcessRepeatedCodeLength(code_len, repeat_delta, alphabet_size,\n          &h->symbol, &h->repeat, &h->space, &h->prev_code_len,\n          &h->repeat_code_len, h->symbol_lists, h->code_length_histo,\n          h->next_symbol);\n    }\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Reads and decodes 15..18 codes using static prefix code.\n   Each code is 2..4 bits long. In total 30..72 bits are used. */\nstatic BrotliDecoderErrorCode ReadCodeLengthCodeLengths(BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  brotli_reg_t num_codes = h->repeat;\n  brotli_reg_t space = h->space;\n  brotli_reg_t i = h->sub_loop_counter;\n  for (; i < BROTLI_CODE_LENGTH_CODES; ++i) {\n    const uint8_t code_len_idx = kCodeLengthCodeOrder[i];\n    brotli_reg_t ix;\n    brotli_reg_t v;\n    if (BROTLI_PREDICT_FALSE(!BrotliSafeGetBits(br, 4, &ix))) {\n      brotli_reg_t available_bits = BrotliGetAvailableBits(br);\n      if (available_bits != 0) {\n        ix = BrotliGetBitsUnmasked(br) & 0xF;\n      } else {\n        ix = 0;\n      }\n      if (kCodeLengthPrefixLength[ix] > available_bits) {\n        h->sub_loop_counter = i;\n        h->repeat = num_codes;\n        h->space = space;\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n    }\n    v = kCodeLengthPrefixValue[ix];\n    BrotliDropBits(br, kCodeLengthPrefixLength[ix]);\n    h->code_length_code_lengths[code_len_idx] = (uint8_t)v;\n    BROTLI_LOG_ARRAY_INDEX(h->code_length_code_lengths, code_len_idx);\n    if (v != 0) {\n      space = space - (32U >> v);\n      ++num_codes;\n      ++h->code_length_histo[v];\n      if (space - 1U >= 32U) {\n        /* space is 0 or wrapped around. */\n        break;\n      }\n    }\n  }\n  if (!(num_codes == 1 || space == 0)) {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CL_SPACE);\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Decodes the Huffman tables.\n   There are 2 scenarios:\n    A) Huffman code contains only few symbols (1..4). Those symbols are read\n       directly; their code lengths are defined by the number of symbols.\n       For this scenario 4 - 49 bits will be read.\n\n    B) 2-phase decoding:\n    B.1) Small Huffman table is decoded; it is specified with code lengths\n         encoded with predefined entropy code. 32 - 74 bits are used.\n    B.2) Decoded table is used to decode code lengths of symbols in resulting\n         Huffman table. In worst case 3520 bits are read. */\nstatic BrotliDecoderErrorCode ReadHuffmanCode(brotli_reg_t alphabet_size_max,\n                                              brotli_reg_t alphabet_size_limit,\n                                              HuffmanCode* table,\n                                              brotli_reg_t* opt_table_size,\n                                              BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  /* State machine. */\n  for (;;) {\n    switch (h->substate_huffman) {\n      case BROTLI_STATE_HUFFMAN_NONE:\n        if (!BrotliSafeReadBits(br, 2, &h->sub_loop_counter)) {\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        BROTLI_LOG_UINT(h->sub_loop_counter);\n        /* The value is used as follows:\n           1 for simple code;\n           0 for no skipping, 2 skips 2 code lengths, 3 skips 3 code lengths */\n        if (h->sub_loop_counter != 1) {\n          h->space = 32;\n          h->repeat = 0;  /* num_codes */\n          memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo[0]) *\n              (BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1));\n          memset(&h->code_length_code_lengths[0], 0,\n              sizeof(h->code_length_code_lengths));\n          h->substate_huffman = BROTLI_STATE_HUFFMAN_COMPLEX;\n          continue;\n        }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_SIMPLE_SIZE:\n        /* Read symbols, codes & code lengths directly. */\n        if (!BrotliSafeReadBits(br, 2, &h->symbol)) {  /* num_symbols */\n          h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_SIZE;\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        h->sub_loop_counter = 0;\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_SIMPLE_READ: {\n        BrotliDecoderErrorCode result =\n            ReadSimpleHuffmanSymbols(alphabet_size_max, alphabet_size_limit, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_SIMPLE_BUILD: {\n        brotli_reg_t table_size;\n        if (h->symbol == 3) {\n          brotli_reg_t bits;\n          if (!BrotliSafeReadBits(br, 1, &bits)) {\n            h->substate_huffman = BROTLI_STATE_HUFFMAN_SIMPLE_BUILD;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          h->symbol += bits;\n        }\n        BROTLI_LOG_UINT(h->symbol);\n        table_size = BrotliBuildSimpleHuffmanTable(table, HUFFMAN_TABLE_BITS,\n                                                   h->symbols_lists_array,\n                                                   (uint32_t)h->symbol);\n        if (opt_table_size) {\n          *opt_table_size = table_size;\n        }\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;\n        return BROTLI_DECODER_SUCCESS;\n      }\n\n      /* Decode Huffman-coded code lengths. */\n      case BROTLI_STATE_HUFFMAN_COMPLEX: {\n        brotli_reg_t i;\n        BrotliDecoderErrorCode result = ReadCodeLengthCodeLengths(s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n        BrotliBuildCodeLengthsHuffmanTable(h->table,\n                                           h->code_length_code_lengths,\n                                           h->code_length_histo);\n        memset(&h->code_length_histo[0], 0, sizeof(h->code_length_histo));\n        for (i = 0; i <= BROTLI_HUFFMAN_MAX_CODE_LENGTH; ++i) {\n          h->next_symbol[i] = (int)i - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);\n          h->symbol_lists[h->next_symbol[i]] = 0xFFFF;\n        }\n\n        h->symbol = 0;\n        h->prev_code_len = BROTLI_INITIAL_REPEATED_CODE_LENGTH;\n        h->repeat = 0;\n        h->repeat_code_len = 0;\n        h->space = 32768;\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS: {\n        brotli_reg_t table_size;\n        BrotliDecoderErrorCode result = ReadSymbolCodeLengths(\n            alphabet_size_limit, s);\n        if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {\n          result = SafeReadSymbolCodeLengths(alphabet_size_limit, s);\n        }\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n\n        if (h->space != 0) {\n          BROTLI_LOG((\"[ReadHuffmanCode] space = %d\\n\", (int)h->space));\n          return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE);\n        }\n        table_size = BrotliBuildHuffmanTable(\n            table, HUFFMAN_TABLE_BITS, h->symbol_lists, h->code_length_histo);\n        if (opt_table_size) {\n          *opt_table_size = table_size;\n        }\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;\n        return BROTLI_DECODER_SUCCESS;\n      }\n\n      default:\n        return\n            BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n    }\n  }\n}\n\n/* Decodes a block length by reading 3..39 bits. */\nstatic BROTLI_INLINE brotli_reg_t ReadBlockLength(const HuffmanCode* table,\n                                                  BrotliBitReader* br) {\n  brotli_reg_t code;\n  brotli_reg_t nbits;\n  code = ReadSymbol(table, br);\n  nbits = _kBrotliPrefixCodeRanges[code].nbits;  /* nbits == 2..24 */\n  return _kBrotliPrefixCodeRanges[code].offset + BrotliReadBits24(br, nbits);\n}\n\n/* WARNING: if state is not BROTLI_STATE_READ_BLOCK_LENGTH_NONE, then\n   reading can't be continued with ReadBlockLength. */\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadBlockLength(\n    BrotliDecoderState* s, brotli_reg_t* result, const HuffmanCode* table,\n    BrotliBitReader* br) {\n  brotli_reg_t index;\n  if (s->substate_read_block_length == BROTLI_STATE_READ_BLOCK_LENGTH_NONE) {\n    if (!SafeReadSymbol(table, br, &index)) {\n      return BROTLI_FALSE;\n    }\n  } else {\n    index = s->block_length_index;\n  }\n  {\n    brotli_reg_t bits;\n    brotli_reg_t nbits = _kBrotliPrefixCodeRanges[index].nbits;\n    brotli_reg_t offset = _kBrotliPrefixCodeRanges[index].offset;\n    if (!BrotliSafeReadBits(br, nbits, &bits)) {\n      s->block_length_index = index;\n      s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX;\n      return BROTLI_FALSE;\n    }\n    *result = offset + bits;\n    s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;\n    return BROTLI_TRUE;\n  }\n}\n\n/* Transform:\n    1) initialize list L with values 0, 1,... 255\n    2) For each input element X:\n    2.1) let Y = L[X]\n    2.2) remove X-th element from L\n    2.3) prepend Y to L\n    2.4) append Y to output\n\n   In most cases max(Y) <= 7, so most of L remains intact.\n   To reduce the cost of initialization, we reuse L, remember the upper bound\n   of Y values, and reinitialize only first elements in L.\n\n   Most of input values are 0 and 1. To reduce number of branches, we replace\n   inner for loop with do-while. */\nstatic BROTLI_NOINLINE void InverseMoveToFrontTransform(\n    uint8_t* v, brotli_reg_t v_len, BrotliDecoderState* state) {\n  /* Reinitialize elements that could have been changed. */\n  brotli_reg_t i = 1;\n  brotli_reg_t upper_bound = state->mtf_upper_bound;\n  uint32_t* mtf = &state->mtf[1];  /* Make mtf[-1] addressable. */\n  uint8_t* mtf_u8 = (uint8_t*)mtf;\n  /* Load endian-aware constant. */\n  const uint8_t b0123[4] = {0, 1, 2, 3};\n  uint32_t pattern;\n  memcpy(&pattern, &b0123, 4);\n\n  /* Initialize list using 4 consequent values pattern. */\n  mtf[0] = pattern;\n  do {\n    pattern += 0x04040404;  /* Advance all 4 values by 4. */\n    mtf[i] = pattern;\n    i++;\n  } while (i <= upper_bound);\n\n  /* Transform the input. */\n  upper_bound = 0;\n  for (i = 0; i < v_len; ++i) {\n    int index = v[i];\n    uint8_t value = mtf_u8[index];\n    upper_bound |= v[i];\n    v[i] = value;\n    mtf_u8[-1] = value;\n    do {\n      index--;\n      mtf_u8[index + 1] = mtf_u8[index];\n    } while (index >= 0);\n  }\n  /* Remember amount of elements to be reinitialized. */\n  state->mtf_upper_bound = upper_bound >> 2;\n}\n\n/* Decodes a series of Huffman table using ReadHuffmanCode function. */\nstatic BrotliDecoderErrorCode HuffmanTreeGroupDecode(\n    HuffmanTreeGroup* group, BrotliDecoderState* s) {\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n  if (h->substate_tree_group != BROTLI_STATE_TREE_GROUP_LOOP) {\n    h->next = group->codes;\n    h->htree_index = 0;\n    h->substate_tree_group = BROTLI_STATE_TREE_GROUP_LOOP;\n  }\n  while (h->htree_index < group->num_htrees) {\n    brotli_reg_t table_size;\n    BrotliDecoderErrorCode result = ReadHuffmanCode(group->alphabet_size_max,\n        group->alphabet_size_limit, h->next, &table_size, s);\n    if (result != BROTLI_DECODER_SUCCESS) return result;\n    group->htrees[h->htree_index] = h->next;\n    h->next += table_size;\n    ++h->htree_index;\n  }\n  h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;\n  return BROTLI_DECODER_SUCCESS;\n}\n\n/* Decodes a context map.\n   Decoding is done in 4 phases:\n    1) Read auxiliary information (6..16 bits) and allocate memory.\n       In case of trivial context map, decoding is finished at this phase.\n    2) Decode Huffman table using ReadHuffmanCode function.\n       This table will be used for reading context map items.\n    3) Read context map items; \"0\" values could be run-length encoded.\n    4) Optionally, apply InverseMoveToFront transform to the resulting map. */\nstatic BrotliDecoderErrorCode DecodeContextMap(brotli_reg_t context_map_size,\n                                               brotli_reg_t* num_htrees,\n                                               uint8_t** context_map_arg,\n                                               BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;\n  BrotliMetablockHeaderArena* h = &s->arena.header;\n\n  switch ((int)h->substate_context_map) {\n    case BROTLI_STATE_CONTEXT_MAP_NONE:\n      result = DecodeVarLenUint8(s, br, num_htrees);\n      if (result != BROTLI_DECODER_SUCCESS) {\n        return result;\n      }\n      (*num_htrees)++;\n      h->context_index = 0;\n      BROTLI_LOG_UINT(context_map_size);\n      BROTLI_LOG_UINT(*num_htrees);\n      *context_map_arg =\n          (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)context_map_size);\n      if (*context_map_arg == 0) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP);\n      }\n      if (*num_htrees <= 1) {\n        memset(*context_map_arg, 0, (size_t)context_map_size);\n        return BROTLI_DECODER_SUCCESS;\n      }\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_READ_PREFIX;\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_READ_PREFIX: {\n      brotli_reg_t bits;\n      /* In next stage ReadHuffmanCode uses at least 4 bits, so it is safe\n         to peek 4 bits ahead. */\n      if (!BrotliSafeGetBits(br, 5, &bits)) {\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if ((bits & 1) != 0) { /* Use RLE for zeros. */\n        h->max_run_length_prefix = (bits >> 1) + 1;\n        BrotliDropBits(br, 5);\n      } else {\n        h->max_run_length_prefix = 0;\n        BrotliDropBits(br, 1);\n      }\n      BROTLI_LOG_UINT(h->max_run_length_prefix);\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_HUFFMAN;\n    }\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_HUFFMAN: {\n      brotli_reg_t alphabet_size = *num_htrees + h->max_run_length_prefix;\n      result = ReadHuffmanCode(alphabet_size, alphabet_size,\n                               h->context_map_table, NULL, s);\n      if (result != BROTLI_DECODER_SUCCESS) return result;\n      h->code = 0xFFFF;\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_DECODE;\n    }\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_DECODE: {\n      brotli_reg_t context_index = h->context_index;\n      brotli_reg_t max_run_length_prefix = h->max_run_length_prefix;\n      uint8_t* context_map = *context_map_arg;\n      brotli_reg_t code = h->code;\n      BROTLI_BOOL skip_preamble = (code != 0xFFFF);\n      while (context_index < context_map_size || skip_preamble) {\n        if (!skip_preamble) {\n          if (!SafeReadSymbol(h->context_map_table, br, &code)) {\n            h->code = 0xFFFF;\n            h->context_index = context_index;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          BROTLI_LOG_UINT(code);\n\n          if (code == 0) {\n            context_map[context_index++] = 0;\n            continue;\n          }\n          if (code > max_run_length_prefix) {\n            context_map[context_index++] =\n                (uint8_t)(code - max_run_length_prefix);\n            continue;\n          }\n        } else {\n          skip_preamble = BROTLI_FALSE;\n        }\n        /* RLE sub-stage. */\n        {\n          brotli_reg_t reps;\n          if (!BrotliSafeReadBits(br, code, &reps)) {\n            h->code = code;\n            h->context_index = context_index;\n            return BROTLI_DECODER_NEEDS_MORE_INPUT;\n          }\n          reps += 1U << code;\n          BROTLI_LOG_UINT(reps);\n          if (context_index + reps > context_map_size) {\n            return\n                BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT);\n          }\n          do {\n            context_map[context_index++] = 0;\n          } while (--reps);\n        }\n      }\n    }\n    /* Fall through. */\n\n    case BROTLI_STATE_CONTEXT_MAP_TRANSFORM: {\n      brotli_reg_t bits;\n      if (!BrotliSafeReadBits(br, 1, &bits)) {\n        h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_TRANSFORM;\n        return BROTLI_DECODER_NEEDS_MORE_INPUT;\n      }\n      if (bits != 0) {\n        InverseMoveToFrontTransform(*context_map_arg, context_map_size, s);\n      }\n      h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;\n      return BROTLI_DECODER_SUCCESS;\n    }\n\n    default:\n      return\n          BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n  }\n}\n\n/* Decodes a command or literal and updates block type ring-buffer.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeBlockTypeAndLength(\n    int safe, BrotliDecoderState* s, int tree_type) {\n  brotli_reg_t max_block_type = s->num_block_types[tree_type];\n  const HuffmanCode* type_tree = &s->block_type_trees[\n      tree_type * BROTLI_HUFFMAN_MAX_SIZE_258];\n  const HuffmanCode* len_tree = &s->block_len_trees[\n      tree_type * BROTLI_HUFFMAN_MAX_SIZE_26];\n  BrotliBitReader* br = &s->br;\n  brotli_reg_t* ringbuffer = &s->block_type_rb[tree_type * 2];\n  brotli_reg_t block_type;\n  if (max_block_type <= 1) {\n    return BROTLI_FALSE;\n  }\n\n  /* Read 0..15 + 3..39 bits. */\n  if (!safe) {\n    block_type = ReadSymbol(type_tree, br);\n    s->block_length[tree_type] = ReadBlockLength(len_tree, br);\n  } else {\n    BrotliBitReaderState memento;\n    BrotliBitReaderSaveState(br, &memento);\n    if (!SafeReadSymbol(type_tree, br, &block_type)) return BROTLI_FALSE;\n    if (!SafeReadBlockLength(s, &s->block_length[tree_type], len_tree, br)) {\n      s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;\n      BrotliBitReaderRestoreState(br, &memento);\n      return BROTLI_FALSE;\n    }\n  }\n\n  if (block_type == 1) {\n    block_type = ringbuffer[1] + 1;\n  } else if (block_type == 0) {\n    block_type = ringbuffer[0];\n  } else {\n    block_type -= 2;\n  }\n  if (block_type >= max_block_type) {\n    block_type -= max_block_type;\n  }\n  ringbuffer[0] = ringbuffer[1];\n  ringbuffer[1] = block_type;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void DetectTrivialLiteralBlockTypes(\n    BrotliDecoderState* s) {\n  size_t i;\n  for (i = 0; i < 8; ++i) s->trivial_literal_contexts[i] = 0;\n  for (i = 0; i < s->num_block_types[0]; i++) {\n    size_t offset = i << BROTLI_LITERAL_CONTEXT_BITS;\n    size_t error = 0;\n    size_t sample = s->context_map[offset];\n    size_t j;\n    for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS);) {\n      /* NOLINTNEXTLINE(bugprone-macro-repeated-side-effects) */\n      BROTLI_REPEAT_4({ error |= s->context_map[offset + j++] ^ sample; })\n    }\n    if (error == 0) {\n      s->trivial_literal_contexts[i >> 5] |= 1u << (i & 31);\n    }\n  }\n}\n\nstatic BROTLI_INLINE void PrepareLiteralDecoding(BrotliDecoderState* s) {\n  uint8_t context_mode;\n  size_t trivial;\n  brotli_reg_t block_type = s->block_type_rb[1];\n  brotli_reg_t context_offset = block_type << BROTLI_LITERAL_CONTEXT_BITS;\n  s->context_map_slice = s->context_map + context_offset;\n  trivial = s->trivial_literal_contexts[block_type >> 5];\n  s->trivial_literal_context = (trivial >> (block_type & 31)) & 1;\n  s->literal_htree = s->literal_hgroup.htrees[s->context_map_slice[0]];\n  context_mode = s->context_modes[block_type] & 3;\n  s->context_lookup = BROTLI_CONTEXT_LUT(context_mode);\n}\n\n/* Decodes the block type and updates the state for literal context.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeLiteralBlockSwitchInternal(\n    int safe, BrotliDecoderState* s) {\n  if (!DecodeBlockTypeAndLength(safe, s, 0)) {\n    return BROTLI_FALSE;\n  }\n  PrepareLiteralDecoding(s);\n  return BROTLI_TRUE;\n}\n\nstatic void BROTLI_NOINLINE DecodeLiteralBlockSwitch(BrotliDecoderState* s) {\n  DecodeLiteralBlockSwitchInternal(0, s);\n}\n\nstatic BROTLI_BOOL BROTLI_NOINLINE SafeDecodeLiteralBlockSwitch(\n    BrotliDecoderState* s) {\n  return DecodeLiteralBlockSwitchInternal(1, s);\n}\n\n/* Block switch for insert/copy length.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeCommandBlockSwitchInternal(\n    int safe, BrotliDecoderState* s) {\n  if (!DecodeBlockTypeAndLength(safe, s, 1)) {\n    return BROTLI_FALSE;\n  }\n  s->htree_command = s->insert_copy_hgroup.htrees[s->block_type_rb[3]];\n  return BROTLI_TRUE;\n}\n\nstatic void BROTLI_NOINLINE DecodeCommandBlockSwitch(BrotliDecoderState* s) {\n  DecodeCommandBlockSwitchInternal(0, s);\n}\n\nstatic BROTLI_BOOL BROTLI_NOINLINE SafeDecodeCommandBlockSwitch(\n    BrotliDecoderState* s) {\n  return DecodeCommandBlockSwitchInternal(1, s);\n}\n\n/* Block switch for distance codes.\n   Reads 3..54 bits. */\nstatic BROTLI_INLINE BROTLI_BOOL DecodeDistanceBlockSwitchInternal(\n    int safe, BrotliDecoderState* s) {\n  if (!DecodeBlockTypeAndLength(safe, s, 2)) {\n    return BROTLI_FALSE;\n  }\n  s->dist_context_map_slice = s->dist_context_map +\n      (s->block_type_rb[5] << BROTLI_DISTANCE_CONTEXT_BITS);\n  s->dist_htree_index = s->dist_context_map_slice[s->distance_context];\n  return BROTLI_TRUE;\n}\n\nstatic void BROTLI_NOINLINE DecodeDistanceBlockSwitch(BrotliDecoderState* s) {\n  DecodeDistanceBlockSwitchInternal(0, s);\n}\n\nstatic BROTLI_BOOL BROTLI_NOINLINE SafeDecodeDistanceBlockSwitch(\n    BrotliDecoderState* s) {\n  return DecodeDistanceBlockSwitchInternal(1, s);\n}\n\nstatic size_t UnwrittenBytes(const BrotliDecoderState* s, BROTLI_BOOL wrap) {\n  size_t pos = wrap && s->pos > s->ringbuffer_size ?\n      (size_t)s->ringbuffer_size : (size_t)(s->pos);\n  size_t partial_pos_rb = (s->rb_roundtrips * (size_t)s->ringbuffer_size) + pos;\n  return partial_pos_rb - s->partial_pos_out;\n}\n\n/* Dumps output.\n   Returns BROTLI_DECODER_NEEDS_MORE_OUTPUT only if there is more output to push\n   and either ring-buffer is as big as window size, or |force| is true. */\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE WriteRingBuffer(\n    BrotliDecoderState* s, size_t* available_out, uint8_t** next_out,\n    size_t* total_out, BROTLI_BOOL force) {\n  uint8_t* start =\n      s->ringbuffer + (s->partial_pos_out & (size_t)s->ringbuffer_mask);\n  size_t to_write = UnwrittenBytes(s, BROTLI_TRUE);\n  size_t num_written = *available_out;\n  if (num_written > to_write) {\n    num_written = to_write;\n  }\n  if (s->meta_block_remaining_len < 0) {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1);\n  }\n  if (next_out && !*next_out) {\n    *next_out = start;\n  } else {\n    if (next_out) {\n      memcpy(*next_out, start, num_written);\n      *next_out += num_written;\n    }\n  }\n  *available_out -= num_written;\n  BROTLI_LOG_UINT(to_write);\n  BROTLI_LOG_UINT(num_written);\n  s->partial_pos_out += num_written;\n  if (total_out) {\n    *total_out = s->partial_pos_out;\n  }\n  if (num_written < to_write) {\n    if (s->ringbuffer_size == (1 << s->window_bits) || force) {\n      return BROTLI_DECODER_NEEDS_MORE_OUTPUT;\n    } else {\n      return BROTLI_DECODER_SUCCESS;\n    }\n  }\n  /* Wrap ring buffer only if it has reached its maximal size. */\n  if (s->ringbuffer_size == (1 << s->window_bits) &&\n      s->pos >= s->ringbuffer_size) {\n    s->pos -= s->ringbuffer_size;\n    s->rb_roundtrips++;\n    s->should_wrap_ringbuffer = (size_t)s->pos != 0 ? 1 : 0;\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic void BROTLI_NOINLINE WrapRingBuffer(BrotliDecoderState* s) {\n  if (s->should_wrap_ringbuffer) {\n    memcpy(s->ringbuffer, s->ringbuffer_end, (size_t)s->pos);\n    s->should_wrap_ringbuffer = 0;\n  }\n}\n\n/* Allocates ring-buffer.\n\n   s->ringbuffer_size MUST be updated by BrotliCalculateRingBufferSize before\n   this function is called.\n\n   Last two bytes of ring-buffer are initialized to 0, so context calculation\n   could be done uniformly for the first two and all other positions. */\nstatic BROTLI_BOOL BROTLI_NOINLINE BrotliEnsureRingBuffer(\n    BrotliDecoderState* s) {\n  uint8_t* old_ringbuffer = s->ringbuffer;\n  if (s->ringbuffer_size == s->new_ringbuffer_size) {\n    return BROTLI_TRUE;\n  }\n\n  s->ringbuffer = (uint8_t*)BROTLI_DECODER_ALLOC(s,\n      (size_t)(s->new_ringbuffer_size) + kRingBufferWriteAheadSlack);\n  if (s->ringbuffer == 0) {\n    /* Restore previous value. */\n    s->ringbuffer = old_ringbuffer;\n    return BROTLI_FALSE;\n  }\n  s->ringbuffer[s->new_ringbuffer_size - 2] = 0;\n  s->ringbuffer[s->new_ringbuffer_size - 1] = 0;\n\n  if (!!old_ringbuffer) {\n    memcpy(s->ringbuffer, old_ringbuffer, (size_t)s->pos);\n    BROTLI_DECODER_FREE(s, old_ringbuffer);\n  }\n\n  s->ringbuffer_size = s->new_ringbuffer_size;\n  s->ringbuffer_mask = s->new_ringbuffer_size - 1;\n  s->ringbuffer_end = s->ringbuffer + s->ringbuffer_size;\n\n  return BROTLI_TRUE;\n}\n\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE\nSkipMetadataBlock(BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n\n  if (s->meta_block_remaining_len == 0) {\n    return BROTLI_DECODER_SUCCESS;\n  }\n\n  BROTLI_DCHECK((BrotliGetAvailableBits(br) & 7) == 0);\n\n  /* Drain accumulator. */\n  if (BrotliGetAvailableBits(br) >= 8) {\n    uint8_t buffer[8];\n    int nbytes = (int)(BrotliGetAvailableBits(br)) >> 3;\n    BROTLI_DCHECK(nbytes <= 8);\n    if (nbytes > s->meta_block_remaining_len) {\n      nbytes = s->meta_block_remaining_len;\n    }\n    BrotliCopyBytes(buffer, br, (size_t)nbytes);\n    if (s->metadata_chunk_func) {\n      s->metadata_chunk_func(s->metadata_callback_opaque, buffer,\n                             (size_t)nbytes);\n    }\n    s->meta_block_remaining_len -= nbytes;\n    if (s->meta_block_remaining_len == 0) {\n      return BROTLI_DECODER_SUCCESS;\n    }\n  }\n\n  /* Direct access to metadata is possible. */\n  int nbytes = (int)BrotliGetRemainingBytes(br);\n  if (nbytes > s->meta_block_remaining_len) {\n    nbytes = s->meta_block_remaining_len;\n  }\n  if (nbytes > 0) {\n    if (s->metadata_chunk_func) {\n      s->metadata_chunk_func(s->metadata_callback_opaque, br->next_in,\n                             (size_t)nbytes);\n    }\n    BrotliDropBytes(br, (size_t)nbytes);\n    s->meta_block_remaining_len -= nbytes;\n    if (s->meta_block_remaining_len == 0) {\n      return BROTLI_DECODER_SUCCESS;\n    }\n  }\n\n  BROTLI_DCHECK(BrotliGetRemainingBytes(br) == 0);\n\n  return BROTLI_DECODER_NEEDS_MORE_INPUT;\n}\n\nstatic BrotliDecoderErrorCode BROTLI_NOINLINE CopyUncompressedBlockToOutput(\n    size_t* available_out, uint8_t** next_out, size_t* total_out,\n    BrotliDecoderState* s) {\n  /* TODO(eustas): avoid allocation for single uncompressed block. */\n  if (!BrotliEnsureRingBuffer(s)) {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1);\n  }\n\n  /* State machine */\n  for (;;) {\n    switch (s->substate_uncompressed) {\n      case BROTLI_STATE_UNCOMPRESSED_NONE: {\n        int nbytes = (int)BrotliGetRemainingBytes(&s->br);\n        if (nbytes > s->meta_block_remaining_len) {\n          nbytes = s->meta_block_remaining_len;\n        }\n        if (s->pos + nbytes > s->ringbuffer_size) {\n          nbytes = s->ringbuffer_size - s->pos;\n        }\n        /* Copy remaining bytes from s->br.buf_ to ring-buffer. */\n        BrotliCopyBytes(&s->ringbuffer[s->pos], &s->br, (size_t)nbytes);\n        s->pos += nbytes;\n        s->meta_block_remaining_len -= nbytes;\n        if (s->pos < 1 << s->window_bits) {\n          if (s->meta_block_remaining_len == 0) {\n            return BROTLI_DECODER_SUCCESS;\n          }\n          return BROTLI_DECODER_NEEDS_MORE_INPUT;\n        }\n        s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_WRITE;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_UNCOMPRESSED_WRITE: {\n        BrotliDecoderErrorCode result;\n        result = WriteRingBuffer(\n            s, available_out, next_out, total_out, BROTLI_FALSE);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          return result;\n        }\n        if (s->ringbuffer_size == 1 << s->window_bits) {\n          s->max_distance = s->max_backward_distance;\n        }\n        s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;\n        break;\n      }\n    }\n  }\n  BROTLI_DCHECK(0);  /* Unreachable */\n}\n\nstatic BROTLI_BOOL AttachCompoundDictionary(\n    BrotliDecoderState* state, const uint8_t* data, size_t size) {\n  BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;\n  if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;\n  if (!addon) {\n    addon = (BrotliDecoderCompoundDictionary*)BROTLI_DECODER_ALLOC(\n        state, sizeof(BrotliDecoderCompoundDictionary));\n    if (!addon) return BROTLI_FALSE;\n    addon->num_chunks = 0;\n    addon->total_size = 0;\n    addon->br_length = 0;\n    addon->br_copied = 0;\n    addon->block_bits = -1;\n    addon->chunk_offsets[0] = 0;\n    state->compound_dictionary = addon;\n  }\n  if (addon->num_chunks == 15) return BROTLI_FALSE;\n  addon->chunks[addon->num_chunks] = data;\n  addon->num_chunks++;\n  addon->total_size += (int)size;\n  addon->chunk_offsets[addon->num_chunks] = addon->total_size;\n  return BROTLI_TRUE;\n}\n\nstatic void EnsureCoumpoundDictionaryInitialized(BrotliDecoderState* state) {\n  BrotliDecoderCompoundDictionary* addon = state->compound_dictionary;\n  /* 256 = (1 << 8) slots in block map. */\n  int block_bits = 8;\n  int cursor = 0;\n  int index = 0;\n  if (addon->block_bits != -1) return;\n  while (((addon->total_size - 1) >> block_bits) != 0) block_bits++;\n  block_bits -= 8;\n  addon->block_bits = block_bits;\n  while (cursor < addon->total_size) {\n    while (addon->chunk_offsets[index + 1] < cursor) index++;\n    addon->block_map[cursor >> block_bits] = (uint8_t)index;\n    cursor += 1 << block_bits;\n  }\n}\n\nstatic BROTLI_BOOL InitializeCompoundDictionaryCopy(BrotliDecoderState* s,\n    int address, int length) {\n  BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;\n  int index;\n  EnsureCoumpoundDictionaryInitialized(s);\n  index = addon->block_map[address >> addon->block_bits];\n  while (address >= addon->chunk_offsets[index + 1]) index++;\n  if (addon->total_size < address + length) return BROTLI_FALSE;\n  /* Update the recent distances cache. */\n  s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;\n  ++s->dist_rb_idx;\n  s->meta_block_remaining_len -= length;\n  addon->br_index = index;\n  addon->br_offset = address - addon->chunk_offsets[index];\n  addon->br_length = length;\n  addon->br_copied = 0;\n  return BROTLI_TRUE;\n}\n\nstatic int GetCompoundDictionarySize(BrotliDecoderState* s) {\n  return s->compound_dictionary ? s->compound_dictionary->total_size : 0;\n}\n\nstatic int CopyFromCompoundDictionary(BrotliDecoderState* s, int pos) {\n  BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;\n  int orig_pos = pos;\n  while (addon->br_length != addon->br_copied) {\n    uint8_t* copy_dst = &s->ringbuffer[pos];\n    const uint8_t* copy_src =\n        addon->chunks[addon->br_index] + addon->br_offset;\n    int space = s->ringbuffer_size - pos;\n    int rem_chunk_length = (addon->chunk_offsets[addon->br_index + 1] -\n        addon->chunk_offsets[addon->br_index]) - addon->br_offset;\n    int length = addon->br_length - addon->br_copied;\n    if (length > rem_chunk_length) length = rem_chunk_length;\n    if (length > space) length = space;\n    memcpy(copy_dst, copy_src, (size_t)length);\n    pos += length;\n    addon->br_offset += length;\n    addon->br_copied += length;\n    if (length == rem_chunk_length) {\n      addon->br_index++;\n      addon->br_offset = 0;\n    }\n    if (pos == s->ringbuffer_size) break;\n  }\n  return pos - orig_pos;\n}\n\nBROTLI_BOOL BrotliDecoderAttachDictionary(\n    BrotliDecoderState* state, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]) {\n  brotli_reg_t i;\n  brotli_reg_t num_prefix_before = state->dictionary->num_prefix;\n  if (state->state != BROTLI_STATE_UNINITED) return BROTLI_FALSE;\n  if (!BrotliSharedDictionaryAttach(state->dictionary, type, data_size, data)) {\n    return BROTLI_FALSE;\n  }\n  for (i = num_prefix_before; i < state->dictionary->num_prefix; i++) {\n    if (!AttachCompoundDictionary(\n        state, state->dictionary->prefix[i],\n        state->dictionary->prefix_size[i])) {\n      return BROTLI_FALSE;\n    }\n  }\n  return BROTLI_TRUE;\n}\n\n/* Calculates the smallest feasible ring buffer.\n\n   If we know the data size is small, do not allocate more ring buffer\n   size than needed to reduce memory usage.\n\n   When this method is called, metablock size and flags MUST be decoded. */\nstatic void BROTLI_NOINLINE BrotliCalculateRingBufferSize(\n    BrotliDecoderState* s) {\n  int window_size = 1 << s->window_bits;\n  int new_ringbuffer_size = window_size;\n  /* We need at least 2 bytes of ring buffer size to get the last two\n     bytes for context from there */\n  int min_size = s->ringbuffer_size ? s->ringbuffer_size : 1024;\n  int output_size;\n\n  /* If maximum is already reached, no further extension is retired. */\n  if (s->ringbuffer_size == window_size) {\n    return;\n  }\n\n  /* Metadata blocks does not touch ring buffer. */\n  if (s->is_metadata) {\n    return;\n  }\n\n  if (!s->ringbuffer) {\n    output_size = 0;\n  } else {\n    output_size = s->pos;\n  }\n  output_size += s->meta_block_remaining_len;\n  min_size = min_size < output_size ? output_size : min_size;\n\n  if (!!s->canny_ringbuffer_allocation) {\n    /* Reduce ring buffer size to save memory when server is unscrupulous.\n       In worst case memory usage might be 1.5x bigger for a short period of\n       ring buffer reallocation. */\n    while ((new_ringbuffer_size >> 1) >= min_size) {\n      new_ringbuffer_size >>= 1;\n    }\n  }\n\n  s->new_ringbuffer_size = new_ringbuffer_size;\n}\n\n/* Reads 1..256 2-bit context modes. */\nstatic BrotliDecoderErrorCode ReadContextModes(BrotliDecoderState* s) {\n  BrotliBitReader* br = &s->br;\n  int i = s->loop_counter;\n\n  while (i < (int)s->num_block_types[0]) {\n    brotli_reg_t bits;\n    if (!BrotliSafeReadBits(br, 2, &bits)) {\n      s->loop_counter = i;\n      return BROTLI_DECODER_NEEDS_MORE_INPUT;\n    }\n    s->context_modes[i] = (uint8_t)bits;\n    BROTLI_LOG_ARRAY_INDEX(s->context_modes, i);\n    i++;\n  }\n  return BROTLI_DECODER_SUCCESS;\n}\n\nstatic BROTLI_INLINE void TakeDistanceFromRingBuffer(BrotliDecoderState* s) {\n  int offset = s->distance_code - 3;\n  if (s->distance_code <= 3) {\n    /* Compensate double distance-ring-buffer roll for dictionary items. */\n    s->distance_context = 1 >> s->distance_code;\n    s->distance_code = s->dist_rb[(s->dist_rb_idx - offset) & 3];\n    s->dist_rb_idx -= s->distance_context;\n  } else {\n    int index_delta = 3;\n    int delta;\n    int base = s->distance_code - 10;\n    if (s->distance_code < 10) {\n      base = s->distance_code - 4;\n    } else {\n      index_delta = 2;\n    }\n    /* Unpack one of six 4-bit values. */\n    delta = ((0x605142 >> (4 * base)) & 0xF) - 3;\n    s->distance_code = s->dist_rb[(s->dist_rb_idx + index_delta) & 0x3] + delta;\n    if (s->distance_code <= 0) {\n      /* A huge distance will cause a BROTLI_FAILURE() soon.\n         This is a little faster than failing here. */\n      s->distance_code = 0x7FFFFFFF;\n    }\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadBits(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  if (n_bits != 0) {\n    return BrotliSafeReadBits(br, n_bits, val);\n  } else {\n    *val = 0;\n    return BROTLI_TRUE;\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadBits32(\n    BrotliBitReader* const br, brotli_reg_t n_bits, brotli_reg_t* val) {\n  if (n_bits != 0) {\n    return BrotliSafeReadBits32(br, n_bits, val);\n  } else {\n    *val = 0;\n    return BROTLI_TRUE;\n  }\n}\n\n/*\n   RFC 7932 Section 4 with \"...\" shortenings and \"[]\" emendations.\n\n   Each distance ... is represented with a pair <distance code, extra bits>...\n   The distance code is encoded using a prefix code... The number of extra bits\n   can be 0..24... Two additional parameters: NPOSTFIX (0..3), and ...\n   NDIRECT (0..120) ... are encoded in the meta-block header...\n\n   The first 16 distance symbols ... reference past distances... ring buffer ...\n   Next NDIRECT distance symbols ... represent distances from 1 to NDIRECT...\n   [For] distance symbols 16 + NDIRECT and greater ... the number of extra bits\n   ... is given by the following formula:\n\n   [ xcode = dcode - NDIRECT - 16 ]\n   ndistbits = 1 + [ xcode ] >> (NPOSTFIX + 1)\n\n   ...\n*/\n\n/*\n   RFC 7932 Section 9.2 with \"...\" shortenings and \"[]\" emendations.\n\n   ... to get the actual value of the parameter NDIRECT, left-shift this\n   four-bit number by NPOSTFIX bits ...\n*/\n\n/* Remaining formulas from RFC 7932 Section 4 could be rewritten as following:\n\n     alphabet_size = 16 + NDIRECT + (max_distbits << (NPOSTFIX + 1))\n\n     half = ((xcode >> NPOSTFIX) & 1) << ndistbits\n     postfix = xcode & ((1 << NPOSTFIX) - 1)\n     range_start = 2 * (1 << ndistbits - 1 - 1)\n\n     distance = (range_start + half + extra) << NPOSTFIX + postfix + NDIRECT + 1\n\n   NB: ndistbits >= 1 -> range_start >= 0\n   NB: range_start has factor 2, as the range is covered by 2 \"halves\"\n   NB: extra -1 offset in range_start formula covers the absence of\n       ndistbits = 0 case\n   NB: when NPOSTFIX = 0, NDIRECT is not greater than 15\n\n   In other words, xcode has the following binary structure - XXXHPPP:\n    - XXX represent the number of extra distance bits\n    - H selects upper / lower range of distances\n    - PPP represent \"postfix\"\n\n  \"Regular\" distance encoding has NPOSTFIX = 0; omitting the postfix part\n  simplifies distance calculation.\n\n  Using NPOSTFIX > 0 allows cheaper encoding of regular structures, e.g. where\n  most of distances have the same reminder of division by 2/4/8. For example,\n  the table of int32_t values that come from different sources; if it is likely\n  that 3 highest bytes of values from the same source are the same, then\n  copy distance often looks like 4x + y.\n\n  Distance calculation could be rewritten to:\n\n    ndistbits = NDISTBITS(NDIRECT, NPOSTFIX)[dcode]\n    distance = OFFSET(NDIRECT, NPOSTFIX)[dcode] + extra << NPOSTFIX\n\n  NDISTBITS and OFFSET could be pre-calculated, as NDIRECT and NPOSTFIX could\n  change only once per meta-block.\n*/\n\n/* Calculates distance lookup table.\n   NB: it is possible to have all 64 tables precalculated. */\nstatic void CalculateDistanceLut(BrotliDecoderState* s) {\n  BrotliMetablockBodyArena* b = &s->arena.body;\n  brotli_reg_t npostfix = s->distance_postfix_bits;\n  brotli_reg_t ndirect = s->num_direct_distance_codes;\n  brotli_reg_t alphabet_size_limit = s->distance_hgroup.alphabet_size_limit;\n  brotli_reg_t postfix = 1u << npostfix;\n  brotli_reg_t j;\n  brotli_reg_t bits = 1;\n  brotli_reg_t half = 0;\n\n  /* Skip short codes. */\n  brotli_reg_t i = BROTLI_NUM_DISTANCE_SHORT_CODES;\n\n  /* Fill direct codes. */\n  for (j = 0; j < ndirect; ++j) {\n    b->dist_extra_bits[i] = 0;\n    b->dist_offset[i] = j + 1;\n    ++i;\n  }\n\n  /* Fill regular distance codes. */\n  while (i < alphabet_size_limit) {\n    brotli_reg_t base = ndirect + ((((2 + half) << bits) - 4) << npostfix) + 1;\n    /* Always fill the complete group. */\n    for (j = 0; j < postfix; ++j) {\n      b->dist_extra_bits[i] = (uint8_t)bits;\n      b->dist_offset[i] = base + j;\n      ++i;\n    }\n    bits = bits + half;\n    half = half ^ 1;\n  }\n}\n\n/* Precondition: s->distance_code < 0. */\nstatic BROTLI_INLINE BROTLI_BOOL ReadDistanceInternal(\n    int safe, BrotliDecoderState* s, BrotliBitReader* br) {\n  BrotliMetablockBodyArena* b = &s->arena.body;\n  brotli_reg_t code;\n  brotli_reg_t bits;\n  BrotliBitReaderState memento;\n  HuffmanCode* distance_tree = s->distance_hgroup.htrees[s->dist_htree_index];\n  if (!safe) {\n    code = ReadSymbol(distance_tree, br);\n  } else {\n    BrotliBitReaderSaveState(br, &memento);\n    if (!SafeReadSymbol(distance_tree, br, &code)) {\n      return BROTLI_FALSE;\n    }\n  }\n  --s->block_length[2];\n  /* Convert the distance code to the actual distance by possibly\n     looking up past distances from the s->dist_rb. */\n  s->distance_context = 0;\n  if ((code & ~0xFu) == 0) {\n    s->distance_code = (int)code;\n    TakeDistanceFromRingBuffer(s);\n    return BROTLI_TRUE;\n  }\n  if (!safe) {\n    bits = BrotliReadBits32(br, b->dist_extra_bits[code]);\n  } else {\n    if (!SafeReadBits32(br, b->dist_extra_bits[code], &bits)) {\n      ++s->block_length[2];\n      BrotliBitReaderRestoreState(br, &memento);\n      return BROTLI_FALSE;\n    }\n  }\n  s->distance_code =\n      (int)(b->dist_offset[code] + (bits << s->distance_postfix_bits));\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void ReadDistance(\n    BrotliDecoderState* s, BrotliBitReader* br) {\n  ReadDistanceInternal(0, s, br);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadDistance(\n    BrotliDecoderState* s, BrotliBitReader* br) {\n  return ReadDistanceInternal(1, s, br);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL ReadCommandInternal(\n    int safe, BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {\n  brotli_reg_t cmd_code;\n  brotli_reg_t insert_len_extra = 0;\n  brotli_reg_t copy_length;\n  CmdLutElement v;\n  BrotliBitReaderState memento;\n  if (!safe) {\n    cmd_code = ReadSymbol(s->htree_command, br);\n  } else {\n    BrotliBitReaderSaveState(br, &memento);\n    if (!SafeReadSymbol(s->htree_command, br, &cmd_code)) {\n      return BROTLI_FALSE;\n    }\n  }\n  v = kCmdLut[cmd_code];\n  s->distance_code = v.distance_code;\n  s->distance_context = v.context;\n  s->dist_htree_index = s->dist_context_map_slice[s->distance_context];\n  *insert_length = v.insert_len_offset;\n  if (!safe) {\n    if (BROTLI_PREDICT_FALSE(v.insert_len_extra_bits != 0)) {\n      insert_len_extra = BrotliReadBits24(br, v.insert_len_extra_bits);\n    }\n    copy_length = BrotliReadBits24(br, v.copy_len_extra_bits);\n  } else {\n    if (!SafeReadBits(br, v.insert_len_extra_bits, &insert_len_extra) ||\n        !SafeReadBits(br, v.copy_len_extra_bits, &copy_length)) {\n      BrotliBitReaderRestoreState(br, &memento);\n      return BROTLI_FALSE;\n    }\n  }\n  s->copy_length = (int)copy_length + v.copy_len_offset;\n  --s->block_length[1];\n  *insert_length += (int)insert_len_extra;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void ReadCommand(\n    BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {\n  ReadCommandInternal(0, s, br, insert_length);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SafeReadCommand(\n    BrotliDecoderState* s, BrotliBitReader* br, int* insert_length) {\n  return ReadCommandInternal(1, s, br, insert_length);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL CheckInputAmount(\n    int safe, BrotliBitReader* const br) {\n  if (safe) {\n    return BROTLI_TRUE;\n  }\n  return BrotliCheckInputAmount(br);\n}\n\n#define BROTLI_SAFE(METHOD)                       \\\n  {                                               \\\n    if (safe) {                                   \\\n      if (!Safe##METHOD) {                        \\\n        result = BROTLI_DECODER_NEEDS_MORE_INPUT; \\\n        goto saveStateAndReturn;                  \\\n      }                                           \\\n    } else {                                      \\\n      METHOD;                                     \\\n    }                                             \\\n  }\n\nstatic BROTLI_INLINE BrotliDecoderErrorCode ProcessCommandsInternal(\n    int safe, BrotliDecoderState* s) {\n  int pos = s->pos;\n  int i = s->loop_counter;\n  BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;\n  BrotliBitReader* br = &s->br;\n  int compound_dictionary_size = GetCompoundDictionarySize(s);\n\n  if (!CheckInputAmount(safe, br)) {\n    result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n    goto saveStateAndReturn;\n  }\n  if (!safe) {\n    BROTLI_UNUSED(BrotliWarmupBitReader(br));\n  }\n\n  /* Jump into state machine. */\n  if (s->state == BROTLI_STATE_COMMAND_BEGIN) {\n    goto CommandBegin;\n  } else if (s->state == BROTLI_STATE_COMMAND_INNER) {\n    goto CommandInner;\n  } else if (s->state == BROTLI_STATE_COMMAND_POST_DECODE_LITERALS) {\n    goto CommandPostDecodeLiterals;\n  } else if (s->state == BROTLI_STATE_COMMAND_POST_WRAP_COPY) {\n    goto CommandPostWrapCopy;\n  } else {\n    return BROTLI_FAILURE(BROTLI_DECODER_ERROR_UNREACHABLE);  /* COV_NF_LINE */\n  }\n\nCommandBegin:\n  if (safe) {\n    s->state = BROTLI_STATE_COMMAND_BEGIN;\n  }\n  if (!CheckInputAmount(safe, br)) {\n    s->state = BROTLI_STATE_COMMAND_BEGIN;\n    result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n    goto saveStateAndReturn;\n  }\n  if (BROTLI_PREDICT_FALSE(s->block_length[1] == 0)) {\n    BROTLI_SAFE(DecodeCommandBlockSwitch(s));\n    goto CommandBegin;\n  }\n  /* Read the insert/copy length in the command. */\n  BROTLI_SAFE(ReadCommand(s, br, &i));\n  BROTLI_LOG((\"[ProcessCommandsInternal] pos = %d insert = %d copy = %d\\n\",\n              pos, i, s->copy_length));\n  if (i == 0) {\n    goto CommandPostDecodeLiterals;\n  }\n  s->meta_block_remaining_len -= i;\n\nCommandInner:\n  if (safe) {\n    s->state = BROTLI_STATE_COMMAND_INNER;\n  }\n  /* Read the literals in the command. */\n  if (s->trivial_literal_context) {\n    brotli_reg_t bits;\n    brotli_reg_t value;\n    PreloadSymbol(safe, s->literal_htree, br, &bits, &value);\n    do {\n      if (!CheckInputAmount(safe, br)) {\n        s->state = BROTLI_STATE_COMMAND_INNER;\n        result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n        goto saveStateAndReturn;\n      }\n      if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {\n        goto NextLiteralBlock;\n      }\n      if (!safe) {\n        s->ringbuffer[pos] =\n            (uint8_t)ReadPreloadedSymbol(s->literal_htree, br, &bits, &value);\n      } else {\n        brotli_reg_t literal;\n        if (!SafeReadSymbol(s->literal_htree, br, &literal)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          goto saveStateAndReturn;\n        }\n        s->ringbuffer[pos] = (uint8_t)literal;\n      }\n      --s->block_length[0];\n      BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos);\n      ++pos;\n      if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {\n        s->state = BROTLI_STATE_COMMAND_INNER_WRITE;\n        --i;\n        goto saveStateAndReturn;\n      }\n    } while (--i != 0);\n  } else {\n    uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];\n    uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];\n    do {\n      const HuffmanCode* hc;\n      uint8_t context;\n      if (!CheckInputAmount(safe, br)) {\n        s->state = BROTLI_STATE_COMMAND_INNER;\n        result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n        goto saveStateAndReturn;\n      }\n      if (BROTLI_PREDICT_FALSE(s->block_length[0] == 0)) {\n        goto NextLiteralBlock;\n      }\n      context = BROTLI_CONTEXT(p1, p2, s->context_lookup);\n      BROTLI_LOG_UINT(context);\n      hc = s->literal_hgroup.htrees[s->context_map_slice[context]];\n      p2 = p1;\n      if (!safe) {\n        p1 = (uint8_t)ReadSymbol(hc, br);\n      } else {\n        brotli_reg_t literal;\n        if (!SafeReadSymbol(hc, br, &literal)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          goto saveStateAndReturn;\n        }\n        p1 = (uint8_t)literal;\n      }\n      s->ringbuffer[pos] = p1;\n      --s->block_length[0];\n      BROTLI_LOG_UINT(s->context_map_slice[context]);\n      BROTLI_LOG_ARRAY_INDEX(s->ringbuffer, pos & s->ringbuffer_mask);\n      ++pos;\n      if (BROTLI_PREDICT_FALSE(pos == s->ringbuffer_size)) {\n        s->state = BROTLI_STATE_COMMAND_INNER_WRITE;\n        --i;\n        goto saveStateAndReturn;\n      }\n    } while (--i != 0);\n  }\n  BROTLI_LOG_UINT(s->meta_block_remaining_len);\n  if (BROTLI_PREDICT_FALSE(s->meta_block_remaining_len <= 0)) {\n    s->state = BROTLI_STATE_METABLOCK_DONE;\n    goto saveStateAndReturn;\n  }\n\nCommandPostDecodeLiterals:\n  if (safe) {\n    s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;\n  }\n  if (s->distance_code >= 0) {\n    /* Implicit distance case. */\n    s->distance_context = s->distance_code ? 0 : 1;\n    --s->dist_rb_idx;\n    s->distance_code = s->dist_rb[s->dist_rb_idx & 3];\n  } else {\n    /* Read distance code in the command, unless it was implicitly zero. */\n    if (BROTLI_PREDICT_FALSE(s->block_length[2] == 0)) {\n      BROTLI_SAFE(DecodeDistanceBlockSwitch(s));\n    }\n    BROTLI_SAFE(ReadDistance(s, br));\n  }\n  BROTLI_LOG((\"[ProcessCommandsInternal] pos = %d distance = %d\\n\",\n              pos, s->distance_code));\n  if (s->max_distance != s->max_backward_distance) {\n    s->max_distance =\n        (pos < s->max_backward_distance) ? pos : s->max_backward_distance;\n  }\n  i = s->copy_length;\n  /* Apply copy of LZ77 back-reference, or static dictionary reference if\n     the distance is larger than the max LZ77 distance */\n  if (s->distance_code > s->max_distance) {\n    /* The maximum allowed distance is BROTLI_MAX_ALLOWED_DISTANCE = 0x7FFFFFFC.\n       With this choice, no signed overflow can occur after decoding\n       a special distance code (e.g., after adding 3 to the last distance). */\n    if (s->distance_code > BROTLI_MAX_ALLOWED_DISTANCE) {\n      BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n          \"len: %d bytes left: %d\\n\",\n          pos, s->distance_code, i, s->meta_block_remaining_len));\n      return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DISTANCE);\n    }\n    if (s->distance_code - s->max_distance - 1 < compound_dictionary_size) {\n      int address = compound_dictionary_size -\n          (s->distance_code - s->max_distance);\n      if (!InitializeCompoundDictionaryCopy(s, address, i)) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_COMPOUND_DICTIONARY);\n      }\n      pos += CopyFromCompoundDictionary(s, pos);\n      if (pos >= s->ringbuffer_size) {\n        s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;\n        goto saveStateAndReturn;\n      }\n    } else if (i >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH &&\n               i <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH) {\n      uint8_t p1 = s->ringbuffer[(pos - 1) & s->ringbuffer_mask];\n      uint8_t p2 = s->ringbuffer[(pos - 2) & s->ringbuffer_mask];\n      uint8_t dict_id = s->dictionary->context_based ?\n          s->dictionary->context_map[BROTLI_CONTEXT(p1, p2, s->context_lookup)]\n          : 0;\n      const BrotliDictionary* words = s->dictionary->words[dict_id];\n      const BrotliTransforms* transforms = s->dictionary->transforms[dict_id];\n      int offset = (int)words->offsets_by_length[i];\n      brotli_reg_t shift = words->size_bits_by_length[i];\n      int address =\n          s->distance_code - s->max_distance - 1 - compound_dictionary_size;\n      int mask = (int)BitMask(shift);\n      int word_idx = address & mask;\n      int transform_idx = address >> shift;\n      /* Compensate double distance-ring-buffer roll. */\n      s->dist_rb_idx += s->distance_context;\n      offset += word_idx * i;\n      /* If the distance is out of bound, select a next static dictionary if\n         there exist multiple. */\n      if ((transform_idx >= (int)transforms->num_transforms ||\n          words->size_bits_by_length[i] == 0) &&\n          s->dictionary->num_dictionaries > 1) {\n        uint8_t dict_id2;\n        int dist_remaining = address -\n            (int)(((1u << shift) & ~1u)) * (int)transforms->num_transforms;\n        for (dict_id2 = 0; dict_id2 < s->dictionary->num_dictionaries;\n            dict_id2++) {\n          const BrotliDictionary* words2 = s->dictionary->words[dict_id2];\n          if (dict_id2 != dict_id && words2->size_bits_by_length[i] != 0) {\n            const BrotliTransforms* transforms2 =\n                s->dictionary->transforms[dict_id2];\n            brotli_reg_t shift2 = words2->size_bits_by_length[i];\n            int num = (int)((1u << shift2) & ~1u) *\n                (int)transforms2->num_transforms;\n            if (dist_remaining < num) {\n              dict_id = dict_id2;\n              words = words2;\n              transforms = transforms2;\n              address = dist_remaining;\n              shift = shift2;\n              mask = (int)BitMask(shift);\n              word_idx = address & mask;\n              transform_idx = address >> shift;\n              offset = (int)words->offsets_by_length[i] + word_idx * i;\n              break;\n            }\n            dist_remaining -= num;\n          }\n        }\n      }\n      if (BROTLI_PREDICT_FALSE(words->size_bits_by_length[i] == 0)) {\n        BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n            \"len: %d bytes left: %d\\n\",\n            pos, s->distance_code, i, s->meta_block_remaining_len));\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);\n      }\n      if (BROTLI_PREDICT_FALSE(!words->data)) {\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET);\n      }\n      if (transform_idx < (int)transforms->num_transforms) {\n        const uint8_t* word = &words->data[offset];\n        int len = i;\n        if (transform_idx == transforms->cutOffTransforms[0]) {\n          memcpy(&s->ringbuffer[pos], word, (size_t)len);\n          BROTLI_LOG((\"[ProcessCommandsInternal] dictionary word: [%.*s]\\n\",\n                      len, word));\n        } else {\n          len = BrotliTransformDictionaryWord(&s->ringbuffer[pos], word, len,\n              transforms, transform_idx);\n          BROTLI_LOG((\"[ProcessCommandsInternal] dictionary word: [%.*s],\"\n                      \" transform_idx = %d, transformed: [%.*s]\\n\",\n                      i, word, transform_idx, len, &s->ringbuffer[pos]));\n          if (len == 0 && s->distance_code <= 120) {\n            BROTLI_LOG((\"Invalid length-0 dictionary word after transform\\n\"));\n            return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);\n          }\n        }\n        pos += len;\n        s->meta_block_remaining_len -= len;\n        if (pos >= s->ringbuffer_size) {\n          s->state = BROTLI_STATE_COMMAND_POST_WRITE_1;\n          goto saveStateAndReturn;\n        }\n      } else {\n        BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n            \"len: %d bytes left: %d\\n\",\n            pos, s->distance_code, i, s->meta_block_remaining_len));\n        return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_TRANSFORM);\n      }\n    } else {\n      BROTLI_LOG((\"Invalid backward reference. pos: %d distance: %d \"\n          \"len: %d bytes left: %d\\n\",\n          pos, s->distance_code, i, s->meta_block_remaining_len));\n      return BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_DICTIONARY);\n    }\n  } else {\n    int src_start = (pos - s->distance_code) & s->ringbuffer_mask;\n    uint8_t* copy_dst = &s->ringbuffer[pos];\n    uint8_t* copy_src = &s->ringbuffer[src_start];\n    int dst_end = pos + i;\n    int src_end = src_start + i;\n    /* Update the recent distances cache. */\n    s->dist_rb[s->dist_rb_idx & 3] = s->distance_code;\n    ++s->dist_rb_idx;\n    s->meta_block_remaining_len -= i;\n    /* There are 32+ bytes of slack in the ring-buffer allocation.\n       Also, we have 16 short codes, that make these 16 bytes irrelevant\n       in the ring-buffer. Let's copy over them as a first guess. */\n    memmove16(copy_dst, copy_src);\n    if (src_end > pos && dst_end > src_start) {\n      /* Regions intersect. */\n      goto CommandPostWrapCopy;\n    }\n    if (dst_end >= s->ringbuffer_size || src_end >= s->ringbuffer_size) {\n      /* At least one region wraps. */\n      goto CommandPostWrapCopy;\n    }\n    pos += i;\n    if (i > 16) {\n      if (i > 32) {\n        memcpy(copy_dst + 16, copy_src + 16, (size_t)(i - 16));\n      } else {\n        /* This branch covers about 45% cases.\n           Fixed size short copy allows more compiler optimizations. */\n        memmove16(copy_dst + 16, copy_src + 16);\n      }\n    }\n  }\n  BROTLI_LOG_UINT(s->meta_block_remaining_len);\n  if (s->meta_block_remaining_len <= 0) {\n    /* Next metablock, if any. */\n    s->state = BROTLI_STATE_METABLOCK_DONE;\n    goto saveStateAndReturn;\n  } else {\n    goto CommandBegin;\n  }\nCommandPostWrapCopy:\n  {\n    int wrap_guard = s->ringbuffer_size - pos;\n    while (--i >= 0) {\n      s->ringbuffer[pos] =\n          s->ringbuffer[(pos - s->distance_code) & s->ringbuffer_mask];\n      ++pos;\n      if (BROTLI_PREDICT_FALSE(--wrap_guard == 0)) {\n        s->state = BROTLI_STATE_COMMAND_POST_WRITE_2;\n        goto saveStateAndReturn;\n      }\n    }\n  }\n  if (s->meta_block_remaining_len <= 0) {\n    /* Next metablock, if any. */\n    s->state = BROTLI_STATE_METABLOCK_DONE;\n    goto saveStateAndReturn;\n  } else {\n    goto CommandBegin;\n  }\n\nNextLiteralBlock:\n  BROTLI_SAFE(DecodeLiteralBlockSwitch(s));\n  goto CommandInner;\n\nsaveStateAndReturn:\n  s->pos = pos;\n  s->loop_counter = i;\n  return result;\n}\n\n#undef BROTLI_SAFE\n\nstatic BROTLI_NOINLINE BrotliDecoderErrorCode ProcessCommands(\n    BrotliDecoderState* s) {\n  return ProcessCommandsInternal(0, s);\n}\n\nstatic BROTLI_NOINLINE BrotliDecoderErrorCode SafeProcessCommands(\n    BrotliDecoderState* s) {\n  return ProcessCommandsInternal(1, s);\n}\n\nBrotliDecoderResult BrotliDecoderDecompress(\n    size_t encoded_size,\n    const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],\n    size_t* decoded_size,\n    uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]) {\n  BrotliDecoderState s;\n  BrotliDecoderResult result;\n  size_t total_out = 0;\n  size_t available_in = encoded_size;\n  const uint8_t* next_in = encoded_buffer;\n  size_t available_out = *decoded_size;\n  uint8_t* next_out = decoded_buffer;\n  if (!BrotliDecoderStateInit(&s, 0, 0, 0)) {\n    return BROTLI_DECODER_RESULT_ERROR;\n  }\n  result = BrotliDecoderDecompressStream(\n      &s, &available_in, &next_in, &available_out, &next_out, &total_out);\n  *decoded_size = total_out;\n  BrotliDecoderStateCleanup(&s);\n  if (result != BROTLI_DECODER_RESULT_SUCCESS) {\n    result = BROTLI_DECODER_RESULT_ERROR;\n  }\n  return result;\n}\n\n/* Invariant: input stream is never overconsumed:\n    - invalid input implies that the whole stream is invalid -> any amount of\n      input could be read and discarded\n    - when result is \"needs more input\", then at least one more byte is REQUIRED\n      to complete decoding; all input data MUST be consumed by decoder, so\n      client could swap the input buffer\n    - when result is \"needs more output\" decoder MUST ensure that it doesn't\n      hold more than 7 bits in bit reader; this saves client from swapping input\n      buffer ahead of time\n    - when result is \"success\" decoder MUST return all unused data back to input\n      buffer; this is possible because the invariant is held on enter */\nBrotliDecoderResult BrotliDecoderDecompressStream(\n    BrotliDecoderState* s, size_t* available_in, const uint8_t** next_in,\n    size_t* available_out, uint8_t** next_out, size_t* total_out) {\n  BrotliDecoderErrorCode result = BROTLI_DECODER_SUCCESS;\n  BrotliBitReader* br = &s->br;\n  size_t input_size = *available_in;\n#define BROTLI_SAVE_ERROR_CODE(code) \\\n    SaveErrorCode(s, (code), input_size - *available_in)\n  /* Ensure that |total_out| is set, even if no data will ever be pushed out. */\n  if (total_out) {\n    *total_out = s->partial_pos_out;\n  }\n  /* Do not try to process further in a case of unrecoverable error. */\n  if ((int)s->error_code < 0) {\n    return BROTLI_DECODER_RESULT_ERROR;\n  }\n  if (*available_out && (!next_out || !*next_out)) {\n    return BROTLI_SAVE_ERROR_CODE(\n        BROTLI_FAILURE(BROTLI_DECODER_ERROR_INVALID_ARGUMENTS));\n  }\n  if (!*available_out) next_out = 0;\n  if (s->buffer_length == 0) {  /* Just connect bit reader to input stream. */\n    BrotliBitReaderSetInput(br, *next_in, *available_in);\n  } else {\n    /* At least one byte of input is required. More than one byte of input may\n       be required to complete the transaction -> reading more data must be\n       done in a loop -> do it in a main loop. */\n    result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n    BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length);\n  }\n  /* State machine */\n  for (;;) {\n    if (result != BROTLI_DECODER_SUCCESS) {\n      /* Error, needs more input/output. */\n      if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {\n        if (s->ringbuffer != 0) {  /* Pro-actively push output. */\n          BrotliDecoderErrorCode intermediate_result = WriteRingBuffer(s,\n              available_out, next_out, total_out, BROTLI_TRUE);\n          /* WriteRingBuffer checks s->meta_block_remaining_len validity. */\n          if ((int)intermediate_result < 0) {\n            result = intermediate_result;\n            break;\n          }\n        }\n        if (s->buffer_length != 0) {  /* Used with internal buffer. */\n          if (br->next_in == br->last_in) {\n            /* Successfully finished read transaction.\n               Accumulator contains less than 8 bits, because internal buffer\n               is expanded byte-by-byte until it is enough to complete read. */\n            s->buffer_length = 0;\n            /* Switch to input stream and restart. */\n            result = BROTLI_DECODER_SUCCESS;\n            BrotliBitReaderSetInput(br, *next_in, *available_in);\n            continue;\n          } else if (*available_in != 0) {\n            /* Not enough data in buffer, but can take one more byte from\n               input stream. */\n            result = BROTLI_DECODER_SUCCESS;\n            BROTLI_DCHECK(s->buffer_length < 8);\n            s->buffer.u8[s->buffer_length] = **next_in;\n            s->buffer_length++;\n            BrotliBitReaderSetInput(br, &s->buffer.u8[0], s->buffer_length);\n            (*next_in)++;\n            (*available_in)--;\n            /* Retry with more data in buffer. */\n            continue;\n          }\n          /* Can't finish reading and no more input. */\n          break;\n        } else {  /* Input stream doesn't contain enough input. */\n          /* Copy tail to internal buffer and return. */\n          *next_in = br->next_in;\n          *available_in = BrotliBitReaderGetAvailIn(br);\n          while (*available_in) {\n            s->buffer.u8[s->buffer_length] = **next_in;\n            s->buffer_length++;\n            (*next_in)++;\n            (*available_in)--;\n          }\n          break;\n        }\n        /* Unreachable. */\n      }\n\n      /* Fail or needs more output. */\n\n      if (s->buffer_length != 0) {\n        /* Just consumed the buffered input and produced some output. Otherwise\n           it would result in \"needs more input\". Reset internal buffer. */\n        s->buffer_length = 0;\n      } else {\n        /* Using input stream in last iteration. When decoder switches to input\n           stream it has less than 8 bits in accumulator, so it is safe to\n           return unused accumulator bits there. */\n        BrotliBitReaderUnload(br);\n        *available_in = BrotliBitReaderGetAvailIn(br);\n        *next_in = br->next_in;\n      }\n      break;\n    }\n    switch (s->state) {\n      case BROTLI_STATE_UNINITED:\n        /* Prepare to the first read. */\n        if (!BrotliWarmupBitReader(br)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        /* Decode window size. */\n        result = DecodeWindowBits(s, br);  /* Reads 1..8 bits. */\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        if (s->large_window) {\n          s->state = BROTLI_STATE_LARGE_WINDOW_BITS;\n          break;\n        }\n        s->state = BROTLI_STATE_INITIALIZE;\n        break;\n\n      case BROTLI_STATE_LARGE_WINDOW_BITS: {\n        brotli_reg_t bits;\n        if (!BrotliSafeReadBits(br, 6, &bits)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        s->window_bits = bits & 63u;\n        if (s->window_bits < BROTLI_LARGE_MIN_WBITS ||\n            s->window_bits > BROTLI_LARGE_MAX_WBITS) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS);\n          break;\n        }\n        s->state = BROTLI_STATE_INITIALIZE;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_INITIALIZE:\n        BROTLI_LOG_UINT(s->window_bits);\n        /* Maximum distance, see section 9.1. of the spec. */\n        s->max_backward_distance = (1 << s->window_bits) - BROTLI_WINDOW_GAP;\n\n        /* Allocate memory for both block_type_trees and block_len_trees. */\n        s->block_type_trees = (HuffmanCode*)BROTLI_DECODER_ALLOC(s,\n            sizeof(HuffmanCode) * 3 *\n                (BROTLI_HUFFMAN_MAX_SIZE_258 + BROTLI_HUFFMAN_MAX_SIZE_26));\n        if (s->block_type_trees == 0) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES);\n          break;\n        }\n        s->block_len_trees =\n            s->block_type_trees + 3 * BROTLI_HUFFMAN_MAX_SIZE_258;\n\n        s->state = BROTLI_STATE_METABLOCK_BEGIN;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_BEGIN:\n        BrotliDecoderStateMetablockBegin(s);\n        BROTLI_LOG_UINT(s->pos);\n        s->state = BROTLI_STATE_METABLOCK_HEADER;\n      /* Fall through. */\n\n      case BROTLI_STATE_METABLOCK_HEADER:\n        result = DecodeMetaBlockLength(s, br);  /* Reads 2 - 31 bits. */\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        BROTLI_LOG_UINT(s->is_last_metablock);\n        BROTLI_LOG_UINT(s->meta_block_remaining_len);\n        BROTLI_LOG_UINT(s->is_metadata);\n        BROTLI_LOG_UINT(s->is_uncompressed);\n        if (s->is_metadata || s->is_uncompressed) {\n          if (!BrotliJumpToByteBoundary(br)) {\n            result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_1);\n            break;\n          }\n        }\n        if (s->is_metadata) {\n          s->state = BROTLI_STATE_METADATA;\n          if (s->metadata_start_func) {\n            s->metadata_start_func(s->metadata_callback_opaque,\n                                   (size_t)s->meta_block_remaining_len);\n          }\n          break;\n        }\n        if (s->meta_block_remaining_len == 0) {\n          s->state = BROTLI_STATE_METABLOCK_DONE;\n          break;\n        }\n        BrotliCalculateRingBufferSize(s);\n        if (s->is_uncompressed) {\n          s->state = BROTLI_STATE_UNCOMPRESSED;\n          break;\n        }\n        s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER;\n      /* Fall through. */\n\n      case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER: {\n        BrotliMetablockHeaderArena* h = &s->arena.header;\n        s->loop_counter = 0;\n        /* Initialize compressed metablock header arena. */\n        h->sub_loop_counter = 0;\n        /* Make small negative indexes addressable. */\n        h->symbol_lists =\n            &h->symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1];\n        h->substate_huffman = BROTLI_STATE_HUFFMAN_NONE;\n        h->substate_tree_group = BROTLI_STATE_TREE_GROUP_NONE;\n        h->substate_context_map = BROTLI_STATE_CONTEXT_MAP_NONE;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_0;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_0:\n        if (s->loop_counter >= 3) {\n          s->state = BROTLI_STATE_METABLOCK_HEADER_2;\n          break;\n        }\n        /* Reads 1..11 bits. */\n        result = DecodeVarLenUint8(s, br, &s->num_block_types[s->loop_counter]);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->num_block_types[s->loop_counter]++;\n        BROTLI_LOG_UINT(s->num_block_types[s->loop_counter]);\n        if (s->num_block_types[s->loop_counter] < 2) {\n          s->loop_counter++;\n          break;\n        }\n        s->state = BROTLI_STATE_HUFFMAN_CODE_1;\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_1: {\n        brotli_reg_t alphabet_size = s->num_block_types[s->loop_counter] + 2;\n        int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_258;\n        result = ReadHuffmanCode(alphabet_size, alphabet_size,\n            &s->block_type_trees[tree_offset], NULL, s);\n        if (result != BROTLI_DECODER_SUCCESS) break;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_2;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_2: {\n        brotli_reg_t alphabet_size = BROTLI_NUM_BLOCK_LEN_SYMBOLS;\n        int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;\n        result = ReadHuffmanCode(alphabet_size, alphabet_size,\n            &s->block_len_trees[tree_offset], NULL, s);\n        if (result != BROTLI_DECODER_SUCCESS) break;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_3;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_HUFFMAN_CODE_3: {\n        int tree_offset = s->loop_counter * BROTLI_HUFFMAN_MAX_SIZE_26;\n        if (!SafeReadBlockLength(s, &s->block_length[s->loop_counter],\n            &s->block_len_trees[tree_offset], br)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        BROTLI_LOG_UINT(s->block_length[s->loop_counter]);\n        s->loop_counter++;\n        s->state = BROTLI_STATE_HUFFMAN_CODE_0;\n        break;\n      }\n\n      case BROTLI_STATE_UNCOMPRESSED: {\n        result = CopyUncompressedBlockToOutput(\n            available_out, next_out, total_out, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->state = BROTLI_STATE_METABLOCK_DONE;\n        break;\n      }\n\n      case BROTLI_STATE_METADATA:\n        result = SkipMetadataBlock(s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->state = BROTLI_STATE_METABLOCK_DONE;\n        break;\n\n      case BROTLI_STATE_METABLOCK_HEADER_2: {\n        brotli_reg_t bits;\n        if (!BrotliSafeReadBits(br, 6, &bits)) {\n          result = BROTLI_DECODER_NEEDS_MORE_INPUT;\n          break;\n        }\n        s->distance_postfix_bits = bits & BitMask(2);\n        bits >>= 2;\n        s->num_direct_distance_codes = bits << s->distance_postfix_bits;\n        BROTLI_LOG_UINT(s->num_direct_distance_codes);\n        BROTLI_LOG_UINT(s->distance_postfix_bits);\n        s->context_modes =\n            (uint8_t*)BROTLI_DECODER_ALLOC(s, (size_t)s->num_block_types[0]);\n        if (s->context_modes == 0) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES);\n          break;\n        }\n        s->loop_counter = 0;\n        s->state = BROTLI_STATE_CONTEXT_MODES;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_CONTEXT_MODES:\n        result = ReadContextModes(s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        s->state = BROTLI_STATE_CONTEXT_MAP_1;\n      /* Fall through. */\n\n      case BROTLI_STATE_CONTEXT_MAP_1:\n        result = DecodeContextMap(\n            s->num_block_types[0] << BROTLI_LITERAL_CONTEXT_BITS,\n            &s->num_literal_htrees, &s->context_map, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        DetectTrivialLiteralBlockTypes(s);\n        s->state = BROTLI_STATE_CONTEXT_MAP_2;\n      /* Fall through. */\n\n      case BROTLI_STATE_CONTEXT_MAP_2: {\n        brotli_reg_t npostfix = s->distance_postfix_bits;\n        brotli_reg_t ndirect = s->num_direct_distance_codes;\n        brotli_reg_t distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n            npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);\n        brotli_reg_t distance_alphabet_size_limit = distance_alphabet_size_max;\n        BROTLI_BOOL allocation_success = BROTLI_TRUE;\n        if (s->large_window) {\n          BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(\n              BROTLI_MAX_ALLOWED_DISTANCE, (uint32_t)npostfix,\n              (uint32_t)ndirect);\n          distance_alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n              npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);\n          distance_alphabet_size_limit = limit.max_alphabet_size;\n        }\n        result = DecodeContextMap(\n            s->num_block_types[2] << BROTLI_DISTANCE_CONTEXT_BITS,\n            &s->num_dist_htrees, &s->dist_context_map, s);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        allocation_success &= BrotliDecoderHuffmanTreeGroupInit(\n            s, &s->literal_hgroup, BROTLI_NUM_LITERAL_SYMBOLS,\n            BROTLI_NUM_LITERAL_SYMBOLS, s->num_literal_htrees);\n        allocation_success &= BrotliDecoderHuffmanTreeGroupInit(\n            s, &s->insert_copy_hgroup, BROTLI_NUM_COMMAND_SYMBOLS,\n            BROTLI_NUM_COMMAND_SYMBOLS, s->num_block_types[1]);\n        allocation_success &= BrotliDecoderHuffmanTreeGroupInit(\n            s, &s->distance_hgroup, distance_alphabet_size_max,\n            distance_alphabet_size_limit, s->num_dist_htrees);\n        if (!allocation_success) {\n          return BROTLI_SAVE_ERROR_CODE(\n              BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS));\n        }\n        s->loop_counter = 0;\n        s->state = BROTLI_STATE_TREE_GROUP;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_TREE_GROUP: {\n        HuffmanTreeGroup* hgroup = NULL;\n        switch (s->loop_counter) {\n          case 0: hgroup = &s->literal_hgroup; break;\n          case 1: hgroup = &s->insert_copy_hgroup; break;\n          case 2: hgroup = &s->distance_hgroup; break;\n          default: return BROTLI_SAVE_ERROR_CODE(BROTLI_FAILURE(\n              BROTLI_DECODER_ERROR_UNREACHABLE));  /* COV_NF_LINE */\n        }\n        result = HuffmanTreeGroupDecode(hgroup, s);\n        if (result != BROTLI_DECODER_SUCCESS) break;\n        s->loop_counter++;\n        if (s->loop_counter < 3) {\n          break;\n        }\n        s->state = BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY;\n      }\n      /* Fall through. */\n\n      case BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY:\n        PrepareLiteralDecoding(s);\n        s->dist_context_map_slice = s->dist_context_map;\n        s->htree_command = s->insert_copy_hgroup.htrees[0];\n        if (!BrotliEnsureRingBuffer(s)) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2);\n          break;\n        }\n        CalculateDistanceLut(s);\n        s->state = BROTLI_STATE_COMMAND_BEGIN;\n      /* Fall through. */\n\n      case BROTLI_STATE_COMMAND_BEGIN:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_INNER:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_DECODE_LITERALS:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_WRAP_COPY:\n        result = ProcessCommands(s);\n        if (result == BROTLI_DECODER_NEEDS_MORE_INPUT) {\n          result = SafeProcessCommands(s);\n        }\n        break;\n\n      case BROTLI_STATE_COMMAND_INNER_WRITE:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_WRITE_1:\n      /* Fall through. */\n      case BROTLI_STATE_COMMAND_POST_WRITE_2:\n        result = WriteRingBuffer(\n            s, available_out, next_out, total_out, BROTLI_FALSE);\n        if (result != BROTLI_DECODER_SUCCESS) {\n          break;\n        }\n        WrapRingBuffer(s);\n        if (s->ringbuffer_size == 1 << s->window_bits) {\n          s->max_distance = s->max_backward_distance;\n        }\n        if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_1) {\n          BrotliDecoderCompoundDictionary* addon = s->compound_dictionary;\n          if (addon && (addon->br_length != addon->br_copied)) {\n            s->pos += CopyFromCompoundDictionary(s, s->pos);\n            if (s->pos >= s->ringbuffer_size) continue;\n          }\n          if (s->meta_block_remaining_len == 0) {\n            /* Next metablock, if any. */\n            s->state = BROTLI_STATE_METABLOCK_DONE;\n          } else {\n            s->state = BROTLI_STATE_COMMAND_BEGIN;\n          }\n          break;\n        } else if (s->state == BROTLI_STATE_COMMAND_POST_WRITE_2) {\n          s->state = BROTLI_STATE_COMMAND_POST_WRAP_COPY;\n        } else {  /* BROTLI_STATE_COMMAND_INNER_WRITE */\n          if (s->loop_counter == 0) {\n            if (s->meta_block_remaining_len == 0) {\n              s->state = BROTLI_STATE_METABLOCK_DONE;\n            } else {\n              s->state = BROTLI_STATE_COMMAND_POST_DECODE_LITERALS;\n            }\n            break;\n          }\n          s->state = BROTLI_STATE_COMMAND_INNER;\n        }\n        break;\n\n      case BROTLI_STATE_METABLOCK_DONE:\n        if (s->meta_block_remaining_len < 0) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2);\n          break;\n        }\n        BrotliDecoderStateCleanupAfterMetablock(s);\n        if (!s->is_last_metablock) {\n          s->state = BROTLI_STATE_METABLOCK_BEGIN;\n          break;\n        }\n        if (!BrotliJumpToByteBoundary(br)) {\n          result = BROTLI_FAILURE(BROTLI_DECODER_ERROR_FORMAT_PADDING_2);\n          break;\n        }\n        if (s->buffer_length == 0) {\n          BrotliBitReaderUnload(br);\n          *available_in = BrotliBitReaderGetAvailIn(br);\n          *next_in = br->next_in;\n        }\n        s->state = BROTLI_STATE_DONE;\n      /* Fall through. */\n\n      case BROTLI_STATE_DONE:\n        if (s->ringbuffer != 0) {\n          result = WriteRingBuffer(\n              s, available_out, next_out, total_out, BROTLI_TRUE);\n          if (result != BROTLI_DECODER_SUCCESS) {\n            break;\n          }\n        }\n        return BROTLI_SAVE_ERROR_CODE(result);\n    }\n  }\n  return BROTLI_SAVE_ERROR_CODE(result);\n#undef BROTLI_SAVE_ERROR_CODE\n}\n\nBROTLI_BOOL BrotliDecoderHasMoreOutput(const BrotliDecoderState* s) {\n  /* After unrecoverable error remaining output is considered nonsensical. */\n  if ((int)s->error_code < 0) {\n    return BROTLI_FALSE;\n  }\n  return TO_BROTLI_BOOL(\n      s->ringbuffer != 0 && UnwrittenBytes(s, BROTLI_FALSE) != 0);\n}\n\nconst uint8_t* BrotliDecoderTakeOutput(BrotliDecoderState* s, size_t* size) {\n  uint8_t* result = 0;\n  size_t available_out = *size ? *size : 1u << 24;\n  size_t requested_out = available_out;\n  BrotliDecoderErrorCode status;\n  if ((s->ringbuffer == 0) || ((int)s->error_code < 0)) {\n    *size = 0;\n    return 0;\n  }\n  WrapRingBuffer(s);\n  status = WriteRingBuffer(s, &available_out, &result, 0, BROTLI_TRUE);\n  /* Either WriteRingBuffer returns those \"success\" codes... */\n  if (status == BROTLI_DECODER_SUCCESS ||\n      status == BROTLI_DECODER_NEEDS_MORE_OUTPUT) {\n    *size = requested_out - available_out;\n  } else {\n    /* ... or stream is broken. Normally this should be caught by\n       BrotliDecoderDecompressStream, this is just a safeguard. */\n    if ((int)status < 0) SaveErrorCode(s, status, 0);\n    *size = 0;\n    result = 0;\n  }\n  return result;\n}\n\nBROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* s) {\n  return TO_BROTLI_BOOL(s->state != BROTLI_STATE_UNINITED ||\n      BrotliGetAvailableBits(&s->br) != 0);\n}\n\nBROTLI_BOOL BrotliDecoderIsFinished(const BrotliDecoderState* s) {\n  return TO_BROTLI_BOOL(s->state == BROTLI_STATE_DONE) &&\n      !BrotliDecoderHasMoreOutput(s);\n}\n\nBrotliDecoderErrorCode BrotliDecoderGetErrorCode(const BrotliDecoderState* s) {\n  return (BrotliDecoderErrorCode)s->error_code;\n}\n\nconst char* BrotliDecoderErrorString(BrotliDecoderErrorCode c) {\n  switch (c) {\n#define BROTLI_ERROR_CODE_CASE_(PREFIX, NAME, CODE) \\\n    case BROTLI_DECODER ## PREFIX ## NAME: return #PREFIX #NAME;\n#define BROTLI_NOTHING_\n    BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_CASE_, BROTLI_NOTHING_)\n#undef BROTLI_ERROR_CODE_CASE_\n#undef BROTLI_NOTHING_\n    default: return \"INVALID\";\n  }\n}\n\nuint32_t BrotliDecoderVersion(void) {\n  return BROTLI_VERSION;\n}\n\nvoid BrotliDecoderSetMetadataCallbacks(\n    BrotliDecoderState* state,\n    brotli_decoder_metadata_start_func start_func,\n    brotli_decoder_metadata_chunk_func chunk_func, void* opaque) {\n  state->metadata_start_func = start_func;\n  state->metadata_chunk_func = chunk_func;\n  state->metadata_callback_opaque = opaque;\n}\n\n/* Escalate internal functions visibility; for testing purposes only. */\n#if defined(BROTLI_TEST)\nBROTLI_BOOL SafeReadSymbolForTest(\n    const HuffmanCode*, BrotliBitReader*, brotli_reg_t*);\nBROTLI_BOOL SafeReadSymbolForTest(\n    const HuffmanCode* table, BrotliBitReader* br, brotli_reg_t* result) {\n  return SafeReadSymbol(table, br, result);\n}\n\nvoid InverseMoveToFrontTransformForTest(\n    uint8_t*, brotli_reg_t, BrotliDecoderState*);\nvoid InverseMoveToFrontTransformForTest(\n    uint8_t* v, brotli_reg_t l, BrotliDecoderState* s) {\n  InverseMoveToFrontTransform(v, l, s);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/dec/huffman.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Utilities for building Huffman decoding tables. */\n\n#include \"huffman.h\"\n\n#include <string.h>  /* memcpy, memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_REVERSE_BITS_MAX 8\n\n#if defined(BROTLI_RBIT)\n#define BROTLI_REVERSE_BITS_BASE \\\n  ((sizeof(brotli_reg_t) << 3) - BROTLI_REVERSE_BITS_MAX)\n#else\n#define BROTLI_REVERSE_BITS_BASE 0\nstatic uint8_t kReverseBits[1 << BROTLI_REVERSE_BITS_MAX] = {\n  0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,\n  0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,\n  0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,\n  0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,\n  0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,\n  0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,\n  0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,\n  0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,\n  0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,\n  0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,\n  0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,\n  0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,\n  0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,\n  0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,\n  0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,\n  0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,\n  0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,\n  0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,\n  0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,\n  0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,\n  0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,\n  0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,\n  0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,\n  0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,\n  0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,\n  0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,\n  0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,\n  0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,\n  0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,\n  0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,\n  0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,\n  0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF\n};\n#endif  /* BROTLI_RBIT */\n\n#define BROTLI_REVERSE_BITS_LOWEST \\\n  ((brotli_reg_t)1 << (BROTLI_REVERSE_BITS_MAX - 1 + BROTLI_REVERSE_BITS_BASE))\n\n/* Returns reverse(num >> BROTLI_REVERSE_BITS_BASE, BROTLI_REVERSE_BITS_MAX),\n   where reverse(value, len) is the bit-wise reversal of the len least\n   significant bits of value. */\nstatic BROTLI_INLINE brotli_reg_t BrotliReverseBits(brotli_reg_t num) {\n#if defined(BROTLI_RBIT)\n  return BROTLI_RBIT(num);\n#else\n  return kReverseBits[num];\n#endif\n}\n\n/* Stores code in table[0], table[step], table[2*step], ..., table[end] */\n/* Assumes that end is an integer multiple of step */\nstatic BROTLI_INLINE void ReplicateValue(HuffmanCode* table,\n                                         int step, int end,\n                                         HuffmanCode code) {\n  do {\n    end -= step;\n    table[end] = code;\n  } while (end > 0);\n}\n\n/* Returns the table width of the next 2nd level table. |count| is the histogram\n   of bit lengths for the remaining symbols, |len| is the code length of the\n   next processed symbol. */\nstatic BROTLI_INLINE int NextTableBitSize(const uint16_t* const count,\n                                          int len, int root_bits) {\n  int left = 1 << (len - root_bits);\n  while (len < BROTLI_HUFFMAN_MAX_CODE_LENGTH) {\n    left -= count[len];\n    if (left <= 0) break;\n    ++len;\n    left <<= 1;\n  }\n  return len - root_bits;\n}\n\nvoid BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* table,\n                                        const uint8_t* const code_lengths,\n                                        uint16_t* count) {\n  HuffmanCode code;       /* current table entry */\n  int symbol;             /* symbol index in original or sorted table */\n  brotli_reg_t key;       /* prefix code */\n  brotli_reg_t key_step;  /* prefix code addend */\n  int step;               /* step size to replicate values in current table */\n  int table_size;         /* size of current table */\n  int sorted[BROTLI_CODE_LENGTH_CODES];  /* symbols sorted by code length */\n  /* offsets in sorted table for each length */\n  int offset[BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH + 1];\n  int bits;\n  int bits_count;\n  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH <=\n                BROTLI_REVERSE_BITS_MAX);\n  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5);\n\n  /* Generate offsets into sorted symbol table by code length. */\n  symbol = -1;\n  bits = 1;\n  /* BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH == 5 */\n  BROTLI_REPEAT_5({\n    symbol += count[bits];\n    offset[bits] = symbol;\n    bits++;\n  });\n  /* Symbols with code length 0 are placed after all other symbols. */\n  offset[0] = BROTLI_CODE_LENGTH_CODES - 1;\n\n  /* Sort symbols by length, by symbol order within each length. */\n  symbol = BROTLI_CODE_LENGTH_CODES;\n  do {\n    BROTLI_REPEAT_6({\n      symbol--;\n      sorted[offset[code_lengths[symbol]]--] = symbol;\n    });\n  } while (symbol != 0);\n\n  table_size = 1 << BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH;\n\n  /* Special case: all symbols but one have 0 code length. */\n  if (offset[0] == 0) {\n    code = ConstructHuffmanCode(0, (uint16_t)sorted[0]);\n    for (key = 0; key < (brotli_reg_t)table_size; ++key) {\n      table[key] = code;\n    }\n    return;\n  }\n\n  /* Fill in table. */\n  key = 0;\n  key_step = BROTLI_REVERSE_BITS_LOWEST;\n  symbol = 0;\n  bits = 1;\n  step = 2;\n  do {\n    for (bits_count = count[bits]; bits_count != 0; --bits_count) {\n      code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)sorted[symbol++]);\n      ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);\n      key += key_step;\n    }\n    step <<= 1;\n    key_step >>= 1;\n  } while (++bits <= BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH);\n}\n\nuint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,\n                                 int root_bits,\n                                 const uint16_t* const symbol_lists,\n                                 uint16_t* count) {\n  HuffmanCode code;       /* current table entry */\n  HuffmanCode* table;     /* next available space in table */\n  int len;                /* current code length */\n  int symbol;             /* symbol index in original or sorted table */\n  brotli_reg_t key;       /* prefix code */\n  brotli_reg_t key_step;  /* prefix code addend */\n  brotli_reg_t sub_key;   /* 2nd level table prefix code */\n  brotli_reg_t sub_key_step;  /* 2nd level table prefix code addend */\n  int step;               /* step size to replicate values in current table */\n  int table_bits;         /* key length of current table */\n  int table_size;         /* size of current table */\n  int total_size;         /* sum of root table size and 2nd level table sizes */\n  int max_length = -1;\n  int bits;\n  int bits_count;\n\n  BROTLI_DCHECK(root_bits <= BROTLI_REVERSE_BITS_MAX);\n  BROTLI_DCHECK(BROTLI_HUFFMAN_MAX_CODE_LENGTH - root_bits <=\n                BROTLI_REVERSE_BITS_MAX);\n\n  while (symbol_lists[max_length] == 0xFFFF) max_length--;\n  max_length += BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1;\n\n  table = root_table;\n  table_bits = root_bits;\n  table_size = 1 << table_bits;\n  total_size = table_size;\n\n  /* Fill in the root table. Reduce the table size to if possible,\n     and create the repetitions by memcpy. */\n  if (table_bits > max_length) {\n    table_bits = max_length;\n    table_size = 1 << table_bits;\n  }\n  key = 0;\n  key_step = BROTLI_REVERSE_BITS_LOWEST;\n  bits = 1;\n  step = 2;\n  do {\n    symbol = bits - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);\n    for (bits_count = count[bits]; bits_count != 0; --bits_count) {\n      symbol = symbol_lists[symbol];\n      code = ConstructHuffmanCode((uint8_t)bits, (uint16_t)symbol);\n      ReplicateValue(&table[BrotliReverseBits(key)], step, table_size, code);\n      key += key_step;\n    }\n    step <<= 1;\n    key_step >>= 1;\n  } while (++bits <= table_bits);\n\n  /* If root_bits != table_bits then replicate to fill the remaining slots. */\n  while (total_size != table_size) {\n    memcpy(&table[table_size], &table[0],\n           (size_t)table_size * sizeof(table[0]));\n    table_size <<= 1;\n  }\n\n  /* Fill in 2nd level tables and add pointers to root table. */\n  key_step = BROTLI_REVERSE_BITS_LOWEST >> (root_bits - 1);\n  sub_key = (BROTLI_REVERSE_BITS_LOWEST << 1);\n  sub_key_step = BROTLI_REVERSE_BITS_LOWEST;\n  for (len = root_bits + 1, step = 2; len <= max_length; ++len) {\n    symbol = len - (BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1);\n    for (; count[len] != 0; --count[len]) {\n      if (sub_key == (BROTLI_REVERSE_BITS_LOWEST << 1U)) {\n        table += table_size;\n        table_bits = NextTableBitSize(count, len, root_bits);\n        table_size = 1 << table_bits;\n        total_size += table_size;\n        sub_key = BrotliReverseBits(key);\n        key += key_step;\n        root_table[sub_key] = ConstructHuffmanCode(\n            (uint8_t)(table_bits + root_bits),\n            (uint16_t)(((size_t)(table - root_table)) - sub_key));\n        sub_key = 0;\n      }\n      symbol = symbol_lists[symbol];\n      code = ConstructHuffmanCode((uint8_t)(len - root_bits), (uint16_t)symbol);\n      ReplicateValue(\n          &table[BrotliReverseBits(sub_key)], step, table_size, code);\n      sub_key += sub_key_step;\n    }\n    step <<= 1;\n    sub_key_step >>= 1;\n  }\n  return (uint32_t)total_size;\n}\n\nuint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,\n                                       int root_bits,\n                                       uint16_t* val,\n                                       uint32_t num_symbols) {\n  uint32_t table_size = 1;\n  const uint32_t goal_size = 1U << root_bits;\n  switch (num_symbols) {\n    case 0:\n      table[0] = ConstructHuffmanCode(0, val[0]);\n      break;\n    case 1:\n      if (val[1] > val[0]) {\n        table[0] = ConstructHuffmanCode(1, val[0]);\n        table[1] = ConstructHuffmanCode(1, val[1]);\n      } else {\n        table[0] = ConstructHuffmanCode(1, val[1]);\n        table[1] = ConstructHuffmanCode(1, val[0]);\n      }\n      table_size = 2;\n      break;\n    case 2:\n      table[0] = ConstructHuffmanCode(1, val[0]);\n      table[2] = ConstructHuffmanCode(1, val[0]);\n      if (val[2] > val[1]) {\n        table[1] = ConstructHuffmanCode(2, val[1]);\n        table[3] = ConstructHuffmanCode(2, val[2]);\n      } else {\n        table[1] = ConstructHuffmanCode(2, val[2]);\n        table[3] = ConstructHuffmanCode(2, val[1]);\n      }\n      table_size = 4;\n      break;\n    case 3: {\n      int i, k;\n      for (i = 0; i < 3; ++i) {\n        for (k = i + 1; k < 4; ++k) {\n          if (val[k] < val[i]) {\n            uint16_t t = val[k];\n            val[k] = val[i];\n            val[i] = t;\n          }\n        }\n      }\n      table[0] = ConstructHuffmanCode(2, val[0]);\n      table[2] = ConstructHuffmanCode(2, val[1]);\n      table[1] = ConstructHuffmanCode(2, val[2]);\n      table[3] = ConstructHuffmanCode(2, val[3]);\n      table_size = 4;\n      break;\n    }\n    case 4: {\n      if (val[3] < val[2]) {\n        uint16_t t = val[3];\n        val[3] = val[2];\n        val[2] = t;\n      }\n      table[0] = ConstructHuffmanCode(1, val[0]);\n      table[1] = ConstructHuffmanCode(2, val[1]);\n      table[2] = ConstructHuffmanCode(1, val[0]);\n      table[3] = ConstructHuffmanCode(3, val[2]);\n      table[4] = ConstructHuffmanCode(1, val[0]);\n      table[5] = ConstructHuffmanCode(2, val[1]);\n      table[6] = ConstructHuffmanCode(1, val[0]);\n      table[7] = ConstructHuffmanCode(3, val[3]);\n      table_size = 8;\n      break;\n    }\n  }\n  while (table_size != goal_size) {\n    memcpy(&table[table_size], &table[0],\n           (size_t)table_size * sizeof(table[0]));\n    table_size <<= 1;\n  }\n  return goal_size;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/dec/huffman.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Utilities for building Huffman decoding tables. */\n\n#ifndef BROTLI_DEC_HUFFMAN_H_\n#define BROTLI_DEC_HUFFMAN_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_HUFFMAN_MAX_CODE_LENGTH 15\n\n/* BROTLI_NUM_BLOCK_LEN_SYMBOLS == 26 */\n#define BROTLI_HUFFMAN_MAX_SIZE_26 396\n/* BROTLI_MAX_BLOCK_TYPE_SYMBOLS == 258 */\n#define BROTLI_HUFFMAN_MAX_SIZE_258 632\n/* BROTLI_MAX_CONTEXT_MAP_SYMBOLS == 272 */\n#define BROTLI_HUFFMAN_MAX_SIZE_272 646\n\n#define BROTLI_HUFFMAN_MAX_CODE_LENGTH_CODE_LENGTH 5\n\n#if ((defined(BROTLI_TARGET_ARMV7) || defined(BROTLI_TARGET_ARMV8_32)) && \\\n  BROTLI_GNUC_HAS_ATTRIBUTE(aligned, 2, 7, 0))\n#define BROTLI_HUFFMAN_CODE_FAST_LOAD\n#endif\n\n#if !defined(BROTLI_HUFFMAN_CODE_FAST_LOAD)\n/* Do not create this struct directly - use the ConstructHuffmanCode\n * constructor below! */\ntypedef struct {\n  uint8_t bits;    /* number of bits used for this symbol */\n  uint16_t value;  /* symbol value or table offset */\n} HuffmanCode;\n\nstatic BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,\n    const uint16_t value) {\n  HuffmanCode h;\n  h.bits = bits;\n  h.value = value;\n  return h;\n}\n\n/* Please use the following macros to optimize HuffmanCode accesses in hot\n * paths.\n *\n * For example, assuming |table| contains a HuffmanCode pointer:\n *\n *   BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(table);\n *   BROTLI_HC_ADJUST_TABLE_INDEX(table, index_into_table);\n *   *bits = BROTLI_HC_GET_BITS(table);\n *   *value = BROTLI_HC_GET_VALUE(table);\n *   BROTLI_HC_ADJUST_TABLE_INDEX(table, offset);\n *   *bits2 = BROTLI_HC_GET_BITS(table);\n *   *value2 = BROTLI_HC_GET_VALUE(table);\n *\n */\n\n#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H)\n#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V)\n\n/* These must be given a HuffmanCode pointer! */\n#define BROTLI_HC_FAST_LOAD_BITS(H) (H->bits)\n#define BROTLI_HC_FAST_LOAD_VALUE(H) (H->value)\n\n#else /* BROTLI_HUFFMAN_CODE_FAST_LOAD */\n\ntypedef BROTLI_ALIGNED(4) uint32_t HuffmanCode;\n\nstatic BROTLI_INLINE HuffmanCode ConstructHuffmanCode(const uint8_t bits,\n    const uint16_t value) {\n  return (HuffmanCode) ((value & 0xFFFF) << 16) | (bits & 0xFF);\n}\n\n#define BROTLI_HC_MARK_TABLE_FOR_FAST_LOAD(H) uint32_t __fastload_##H = (*H)\n#define BROTLI_HC_ADJUST_TABLE_INDEX(H, V) H += (V); __fastload_##H = (*H)\n\n/* These must be given a HuffmanCode pointer! */\n#define BROTLI_HC_FAST_LOAD_BITS(H) ((__fastload_##H) & 0xFF)\n#define BROTLI_HC_FAST_LOAD_VALUE(H) ((__fastload_##H) >> 16)\n#endif /* BROTLI_HUFFMAN_CODE_FAST_LOAD */\n\n/* Builds Huffman lookup table assuming code lengths are in symbol order. */\nBROTLI_INTERNAL void BrotliBuildCodeLengthsHuffmanTable(HuffmanCode* root_table,\n    const uint8_t* const code_lengths, uint16_t* count);\n\n/* Builds Huffman lookup table assuming code lengths are in symbol order.\n   Returns size of resulting table. */\nBROTLI_INTERNAL uint32_t BrotliBuildHuffmanTable(HuffmanCode* root_table,\n    int root_bits, const uint16_t* const symbol_lists, uint16_t* count);\n\n/* Builds a simple Huffman table. The |num_symbols| parameter is to be\n   interpreted as follows: 0 means 1 symbol, 1 means 2 symbols,\n   2 means 3 symbols, 3 means 4 symbols with lengths [2, 2, 2, 2],\n   4 means 4 symbols with lengths [1, 2, 3, 3]. */\nBROTLI_INTERNAL uint32_t BrotliBuildSimpleHuffmanTable(HuffmanCode* table,\n    int root_bits, uint16_t* symbols, uint32_t num_symbols);\n\n/* Contains a collection of Huffman trees with the same alphabet size. */\n/* alphabet_size_limit is needed due to simple codes, since\n   log2(alphabet_size_max) could be greater than log2(alphabet_size_limit). */\ntypedef struct {\n  HuffmanCode** htrees;\n  HuffmanCode* codes;\n  uint16_t alphabet_size_max;\n  uint16_t alphabet_size_limit;\n  uint16_t num_htrees;\n} HuffmanTreeGroup;\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_HUFFMAN_H_ */\n"
  },
  {
    "path": "third-party/brotli/dec/prefix.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup tables to map prefix codes to value ranges. This is used during\n   decoding of the block lengths, literal insertion lengths and copy lengths. */\n\n#ifndef BROTLI_DEC_PREFIX_H_\n#define BROTLI_DEC_PREFIX_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n\ntypedef struct CmdLutElement {\n  uint8_t insert_len_extra_bits;\n  uint8_t copy_len_extra_bits;\n  int8_t distance_code;\n  uint8_t context;\n  uint16_t insert_len_offset;\n  uint16_t copy_len_offset;\n} CmdLutElement;\n\nstatic const CmdLutElement kCmdLut[BROTLI_NUM_COMMAND_SYMBOLS] = {\n  { 0x00, 0x00, 0, 0x00, 0x0000, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0000, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0000, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0000, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0001, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0001, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0001, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0001, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0002, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0002, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0002, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0002, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0003, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0003, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0003, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0003, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0004, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0004, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0004, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0004, 0x0009 },\n  { 0x00, 0x00, 0, 0x00, 0x0005, 0x0002 },\n  { 0x00, 0x00, 0, 0x01, 0x0005, 0x0003 },\n  { 0x00, 0x00, 0, 0x02, 0x0005, 0x0004 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0005 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0006 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0007 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0008 },\n  { 0x00, 0x00, 0, 0x03, 0x0005, 0x0009 },\n  { 0x01, 0x00, 0, 0x00, 0x0006, 0x0002 },\n  { 0x01, 0x00, 0, 0x01, 0x0006, 0x0003 },\n  { 0x01, 0x00, 0, 0x02, 0x0006, 0x0004 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0005 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0006 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0007 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0008 },\n  { 0x01, 0x00, 0, 0x03, 0x0006, 0x0009 },\n  { 0x01, 0x00, 0, 0x00, 0x0008, 0x0002 },\n  { 0x01, 0x00, 0, 0x01, 0x0008, 0x0003 },\n  { 0x01, 0x00, 0, 0x02, 0x0008, 0x0004 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0005 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0006 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0007 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0008 },\n  { 0x01, 0x00, 0, 0x03, 0x0008, 0x0009 },\n  { 0x00, 0x01, 0, 0x03, 0x0000, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0000, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0000, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0000, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0000, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0000, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0000, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0000, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0001, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0001, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0001, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0001, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0001, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0001, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0001, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0001, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0002, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0002, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0002, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0002, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0002, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0002, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0002, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0002, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0003, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0003, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0003, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0003, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0003, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0003, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0003, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0003, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0004, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0004, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0004, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0004, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0004, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0004, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0004, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0004, 0x0036 },\n  { 0x00, 0x01, 0, 0x03, 0x0005, 0x000a },\n  { 0x00, 0x01, 0, 0x03, 0x0005, 0x000c },\n  { 0x00, 0x02, 0, 0x03, 0x0005, 0x000e },\n  { 0x00, 0x02, 0, 0x03, 0x0005, 0x0012 },\n  { 0x00, 0x03, 0, 0x03, 0x0005, 0x0016 },\n  { 0x00, 0x03, 0, 0x03, 0x0005, 0x001e },\n  { 0x00, 0x04, 0, 0x03, 0x0005, 0x0026 },\n  { 0x00, 0x04, 0, 0x03, 0x0005, 0x0036 },\n  { 0x01, 0x01, 0, 0x03, 0x0006, 0x000a },\n  { 0x01, 0x01, 0, 0x03, 0x0006, 0x000c },\n  { 0x01, 0x02, 0, 0x03, 0x0006, 0x000e },\n  { 0x01, 0x02, 0, 0x03, 0x0006, 0x0012 },\n  { 0x01, 0x03, 0, 0x03, 0x0006, 0x0016 },\n  { 0x01, 0x03, 0, 0x03, 0x0006, 0x001e },\n  { 0x01, 0x04, 0, 0x03, 0x0006, 0x0026 },\n  { 0x01, 0x04, 0, 0x03, 0x0006, 0x0036 },\n  { 0x01, 0x01, 0, 0x03, 0x0008, 0x000a },\n  { 0x01, 0x01, 0, 0x03, 0x0008, 0x000c },\n  { 0x01, 0x02, 0, 0x03, 0x0008, 0x000e },\n  { 0x01, 0x02, 0, 0x03, 0x0008, 0x0012 },\n  { 0x01, 0x03, 0, 0x03, 0x0008, 0x0016 },\n  { 0x01, 0x03, 0, 0x03, 0x0008, 0x001e },\n  { 0x01, 0x04, 0, 0x03, 0x0008, 0x0026 },\n  { 0x01, 0x04, 0, 0x03, 0x0008, 0x0036 },\n  { 0x00, 0x00, -1, 0x00, 0x0000, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0000, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0000, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0000, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0001, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0001, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0001, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0001, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0002, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0002, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0002, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0002, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0003, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0003, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0003, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0003, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0004, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0004, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0004, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0004, 0x0009 },\n  { 0x00, 0x00, -1, 0x00, 0x0005, 0x0002 },\n  { 0x00, 0x00, -1, 0x01, 0x0005, 0x0003 },\n  { 0x00, 0x00, -1, 0x02, 0x0005, 0x0004 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0005 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0006 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0007 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0008 },\n  { 0x00, 0x00, -1, 0x03, 0x0005, 0x0009 },\n  { 0x01, 0x00, -1, 0x00, 0x0006, 0x0002 },\n  { 0x01, 0x00, -1, 0x01, 0x0006, 0x0003 },\n  { 0x01, 0x00, -1, 0x02, 0x0006, 0x0004 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0005 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0006 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0007 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0008 },\n  { 0x01, 0x00, -1, 0x03, 0x0006, 0x0009 },\n  { 0x01, 0x00, -1, 0x00, 0x0008, 0x0002 },\n  { 0x01, 0x00, -1, 0x01, 0x0008, 0x0003 },\n  { 0x01, 0x00, -1, 0x02, 0x0008, 0x0004 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0005 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0006 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0007 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0008 },\n  { 0x01, 0x00, -1, 0x03, 0x0008, 0x0009 },\n  { 0x00, 0x01, -1, 0x03, 0x0000, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0000, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0000, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0000, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0000, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0000, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0000, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0000, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0001, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0001, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0001, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0001, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0001, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0001, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0001, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0001, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0002, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0002, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0002, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0002, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0002, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0002, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0002, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0002, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0003, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0003, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0003, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0003, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0003, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0003, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0003, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0003, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0004, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0004, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0004, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0004, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0004, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0004, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0004, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0004, 0x0036 },\n  { 0x00, 0x01, -1, 0x03, 0x0005, 0x000a },\n  { 0x00, 0x01, -1, 0x03, 0x0005, 0x000c },\n  { 0x00, 0x02, -1, 0x03, 0x0005, 0x000e },\n  { 0x00, 0x02, -1, 0x03, 0x0005, 0x0012 },\n  { 0x00, 0x03, -1, 0x03, 0x0005, 0x0016 },\n  { 0x00, 0x03, -1, 0x03, 0x0005, 0x001e },\n  { 0x00, 0x04, -1, 0x03, 0x0005, 0x0026 },\n  { 0x00, 0x04, -1, 0x03, 0x0005, 0x0036 },\n  { 0x01, 0x01, -1, 0x03, 0x0006, 0x000a },\n  { 0x01, 0x01, -1, 0x03, 0x0006, 0x000c },\n  { 0x01, 0x02, -1, 0x03, 0x0006, 0x000e },\n  { 0x01, 0x02, -1, 0x03, 0x0006, 0x0012 },\n  { 0x01, 0x03, -1, 0x03, 0x0006, 0x0016 },\n  { 0x01, 0x03, -1, 0x03, 0x0006, 0x001e },\n  { 0x01, 0x04, -1, 0x03, 0x0006, 0x0026 },\n  { 0x01, 0x04, -1, 0x03, 0x0006, 0x0036 },\n  { 0x01, 0x01, -1, 0x03, 0x0008, 0x000a },\n  { 0x01, 0x01, -1, 0x03, 0x0008, 0x000c },\n  { 0x01, 0x02, -1, 0x03, 0x0008, 0x000e },\n  { 0x01, 0x02, -1, 0x03, 0x0008, 0x0012 },\n  { 0x01, 0x03, -1, 0x03, 0x0008, 0x0016 },\n  { 0x01, 0x03, -1, 0x03, 0x0008, 0x001e },\n  { 0x01, 0x04, -1, 0x03, 0x0008, 0x0026 },\n  { 0x01, 0x04, -1, 0x03, 0x0008, 0x0036 },\n  { 0x02, 0x00, -1, 0x00, 0x000a, 0x0002 },\n  { 0x02, 0x00, -1, 0x01, 0x000a, 0x0003 },\n  { 0x02, 0x00, -1, 0x02, 0x000a, 0x0004 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0005 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0006 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0007 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0008 },\n  { 0x02, 0x00, -1, 0x03, 0x000a, 0x0009 },\n  { 0x02, 0x00, -1, 0x00, 0x000e, 0x0002 },\n  { 0x02, 0x00, -1, 0x01, 0x000e, 0x0003 },\n  { 0x02, 0x00, -1, 0x02, 0x000e, 0x0004 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0005 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0006 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0007 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0008 },\n  { 0x02, 0x00, -1, 0x03, 0x000e, 0x0009 },\n  { 0x03, 0x00, -1, 0x00, 0x0012, 0x0002 },\n  { 0x03, 0x00, -1, 0x01, 0x0012, 0x0003 },\n  { 0x03, 0x00, -1, 0x02, 0x0012, 0x0004 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0005 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0006 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0007 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0008 },\n  { 0x03, 0x00, -1, 0x03, 0x0012, 0x0009 },\n  { 0x03, 0x00, -1, 0x00, 0x001a, 0x0002 },\n  { 0x03, 0x00, -1, 0x01, 0x001a, 0x0003 },\n  { 0x03, 0x00, -1, 0x02, 0x001a, 0x0004 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0005 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0006 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0007 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0008 },\n  { 0x03, 0x00, -1, 0x03, 0x001a, 0x0009 },\n  { 0x04, 0x00, -1, 0x00, 0x0022, 0x0002 },\n  { 0x04, 0x00, -1, 0x01, 0x0022, 0x0003 },\n  { 0x04, 0x00, -1, 0x02, 0x0022, 0x0004 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0005 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0006 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0007 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0008 },\n  { 0x04, 0x00, -1, 0x03, 0x0022, 0x0009 },\n  { 0x04, 0x00, -1, 0x00, 0x0032, 0x0002 },\n  { 0x04, 0x00, -1, 0x01, 0x0032, 0x0003 },\n  { 0x04, 0x00, -1, 0x02, 0x0032, 0x0004 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0005 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0006 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0007 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0008 },\n  { 0x04, 0x00, -1, 0x03, 0x0032, 0x0009 },\n  { 0x05, 0x00, -1, 0x00, 0x0042, 0x0002 },\n  { 0x05, 0x00, -1, 0x01, 0x0042, 0x0003 },\n  { 0x05, 0x00, -1, 0x02, 0x0042, 0x0004 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0005 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0006 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0007 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0008 },\n  { 0x05, 0x00, -1, 0x03, 0x0042, 0x0009 },\n  { 0x05, 0x00, -1, 0x00, 0x0062, 0x0002 },\n  { 0x05, 0x00, -1, 0x01, 0x0062, 0x0003 },\n  { 0x05, 0x00, -1, 0x02, 0x0062, 0x0004 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0005 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0006 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0007 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0008 },\n  { 0x05, 0x00, -1, 0x03, 0x0062, 0x0009 },\n  { 0x02, 0x01, -1, 0x03, 0x000a, 0x000a },\n  { 0x02, 0x01, -1, 0x03, 0x000a, 0x000c },\n  { 0x02, 0x02, -1, 0x03, 0x000a, 0x000e },\n  { 0x02, 0x02, -1, 0x03, 0x000a, 0x0012 },\n  { 0x02, 0x03, -1, 0x03, 0x000a, 0x0016 },\n  { 0x02, 0x03, -1, 0x03, 0x000a, 0x001e },\n  { 0x02, 0x04, -1, 0x03, 0x000a, 0x0026 },\n  { 0x02, 0x04, -1, 0x03, 0x000a, 0x0036 },\n  { 0x02, 0x01, -1, 0x03, 0x000e, 0x000a },\n  { 0x02, 0x01, -1, 0x03, 0x000e, 0x000c },\n  { 0x02, 0x02, -1, 0x03, 0x000e, 0x000e },\n  { 0x02, 0x02, -1, 0x03, 0x000e, 0x0012 },\n  { 0x02, 0x03, -1, 0x03, 0x000e, 0x0016 },\n  { 0x02, 0x03, -1, 0x03, 0x000e, 0x001e },\n  { 0x02, 0x04, -1, 0x03, 0x000e, 0x0026 },\n  { 0x02, 0x04, -1, 0x03, 0x000e, 0x0036 },\n  { 0x03, 0x01, -1, 0x03, 0x0012, 0x000a },\n  { 0x03, 0x01, -1, 0x03, 0x0012, 0x000c },\n  { 0x03, 0x02, -1, 0x03, 0x0012, 0x000e },\n  { 0x03, 0x02, -1, 0x03, 0x0012, 0x0012 },\n  { 0x03, 0x03, -1, 0x03, 0x0012, 0x0016 },\n  { 0x03, 0x03, -1, 0x03, 0x0012, 0x001e },\n  { 0x03, 0x04, -1, 0x03, 0x0012, 0x0026 },\n  { 0x03, 0x04, -1, 0x03, 0x0012, 0x0036 },\n  { 0x03, 0x01, -1, 0x03, 0x001a, 0x000a },\n  { 0x03, 0x01, -1, 0x03, 0x001a, 0x000c },\n  { 0x03, 0x02, -1, 0x03, 0x001a, 0x000e },\n  { 0x03, 0x02, -1, 0x03, 0x001a, 0x0012 },\n  { 0x03, 0x03, -1, 0x03, 0x001a, 0x0016 },\n  { 0x03, 0x03, -1, 0x03, 0x001a, 0x001e },\n  { 0x03, 0x04, -1, 0x03, 0x001a, 0x0026 },\n  { 0x03, 0x04, -1, 0x03, 0x001a, 0x0036 },\n  { 0x04, 0x01, -1, 0x03, 0x0022, 0x000a },\n  { 0x04, 0x01, -1, 0x03, 0x0022, 0x000c },\n  { 0x04, 0x02, -1, 0x03, 0x0022, 0x000e },\n  { 0x04, 0x02, -1, 0x03, 0x0022, 0x0012 },\n  { 0x04, 0x03, -1, 0x03, 0x0022, 0x0016 },\n  { 0x04, 0x03, -1, 0x03, 0x0022, 0x001e },\n  { 0x04, 0x04, -1, 0x03, 0x0022, 0x0026 },\n  { 0x04, 0x04, -1, 0x03, 0x0022, 0x0036 },\n  { 0x04, 0x01, -1, 0x03, 0x0032, 0x000a },\n  { 0x04, 0x01, -1, 0x03, 0x0032, 0x000c },\n  { 0x04, 0x02, -1, 0x03, 0x0032, 0x000e },\n  { 0x04, 0x02, -1, 0x03, 0x0032, 0x0012 },\n  { 0x04, 0x03, -1, 0x03, 0x0032, 0x0016 },\n  { 0x04, 0x03, -1, 0x03, 0x0032, 0x001e },\n  { 0x04, 0x04, -1, 0x03, 0x0032, 0x0026 },\n  { 0x04, 0x04, -1, 0x03, 0x0032, 0x0036 },\n  { 0x05, 0x01, -1, 0x03, 0x0042, 0x000a },\n  { 0x05, 0x01, -1, 0x03, 0x0042, 0x000c },\n  { 0x05, 0x02, -1, 0x03, 0x0042, 0x000e },\n  { 0x05, 0x02, -1, 0x03, 0x0042, 0x0012 },\n  { 0x05, 0x03, -1, 0x03, 0x0042, 0x0016 },\n  { 0x05, 0x03, -1, 0x03, 0x0042, 0x001e },\n  { 0x05, 0x04, -1, 0x03, 0x0042, 0x0026 },\n  { 0x05, 0x04, -1, 0x03, 0x0042, 0x0036 },\n  { 0x05, 0x01, -1, 0x03, 0x0062, 0x000a },\n  { 0x05, 0x01, -1, 0x03, 0x0062, 0x000c },\n  { 0x05, 0x02, -1, 0x03, 0x0062, 0x000e },\n  { 0x05, 0x02, -1, 0x03, 0x0062, 0x0012 },\n  { 0x05, 0x03, -1, 0x03, 0x0062, 0x0016 },\n  { 0x05, 0x03, -1, 0x03, 0x0062, 0x001e },\n  { 0x05, 0x04, -1, 0x03, 0x0062, 0x0026 },\n  { 0x05, 0x04, -1, 0x03, 0x0062, 0x0036 },\n  { 0x00, 0x05, -1, 0x03, 0x0000, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0000, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0000, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0000, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0000, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0000, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0000, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0000, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0001, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0001, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0001, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0001, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0001, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0001, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0001, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0001, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0002, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0002, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0002, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0002, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0002, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0002, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0002, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0002, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0003, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0003, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0003, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0003, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0003, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0003, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0003, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0003, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0004, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0004, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0004, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0004, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0004, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0004, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0004, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0004, 0x0846 },\n  { 0x00, 0x05, -1, 0x03, 0x0005, 0x0046 },\n  { 0x00, 0x05, -1, 0x03, 0x0005, 0x0066 },\n  { 0x00, 0x06, -1, 0x03, 0x0005, 0x0086 },\n  { 0x00, 0x07, -1, 0x03, 0x0005, 0x00c6 },\n  { 0x00, 0x08, -1, 0x03, 0x0005, 0x0146 },\n  { 0x00, 0x09, -1, 0x03, 0x0005, 0x0246 },\n  { 0x00, 0x0a, -1, 0x03, 0x0005, 0x0446 },\n  { 0x00, 0x18, -1, 0x03, 0x0005, 0x0846 },\n  { 0x01, 0x05, -1, 0x03, 0x0006, 0x0046 },\n  { 0x01, 0x05, -1, 0x03, 0x0006, 0x0066 },\n  { 0x01, 0x06, -1, 0x03, 0x0006, 0x0086 },\n  { 0x01, 0x07, -1, 0x03, 0x0006, 0x00c6 },\n  { 0x01, 0x08, -1, 0x03, 0x0006, 0x0146 },\n  { 0x01, 0x09, -1, 0x03, 0x0006, 0x0246 },\n  { 0x01, 0x0a, -1, 0x03, 0x0006, 0x0446 },\n  { 0x01, 0x18, -1, 0x03, 0x0006, 0x0846 },\n  { 0x01, 0x05, -1, 0x03, 0x0008, 0x0046 },\n  { 0x01, 0x05, -1, 0x03, 0x0008, 0x0066 },\n  { 0x01, 0x06, -1, 0x03, 0x0008, 0x0086 },\n  { 0x01, 0x07, -1, 0x03, 0x0008, 0x00c6 },\n  { 0x01, 0x08, -1, 0x03, 0x0008, 0x0146 },\n  { 0x01, 0x09, -1, 0x03, 0x0008, 0x0246 },\n  { 0x01, 0x0a, -1, 0x03, 0x0008, 0x0446 },\n  { 0x01, 0x18, -1, 0x03, 0x0008, 0x0846 },\n  { 0x06, 0x00, -1, 0x00, 0x0082, 0x0002 },\n  { 0x06, 0x00, -1, 0x01, 0x0082, 0x0003 },\n  { 0x06, 0x00, -1, 0x02, 0x0082, 0x0004 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0005 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0006 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0007 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0008 },\n  { 0x06, 0x00, -1, 0x03, 0x0082, 0x0009 },\n  { 0x07, 0x00, -1, 0x00, 0x00c2, 0x0002 },\n  { 0x07, 0x00, -1, 0x01, 0x00c2, 0x0003 },\n  { 0x07, 0x00, -1, 0x02, 0x00c2, 0x0004 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0005 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0006 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0007 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0008 },\n  { 0x07, 0x00, -1, 0x03, 0x00c2, 0x0009 },\n  { 0x08, 0x00, -1, 0x00, 0x0142, 0x0002 },\n  { 0x08, 0x00, -1, 0x01, 0x0142, 0x0003 },\n  { 0x08, 0x00, -1, 0x02, 0x0142, 0x0004 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0005 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0006 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0007 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0008 },\n  { 0x08, 0x00, -1, 0x03, 0x0142, 0x0009 },\n  { 0x09, 0x00, -1, 0x00, 0x0242, 0x0002 },\n  { 0x09, 0x00, -1, 0x01, 0x0242, 0x0003 },\n  { 0x09, 0x00, -1, 0x02, 0x0242, 0x0004 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0005 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0006 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0007 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0008 },\n  { 0x09, 0x00, -1, 0x03, 0x0242, 0x0009 },\n  { 0x0a, 0x00, -1, 0x00, 0x0442, 0x0002 },\n  { 0x0a, 0x00, -1, 0x01, 0x0442, 0x0003 },\n  { 0x0a, 0x00, -1, 0x02, 0x0442, 0x0004 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0005 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0006 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0007 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0008 },\n  { 0x0a, 0x00, -1, 0x03, 0x0442, 0x0009 },\n  { 0x0c, 0x00, -1, 0x00, 0x0842, 0x0002 },\n  { 0x0c, 0x00, -1, 0x01, 0x0842, 0x0003 },\n  { 0x0c, 0x00, -1, 0x02, 0x0842, 0x0004 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0005 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0006 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0007 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0008 },\n  { 0x0c, 0x00, -1, 0x03, 0x0842, 0x0009 },\n  { 0x0e, 0x00, -1, 0x00, 0x1842, 0x0002 },\n  { 0x0e, 0x00, -1, 0x01, 0x1842, 0x0003 },\n  { 0x0e, 0x00, -1, 0x02, 0x1842, 0x0004 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0005 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0006 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0007 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0008 },\n  { 0x0e, 0x00, -1, 0x03, 0x1842, 0x0009 },\n  { 0x18, 0x00, -1, 0x00, 0x5842, 0x0002 },\n  { 0x18, 0x00, -1, 0x01, 0x5842, 0x0003 },\n  { 0x18, 0x00, -1, 0x02, 0x5842, 0x0004 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0005 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0006 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0007 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0008 },\n  { 0x18, 0x00, -1, 0x03, 0x5842, 0x0009 },\n  { 0x02, 0x05, -1, 0x03, 0x000a, 0x0046 },\n  { 0x02, 0x05, -1, 0x03, 0x000a, 0x0066 },\n  { 0x02, 0x06, -1, 0x03, 0x000a, 0x0086 },\n  { 0x02, 0x07, -1, 0x03, 0x000a, 0x00c6 },\n  { 0x02, 0x08, -1, 0x03, 0x000a, 0x0146 },\n  { 0x02, 0x09, -1, 0x03, 0x000a, 0x0246 },\n  { 0x02, 0x0a, -1, 0x03, 0x000a, 0x0446 },\n  { 0x02, 0x18, -1, 0x03, 0x000a, 0x0846 },\n  { 0x02, 0x05, -1, 0x03, 0x000e, 0x0046 },\n  { 0x02, 0x05, -1, 0x03, 0x000e, 0x0066 },\n  { 0x02, 0x06, -1, 0x03, 0x000e, 0x0086 },\n  { 0x02, 0x07, -1, 0x03, 0x000e, 0x00c6 },\n  { 0x02, 0x08, -1, 0x03, 0x000e, 0x0146 },\n  { 0x02, 0x09, -1, 0x03, 0x000e, 0x0246 },\n  { 0x02, 0x0a, -1, 0x03, 0x000e, 0x0446 },\n  { 0x02, 0x18, -1, 0x03, 0x000e, 0x0846 },\n  { 0x03, 0x05, -1, 0x03, 0x0012, 0x0046 },\n  { 0x03, 0x05, -1, 0x03, 0x0012, 0x0066 },\n  { 0x03, 0x06, -1, 0x03, 0x0012, 0x0086 },\n  { 0x03, 0x07, -1, 0x03, 0x0012, 0x00c6 },\n  { 0x03, 0x08, -1, 0x03, 0x0012, 0x0146 },\n  { 0x03, 0x09, -1, 0x03, 0x0012, 0x0246 },\n  { 0x03, 0x0a, -1, 0x03, 0x0012, 0x0446 },\n  { 0x03, 0x18, -1, 0x03, 0x0012, 0x0846 },\n  { 0x03, 0x05, -1, 0x03, 0x001a, 0x0046 },\n  { 0x03, 0x05, -1, 0x03, 0x001a, 0x0066 },\n  { 0x03, 0x06, -1, 0x03, 0x001a, 0x0086 },\n  { 0x03, 0x07, -1, 0x03, 0x001a, 0x00c6 },\n  { 0x03, 0x08, -1, 0x03, 0x001a, 0x0146 },\n  { 0x03, 0x09, -1, 0x03, 0x001a, 0x0246 },\n  { 0x03, 0x0a, -1, 0x03, 0x001a, 0x0446 },\n  { 0x03, 0x18, -1, 0x03, 0x001a, 0x0846 },\n  { 0x04, 0x05, -1, 0x03, 0x0022, 0x0046 },\n  { 0x04, 0x05, -1, 0x03, 0x0022, 0x0066 },\n  { 0x04, 0x06, -1, 0x03, 0x0022, 0x0086 },\n  { 0x04, 0x07, -1, 0x03, 0x0022, 0x00c6 },\n  { 0x04, 0x08, -1, 0x03, 0x0022, 0x0146 },\n  { 0x04, 0x09, -1, 0x03, 0x0022, 0x0246 },\n  { 0x04, 0x0a, -1, 0x03, 0x0022, 0x0446 },\n  { 0x04, 0x18, -1, 0x03, 0x0022, 0x0846 },\n  { 0x04, 0x05, -1, 0x03, 0x0032, 0x0046 },\n  { 0x04, 0x05, -1, 0x03, 0x0032, 0x0066 },\n  { 0x04, 0x06, -1, 0x03, 0x0032, 0x0086 },\n  { 0x04, 0x07, -1, 0x03, 0x0032, 0x00c6 },\n  { 0x04, 0x08, -1, 0x03, 0x0032, 0x0146 },\n  { 0x04, 0x09, -1, 0x03, 0x0032, 0x0246 },\n  { 0x04, 0x0a, -1, 0x03, 0x0032, 0x0446 },\n  { 0x04, 0x18, -1, 0x03, 0x0032, 0x0846 },\n  { 0x05, 0x05, -1, 0x03, 0x0042, 0x0046 },\n  { 0x05, 0x05, -1, 0x03, 0x0042, 0x0066 },\n  { 0x05, 0x06, -1, 0x03, 0x0042, 0x0086 },\n  { 0x05, 0x07, -1, 0x03, 0x0042, 0x00c6 },\n  { 0x05, 0x08, -1, 0x03, 0x0042, 0x0146 },\n  { 0x05, 0x09, -1, 0x03, 0x0042, 0x0246 },\n  { 0x05, 0x0a, -1, 0x03, 0x0042, 0x0446 },\n  { 0x05, 0x18, -1, 0x03, 0x0042, 0x0846 },\n  { 0x05, 0x05, -1, 0x03, 0x0062, 0x0046 },\n  { 0x05, 0x05, -1, 0x03, 0x0062, 0x0066 },\n  { 0x05, 0x06, -1, 0x03, 0x0062, 0x0086 },\n  { 0x05, 0x07, -1, 0x03, 0x0062, 0x00c6 },\n  { 0x05, 0x08, -1, 0x03, 0x0062, 0x0146 },\n  { 0x05, 0x09, -1, 0x03, 0x0062, 0x0246 },\n  { 0x05, 0x0a, -1, 0x03, 0x0062, 0x0446 },\n  { 0x05, 0x18, -1, 0x03, 0x0062, 0x0846 },\n  { 0x06, 0x01, -1, 0x03, 0x0082, 0x000a },\n  { 0x06, 0x01, -1, 0x03, 0x0082, 0x000c },\n  { 0x06, 0x02, -1, 0x03, 0x0082, 0x000e },\n  { 0x06, 0x02, -1, 0x03, 0x0082, 0x0012 },\n  { 0x06, 0x03, -1, 0x03, 0x0082, 0x0016 },\n  { 0x06, 0x03, -1, 0x03, 0x0082, 0x001e },\n  { 0x06, 0x04, -1, 0x03, 0x0082, 0x0026 },\n  { 0x06, 0x04, -1, 0x03, 0x0082, 0x0036 },\n  { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000a },\n  { 0x07, 0x01, -1, 0x03, 0x00c2, 0x000c },\n  { 0x07, 0x02, -1, 0x03, 0x00c2, 0x000e },\n  { 0x07, 0x02, -1, 0x03, 0x00c2, 0x0012 },\n  { 0x07, 0x03, -1, 0x03, 0x00c2, 0x0016 },\n  { 0x07, 0x03, -1, 0x03, 0x00c2, 0x001e },\n  { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0026 },\n  { 0x07, 0x04, -1, 0x03, 0x00c2, 0x0036 },\n  { 0x08, 0x01, -1, 0x03, 0x0142, 0x000a },\n  { 0x08, 0x01, -1, 0x03, 0x0142, 0x000c },\n  { 0x08, 0x02, -1, 0x03, 0x0142, 0x000e },\n  { 0x08, 0x02, -1, 0x03, 0x0142, 0x0012 },\n  { 0x08, 0x03, -1, 0x03, 0x0142, 0x0016 },\n  { 0x08, 0x03, -1, 0x03, 0x0142, 0x001e },\n  { 0x08, 0x04, -1, 0x03, 0x0142, 0x0026 },\n  { 0x08, 0x04, -1, 0x03, 0x0142, 0x0036 },\n  { 0x09, 0x01, -1, 0x03, 0x0242, 0x000a },\n  { 0x09, 0x01, -1, 0x03, 0x0242, 0x000c },\n  { 0x09, 0x02, -1, 0x03, 0x0242, 0x000e },\n  { 0x09, 0x02, -1, 0x03, 0x0242, 0x0012 },\n  { 0x09, 0x03, -1, 0x03, 0x0242, 0x0016 },\n  { 0x09, 0x03, -1, 0x03, 0x0242, 0x001e },\n  { 0x09, 0x04, -1, 0x03, 0x0242, 0x0026 },\n  { 0x09, 0x04, -1, 0x03, 0x0242, 0x0036 },\n  { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000a },\n  { 0x0a, 0x01, -1, 0x03, 0x0442, 0x000c },\n  { 0x0a, 0x02, -1, 0x03, 0x0442, 0x000e },\n  { 0x0a, 0x02, -1, 0x03, 0x0442, 0x0012 },\n  { 0x0a, 0x03, -1, 0x03, 0x0442, 0x0016 },\n  { 0x0a, 0x03, -1, 0x03, 0x0442, 0x001e },\n  { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0026 },\n  { 0x0a, 0x04, -1, 0x03, 0x0442, 0x0036 },\n  { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000a },\n  { 0x0c, 0x01, -1, 0x03, 0x0842, 0x000c },\n  { 0x0c, 0x02, -1, 0x03, 0x0842, 0x000e },\n  { 0x0c, 0x02, -1, 0x03, 0x0842, 0x0012 },\n  { 0x0c, 0x03, -1, 0x03, 0x0842, 0x0016 },\n  { 0x0c, 0x03, -1, 0x03, 0x0842, 0x001e },\n  { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0026 },\n  { 0x0c, 0x04, -1, 0x03, 0x0842, 0x0036 },\n  { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000a },\n  { 0x0e, 0x01, -1, 0x03, 0x1842, 0x000c },\n  { 0x0e, 0x02, -1, 0x03, 0x1842, 0x000e },\n  { 0x0e, 0x02, -1, 0x03, 0x1842, 0x0012 },\n  { 0x0e, 0x03, -1, 0x03, 0x1842, 0x0016 },\n  { 0x0e, 0x03, -1, 0x03, 0x1842, 0x001e },\n  { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0026 },\n  { 0x0e, 0x04, -1, 0x03, 0x1842, 0x0036 },\n  { 0x18, 0x01, -1, 0x03, 0x5842, 0x000a },\n  { 0x18, 0x01, -1, 0x03, 0x5842, 0x000c },\n  { 0x18, 0x02, -1, 0x03, 0x5842, 0x000e },\n  { 0x18, 0x02, -1, 0x03, 0x5842, 0x0012 },\n  { 0x18, 0x03, -1, 0x03, 0x5842, 0x0016 },\n  { 0x18, 0x03, -1, 0x03, 0x5842, 0x001e },\n  { 0x18, 0x04, -1, 0x03, 0x5842, 0x0026 },\n  { 0x18, 0x04, -1, 0x03, 0x5842, 0x0036 },\n  { 0x06, 0x05, -1, 0x03, 0x0082, 0x0046 },\n  { 0x06, 0x05, -1, 0x03, 0x0082, 0x0066 },\n  { 0x06, 0x06, -1, 0x03, 0x0082, 0x0086 },\n  { 0x06, 0x07, -1, 0x03, 0x0082, 0x00c6 },\n  { 0x06, 0x08, -1, 0x03, 0x0082, 0x0146 },\n  { 0x06, 0x09, -1, 0x03, 0x0082, 0x0246 },\n  { 0x06, 0x0a, -1, 0x03, 0x0082, 0x0446 },\n  { 0x06, 0x18, -1, 0x03, 0x0082, 0x0846 },\n  { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0046 },\n  { 0x07, 0x05, -1, 0x03, 0x00c2, 0x0066 },\n  { 0x07, 0x06, -1, 0x03, 0x00c2, 0x0086 },\n  { 0x07, 0x07, -1, 0x03, 0x00c2, 0x00c6 },\n  { 0x07, 0x08, -1, 0x03, 0x00c2, 0x0146 },\n  { 0x07, 0x09, -1, 0x03, 0x00c2, 0x0246 },\n  { 0x07, 0x0a, -1, 0x03, 0x00c2, 0x0446 },\n  { 0x07, 0x18, -1, 0x03, 0x00c2, 0x0846 },\n  { 0x08, 0x05, -1, 0x03, 0x0142, 0x0046 },\n  { 0x08, 0x05, -1, 0x03, 0x0142, 0x0066 },\n  { 0x08, 0x06, -1, 0x03, 0x0142, 0x0086 },\n  { 0x08, 0x07, -1, 0x03, 0x0142, 0x00c6 },\n  { 0x08, 0x08, -1, 0x03, 0x0142, 0x0146 },\n  { 0x08, 0x09, -1, 0x03, 0x0142, 0x0246 },\n  { 0x08, 0x0a, -1, 0x03, 0x0142, 0x0446 },\n  { 0x08, 0x18, -1, 0x03, 0x0142, 0x0846 },\n  { 0x09, 0x05, -1, 0x03, 0x0242, 0x0046 },\n  { 0x09, 0x05, -1, 0x03, 0x0242, 0x0066 },\n  { 0x09, 0x06, -1, 0x03, 0x0242, 0x0086 },\n  { 0x09, 0x07, -1, 0x03, 0x0242, 0x00c6 },\n  { 0x09, 0x08, -1, 0x03, 0x0242, 0x0146 },\n  { 0x09, 0x09, -1, 0x03, 0x0242, 0x0246 },\n  { 0x09, 0x0a, -1, 0x03, 0x0242, 0x0446 },\n  { 0x09, 0x18, -1, 0x03, 0x0242, 0x0846 },\n  { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0046 },\n  { 0x0a, 0x05, -1, 0x03, 0x0442, 0x0066 },\n  { 0x0a, 0x06, -1, 0x03, 0x0442, 0x0086 },\n  { 0x0a, 0x07, -1, 0x03, 0x0442, 0x00c6 },\n  { 0x0a, 0x08, -1, 0x03, 0x0442, 0x0146 },\n  { 0x0a, 0x09, -1, 0x03, 0x0442, 0x0246 },\n  { 0x0a, 0x0a, -1, 0x03, 0x0442, 0x0446 },\n  { 0x0a, 0x18, -1, 0x03, 0x0442, 0x0846 },\n  { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0046 },\n  { 0x0c, 0x05, -1, 0x03, 0x0842, 0x0066 },\n  { 0x0c, 0x06, -1, 0x03, 0x0842, 0x0086 },\n  { 0x0c, 0x07, -1, 0x03, 0x0842, 0x00c6 },\n  { 0x0c, 0x08, -1, 0x03, 0x0842, 0x0146 },\n  { 0x0c, 0x09, -1, 0x03, 0x0842, 0x0246 },\n  { 0x0c, 0x0a, -1, 0x03, 0x0842, 0x0446 },\n  { 0x0c, 0x18, -1, 0x03, 0x0842, 0x0846 },\n  { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0046 },\n  { 0x0e, 0x05, -1, 0x03, 0x1842, 0x0066 },\n  { 0x0e, 0x06, -1, 0x03, 0x1842, 0x0086 },\n  { 0x0e, 0x07, -1, 0x03, 0x1842, 0x00c6 },\n  { 0x0e, 0x08, -1, 0x03, 0x1842, 0x0146 },\n  { 0x0e, 0x09, -1, 0x03, 0x1842, 0x0246 },\n  { 0x0e, 0x0a, -1, 0x03, 0x1842, 0x0446 },\n  { 0x0e, 0x18, -1, 0x03, 0x1842, 0x0846 },\n  { 0x18, 0x05, -1, 0x03, 0x5842, 0x0046 },\n  { 0x18, 0x05, -1, 0x03, 0x5842, 0x0066 },\n  { 0x18, 0x06, -1, 0x03, 0x5842, 0x0086 },\n  { 0x18, 0x07, -1, 0x03, 0x5842, 0x00c6 },\n  { 0x18, 0x08, -1, 0x03, 0x5842, 0x0146 },\n  { 0x18, 0x09, -1, 0x03, 0x5842, 0x0246 },\n  { 0x18, 0x0a, -1, 0x03, 0x5842, 0x0446 },\n  { 0x18, 0x18, -1, 0x03, 0x5842, 0x0846 },\n};\n\n#endif  /* BROTLI_DEC_PREFIX_H_ */\n"
  },
  {
    "path": "third-party/brotli/dec/state.c",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"state.h\"\n\n#include <stdlib.h>  /* free, malloc */\n\n#include <brotli/types.h>\n\n#include \"../common/dictionary.h\"\n#include \"huffman.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nBROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  if (!alloc_func) {\n    s->alloc_func = BrotliDefaultAllocFunc;\n    s->free_func = BrotliDefaultFreeFunc;\n    s->memory_manager_opaque = 0;\n  } else {\n    s->alloc_func = alloc_func;\n    s->free_func = free_func;\n    s->memory_manager_opaque = opaque;\n  }\n\n  s->error_code = 0; /* BROTLI_DECODER_NO_ERROR */\n\n  BrotliInitBitReader(&s->br);\n  s->state = BROTLI_STATE_UNINITED;\n  s->large_window = 0;\n  s->substate_metablock_header = BROTLI_STATE_METABLOCK_HEADER_NONE;\n  s->substate_uncompressed = BROTLI_STATE_UNCOMPRESSED_NONE;\n  s->substate_decode_uint8 = BROTLI_STATE_DECODE_UINT8_NONE;\n  s->substate_read_block_length = BROTLI_STATE_READ_BLOCK_LENGTH_NONE;\n\n  s->buffer_length = 0;\n  s->loop_counter = 0;\n  s->pos = 0;\n  s->rb_roundtrips = 0;\n  s->partial_pos_out = 0;\n  s->used_input = 0;\n\n  s->block_type_trees = NULL;\n  s->block_len_trees = NULL;\n  s->ringbuffer = NULL;\n  s->ringbuffer_size = 0;\n  s->new_ringbuffer_size = 0;\n  s->ringbuffer_mask = 0;\n\n  s->context_map = NULL;\n  s->context_modes = NULL;\n  s->dist_context_map = NULL;\n  s->context_map_slice = NULL;\n  s->dist_context_map_slice = NULL;\n\n  s->literal_hgroup.codes = NULL;\n  s->literal_hgroup.htrees = NULL;\n  s->insert_copy_hgroup.codes = NULL;\n  s->insert_copy_hgroup.htrees = NULL;\n  s->distance_hgroup.codes = NULL;\n  s->distance_hgroup.htrees = NULL;\n\n  s->is_last_metablock = 0;\n  s->is_uncompressed = 0;\n  s->is_metadata = 0;\n  s->should_wrap_ringbuffer = 0;\n  s->canny_ringbuffer_allocation = 1;\n\n  s->window_bits = 0;\n  s->max_distance = 0;\n  s->dist_rb[0] = 16;\n  s->dist_rb[1] = 15;\n  s->dist_rb[2] = 11;\n  s->dist_rb[3] = 4;\n  s->dist_rb_idx = 0;\n  s->block_type_trees = NULL;\n  s->block_len_trees = NULL;\n\n  s->mtf_upper_bound = 63;\n\n  s->compound_dictionary = NULL;\n  s->dictionary =\n      BrotliSharedDictionaryCreateInstance(alloc_func, free_func, opaque);\n  if (!s->dictionary) return BROTLI_FALSE;\n\n  s->metadata_start_func = NULL;\n  s->metadata_chunk_func = NULL;\n  s->metadata_callback_opaque = 0;\n\n  return BROTLI_TRUE;\n}\n\nvoid BrotliDecoderStateMetablockBegin(BrotliDecoderState* s) {\n  s->meta_block_remaining_len = 0;\n  s->block_length[0] = BROTLI_BLOCK_SIZE_CAP;\n  s->block_length[1] = BROTLI_BLOCK_SIZE_CAP;\n  s->block_length[2] = BROTLI_BLOCK_SIZE_CAP;\n  s->num_block_types[0] = 1;\n  s->num_block_types[1] = 1;\n  s->num_block_types[2] = 1;\n  s->block_type_rb[0] = 1;\n  s->block_type_rb[1] = 0;\n  s->block_type_rb[2] = 1;\n  s->block_type_rb[3] = 0;\n  s->block_type_rb[4] = 1;\n  s->block_type_rb[5] = 0;\n  s->context_map = NULL;\n  s->context_modes = NULL;\n  s->dist_context_map = NULL;\n  s->context_map_slice = NULL;\n  s->literal_htree = NULL;\n  s->dist_context_map_slice = NULL;\n  s->dist_htree_index = 0;\n  s->context_lookup = NULL;\n  s->literal_hgroup.codes = NULL;\n  s->literal_hgroup.htrees = NULL;\n  s->insert_copy_hgroup.codes = NULL;\n  s->insert_copy_hgroup.htrees = NULL;\n  s->distance_hgroup.codes = NULL;\n  s->distance_hgroup.htrees = NULL;\n}\n\nvoid BrotliDecoderStateCleanupAfterMetablock(BrotliDecoderState* s) {\n  BROTLI_DECODER_FREE(s, s->context_modes);\n  BROTLI_DECODER_FREE(s, s->context_map);\n  BROTLI_DECODER_FREE(s, s->dist_context_map);\n  BROTLI_DECODER_FREE(s, s->literal_hgroup.htrees);\n  BROTLI_DECODER_FREE(s, s->insert_copy_hgroup.htrees);\n  BROTLI_DECODER_FREE(s, s->distance_hgroup.htrees);\n}\n\n#ifdef BROTLI_REPORTING\n/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */\nvoid BrotliDecoderOnFinish(const BrotliDecoderState* s);\n#define BROTLI_DECODER_ON_FINISH(s) BrotliDecoderOnFinish(s);\n#else\n#if !defined(BROTLI_DECODER_ON_FINISH)\n#define BROTLI_DECODER_ON_FINISH(s) (void)(s);\n#endif\n#endif\n\nvoid BrotliDecoderStateCleanup(BrotliDecoderState* s) {\n  BrotliDecoderStateCleanupAfterMetablock(s);\n\n  BROTLI_DECODER_ON_FINISH(s);\n\n  BROTLI_DECODER_FREE(s, s->compound_dictionary);\n  BrotliSharedDictionaryDestroyInstance(s->dictionary);\n  s->dictionary = NULL;\n  BROTLI_DECODER_FREE(s, s->ringbuffer);\n  BROTLI_DECODER_FREE(s, s->block_type_trees);\n}\n\nBROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(BrotliDecoderState* s,\n    HuffmanTreeGroup* group, brotli_reg_t alphabet_size_max,\n    brotli_reg_t alphabet_size_limit, brotli_reg_t ntrees) {\n  /* 376 = 256 (1-st level table) + 4 + 7 + 15 + 31 + 63 (2-nd level mix-tables)\n     This number is discovered \"unlimited\" \"enough\" calculator; it is actually\n     a wee bigger than required in several cases (especially for alphabets with\n     less than 16 symbols). */\n  const size_t max_table_size = alphabet_size_limit + 376;\n  const size_t code_size = sizeof(HuffmanCode) * ntrees * max_table_size;\n  const size_t htree_size = sizeof(HuffmanCode*) * ntrees;\n  /* Pointer alignment is, hopefully, wider than sizeof(HuffmanCode). */\n  HuffmanCode** p = (HuffmanCode**)BROTLI_DECODER_ALLOC(s,\n      code_size + htree_size);\n  group->alphabet_size_max = (uint16_t)alphabet_size_max;\n  group->alphabet_size_limit = (uint16_t)alphabet_size_limit;\n  group->num_htrees = (uint16_t)ntrees;\n  group->htrees = p;\n  group->codes = (HuffmanCode*)(&p[ntrees]);\n  return !!p;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/dec/state.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Brotli state for partial streaming decoding. */\n\n#ifndef BROTLI_DEC_STATE_H_\n#define BROTLI_DEC_STATE_H_\n\n#include <brotli/decode.h>\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/transform.h\"\n#include \"bit_reader.h\"\n#include \"huffman.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Graphviz diagram that describes state transitions:\n\ndigraph States {\n  graph [compound=true]\n  concentrate=true\n  node [shape=\"box\"]\n\n  UNINITED -> {LARGE_WINDOW_BITS -> INITIALIZE}\n  subgraph cluster_metablock_workflow {\n    style=\"rounded\"\n    label=< <B>METABLOCK CYCLE</B> >\n    METABLOCK_BEGIN -> METABLOCK_HEADER\n    METABLOCK_HEADER:sw -> METADATA\n    METABLOCK_HEADER:s -> UNCOMPRESSED\n    METABLOCK_HEADER:se -> METABLOCK_DONE:ne\n    METADATA:s -> METABLOCK_DONE:w\n    UNCOMPRESSED:s -> METABLOCK_DONE:n\n    METABLOCK_DONE:e -> METABLOCK_BEGIN:e [constraint=\"false\"]\n  }\n  INITIALIZE -> METABLOCK_BEGIN\n  METABLOCK_DONE -> DONE\n\n  subgraph cluster_compressed_metablock {\n    style=\"rounded\"\n    label=< <B>COMPRESSED METABLOCK</B> >\n\n    subgraph cluster_command {\n      style=\"rounded\"\n      label=< <B>HOT LOOP</B> >\n\n      _METABLOCK_DONE_PORT_ [shape=point style=invis]\n\n      {\n        // Set different shape for nodes returning from \"compressed metablock\".\n        node [shape=invhouse]; CMD_INNER CMD_POST_DECODE_LITERALS;\n        CMD_POST_WRAP_COPY; CMD_INNER_WRITE; CMD_POST_WRITE_1;\n      }\n\n      CMD_BEGIN -> CMD_INNER -> CMD_POST_DECODE_LITERALS -> CMD_POST_WRAP_COPY\n\n      // IO (\"write\") nodes are not in the hot loop!\n      CMD_INNER_WRITE [style=dashed]\n      CMD_INNER -> CMD_INNER_WRITE\n      CMD_POST_WRITE_1 [style=dashed]\n      CMD_POST_DECODE_LITERALS -> CMD_POST_WRITE_1\n      CMD_POST_WRITE_2 [style=dashed]\n      CMD_POST_WRAP_COPY -> CMD_POST_WRITE_2\n\n      CMD_POST_WRITE_1 -> CMD_BEGIN:s [constraint=\"false\"]\n      CMD_INNER_WRITE -> {CMD_INNER CMD_POST_DECODE_LITERALS}\n          [constraint=\"false\"]\n      CMD_BEGIN:ne -> CMD_POST_DECODE_LITERALS [constraint=\"false\"]\n      CMD_POST_WRAP_COPY -> CMD_BEGIN [constraint=\"false\"]\n      CMD_POST_DECODE_LITERALS -> CMD_BEGIN:ne [constraint=\"false\"]\n      CMD_POST_WRITE_2 -> CMD_POST_WRAP_COPY [constraint=\"false\"]\n      {rank=same; CMD_BEGIN; CMD_INNER; CMD_POST_DECODE_LITERALS;\n          CMD_POST_WRAP_COPY}\n      {rank=same; CMD_INNER_WRITE; CMD_POST_WRITE_1; CMD_POST_WRITE_2}\n\n      {CMD_INNER CMD_POST_DECODE_LITERALS CMD_POST_WRAP_COPY} ->\n          _METABLOCK_DONE_PORT_ [style=invis]\n      {CMD_INNER_WRITE CMD_POST_WRITE_1} -> _METABLOCK_DONE_PORT_\n          [constraint=\"false\" style=invis]\n    }\n\n    BEFORE_COMPRESSED_METABLOCK_HEADER:s -> HUFFMAN_CODE_0:n\n    HUFFMAN_CODE_0 -> HUFFMAN_CODE_1 -> HUFFMAN_CODE_2 -> HUFFMAN_CODE_3\n    HUFFMAN_CODE_0 -> METABLOCK_HEADER_2 -> CONTEXT_MODES -> CONTEXT_MAP_1\n    CONTEXT_MAP_1 -> CONTEXT_MAP_2 -> TREE_GROUP\n    TREE_GROUP -> BEFORE_COMPRESSED_METABLOCK_BODY:e\n    BEFORE_COMPRESSED_METABLOCK_BODY:s -> CMD_BEGIN:n\n\n    HUFFMAN_CODE_3:e -> HUFFMAN_CODE_0:ne [constraint=\"false\"]\n    {rank=same; HUFFMAN_CODE_0; HUFFMAN_CODE_1; HUFFMAN_CODE_2; HUFFMAN_CODE_3}\n    {rank=same; METABLOCK_HEADER_2; CONTEXT_MODES; CONTEXT_MAP_1; CONTEXT_MAP_2;\n        TREE_GROUP}\n  }\n  METABLOCK_HEADER:e -> BEFORE_COMPRESSED_METABLOCK_HEADER:n\n\n  _METABLOCK_DONE_PORT_ -> METABLOCK_DONE:se\n      [constraint=\"false\" ltail=cluster_command]\n\n  UNINITED [shape=Mdiamond];\n  DONE [shape=Msquare];\n}\n\n\n */\n\ntypedef enum {\n  BROTLI_STATE_UNINITED,\n  BROTLI_STATE_LARGE_WINDOW_BITS,\n  BROTLI_STATE_INITIALIZE,\n  BROTLI_STATE_METABLOCK_BEGIN,\n  BROTLI_STATE_METABLOCK_HEADER,\n  BROTLI_STATE_METABLOCK_HEADER_2,\n  BROTLI_STATE_CONTEXT_MODES,\n  BROTLI_STATE_COMMAND_BEGIN,\n  BROTLI_STATE_COMMAND_INNER,\n  BROTLI_STATE_COMMAND_POST_DECODE_LITERALS,\n  BROTLI_STATE_COMMAND_POST_WRAP_COPY,\n  BROTLI_STATE_UNCOMPRESSED,\n  BROTLI_STATE_METADATA,\n  BROTLI_STATE_COMMAND_INNER_WRITE,\n  BROTLI_STATE_METABLOCK_DONE,\n  BROTLI_STATE_COMMAND_POST_WRITE_1,\n  BROTLI_STATE_COMMAND_POST_WRITE_2,\n  BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_HEADER,\n  BROTLI_STATE_HUFFMAN_CODE_0,\n  BROTLI_STATE_HUFFMAN_CODE_1,\n  BROTLI_STATE_HUFFMAN_CODE_2,\n  BROTLI_STATE_HUFFMAN_CODE_3,\n  BROTLI_STATE_CONTEXT_MAP_1,\n  BROTLI_STATE_CONTEXT_MAP_2,\n  BROTLI_STATE_TREE_GROUP,\n  BROTLI_STATE_BEFORE_COMPRESSED_METABLOCK_BODY,\n  BROTLI_STATE_DONE\n} BrotliRunningState;\n\ntypedef enum {\n  BROTLI_STATE_METABLOCK_HEADER_NONE,\n  BROTLI_STATE_METABLOCK_HEADER_EMPTY,\n  BROTLI_STATE_METABLOCK_HEADER_NIBBLES,\n  BROTLI_STATE_METABLOCK_HEADER_SIZE,\n  BROTLI_STATE_METABLOCK_HEADER_UNCOMPRESSED,\n  BROTLI_STATE_METABLOCK_HEADER_RESERVED,\n  BROTLI_STATE_METABLOCK_HEADER_BYTES,\n  BROTLI_STATE_METABLOCK_HEADER_METADATA\n} BrotliRunningMetablockHeaderState;\n\ntypedef enum {\n  BROTLI_STATE_UNCOMPRESSED_NONE,\n  BROTLI_STATE_UNCOMPRESSED_WRITE\n} BrotliRunningUncompressedState;\n\ntypedef enum {\n  BROTLI_STATE_TREE_GROUP_NONE,\n  BROTLI_STATE_TREE_GROUP_LOOP\n} BrotliRunningTreeGroupState;\n\ntypedef enum {\n  BROTLI_STATE_CONTEXT_MAP_NONE,\n  BROTLI_STATE_CONTEXT_MAP_READ_PREFIX,\n  BROTLI_STATE_CONTEXT_MAP_HUFFMAN,\n  BROTLI_STATE_CONTEXT_MAP_DECODE,\n  BROTLI_STATE_CONTEXT_MAP_TRANSFORM\n} BrotliRunningContextMapState;\n\ntypedef enum {\n  BROTLI_STATE_HUFFMAN_NONE,\n  BROTLI_STATE_HUFFMAN_SIMPLE_SIZE,\n  BROTLI_STATE_HUFFMAN_SIMPLE_READ,\n  BROTLI_STATE_HUFFMAN_SIMPLE_BUILD,\n  BROTLI_STATE_HUFFMAN_COMPLEX,\n  BROTLI_STATE_HUFFMAN_LENGTH_SYMBOLS\n} BrotliRunningHuffmanState;\n\ntypedef enum {\n  BROTLI_STATE_DECODE_UINT8_NONE,\n  BROTLI_STATE_DECODE_UINT8_SHORT,\n  BROTLI_STATE_DECODE_UINT8_LONG\n} BrotliRunningDecodeUint8State;\n\ntypedef enum {\n  BROTLI_STATE_READ_BLOCK_LENGTH_NONE,\n  BROTLI_STATE_READ_BLOCK_LENGTH_SUFFIX\n} BrotliRunningReadBlockLengthState;\n\n/* BrotliDecoderState addon, used for Compound Dictionary functionality. */\ntypedef struct BrotliDecoderCompoundDictionary {\n  int num_chunks;\n  int total_size;\n  int br_index;\n  int br_offset;\n  int br_length;\n  int br_copied;\n  const uint8_t* chunks[16];\n  int chunk_offsets[16];\n  int block_bits;\n  uint8_t block_map[256];\n} BrotliDecoderCompoundDictionary;\n\ntypedef struct BrotliMetablockHeaderArena {\n  BrotliRunningTreeGroupState substate_tree_group;\n  BrotliRunningContextMapState substate_context_map;\n  BrotliRunningHuffmanState substate_huffman;\n\n  brotli_reg_t sub_loop_counter;\n\n  brotli_reg_t repeat_code_len;\n  brotli_reg_t prev_code_len;\n\n  /* For ReadHuffmanCode. */\n  brotli_reg_t symbol;\n  brotli_reg_t repeat;\n  brotli_reg_t space;\n\n  /* Huffman table for \"histograms\". */\n  HuffmanCode table[32];\n  /* List of heads of symbol chains. */\n  uint16_t* symbol_lists;\n  /* Storage from symbol_lists. */\n  uint16_t symbols_lists_array[BROTLI_HUFFMAN_MAX_CODE_LENGTH + 1 +\n                               BROTLI_NUM_COMMAND_SYMBOLS];\n  /* Tails of symbol chains. */\n  int next_symbol[32];\n  uint8_t code_length_code_lengths[BROTLI_CODE_LENGTH_CODES];\n  /* Population counts for the code lengths. */\n  uint16_t code_length_histo[16];\n  /* TODO(eustas): +2 bytes padding */\n\n  /* For HuffmanTreeGroupDecode. */\n  int htree_index;\n  HuffmanCode* next;\n\n  /* For DecodeContextMap. */\n  brotli_reg_t context_index;\n  brotli_reg_t max_run_length_prefix;\n  brotli_reg_t code;\n  HuffmanCode context_map_table[BROTLI_HUFFMAN_MAX_SIZE_272];\n} BrotliMetablockHeaderArena;\n\ntypedef struct BrotliMetablockBodyArena {\n  uint8_t dist_extra_bits[544];\n  brotli_reg_t dist_offset[544];\n} BrotliMetablockBodyArena;\n\nstruct BrotliDecoderStateStruct {\n  BrotliRunningState state;\n\n  /* This counter is reused for several disjoint loops. */\n  int loop_counter;\n\n  BrotliBitReader br;\n\n  brotli_alloc_func alloc_func;\n  brotli_free_func free_func;\n  void* memory_manager_opaque;\n\n  /* Temporary storage for remaining input. Brotli stream format is designed in\n     a way, that 64 bits are enough to make progress in decoding. */\n  union {\n    uint64_t u64;\n    uint8_t u8[8];\n  } buffer;\n  brotli_reg_t buffer_length;\n\n  int pos;\n  int max_backward_distance;\n  int max_distance;\n  int ringbuffer_size;\n  int ringbuffer_mask;\n  int dist_rb_idx;\n  int dist_rb[4];\n  int error_code;\n  int meta_block_remaining_len;\n\n  uint8_t* ringbuffer;\n  uint8_t* ringbuffer_end;\n  HuffmanCode* htree_command;\n  const uint8_t* context_lookup;\n  uint8_t* context_map_slice;\n  uint8_t* dist_context_map_slice;\n\n  /* This ring buffer holds a few past copy distances that will be used by\n     some special distance codes. */\n  HuffmanTreeGroup literal_hgroup;\n  HuffmanTreeGroup insert_copy_hgroup;\n  HuffmanTreeGroup distance_hgroup;\n  HuffmanCode* block_type_trees;\n  HuffmanCode* block_len_trees;\n  /* This is true if the literal context map histogram type always matches the\n     block type. It is then not needed to keep the context (faster decoding). */\n  int trivial_literal_context;\n  /* Distance context is actual after command is decoded and before distance is\n     computed. After distance computation it is used as a temporary variable. */\n  int distance_context;\n  brotli_reg_t block_length[3];\n  brotli_reg_t block_length_index;\n  brotli_reg_t num_block_types[3];\n  brotli_reg_t block_type_rb[6];\n  brotli_reg_t distance_postfix_bits;\n  brotli_reg_t num_direct_distance_codes;\n  brotli_reg_t num_dist_htrees;\n  uint8_t* dist_context_map;\n  HuffmanCode* literal_htree;\n\n  /* For partial write operations. */\n  size_t rb_roundtrips;  /* how many times we went around the ring-buffer */\n  size_t partial_pos_out;  /* how much output to the user in total */\n\n  /* For InverseMoveToFrontTransform. */\n  brotli_reg_t mtf_upper_bound;\n  uint32_t mtf[64 + 1];\n\n  int copy_length;\n  int distance_code;\n\n  uint8_t dist_htree_index;\n  /* TODO(eustas): +3 bytes padding */\n\n  /* Less used attributes are at the end of this struct. */\n\n  brotli_decoder_metadata_start_func metadata_start_func;\n  brotli_decoder_metadata_chunk_func metadata_chunk_func;\n  void* metadata_callback_opaque;\n\n  /* For reporting. */\n  uint64_t used_input;  /* how many bytes of input are consumed */\n\n  /* States inside function calls. */\n  BrotliRunningMetablockHeaderState substate_metablock_header;\n  BrotliRunningUncompressedState substate_uncompressed;\n  BrotliRunningDecodeUint8State substate_decode_uint8;\n  BrotliRunningReadBlockLengthState substate_read_block_length;\n\n  int new_ringbuffer_size;\n  /* TODO(eustas): +4 bytes padding */\n\n  unsigned int is_last_metablock : 1;\n  unsigned int is_uncompressed : 1;\n  unsigned int is_metadata : 1;\n  unsigned int should_wrap_ringbuffer : 1;\n  unsigned int canny_ringbuffer_allocation : 1;\n  unsigned int large_window : 1;\n  unsigned int window_bits : 6;\n  unsigned int size_nibbles : 8;\n  /* TODO(eustas): +12 bits padding */\n\n  brotli_reg_t num_literal_htrees;\n  uint8_t* context_map;\n  uint8_t* context_modes;\n\n  BrotliSharedDictionary* dictionary;\n  BrotliDecoderCompoundDictionary* compound_dictionary;\n\n  uint32_t trivial_literal_contexts[8];  /* 256 bits */\n\n  union {\n    BrotliMetablockHeaderArena header;\n    BrotliMetablockBodyArena body;\n  } arena;\n};\n\ntypedef struct BrotliDecoderStateStruct BrotliDecoderStateInternal;\n#define BrotliDecoderState BrotliDecoderStateInternal\n\nBROTLI_INTERNAL BROTLI_BOOL BrotliDecoderStateInit(BrotliDecoderState* s,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\nBROTLI_INTERNAL void BrotliDecoderStateCleanup(BrotliDecoderState* s);\nBROTLI_INTERNAL void BrotliDecoderStateMetablockBegin(BrotliDecoderState* s);\nBROTLI_INTERNAL void BrotliDecoderStateCleanupAfterMetablock(\n    BrotliDecoderState* s);\nBROTLI_INTERNAL BROTLI_BOOL BrotliDecoderHuffmanTreeGroupInit(\n    BrotliDecoderState* s, HuffmanTreeGroup* group,\n    brotli_reg_t alphabet_size_max, brotli_reg_t alphabet_size_limit,\n    brotli_reg_t ntrees);\n\n#define BROTLI_DECODER_ALLOC(S, L) S->alloc_func(S->memory_manager_opaque, L)\n\n#define BROTLI_DECODER_FREE(S, X) {          \\\n  S->free_func(S->memory_manager_opaque, X); \\\n  X = NULL;                                  \\\n}\n\n/* Literal/Command/Distance block size maximum; same as maximum metablock size;\n   used as block size when there is no block switching. */\n#define BROTLI_BLOCK_SIZE_CAP (1U << 24)\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_STATE_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/backward_references.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#include \"backward_references.h\"\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"compound_dictionary.h\"\n#include \"dictionary_hash.h\"\n#include \"encoder_dict.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE size_t ComputeDistanceCode(size_t distance,\n                                                size_t max_distance,\n                                                const int* dist_cache) {\n  if (distance <= max_distance) {\n    size_t distance_plus_3 = distance + 3;\n    size_t offset0 = distance_plus_3 - (size_t)dist_cache[0];\n    size_t offset1 = distance_plus_3 - (size_t)dist_cache[1];\n    if (distance == (size_t)dist_cache[0]) {\n      return 0;\n    } else if (distance == (size_t)dist_cache[1]) {\n      return 1;\n    } else if (offset0 < 7) {\n      return (0x9750468 >> (4 * offset0)) & 0xF;\n    } else if (offset1 < 7) {\n      return (0xFDB1ACE >> (4 * offset1)) & 0xF;\n    } else if (distance == (size_t)dist_cache[2]) {\n      return 2;\n    } else if (distance == (size_t)dist_cache[3]) {\n      return 3;\n    }\n  }\n  return distance + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;\n}\n\n#define EXPAND_CAT(a, b) CAT(a, b)\n#define CAT(a, b) a ## b\n#define FN(X) EXPAND_CAT(X, HASHER())\n#define EXPORT_FN(X) EXPAND_CAT(X, EXPAND_CAT(PREFIX(), HASHER()))\n\n#define PREFIX() N\n#define ENABLE_COMPOUND_DICTIONARY 0\n\n#define HASHER() H2\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H3\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H4\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H5\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H6\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H40\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H41\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H42\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H54\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H35\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H55\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#define HASHER() H65\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#undef ENABLE_COMPOUND_DICTIONARY\n#undef PREFIX\n#define PREFIX() D\n#define ENABLE_COMPOUND_DICTIONARY 1\n\n#define HASHER() H5\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H6\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H40\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H41\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H42\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H55\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n#define HASHER() H65\n/* NOLINTNEXTLINE(build/include) */\n#include \"backward_references_inc.h\"\n#undef HASHER\n\n#undef ENABLE_COMPOUND_DICTIONARY\n#undef PREFIX\n\n#undef EXPORT_FN\n#undef FN\n#undef CAT\n#undef EXPAND_CAT\n\nvoid BrotliCreateBackwardReferences(size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  if (params->dictionary.compound.num_chunks != 0) {\n    switch (params->hasher.type) {\n#define CASE_(N)                                                    \\\n      case N:                                                       \\\n        CreateBackwardReferencesDH ## N(num_bytes,                  \\\n            position, ringbuffer, ringbuffer_mask,                  \\\n            literal_context_lut, params, hasher, dist_cache,        \\\n            last_insert_len, commands, num_commands, num_literals); \\\n        return;\n      CASE_(5)\n      CASE_(6)\n      CASE_(40)\n      CASE_(41)\n      CASE_(42)\n      CASE_(55)\n      CASE_(65)\n#undef CASE_\n      default:\n        BROTLI_DCHECK(false);\n        break;\n    }\n  }\n\n  switch (params->hasher.type) {\n#define CASE_(N)                                                  \\\n    case N:                                                       \\\n      CreateBackwardReferencesNH ## N(num_bytes,                  \\\n          position, ringbuffer, ringbuffer_mask,                  \\\n          literal_context_lut, params, hasher, dist_cache,        \\\n          last_insert_len, commands, num_commands, num_literals); \\\n      return;\n    FOR_GENERIC_HASHERS(CASE_)\n#undef CASE_\n    default:\n      BROTLI_DCHECK(false);\n      break;\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/backward_references.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#ifndef BROTLI_ENC_BACKWARD_REFERENCES_H_\n#define BROTLI_ENC_BACKWARD_REFERENCES_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"hash.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* \"commands\" points to the next output command to write to, \"*num_commands\" is\n   initially the total amount of commands output by previous\n   CreateBackwardReferences calls, and must be incremented by the amount written\n   by this call. */\nBROTLI_INTERNAL void BrotliCreateBackwardReferences(size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BACKWARD_REFERENCES_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/backward_references_hq.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#include \"backward_references_hq.h\"\n\n#include <string.h>  /* memcpy, memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"compound_dictionary.h\"\n#include \"encoder_dict.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"literal_cost.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"prefix.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* BrotliCalculateDistanceCodeLimit(BROTLI_MAX_ALLOWED_DISTANCE, 3, 120). */\n#define BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE 544\n\nstatic const float kInfinity = 1.7e38f;  /* ~= 2 ^ 127 */\n\nstatic const uint32_t kDistanceCacheIndex[] = {\n  0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1,\n};\nstatic const int kDistanceCacheOffset[] = {\n  0, 0, 0, 0, -1, 1, -2, 2, -3, 3, -1, 1, -2, 2, -3, 3\n};\n\nvoid BrotliInitZopfliNodes(ZopfliNode* array, size_t length) {\n  ZopfliNode stub;\n  size_t i;\n  stub.length = 1;\n  stub.distance = 0;\n  stub.dcode_insert_length = 0;\n  stub.u.cost = kInfinity;\n  for (i = 0; i < length; ++i) array[i] = stub;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeCopyLength(const ZopfliNode* self) {\n  return self->length & 0x1FFFFFF;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeLengthCode(const ZopfliNode* self) {\n  const uint32_t modifier = self->length >> 25;\n  return ZopfliNodeCopyLength(self) + 9u - modifier;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeCopyDistance(const ZopfliNode* self) {\n  return self->distance;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeDistanceCode(const ZopfliNode* self) {\n  const uint32_t short_code = self->dcode_insert_length >> 27;\n  return short_code == 0 ?\n      ZopfliNodeCopyDistance(self) + BROTLI_NUM_DISTANCE_SHORT_CODES - 1 :\n      short_code - 1;\n}\n\nstatic BROTLI_INLINE uint32_t ZopfliNodeCommandLength(const ZopfliNode* self) {\n  return ZopfliNodeCopyLength(self) + (self->dcode_insert_length & 0x7FFFFFF);\n}\n\n/* Temporary data for ZopfliCostModelSetFromCommands. */\ntypedef struct ZopfliCostModelArena {\n  uint32_t histogram_literal[BROTLI_NUM_LITERAL_SYMBOLS];\n  uint32_t histogram_cmd[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint32_t histogram_dist[BROTLI_MAX_EFFECTIVE_DISTANCE_ALPHABET_SIZE];\n  float cost_literal[BROTLI_NUM_LITERAL_SYMBOLS];\n} ZopfliCostModelArena;\n\n/* Histogram based cost model for zopflification. */\ntypedef struct ZopfliCostModel {\n  /* The insert and copy length symbols. */\n  float cost_cmd_[BROTLI_NUM_COMMAND_SYMBOLS];\n  float* cost_dist_;\n  uint32_t distance_histogram_size;\n  /* Cumulative costs of literals per position in the stream. */\n  float* literal_costs_;\n  float min_cost_cmd_;\n  size_t num_bytes_;\n\n  /* Temporary data. */\n  union {\n    size_t literal_histograms[3 * 256];\n    ZopfliCostModelArena arena;\n  };\n} ZopfliCostModel;\n\nstatic void InitZopfliCostModel(\n    MemoryManager* m, ZopfliCostModel* self, const BrotliDistanceParams* dist,\n    size_t num_bytes) {\n  self->num_bytes_ = num_bytes;\n  self->literal_costs_ = BROTLI_ALLOC(m, float, num_bytes + 2);\n  self->cost_dist_ = BROTLI_ALLOC(m, float, dist->alphabet_size_limit);\n  self->distance_histogram_size = dist->alphabet_size_limit;\n  if (BROTLI_IS_OOM(m)) return;\n}\n\nstatic void CleanupZopfliCostModel(MemoryManager* m, ZopfliCostModel* self) {\n  BROTLI_FREE(m, self->literal_costs_);\n  BROTLI_FREE(m, self->cost_dist_);\n}\n\nstatic void SetCost(const uint32_t* histogram, size_t histogram_size,\n                    BROTLI_BOOL literal_histogram, float* cost) {\n  size_t sum = 0;\n  size_t missing_symbol_sum;\n  float log2sum;\n  float missing_symbol_cost;\n  size_t i;\n  for (i = 0; i < histogram_size; i++) {\n    sum += histogram[i];\n  }\n  log2sum = (float)FastLog2(sum);\n  missing_symbol_sum = sum;\n  if (!literal_histogram) {\n    for (i = 0; i < histogram_size; i++) {\n      if (histogram[i] == 0) missing_symbol_sum++;\n    }\n  }\n  missing_symbol_cost = (float)FastLog2(missing_symbol_sum) + 2;\n  for (i = 0; i < histogram_size; i++) {\n    if (histogram[i] == 0) {\n      cost[i] = missing_symbol_cost;\n      continue;\n    }\n\n    /* Shannon bits for this symbol. */\n    cost[i] = log2sum - (float)FastLog2(histogram[i]);\n\n    /* Cannot be coded with less than 1 bit */\n    if (cost[i] < 1) cost[i] = 1;\n  }\n}\n\nstatic void ZopfliCostModelSetFromCommands(ZopfliCostModel* self,\n                                           size_t position,\n                                           const uint8_t* ringbuffer,\n                                           size_t ringbuffer_mask,\n                                           const Command* commands,\n                                           size_t num_commands,\n                                           size_t last_insert_len) {\n  ZopfliCostModelArena* arena = &self->arena;\n  size_t pos = position - last_insert_len;\n  float min_cost_cmd = kInfinity;\n  size_t i;\n  float* cost_cmd = self->cost_cmd_;\n\n  memset(arena->histogram_literal, 0, sizeof(arena->histogram_literal));\n  memset(arena->histogram_cmd, 0, sizeof(arena->histogram_cmd));\n  memset(arena->histogram_dist, 0, sizeof(arena->histogram_dist));\n\n  for (i = 0; i < num_commands; i++) {\n    size_t inslength = commands[i].insert_len_;\n    size_t copylength = CommandCopyLen(&commands[i]);\n    size_t distcode = commands[i].dist_prefix_ & 0x3FF;\n    size_t cmdcode = commands[i].cmd_prefix_;\n    size_t j;\n\n    arena->histogram_cmd[cmdcode]++;\n    if (cmdcode >= 128) arena->histogram_dist[distcode]++;\n\n    for (j = 0; j < inslength; j++) {\n      arena->histogram_literal[ringbuffer[(pos + j) & ringbuffer_mask]]++;\n    }\n\n    pos += inslength + copylength;\n  }\n\n  SetCost(arena->histogram_literal, BROTLI_NUM_LITERAL_SYMBOLS, BROTLI_TRUE,\n          arena->cost_literal);\n  SetCost(arena->histogram_cmd, BROTLI_NUM_COMMAND_SYMBOLS, BROTLI_FALSE,\n          cost_cmd);\n  SetCost(arena->histogram_dist, self->distance_histogram_size, BROTLI_FALSE,\n          self->cost_dist_);\n\n  for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) {\n    min_cost_cmd = BROTLI_MIN(float, min_cost_cmd, cost_cmd[i]);\n  }\n  self->min_cost_cmd_ = min_cost_cmd;\n\n  {\n    float* literal_costs = self->literal_costs_;\n    float literal_carry = 0.0;\n    size_t num_bytes = self->num_bytes_;\n    literal_costs[0] = 0.0;\n    for (i = 0; i < num_bytes; ++i) {\n      literal_carry +=\n          arena->cost_literal[ringbuffer[(position + i) & ringbuffer_mask]];\n      literal_costs[i + 1] = literal_costs[i] + literal_carry;\n      literal_carry -= literal_costs[i + 1] - literal_costs[i];\n    }\n  }\n}\n\nstatic void ZopfliCostModelSetFromLiteralCosts(ZopfliCostModel* self,\n                                               size_t position,\n                                               const uint8_t* ringbuffer,\n                                               size_t ringbuffer_mask) {\n  float* literal_costs = self->literal_costs_;\n  float literal_carry = 0.0;\n  float* cost_dist = self->cost_dist_;\n  float* cost_cmd = self->cost_cmd_;\n  size_t num_bytes = self->num_bytes_;\n  size_t i;\n  BrotliEstimateBitCostsForLiterals(position, num_bytes, ringbuffer_mask,\n                                    ringbuffer, self->literal_histograms,\n                                    &literal_costs[1]);\n  literal_costs[0] = 0.0;\n  for (i = 0; i < num_bytes; ++i) {\n    literal_carry += literal_costs[i + 1];\n    literal_costs[i + 1] = literal_costs[i] + literal_carry;\n    literal_carry -= literal_costs[i + 1] - literal_costs[i];\n  }\n  for (i = 0; i < BROTLI_NUM_COMMAND_SYMBOLS; ++i) {\n    cost_cmd[i] = (float)FastLog2(11 + (uint32_t)i);\n  }\n  for (i = 0; i < self->distance_histogram_size; ++i) {\n    cost_dist[i] = (float)FastLog2(20 + (uint32_t)i);\n  }\n  self->min_cost_cmd_ = (float)FastLog2(11);\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetCommandCost(\n    const ZopfliCostModel* self, uint16_t cmdcode) {\n  return self->cost_cmd_[cmdcode];\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetDistanceCost(\n    const ZopfliCostModel* self, size_t distcode) {\n  return self->cost_dist_[distcode];\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetLiteralCosts(\n    const ZopfliCostModel* self, size_t from, size_t to) {\n  return self->literal_costs_[to] - self->literal_costs_[from];\n}\n\nstatic BROTLI_INLINE float ZopfliCostModelGetMinCostCmd(\n    const ZopfliCostModel* self) {\n  return self->min_cost_cmd_;\n}\n\n/* REQUIRES: len >= 2, start_pos <= pos */\n/* REQUIRES: cost < kInfinity, nodes[start_pos].cost < kInfinity */\n/* Maintains the \"ZopfliNode array invariant\". */\nstatic BROTLI_INLINE void UpdateZopfliNode(ZopfliNode* nodes, size_t pos,\n    size_t start_pos, size_t len, size_t len_code, size_t dist,\n    size_t short_code, float cost) {\n  ZopfliNode* next = &nodes[pos + len];\n  next->length = (uint32_t)(len | ((len + 9u - len_code) << 25));\n  next->distance = (uint32_t)dist;\n  next->dcode_insert_length = (uint32_t)(\n      (short_code << 27) | (pos - start_pos));\n  next->u.cost = cost;\n}\n\ntypedef struct PosData {\n  size_t pos;\n  int distance_cache[4];\n  float costdiff;\n  float cost;\n} PosData;\n\n/* Maintains the smallest 8 cost difference together with their positions */\ntypedef struct StartPosQueue {\n  PosData q_[8];\n  size_t idx_;\n} StartPosQueue;\n\nstatic BROTLI_INLINE void InitStartPosQueue(StartPosQueue* self) {\n  self->idx_ = 0;\n}\n\nstatic size_t StartPosQueueSize(const StartPosQueue* self) {\n  return BROTLI_MIN(size_t, self->idx_, 8);\n}\n\nstatic void StartPosQueuePush(StartPosQueue* self, const PosData* posdata) {\n  size_t offset = ~(self->idx_++) & 7;\n  size_t len = StartPosQueueSize(self);\n  size_t i;\n  PosData* q = self->q_;\n  q[offset] = *posdata;\n  /* Restore the sorted order. In the list of |len| items at most |len - 1|\n     adjacent element comparisons / swaps are required. */\n  for (i = 1; i < len; ++i) {\n    if (q[offset & 7].costdiff > q[(offset + 1) & 7].costdiff) {\n      BROTLI_SWAP(PosData, q, offset & 7, (offset + 1) & 7);\n    }\n    ++offset;\n  }\n}\n\nstatic const PosData* StartPosQueueAt(const StartPosQueue* self, size_t k) {\n  return &self->q_[(k - self->idx_) & 7];\n}\n\n/* Returns the minimum possible copy length that can improve the cost of any */\n/* future position. */\nstatic size_t ComputeMinimumCopyLength(const float start_cost,\n                                       const ZopfliNode* nodes,\n                                       const size_t num_bytes,\n                                       const size_t pos) {\n  /* Compute the minimum possible cost of reaching any future position. */\n  float min_cost = start_cost;\n  size_t len = 2;\n  size_t next_len_bucket = 4;\n  size_t next_len_offset = 10;\n  while (pos + len <= num_bytes && nodes[pos + len].u.cost <= min_cost) {\n    /* We already reached (pos + len) with no more cost than the minimum\n       possible cost of reaching anything from this pos, so there is no point in\n       looking for lengths <= len. */\n    ++len;\n    if (len == next_len_offset) {\n      /* We reached the next copy length code bucket, so we add one more\n         extra bit to the minimum cost. */\n      min_cost += 1.0f;\n      next_len_offset += next_len_bucket;\n      next_len_bucket *= 2;\n    }\n  }\n  return len;\n}\n\n/* REQUIRES: nodes[pos].cost < kInfinity\n   REQUIRES: nodes[0..pos] satisfies that \"ZopfliNode array invariant\". */\nstatic uint32_t ComputeDistanceShortcut(const size_t block_start,\n                                        const size_t pos,\n                                        const size_t max_backward_limit,\n                                        const size_t gap,\n                                        const ZopfliNode* nodes) {\n  const size_t clen = ZopfliNodeCopyLength(&nodes[pos]);\n  const size_t ilen = nodes[pos].dcode_insert_length & 0x7FFFFFF;\n  const size_t dist = ZopfliNodeCopyDistance(&nodes[pos]);\n  /* Since |block_start + pos| is the end position of the command, the copy part\n     starts from |block_start + pos - clen|. Distances that are greater than\n     this or greater than |max_backward_limit| + |gap| are static dictionary\n     references, and do not update the last distances.\n     Also distance code 0 (last distance) does not update the last distances. */\n  if (pos == 0) {\n    return 0;\n  } else if (dist + clen <= block_start + pos + gap &&\n             dist <= max_backward_limit + gap &&\n             ZopfliNodeDistanceCode(&nodes[pos]) > 0) {\n    return (uint32_t)pos;\n  } else {\n    return nodes[pos - clen - ilen].u.shortcut;\n  }\n}\n\n/* Fills in dist_cache[0..3] with the last four distances (as defined by\n   Section 4. of the Spec) that would be used at (block_start + pos) if we\n   used the shortest path of commands from block_start, computed from\n   nodes[0..pos]. The last four distances at block_start are in\n   starting_dist_cache[0..3].\n   REQUIRES: nodes[pos].cost < kInfinity\n   REQUIRES: nodes[0..pos] satisfies that \"ZopfliNode array invariant\". */\nstatic void ComputeDistanceCache(const size_t pos,\n                                 const int* starting_dist_cache,\n                                 const ZopfliNode* nodes,\n                                 int* dist_cache) {\n  int idx = 0;\n  size_t p = nodes[pos].u.shortcut;\n  while (idx < 4 && p > 0) {\n    const size_t ilen = nodes[p].dcode_insert_length & 0x7FFFFFF;\n    const size_t clen = ZopfliNodeCopyLength(&nodes[p]);\n    const size_t dist = ZopfliNodeCopyDistance(&nodes[p]);\n    dist_cache[idx++] = (int)dist;\n    /* Because of prerequisite, p >= clen + ilen >= 2. */\n    p = nodes[p - clen - ilen].u.shortcut;\n  }\n  for (; idx < 4; ++idx) {\n    dist_cache[idx] = *starting_dist_cache++;\n  }\n}\n\n/* Maintains \"ZopfliNode array invariant\" and pushes node to the queue, if it\n   is eligible. */\nstatic void EvaluateNode(\n    const size_t block_start, const size_t pos, const size_t max_backward_limit,\n    const size_t gap, const int* starting_dist_cache,\n    const ZopfliCostModel* model, StartPosQueue* queue, ZopfliNode* nodes) {\n  /* Save cost, because ComputeDistanceCache invalidates it. */\n  float node_cost = nodes[pos].u.cost;\n  nodes[pos].u.shortcut = ComputeDistanceShortcut(\n      block_start, pos, max_backward_limit, gap, nodes);\n  if (node_cost <= ZopfliCostModelGetLiteralCosts(model, 0, pos)) {\n    PosData posdata;\n    posdata.pos = pos;\n    posdata.cost = node_cost;\n    posdata.costdiff = node_cost -\n        ZopfliCostModelGetLiteralCosts(model, 0, pos);\n    ComputeDistanceCache(\n        pos, starting_dist_cache, nodes, posdata.distance_cache);\n    StartPosQueuePush(queue, &posdata);\n  }\n}\n\n/* Returns longest copy length. */\nstatic size_t UpdateNodes(\n    const size_t num_bytes, const size_t block_start, const size_t pos,\n    const uint8_t* ringbuffer, const size_t ringbuffer_mask,\n    const BrotliEncoderParams* params, const size_t max_backward_limit,\n    const int* starting_dist_cache, const size_t num_matches,\n    const BackwardMatch* matches, const ZopfliCostModel* model,\n    StartPosQueue* queue, ZopfliNode* nodes) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t cur_ix = block_start + pos;\n  const size_t cur_ix_masked = cur_ix & ringbuffer_mask;\n  const size_t max_distance = BROTLI_MIN(size_t, cur_ix, max_backward_limit);\n  const size_t dictionary_start = BROTLI_MIN(size_t,\n      cur_ix + stream_offset, max_backward_limit);\n  const size_t max_len = num_bytes - pos;\n  const size_t max_zopfli_len = MaxZopfliLen(params);\n  const size_t max_iters = MaxZopfliCandidates(params);\n  size_t min_len;\n  size_t result = 0;\n  size_t k;\n  const CompoundDictionary* addon = &params->dictionary.compound;\n  size_t gap = addon->total_size;\n\n  EvaluateNode(block_start + stream_offset, pos, max_backward_limit, gap,\n      starting_dist_cache, model, queue, nodes);\n\n  {\n    const PosData* posdata = StartPosQueueAt(queue, 0);\n    float min_cost = (posdata->cost + ZopfliCostModelGetMinCostCmd(model) +\n        ZopfliCostModelGetLiteralCosts(model, posdata->pos, pos));\n    min_len = ComputeMinimumCopyLength(min_cost, nodes, num_bytes, pos);\n  }\n\n  /* Go over the command starting positions in order of increasing cost\n     difference. */\n  for (k = 0; k < max_iters && k < StartPosQueueSize(queue); ++k) {\n    const PosData* posdata = StartPosQueueAt(queue, k);\n    const size_t start = posdata->pos;\n    const uint16_t inscode = GetInsertLengthCode(pos - start);\n    const float start_costdiff = posdata->costdiff;\n    const float base_cost = start_costdiff + (float)GetInsertExtra(inscode) +\n        ZopfliCostModelGetLiteralCosts(model, 0, pos);\n\n    /* Look for last distance matches using the distance cache from this\n       starting position. */\n    size_t best_len = min_len - 1;\n    size_t j = 0;\n    for (; j < BROTLI_NUM_DISTANCE_SHORT_CODES && best_len < max_len; ++j) {\n      const size_t idx = kDistanceCacheIndex[j];\n      const size_t backward =\n          (size_t)(posdata->distance_cache[idx] + kDistanceCacheOffset[j]);\n      size_t prev_ix = cur_ix - backward;\n      size_t len = 0;\n      uint8_t continuation = ringbuffer[cur_ix_masked + best_len];\n      if (cur_ix_masked + best_len > ringbuffer_mask) {\n        break;\n      }\n      if (BROTLI_PREDICT_FALSE(backward > dictionary_start + gap)) {\n        /* Word dictionary -> ignore. */\n        continue;\n      }\n      if (backward <= max_distance) {\n        /* Regular backward reference. */\n        if (prev_ix >= cur_ix) {\n          continue;\n        }\n\n        prev_ix &= ringbuffer_mask;\n        if (prev_ix + best_len > ringbuffer_mask ||\n            continuation != ringbuffer[prev_ix + best_len]) {\n          continue;\n        }\n        len = FindMatchLengthWithLimit(&ringbuffer[prev_ix],\n                                       &ringbuffer[cur_ix_masked],\n                                       max_len);\n      } else if (backward > dictionary_start) {\n        size_t d = 0;\n        size_t offset;\n        size_t limit;\n        const uint8_t* source;\n        offset = dictionary_start + 1 + addon->total_size - 1;\n        while (offset >= backward + addon->chunk_offsets[d + 1]) d++;\n        source = addon->chunk_source[d];\n        offset = offset - addon->chunk_offsets[d] - backward;\n        limit = addon->chunk_offsets[d + 1] - addon->chunk_offsets[d] - offset;\n        limit = limit > max_len ? max_len : limit;\n        if (best_len >= limit ||\n            continuation != source[offset + best_len]) {\n          continue;\n        }\n        len = FindMatchLengthWithLimit(&source[offset],\n                                       &ringbuffer[cur_ix_masked],\n                                       limit);\n      } else {\n        /* \"Gray\" area. It is addressable by decoder, but this encoder\n           instance does not have that data -> should not touch it. */\n        continue;\n      }\n      {\n        const float dist_cost = base_cost +\n            ZopfliCostModelGetDistanceCost(model, j);\n        size_t l;\n        for (l = best_len + 1; l <= len; ++l) {\n          const uint16_t copycode = GetCopyLengthCode(l);\n          const uint16_t cmdcode =\n              CombineLengthCodes(inscode, copycode, j == 0);\n          const float cost = (cmdcode < 128 ? base_cost : dist_cost) +\n              (float)GetCopyExtra(copycode) +\n              ZopfliCostModelGetCommandCost(model, cmdcode);\n          if (cost < nodes[pos + l].u.cost) {\n            UpdateZopfliNode(nodes, pos, start, l, l, backward, j + 1, cost);\n            result = BROTLI_MAX(size_t, result, l);\n          }\n          best_len = l;\n        }\n      }\n    }\n\n    /* At higher iterations look only for new last distance matches, since\n       looking only for new command start positions with the same distances\n       does not help much. */\n    if (k >= 2) continue;\n\n    {\n      /* Loop through all possible copy lengths at this position. */\n      size_t len = min_len;\n      for (j = 0; j < num_matches; ++j) {\n        BackwardMatch match = matches[j];\n        size_t dist = match.distance;\n        BROTLI_BOOL is_dictionary_match =\n            TO_BROTLI_BOOL(dist > dictionary_start + gap);\n        /* We already tried all possible last distance matches, so we can use\n           normal distance code here. */\n        size_t dist_code = dist + BROTLI_NUM_DISTANCE_SHORT_CODES - 1;\n        uint16_t dist_symbol;\n        uint32_t distextra;\n        uint32_t distnumextra;\n        float dist_cost;\n        size_t max_match_len;\n        PrefixEncodeCopyDistance(\n            dist_code, params->dist.num_direct_distance_codes,\n            params->dist.distance_postfix_bits, &dist_symbol, &distextra);\n        distnumextra = dist_symbol >> 10;\n        dist_cost = base_cost + (float)distnumextra +\n            ZopfliCostModelGetDistanceCost(model, dist_symbol & 0x3FF);\n\n        /* Try all copy lengths up until the maximum copy length corresponding\n           to this distance. If the distance refers to the static dictionary, or\n           the maximum length is long enough, try only one maximum length. */\n        max_match_len = BackwardMatchLength(&match);\n        if (len < max_match_len &&\n            (is_dictionary_match || max_match_len > max_zopfli_len)) {\n          len = max_match_len;\n        }\n        for (; len <= max_match_len; ++len) {\n          const size_t len_code =\n              is_dictionary_match ? BackwardMatchLengthCode(&match) : len;\n          const uint16_t copycode = GetCopyLengthCode(len_code);\n          const uint16_t cmdcode = CombineLengthCodes(inscode, copycode, 0);\n          const float cost = dist_cost + (float)GetCopyExtra(copycode) +\n              ZopfliCostModelGetCommandCost(model, cmdcode);\n          if (cost < nodes[pos + len].u.cost) {\n            UpdateZopfliNode(nodes, pos, start, len, len_code, dist, 0, cost);\n            result = BROTLI_MAX(size_t, result, len);\n          }\n        }\n      }\n    }\n  }\n  return result;\n}\n\nstatic size_t ComputeShortestPathFromNodes(size_t num_bytes,\n    ZopfliNode* nodes) {\n  size_t index = num_bytes;\n  size_t num_commands = 0;\n  while ((nodes[index].dcode_insert_length & 0x7FFFFFF) == 0 &&\n      nodes[index].length == 1) --index;\n  nodes[index].u.next = BROTLI_UINT32_MAX;\n  while (index != 0) {\n    size_t len = ZopfliNodeCommandLength(&nodes[index]);\n    index -= len;\n    nodes[index].u.next = (uint32_t)len;\n    num_commands++;\n  }\n  return num_commands;\n}\n\n/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */\nvoid BrotliZopfliCreateCommands(const size_t num_bytes,\n    const size_t block_start, const ZopfliNode* nodes, int* dist_cache,\n    size_t* last_insert_len, const BrotliEncoderParams* params,\n    Command* commands, size_t* num_literals) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  size_t pos = 0;\n  uint32_t offset = nodes[0].u.next;\n  size_t i;\n  size_t gap = params->dictionary.compound.total_size;\n  for (i = 0; offset != BROTLI_UINT32_MAX; i++) {\n    const ZopfliNode* next = &nodes[pos + offset];\n    size_t copy_length = ZopfliNodeCopyLength(next);\n    size_t insert_length = next->dcode_insert_length & 0x7FFFFFF;\n    pos += insert_length;\n    offset = next->u.next;\n    if (i == 0) {\n      insert_length += *last_insert_len;\n      *last_insert_len = 0;\n    }\n    {\n      size_t distance = ZopfliNodeCopyDistance(next);\n      size_t len_code = ZopfliNodeLengthCode(next);\n      size_t dictionary_start = BROTLI_MIN(size_t,\n          block_start + pos + stream_offset, max_backward_limit);\n      BROTLI_BOOL is_dictionary =\n          TO_BROTLI_BOOL(distance > dictionary_start + gap);\n      size_t dist_code = ZopfliNodeDistanceCode(next);\n      InitCommand(&commands[i], &params->dist, insert_length,\n          copy_length, (int)len_code - (int)copy_length, dist_code);\n\n      if (!is_dictionary && dist_code > 0) {\n        dist_cache[3] = dist_cache[2];\n        dist_cache[2] = dist_cache[1];\n        dist_cache[1] = dist_cache[0];\n        dist_cache[0] = (int)distance;\n      }\n    }\n\n    *num_literals += insert_length;\n    pos += copy_length;\n  }\n  *last_insert_len += num_bytes - pos;\n}\n\nstatic size_t ZopfliIterate(size_t num_bytes, size_t position,\n    const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    const BrotliEncoderParams* params, const size_t gap, const int* dist_cache,\n    const ZopfliCostModel* model, const uint32_t* num_matches,\n    const BackwardMatch* matches, ZopfliNode* nodes) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  const size_t max_zopfli_len = MaxZopfliLen(params);\n  StartPosQueue queue;\n  size_t cur_match_pos = 0;\n  size_t i;\n  nodes[0].length = 0;\n  nodes[0].u.cost = 0;\n  InitStartPosQueue(&queue);\n  for (i = 0; i + 3 < num_bytes; i++) {\n    size_t skip = UpdateNodes(num_bytes, position, i, ringbuffer,\n        ringbuffer_mask, params, max_backward_limit, dist_cache,\n        num_matches[i], &matches[cur_match_pos], model, &queue, nodes);\n    if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;\n    cur_match_pos += num_matches[i];\n    if (num_matches[i] == 1 &&\n        BackwardMatchLength(&matches[cur_match_pos - 1]) > max_zopfli_len) {\n      skip = BROTLI_MAX(size_t,\n          BackwardMatchLength(&matches[cur_match_pos - 1]), skip);\n    }\n    if (skip > 1) {\n      skip--;\n      while (skip) {\n        i++;\n        if (i + 3 >= num_bytes) break;\n        EvaluateNode(position + stream_offset, i, max_backward_limit, gap,\n            dist_cache, model, &queue, nodes);\n        cur_match_pos += num_matches[i];\n        skip--;\n      }\n    }\n  }\n  return ComputeShortestPathFromNodes(num_bytes, nodes);\n}\n\nstatic void MergeMatches(BackwardMatch* dst,\n    BackwardMatch* src1, size_t len1, BackwardMatch* src2, size_t len2) {\n  while (len1 > 0 && len2 > 0) {\n    size_t l1 = BackwardMatchLength(src1);\n    size_t l2 = BackwardMatchLength(src2);\n    if (l1 < l2 || ((l1 == l2) && (src1->distance < src2->distance))) {\n      *dst++ = *src1++;\n      len1--;\n    } else {\n      *dst++ = *src2++;\n      len2--;\n    }\n  }\n  while (len1-- > 0) *dst++ = *src1++;\n  while (len2-- > 0) *dst++ = *src2++;\n}\n\n/* REQUIRES: nodes != NULL and len(nodes) >= num_bytes + 1 */\nsize_t BrotliZopfliComputeShortestPath(MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    const int* dist_cache, Hasher* hasher, ZopfliNode* nodes) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  const size_t max_zopfli_len = MaxZopfliLen(params);\n  StartPosQueue queue;\n  BackwardMatch* BROTLI_RESTRICT matches =\n      BROTLI_ALLOC(m, BackwardMatch, 2 * (MAX_NUM_MATCHES_H10 + 64));\n  const size_t store_end = num_bytes >= StoreLookaheadH10() ?\n      position + num_bytes - StoreLookaheadH10() + 1 : position;\n  size_t i;\n  const CompoundDictionary* addon = &params->dictionary.compound;\n  size_t gap = addon->total_size;\n  size_t lz_matches_offset =\n      (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0;\n  ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) || BROTLI_IS_NULL(matches)) {\n    return 0;\n  }\n  nodes[0].length = 0;\n  nodes[0].u.cost = 0;\n  InitZopfliCostModel(m, model, &params->dist, num_bytes);\n  if (BROTLI_IS_OOM(m)) return 0;\n  ZopfliCostModelSetFromLiteralCosts(\n      model, position, ringbuffer, ringbuffer_mask);\n  InitStartPosQueue(&queue);\n  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; i++) {\n    const size_t pos = position + i;\n    const size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);\n    const size_t dictionary_start = BROTLI_MIN(size_t,\n        pos + stream_offset, max_backward_limit);\n    size_t skip;\n    size_t num_matches;\n    int dict_id = 0;\n    if (params->dictionary.contextual.context_based) {\n      uint8_t p1 = pos >= 1 ?\n          ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0;\n      uint8_t p2 = pos >= 2 ?\n          ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0;\n      dict_id = params->dictionary.contextual.context_map[\n          BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n    }\n    num_matches = FindAllMatchesH10(&hasher->privat._H10,\n        params->dictionary.contextual.dict[dict_id],\n        ringbuffer, ringbuffer_mask, pos, num_bytes - i, max_distance,\n        dictionary_start + gap, params, &matches[lz_matches_offset]);\n    if (addon->num_chunks != 0) {\n      size_t cd_matches = LookupAllCompoundDictionaryMatches(addon,\n          ringbuffer, ringbuffer_mask, pos, 3, num_bytes - i,\n          dictionary_start, params->dist.max_distance,\n          &matches[lz_matches_offset - 64], 64);\n      MergeMatches(matches, &matches[lz_matches_offset - 64], cd_matches,\n          &matches[lz_matches_offset], num_matches);\n      num_matches += cd_matches;\n    }\n    if (num_matches > 0 &&\n        BackwardMatchLength(&matches[num_matches - 1]) > max_zopfli_len) {\n      matches[0] = matches[num_matches - 1];\n      num_matches = 1;\n    }\n    skip = UpdateNodes(num_bytes, position, i, ringbuffer, ringbuffer_mask,\n        params, max_backward_limit, dist_cache, num_matches, matches, model,\n        &queue, nodes);\n    if (skip < BROTLI_LONG_COPY_QUICK_STEP) skip = 0;\n    if (num_matches == 1 && BackwardMatchLength(&matches[0]) > max_zopfli_len) {\n      skip = BROTLI_MAX(size_t, BackwardMatchLength(&matches[0]), skip);\n    }\n    if (skip > 1) {\n      /* Add the tail of the copy to the hasher. */\n      StoreRangeH10(&hasher->privat._H10,\n          ringbuffer, ringbuffer_mask, pos + 1, BROTLI_MIN(\n          size_t, pos + skip, store_end));\n      skip--;\n      while (skip) {\n        i++;\n        if (i + HashTypeLengthH10() - 1 >= num_bytes) break;\n        EvaluateNode(position + stream_offset, i, max_backward_limit, gap,\n            dist_cache, model, &queue, nodes);\n        skip--;\n      }\n    }\n  }\n  CleanupZopfliCostModel(m, model);\n  BROTLI_FREE(m, model);\n  BROTLI_FREE(m, matches);\n  return ComputeShortestPathFromNodes(num_bytes, nodes);\n}\n\nvoid BrotliCreateZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  ZopfliNode* nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return;\n  BrotliInitZopfliNodes(nodes, num_bytes + 1);\n  *num_commands += BrotliZopfliComputeShortestPath(m, num_bytes,\n      position, ringbuffer, ringbuffer_mask, literal_context_lut, params,\n      dist_cache, hasher, nodes);\n  if (BROTLI_IS_OOM(m)) return;\n  BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,\n      last_insert_len, params, commands, num_literals);\n  BROTLI_FREE(m, nodes);\n}\n\nvoid BrotliCreateHqZopfliBackwardReferences(MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  const size_t stream_offset = params->stream_offset;\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  uint32_t* num_matches = BROTLI_ALLOC(m, uint32_t, num_bytes);\n  size_t matches_size = 4 * num_bytes;\n  const size_t store_end = num_bytes >= StoreLookaheadH10() ?\n      position + num_bytes - StoreLookaheadH10() + 1 : position;\n  size_t cur_match_pos = 0;\n  size_t i;\n  size_t orig_num_literals;\n  size_t orig_last_insert_len;\n  int orig_dist_cache[4];\n  size_t orig_num_commands;\n  ZopfliCostModel* model = BROTLI_ALLOC(m, ZopfliCostModel, 1);\n  ZopfliNode* nodes;\n  BackwardMatch* matches = BROTLI_ALLOC(m, BackwardMatch, matches_size);\n  const CompoundDictionary* addon = &params->dictionary.compound;\n  size_t gap = addon->total_size;\n  size_t shadow_matches =\n      (addon->num_chunks != 0) ? (MAX_NUM_MATCHES_H10 + 128) : 0;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(model) ||\n      BROTLI_IS_NULL(num_matches) || BROTLI_IS_NULL(matches)) {\n    return;\n  }\n  for (i = 0; i + HashTypeLengthH10() - 1 < num_bytes; ++i) {\n    const size_t pos = position + i;\n    size_t max_distance = BROTLI_MIN(size_t, pos, max_backward_limit);\n    size_t dictionary_start = BROTLI_MIN(size_t,\n        pos + stream_offset, max_backward_limit);\n    size_t max_length = num_bytes - i;\n    size_t num_found_matches;\n    size_t cur_match_end;\n    size_t j;\n    int dict_id = 0;\n    if (params->dictionary.contextual.context_based) {\n      uint8_t p1 = pos >= 1 ?\n          ringbuffer[(size_t)(pos - 1) & ringbuffer_mask] : 0;\n      uint8_t p2 = pos >= 2 ?\n          ringbuffer[(size_t)(pos - 2) & ringbuffer_mask] : 0;\n      dict_id = params->dictionary.contextual.context_map[\n          BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n    }\n    /* Ensure that we have enough free slots. */\n    BROTLI_ENSURE_CAPACITY(m, BackwardMatch, matches, matches_size,\n        cur_match_pos + MAX_NUM_MATCHES_H10 + shadow_matches);\n    if (BROTLI_IS_OOM(m)) return;\n    num_found_matches = FindAllMatchesH10(&hasher->privat._H10,\n        params->dictionary.contextual.dict[dict_id],\n        ringbuffer, ringbuffer_mask, pos, max_length,\n        max_distance, dictionary_start + gap, params,\n        &matches[cur_match_pos + shadow_matches]);\n    if (addon->num_chunks != 0) {\n      size_t cd_matches = LookupAllCompoundDictionaryMatches(addon,\n          ringbuffer, ringbuffer_mask, pos, 3, max_length,\n          dictionary_start, params->dist.max_distance,\n          &matches[cur_match_pos + shadow_matches - 64], 64);\n      MergeMatches(&matches[cur_match_pos],\n          &matches[cur_match_pos + shadow_matches - 64], cd_matches,\n          &matches[cur_match_pos + shadow_matches], num_found_matches);\n      num_found_matches += cd_matches;\n    }\n    cur_match_end = cur_match_pos + num_found_matches;\n    for (j = cur_match_pos; j + 1 < cur_match_end; ++j) {\n      BROTLI_DCHECK(BackwardMatchLength(&matches[j]) <=\n          BackwardMatchLength(&matches[j + 1]));\n    }\n    num_matches[i] = (uint32_t)num_found_matches;\n    if (num_found_matches > 0) {\n      const size_t match_len = BackwardMatchLength(&matches[cur_match_end - 1]);\n      if (match_len > MAX_ZOPFLI_LEN_QUALITY_11) {\n        const size_t skip = match_len - 1;\n        matches[cur_match_pos++] = matches[cur_match_end - 1];\n        num_matches[i] = 1;\n        /* Add the tail of the copy to the hasher. */\n        StoreRangeH10(&hasher->privat._H10,\n                      ringbuffer, ringbuffer_mask, pos + 1,\n                      BROTLI_MIN(size_t, pos + match_len, store_end));\n        memset(&num_matches[i + 1], 0, skip * sizeof(num_matches[0]));\n        i += skip;\n      } else {\n        cur_match_pos = cur_match_end;\n      }\n    }\n  }\n  orig_num_literals = *num_literals;\n  orig_last_insert_len = *last_insert_len;\n  memcpy(orig_dist_cache, dist_cache, 4 * sizeof(dist_cache[0]));\n  orig_num_commands = *num_commands;\n  nodes = BROTLI_ALLOC(m, ZopfliNode, num_bytes + 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(nodes)) return;\n  InitZopfliCostModel(m, model, &params->dist, num_bytes);\n  if (BROTLI_IS_OOM(m)) return;\n  for (i = 0; i < 2; i++) {\n    BrotliInitZopfliNodes(nodes, num_bytes + 1);\n    if (i == 0) {\n      ZopfliCostModelSetFromLiteralCosts(\n          model, position, ringbuffer, ringbuffer_mask);\n    } else {\n      ZopfliCostModelSetFromCommands(model, position, ringbuffer,\n          ringbuffer_mask, commands, *num_commands - orig_num_commands,\n          orig_last_insert_len);\n    }\n    *num_commands = orig_num_commands;\n    *num_literals = orig_num_literals;\n    *last_insert_len = orig_last_insert_len;\n    memcpy(dist_cache, orig_dist_cache, 4 * sizeof(dist_cache[0]));\n    *num_commands += ZopfliIterate(num_bytes, position, ringbuffer,\n        ringbuffer_mask, params, gap, dist_cache, model, num_matches, matches,\n        nodes);\n    BrotliZopfliCreateCommands(num_bytes, position, nodes, dist_cache,\n        last_insert_len, params, commands, num_literals);\n  }\n  CleanupZopfliCostModel(m, model);\n  BROTLI_FREE(m, model);\n  BROTLI_FREE(m, nodes);\n  BROTLI_FREE(m, matches);\n  BROTLI_FREE(m, num_matches);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/backward_references_hq.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find backward reference copies. */\n\n#ifndef BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_\n#define BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"hash.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nBROTLI_INTERNAL void BrotliCreateZopfliBackwardReferences(MemoryManager* m,\n    size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals);\n\nBROTLI_INTERNAL void BrotliCreateHqZopfliBackwardReferences(MemoryManager* m,\n    size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals);\n\ntypedef struct ZopfliNode {\n  /* Best length to get up to this byte (not including this byte itself)\n     highest 7 bit is used to reconstruct the length code. */\n  uint32_t length;\n  /* Distance associated with the length. */\n  uint32_t distance;\n  /* Number of literal inserts before this copy; highest 5 bits contain\n     distance short code + 1 (or zero if no short code). */\n  uint32_t dcode_insert_length;\n\n  /* This union holds information used by dynamic-programming. During forward\n     pass |cost| it used to store the goal function. When node is processed its\n     |cost| is invalidated in favor of |shortcut|. On path back-tracing pass\n     |next| is assigned the offset to next node on the path. */\n  union {\n    /* Smallest cost to get to this byte from the beginning, as found so far. */\n    float cost;\n    /* Offset to the next node on the path. Equals to command_length() of the\n       next node on the path. For last node equals to BROTLI_UINT32_MAX */\n    uint32_t next;\n    /* Node position that provides next distance for distance cache. */\n    uint32_t shortcut;\n  } u;\n} ZopfliNode;\n\nBROTLI_INTERNAL void BrotliInitZopfliNodes(ZopfliNode* array, size_t length);\n\n/* Computes the shortest path of commands from position to at most\n   position + num_bytes.\n\n   On return, path->size() is the number of commands found and path[i] is the\n   length of the i-th command (copy length plus insert length).\n   Note that the sum of the lengths of all commands can be less than num_bytes.\n\n   On return, the nodes[0..num_bytes] array will have the following\n   \"ZopfliNode array invariant\":\n   For each i in [1..num_bytes], if nodes[i].cost < kInfinity, then\n     (1) nodes[i].copy_length() >= 2\n     (2) nodes[i].command_length() <= i and\n     (3) nodes[i - nodes[i].command_length()].cost < kInfinity */\nBROTLI_INTERNAL size_t BrotliZopfliComputeShortestPath(\n    MemoryManager* m, size_t num_bytes,\n    size_t position, const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    const int* dist_cache, Hasher* hasher, ZopfliNode* nodes);\n\nBROTLI_INTERNAL void BrotliZopfliCreateCommands(\n    const size_t num_bytes, const size_t block_start, const ZopfliNode* nodes,\n    int* dist_cache, size_t* last_insert_len, const BrotliEncoderParams* params,\n    Command* commands, size_t* num_literals);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BACKWARD_REFERENCES_HQ_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/backward_references_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: EXPORT_FN, FN */\n\nstatic BROTLI_NOINLINE void EXPORT_FN(CreateBackwardReferences)(\n    size_t num_bytes, size_t position,\n    const uint8_t* ringbuffer, size_t ringbuffer_mask,\n    ContextLut literal_context_lut, const BrotliEncoderParams* params,\n    Hasher* hasher, int* dist_cache, size_t* last_insert_len,\n    Command* commands, size_t* num_commands, size_t* num_literals) {\n  HASHER()* privat = &hasher->privat.FN(_);\n  /* Set maximum distance, see section 9.1. of the spec. */\n  const size_t max_backward_limit = BROTLI_MAX_BACKWARD_LIMIT(params->lgwin);\n  const size_t position_offset = params->stream_offset;\n\n  const Command* const orig_commands = commands;\n  size_t insert_length = *last_insert_len;\n  const size_t pos_end = position + num_bytes;\n  const size_t store_end = num_bytes >= FN(StoreLookahead)() ?\n      position + num_bytes - FN(StoreLookahead)() + 1 : position;\n\n  /* For speed up heuristics for random data. */\n  const size_t random_heuristics_window_size =\n      LiteralSpreeLengthForSparseSearch(params);\n  size_t apply_random_heuristics = position + random_heuristics_window_size;\n  const size_t gap = params->dictionary.compound.total_size;\n\n  /* Minimum score to accept a backward reference. */\n  const score_t kMinScore = BROTLI_SCORE_BASE + 100;\n\n  FN(PrepareDistanceCache)(privat, dist_cache);\n\n  while (position + FN(HashTypeLength)() < pos_end) {\n    size_t max_length = pos_end - position;\n    size_t max_distance = BROTLI_MIN(size_t, position, max_backward_limit);\n    size_t dictionary_start = BROTLI_MIN(size_t,\n        position + position_offset, max_backward_limit);\n    HasherSearchResult sr;\n    int dict_id = 0;\n    uint8_t p1 = 0;\n    uint8_t p2 = 0;\n    if (params->dictionary.contextual.context_based) {\n      p1 = position >= 1 ?\n          ringbuffer[(size_t)(position - 1) & ringbuffer_mask] : 0;\n      p2 = position >= 2 ?\n          ringbuffer[(size_t)(position - 2) & ringbuffer_mask] : 0;\n      dict_id = params->dictionary.contextual.context_map[\n          BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n    }\n    sr.len = 0;\n    sr.len_code_delta = 0;\n    sr.distance = 0;\n    sr.score = kMinScore;\n    FN(FindLongestMatch)(privat, params->dictionary.contextual.dict[dict_id],\n        ringbuffer, ringbuffer_mask, dist_cache, position, max_length,\n        max_distance, dictionary_start + gap, params->dist.max_distance, &sr);\n    if (ENABLE_COMPOUND_DICTIONARY) {\n      LookupCompoundDictionaryMatch(&params->dictionary.compound, ringbuffer,\n          ringbuffer_mask, dist_cache, position, max_length,\n          dictionary_start, params->dist.max_distance, &sr);\n    }\n    if (sr.score > kMinScore) {\n      /* Found a match. Let's look for something even better ahead. */\n      int delayed_backward_references_in_row = 0;\n      --max_length;\n      for (;; --max_length) {\n        const score_t cost_diff_lazy = 175;\n        HasherSearchResult sr2;\n        sr2.len = params->quality < MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH ?\n            BROTLI_MIN(size_t, sr.len - 1, max_length) : 0;\n        sr2.len_code_delta = 0;\n        sr2.distance = 0;\n        sr2.score = kMinScore;\n        max_distance = BROTLI_MIN(size_t, position + 1, max_backward_limit);\n        dictionary_start = BROTLI_MIN(size_t,\n            position + 1 + position_offset, max_backward_limit);\n        if (params->dictionary.contextual.context_based) {\n          p2 = p1;\n          p1 = ringbuffer[position & ringbuffer_mask];\n          dict_id = params->dictionary.contextual.context_map[\n              BROTLI_CONTEXT(p1, p2, literal_context_lut)];\n        }\n        FN(FindLongestMatch)(privat,\n            params->dictionary.contextual.dict[dict_id],\n            ringbuffer, ringbuffer_mask, dist_cache, position + 1, max_length,\n            max_distance, dictionary_start + gap, params->dist.max_distance,\n            &sr2);\n        if (ENABLE_COMPOUND_DICTIONARY) {\n          LookupCompoundDictionaryMatch(\n              &params->dictionary.compound, ringbuffer,\n              ringbuffer_mask, dist_cache, position + 1, max_length,\n              dictionary_start, params->dist.max_distance, &sr2);\n        }\n        if (sr2.score >= sr.score + cost_diff_lazy) {\n          /* Ok, let's just write one byte for now and start a match from the\n             next byte. */\n          ++position;\n          ++insert_length;\n          sr = sr2;\n          if (++delayed_backward_references_in_row < 4 &&\n              position + FN(HashTypeLength)() < pos_end) {\n            continue;\n          }\n        }\n        break;\n      }\n      apply_random_heuristics =\n          position + 2 * sr.len + random_heuristics_window_size;\n      dictionary_start = BROTLI_MIN(size_t,\n          position + position_offset, max_backward_limit);\n      {\n        /* The first 16 codes are special short-codes,\n           and the minimum offset is 1. */\n        size_t distance_code = ComputeDistanceCode(\n            sr.distance, dictionary_start + gap, dist_cache);\n        if ((sr.distance <= (dictionary_start + gap)) && distance_code > 0) {\n          dist_cache[3] = dist_cache[2];\n          dist_cache[2] = dist_cache[1];\n          dist_cache[1] = dist_cache[0];\n          dist_cache[0] = (int)sr.distance;\n          FN(PrepareDistanceCache)(privat, dist_cache);\n        }\n        InitCommand(commands++, &params->dist, insert_length,\n            sr.len, sr.len_code_delta, distance_code);\n      }\n      *num_literals += insert_length;\n      insert_length = 0;\n      /* Put the hash keys into the table, if there are enough bytes left.\n         Depending on the hasher implementation, it can push all positions\n         in the given range or only a subset of them.\n         Avoid hash poisoning with RLE data. */\n      {\n        size_t range_start = position + 2;\n        size_t range_end = BROTLI_MIN(size_t, position + sr.len, store_end);\n        if (sr.distance < (sr.len >> 2)) {\n          range_start = BROTLI_MIN(size_t, range_end, BROTLI_MAX(size_t,\n              range_start, position + sr.len - (sr.distance << 2)));\n        }\n        FN(StoreRange)(privat, ringbuffer, ringbuffer_mask, range_start,\n                       range_end);\n      }\n      position += sr.len;\n    } else {\n      ++insert_length;\n      ++position;\n      /* If we have not seen matches for a long time, we can skip some\n         match lookups. Unsuccessful match lookups are very very expensive\n         and this kind of a heuristic speeds up compression quite\n         a lot. */\n      if (position > apply_random_heuristics) {\n        /* Going through uncompressible data, jump. */\n        if (position >\n            apply_random_heuristics + 4 * random_heuristics_window_size) {\n          /* It is quite a long time since we saw a copy, so we assume\n             that this data is not compressible, and store hashes less\n             often. Hashes of non compressible data are less likely to\n             turn out to be useful in the future, too, so we store less of\n             them to not to flood out the hash table of good compressible\n             data. */\n          const size_t kMargin =\n              BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 4);\n          size_t pos_jump =\n              BROTLI_MIN(size_t, position + 16, pos_end - kMargin);\n          for (; position < pos_jump; position += 4) {\n            FN(Store)(privat, ringbuffer, ringbuffer_mask, position);\n            insert_length += 4;\n          }\n        } else {\n          const size_t kMargin =\n              BROTLI_MAX(size_t, FN(StoreLookahead)() - 1, 2);\n          size_t pos_jump =\n              BROTLI_MIN(size_t, position + 8, pos_end - kMargin);\n          for (; position < pos_jump; position += 2) {\n            FN(Store)(privat, ringbuffer, ringbuffer_mask, position);\n            insert_length += 2;\n          }\n        }\n      }\n    }\n  }\n  insert_length += pos_end - position;\n  *last_insert_len = insert_length;\n  *num_commands += (size_t)(commands - orig_commands);\n}\n"
  },
  {
    "path": "third-party/brotli/enc/bit_cost.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions to estimate the bit cost of Huffman trees. */\n\n#include \"bit_cost.h\"\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n#include \"histogram.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define FN(X) X ## Literal\n#include \"bit_cost_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"bit_cost_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"bit_cost_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/bit_cost.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions to estimate the bit cost of Huffman trees. */\n\n#ifndef BROTLI_ENC_BIT_COST_H_\n#define BROTLI_ENC_BIT_COST_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n#include \"histogram.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE double ShannonEntropy(\n    const uint32_t* population, size_t size, size_t* total) {\n  size_t sum = 0;\n  double retval = 0;\n  const uint32_t* population_end = population + size;\n  size_t p;\n  if (size & 1) {\n    goto odd_number_of_elements_left;\n  }\n  while (population < population_end) {\n    p = *population++;\n    sum += p;\n    retval -= (double)p * FastLog2(p);\n odd_number_of_elements_left:\n    p = *population++;\n    sum += p;\n    retval -= (double)p * FastLog2(p);\n  }\n  if (sum) retval += (double)sum * FastLog2(sum);\n  *total = sum;\n  return retval;\n}\n\nstatic BROTLI_INLINE double BitsEntropy(\n    const uint32_t* population, size_t size) {\n  size_t sum;\n  double retval = ShannonEntropy(population, size, &sum);\n  if (retval < (double)sum) {\n    /* At least one bit per literal is needed. */\n    retval = (double)sum;\n  }\n  return retval;\n}\n\nBROTLI_INTERNAL double BrotliPopulationCostLiteral(const HistogramLiteral*);\nBROTLI_INTERNAL double BrotliPopulationCostCommand(const HistogramCommand*);\nBROTLI_INTERNAL double BrotliPopulationCostDistance(const HistogramDistance*);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BIT_COST_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/bit_cost_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n#define HistogramType FN(Histogram)\n\ndouble FN(BrotliPopulationCost)(const HistogramType* histogram) {\n  static const double kOneSymbolHistogramCost = 12;\n  static const double kTwoSymbolHistogramCost = 20;\n  static const double kThreeSymbolHistogramCost = 28;\n  static const double kFourSymbolHistogramCost = 37;\n  const size_t data_size = FN(HistogramDataSize)();\n  int count = 0;\n  size_t s[5];\n  double bits = 0.0;\n  size_t i;\n  if (histogram->total_count_ == 0) {\n    return kOneSymbolHistogramCost;\n  }\n  for (i = 0; i < data_size; ++i) {\n    if (histogram->data_[i] > 0) {\n      s[count] = i;\n      ++count;\n      if (count > 4) break;\n    }\n  }\n  if (count == 1) {\n    return kOneSymbolHistogramCost;\n  }\n  if (count == 2) {\n    return (kTwoSymbolHistogramCost + (double)histogram->total_count_);\n  }\n  if (count == 3) {\n    const uint32_t histo0 = histogram->data_[s[0]];\n    const uint32_t histo1 = histogram->data_[s[1]];\n    const uint32_t histo2 = histogram->data_[s[2]];\n    const uint32_t histomax =\n        BROTLI_MAX(uint32_t, histo0, BROTLI_MAX(uint32_t, histo1, histo2));\n    return (kThreeSymbolHistogramCost +\n            2 * (histo0 + histo1 + histo2) - histomax);\n  }\n  if (count == 4) {\n    uint32_t histo[4];\n    uint32_t h23;\n    uint32_t histomax;\n    for (i = 0; i < 4; ++i) {\n      histo[i] = histogram->data_[s[i]];\n    }\n    /* Sort */\n    for (i = 0; i < 4; ++i) {\n      size_t j;\n      for (j = i + 1; j < 4; ++j) {\n        if (histo[j] > histo[i]) {\n          BROTLI_SWAP(uint32_t, histo, j, i);\n        }\n      }\n    }\n    h23 = histo[2] + histo[3];\n    histomax = BROTLI_MAX(uint32_t, h23, histo[0]);\n    return (kFourSymbolHistogramCost +\n            3 * h23 + 2 * (histo[0] + histo[1]) - histomax);\n  }\n\n  {\n    /* In this loop we compute the entropy of the histogram and simultaneously\n       build a simplified histogram of the code length codes where we use the\n       zero repeat code 17, but we don't use the non-zero repeat code 16. */\n    size_t max_depth = 1;\n    uint32_t depth_histo[BROTLI_CODE_LENGTH_CODES] = { 0 };\n    const double log2total = FastLog2(histogram->total_count_);\n    for (i = 0; i < data_size;) {\n      if (histogram->data_[i] > 0) {\n        /* Compute -log2(P(symbol)) = -log2(count(symbol)/total_count) =\n                                    = log2(total_count) - log2(count(symbol)) */\n        double log2p = log2total - FastLog2(histogram->data_[i]);\n        /* Approximate the bit depth by round(-log2(P(symbol))) */\n        size_t depth = (size_t)(log2p + 0.5);\n        bits += histogram->data_[i] * log2p;\n        if (depth > 15) {\n          depth = 15;\n        }\n        if (depth > max_depth) {\n          max_depth = depth;\n        }\n        ++depth_histo[depth];\n        ++i;\n      } else {\n        /* Compute the run length of zeros and add the appropriate number of 0\n           and 17 code length codes to the code length code histogram. */\n        uint32_t reps = 1;\n        size_t k;\n        for (k = i + 1; k < data_size && histogram->data_[k] == 0; ++k) {\n          ++reps;\n        }\n        i += reps;\n        if (i == data_size) {\n          /* Don't add any cost for the last zero run, since these are encoded\n             only implicitly. */\n          break;\n        }\n        if (reps < 3) {\n          depth_histo[0] += reps;\n        } else {\n          reps -= 2;\n          while (reps > 0) {\n            ++depth_histo[BROTLI_REPEAT_ZERO_CODE_LENGTH];\n            /* Add the 3 extra bits for the 17 code length code. */\n            bits += 3;\n            reps >>= 3;\n          }\n        }\n      }\n    }\n    /* Add the estimated encoding cost of the code length code histogram. */\n    bits += (double)(18 + 2 * max_depth);\n    /* Add the entropy of the code length code histogram. */\n    bits += BitsEntropy(depth_histo, BROTLI_CODE_LENGTH_CODES);\n  }\n  return bits;\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "third-party/brotli/enc/block_encoder_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2014 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n#define HistogramType FN(Histogram)\n\n/* Creates entropy codes for all block types and stores them to the bit\n   stream. */\nstatic void FN(BuildAndStoreEntropyCodes)(MemoryManager* m, BlockEncoder* self,\n    const HistogramType* histograms, const size_t histograms_size,\n    const size_t alphabet_size, HuffmanTree* tree,\n    size_t* storage_ix, uint8_t* storage) {\n  const size_t table_size = histograms_size * self->histogram_length_;\n  self->depths_ = BROTLI_ALLOC(m, uint8_t, table_size);\n  self->bits_ = BROTLI_ALLOC(m, uint16_t, table_size);\n  if (BROTLI_IS_OOM(m)) return;\n\n  {\n    size_t i;\n    for (i = 0; i < histograms_size; ++i) {\n      size_t ix = i * self->histogram_length_;\n      BuildAndStoreHuffmanTree(&histograms[i].data_[0], self->histogram_length_,\n          alphabet_size, tree, &self->depths_[ix], &self->bits_[ix],\n          storage_ix, storage);\n    }\n  }\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "third-party/brotli/enc/block_splitter.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Block split point selection utilities. */\n\n#include \"block_splitter.h\"\n\n#include <string.h>  /* memcpy, memset */\n\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"\n#include \"cluster.h\"\n#include \"command.h\"\n#include \"fast_log.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic const size_t kMaxLiteralHistograms = 100;\nstatic const size_t kMaxCommandHistograms = 50;\nstatic const double kLiteralBlockSwitchCost = 28.1;\nstatic const double kCommandBlockSwitchCost = 13.5;\nstatic const double kDistanceBlockSwitchCost = 14.6;\nstatic const size_t kLiteralStrideLength = 70;\nstatic const size_t kCommandStrideLength = 40;\nstatic const size_t kDistanceStrideLength = 40;\nstatic const size_t kSymbolsPerLiteralHistogram = 544;\nstatic const size_t kSymbolsPerCommandHistogram = 530;\nstatic const size_t kSymbolsPerDistanceHistogram = 544;\nstatic const size_t kMinLengthForBlockSplitting = 128;\nstatic const size_t kIterMulForRefining = 2;\nstatic const size_t kMinItersForRefining = 100;\n\nstatic size_t CountLiterals(const Command* cmds, const size_t num_commands) {\n  /* Count how many we have. */\n  size_t total_length = 0;\n  size_t i;\n  for (i = 0; i < num_commands; ++i) {\n    total_length += cmds[i].insert_len_;\n  }\n  return total_length;\n}\n\nstatic void CopyLiteralsToByteArray(const Command* cmds,\n                                    const size_t num_commands,\n                                    const uint8_t* data,\n                                    const size_t offset,\n                                    const size_t mask,\n                                    uint8_t* literals) {\n  size_t pos = 0;\n  size_t from_pos = offset & mask;\n  size_t i;\n  for (i = 0; i < num_commands; ++i) {\n    size_t insert_len = cmds[i].insert_len_;\n    if (from_pos + insert_len > mask) {\n      size_t head_size = mask + 1 - from_pos;\n      memcpy(literals + pos, data + from_pos, head_size);\n      from_pos = 0;\n      pos += head_size;\n      insert_len -= head_size;\n    }\n    if (insert_len > 0) {\n      memcpy(literals + pos, data + from_pos, insert_len);\n      pos += insert_len;\n    }\n    from_pos = (from_pos + insert_len + CommandCopyLen(&cmds[i])) & mask;\n  }\n}\n\nstatic BROTLI_INLINE uint32_t MyRand(uint32_t* seed) {\n  /* Initial seed should be 7. In this case, loop length is (1 << 29). */\n  *seed *= 16807U;\n  return *seed;\n}\n\nstatic BROTLI_INLINE double BitCost(size_t count) {\n  return count == 0 ? -2.0 : FastLog2(count);\n}\n\n#define HISTOGRAMS_PER_BATCH 64\n#define CLUSTERS_PER_BATCH 16\n\n#define FN(X) X ## Literal\n#define DataType uint8_t\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_splitter_inc.h\"\n#undef DataType\n#undef FN\n\n#define FN(X) X ## Command\n#define DataType uint16_t\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_splitter_inc.h\"\n#undef FN\n\n#define FN(X) X ## Distance\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_splitter_inc.h\"\n#undef DataType\n#undef FN\n\nvoid BrotliInitBlockSplit(BlockSplit* self) {\n  self->num_types = 0;\n  self->num_blocks = 0;\n  self->types = 0;\n  self->lengths = 0;\n  self->types_alloc_size = 0;\n  self->lengths_alloc_size = 0;\n}\n\nvoid BrotliDestroyBlockSplit(MemoryManager* m, BlockSplit* self) {\n  BROTLI_FREE(m, self->types);\n  BROTLI_FREE(m, self->lengths);\n}\n\n/* Extracts literals, command distance and prefix codes, then applies\n * SplitByteVector to create partitioning. */\nvoid BrotliSplitBlock(MemoryManager* m,\n                      const Command* cmds,\n                      const size_t num_commands,\n                      const uint8_t* data,\n                      const size_t pos,\n                      const size_t mask,\n                      const BrotliEncoderParams* params,\n                      BlockSplit* literal_split,\n                      BlockSplit* insert_and_copy_split,\n                      BlockSplit* dist_split) {\n  {\n    size_t literals_count = CountLiterals(cmds, num_commands);\n    uint8_t* literals = BROTLI_ALLOC(m, uint8_t, literals_count);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literals)) return;\n    /* Create a continuous array of literals. */\n    CopyLiteralsToByteArray(cmds, num_commands, data, pos, mask, literals);\n    /* Create the block split on the array of literals.\n     * Literal histograms can have alphabet size up to 256.\n     * Though, to accommodate context modeling, less than half of maximum size\n     * is allowed. */\n    SplitByteVectorLiteral(\n        m, literals, literals_count,\n        kSymbolsPerLiteralHistogram, kMaxLiteralHistograms,\n        kLiteralStrideLength, kLiteralBlockSwitchCost, params,\n        literal_split);\n    if (BROTLI_IS_OOM(m)) return;\n    BROTLI_FREE(m, literals);\n    /* NB: this might be a good place for injecting extra splitting without\n     *     increasing encoder complexity; however, output parition would be less\n     *     optimal than one produced with forced splitting inside\n     *     SplitByteVector (FindBlocks / ClusterBlocks). */\n  }\n\n  {\n    /* Compute prefix codes for commands. */\n    uint16_t* insert_and_copy_codes = BROTLI_ALLOC(m, uint16_t, num_commands);\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(insert_and_copy_codes)) return;\n    for (i = 0; i < num_commands; ++i) {\n      insert_and_copy_codes[i] = cmds[i].cmd_prefix_;\n    }\n    /* Create the block split on the array of command prefixes. */\n    SplitByteVectorCommand(\n        m, insert_and_copy_codes, num_commands,\n        kSymbolsPerCommandHistogram, kMaxCommandHistograms,\n        kCommandStrideLength, kCommandBlockSwitchCost, params,\n        insert_and_copy_split);\n    if (BROTLI_IS_OOM(m)) return;\n    /* TODO(eustas): reuse for distances? */\n    BROTLI_FREE(m, insert_and_copy_codes);\n  }\n\n  {\n    /* Create a continuous array of distance prefixes. */\n    uint16_t* distance_prefixes = BROTLI_ALLOC(m, uint16_t, num_commands);\n    size_t j = 0;\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_prefixes)) return;\n    for (i = 0; i < num_commands; ++i) {\n      const Command* cmd = &cmds[i];\n      if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\n        distance_prefixes[j++] = cmd->dist_prefix_ & 0x3FF;\n      }\n    }\n    /* Create the block split on the array of distance prefixes. */\n    SplitByteVectorDistance(\n        m, distance_prefixes, j,\n        kSymbolsPerDistanceHistogram, kMaxCommandHistograms,\n        kDistanceStrideLength, kDistanceBlockSwitchCost, params,\n        dist_split);\n    if (BROTLI_IS_OOM(m)) return;\n    BROTLI_FREE(m, distance_prefixes);\n  }\n}\n\n#if defined(BROTLI_TEST)\nsize_t CountLiteralsForTest(const Command*, const size_t);\nsize_t CountLiteralsForTest(const Command* cmds, const size_t num_commands) {\n  return CountLiterals(cmds, num_commands);\n}\n\nvoid CopyLiteralsToByteArrayForTest(const Command*,\n    const size_t, const uint8_t*, const size_t, const size_t, uint8_t*);\nvoid CopyLiteralsToByteArrayForTest(const Command* cmds,\n    const size_t num_commands, const uint8_t* data, const size_t offset,\n    const size_t mask, uint8_t* literals) {\n  CopyLiteralsToByteArray(cmds, num_commands, data, offset, mask, literals);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/block_splitter.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Block split point selection utilities. */\n\n#ifndef BROTLI_ENC_BLOCK_SPLITTER_H_\n#define BROTLI_ENC_BLOCK_SPLITTER_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BlockSplit {\n  size_t num_types;  /* Amount of distinct types */\n  size_t num_blocks;  /* Amount of values in types and length */\n  uint8_t* types;\n  uint32_t* lengths;\n\n  size_t types_alloc_size;\n  size_t lengths_alloc_size;\n} BlockSplit;\n\nBROTLI_INTERNAL void BrotliInitBlockSplit(BlockSplit* self);\nBROTLI_INTERNAL void BrotliDestroyBlockSplit(MemoryManager* m,\n                                             BlockSplit* self);\n\nBROTLI_INTERNAL void BrotliSplitBlock(MemoryManager* m,\n                                      const Command* cmds,\n                                      const size_t num_commands,\n                                      const uint8_t* data,\n                                      const size_t offset,\n                                      const size_t mask,\n                                      const BrotliEncoderParams* params,\n                                      BlockSplit* literal_split,\n                                      BlockSplit* insert_and_copy_split,\n                                      BlockSplit* dist_split);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BLOCK_SPLITTER_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/block_splitter_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, DataType */\n\n#define HistogramType FN(Histogram)\n\nstatic void FN(InitialEntropyCodes)(const DataType* data, size_t length,\n                                    size_t stride,\n                                    size_t num_histograms,\n                                    HistogramType* histograms) {\n  uint32_t seed = 7;\n  size_t block_length = length / num_histograms;\n  size_t i;\n  FN(ClearHistograms)(histograms, num_histograms);\n  for (i = 0; i < num_histograms; ++i) {\n    size_t pos = length * i / num_histograms;\n    if (i != 0) {\n      pos += MyRand(&seed) % block_length;\n    }\n    if (pos + stride >= length) {\n      pos = length - stride - 1;\n    }\n    FN(HistogramAddVector)(&histograms[i], data + pos, stride);\n  }\n}\n\nstatic void FN(RandomSample)(uint32_t* seed,\n                             const DataType* data,\n                             size_t length,\n                             size_t stride,\n                             HistogramType* sample) {\n  size_t pos = 0;\n  if (stride >= length) {\n    stride = length;\n  } else {\n    pos = MyRand(seed) % (length - stride + 1);\n  }\n  FN(HistogramAddVector)(sample, data + pos, stride);\n}\n\nstatic void FN(RefineEntropyCodes)(const DataType* data, size_t length,\n                                   size_t stride,\n                                   size_t num_histograms,\n                                   HistogramType* histograms,\n                                   HistogramType* tmp) {\n  size_t iters =\n      kIterMulForRefining * length / stride + kMinItersForRefining;\n  uint32_t seed = 7;\n  size_t iter;\n  iters = ((iters + num_histograms - 1) / num_histograms) * num_histograms;\n  for (iter = 0; iter < iters; ++iter) {\n    FN(HistogramClear)(tmp);\n    FN(RandomSample)(&seed, data, length, stride, tmp);\n    FN(HistogramAddHistogram)(&histograms[iter % num_histograms], tmp);\n  }\n}\n\n/* Assigns a block id from the range [0, num_histograms) to each data element\n   in data[0..length) and fills in block_id[0..length) with the assigned values.\n   Returns the number of blocks, i.e. one plus the number of block switches. */\nstatic size_t FN(FindBlocks)(const DataType* data, const size_t length,\n                             const double block_switch_bitcost,\n                             const size_t num_histograms,\n                             const HistogramType* histograms,\n                             double* insert_cost,\n                             double* cost,\n                             uint8_t* switch_signal,\n                             uint8_t* block_id) {\n  const size_t alphabet_size = FN(HistogramDataSize)();\n  const size_t bitmap_len = (num_histograms + 7) >> 3;\n  size_t num_blocks = 1;\n  size_t byte_ix;\n  size_t i;\n  size_t j;\n  BROTLI_DCHECK(num_histograms <= 256);\n\n  /* Trivial case: single historgram -> single block type. */\n  if (num_histograms <= 1) {\n    for (i = 0; i < length; ++i) {\n      block_id[i] = 0;\n    }\n    return 1;\n  }\n\n  /* Fill bitcost for each symbol of all histograms.\n   * Non-existing symbol cost: 2 + log2(total_count).\n   * Regular symbol cost: -log2(symbol_count / total_count). */\n  memset(insert_cost, 0,\n         sizeof(insert_cost[0]) * alphabet_size * num_histograms);\n  for (i = 0; i < num_histograms; ++i) {\n    insert_cost[i] = FastLog2((uint32_t)histograms[i].total_count_);\n  }\n  for (i = alphabet_size; i != 0;) {\n    /* Reverse order to use the 0-th row as a temporary storage. */\n    --i;\n    for (j = 0; j < num_histograms; ++j) {\n      insert_cost[i * num_histograms + j] =\n          insert_cost[j] - BitCost(histograms[j].data_[i]);\n    }\n  }\n\n  /* After each iteration of this loop, cost[k] will contain the difference\n     between the minimum cost of arriving at the current byte position using\n     entropy code k, and the minimum cost of arriving at the current byte\n     position. This difference is capped at the block switch cost, and if it\n     reaches block switch cost, it means that when we trace back from the last\n     position, we need to switch here. */\n  memset(cost, 0, sizeof(cost[0]) * num_histograms);\n  memset(switch_signal, 0, sizeof(switch_signal[0]) * length * bitmap_len);\n  for (byte_ix = 0; byte_ix < length; ++byte_ix) {\n    size_t ix = byte_ix * bitmap_len;\n    size_t symbol = data[byte_ix];\n    size_t insert_cost_ix = symbol * num_histograms;\n    double min_cost = 1e99;\n    double block_switch_cost = block_switch_bitcost;\n    size_t k;\n    for (k = 0; k < num_histograms; ++k) {\n      /* We are coding the symbol with entropy code k. */\n      cost[k] += insert_cost[insert_cost_ix + k];\n      if (cost[k] < min_cost) {\n        min_cost = cost[k];\n        block_id[byte_ix] = (uint8_t)k;\n      }\n    }\n    /* More blocks for the beginning. */\n    if (byte_ix < 2000) {\n      block_switch_cost *= 0.77 + 0.07 * (double)byte_ix / 2000;\n    }\n    for (k = 0; k < num_histograms; ++k) {\n      cost[k] -= min_cost;\n      if (cost[k] >= block_switch_cost) {\n        const uint8_t mask = (uint8_t)(1u << (k & 7));\n        cost[k] = block_switch_cost;\n        BROTLI_DCHECK((k >> 3) < bitmap_len);\n        switch_signal[ix + (k >> 3)] |= mask;\n      }\n    }\n  }\n\n  byte_ix = length - 1;\n  {  /* Trace back from the last position and switch at the marked places. */\n    size_t ix = byte_ix * bitmap_len;\n    uint8_t cur_id = block_id[byte_ix];\n    while (byte_ix > 0) {\n      const uint8_t mask = (uint8_t)(1u << (cur_id & 7));\n      BROTLI_DCHECK(((size_t)cur_id >> 3) < bitmap_len);\n      --byte_ix;\n      ix -= bitmap_len;\n      if (switch_signal[ix + (cur_id >> 3)] & mask) {\n        if (cur_id != block_id[byte_ix]) {\n          cur_id = block_id[byte_ix];\n          ++num_blocks;\n        }\n      }\n      block_id[byte_ix] = cur_id;\n    }\n  }\n  return num_blocks;\n}\n\nstatic size_t FN(RemapBlockIds)(uint8_t* block_ids, const size_t length,\n                                uint16_t* new_id, const size_t num_histograms) {\n  static const uint16_t kInvalidId = 256;\n  uint16_t next_id = 0;\n  size_t i;\n  for (i = 0; i < num_histograms; ++i) {\n    new_id[i] = kInvalidId;\n  }\n  for (i = 0; i < length; ++i) {\n    BROTLI_DCHECK(block_ids[i] < num_histograms);\n    if (new_id[block_ids[i]] == kInvalidId) {\n      new_id[block_ids[i]] = next_id++;\n    }\n  }\n  for (i = 0; i < length; ++i) {\n    block_ids[i] = (uint8_t)new_id[block_ids[i]];\n    BROTLI_DCHECK(block_ids[i] < num_histograms);\n  }\n  BROTLI_DCHECK(next_id <= num_histograms);\n  return next_id;\n}\n\nstatic void FN(BuildBlockHistograms)(const DataType* data, const size_t length,\n                                     const uint8_t* block_ids,\n                                     const size_t num_histograms,\n                                     HistogramType* histograms) {\n  size_t i;\n  FN(ClearHistograms)(histograms, num_histograms);\n  for (i = 0; i < length; ++i) {\n    FN(HistogramAdd)(&histograms[block_ids[i]], data[i]);\n  }\n}\n\n/* Given the initial partitioning build partitioning with limited number\n * of histograms (and block types). */\nstatic void FN(ClusterBlocks)(MemoryManager* m,\n                              const DataType* data, const size_t length,\n                              const size_t num_blocks,\n                              uint8_t* block_ids,\n                              BlockSplit* split) {\n  uint32_t* histogram_symbols = BROTLI_ALLOC(m, uint32_t, num_blocks);\n  uint32_t* u32 =\n      BROTLI_ALLOC(m, uint32_t, num_blocks + 4 * HISTOGRAMS_PER_BATCH);\n  const size_t expected_num_clusters = CLUSTERS_PER_BATCH *\n      (num_blocks + HISTOGRAMS_PER_BATCH - 1) / HISTOGRAMS_PER_BATCH;\n  size_t all_histograms_size = 0;\n  size_t all_histograms_capacity = expected_num_clusters;\n  HistogramType* all_histograms =\n      BROTLI_ALLOC(m, HistogramType, all_histograms_capacity);\n  size_t cluster_size_size = 0;\n  size_t cluster_size_capacity = expected_num_clusters;\n  uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, cluster_size_capacity);\n  size_t num_clusters = 0;\n  HistogramType* histograms = BROTLI_ALLOC(m, HistogramType,\n      BROTLI_MIN(size_t, num_blocks, HISTOGRAMS_PER_BATCH));\n  size_t max_num_pairs =\n      HISTOGRAMS_PER_BATCH * HISTOGRAMS_PER_BATCH / 2;\n  size_t pairs_capacity = max_num_pairs + 1;\n  HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity);\n  size_t pos = 0;\n  uint32_t* clusters;\n  size_t num_final_clusters;\n  static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX;\n  uint32_t* new_index;\n  size_t i;\n  uint32_t* BROTLI_RESTRICT const sizes = u32 + 0 * HISTOGRAMS_PER_BATCH;\n  uint32_t* BROTLI_RESTRICT const new_clusters = u32 + 1 * HISTOGRAMS_PER_BATCH;\n  uint32_t* BROTLI_RESTRICT const symbols = u32 + 2 * HISTOGRAMS_PER_BATCH;\n  uint32_t* BROTLI_RESTRICT const remap = u32 + 3 * HISTOGRAMS_PER_BATCH;\n  uint32_t* BROTLI_RESTRICT const block_lengths =\n      u32 + 4 * HISTOGRAMS_PER_BATCH;\n  /* TODO(eustas): move to arena? */\n  HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 2);\n\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histogram_symbols) ||\n      BROTLI_IS_NULL(u32) || BROTLI_IS_NULL(all_histograms) ||\n      BROTLI_IS_NULL(cluster_size) || BROTLI_IS_NULL(histograms) ||\n      BROTLI_IS_NULL(pairs) || BROTLI_IS_NULL(tmp)) {\n    return;\n  }\n\n  memset(u32, 0, (num_blocks + 4 * HISTOGRAMS_PER_BATCH) * sizeof(uint32_t));\n\n  /* Calculate block lengths (convert repeating values -> series length). */\n  {\n    size_t block_idx = 0;\n    for (i = 0; i < length; ++i) {\n      BROTLI_DCHECK(block_idx < num_blocks);\n      ++block_lengths[block_idx];\n      if (i + 1 == length || block_ids[i] != block_ids[i + 1]) {\n        ++block_idx;\n      }\n    }\n    BROTLI_DCHECK(block_idx == num_blocks);\n  }\n\n  /* Pre-cluster blocks (cluster batches). */\n  for (i = 0; i < num_blocks; i += HISTOGRAMS_PER_BATCH) {\n    const size_t num_to_combine =\n        BROTLI_MIN(size_t, num_blocks - i, HISTOGRAMS_PER_BATCH);\n    size_t num_new_clusters;\n    size_t j;\n    for (j = 0; j < num_to_combine; ++j) {\n      size_t k;\n      size_t block_length = block_lengths[i + j];\n      FN(HistogramClear)(&histograms[j]);\n      for (k = 0; k < block_length; ++k) {\n        FN(HistogramAdd)(&histograms[j], data[pos++]);\n      }\n      histograms[j].bit_cost_ = FN(BrotliPopulationCost)(&histograms[j]);\n      new_clusters[j] = (uint32_t)j;\n      symbols[j] = (uint32_t)j;\n      sizes[j] = 1;\n    }\n    num_new_clusters = FN(BrotliHistogramCombine)(\n        histograms, tmp, sizes, symbols, new_clusters, pairs, num_to_combine,\n        num_to_combine, HISTOGRAMS_PER_BATCH, max_num_pairs);\n    BROTLI_ENSURE_CAPACITY(m, HistogramType, all_histograms,\n        all_histograms_capacity, all_histograms_size + num_new_clusters);\n    BROTLI_ENSURE_CAPACITY(m, uint32_t, cluster_size,\n        cluster_size_capacity, cluster_size_size + num_new_clusters);\n    if (BROTLI_IS_OOM(m)) return;\n    for (j = 0; j < num_new_clusters; ++j) {\n      all_histograms[all_histograms_size++] = histograms[new_clusters[j]];\n      cluster_size[cluster_size_size++] = sizes[new_clusters[j]];\n      remap[new_clusters[j]] = (uint32_t)j;\n    }\n    for (j = 0; j < num_to_combine; ++j) {\n      histogram_symbols[i + j] = (uint32_t)num_clusters + remap[symbols[j]];\n    }\n    num_clusters += num_new_clusters;\n    BROTLI_DCHECK(num_clusters == cluster_size_size);\n    BROTLI_DCHECK(num_clusters == all_histograms_size);\n  }\n  BROTLI_FREE(m, histograms);\n\n  /* Final clustering. */\n  max_num_pairs =\n      BROTLI_MIN(size_t, 64 * num_clusters, (num_clusters / 2) * num_clusters);\n  if (pairs_capacity < max_num_pairs + 1) {\n    BROTLI_FREE(m, pairs);\n    pairs = BROTLI_ALLOC(m, HistogramPair, max_num_pairs + 1);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(pairs)) return;\n  }\n  clusters = BROTLI_ALLOC(m, uint32_t, num_clusters);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(clusters)) return;\n  for (i = 0; i < num_clusters; ++i) {\n    clusters[i] = (uint32_t)i;\n  }\n  num_final_clusters = FN(BrotliHistogramCombine)(\n      all_histograms, tmp, cluster_size, histogram_symbols, clusters, pairs,\n      num_clusters, num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES,\n      max_num_pairs);\n  BROTLI_FREE(m, pairs);\n  BROTLI_FREE(m, cluster_size);\n\n  /* Assign blocks to final histograms. */\n  new_index = BROTLI_ALLOC(m, uint32_t, num_clusters);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return;\n  for (i = 0; i < num_clusters; ++i) new_index[i] = kInvalidIndex;\n  pos = 0;\n  {\n    uint32_t next_index = 0;\n    for (i = 0; i < num_blocks; ++i) {\n      size_t j;\n      uint32_t best_out;\n      double best_bits;\n      FN(HistogramClear)(tmp);\n      for (j = 0; j < block_lengths[i]; ++j) {\n        FN(HistogramAdd)(tmp, data[pos++]);\n      }\n      /* Among equally good histograms prefer last used. */\n      /* TODO(eustas): should we give a block-switch discount here? */\n      best_out = (i == 0) ? histogram_symbols[0] : histogram_symbols[i - 1];\n      best_bits = FN(BrotliHistogramBitCostDistance)(\n          tmp, &all_histograms[best_out], tmp + 1);\n      for (j = 0; j < num_final_clusters; ++j) {\n        const double cur_bits = FN(BrotliHistogramBitCostDistance)(\n            tmp, &all_histograms[clusters[j]], tmp + 1);\n        if (cur_bits < best_bits) {\n          best_bits = cur_bits;\n          best_out = clusters[j];\n        }\n      }\n      histogram_symbols[i] = best_out;\n      if (new_index[best_out] == kInvalidIndex) {\n        new_index[best_out] = next_index++;\n      }\n    }\n  }\n  BROTLI_FREE(m, tmp);\n  BROTLI_FREE(m, clusters);\n  BROTLI_FREE(m, all_histograms);\n  BROTLI_ENSURE_CAPACITY(\n      m, uint8_t, split->types, split->types_alloc_size, num_blocks);\n  BROTLI_ENSURE_CAPACITY(\n      m, uint32_t, split->lengths, split->lengths_alloc_size, num_blocks);\n  if (BROTLI_IS_OOM(m)) return;\n\n  /* Rewrite final assignment to block-split. There might be less blocks\n   * than |num_blocks| due to clustering. */\n  {\n    uint32_t cur_length = 0;\n    size_t block_idx = 0;\n    uint8_t max_type = 0;\n    for (i = 0; i < num_blocks; ++i) {\n      cur_length += block_lengths[i];\n      if (i + 1 == num_blocks ||\n          histogram_symbols[i] != histogram_symbols[i + 1]) {\n        const uint8_t id = (uint8_t)new_index[histogram_symbols[i]];\n        split->types[block_idx] = id;\n        split->lengths[block_idx] = cur_length;\n        max_type = BROTLI_MAX(uint8_t, max_type, id);\n        cur_length = 0;\n        ++block_idx;\n      }\n    }\n    split->num_blocks = block_idx;\n    split->num_types = (size_t)max_type + 1;\n  }\n  BROTLI_FREE(m, new_index);\n  BROTLI_FREE(m, u32);\n  BROTLI_FREE(m, histogram_symbols);\n}\n\n/* Create BlockSplit (partitioning) given the limits, estimates and \"effort\"\n * parameters.\n *\n * NB: max_histograms is often less than number of histograms allowed by format;\n *     this is done intentionally, to save some \"space\" for context-aware\n *     clustering (here entropy is estimated for context-free symbols). */\nstatic void FN(SplitByteVector)(MemoryManager* m,\n                                const DataType* data, const size_t length,\n                                const size_t symbols_per_histogram,\n                                const size_t max_histograms,\n                                const size_t sampling_stride_length,\n                                const double block_switch_cost,\n                                const BrotliEncoderParams* params,\n                                BlockSplit* split) {\n  const size_t data_size = FN(HistogramDataSize)();\n  HistogramType* histograms;\n  HistogramType* tmp;\n  /* Calculate number of histograms; initial estimate is one histogram per\n   * specified amount of symbols; however, this value is capped. */\n  size_t num_histograms = length / symbols_per_histogram + 1;\n  if (num_histograms > max_histograms) {\n    num_histograms = max_histograms;\n  }\n\n  /* Corner case: no input. */\n  if (length == 0) {\n    split->num_types = 1;\n    return;\n  }\n\n  if (length < kMinLengthForBlockSplitting) {\n    BROTLI_ENSURE_CAPACITY(m, uint8_t,\n        split->types, split->types_alloc_size, split->num_blocks + 1);\n    BROTLI_ENSURE_CAPACITY(m, uint32_t,\n        split->lengths, split->lengths_alloc_size, split->num_blocks + 1);\n    if (BROTLI_IS_OOM(m)) return;\n    split->num_types = 1;\n    split->types[split->num_blocks] = 0;\n    split->lengths[split->num_blocks] = (uint32_t)length;\n    split->num_blocks++;\n    return;\n  }\n  histograms = BROTLI_ALLOC(m, HistogramType, num_histograms + 1);\n  tmp = histograms + num_histograms;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(histograms)) return;\n  /* Find good entropy codes. */\n  FN(InitialEntropyCodes)(data, length,\n                          sampling_stride_length,\n                          num_histograms, histograms);\n  FN(RefineEntropyCodes)(data, length,\n                         sampling_stride_length,\n                         num_histograms, histograms, tmp);\n  {\n    /* Find a good path through literals with the good entropy codes. */\n    uint8_t* block_ids = BROTLI_ALLOC(m, uint8_t, length);\n    size_t num_blocks = 0;\n    const size_t bitmaplen = (num_histograms + 7) >> 3;\n    double* insert_cost = BROTLI_ALLOC(m, double, data_size * num_histograms);\n    double* cost = BROTLI_ALLOC(m, double, num_histograms);\n    uint8_t* switch_signal = BROTLI_ALLOC(m, uint8_t, length * bitmaplen);\n    uint16_t* new_id = BROTLI_ALLOC(m, uint16_t, num_histograms);\n    const size_t iters = params->quality < HQ_ZOPFLIFICATION_QUALITY ? 3 : 10;\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(block_ids) ||\n        BROTLI_IS_NULL(insert_cost) || BROTLI_IS_NULL(cost) ||\n        BROTLI_IS_NULL(switch_signal) || BROTLI_IS_NULL(new_id)) {\n      return;\n    }\n    for (i = 0; i < iters; ++i) {\n      num_blocks = FN(FindBlocks)(data, length,\n                                  block_switch_cost,\n                                  num_histograms, histograms,\n                                  insert_cost, cost, switch_signal,\n                                  block_ids);\n      num_histograms = FN(RemapBlockIds)(block_ids, length,\n                                         new_id, num_histograms);\n      FN(BuildBlockHistograms)(data, length, block_ids,\n                               num_histograms, histograms);\n    }\n    BROTLI_FREE(m, insert_cost);\n    BROTLI_FREE(m, cost);\n    BROTLI_FREE(m, switch_signal);\n    BROTLI_FREE(m, new_id);\n    BROTLI_FREE(m, histograms);\n    FN(ClusterBlocks)(m, data, length, num_blocks, block_ids, split);\n    if (BROTLI_IS_OOM(m)) return;\n    BROTLI_FREE(m, block_ids);\n  }\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "third-party/brotli/enc/brotli_bit_stream.c",
    "content": "/* Copyright 2014 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Brotli bit stream functions to support the low level format. There are no\n   compression algorithms here, just the right ordering of bits to match the\n   specs. */\n\n#include \"brotli_bit_stream.h\"\n\n#include <string.h>  /* memcpy, memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"entropy_encode.h\"\n#include \"entropy_encode_static.h\"\n#include \"fast_log.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_HUFFMAN_TREE_SIZE (2 * BROTLI_NUM_COMMAND_SYMBOLS + 1)\n/* The maximum size of Huffman dictionary for distances assuming that\n   NPOSTFIX = 0 and NDIRECT = 0. */\n#define MAX_SIMPLE_DISTANCE_ALPHABET_SIZE \\\n  BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_LARGE_MAX_DISTANCE_BITS)\n/* MAX_SIMPLE_DISTANCE_ALPHABET_SIZE == 140 */\n\nstatic BROTLI_INLINE uint32_t BlockLengthPrefixCode(uint32_t len) {\n  uint32_t code = (len >= 177) ? (len >= 753 ? 20 : 14) : (len >= 41 ? 7 : 0);\n  while (code < (BROTLI_NUM_BLOCK_LEN_SYMBOLS - 1) &&\n      len >= _kBrotliPrefixCodeRanges[code + 1].offset) ++code;\n  return code;\n}\n\nstatic BROTLI_INLINE void GetBlockLengthPrefixCode(uint32_t len, size_t* code,\n    uint32_t* n_extra, uint32_t* extra) {\n  *code = BlockLengthPrefixCode(len);\n  *n_extra = _kBrotliPrefixCodeRanges[*code].nbits;\n  *extra = len - _kBrotliPrefixCodeRanges[*code].offset;\n}\n\ntypedef struct BlockTypeCodeCalculator {\n  size_t last_type;\n  size_t second_last_type;\n} BlockTypeCodeCalculator;\n\nstatic void InitBlockTypeCodeCalculator(BlockTypeCodeCalculator* self) {\n  self->last_type = 1;\n  self->second_last_type = 0;\n}\n\nstatic BROTLI_INLINE size_t NextBlockTypeCode(\n    BlockTypeCodeCalculator* calculator, uint8_t type) {\n  size_t type_code = (type == calculator->last_type + 1) ? 1u :\n      (type == calculator->second_last_type) ? 0u : type + 2u;\n  calculator->second_last_type = calculator->last_type;\n  calculator->last_type = type;\n  return type_code;\n}\n\n/* |nibblesbits| represents the 2 bits to encode MNIBBLES (0-3)\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nstatic void BrotliEncodeMlen(size_t length, uint64_t* bits,\n                             size_t* numbits, uint64_t* nibblesbits) {\n  size_t lg = (length == 1) ? 1 : Log2FloorNonZero((uint32_t)(length - 1)) + 1;\n  size_t mnibbles = (lg < 16 ? 16 : (lg + 3)) / 4;\n  BROTLI_DCHECK(length > 0);\n  BROTLI_DCHECK(length <= (1 << 24));\n  BROTLI_DCHECK(lg <= 24);\n  *nibblesbits = mnibbles - 4;\n  *numbits = mnibbles * 4;\n  *bits = length - 1;\n}\n\nstatic BROTLI_INLINE void StoreCommandExtra(\n    const Command* cmd, size_t* storage_ix, uint8_t* storage) {\n  uint32_t copylen_code = CommandCopyLenCode(cmd);\n  uint16_t inscode = GetInsertLengthCode(cmd->insert_len_);\n  uint16_t copycode = GetCopyLengthCode(copylen_code);\n  uint32_t insnumextra = GetInsertExtra(inscode);\n  uint64_t insextraval = cmd->insert_len_ - GetInsertBase(inscode);\n  uint64_t copyextraval = copylen_code - GetCopyBase(copycode);\n  uint64_t bits = (copyextraval << insnumextra) | insextraval;\n  BrotliWriteBits(\n      insnumextra + GetCopyExtra(copycode), bits, storage_ix, storage);\n}\n\n/* Data structure that stores almost everything that is needed to encode each\n   block switch command. */\ntypedef struct BlockSplitCode {\n  BlockTypeCodeCalculator type_code_calculator;\n  uint8_t type_depths[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];\n  uint16_t type_bits[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];\n  uint8_t length_depths[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n  uint16_t length_bits[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n} BlockSplitCode;\n\n/* Stores a number between 0 and 255. */\nstatic void StoreVarLenUint8(size_t n, size_t* storage_ix, uint8_t* storage) {\n  if (n == 0) {\n    BrotliWriteBits(1, 0, storage_ix, storage);\n  } else {\n    size_t nbits = Log2FloorNonZero(n);\n    BrotliWriteBits(1, 1, storage_ix, storage);\n    BrotliWriteBits(3, nbits, storage_ix, storage);\n    BrotliWriteBits(nbits, n - ((size_t)1 << nbits), storage_ix, storage);\n  }\n}\n\n/* Stores the compressed meta-block header.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nstatic void StoreCompressedMetaBlockHeader(BROTLI_BOOL is_final_block,\n                                           size_t length,\n                                           size_t* storage_ix,\n                                           uint8_t* storage) {\n  uint64_t lenbits;\n  size_t nlenbits;\n  uint64_t nibblesbits;\n\n  /* Write ISLAST bit. */\n  BrotliWriteBits(1, (uint64_t)is_final_block, storage_ix, storage);\n  /* Write ISEMPTY bit. */\n  if (is_final_block) {\n    BrotliWriteBits(1, 0, storage_ix, storage);\n  }\n\n  BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits);\n  BrotliWriteBits(2, nibblesbits, storage_ix, storage);\n  BrotliWriteBits(nlenbits, lenbits, storage_ix, storage);\n\n  if (!is_final_block) {\n    /* Write ISUNCOMPRESSED bit. */\n    BrotliWriteBits(1, 0, storage_ix, storage);\n  }\n}\n\n/* Stores the uncompressed meta-block header.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nstatic void BrotliStoreUncompressedMetaBlockHeader(size_t length,\n                                                   size_t* storage_ix,\n                                                   uint8_t* storage) {\n  uint64_t lenbits;\n  size_t nlenbits;\n  uint64_t nibblesbits;\n\n  /* Write ISLAST bit.\n     Uncompressed block cannot be the last one, so set to 0. */\n  BrotliWriteBits(1, 0, storage_ix, storage);\n  BrotliEncodeMlen(length, &lenbits, &nlenbits, &nibblesbits);\n  BrotliWriteBits(2, nibblesbits, storage_ix, storage);\n  BrotliWriteBits(nlenbits, lenbits, storage_ix, storage);\n  /* Write ISUNCOMPRESSED bit. */\n  BrotliWriteBits(1, 1, storage_ix, storage);\n}\n\nstatic void BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(\n    const int num_codes, const uint8_t* code_length_bitdepth,\n    size_t* storage_ix, uint8_t* storage) {\n  static const uint8_t kStorageOrder[BROTLI_CODE_LENGTH_CODES] = {\n    1, 2, 3, 4, 0, 5, 17, 6, 16, 7, 8, 9, 10, 11, 12, 13, 14, 15\n  };\n  /* The bit lengths of the Huffman code over the code length alphabet\n     are compressed with the following static Huffman code:\n       Symbol   Code\n       ------   ----\n       0          00\n       1        1110\n       2         110\n       3          01\n       4          10\n       5        1111 */\n  static const uint8_t kHuffmanBitLengthHuffmanCodeSymbols[6] = {\n     0, 7, 3, 2, 1, 15\n  };\n  static const uint8_t kHuffmanBitLengthHuffmanCodeBitLengths[6] = {\n    2, 4, 3, 2, 2, 4\n  };\n\n  size_t skip_some = 0;  /* skips none. */\n\n  /* Throw away trailing zeros: */\n  size_t codes_to_store = BROTLI_CODE_LENGTH_CODES;\n  if (num_codes > 1) {\n    for (; codes_to_store > 0; --codes_to_store) {\n      if (code_length_bitdepth[kStorageOrder[codes_to_store - 1]] != 0) {\n        break;\n      }\n    }\n  }\n  if (code_length_bitdepth[kStorageOrder[0]] == 0 &&\n      code_length_bitdepth[kStorageOrder[1]] == 0) {\n    skip_some = 2;  /* skips two. */\n    if (code_length_bitdepth[kStorageOrder[2]] == 0) {\n      skip_some = 3;  /* skips three. */\n    }\n  }\n  BrotliWriteBits(2, skip_some, storage_ix, storage);\n  {\n    size_t i;\n    for (i = skip_some; i < codes_to_store; ++i) {\n      size_t l = code_length_bitdepth[kStorageOrder[i]];\n      BrotliWriteBits(kHuffmanBitLengthHuffmanCodeBitLengths[l],\n          kHuffmanBitLengthHuffmanCodeSymbols[l], storage_ix, storage);\n    }\n  }\n}\n\nstatic void BrotliStoreHuffmanTreeToBitMask(\n    const size_t huffman_tree_size, const uint8_t* huffman_tree,\n    const uint8_t* huffman_tree_extra_bits, const uint8_t* code_length_bitdepth,\n    const uint16_t* code_length_bitdepth_symbols,\n    size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage) {\n  size_t i;\n  for (i = 0; i < huffman_tree_size; ++i) {\n    size_t ix = huffman_tree[i];\n    BrotliWriteBits(code_length_bitdepth[ix], code_length_bitdepth_symbols[ix],\n                    storage_ix, storage);\n    /* Extra bits */\n    switch (ix) {\n      case BROTLI_REPEAT_PREVIOUS_CODE_LENGTH:\n        BrotliWriteBits(2, huffman_tree_extra_bits[i], storage_ix, storage);\n        break;\n      case BROTLI_REPEAT_ZERO_CODE_LENGTH:\n        BrotliWriteBits(3, huffman_tree_extra_bits[i], storage_ix, storage);\n        break;\n    }\n  }\n}\n\nstatic void StoreSimpleHuffmanTree(const uint8_t* depths,\n                                   size_t symbols[4],\n                                   size_t num_symbols,\n                                   size_t max_bits,\n                                   size_t* storage_ix, uint8_t* storage) {\n  /* value of 1 indicates a simple Huffman code */\n  BrotliWriteBits(2, 1, storage_ix, storage);\n  BrotliWriteBits(2, num_symbols - 1, storage_ix, storage);  /* NSYM - 1 */\n\n  {\n    /* Sort */\n    size_t i;\n    for (i = 0; i < num_symbols; i++) {\n      size_t j;\n      for (j = i + 1; j < num_symbols; j++) {\n        if (depths[symbols[j]] < depths[symbols[i]]) {\n          BROTLI_SWAP(size_t, symbols, j, i);\n        }\n      }\n    }\n  }\n\n  if (num_symbols == 2) {\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n  } else if (num_symbols == 3) {\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n  } else {\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[3], storage_ix, storage);\n    /* tree-select */\n    BrotliWriteBits(1, depths[symbols[0]] == 1 ? 1 : 0, storage_ix, storage);\n  }\n}\n\n/* num = alphabet size\n   depths = symbol depths */\nvoid BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,\n                            HuffmanTree* tree,\n                            size_t* storage_ix, uint8_t* storage) {\n  /* Write the Huffman tree into the brotli-representation.\n     The command alphabet is the largest, so this allocation will fit all\n     alphabets. */\n  /* TODO(eustas): fix me */\n  uint8_t huffman_tree[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint8_t huffman_tree_extra_bits[BROTLI_NUM_COMMAND_SYMBOLS];\n  size_t huffman_tree_size = 0;\n  uint8_t code_length_bitdepth[BROTLI_CODE_LENGTH_CODES] = { 0 };\n  uint16_t code_length_bitdepth_symbols[BROTLI_CODE_LENGTH_CODES];\n  uint32_t huffman_tree_histogram[BROTLI_CODE_LENGTH_CODES] = { 0 };\n  size_t i;\n  int num_codes = 0;\n  size_t code = 0;\n\n  BROTLI_DCHECK(num <= BROTLI_NUM_COMMAND_SYMBOLS);\n\n  BrotliWriteHuffmanTree(depths, num, &huffman_tree_size, huffman_tree,\n                         huffman_tree_extra_bits);\n\n  /* Calculate the statistics of the Huffman tree in brotli-representation. */\n  for (i = 0; i < huffman_tree_size; ++i) {\n    ++huffman_tree_histogram[huffman_tree[i]];\n  }\n\n  for (i = 0; i < BROTLI_CODE_LENGTH_CODES; ++i) {\n    if (huffman_tree_histogram[i]) {\n      if (num_codes == 0) {\n        code = i;\n        num_codes = 1;\n      } else if (num_codes == 1) {\n        num_codes = 2;\n        break;\n      }\n    }\n  }\n\n  /* Calculate another Huffman tree to use for compressing both the\n     earlier Huffman tree with. */\n  BrotliCreateHuffmanTree(huffman_tree_histogram, BROTLI_CODE_LENGTH_CODES,\n                          5, tree, code_length_bitdepth);\n  BrotliConvertBitDepthsToSymbols(code_length_bitdepth,\n                                  BROTLI_CODE_LENGTH_CODES,\n                                  code_length_bitdepth_symbols);\n\n  /* Now, we have all the data, let's start storing it */\n  BrotliStoreHuffmanTreeOfHuffmanTreeToBitMask(num_codes, code_length_bitdepth,\n                                               storage_ix, storage);\n\n  if (num_codes == 1) {\n    code_length_bitdepth[code] = 0;\n  }\n\n  /* Store the real Huffman tree now. */\n  BrotliStoreHuffmanTreeToBitMask(huffman_tree_size,\n                                  huffman_tree,\n                                  huffman_tree_extra_bits,\n                                  code_length_bitdepth,\n                                  code_length_bitdepth_symbols,\n                                  storage_ix, storage);\n}\n\n/* Builds a Huffman tree from histogram[0:length] into depth[0:length] and\n   bits[0:length] and stores the encoded tree to the bit stream. */\nstatic void BuildAndStoreHuffmanTree(const uint32_t* histogram,\n                                     const size_t histogram_length,\n                                     const size_t alphabet_size,\n                                     HuffmanTree* tree,\n                                     uint8_t* depth,\n                                     uint16_t* bits,\n                                     size_t* storage_ix,\n                                     uint8_t* storage) {\n  size_t count = 0;\n  size_t s4[4] = { 0 };\n  size_t i;\n  size_t max_bits = 0;\n  for (i = 0; i < histogram_length; i++) {\n    if (histogram[i]) {\n      if (count < 4) {\n        s4[count] = i;\n      } else if (count > 4) {\n        break;\n      }\n      count++;\n    }\n  }\n\n  {\n    size_t max_bits_counter = alphabet_size - 1;\n    while (max_bits_counter) {\n      max_bits_counter >>= 1;\n      ++max_bits;\n    }\n  }\n\n  if (count <= 1) {\n    BrotliWriteBits(4, 1, storage_ix, storage);\n    BrotliWriteBits(max_bits, s4[0], storage_ix, storage);\n    depth[s4[0]] = 0;\n    bits[s4[0]] = 0;\n    return;\n  }\n\n  memset(depth, 0, histogram_length * sizeof(depth[0]));\n  BrotliCreateHuffmanTree(histogram, histogram_length, 15, tree, depth);\n  BrotliConvertBitDepthsToSymbols(depth, histogram_length, bits);\n\n  if (count <= 4) {\n    StoreSimpleHuffmanTree(depth, s4, count, max_bits, storage_ix, storage);\n  } else {\n    BrotliStoreHuffmanTree(depth, histogram_length, tree, storage_ix, storage);\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(\n    const HuffmanTree* v0, const HuffmanTree* v1) {\n  return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);\n}\n\nvoid BrotliBuildAndStoreHuffmanTreeFast(HuffmanTree* tree,\n                                        const uint32_t* histogram,\n                                        const size_t histogram_total,\n                                        const size_t max_bits,\n                                        uint8_t* depth, uint16_t* bits,\n                                        size_t* storage_ix,\n                                        uint8_t* storage) {\n  size_t count = 0;\n  size_t symbols[4] = { 0 };\n  size_t length = 0;\n  size_t total = histogram_total;\n  while (total != 0) {\n    if (histogram[length]) {\n      if (count < 4) {\n        symbols[count] = length;\n      }\n      ++count;\n      total -= histogram[length];\n    }\n    ++length;\n  }\n\n  if (count <= 1) {\n    BrotliWriteBits(4, 1, storage_ix, storage);\n    BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n    depth[symbols[0]] = 0;\n    bits[symbols[0]] = 0;\n    return;\n  }\n\n  memset(depth, 0, length * sizeof(depth[0]));\n  {\n    uint32_t count_limit;\n    for (count_limit = 1; ; count_limit *= 2) {\n      HuffmanTree* node = tree;\n      size_t l;\n      for (l = length; l != 0;) {\n        --l;\n        if (histogram[l]) {\n          if (BROTLI_PREDICT_TRUE(histogram[l] >= count_limit)) {\n            InitHuffmanTree(node, histogram[l], -1, (int16_t)l);\n          } else {\n            InitHuffmanTree(node, count_limit, -1, (int16_t)l);\n          }\n          ++node;\n        }\n      }\n      {\n        const int n = (int)(node - tree);\n        HuffmanTree sentinel;\n        int i = 0;      /* Points to the next leaf node. */\n        int j = n + 1;  /* Points to the next non-leaf node. */\n        int k;\n\n        SortHuffmanTreeItems(tree, (size_t)n, SortHuffmanTree);\n        /* The nodes are:\n           [0, n): the sorted leaf nodes that we start with.\n           [n]: we add a sentinel here.\n           [n + 1, 2n): new parent nodes are added here, starting from\n                        (n+1). These are naturally in ascending order.\n           [2n]: we add a sentinel at the end as well.\n           There will be (2n+1) elements at the end. */\n        InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1);\n        *node++ = sentinel;\n        *node++ = sentinel;\n\n        for (k = n - 1; k > 0; --k) {\n          int left, right;\n          if (tree[i].total_count_ <= tree[j].total_count_) {\n            left = i;\n            ++i;\n          } else {\n            left = j;\n            ++j;\n          }\n          if (tree[i].total_count_ <= tree[j].total_count_) {\n            right = i;\n            ++i;\n          } else {\n            right = j;\n            ++j;\n          }\n          /* The sentinel node becomes the parent node. */\n          node[-1].total_count_ =\n              tree[left].total_count_ + tree[right].total_count_;\n          node[-1].index_left_ = (int16_t)left;\n          node[-1].index_right_or_value_ = (int16_t)right;\n          /* Add back the last sentinel node. */\n          *node++ = sentinel;\n        }\n        if (BrotliSetDepth(2 * n - 1, tree, depth, 14)) {\n          /* We need to pack the Huffman tree in 14 bits. If this was not\n             successful, add fake entities to the lowest values and retry. */\n          break;\n        }\n      }\n    }\n  }\n  BrotliConvertBitDepthsToSymbols(depth, length, bits);\n  if (count <= 4) {\n    size_t i;\n    /* value of 1 indicates a simple Huffman code */\n    BrotliWriteBits(2, 1, storage_ix, storage);\n    BrotliWriteBits(2, count - 1, storage_ix, storage);  /* NSYM - 1 */\n\n    /* Sort */\n    for (i = 0; i < count; i++) {\n      size_t j;\n      for (j = i + 1; j < count; j++) {\n        if (depth[symbols[j]] < depth[symbols[i]]) {\n          BROTLI_SWAP(size_t, symbols, j, i);\n        }\n      }\n    }\n\n    if (count == 2) {\n      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n    } else if (count == 3) {\n      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n    } else {\n      BrotliWriteBits(max_bits, symbols[0], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[1], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[2], storage_ix, storage);\n      BrotliWriteBits(max_bits, symbols[3], storage_ix, storage);\n      /* tree-select */\n      BrotliWriteBits(1, depth[symbols[0]] == 1 ? 1 : 0, storage_ix, storage);\n    }\n  } else {\n    uint8_t previous_value = 8;\n    size_t i;\n    /* Complex Huffman Tree */\n    StoreStaticCodeLengthCode(storage_ix, storage);\n\n    /* Actual RLE coding. */\n    for (i = 0; i < length;) {\n      const uint8_t value = depth[i];\n      size_t reps = 1;\n      size_t k;\n      for (k = i + 1; k < length && depth[k] == value; ++k) {\n        ++reps;\n      }\n      i += reps;\n      if (value == 0) {\n        BrotliWriteBits(kZeroRepsDepth[reps], kZeroRepsBits[reps],\n                        storage_ix, storage);\n      } else {\n        if (previous_value != value) {\n          BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value],\n                          storage_ix, storage);\n          --reps;\n        }\n        if (reps < 3) {\n          while (reps != 0) {\n            reps--;\n            BrotliWriteBits(kCodeLengthDepth[value], kCodeLengthBits[value],\n                            storage_ix, storage);\n          }\n        } else {\n          reps -= 3;\n          BrotliWriteBits(kNonZeroRepsDepth[reps], kNonZeroRepsBits[reps],\n                          storage_ix, storage);\n        }\n        previous_value = value;\n      }\n    }\n  }\n}\n\nstatic size_t IndexOf(const uint8_t* v, size_t v_size, uint8_t value) {\n  size_t i = 0;\n  for (; i < v_size; ++i) {\n    if (v[i] == value) return i;\n  }\n  return i;\n}\n\nstatic void MoveToFront(uint8_t* v, size_t index) {\n  uint8_t value = v[index];\n  size_t i;\n  for (i = index; i != 0; --i) {\n    v[i] = v[i - 1];\n  }\n  v[0] = value;\n}\n\nstatic void MoveToFrontTransform(const uint32_t* BROTLI_RESTRICT v_in,\n                                 const size_t v_size,\n                                 uint32_t* v_out) {\n  size_t i;\n  uint8_t mtf[256];\n  uint32_t max_value;\n  if (v_size == 0) {\n    return;\n  }\n  max_value = v_in[0];\n  for (i = 1; i < v_size; ++i) {\n    if (v_in[i] > max_value) max_value = v_in[i];\n  }\n  BROTLI_DCHECK(max_value < 256u);\n  for (i = 0; i <= max_value; ++i) {\n    mtf[i] = (uint8_t)i;\n  }\n  {\n    size_t mtf_size = max_value + 1;\n    for (i = 0; i < v_size; ++i) {\n      size_t index = IndexOf(mtf, mtf_size, (uint8_t)v_in[i]);\n      BROTLI_DCHECK(index < mtf_size);\n      v_out[i] = (uint32_t)index;\n      MoveToFront(mtf, index);\n    }\n  }\n}\n\n/* Finds runs of zeros in v[0..in_size) and replaces them with a prefix code of\n   the run length plus extra bits (lower 9 bits is the prefix code and the rest\n   are the extra bits). Non-zero values in v[] are shifted by\n   *max_length_prefix. Will not create prefix codes bigger than the initial\n   value of *max_run_length_prefix. The prefix code of run length L is simply\n   Log2Floor(L) and the number of extra bits is the same as the prefix code. */\nstatic void RunLengthCodeZeros(const size_t in_size,\n    uint32_t* BROTLI_RESTRICT v, size_t* BROTLI_RESTRICT out_size,\n    uint32_t* BROTLI_RESTRICT max_run_length_prefix) {\n  uint32_t max_reps = 0;\n  size_t i;\n  uint32_t max_prefix;\n  for (i = 0; i < in_size;) {\n    uint32_t reps = 0;\n    for (; i < in_size && v[i] != 0; ++i) ;\n    for (; i < in_size && v[i] == 0; ++i) {\n      ++reps;\n    }\n    max_reps = BROTLI_MAX(uint32_t, reps, max_reps);\n  }\n  max_prefix = max_reps > 0 ? Log2FloorNonZero(max_reps) : 0;\n  max_prefix = BROTLI_MIN(uint32_t, max_prefix, *max_run_length_prefix);\n  *max_run_length_prefix = max_prefix;\n  *out_size = 0;\n  for (i = 0; i < in_size;) {\n    BROTLI_DCHECK(*out_size <= i);\n    if (v[i] != 0) {\n      v[*out_size] = v[i] + *max_run_length_prefix;\n      ++i;\n      ++(*out_size);\n    } else {\n      uint32_t reps = 1;\n      size_t k;\n      for (k = i + 1; k < in_size && v[k] == 0; ++k) {\n        ++reps;\n      }\n      i += reps;\n      while (reps != 0) {\n        if (reps < (2u << max_prefix)) {\n          uint32_t run_length_prefix = Log2FloorNonZero(reps);\n          const uint32_t extra_bits = reps - (1u << run_length_prefix);\n          v[*out_size] = run_length_prefix + (extra_bits << 9);\n          ++(*out_size);\n          break;\n        } else {\n          const uint32_t extra_bits = (1u << max_prefix) - 1u;\n          v[*out_size] = max_prefix + (extra_bits << 9);\n          reps -= (2u << max_prefix) - 1u;\n          ++(*out_size);\n        }\n      }\n    }\n  }\n}\n\n#define SYMBOL_BITS 9\n\ntypedef struct EncodeContextMapArena {\n  uint32_t histogram[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];\n  uint8_t depths[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];\n  uint16_t bits[BROTLI_MAX_CONTEXT_MAP_SYMBOLS];\n} EncodeContextMapArena;\n\nstatic void EncodeContextMap(MemoryManager* m,\n                             EncodeContextMapArena* arena,\n                             const uint32_t* context_map,\n                             size_t context_map_size,\n                             size_t num_clusters,\n                             HuffmanTree* tree,\n                             size_t* storage_ix, uint8_t* storage) {\n  size_t i;\n  uint32_t* rle_symbols;\n  uint32_t max_run_length_prefix = 6;\n  size_t num_rle_symbols = 0;\n  uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;\n  static const uint32_t kSymbolMask = (1u << SYMBOL_BITS) - 1u;\n  uint8_t* BROTLI_RESTRICT const depths = arena->depths;\n  uint16_t* BROTLI_RESTRICT const bits = arena->bits;\n\n  StoreVarLenUint8(num_clusters - 1, storage_ix, storage);\n\n  if (num_clusters == 1) {\n    return;\n  }\n\n  rle_symbols = BROTLI_ALLOC(m, uint32_t, context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(rle_symbols)) return;\n  MoveToFrontTransform(context_map, context_map_size, rle_symbols);\n  RunLengthCodeZeros(context_map_size, rle_symbols,\n                     &num_rle_symbols, &max_run_length_prefix);\n  memset(histogram, 0, sizeof(arena->histogram));\n  for (i = 0; i < num_rle_symbols; ++i) {\n    ++histogram[rle_symbols[i] & kSymbolMask];\n  }\n  {\n    BROTLI_BOOL use_rle = TO_BROTLI_BOOL(max_run_length_prefix > 0);\n    BrotliWriteBits(1, (uint64_t)use_rle, storage_ix, storage);\n    if (use_rle) {\n      BrotliWriteBits(4, max_run_length_prefix - 1, storage_ix, storage);\n    }\n  }\n  BuildAndStoreHuffmanTree(histogram, num_clusters + max_run_length_prefix,\n                           num_clusters + max_run_length_prefix,\n                           tree, depths, bits, storage_ix, storage);\n  for (i = 0; i < num_rle_symbols; ++i) {\n    const uint32_t rle_symbol = rle_symbols[i] & kSymbolMask;\n    const uint32_t extra_bits_val = rle_symbols[i] >> SYMBOL_BITS;\n    BrotliWriteBits(depths[rle_symbol], bits[rle_symbol], storage_ix, storage);\n    if (rle_symbol > 0 && rle_symbol <= max_run_length_prefix) {\n      BrotliWriteBits(rle_symbol, extra_bits_val, storage_ix, storage);\n    }\n  }\n  BrotliWriteBits(1, 1, storage_ix, storage);  /* use move-to-front */\n  BROTLI_FREE(m, rle_symbols);\n}\n\n/* Stores the block switch command with index block_ix to the bit stream. */\nstatic BROTLI_INLINE void StoreBlockSwitch(BlockSplitCode* code,\n                                           const uint32_t block_len,\n                                           const uint8_t block_type,\n                                           BROTLI_BOOL is_first_block,\n                                           size_t* storage_ix,\n                                           uint8_t* storage) {\n  size_t typecode = NextBlockTypeCode(&code->type_code_calculator, block_type);\n  size_t lencode;\n  uint32_t len_nextra;\n  uint32_t len_extra;\n  if (!is_first_block) {\n    BrotliWriteBits(code->type_depths[typecode], code->type_bits[typecode],\n                    storage_ix, storage);\n  }\n  GetBlockLengthPrefixCode(block_len, &lencode, &len_nextra, &len_extra);\n\n  BrotliWriteBits(code->length_depths[lencode], code->length_bits[lencode],\n                  storage_ix, storage);\n  BrotliWriteBits(len_nextra, len_extra, storage_ix, storage);\n}\n\n/* Builds a BlockSplitCode data structure from the block split given by the\n   vector of block types and block lengths and stores it to the bit stream. */\nstatic void BuildAndStoreBlockSplitCode(const uint8_t* types,\n                                        const uint32_t* lengths,\n                                        const size_t num_blocks,\n                                        const size_t num_types,\n                                        HuffmanTree* tree,\n                                        BlockSplitCode* code,\n                                        size_t* storage_ix,\n                                        uint8_t* storage) {\n  uint32_t type_histo[BROTLI_MAX_BLOCK_TYPE_SYMBOLS];\n  uint32_t length_histo[BROTLI_NUM_BLOCK_LEN_SYMBOLS];\n  size_t i;\n  BlockTypeCodeCalculator type_code_calculator;\n  memset(type_histo, 0, (num_types + 2) * sizeof(type_histo[0]));\n  memset(length_histo, 0, sizeof(length_histo));\n  InitBlockTypeCodeCalculator(&type_code_calculator);\n  for (i = 0; i < num_blocks; ++i) {\n    size_t type_code = NextBlockTypeCode(&type_code_calculator, types[i]);\n    if (i != 0) ++type_histo[type_code];\n    ++length_histo[BlockLengthPrefixCode(lengths[i])];\n  }\n  StoreVarLenUint8(num_types - 1, storage_ix, storage);\n  if (num_types > 1) {  /* TODO(eustas): else? could StoreBlockSwitch occur? */\n    BuildAndStoreHuffmanTree(&type_histo[0], num_types + 2, num_types + 2, tree,\n                             &code->type_depths[0], &code->type_bits[0],\n                             storage_ix, storage);\n    BuildAndStoreHuffmanTree(&length_histo[0], BROTLI_NUM_BLOCK_LEN_SYMBOLS,\n                             BROTLI_NUM_BLOCK_LEN_SYMBOLS,\n                             tree, &code->length_depths[0],\n                             &code->length_bits[0], storage_ix, storage);\n    StoreBlockSwitch(code, lengths[0], types[0], 1, storage_ix, storage);\n  }\n}\n\n/* Stores a context map where the histogram type is always the block type. */\nstatic void StoreTrivialContextMap(EncodeContextMapArena* arena,\n                                   size_t num_types,\n                                   size_t context_bits,\n                                   HuffmanTree* tree,\n                                   size_t* storage_ix,\n                                   uint8_t* storage) {\n  StoreVarLenUint8(num_types - 1, storage_ix, storage);\n  if (num_types > 1) {\n    size_t repeat_code = context_bits - 1u;\n    size_t repeat_bits = (1u << repeat_code) - 1u;\n    size_t alphabet_size = num_types + repeat_code;\n    uint32_t* BROTLI_RESTRICT const histogram = arena->histogram;\n    uint8_t* BROTLI_RESTRICT const depths = arena->depths;\n    uint16_t* BROTLI_RESTRICT const bits = arena->bits;\n    size_t i;\n    memset(histogram, 0, alphabet_size * sizeof(histogram[0]));\n    /* Write RLEMAX. */\n    BrotliWriteBits(1, 1, storage_ix, storage);\n    BrotliWriteBits(4, repeat_code - 1, storage_ix, storage);\n    histogram[repeat_code] = (uint32_t)num_types;\n    histogram[0] = 1;\n    for (i = context_bits; i < alphabet_size; ++i) {\n      histogram[i] = 1;\n    }\n    BuildAndStoreHuffmanTree(histogram, alphabet_size, alphabet_size,\n                             tree, depths, bits, storage_ix, storage);\n    for (i = 0; i < num_types; ++i) {\n      size_t code = (i == 0 ? 0 : i + context_bits - 1);\n      BrotliWriteBits(depths[code], bits[code], storage_ix, storage);\n      BrotliWriteBits(\n          depths[repeat_code], bits[repeat_code], storage_ix, storage);\n      BrotliWriteBits(repeat_code, repeat_bits, storage_ix, storage);\n    }\n    /* Write IMTF (inverse-move-to-front) bit. */\n    BrotliWriteBits(1, 1, storage_ix, storage);\n  }\n}\n\n/* Manages the encoding of one block category (literal, command or distance). */\ntypedef struct BlockEncoder {\n  size_t histogram_length_;\n  size_t num_block_types_;\n  const uint8_t* block_types_;  /* Not owned. */\n  const uint32_t* block_lengths_;  /* Not owned. */\n  size_t num_blocks_;\n  BlockSplitCode block_split_code_;\n  size_t block_ix_;\n  size_t block_len_;\n  size_t entropy_ix_;\n  uint8_t* depths_;\n  uint16_t* bits_;\n} BlockEncoder;\n\nstatic void InitBlockEncoder(BlockEncoder* self, size_t histogram_length,\n    size_t num_block_types, const uint8_t* block_types,\n    const uint32_t* block_lengths, const size_t num_blocks) {\n  self->histogram_length_ = histogram_length;\n  self->num_block_types_ = num_block_types;\n  self->block_types_ = block_types;\n  self->block_lengths_ = block_lengths;\n  self->num_blocks_ = num_blocks;\n  InitBlockTypeCodeCalculator(&self->block_split_code_.type_code_calculator);\n  self->block_ix_ = 0;\n  self->block_len_ = num_blocks == 0 ? 0 : block_lengths[0];\n  self->entropy_ix_ = 0;\n  self->depths_ = 0;\n  self->bits_ = 0;\n}\n\nstatic void CleanupBlockEncoder(MemoryManager* m, BlockEncoder* self) {\n  BROTLI_FREE(m, self->depths_);\n  BROTLI_FREE(m, self->bits_);\n}\n\n/* Creates entropy codes of block lengths and block types and stores them\n   to the bit stream. */\nstatic void BuildAndStoreBlockSwitchEntropyCodes(BlockEncoder* self,\n    HuffmanTree* tree, size_t* storage_ix, uint8_t* storage) {\n  BuildAndStoreBlockSplitCode(self->block_types_, self->block_lengths_,\n      self->num_blocks_, self->num_block_types_, tree, &self->block_split_code_,\n      storage_ix, storage);\n}\n\n/* Stores the next symbol with the entropy code of the current block type.\n   Updates the block type and block length at block boundaries. */\nstatic void StoreSymbol(BlockEncoder* self, size_t symbol, size_t* storage_ix,\n    uint8_t* storage) {\n  if (self->block_len_ == 0) {\n    size_t block_ix = ++self->block_ix_;\n    uint32_t block_len = self->block_lengths_[block_ix];\n    uint8_t block_type = self->block_types_[block_ix];\n    self->block_len_ = block_len;\n    self->entropy_ix_ = block_type * self->histogram_length_;\n    StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0,\n        storage_ix, storage);\n  }\n  --self->block_len_;\n  {\n    size_t ix = self->entropy_ix_ + symbol;\n    BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage);\n  }\n}\n\n/* Stores the next symbol with the entropy code of the current block type and\n   context value.\n   Updates the block type and block length at block boundaries. */\nstatic void StoreSymbolWithContext(BlockEncoder* self, size_t symbol,\n    size_t context, const uint32_t* context_map, size_t* storage_ix,\n    uint8_t* storage, const size_t context_bits) {\n  if (self->block_len_ == 0) {\n    size_t block_ix = ++self->block_ix_;\n    uint32_t block_len = self->block_lengths_[block_ix];\n    uint8_t block_type = self->block_types_[block_ix];\n    self->block_len_ = block_len;\n    self->entropy_ix_ = (size_t)block_type << context_bits;\n    StoreBlockSwitch(&self->block_split_code_, block_len, block_type, 0,\n        storage_ix, storage);\n  }\n  --self->block_len_;\n  {\n    size_t histo_ix = context_map[self->entropy_ix_ + context];\n    size_t ix = histo_ix * self->histogram_length_ + symbol;\n    BrotliWriteBits(self->depths_[ix], self->bits_[ix], storage_ix, storage);\n  }\n}\n\n#define FN(X) X ## Literal\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_encoder_inc.h\"\n#undef FN\n\n#define FN(X) X ## Command\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_encoder_inc.h\"\n#undef FN\n\n#define FN(X) X ## Distance\n/* NOLINTNEXTLINE(build/include) */\n#include \"block_encoder_inc.h\"\n#undef FN\n\nstatic void JumpToByteBoundary(size_t* storage_ix, uint8_t* storage) {\n  *storage_ix = (*storage_ix + 7u) & ~7u;\n  storage[*storage_ix >> 3] = 0;\n}\n\ntypedef struct StoreMetablockArena {\n  BlockEncoder literal_enc;\n  BlockEncoder command_enc;\n  BlockEncoder distance_enc;\n  EncodeContextMapArena context_map_arena;\n} StoreMetablockArena;\n\nvoid BrotliStoreMetaBlock(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,\n    const BrotliEncoderParams* params, ContextType literal_context_mode,\n    const Command* commands, size_t n_commands, const MetaBlockSplit* mb,\n    size_t* storage_ix, uint8_t* storage) {\n\n  size_t pos = start_pos;\n  size_t i;\n  uint32_t num_distance_symbols = params->dist.alphabet_size_max;\n  uint32_t num_effective_distance_symbols = params->dist.alphabet_size_limit;\n  HuffmanTree* tree;\n  ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);\n  StoreMetablockArena* arena = NULL;\n  BlockEncoder* literal_enc = NULL;\n  BlockEncoder* command_enc = NULL;\n  BlockEncoder* distance_enc = NULL;\n  const BrotliDistanceParams* dist = &params->dist;\n  BROTLI_DCHECK(\n      num_effective_distance_symbols <= BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS);\n\n  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);\n\n  tree = BROTLI_ALLOC(m, HuffmanTree, MAX_HUFFMAN_TREE_SIZE);\n  arena = BROTLI_ALLOC(m, StoreMetablockArena, 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tree) || BROTLI_IS_NULL(arena)) return;\n  literal_enc = &arena->literal_enc;\n  command_enc = &arena->command_enc;\n  distance_enc = &arena->distance_enc;\n  InitBlockEncoder(literal_enc, BROTLI_NUM_LITERAL_SYMBOLS,\n      mb->literal_split.num_types, mb->literal_split.types,\n      mb->literal_split.lengths, mb->literal_split.num_blocks);\n  InitBlockEncoder(command_enc, BROTLI_NUM_COMMAND_SYMBOLS,\n      mb->command_split.num_types, mb->command_split.types,\n      mb->command_split.lengths, mb->command_split.num_blocks);\n  InitBlockEncoder(distance_enc, num_effective_distance_symbols,\n      mb->distance_split.num_types, mb->distance_split.types,\n      mb->distance_split.lengths, mb->distance_split.num_blocks);\n\n  BuildAndStoreBlockSwitchEntropyCodes(literal_enc, tree, storage_ix, storage);\n  BuildAndStoreBlockSwitchEntropyCodes(command_enc, tree, storage_ix, storage);\n  BuildAndStoreBlockSwitchEntropyCodes(distance_enc, tree, storage_ix, storage);\n\n  BrotliWriteBits(2, dist->distance_postfix_bits, storage_ix, storage);\n  BrotliWriteBits(\n      4, dist->num_direct_distance_codes >> dist->distance_postfix_bits,\n      storage_ix, storage);\n  for (i = 0; i < mb->literal_split.num_types; ++i) {\n    BrotliWriteBits(2, literal_context_mode, storage_ix, storage);\n  }\n\n  if (mb->literal_context_map_size == 0) {\n    StoreTrivialContextMap(\n        &arena->context_map_arena, mb->literal_histograms_size,\n        BROTLI_LITERAL_CONTEXT_BITS, tree, storage_ix, storage);\n  } else {\n    EncodeContextMap(m, &arena->context_map_arena,\n        mb->literal_context_map, mb->literal_context_map_size,\n        mb->literal_histograms_size, tree, storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n\n  if (mb->distance_context_map_size == 0) {\n    StoreTrivialContextMap(\n        &arena->context_map_arena, mb->distance_histograms_size,\n        BROTLI_DISTANCE_CONTEXT_BITS, tree, storage_ix, storage);\n  } else {\n    EncodeContextMap(m, &arena->context_map_arena,\n        mb->distance_context_map, mb->distance_context_map_size,\n        mb->distance_histograms_size, tree, storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n\n  BuildAndStoreEntropyCodesLiteral(m, literal_enc, mb->literal_histograms,\n      mb->literal_histograms_size, BROTLI_NUM_LITERAL_SYMBOLS, tree,\n      storage_ix, storage);\n  if (BROTLI_IS_OOM(m)) return;\n  BuildAndStoreEntropyCodesCommand(m, command_enc, mb->command_histograms,\n      mb->command_histograms_size, BROTLI_NUM_COMMAND_SYMBOLS, tree,\n      storage_ix, storage);\n  if (BROTLI_IS_OOM(m)) return;\n  BuildAndStoreEntropyCodesDistance(m, distance_enc, mb->distance_histograms,\n      mb->distance_histograms_size, num_distance_symbols, tree,\n      storage_ix, storage);\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_FREE(m, tree);\n\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    size_t cmd_code = cmd.cmd_prefix_;\n    StoreSymbol(command_enc, cmd_code, storage_ix, storage);\n    StoreCommandExtra(&cmd, storage_ix, storage);\n    if (mb->literal_context_map_size == 0) {\n      size_t j;\n      for (j = cmd.insert_len_; j != 0; --j) {\n        StoreSymbol(literal_enc, input[pos & mask], storage_ix, storage);\n        ++pos;\n      }\n    } else {\n      size_t j;\n      for (j = cmd.insert_len_; j != 0; --j) {\n        size_t context =\n            BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);\n        uint8_t literal = input[pos & mask];\n        StoreSymbolWithContext(literal_enc, literal, context,\n            mb->literal_context_map, storage_ix, storage,\n            BROTLI_LITERAL_CONTEXT_BITS);\n        prev_byte2 = prev_byte;\n        prev_byte = literal;\n        ++pos;\n      }\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd)) {\n      prev_byte2 = input[(pos - 2) & mask];\n      prev_byte = input[(pos - 1) & mask];\n      if (cmd.cmd_prefix_ >= 128) {\n        size_t dist_code = cmd.dist_prefix_ & 0x3FF;\n        uint32_t distnumextra = cmd.dist_prefix_ >> 10;\n        uint64_t distextra = cmd.dist_extra_;\n        if (mb->distance_context_map_size == 0) {\n          StoreSymbol(distance_enc, dist_code, storage_ix, storage);\n        } else {\n          size_t context = CommandDistanceContext(&cmd);\n          StoreSymbolWithContext(distance_enc, dist_code, context,\n              mb->distance_context_map, storage_ix, storage,\n              BROTLI_DISTANCE_CONTEXT_BITS);\n        }\n        BrotliWriteBits(distnumextra, distextra, storage_ix, storage);\n      }\n    }\n  }\n  CleanupBlockEncoder(m, distance_enc);\n  CleanupBlockEncoder(m, command_enc);\n  CleanupBlockEncoder(m, literal_enc);\n  BROTLI_FREE(m, arena);\n  if (is_last) {\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\nstatic void BuildHistograms(const uint8_t* input,\n                            size_t start_pos,\n                            size_t mask,\n                            const Command* commands,\n                            size_t n_commands,\n                            HistogramLiteral* lit_histo,\n                            HistogramCommand* cmd_histo,\n                            HistogramDistance* dist_histo) {\n  size_t pos = start_pos;\n  size_t i;\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    size_t j;\n    HistogramAddCommand(cmd_histo, cmd.cmd_prefix_);\n    for (j = cmd.insert_len_; j != 0; --j) {\n      HistogramAddLiteral(lit_histo, input[pos & mask]);\n      ++pos;\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {\n      HistogramAddDistance(dist_histo, cmd.dist_prefix_ & 0x3FF);\n    }\n  }\n}\n\nstatic void StoreDataWithHuffmanCodes(const uint8_t* input,\n                                      size_t start_pos,\n                                      size_t mask,\n                                      const Command* commands,\n                                      size_t n_commands,\n                                      const uint8_t* lit_depth,\n                                      const uint16_t* lit_bits,\n                                      const uint8_t* cmd_depth,\n                                      const uint16_t* cmd_bits,\n                                      const uint8_t* dist_depth,\n                                      const uint16_t* dist_bits,\n                                      size_t* storage_ix,\n                                      uint8_t* storage) {\n  size_t pos = start_pos;\n  size_t i;\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    const size_t cmd_code = cmd.cmd_prefix_;\n    size_t j;\n    BrotliWriteBits(\n        cmd_depth[cmd_code], cmd_bits[cmd_code], storage_ix, storage);\n    StoreCommandExtra(&cmd, storage_ix, storage);\n    for (j = cmd.insert_len_; j != 0; --j) {\n      const uint8_t literal = input[pos & mask];\n      BrotliWriteBits(\n          lit_depth[literal], lit_bits[literal], storage_ix, storage);\n      ++pos;\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd) && cmd.cmd_prefix_ >= 128) {\n      const size_t dist_code = cmd.dist_prefix_ & 0x3FF;\n      const uint32_t distnumextra = cmd.dist_prefix_ >> 10;\n      const uint32_t distextra = cmd.dist_extra_;\n      BrotliWriteBits(dist_depth[dist_code], dist_bits[dist_code],\n                      storage_ix, storage);\n      BrotliWriteBits(distnumextra, distextra, storage_ix, storage);\n    }\n  }\n}\n\n/* TODO(eustas): pull alloc/dealloc to caller? */\ntypedef struct MetablockArena {\n  HistogramLiteral lit_histo;\n  HistogramCommand cmd_histo;\n  HistogramDistance dist_histo;\n  /* TODO(eustas): merge bits and depth? */\n  uint8_t lit_depth[BROTLI_NUM_LITERAL_SYMBOLS];\n  uint16_t lit_bits[BROTLI_NUM_LITERAL_SYMBOLS];\n  uint8_t cmd_depth[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint16_t cmd_bits[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint8_t dist_depth[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];\n  uint16_t dist_bits[MAX_SIMPLE_DISTANCE_ALPHABET_SIZE];\n  HuffmanTree tree[MAX_HUFFMAN_TREE_SIZE];\n} MetablockArena;\n\nvoid BrotliStoreMetaBlockTrivial(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage) {\n  MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);\n  uint32_t num_distance_symbols = params->dist.alphabet_size_max;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n\n  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);\n\n  HistogramClearLiteral(&arena->lit_histo);\n  HistogramClearCommand(&arena->cmd_histo);\n  HistogramClearDistance(&arena->dist_histo);\n\n  BuildHistograms(input, start_pos, mask, commands, n_commands,\n                  &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);\n\n  BrotliWriteBits(13, 0, storage_ix, storage);\n\n  BuildAndStoreHuffmanTree(arena->lit_histo.data_, BROTLI_NUM_LITERAL_SYMBOLS,\n                           BROTLI_NUM_LITERAL_SYMBOLS, arena->tree,\n                           arena->lit_depth, arena->lit_bits,\n                           storage_ix, storage);\n  BuildAndStoreHuffmanTree(arena->cmd_histo.data_, BROTLI_NUM_COMMAND_SYMBOLS,\n                           BROTLI_NUM_COMMAND_SYMBOLS, arena->tree,\n                           arena->cmd_depth, arena->cmd_bits,\n                           storage_ix, storage);\n  BuildAndStoreHuffmanTree(arena->dist_histo.data_,\n                           MAX_SIMPLE_DISTANCE_ALPHABET_SIZE,\n                           num_distance_symbols, arena->tree,\n                           arena->dist_depth, arena->dist_bits,\n                           storage_ix, storage);\n  StoreDataWithHuffmanCodes(input, start_pos, mask, commands,\n                            n_commands, arena->lit_depth, arena->lit_bits,\n                            arena->cmd_depth, arena->cmd_bits,\n                            arena->dist_depth, arena->dist_bits,\n                            storage_ix, storage);\n  BROTLI_FREE(m, arena);\n  if (is_last) {\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\nvoid BrotliStoreMetaBlockFast(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage) {\n  MetablockArena* arena = BROTLI_ALLOC(m, MetablockArena, 1);\n  uint32_t num_distance_symbols = params->dist.alphabet_size_max;\n  uint32_t distance_alphabet_bits =\n      Log2FloorNonZero(num_distance_symbols - 1) + 1;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n\n  StoreCompressedMetaBlockHeader(is_last, length, storage_ix, storage);\n\n  BrotliWriteBits(13, 0, storage_ix, storage);\n\n  if (n_commands <= 128) {\n    uint32_t histogram[BROTLI_NUM_LITERAL_SYMBOLS] = { 0 };\n    size_t pos = start_pos;\n    size_t num_literals = 0;\n    size_t i;\n    for (i = 0; i < n_commands; ++i) {\n      const Command cmd = commands[i];\n      size_t j;\n      for (j = cmd.insert_len_; j != 0; --j) {\n        ++histogram[input[pos & mask]];\n        ++pos;\n      }\n      num_literals += cmd.insert_len_;\n      pos += CommandCopyLen(&cmd);\n    }\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, histogram, num_literals,\n                                       /* max_bits = */ 8,\n                                       arena->lit_depth, arena->lit_bits,\n                                       storage_ix, storage);\n    StoreStaticCommandHuffmanTree(storage_ix, storage);\n    StoreStaticDistanceHuffmanTree(storage_ix, storage);\n    StoreDataWithHuffmanCodes(input, start_pos, mask, commands,\n                              n_commands, arena->lit_depth, arena->lit_bits,\n                              kStaticCommandCodeDepth,\n                              kStaticCommandCodeBits,\n                              kStaticDistanceCodeDepth,\n                              kStaticDistanceCodeBits,\n                              storage_ix, storage);\n  } else {\n    HistogramClearLiteral(&arena->lit_histo);\n    HistogramClearCommand(&arena->cmd_histo);\n    HistogramClearDistance(&arena->dist_histo);\n    BuildHistograms(input, start_pos, mask, commands, n_commands,\n                    &arena->lit_histo, &arena->cmd_histo, &arena->dist_histo);\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->lit_histo.data_,\n                                       arena->lit_histo.total_count_,\n                                       /* max_bits = */ 8,\n                                       arena->lit_depth, arena->lit_bits,\n                                       storage_ix, storage);\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->cmd_histo.data_,\n                                       arena->cmd_histo.total_count_,\n                                       /* max_bits = */ 10,\n                                       arena->cmd_depth, arena->cmd_bits,\n                                       storage_ix, storage);\n    BrotliBuildAndStoreHuffmanTreeFast(arena->tree, arena->dist_histo.data_,\n                                       arena->dist_histo.total_count_,\n                                       /* max_bits = */\n                                       distance_alphabet_bits,\n                                       arena->dist_depth, arena->dist_bits,\n                                       storage_ix, storage);\n    StoreDataWithHuffmanCodes(input, start_pos, mask, commands,\n                              n_commands, arena->lit_depth, arena->lit_bits,\n                              arena->cmd_depth, arena->cmd_bits,\n                              arena->dist_depth, arena->dist_bits,\n                              storage_ix, storage);\n  }\n\n  BROTLI_FREE(m, arena);\n\n  if (is_last) {\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\n/* This is for storing uncompressed blocks (simple raw storage of\n   bytes-as-bytes). */\nvoid BrotliStoreUncompressedMetaBlock(BROTLI_BOOL is_final_block,\n                                      const uint8_t* BROTLI_RESTRICT input,\n                                      size_t position, size_t mask,\n                                      size_t len,\n                                      size_t* BROTLI_RESTRICT storage_ix,\n                                      uint8_t* BROTLI_RESTRICT storage) {\n  size_t masked_pos = position & mask;\n  BrotliStoreUncompressedMetaBlockHeader(len, storage_ix, storage);\n  JumpToByteBoundary(storage_ix, storage);\n\n  if (masked_pos + len > mask + 1) {\n    size_t len1 = mask + 1 - masked_pos;\n    memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len1);\n    *storage_ix += len1 << 3;\n    len -= len1;\n    masked_pos = 0;\n  }\n  memcpy(&storage[*storage_ix >> 3], &input[masked_pos], len);\n  *storage_ix += len << 3;\n\n  /* We need to clear the next 4 bytes to continue to be\n     compatible with BrotliWriteBits. */\n  BrotliWriteBitsPrepareStorage(*storage_ix, storage);\n\n  /* Since the uncompressed block itself may not be the final block, add an\n     empty one after this. */\n  if (is_final_block) {\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    JumpToByteBoundary(storage_ix, storage);\n  }\n}\n\n#if defined(BROTLI_TEST)\nvoid GetBlockLengthPrefixCodeForTest(uint32_t len, size_t* code,\n                                     uint32_t* n_extra, uint32_t* extra) {\n  GetBlockLengthPrefixCode(len, code, n_extra, extra);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/brotli_bit_stream.h",
    "content": "/* Copyright 2014 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions to convert brotli-related data structures into the\n   brotli bit stream. The functions here operate under\n   assumption that there is enough space in the storage, i.e., there are\n   no out-of-range checks anywhere.\n\n   These functions do bit addressing into a byte array. The byte array\n   is called \"storage\" and the index to the bit is called storage_ix\n   in function arguments. */\n\n#ifndef BROTLI_ENC_BROTLI_BIT_STREAM_H_\n#define BROTLI_ENC_BROTLI_BIT_STREAM_H_\n\n#include <brotli/types.h>\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"command.h\"\n#include \"entropy_encode.h\"\n#include \"memory.h\"\n#include \"metablock.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* All Store functions here will use a storage_ix, which is always the bit\n   position for the current storage. */\n\nBROTLI_INTERNAL void BrotliStoreHuffmanTree(const uint8_t* depths, size_t num,\n    HuffmanTree* tree, size_t* storage_ix, uint8_t* storage);\n\nBROTLI_INTERNAL void BrotliBuildAndStoreHuffmanTreeFast(\n    HuffmanTree* tree, const uint32_t* histogram, const size_t histogram_total,\n    const size_t max_bits, uint8_t* depth, uint16_t* bits, size_t* storage_ix,\n    uint8_t* storage);\n\n/* REQUIRES: length > 0 */\n/* REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreMetaBlock(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    uint8_t prev_byte, uint8_t prev_byte2, BROTLI_BOOL is_last,\n    const BrotliEncoderParams* params, ContextType literal_context_mode,\n    const Command* commands, size_t n_commands, const MetaBlockSplit* mb,\n    size_t* storage_ix, uint8_t* storage);\n\n/* Stores the meta-block without doing any block splitting, just collects\n   one histogram per block category and uses that for entropy coding.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreMetaBlockTrivial(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage);\n\n/* Same as above, but uses static prefix codes for histograms with a only a few\n   symbols, and uses static code length prefix codes for all other histograms.\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreMetaBlockFast(MemoryManager* m,\n    const uint8_t* input, size_t start_pos, size_t length, size_t mask,\n    BROTLI_BOOL is_last, const BrotliEncoderParams* params,\n    const Command* commands, size_t n_commands,\n    size_t* storage_ix, uint8_t* storage);\n\n/* This is for storing uncompressed blocks (simple raw storage of\n   bytes-as-bytes).\n   REQUIRES: length > 0\n   REQUIRES: length <= (1 << 24) */\nBROTLI_INTERNAL void BrotliStoreUncompressedMetaBlock(\n    BROTLI_BOOL is_final_block, const uint8_t* BROTLI_RESTRICT input,\n    size_t position, size_t mask, size_t len,\n    size_t* BROTLI_RESTRICT storage_ix, uint8_t* BROTLI_RESTRICT storage);\n\n#if defined(BROTLI_TEST)\nvoid GetBlockLengthPrefixCodeForTest(uint32_t, size_t*, uint32_t*, uint32_t*);\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_BROTLI_BIT_STREAM_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/cluster.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions for clustering similar histograms together. */\n\n#include \"cluster.h\"\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"  /* BrotliPopulationCost */\n#include \"fast_log.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE BROTLI_BOOL HistogramPairIsLess(\n    const HistogramPair* p1, const HistogramPair* p2) {\n  if (p1->cost_diff != p2->cost_diff) {\n    return TO_BROTLI_BOOL(p1->cost_diff > p2->cost_diff);\n  }\n  return TO_BROTLI_BOOL((p1->idx2 - p1->idx1) > (p2->idx2 - p2->idx1));\n}\n\n/* Returns entropy reduction of the context map when we combine two clusters. */\nstatic BROTLI_INLINE double ClusterCostDiff(size_t size_a, size_t size_b) {\n  size_t size_c = size_a + size_b;\n  return (double)size_a * FastLog2(size_a) +\n    (double)size_b * FastLog2(size_b) -\n    (double)size_c * FastLog2(size_c);\n}\n\n#define CODE(X) X\n\n#define FN(X) X ## Literal\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#undef CODE\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/cluster.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions for clustering similar histograms together. */\n\n#ifndef BROTLI_ENC_CLUSTER_H_\n#define BROTLI_ENC_CLUSTER_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct HistogramPair {\n  uint32_t idx1;\n  uint32_t idx2;\n  double cost_combo;\n  double cost_diff;\n} HistogramPair;\n\n#define CODE(X) /* Declaration */;\n\n#define FN(X) X ## Literal\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"cluster_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#undef CODE\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_CLUSTER_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/cluster_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, CODE */\n\n#define HistogramType FN(Histogram)\n\n/* Computes the bit cost reduction by combining out[idx1] and out[idx2] and if\n   it is below a threshold, stores the pair (idx1, idx2) in the *pairs queue. */\nBROTLI_INTERNAL void FN(BrotliCompareAndPushToQueue)(\n    const HistogramType* out, HistogramType* tmp, const uint32_t* cluster_size,\n    uint32_t idx1, uint32_t idx2, size_t max_num_pairs, HistogramPair* pairs,\n    size_t* num_pairs) CODE({\n  BROTLI_BOOL is_good_pair = BROTLI_FALSE;\n  HistogramPair p;\n  p.idx1 = p.idx2 = 0;\n  p.cost_diff = p.cost_combo = 0;\n  if (idx1 == idx2) {\n    return;\n  }\n  if (idx2 < idx1) {\n    uint32_t t = idx2;\n    idx2 = idx1;\n    idx1 = t;\n  }\n  p.idx1 = idx1;\n  p.idx2 = idx2;\n  p.cost_diff = 0.5 * ClusterCostDiff(cluster_size[idx1], cluster_size[idx2]);\n  p.cost_diff -= out[idx1].bit_cost_;\n  p.cost_diff -= out[idx2].bit_cost_;\n\n  if (out[idx1].total_count_ == 0) {\n    p.cost_combo = out[idx2].bit_cost_;\n    is_good_pair = BROTLI_TRUE;\n  } else if (out[idx2].total_count_ == 0) {\n    p.cost_combo = out[idx1].bit_cost_;\n    is_good_pair = BROTLI_TRUE;\n  } else {\n    double threshold = *num_pairs == 0 ? 1e99 :\n        BROTLI_MAX(double, 0.0, pairs[0].cost_diff);\n    double cost_combo;\n    *tmp = out[idx1];\n    FN(HistogramAddHistogram)(tmp, &out[idx2]);\n    cost_combo = FN(BrotliPopulationCost)(tmp);\n    if (cost_combo < threshold - p.cost_diff) {\n      p.cost_combo = cost_combo;\n      is_good_pair = BROTLI_TRUE;\n    }\n  }\n  if (is_good_pair) {\n    p.cost_diff += p.cost_combo;\n    if (*num_pairs > 0 && HistogramPairIsLess(&pairs[0], &p)) {\n      /* Replace the top of the queue if needed. */\n      if (*num_pairs < max_num_pairs) {\n        pairs[*num_pairs] = pairs[0];\n        ++(*num_pairs);\n      }\n      pairs[0] = p;\n    } else if (*num_pairs < max_num_pairs) {\n      pairs[*num_pairs] = p;\n      ++(*num_pairs);\n    }\n  }\n})\n\nBROTLI_INTERNAL size_t FN(BrotliHistogramCombine)(HistogramType* out,\n                                                  HistogramType* tmp,\n                                                  uint32_t* cluster_size,\n                                                  uint32_t* symbols,\n                                                  uint32_t* clusters,\n                                                  HistogramPair* pairs,\n                                                  size_t num_clusters,\n                                                  size_t symbols_size,\n                                                  size_t max_clusters,\n                                                  size_t max_num_pairs) CODE({\n  double cost_diff_threshold = 0.0;\n  size_t min_cluster_size = 1;\n  size_t num_pairs = 0;\n\n  {\n    /* We maintain a vector of histogram pairs, with the property that the pair\n       with the maximum bit cost reduction is the first. */\n    size_t idx1;\n    for (idx1 = 0; idx1 < num_clusters; ++idx1) {\n      size_t idx2;\n      for (idx2 = idx1 + 1; idx2 < num_clusters; ++idx2) {\n        FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, clusters[idx1],\n            clusters[idx2], max_num_pairs, &pairs[0], &num_pairs);\n      }\n    }\n  }\n\n  while (num_clusters > min_cluster_size) {\n    uint32_t best_idx1;\n    uint32_t best_idx2;\n    size_t i;\n    if (pairs[0].cost_diff >= cost_diff_threshold) {\n      cost_diff_threshold = 1e99;\n      min_cluster_size = max_clusters;\n      continue;\n    }\n    /* Take the best pair from the top of heap. */\n    best_idx1 = pairs[0].idx1;\n    best_idx2 = pairs[0].idx2;\n    FN(HistogramAddHistogram)(&out[best_idx1], &out[best_idx2]);\n    out[best_idx1].bit_cost_ = pairs[0].cost_combo;\n    cluster_size[best_idx1] += cluster_size[best_idx2];\n    for (i = 0; i < symbols_size; ++i) {\n      if (symbols[i] == best_idx2) {\n        symbols[i] = best_idx1;\n      }\n    }\n    for (i = 0; i < num_clusters; ++i) {\n      if (clusters[i] == best_idx2) {\n        memmove(&clusters[i], &clusters[i + 1],\n                (num_clusters - i - 1) * sizeof(clusters[0]));\n        break;\n      }\n    }\n    --num_clusters;\n    {\n      /* Remove pairs intersecting the just combined best pair. */\n      size_t copy_to_idx = 0;\n      for (i = 0; i < num_pairs; ++i) {\n        HistogramPair* p = &pairs[i];\n        if (p->idx1 == best_idx1 || p->idx2 == best_idx1 ||\n            p->idx1 == best_idx2 || p->idx2 == best_idx2) {\n          /* Remove invalid pair from the queue. */\n          continue;\n        }\n        if (HistogramPairIsLess(&pairs[0], p)) {\n          /* Replace the top of the queue if needed. */\n          HistogramPair front = pairs[0];\n          pairs[0] = *p;\n          pairs[copy_to_idx] = front;\n        } else {\n          pairs[copy_to_idx] = *p;\n        }\n        ++copy_to_idx;\n      }\n      num_pairs = copy_to_idx;\n    }\n\n    /* Push new pairs formed with the combined histogram to the heap. */\n    for (i = 0; i < num_clusters; ++i) {\n      FN(BrotliCompareAndPushToQueue)(out, tmp, cluster_size, best_idx1,\n          clusters[i], max_num_pairs, &pairs[0], &num_pairs);\n    }\n  }\n  return num_clusters;\n})\n\n/* What is the bit cost of moving histogram from cur_symbol to candidate. */\nBROTLI_INTERNAL double FN(BrotliHistogramBitCostDistance)(\n    const HistogramType* histogram, const HistogramType* candidate,\n    HistogramType* tmp) CODE({\n  if (histogram->total_count_ == 0) {\n    return 0.0;\n  } else {\n    *tmp = *histogram;\n    FN(HistogramAddHistogram)(tmp, candidate);\n    return FN(BrotliPopulationCost)(tmp) - candidate->bit_cost_;\n  }\n})\n\n/* Find the best 'out' histogram for each of the 'in' histograms.\n   When called, clusters[0..num_clusters) contains the unique values from\n   symbols[0..in_size), but this property is not preserved in this function.\n   Note: we assume that out[]->bit_cost_ is already up-to-date. */\nBROTLI_INTERNAL void FN(BrotliHistogramRemap)(const HistogramType* in,\n    size_t in_size, const uint32_t* clusters, size_t num_clusters,\n    HistogramType* out, HistogramType* tmp, uint32_t* symbols) CODE({\n  size_t i;\n  for (i = 0; i < in_size; ++i) {\n    uint32_t best_out = i == 0 ? symbols[0] : symbols[i - 1];\n    double best_bits =\n        FN(BrotliHistogramBitCostDistance)(&in[i], &out[best_out], tmp);\n    size_t j;\n    for (j = 0; j < num_clusters; ++j) {\n      const double cur_bits =\n          FN(BrotliHistogramBitCostDistance)(&in[i], &out[clusters[j]], tmp);\n      if (cur_bits < best_bits) {\n        best_bits = cur_bits;\n        best_out = clusters[j];\n      }\n    }\n    symbols[i] = best_out;\n  }\n\n  /* Recompute each out based on raw and symbols. */\n  for (i = 0; i < num_clusters; ++i) {\n    FN(HistogramClear)(&out[clusters[i]]);\n  }\n  for (i = 0; i < in_size; ++i) {\n    FN(HistogramAddHistogram)(&out[symbols[i]], &in[i]);\n  }\n})\n\n/* Reorders elements of the out[0..length) array and changes values in\n   symbols[0..length) array in the following way:\n     * when called, symbols[] contains indexes into out[], and has N unique\n       values (possibly N < length)\n     * on return, symbols'[i] = f(symbols[i]) and\n                  out'[symbols'[i]] = out[symbols[i]], for each 0 <= i < length,\n       where f is a bijection between the range of symbols[] and [0..N), and\n       the first occurrences of values in symbols'[i] come in consecutive\n       increasing order.\n   Returns N, the number of unique values in symbols[]. */\nBROTLI_INTERNAL size_t FN(BrotliHistogramReindex)(MemoryManager* m,\n    HistogramType* out, uint32_t* symbols, size_t length) CODE({\n  static const uint32_t kInvalidIndex = BROTLI_UINT32_MAX;\n  uint32_t* new_index = BROTLI_ALLOC(m, uint32_t, length);\n  uint32_t next_index;\n  HistogramType* tmp;\n  size_t i;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_index)) return 0;\n  for (i = 0; i < length; ++i) {\n      new_index[i] = kInvalidIndex;\n  }\n  next_index = 0;\n  for (i = 0; i < length; ++i) {\n    if (new_index[symbols[i]] == kInvalidIndex) {\n      new_index[symbols[i]] = next_index;\n      ++next_index;\n    }\n  }\n  /* TODO(eustas): by using idea of \"cycle-sort\" we can avoid allocation of\n     tmp and reduce the number of copying by the factor of 2. */\n  tmp = BROTLI_ALLOC(m, HistogramType, next_index);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return 0;\n  next_index = 0;\n  for (i = 0; i < length; ++i) {\n    if (new_index[symbols[i]] == next_index) {\n      tmp[next_index] = out[symbols[i]];\n      ++next_index;\n    }\n    symbols[i] = new_index[symbols[i]];\n  }\n  BROTLI_FREE(m, new_index);\n  for (i = 0; i < next_index; ++i) {\n    out[i] = tmp[i];\n  }\n  BROTLI_FREE(m, tmp);\n  return next_index;\n})\n\nBROTLI_INTERNAL void FN(BrotliClusterHistograms)(\n    MemoryManager* m, const HistogramType* in, const size_t in_size,\n    size_t max_histograms, HistogramType* out, size_t* out_size,\n    uint32_t* histogram_symbols) CODE({\n  uint32_t* cluster_size = BROTLI_ALLOC(m, uint32_t, in_size);\n  uint32_t* clusters = BROTLI_ALLOC(m, uint32_t, in_size);\n  size_t num_clusters = 0;\n  const size_t max_input_histograms = 64;\n  size_t pairs_capacity = max_input_histograms * max_input_histograms / 2;\n  /* For the first pass of clustering, we allow all pairs. */\n  HistogramPair* pairs = BROTLI_ALLOC(m, HistogramPair, pairs_capacity + 1);\n  /* TODO(eustas): move to \"persistent\" arena? */\n  HistogramType* tmp = BROTLI_ALLOC(m, HistogramType, 1);\n  size_t i;\n\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(cluster_size) ||\n      BROTLI_IS_NULL(clusters) || BROTLI_IS_NULL(pairs)|| BROTLI_IS_NULL(tmp)) {\n    return;\n  }\n\n  for (i = 0; i < in_size; ++i) {\n    cluster_size[i] = 1;\n  }\n\n  for (i = 0; i < in_size; ++i) {\n    out[i] = in[i];\n    out[i].bit_cost_ = FN(BrotliPopulationCost)(&in[i]);\n    histogram_symbols[i] = (uint32_t)i;\n  }\n\n  for (i = 0; i < in_size; i += max_input_histograms) {\n    size_t num_to_combine =\n        BROTLI_MIN(size_t, in_size - i, max_input_histograms);\n    size_t num_new_clusters;\n    size_t j;\n    for (j = 0; j < num_to_combine; ++j) {\n      clusters[num_clusters + j] = (uint32_t)(i + j);\n    }\n    num_new_clusters =\n        FN(BrotliHistogramCombine)(out, tmp, cluster_size,\n                                   &histogram_symbols[i],\n                                   &clusters[num_clusters], pairs,\n                                   num_to_combine, num_to_combine,\n                                   max_histograms, pairs_capacity);\n    num_clusters += num_new_clusters;\n  }\n\n  {\n    /* For the second pass, we limit the total number of histogram pairs.\n       After this limit is reached, we only keep searching for the best pair. */\n    size_t max_num_pairs = BROTLI_MIN(size_t,\n        64 * num_clusters, (num_clusters / 2) * num_clusters);\n    BROTLI_ENSURE_CAPACITY(\n        m, HistogramPair, pairs, pairs_capacity, max_num_pairs + 1);\n    if (BROTLI_IS_OOM(m)) return;\n\n    /* Collapse similar histograms. */\n    num_clusters = FN(BrotliHistogramCombine)(out, tmp, cluster_size,\n                                              histogram_symbols, clusters,\n                                              pairs, num_clusters, in_size,\n                                              max_histograms, max_num_pairs);\n  }\n  BROTLI_FREE(m, pairs);\n  BROTLI_FREE(m, cluster_size);\n  /* Find the optimal map from original histograms to the final ones. */\n  FN(BrotliHistogramRemap)(in, in_size, clusters, num_clusters,\n                           out, tmp, histogram_symbols);\n  BROTLI_FREE(m, tmp);\n  BROTLI_FREE(m, clusters);\n  /* Convert the context map to a canonical form. */\n  *out_size = FN(BrotliHistogramReindex)(m, out, histogram_symbols, in_size);\n  if (BROTLI_IS_OOM(m)) return;\n})\n\n#undef HistogramType\n"
  },
  {
    "path": "third-party/brotli/enc/command.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"command.h\"\n\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nconst uint32_t kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES] = {\n    0,  1,  2,  3,  4,   5,   6,   8,   10,   14,   18,   26,\n    34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594};\nconst uint32_t kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES] = {\n    0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 12, 14, 24};\nconst uint32_t kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES] = {\n    2,  3,  4,  5,  6,  7,   8,   9,   10,  12,  14,   18,\n    22, 30, 38, 54, 70, 102, 134, 198, 326, 582, 1094, 2118};\nconst uint32_t kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES] = {\n    0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9, 10, 24};\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/command.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* This class models a sequence of literals and a backward reference copy. */\n\n#ifndef BROTLI_ENC_COMMAND_H_\n#define BROTLI_ENC_COMMAND_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n#include \"params.h\"\n#include \"prefix.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nBROTLI_INTERNAL extern const uint32_t\n    kBrotliInsBase[BROTLI_NUM_INS_COPY_CODES];\nBROTLI_INTERNAL extern const uint32_t\n    kBrotliInsExtra[BROTLI_NUM_INS_COPY_CODES];\nBROTLI_INTERNAL extern const uint32_t\n    kBrotliCopyBase[BROTLI_NUM_INS_COPY_CODES];\nBROTLI_INTERNAL extern const uint32_t\n    kBrotliCopyExtra[BROTLI_NUM_INS_COPY_CODES];\n\nstatic BROTLI_INLINE uint16_t GetInsertLengthCode(size_t insertlen) {\n  if (insertlen < 6) {\n    return (uint16_t)insertlen;\n  } else if (insertlen < 130) {\n    uint32_t nbits = Log2FloorNonZero(insertlen - 2) - 1u;\n    return (uint16_t)((nbits << 1) + ((insertlen - 2) >> nbits) + 2);\n  } else if (insertlen < 2114) {\n    return (uint16_t)(Log2FloorNonZero(insertlen - 66) + 10);\n  } else if (insertlen < 6210) {\n    return 21u;\n  } else if (insertlen < 22594) {\n    return 22u;\n  } else {\n    return 23u;\n  }\n}\n\nstatic BROTLI_INLINE uint16_t GetCopyLengthCode(size_t copylen) {\n  if (copylen < 10) {\n    return (uint16_t)(copylen - 2);\n  } else if (copylen < 134) {\n    uint32_t nbits = Log2FloorNonZero(copylen - 6) - 1u;\n    return (uint16_t)((nbits << 1) + ((copylen - 6) >> nbits) + 4);\n  } else if (copylen < 2118) {\n    return (uint16_t)(Log2FloorNonZero(copylen - 70) + 12);\n  } else {\n    return 23u;\n  }\n}\n\nstatic BROTLI_INLINE uint16_t CombineLengthCodes(\n    uint16_t inscode, uint16_t copycode, BROTLI_BOOL use_last_distance) {\n  uint16_t bits64 =\n      (uint16_t)((copycode & 0x7u) | ((inscode & 0x7u) << 3u));\n  if (use_last_distance && inscode < 8u && copycode < 16u) {\n    return (copycode < 8u) ? bits64 : (bits64 | 64u);\n  } else {\n    /* Specification: 5 Encoding of ... (last table) */\n    /* offset = 2 * index, where index is in range [0..8] */\n    uint32_t offset = 2u * ((copycode >> 3u) + 3u * (inscode >> 3u));\n    /* All values in specification are K * 64,\n       where   K = [2, 3, 6, 4, 5, 8, 7, 9, 10],\n           i + 1 = [1, 2, 3, 4, 5, 6, 7, 8,  9],\n       K - i - 1 = [1, 1, 3, 0, 0, 2, 0, 1,  2] = D.\n       All values in D require only 2 bits to encode.\n       Magic constant is shifted 6 bits left, to avoid final multiplication. */\n    offset = (offset << 5u) + 0x40u + ((0x520D40u >> offset) & 0xC0u);\n    return (uint16_t)(offset | bits64);\n  }\n}\n\nstatic BROTLI_INLINE void GetLengthCode(size_t insertlen, size_t copylen,\n                                        BROTLI_BOOL use_last_distance,\n                                        uint16_t* code) {\n  uint16_t inscode = GetInsertLengthCode(insertlen);\n  uint16_t copycode = GetCopyLengthCode(copylen);\n  *code = CombineLengthCodes(inscode, copycode, use_last_distance);\n}\n\nstatic BROTLI_INLINE uint32_t GetInsertBase(uint16_t inscode) {\n  return kBrotliInsBase[inscode];\n}\n\nstatic BROTLI_INLINE uint32_t GetInsertExtra(uint16_t inscode) {\n  return kBrotliInsExtra[inscode];\n}\n\nstatic BROTLI_INLINE uint32_t GetCopyBase(uint16_t copycode) {\n  return kBrotliCopyBase[copycode];\n}\n\nstatic BROTLI_INLINE uint32_t GetCopyExtra(uint16_t copycode) {\n  return kBrotliCopyExtra[copycode];\n}\n\ntypedef struct Command {\n  uint32_t insert_len_;\n  /* Stores copy_len in low 25 bits and copy_code - copy_len in high 7 bit. */\n  uint32_t copy_len_;\n  /* Stores distance extra bits. */\n  uint32_t dist_extra_;\n  uint16_t cmd_prefix_;\n  /* Stores distance code in low 10 bits\n     and number of extra bits in high 6 bits. */\n  uint16_t dist_prefix_;\n} Command;\n\n/* distance_code is e.g. 0 for same-as-last short code, or 16 for offset 1. */\nstatic BROTLI_INLINE void InitCommand(Command* self,\n    const BrotliDistanceParams* dist, size_t insertlen,\n    size_t copylen, int copylen_code_delta, size_t distance_code) {\n  /* Don't rely on signed int representation, use honest casts. */\n  uint32_t delta = (uint8_t)((int8_t)copylen_code_delta);\n  self->insert_len_ = (uint32_t)insertlen;\n  self->copy_len_ = (uint32_t)(copylen | (delta << 25));\n  /* The distance prefix and extra bits are stored in this Command as if\n     npostfix and ndirect were 0, they are only recomputed later after the\n     clustering if needed. */\n  PrefixEncodeCopyDistance(\n      distance_code, dist->num_direct_distance_codes,\n      dist->distance_postfix_bits, &self->dist_prefix_, &self->dist_extra_);\n  GetLengthCode(\n      insertlen, (size_t)((int)copylen + copylen_code_delta),\n      TO_BROTLI_BOOL((self->dist_prefix_ & 0x3FF) == 0), &self->cmd_prefix_);\n}\n\nstatic BROTLI_INLINE void InitInsertCommand(Command* self, size_t insertlen) {\n  self->insert_len_ = (uint32_t)insertlen;\n  self->copy_len_ = 4 << 25;\n  self->dist_extra_ = 0;\n  self->dist_prefix_ = BROTLI_NUM_DISTANCE_SHORT_CODES;\n  GetLengthCode(insertlen, 4, BROTLI_FALSE, &self->cmd_prefix_);\n}\n\nstatic BROTLI_INLINE uint32_t CommandRestoreDistanceCode(\n    const Command* self, const BrotliDistanceParams* dist) {\n  if ((self->dist_prefix_ & 0x3FFu) <\n      BROTLI_NUM_DISTANCE_SHORT_CODES + dist->num_direct_distance_codes) {\n    return self->dist_prefix_ & 0x3FFu;\n  } else {\n    uint32_t dcode = self->dist_prefix_ & 0x3FFu;\n    uint32_t nbits = self->dist_prefix_ >> 10;\n    uint32_t extra = self->dist_extra_;\n    uint32_t postfix_mask = (1U << dist->distance_postfix_bits) - 1U;\n    uint32_t hcode = (dcode - dist->num_direct_distance_codes -\n        BROTLI_NUM_DISTANCE_SHORT_CODES) >>\n        dist->distance_postfix_bits;\n    uint32_t lcode = (dcode - dist->num_direct_distance_codes -\n        BROTLI_NUM_DISTANCE_SHORT_CODES) & postfix_mask;\n    uint32_t offset = ((2U + (hcode & 1U)) << nbits) - 4U;\n    return ((offset + extra) << dist->distance_postfix_bits) + lcode +\n        dist->num_direct_distance_codes + BROTLI_NUM_DISTANCE_SHORT_CODES;\n  }\n}\n\nstatic BROTLI_INLINE uint32_t CommandDistanceContext(const Command* self) {\n  uint32_t r = self->cmd_prefix_ >> 6;\n  uint32_t c = self->cmd_prefix_ & 7;\n  if ((r == 0 || r == 2 || r == 4 || r == 7) && (c <= 2)) {\n    return c;\n  }\n  return 3;\n}\n\nstatic BROTLI_INLINE uint32_t CommandCopyLen(const Command* self) {\n  return self->copy_len_ & 0x1FFFFFF;\n}\n\nstatic BROTLI_INLINE uint32_t CommandCopyLenCode(const Command* self) {\n  uint32_t modifier = self->copy_len_ >> 25;\n  int32_t delta = (int8_t)((uint8_t)(modifier | ((modifier & 0x40) << 1)));\n  return (uint32_t)((int32_t)(self->copy_len_ & 0x1FFFFFF) + delta);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_COMMAND_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/compound_dictionary.c",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"compound_dictionary.h\"\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\nstatic PreparedDictionary* CreatePreparedDictionaryWithParams(MemoryManager* m,\n    const uint8_t* source, size_t source_size, uint32_t bucket_bits,\n    uint32_t slot_bits, uint32_t hash_bits, uint16_t bucket_limit) {\n  /* Step 1: create \"bloated\" hasher. */\n  uint32_t num_slots = 1u << slot_bits;\n  uint32_t num_buckets = 1u << bucket_bits;\n  uint32_t hash_shift = 64u - bucket_bits;\n  uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);\n  uint32_t slot_mask = num_slots - 1;\n  size_t alloc_size = (sizeof(uint32_t) << slot_bits) +\n      (sizeof(uint32_t) << slot_bits) +\n      (sizeof(uint16_t) << bucket_bits) +\n      (sizeof(uint32_t) << bucket_bits) +\n      (sizeof(uint32_t) * source_size);\n  uint8_t* flat = NULL;\n  PreparedDictionary* result = NULL;\n  uint16_t* num = NULL;\n  uint32_t* bucket_heads = NULL;\n  uint32_t* next_bucket = NULL;\n  uint32_t* slot_offsets = NULL;\n  uint16_t* heads = NULL;\n  uint32_t* items = NULL;\n  uint8_t** source_ref = NULL;\n  uint32_t i;\n  uint32_t* slot_size = NULL;\n  uint32_t* slot_limit = NULL;\n  uint32_t total_items = 0;\n  if (slot_bits > 16) return NULL;\n  if (slot_bits > bucket_bits) return NULL;\n  if (bucket_bits - slot_bits >= 16) return NULL;\n\n  flat = BROTLI_ALLOC(m, uint8_t, alloc_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(flat)) return NULL;\n\n  slot_size = (uint32_t*)flat;\n  slot_limit = (uint32_t*)(&slot_size[num_slots]);\n  num = (uint16_t*)(&slot_limit[num_slots]);\n  bucket_heads = (uint32_t*)(&num[num_buckets]);\n  next_bucket = (uint32_t*)(&bucket_heads[num_buckets]);\n  memset(num, 0, num_buckets * sizeof(num[0]));\n\n  /* TODO(eustas): apply custom \"store\" order. */\n  for (i = 0; i + 7 < source_size; ++i) {\n    const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(&source[i]) & hash_mask) *\n        kPreparedDictionaryHashMul64Long;\n    const uint32_t key = (uint32_t)(h >> hash_shift);\n    uint16_t count = num[key];\n    next_bucket[i] = (count == 0) ? ((uint32_t)(-1)) : bucket_heads[key];\n    bucket_heads[key] = i;\n    count++;\n    if (count > bucket_limit) count = bucket_limit;\n    num[key] = count;\n  }\n\n  /* Step 2: find slot limits. */\n  for (i = 0; i < num_slots; ++i) {\n    BROTLI_BOOL overflow = BROTLI_FALSE;\n    slot_limit[i] = bucket_limit;\n    while (BROTLI_TRUE) {\n      uint32_t limit = slot_limit[i];\n      size_t j;\n      uint32_t count = 0;\n      overflow = BROTLI_FALSE;\n      for (j = i; j < num_buckets; j += num_slots) {\n        uint32_t size = num[j];\n        /* Last chain may span behind 64K limit; overflow happens only if\n           we are about to use 0xFFFF+ as item offset. */\n        if (count >= 0xFFFF) {\n          overflow = BROTLI_TRUE;\n          break;\n        }\n        if (size > limit) size = limit;\n        count += size;\n      }\n      if (!overflow) {\n        slot_size[i] = count;\n        total_items += count;\n        break;\n      }\n      slot_limit[i]--;\n    }\n  }\n\n  /* Step 3: transfer data to \"slim\" hasher. */\n  alloc_size = sizeof(PreparedDictionary) + (sizeof(uint32_t) << slot_bits) +\n      (sizeof(uint16_t) << bucket_bits) + (sizeof(uint32_t) * total_items) +\n      sizeof(uint8_t*);\n\n  result = (PreparedDictionary*)BROTLI_ALLOC(m, uint8_t, alloc_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(result)) {\n    BROTLI_FREE(m, flat);\n    return NULL;\n  }\n  slot_offsets = (uint32_t*)(&result[1]);\n  heads = (uint16_t*)(&slot_offsets[num_slots]);\n  items = (uint32_t*)(&heads[num_buckets]);\n  source_ref = (uint8_t**)(&items[total_items]);\n\n  result->magic = kLeanPreparedDictionaryMagic;\n  result->num_items = total_items;\n  result->source_size = (uint32_t)source_size;\n  result->hash_bits = hash_bits;\n  result->bucket_bits = bucket_bits;\n  result->slot_bits = slot_bits;\n  BROTLI_UNALIGNED_STORE_PTR(source_ref, source);\n\n  total_items = 0;\n  for (i = 0; i < num_slots; ++i) {\n    slot_offsets[i] = total_items;\n    total_items += slot_size[i];\n    slot_size[i] = 0;\n  }\n  for (i = 0; i < num_buckets; ++i) {\n    uint32_t slot = i & slot_mask;\n    uint32_t count = num[i];\n    uint32_t pos;\n    size_t j;\n    size_t cursor = slot_size[slot];\n    if (count > slot_limit[slot]) count = slot_limit[slot];\n    if (count == 0) {\n      heads[i] = 0xFFFF;\n      continue;\n    }\n    heads[i] = (uint16_t)cursor;\n    cursor += slot_offsets[slot];\n    slot_size[slot] += count;\n    pos = bucket_heads[i];\n    for (j = 0; j < count; j++) {\n      items[cursor++] = pos;\n      pos = next_bucket[pos];\n    }\n    items[cursor - 1] |= 0x80000000;\n  }\n\n  BROTLI_FREE(m, flat);\n  return result;\n}\n\nPreparedDictionary* CreatePreparedDictionary(MemoryManager* m,\n    const uint8_t* source, size_t source_size) {\n  uint32_t bucket_bits = 17;\n  uint32_t slot_bits = 7;\n  uint32_t hash_bits = 40;\n  uint16_t bucket_limit = 32;\n  size_t volume = 16u << bucket_bits;\n  /* Tune parameters to fit dictionary size. */\n  while (volume < source_size && bucket_bits < 22) {\n    bucket_bits++;\n    slot_bits++;\n    volume <<= 1;\n  }\n  return CreatePreparedDictionaryWithParams(m,\n      source, source_size, bucket_bits, slot_bits, hash_bits, bucket_limit);\n}\n\nvoid DestroyPreparedDictionary(MemoryManager* m,\n    PreparedDictionary* dictionary) {\n  if (!dictionary) return;\n  BROTLI_FREE(m, dictionary);\n}\n\nBROTLI_BOOL AttachPreparedDictionary(\n    CompoundDictionary* compound, const PreparedDictionary* dictionary) {\n  size_t length = 0;\n  size_t index = 0;\n\n  if (compound->num_chunks == SHARED_BROTLI_MAX_COMPOUND_DICTS) {\n    return BROTLI_FALSE;\n  }\n\n  if (!dictionary) return BROTLI_FALSE;\n\n  length = dictionary->source_size;\n  index = compound->num_chunks;\n  compound->total_size += length;\n  compound->chunks[index] = dictionary;\n  compound->chunk_offsets[index + 1] = compound->total_size;\n  {\n    uint32_t* slot_offsets = (uint32_t*)(&dictionary[1]);\n    uint16_t* heads = (uint16_t*)(&slot_offsets[1u << dictionary->slot_bits]);\n    uint32_t* items = (uint32_t*)(&heads[1u << dictionary->bucket_bits]);\n    const void* tail = (void*)&items[dictionary->num_items];\n    if (dictionary->magic == kPreparedDictionaryMagic) {\n      compound->chunk_source[index] = (const uint8_t*)tail;\n    } else {\n      /* dictionary->magic == kLeanPreparedDictionaryMagic */\n      compound->chunk_source[index] =\n          (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);\n    }\n  }\n  compound->num_chunks++;\n  return BROTLI_TRUE;\n}\n"
  },
  {
    "path": "third-party/brotli/enc/compound_dictionary.h",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#ifndef BROTLI_ENC_PREPARED_DICTIONARY_H_\n#define BROTLI_ENC_PREPARED_DICTIONARY_H_\n\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"../common/constants.h\"\n#include \"memory.h\"\n\n/* \"Fat\" prepared dictionary, could be cooked outside of C implementation,\n * e.g. on Java side. LZ77 data is copied inside PreparedDictionary struct. */\nstatic const uint32_t kPreparedDictionaryMagic = 0xDEBCEDE0;\n\nstatic const uint32_t kSharedDictionaryMagic = 0xDEBCEDE1;\n\nstatic const uint32_t kManagedDictionaryMagic = 0xDEBCEDE2;\n\n/* \"Lean\" prepared dictionary. LZ77 data is referenced. It is the responsibility\n * of caller of \"prepare dictionary\" to keep the LZ77 data while prepared\n * dictionary is in use. */\nstatic const uint32_t kLeanPreparedDictionaryMagic = 0xDEBCEDE3;\n\nstatic const uint64_t kPreparedDictionaryHashMul64Long =\n    BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);\n\ntypedef struct PreparedDictionary {\n  uint32_t magic;\n  uint32_t num_items;\n  uint32_t source_size;\n  uint32_t hash_bits;\n  uint32_t bucket_bits;\n  uint32_t slot_bits;\n\n  /* --- Dynamic size members --- */\n\n  /* uint32_t slot_offsets[1 << slot_bits]; */\n  /* uint16_t heads[1 << bucket_bits]; */\n  /* uint32_t items[variable]; */\n\n  /* [maybe] uint8_t* source_ref, depending on magic. */\n  /* [maybe] uint8_t source[source_size], depending on magic. */\n} PreparedDictionary;\n\nBROTLI_INTERNAL PreparedDictionary* CreatePreparedDictionary(MemoryManager* m,\n    const uint8_t* source, size_t source_size);\n\nBROTLI_INTERNAL void DestroyPreparedDictionary(MemoryManager* m,\n    PreparedDictionary* dictionary);\n\ntypedef struct CompoundDictionary {\n  /* LZ77 prefix, compound dictionary */\n  size_t num_chunks;\n  size_t total_size;\n  /* Client instances. */\n  const PreparedDictionary* chunks[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n  const uint8_t* chunk_source[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n  size_t chunk_offsets[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n\n  size_t num_prepared_instances_;\n  /* Owned instances. */\n  PreparedDictionary* prepared_instances_[SHARED_BROTLI_MAX_COMPOUND_DICTS + 1];\n} CompoundDictionary;\n\nBROTLI_INTERNAL BROTLI_BOOL AttachPreparedDictionary(\n    CompoundDictionary* compound, const PreparedDictionary* dictionary);\n\n#endif /* BROTLI_ENC_PREPARED_DICTIONARY */\n"
  },
  {
    "path": "third-party/brotli/enc/compress_fragment.c",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses one-pass processing: when we find a backward\n   match, we immediately emit the corresponding command and literal codes to\n   the bit stream.\n\n   Adapted from the CompressFragment() function in\n   https://github.com/google/snappy/blob/master/snappy.cc */\n\n#include \"compress_fragment.h\"\n\n#include <string.h>  /* memcmp, memcpy, memset */\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"brotli_bit_stream.h\"\n#include \"entropy_encode.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)\n\n/* kHashMul32 multiplier has these properties:\n   * The multiplier must be odd. Otherwise we may lose the highest bit.\n   * No long streaks of ones or zeros.\n   * There is no effort to ensure that it is a prime, the oddity is enough\n     for this use.\n   * The number has been tuned heuristically against compression benchmarks. */\nstatic const uint32_t kHashMul32 = 0x1E35A7BD;\n\nstatic BROTLI_INLINE uint32_t Hash(const uint8_t* p, size_t shift) {\n  const uint64_t h = (BROTLI_UNALIGNED_LOAD64LE(p) << 24) * kHashMul32;\n  return (uint32_t)(h >> shift);\n}\n\nstatic BROTLI_INLINE uint32_t HashBytesAtOffset(\n    uint64_t v, int offset, size_t shift) {\n  BROTLI_DCHECK(offset >= 0);\n  BROTLI_DCHECK(offset <= 3);\n  {\n    const uint64_t h = ((v >> (8 * offset)) << 24) * kHashMul32;\n    return (uint32_t)(h >> shift);\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2) {\n  return TO_BROTLI_BOOL(\n      BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2) &&\n      p1[4] == p2[4]);\n}\n\n/* Builds a literal prefix code into \"depths\" and \"bits\" based on the statistics\n   of the \"input\" string and stores it into the bit stream.\n   Note that the prefix code here is built from the pre-LZ77 input, therefore\n   we can only approximate the statistics of the actual literal stream.\n   Moreover, for long inputs we build a histogram from a sample of the input\n   and thus have to assign a non-zero depth for each literal.\n   Returns estimated compression ratio millibytes/char for encoding given input\n   with generated code. */\nstatic size_t BuildAndStoreLiteralPrefixCode(BrotliOnePassArena* s,\n                                             const uint8_t* input,\n                                             const size_t input_size,\n                                             uint8_t depths[256],\n                                             uint16_t bits[256],\n                                             size_t* storage_ix,\n                                             uint8_t* storage) {\n  uint32_t* BROTLI_RESTRICT const histogram = s->histogram;\n  size_t histogram_total;\n  size_t i;\n  memset(histogram, 0, sizeof(s->histogram));\n\n  if (input_size < (1 << 15)) {\n    for (i = 0; i < input_size; ++i) {\n      ++histogram[input[i]];\n    }\n    histogram_total = input_size;\n    for (i = 0; i < 256; ++i) {\n      /* We weigh the first 11 samples with weight 3 to account for the\n         balancing effect of the LZ77 phase on the histogram. */\n      const uint32_t adjust = 2 * BROTLI_MIN(uint32_t, histogram[i], 11u);\n      histogram[i] += adjust;\n      histogram_total += adjust;\n    }\n  } else {\n    static const size_t kSampleRate = 29;\n    for (i = 0; i < input_size; i += kSampleRate) {\n      ++histogram[input[i]];\n    }\n    histogram_total = (input_size + kSampleRate - 1) / kSampleRate;\n    for (i = 0; i < 256; ++i) {\n      /* We add 1 to each population count to avoid 0 bit depths (since this is\n         only a sample and we don't know if the symbol appears or not), and we\n         weigh the first 11 samples with weight 3 to account for the balancing\n         effect of the LZ77 phase on the histogram (more frequent symbols are\n         more likely to be in backward references instead as literals). */\n      const uint32_t adjust = 1 + 2 * BROTLI_MIN(uint32_t, histogram[i], 11u);\n      histogram[i] += adjust;\n      histogram_total += adjust;\n    }\n  }\n  BrotliBuildAndStoreHuffmanTreeFast(s->tree, histogram, histogram_total,\n                                     /* max_bits = */ 8,\n                                     depths, bits, storage_ix, storage);\n  {\n    size_t literal_ratio = 0;\n    for (i = 0; i < 256; ++i) {\n      if (histogram[i]) literal_ratio += histogram[i] * depths[i];\n    }\n    /* Estimated encoding ratio, millibytes per symbol. */\n    return (literal_ratio * 125) / histogram_total;\n  }\n}\n\n/* Builds a command and distance prefix code (each 64 symbols) into \"depth\" and\n   \"bits\" based on \"histogram\" and stores it into the bit stream. */\nstatic void BuildAndStoreCommandPrefixCode(BrotliOnePassArena* s,\n    size_t* storage_ix, uint8_t* storage) {\n  const uint32_t* const histogram = s->cmd_histo;\n  uint8_t* const depth = s->cmd_depth;\n  uint16_t* const bits = s->cmd_bits;\n  uint8_t* BROTLI_RESTRICT const tmp_depth = s->tmp_depth;\n  uint16_t* BROTLI_RESTRICT const tmp_bits = s->tmp_bits;\n  /* TODO(eustas): do only once on initialization. */\n  memset(tmp_depth, 0, BROTLI_NUM_COMMAND_SYMBOLS);\n\n  BrotliCreateHuffmanTree(histogram, 64, 15, s->tree, depth);\n  BrotliCreateHuffmanTree(&histogram[64], 64, 14, s->tree, &depth[64]);\n  /* We have to jump through a few hoops here in order to compute\n     the command bits because the symbols are in a different order than in\n     the full alphabet. This looks complicated, but having the symbols\n     in this order in the command bits saves a few branches in the Emit*\n     functions. */\n  memcpy(tmp_depth, depth, 24);\n  memcpy(tmp_depth + 24, depth + 40, 8);\n  memcpy(tmp_depth + 32, depth + 24, 8);\n  memcpy(tmp_depth + 40, depth + 48, 8);\n  memcpy(tmp_depth + 48, depth + 32, 8);\n  memcpy(tmp_depth + 56, depth + 56, 8);\n  BrotliConvertBitDepthsToSymbols(tmp_depth, 64, tmp_bits);\n  memcpy(bits, tmp_bits, 48);\n  memcpy(bits + 24, tmp_bits + 32, 16);\n  memcpy(bits + 32, tmp_bits + 48, 16);\n  memcpy(bits + 40, tmp_bits + 24, 16);\n  memcpy(bits + 48, tmp_bits + 40, 16);\n  memcpy(bits + 56, tmp_bits + 56, 16);\n  BrotliConvertBitDepthsToSymbols(&depth[64], 64, &bits[64]);\n  {\n    /* Create the bit length array for the full command alphabet. */\n    size_t i;\n    memset(tmp_depth, 0, 64);  /* only 64 first values were used */\n    memcpy(tmp_depth, depth, 8);\n    memcpy(tmp_depth + 64, depth + 8, 8);\n    memcpy(tmp_depth + 128, depth + 16, 8);\n    memcpy(tmp_depth + 192, depth + 24, 8);\n    memcpy(tmp_depth + 384, depth + 32, 8);\n    for (i = 0; i < 8; ++i) {\n      tmp_depth[128 + 8 * i] = depth[40 + i];\n      tmp_depth[256 + 8 * i] = depth[48 + i];\n      tmp_depth[448 + 8 * i] = depth[56 + i];\n    }\n    /* TODO(eustas): could/should full-length machinery be avoided? */\n    BrotliStoreHuffmanTree(\n        tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS, s->tree, storage_ix, storage);\n  }\n  BrotliStoreHuffmanTree(&depth[64], 64, s->tree, storage_ix, storage);\n}\n\n/* REQUIRES: insertlen < 6210 */\nstatic BROTLI_INLINE void EmitInsertLen(size_t insertlen,\n                                        const uint8_t depth[128],\n                                        const uint16_t bits[128],\n                                        uint32_t histo[128],\n                                        size_t* storage_ix,\n                                        uint8_t* storage) {\n  if (insertlen < 6) {\n    const size_t code = insertlen + 40;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    ++histo[code];\n  } else if (insertlen < 130) {\n    const size_t tail = insertlen - 2;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1u;\n    const size_t prefix = tail >> nbits;\n    const size_t inscode = (nbits << 1) + prefix + 42;\n    BrotliWriteBits(depth[inscode], bits[inscode], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage);\n    ++histo[inscode];\n  } else if (insertlen < 2114) {\n    const size_t tail = insertlen - 66;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 50;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage);\n    ++histo[code];\n  } else {\n    BrotliWriteBits(depth[61], bits[61], storage_ix, storage);\n    BrotliWriteBits(12, insertlen - 2114, storage_ix, storage);\n    ++histo[61];\n  }\n}\n\nstatic BROTLI_INLINE void EmitLongInsertLen(size_t insertlen,\n                                            const uint8_t depth[128],\n                                            const uint16_t bits[128],\n                                            uint32_t histo[128],\n                                            size_t* storage_ix,\n                                            uint8_t* storage) {\n  if (insertlen < 22594) {\n    BrotliWriteBits(depth[62], bits[62], storage_ix, storage);\n    BrotliWriteBits(14, insertlen - 6210, storage_ix, storage);\n    ++histo[62];\n  } else {\n    BrotliWriteBits(depth[63], bits[63], storage_ix, storage);\n    BrotliWriteBits(24, insertlen - 22594, storage_ix, storage);\n    ++histo[63];\n  }\n}\n\nstatic BROTLI_INLINE void EmitCopyLen(size_t copylen,\n                                      const uint8_t depth[128],\n                                      const uint16_t bits[128],\n                                      uint32_t histo[128],\n                                      size_t* storage_ix,\n                                      uint8_t* storage) {\n  if (copylen < 10) {\n    BrotliWriteBits(\n        depth[copylen + 14], bits[copylen + 14], storage_ix, storage);\n    ++histo[copylen + 14];\n  } else if (copylen < 134) {\n    const size_t tail = copylen - 6;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1u;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 20;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage);\n    ++histo[code];\n  } else if (copylen < 2118) {\n    const size_t tail = copylen - 70;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 28;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage);\n    ++histo[code];\n  } else {\n    BrotliWriteBits(depth[39], bits[39], storage_ix, storage);\n    BrotliWriteBits(24, copylen - 2118, storage_ix, storage);\n    ++histo[39];\n  }\n}\n\nstatic BROTLI_INLINE void EmitCopyLenLastDistance(size_t copylen,\n                                                  const uint8_t depth[128],\n                                                  const uint16_t bits[128],\n                                                  uint32_t histo[128],\n                                                  size_t* storage_ix,\n                                                  uint8_t* storage) {\n  if (copylen < 12) {\n    BrotliWriteBits(depth[copylen - 4], bits[copylen - 4], storage_ix, storage);\n    ++histo[copylen - 4];\n  } else if (copylen < 72) {\n    const size_t tail = copylen - 8;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 4;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - (prefix << nbits), storage_ix, storage);\n    ++histo[code];\n  } else if (copylen < 136) {\n    const size_t tail = copylen - 8;\n    const size_t code = (tail >> 5) + 30;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(5, tail & 31, storage_ix, storage);\n    BrotliWriteBits(depth[64], bits[64], storage_ix, storage);\n    ++histo[code];\n    ++histo[64];\n  } else if (copylen < 2120) {\n    const size_t tail = copylen - 72;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 28;\n    BrotliWriteBits(depth[code], bits[code], storage_ix, storage);\n    BrotliWriteBits(nbits, tail - ((size_t)1 << nbits), storage_ix, storage);\n    BrotliWriteBits(depth[64], bits[64], storage_ix, storage);\n    ++histo[code];\n    ++histo[64];\n  } else {\n    BrotliWriteBits(depth[39], bits[39], storage_ix, storage);\n    BrotliWriteBits(24, copylen - 2120, storage_ix, storage);\n    BrotliWriteBits(depth[64], bits[64], storage_ix, storage);\n    ++histo[39];\n    ++histo[64];\n  }\n}\n\nstatic BROTLI_INLINE void EmitDistance(size_t distance,\n                                       const uint8_t depth[128],\n                                       const uint16_t bits[128],\n                                       uint32_t histo[128],\n                                       size_t* storage_ix, uint8_t* storage) {\n  const size_t d = distance + 3;\n  const uint32_t nbits = Log2FloorNonZero(d) - 1u;\n  const size_t prefix = (d >> nbits) & 1;\n  const size_t offset = (2 + prefix) << nbits;\n  const size_t distcode = 2 * (nbits - 1) + prefix + 80;\n  BrotliWriteBits(depth[distcode], bits[distcode], storage_ix, storage);\n  BrotliWriteBits(nbits, d - offset, storage_ix, storage);\n  ++histo[distcode];\n}\n\nstatic BROTLI_INLINE void EmitLiterals(const uint8_t* input, const size_t len,\n                                       const uint8_t depth[256],\n                                       const uint16_t bits[256],\n                                       size_t* storage_ix, uint8_t* storage) {\n  size_t j;\n  for (j = 0; j < len; j++) {\n    const uint8_t lit = input[j];\n    BrotliWriteBits(depth[lit], bits[lit], storage_ix, storage);\n  }\n}\n\n/* REQUIRES: len <= 1 << 24. */\nstatic void BrotliStoreMetaBlockHeader(\n    size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix,\n    uint8_t* storage) {\n  size_t nibbles = 6;\n  /* ISLAST */\n  BrotliWriteBits(1, 0, storage_ix, storage);\n  if (len <= (1U << 16)) {\n    nibbles = 4;\n  } else if (len <= (1U << 20)) {\n    nibbles = 5;\n  }\n  BrotliWriteBits(2, nibbles - 4, storage_ix, storage);\n  BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage);\n  /* ISUNCOMPRESSED */\n  BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage);\n}\n\nstatic void UpdateBits(size_t n_bits, uint32_t bits, size_t pos,\n    uint8_t* array) {\n  while (n_bits > 0) {\n    size_t byte_pos = pos >> 3;\n    size_t n_unchanged_bits = pos & 7;\n    size_t n_changed_bits = BROTLI_MIN(size_t, n_bits, 8 - n_unchanged_bits);\n    size_t total_bits = n_unchanged_bits + n_changed_bits;\n    uint32_t mask =\n        (~((1u << total_bits) - 1u)) | ((1u << n_unchanged_bits) - 1u);\n    uint32_t unchanged_bits = array[byte_pos] & mask;\n    uint32_t changed_bits = bits & ((1u << n_changed_bits) - 1u);\n    array[byte_pos] =\n        (uint8_t)((changed_bits << n_unchanged_bits) | unchanged_bits);\n    n_bits -= n_changed_bits;\n    bits >>= n_changed_bits;\n    pos += n_changed_bits;\n  }\n}\n\nstatic void RewindBitPosition(const size_t new_storage_ix,\n                              size_t* storage_ix, uint8_t* storage) {\n  const size_t bitpos = new_storage_ix & 7;\n  const size_t mask = (1u << bitpos) - 1;\n  storage[new_storage_ix >> 3] &= (uint8_t)mask;\n  *storage_ix = new_storage_ix;\n}\n\nstatic BROTLI_BOOL ShouldMergeBlock(BrotliOnePassArena* s,\n    const uint8_t* data, size_t len, const uint8_t* depths) {\n  uint32_t* BROTLI_RESTRICT const histo = s->histogram;\n  static const size_t kSampleRate = 43;\n  size_t i;\n  memset(histo, 0, sizeof(s->histogram));\n  for (i = 0; i < len; i += kSampleRate) {\n    ++histo[data[i]];\n  }\n  {\n    const size_t total = (len + kSampleRate - 1) / kSampleRate;\n    double r = (FastLog2(total) + 0.5) * (double)total + 200;\n    for (i = 0; i < 256; ++i) {\n      r -= (double)histo[i] * (depths[i] + FastLog2(histo[i]));\n    }\n    return TO_BROTLI_BOOL(r >= 0.0);\n  }\n}\n\n/* Acceptable loss for uncompressible speedup is 2% */\n#define MIN_RATIO 980\n\nstatic BROTLI_INLINE BROTLI_BOOL ShouldUseUncompressedMode(\n    const uint8_t* metablock_start, const uint8_t* next_emit,\n    const size_t insertlen, const size_t literal_ratio) {\n  const size_t compressed = (size_t)(next_emit - metablock_start);\n  if (compressed * 50 > insertlen) {\n    return BROTLI_FALSE;\n  } else {\n    return TO_BROTLI_BOOL(literal_ratio > MIN_RATIO);\n  }\n}\n\nstatic void EmitUncompressedMetaBlock(const uint8_t* begin, const uint8_t* end,\n                                      const size_t storage_ix_start,\n                                      size_t* storage_ix, uint8_t* storage) {\n  const size_t len = (size_t)(end - begin);\n  RewindBitPosition(storage_ix_start, storage_ix, storage);\n  BrotliStoreMetaBlockHeader(len, 1, storage_ix, storage);\n  *storage_ix = (*storage_ix + 7u) & ~7u;\n  memcpy(&storage[*storage_ix >> 3], begin, len);\n  *storage_ix += len << 3;\n  storage[*storage_ix >> 3] = 0;\n}\n\nstatic uint32_t kCmdHistoSeed[128] = {\n  0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0,\n  0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,\n  1, 1, 1, 1, 0, 0, 0, 0,\n};\n\nstatic BROTLI_INLINE void BrotliCompressFragmentFastImpl(\n    BrotliOnePassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, int* table, size_t table_bits,\n    size_t* storage_ix, uint8_t* storage) {\n  uint8_t* BROTLI_RESTRICT const cmd_depth = s->cmd_depth;\n  uint16_t* BROTLI_RESTRICT const cmd_bits = s->cmd_bits;\n  uint32_t* BROTLI_RESTRICT const cmd_histo = s->cmd_histo;\n  uint8_t* BROTLI_RESTRICT const lit_depth = s->lit_depth;\n  uint16_t* BROTLI_RESTRICT const lit_bits = s->lit_bits;\n  const uint8_t* ip_end;\n\n  /* \"next_emit\" is a pointer to the first byte that is not covered by a\n     previous copy. Bytes between \"next_emit\" and the start of the next copy or\n     the end of the input will be emitted as literal bytes. */\n  const uint8_t* next_emit = input;\n  /* Save the start of the first block for position and distance computations.\n  */\n  const uint8_t* base_ip = input;\n\n  static const size_t kFirstBlockSize = 3 << 15;\n  static const size_t kMergeBlockSize = 1 << 16;\n\n  const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;\n  const size_t kMinMatchLen = 5;\n\n  const uint8_t* metablock_start = input;\n  size_t block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize);\n  size_t total_block_size = block_size;\n  /* Save the bit position of the MLEN field of the meta-block header, so that\n     we can update it later if we decide to extend this meta-block. */\n  size_t mlen_storage_ix = *storage_ix + 3;\n\n  size_t literal_ratio;\n\n  const uint8_t* ip;\n  int last_distance;\n\n  const size_t shift = 64u - table_bits;\n\n  BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);\n  /* No block splits, no contexts. */\n  BrotliWriteBits(13, 0, storage_ix, storage);\n\n  literal_ratio = BuildAndStoreLiteralPrefixCode(\n      s, input, block_size, s->lit_depth, s->lit_bits, storage_ix, storage);\n\n  {\n    /* Store the pre-compressed command and distance prefix codes. */\n    size_t i;\n    for (i = 0; i + 7 < s->cmd_code_numbits; i += 8) {\n      BrotliWriteBits(8, s->cmd_code[i >> 3], storage_ix, storage);\n    }\n  }\n  BrotliWriteBits(s->cmd_code_numbits & 7,\n                  s->cmd_code[s->cmd_code_numbits >> 3], storage_ix, storage);\n\n emit_commands:\n  /* Initialize the command and distance histograms. We will gather\n     statistics of command and distance codes during the processing\n     of this block and use it to update the command and distance\n     prefix codes for the next block. */\n  memcpy(s->cmd_histo, kCmdHistoSeed, sizeof(kCmdHistoSeed));\n\n  /* \"ip\" is the input pointer. */\n  ip = input;\n  last_distance = -1;\n  ip_end = input + block_size;\n\n  if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {\n    /* For the last block, we need to keep a 16 bytes margin so that we can be\n       sure that all distances are at most window size - 16.\n       For all other blocks, we only need to keep a margin of 5 bytes so that\n       we don't go over the block size with a copy. */\n    const size_t len_limit = BROTLI_MIN(size_t, block_size - kMinMatchLen,\n                                        input_size - kInputMarginBytes);\n    const uint8_t* ip_limit = input + len_limit;\n\n    uint32_t next_hash;\n    for (next_hash = Hash(++ip, shift); ; ) {\n      /* Step 1: Scan forward in the input looking for a 5-byte-long match.\n         If we get close to exhausting the input then goto emit_remainder.\n\n         Heuristic match skipping: If 32 bytes are scanned with no matches\n         found, start looking only at every other byte. If 32 more bytes are\n         scanned, look at every third byte, etc.. When a match is found,\n         immediately go back to looking at every byte. This is a small loss\n         (~5% performance, ~0.1% density) for compressible data due to more\n         bookkeeping, but for non-compressible data (such as JPEG) it's a huge\n         win since the compressor quickly \"realizes\" the data is incompressible\n         and doesn't bother looking for matches everywhere.\n\n         The \"skip\" variable keeps track of how many bytes there are since the\n         last match; dividing it by 32 (i.e. right-shifting by five) gives the\n         number of bytes to move ahead for each iteration. */\n      uint32_t skip = 32;\n\n      const uint8_t* next_ip = ip;\n      const uint8_t* candidate;\n      BROTLI_DCHECK(next_emit < ip);\ntrawl:\n      do {\n        uint32_t hash = next_hash;\n        uint32_t bytes_between_hash_lookups = skip++ >> 5;\n        BROTLI_DCHECK(hash == Hash(next_ip, shift));\n        ip = next_ip;\n        next_ip = ip + bytes_between_hash_lookups;\n        if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {\n          goto emit_remainder;\n        }\n        next_hash = Hash(next_ip, shift);\n        candidate = ip - last_distance;\n        if (IsMatch(ip, candidate)) {\n          if (BROTLI_PREDICT_TRUE(candidate < ip)) {\n            table[hash] = (int)(ip - base_ip);\n            break;\n          }\n        }\n        candidate = base_ip + table[hash];\n        BROTLI_DCHECK(candidate >= base_ip);\n        BROTLI_DCHECK(candidate < ip);\n\n        table[hash] = (int)(ip - base_ip);\n      } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate)));\n\n      /* Check copy distance. If candidate is not feasible, continue search.\n         Checking is done outside of hot loop to reduce overhead. */\n      if (ip - candidate > MAX_DISTANCE) goto trawl;\n\n      /* Step 2: Emit the found match together with the literal bytes from\n         \"next_emit\" to the bit stream, and then see if we can find a next match\n         immediately afterwards. Repeat until we find no match for the input\n         without emitting some literal bytes. */\n\n      {\n        /* We have a 5-byte match at ip, and we need to emit bytes in\n           [next_emit, ip). */\n        const uint8_t* base = ip;\n        size_t matched = 5 + FindMatchLengthWithLimit(\n            candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5);\n        int distance = (int)(base - candidate);  /* > 0 */\n        size_t insert = (size_t)(base - next_emit);\n        ip += matched;\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %lu copy = %d\\n\",\n                    (int)(next_emit - base_ip), (unsigned long)insert, 2));\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        if (BROTLI_PREDICT_TRUE(insert < 6210)) {\n          EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                        storage_ix, storage);\n        } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert,\n                                             literal_ratio)) {\n          EmitUncompressedMetaBlock(metablock_start, base, mlen_storage_ix - 3,\n                                    storage_ix, storage);\n          input_size -= (size_t)(base - input);\n          input = base;\n          next_emit = input;\n          goto next_block;\n        } else {\n          EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                            storage_ix, storage);\n        }\n        EmitLiterals(next_emit, insert, lit_depth, lit_bits,\n                     storage_ix, storage);\n        if (distance == last_distance) {\n          BrotliWriteBits(cmd_depth[64], cmd_bits[64], storage_ix, storage);\n          ++cmd_histo[64];\n        } else {\n          EmitDistance((size_t)distance, cmd_depth, cmd_bits,\n                       cmd_histo, storage_ix, storage);\n          last_distance = distance;\n        }\n        EmitCopyLenLastDistance(matched, cmd_depth, cmd_bits, cmd_histo,\n                                storage_ix, storage);\n        BROTLI_LOG((\"[CompressFragment] pos = %d distance = %d\\n\"\n                    \"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), (int)distance,\n                    (int)(base - base_ip) + 2, 0, (int)matched - 2,\n                    (int)(base - base_ip) + 2, (int)distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        /* We could immediately start working at ip now, but to improve\n           compression we first update \"table\" with the hashes of some positions\n           within the last copy. */\n        {\n          uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n          uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);\n          uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift);\n          table[prev_hash] = (int)(ip - base_ip - 3);\n          prev_hash = HashBytesAtOffset(input_bytes, 1, shift);\n          table[prev_hash] = (int)(ip - base_ip - 2);\n          prev_hash = HashBytesAtOffset(input_bytes, 2, shift);\n          table[prev_hash] = (int)(ip - base_ip - 1);\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      while (IsMatch(ip, candidate)) {\n        /* We have a 5-byte match at ip, and no need to emit any literal bytes\n           prior to ip. */\n        const uint8_t* base = ip;\n        size_t matched = 5 + FindMatchLengthWithLimit(\n            candidate + 5, ip + 5, (size_t)(ip_end - ip) - 5);\n        if (ip - candidate > MAX_DISTANCE) break;\n        ip += matched;\n        last_distance = (int)(base - candidate);  /* > 0 */\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        EmitCopyLen(matched, cmd_depth, cmd_bits, cmd_histo,\n                    storage_ix, storage);\n        EmitDistance((size_t)last_distance, cmd_depth, cmd_bits,\n                     cmd_histo, storage_ix, storage);\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), 0, (int)matched,\n                    (int)(base - base_ip), (int)last_distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        /* We could immediately start working at ip now, but to improve\n           compression we first update \"table\" with the hashes of some positions\n           within the last copy. */\n        {\n          uint64_t input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n          uint32_t prev_hash = HashBytesAtOffset(input_bytes, 0, shift);\n          uint32_t cur_hash = HashBytesAtOffset(input_bytes, 3, shift);\n          table[prev_hash] = (int)(ip - base_ip - 3);\n          prev_hash = HashBytesAtOffset(input_bytes, 1, shift);\n          table[prev_hash] = (int)(ip - base_ip - 2);\n          prev_hash = HashBytesAtOffset(input_bytes, 2, shift);\n          table[prev_hash] = (int)(ip - base_ip - 1);\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      next_hash = Hash(++ip, shift);\n    }\n  }\n\n emit_remainder:\n  BROTLI_DCHECK(next_emit <= ip_end);\n  input += block_size;\n  input_size -= block_size;\n  block_size = BROTLI_MIN(size_t, input_size, kMergeBlockSize);\n\n  /* Decide if we want to continue this meta-block instead of emitting the\n     last insert-only command. */\n  if (input_size > 0 &&\n      total_block_size + block_size <= (1 << 20) &&\n      ShouldMergeBlock(s, input, block_size, lit_depth)) {\n    BROTLI_DCHECK(total_block_size > (1 << 16));\n    /* Update the size of the current meta-block and continue emitting commands.\n       We can do this because the current size and the new size both have 5\n       nibbles. */\n    total_block_size += block_size;\n    UpdateBits(20, (uint32_t)(total_block_size - 1), mlen_storage_ix, storage);\n    goto emit_commands;\n  }\n\n  /* Emit the remaining bytes as literals. */\n  if (next_emit < ip_end) {\n    const size_t insert = (size_t)(ip_end - next_emit);\n    BROTLI_LOG((\"[CompressFragment] pos = %d insert = %lu copy = %d\\n\",\n                (int)(next_emit - base_ip), (unsigned long)insert, 2));\n    if (BROTLI_PREDICT_TRUE(insert < 6210)) {\n      EmitInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                    storage_ix, storage);\n      EmitLiterals(next_emit, insert, lit_depth, lit_bits, storage_ix, storage);\n    } else if (ShouldUseUncompressedMode(metablock_start, next_emit, insert,\n                                         literal_ratio)) {\n      EmitUncompressedMetaBlock(metablock_start, ip_end, mlen_storage_ix - 3,\n                                storage_ix, storage);\n    } else {\n      EmitLongInsertLen(insert, cmd_depth, cmd_bits, cmd_histo,\n                        storage_ix, storage);\n      EmitLiterals(next_emit, insert, lit_depth, lit_bits,\n                   storage_ix, storage);\n    }\n  }\n  next_emit = ip_end;\n\nnext_block:\n  /* If we have more data, write a new meta-block header and prefix codes and\n     then continue emitting commands. */\n  if (input_size > 0) {\n    metablock_start = input;\n    block_size = BROTLI_MIN(size_t, input_size, kFirstBlockSize);\n    total_block_size = block_size;\n    /* Save the bit position of the MLEN field of the meta-block header, so that\n       we can update it later if we decide to extend this meta-block. */\n    mlen_storage_ix = *storage_ix + 3;\n    BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);\n    /* No block splits, no contexts. */\n    BrotliWriteBits(13, 0, storage_ix, storage);\n    literal_ratio = BuildAndStoreLiteralPrefixCode(\n        s, input, block_size, lit_depth, lit_bits, storage_ix, storage);\n    BuildAndStoreCommandPrefixCode(s, storage_ix, storage);\n    goto emit_commands;\n  }\n\n  if (!is_last) {\n    /* If this is not the last block, update the command and distance prefix\n       codes for the next block and store the compressed forms. */\n    s->cmd_code[0] = 0;\n    s->cmd_code_numbits = 0;\n    BuildAndStoreCommandPrefixCode(s, &s->cmd_code_numbits, s->cmd_code);\n  }\n}\n\n#define FOR_TABLE_BITS_(X) X(9) X(11) X(13) X(15)\n\n#define BAKE_METHOD_PARAM_(B) \\\nstatic BROTLI_NOINLINE void BrotliCompressFragmentFastImpl ## B(             \\\n    BrotliOnePassArena* s, const uint8_t* input, size_t input_size,          \\\n    BROTLI_BOOL is_last, int* table, size_t* storage_ix, uint8_t* storage) { \\\n  BrotliCompressFragmentFastImpl(s, input, input_size, is_last, table, B,    \\\n      storage_ix, storage);                                                  \\\n}\nFOR_TABLE_BITS_(BAKE_METHOD_PARAM_)\n#undef BAKE_METHOD_PARAM_\n\nvoid BrotliCompressFragmentFast(\n    BrotliOnePassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, int* table, size_t table_size,\n    size_t* storage_ix, uint8_t* storage) {\n  const size_t initial_storage_ix = *storage_ix;\n  const size_t table_bits = Log2FloorNonZero(table_size);\n\n  if (input_size == 0) {\n    BROTLI_DCHECK(is_last);\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n    return;\n  }\n\n  switch (table_bits) {\n#define CASE_(B)                                                     \\\n    case B:                                                          \\\n      BrotliCompressFragmentFastImpl ## B(                           \\\n          s, input, input_size, is_last, table, storage_ix, storage);\\\n      break;\n    FOR_TABLE_BITS_(CASE_)\n#undef CASE_\n    default: BROTLI_DCHECK(0); break;\n  }\n\n  /* If output is larger than single uncompressed block, rewrite it. */\n  if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) {\n    EmitUncompressedMetaBlock(input, input + input_size, initial_storage_ix,\n                              storage_ix, storage);\n  }\n\n  if (is_last) {\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n  }\n}\n\n#undef FOR_TABLE_BITS_\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/compress_fragment.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses one-pass processing: when we find a backward\n   match, we immediately emit the corresponding command and literal codes to\n   the bit stream. */\n\n#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_H_\n#define BROTLI_ENC_COMPRESS_FRAGMENT_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"entropy_encode.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BrotliOnePassArena {\n  uint8_t lit_depth[256];\n  uint16_t lit_bits[256];\n\n  /* Command and distance prefix codes (each 64 symbols, stored back-to-back)\n     used for the next block. The command prefix code is over a smaller alphabet\n     with the following 64 symbols:\n        0 - 15: insert length code 0, copy length code 0 - 15, same distance\n       16 - 39: insert length code 0, copy length code 0 - 23\n       40 - 63: insert length code 0 - 23, copy length code 0\n     Note that symbols 16 and 40 represent the same code in the full alphabet,\n     but we do not use either of them. */\n  uint8_t cmd_depth[128];\n  uint16_t cmd_bits[128];\n  uint32_t cmd_histo[128];\n\n  /* The compressed form of the command and distance prefix codes for the next\n     block. */\n  uint8_t cmd_code[512];\n  size_t cmd_code_numbits;\n\n  HuffmanTree tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1];\n  uint32_t histogram[256];\n  uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint16_t tmp_bits[64];\n} BrotliOnePassArena;\n\n/* Compresses \"input\" string to the \"*storage\" buffer as one or more complete\n   meta-blocks, and updates the \"*storage_ix\" bit position.\n\n   If \"is_last\" is 1, emits an additional empty last meta-block.\n\n   \"cmd_depth\" and \"cmd_bits\" contain the command and distance prefix codes\n   (see comment in encode.h) used for the encoding of this input fragment.\n   If \"is_last\" is 0, they are updated to reflect the statistics\n   of this input fragment, to be used for the encoding of the next fragment.\n\n   \"*cmd_code_numbits\" is the number of bits of the compressed representation\n   of the command and distance prefix codes, and \"cmd_code\" is an array of\n   at least \"(*cmd_code_numbits + 7) >> 3\" size that contains the compressed\n   command and distance prefix codes. If \"is_last\" is 0, these are also\n   updated to represent the updated \"cmd_depth\" and \"cmd_bits\".\n\n   REQUIRES: \"input_size\" is greater than zero, or \"is_last\" is 1.\n   REQUIRES: \"input_size\" is less or equal to maximal metablock size (1 << 24).\n   REQUIRES: All elements in \"table[0..table_size-1]\" are initialized to zero.\n   REQUIRES: \"table_size\" is an odd (9, 11, 13, 15) power of two\n   OUTPUT: maximal copy distance <= |input_size|\n   OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */\nBROTLI_INTERNAL void BrotliCompressFragmentFast(BrotliOnePassArena* s,\n                                                const uint8_t* input,\n                                                size_t input_size,\n                                                BROTLI_BOOL is_last,\n                                                int* table, size_t table_size,\n                                                size_t* storage_ix,\n                                                uint8_t* storage);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_COMPRESS_FRAGMENT_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/compress_fragment_two_pass.c",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses two-pass processing: in the first pass we save\n   the found backward matches and literal bytes into a buffer, and in the\n   second pass we emit them into the bit stream using prefix codes built based\n   on the actual command and literal byte histograms. */\n\n#include \"compress_fragment_two_pass.h\"\n\n#include <string.h>  /* memcmp, memcpy, memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"\n#include \"brotli_bit_stream.h\"\n#include \"entropy_encode.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_DISTANCE (long)BROTLI_MAX_BACKWARD_LIMIT(18)\n\n/* kHashMul32 multiplier has these properties:\n   * The multiplier must be odd. Otherwise we may lose the highest bit.\n   * No long streaks of ones or zeros.\n   * There is no effort to ensure that it is a prime, the oddity is enough\n     for this use.\n   * The number has been tuned heuristically against compression benchmarks. */\nstatic const uint32_t kHashMul32 = 0x1E35A7BD;\n\nstatic BROTLI_INLINE uint32_t Hash(const uint8_t* p,\n    size_t shift, size_t length) {\n  const uint64_t h =\n      (BROTLI_UNALIGNED_LOAD64LE(p) << ((8 - length) * 8)) * kHashMul32;\n  return (uint32_t)(h >> shift);\n}\n\nstatic BROTLI_INLINE uint32_t HashBytesAtOffset(uint64_t v, size_t offset,\n    size_t shift, size_t length) {\n  BROTLI_DCHECK(offset <= 8 - length);\n  {\n    const uint64_t h = ((v >> (8 * offset)) << ((8 - length) * 8)) * kHashMul32;\n    return (uint32_t)(h >> shift);\n  }\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL IsMatch(const uint8_t* p1, const uint8_t* p2,\n    size_t length) {\n  if (BrotliUnalignedRead32(p1) == BrotliUnalignedRead32(p2)) {\n    if (length == 4) return BROTLI_TRUE;\n    return TO_BROTLI_BOOL(p1[4] == p2[4] && p1[5] == p2[5]);\n  }\n  return BROTLI_FALSE;\n}\n\n/* Builds a command and distance prefix code (each 64 symbols) into \"depth\" and\n   \"bits\" based on \"histogram\" and stores it into the bit stream. */\nstatic void BuildAndStoreCommandPrefixCode(BrotliTwoPassArena* s,\n                                           size_t* storage_ix,\n                                           uint8_t* storage) {\n  /* Tree size for building a tree over 64 symbols is 2 * 64 + 1. */\n  /* TODO(eustas): initialize once. */\n  memset(s->tmp_depth, 0, sizeof(s->tmp_depth));\n  BrotliCreateHuffmanTree(s->cmd_histo, 64, 15, s->tmp_tree, s->cmd_depth);\n  BrotliCreateHuffmanTree(&s->cmd_histo[64], 64, 14, s->tmp_tree,\n                          &s->cmd_depth[64]);\n  /* We have to jump through a few hoops here in order to compute\n     the command bits because the symbols are in a different order than in\n     the full alphabet. This looks complicated, but having the symbols\n     in this order in the command bits saves a few branches in the Emit*\n     functions. */\n  memcpy(s->tmp_depth, s->cmd_depth + 24, 24);\n  memcpy(s->tmp_depth + 24, s->cmd_depth, 8);\n  memcpy(s->tmp_depth + 32, s->cmd_depth + 48, 8);\n  memcpy(s->tmp_depth + 40, s->cmd_depth + 8, 8);\n  memcpy(s->tmp_depth + 48, s->cmd_depth + 56, 8);\n  memcpy(s->tmp_depth + 56, s->cmd_depth + 16, 8);\n  BrotliConvertBitDepthsToSymbols(s->tmp_depth, 64, s->tmp_bits);\n  memcpy(s->cmd_bits, s->tmp_bits + 24, 16);\n  memcpy(s->cmd_bits + 8, s->tmp_bits + 40, 16);\n  memcpy(s->cmd_bits + 16, s->tmp_bits + 56, 16);\n  memcpy(s->cmd_bits + 24, s->tmp_bits, 48);\n  memcpy(s->cmd_bits + 48, s->tmp_bits + 32, 16);\n  memcpy(s->cmd_bits + 56, s->tmp_bits + 48, 16);\n  BrotliConvertBitDepthsToSymbols(&s->cmd_depth[64], 64, &s->cmd_bits[64]);\n  {\n    /* Create the bit length array for the full command alphabet. */\n    size_t i;\n    memset(s->tmp_depth, 0, 64); /* only 64 first values were used */\n    memcpy(s->tmp_depth, s->cmd_depth + 24, 8);\n    memcpy(s->tmp_depth + 64, s->cmd_depth + 32, 8);\n    memcpy(s->tmp_depth + 128, s->cmd_depth + 40, 8);\n    memcpy(s->tmp_depth + 192, s->cmd_depth + 48, 8);\n    memcpy(s->tmp_depth + 384, s->cmd_depth + 56, 8);\n    for (i = 0; i < 8; ++i) {\n      s->tmp_depth[128 + 8 * i] = s->cmd_depth[i];\n      s->tmp_depth[256 + 8 * i] = s->cmd_depth[8 + i];\n      s->tmp_depth[448 + 8 * i] = s->cmd_depth[16 + i];\n    }\n    BrotliStoreHuffmanTree(s->tmp_depth, BROTLI_NUM_COMMAND_SYMBOLS,\n                           s->tmp_tree, storage_ix, storage);\n  }\n  BrotliStoreHuffmanTree(&s->cmd_depth[64], 64, s->tmp_tree, storage_ix,\n                         storage);\n}\n\nstatic BROTLI_INLINE void EmitInsertLen(\n    uint32_t insertlen, uint32_t** commands) {\n  if (insertlen < 6) {\n    **commands = insertlen;\n  } else if (insertlen < 130) {\n    const uint32_t tail = insertlen - 2;\n    const uint32_t nbits = Log2FloorNonZero(tail) - 1u;\n    const uint32_t prefix = tail >> nbits;\n    const uint32_t inscode = (nbits << 1) + prefix + 2;\n    const uint32_t extra = tail - (prefix << nbits);\n    **commands = inscode | (extra << 8);\n  } else if (insertlen < 2114) {\n    const uint32_t tail = insertlen - 66;\n    const uint32_t nbits = Log2FloorNonZero(tail);\n    const uint32_t code = nbits + 10;\n    const uint32_t extra = tail - (1u << nbits);\n    **commands = code | (extra << 8);\n  } else if (insertlen < 6210) {\n    const uint32_t extra = insertlen - 2114;\n    **commands = 21 | (extra << 8);\n  } else if (insertlen < 22594) {\n    const uint32_t extra = insertlen - 6210;\n    **commands = 22 | (extra << 8);\n  } else {\n    const uint32_t extra = insertlen - 22594;\n    **commands = 23 | (extra << 8);\n  }\n  ++(*commands);\n}\n\nstatic BROTLI_INLINE void EmitCopyLen(size_t copylen, uint32_t** commands) {\n  if (copylen < 10) {\n    **commands = (uint32_t)(copylen + 38);\n  } else if (copylen < 134) {\n    const size_t tail = copylen - 6;\n    const size_t nbits = Log2FloorNonZero(tail) - 1;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 44;\n    const size_t extra = tail - (prefix << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n  } else if (copylen < 2118) {\n    const size_t tail = copylen - 70;\n    const size_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 52;\n    const size_t extra = tail - ((size_t)1 << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n  } else {\n    const size_t extra = copylen - 2118;\n    **commands = (uint32_t)(63 | (extra << 8));\n  }\n  ++(*commands);\n}\n\nstatic BROTLI_INLINE void EmitCopyLenLastDistance(\n    size_t copylen, uint32_t** commands) {\n  if (copylen < 12) {\n    **commands = (uint32_t)(copylen + 20);\n    ++(*commands);\n  } else if (copylen < 72) {\n    const size_t tail = copylen - 8;\n    const size_t nbits = Log2FloorNonZero(tail) - 1;\n    const size_t prefix = tail >> nbits;\n    const size_t code = (nbits << 1) + prefix + 28;\n    const size_t extra = tail - (prefix << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n    ++(*commands);\n  } else if (copylen < 136) {\n    const size_t tail = copylen - 8;\n    const size_t code = (tail >> 5) + 54;\n    const size_t extra = tail & 31;\n    **commands = (uint32_t)(code | (extra << 8));\n    ++(*commands);\n    **commands = 64;\n    ++(*commands);\n  } else if (copylen < 2120) {\n    const size_t tail = copylen - 72;\n    const size_t nbits = Log2FloorNonZero(tail);\n    const size_t code = nbits + 52;\n    const size_t extra = tail - ((size_t)1 << nbits);\n    **commands = (uint32_t)(code | (extra << 8));\n    ++(*commands);\n    **commands = 64;\n    ++(*commands);\n  } else {\n    const size_t extra = copylen - 2120;\n    **commands = (uint32_t)(63 | (extra << 8));\n    ++(*commands);\n    **commands = 64;\n    ++(*commands);\n  }\n}\n\nstatic BROTLI_INLINE void EmitDistance(uint32_t distance, uint32_t** commands) {\n  uint32_t d = distance + 3;\n  uint32_t nbits = Log2FloorNonZero(d) - 1;\n  const uint32_t prefix = (d >> nbits) & 1;\n  const uint32_t offset = (2 + prefix) << nbits;\n  const uint32_t distcode = 2 * (nbits - 1) + prefix + 80;\n  uint32_t extra = d - offset;\n  **commands = distcode | (extra << 8);\n  ++(*commands);\n}\n\n/* REQUIRES: len <= 1 << 24. */\nstatic void BrotliStoreMetaBlockHeader(\n    size_t len, BROTLI_BOOL is_uncompressed, size_t* storage_ix,\n    uint8_t* storage) {\n  size_t nibbles = 6;\n  /* ISLAST */\n  BrotliWriteBits(1, 0, storage_ix, storage);\n  if (len <= (1U << 16)) {\n    nibbles = 4;\n  } else if (len <= (1U << 20)) {\n    nibbles = 5;\n  }\n  BrotliWriteBits(2, nibbles - 4, storage_ix, storage);\n  BrotliWriteBits(nibbles * 4, len - 1, storage_ix, storage);\n  /* ISUNCOMPRESSED */\n  BrotliWriteBits(1, (uint64_t)is_uncompressed, storage_ix, storage);\n}\n\nstatic BROTLI_INLINE void CreateCommands(const uint8_t* input,\n    size_t block_size, size_t input_size, const uint8_t* base_ip, int* table,\n    size_t table_bits, size_t min_match,\n    uint8_t** literals, uint32_t** commands) {\n  /* \"ip\" is the input pointer. */\n  const uint8_t* ip = input;\n  const size_t shift = 64u - table_bits;\n  const uint8_t* ip_end = input + block_size;\n  /* \"next_emit\" is a pointer to the first byte that is not covered by a\n     previous copy. Bytes between \"next_emit\" and the start of the next copy or\n     the end of the input will be emitted as literal bytes. */\n  const uint8_t* next_emit = input;\n\n  int last_distance = -1;\n  const size_t kInputMarginBytes = BROTLI_WINDOW_GAP;\n\n  if (BROTLI_PREDICT_TRUE(block_size >= kInputMarginBytes)) {\n    /* For the last block, we need to keep a 16 bytes margin so that we can be\n       sure that all distances are at most window size - 16.\n       For all other blocks, we only need to keep a margin of 5 bytes so that\n       we don't go over the block size with a copy. */\n    const size_t len_limit = BROTLI_MIN(size_t, block_size - min_match,\n                                        input_size - kInputMarginBytes);\n    const uint8_t* ip_limit = input + len_limit;\n\n    uint32_t next_hash;\n    for (next_hash = Hash(++ip, shift, min_match); ; ) {\n      /* Step 1: Scan forward in the input looking for a 6-byte-long match.\n         If we get close to exhausting the input then goto emit_remainder.\n\n         Heuristic match skipping: If 32 bytes are scanned with no matches\n         found, start looking only at every other byte. If 32 more bytes are\n         scanned, look at every third byte, etc.. When a match is found,\n         immediately go back to looking at every byte. This is a small loss\n         (~5% performance, ~0.1% density) for compressible data due to more\n         bookkeeping, but for non-compressible data (such as JPEG) it's a huge\n         win since the compressor quickly \"realizes\" the data is incompressible\n         and doesn't bother looking for matches everywhere.\n\n         The \"skip\" variable keeps track of how many bytes there are since the\n         last match; dividing it by 32 (ie. right-shifting by five) gives the\n         number of bytes to move ahead for each iteration. */\n      uint32_t skip = 32;\n\n      const uint8_t* next_ip = ip;\n      const uint8_t* candidate;\n\n      BROTLI_DCHECK(next_emit < ip);\ntrawl:\n      do {\n        uint32_t hash = next_hash;\n        uint32_t bytes_between_hash_lookups = skip++ >> 5;\n        ip = next_ip;\n        BROTLI_DCHECK(hash == Hash(ip, shift, min_match));\n        next_ip = ip + bytes_between_hash_lookups;\n        if (BROTLI_PREDICT_FALSE(next_ip > ip_limit)) {\n          goto emit_remainder;\n        }\n        next_hash = Hash(next_ip, shift, min_match);\n        candidate = ip - last_distance;\n        if (IsMatch(ip, candidate, min_match)) {\n          if (BROTLI_PREDICT_TRUE(candidate < ip)) {\n            table[hash] = (int)(ip - base_ip);\n            break;\n          }\n        }\n        candidate = base_ip + table[hash];\n        BROTLI_DCHECK(candidate >= base_ip);\n        BROTLI_DCHECK(candidate < ip);\n\n        table[hash] = (int)(ip - base_ip);\n      } while (BROTLI_PREDICT_TRUE(!IsMatch(ip, candidate, min_match)));\n\n      /* Check copy distance. If candidate is not feasible, continue search.\n         Checking is done outside of hot loop to reduce overhead. */\n      if (ip - candidate > MAX_DISTANCE) goto trawl;\n\n      /* Step 2: Emit the found match together with the literal bytes from\n         \"next_emit\", and then see if we can find a next match immediately\n         afterwards. Repeat until we find no match for the input\n         without emitting some literal bytes. */\n\n      {\n        /* We have a 6-byte match at ip, and we need to emit bytes in\n           [next_emit, ip). */\n        const uint8_t* base = ip;\n        size_t matched = min_match + FindMatchLengthWithLimit(\n            candidate + min_match, ip + min_match,\n            (size_t)(ip_end - ip) - min_match);\n        int distance = (int)(base - candidate);  /* > 0 */\n        int insert = (int)(base - next_emit);\n        ip += matched;\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        EmitInsertLen((uint32_t)insert, commands);\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\",\n                    (int)(next_emit - base_ip), insert, 2));\n        memcpy(*literals, next_emit, (size_t)insert);\n        *literals += insert;\n        if (distance == last_distance) {\n          **commands = 64;\n          ++(*commands);\n        } else {\n          EmitDistance((uint32_t)distance, commands);\n          last_distance = distance;\n        }\n        EmitCopyLenLastDistance(matched, commands);\n        BROTLI_LOG((\"[CompressFragment] pos = %d distance = %d\\n\"\n                    \"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), (int)distance,\n                    (int)(base - base_ip) + 2, 0, (int)matched - 2,\n                    (int)(base - base_ip) + 2, (int)distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        {\n          /* We could immediately start working at ip now, but to improve\n             compression we first update \"table\" with the hashes of some\n             positions within the last copy. */\n          uint64_t input_bytes;\n          uint32_t cur_hash;\n          uint32_t prev_hash;\n          if (min_match == 4) {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n            cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          } else {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 4);\n            prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);\n            cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          }\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      while (ip - candidate <= MAX_DISTANCE &&\n          IsMatch(ip, candidate, min_match)) {\n        /* We have a 6-byte match at ip, and no need to emit any\n           literal bytes prior to ip. */\n        const uint8_t* base = ip;\n        size_t matched = min_match + FindMatchLengthWithLimit(\n            candidate + min_match, ip + min_match,\n            (size_t)(ip_end - ip) - min_match);\n        ip += matched;\n        last_distance = (int)(base - candidate);  /* > 0 */\n        BROTLI_DCHECK(0 == memcmp(base, candidate, matched));\n        EmitCopyLen(matched, commands);\n        EmitDistance((uint32_t)last_distance, commands);\n        BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\"\n                    \"[CompressFragment] pos = %d distance = %d\\n\",\n                    (int)(base - base_ip), 0, (int)matched,\n                    (int)(base - base_ip), (int)last_distance));\n\n        next_emit = ip;\n        if (BROTLI_PREDICT_FALSE(ip >= ip_limit)) {\n          goto emit_remainder;\n        }\n        {\n          /* We could immediately start working at ip now, but to improve\n             compression we first update \"table\" with the hashes of some\n             positions within the last copy. */\n          uint64_t input_bytes;\n          uint32_t cur_hash;\n          uint32_t prev_hash;\n          if (min_match == 4) {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 3);\n            cur_hash = HashBytesAtOffset(input_bytes, 3, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          } else {\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 5);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 4);\n            prev_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 3);\n            input_bytes = BROTLI_UNALIGNED_LOAD64LE(ip - 2);\n            cur_hash = HashBytesAtOffset(input_bytes, 2, shift, min_match);\n            prev_hash = HashBytesAtOffset(input_bytes, 0, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 2);\n            prev_hash = HashBytesAtOffset(input_bytes, 1, shift, min_match);\n            table[prev_hash] = (int)(ip - base_ip - 1);\n          }\n\n          candidate = base_ip + table[cur_hash];\n          table[cur_hash] = (int)(ip - base_ip);\n        }\n      }\n\n      next_hash = Hash(++ip, shift, min_match);\n    }\n  }\n\nemit_remainder:\n  BROTLI_DCHECK(next_emit <= ip_end);\n  /* Emit the remaining bytes as literals. */\n  if (next_emit < ip_end) {\n    const uint32_t insert = (uint32_t)(ip_end - next_emit);\n    EmitInsertLen(insert, commands);\n    BROTLI_LOG((\"[CompressFragment] pos = %d insert = %d copy = %d\\n\",\n                (int)(next_emit - base_ip), insert, 2));\n    memcpy(*literals, next_emit, insert);\n    *literals += insert;\n  }\n}\n\nstatic void StoreCommands(BrotliTwoPassArena* s,\n                          const uint8_t* literals, const size_t num_literals,\n                          const uint32_t* commands, const size_t num_commands,\n                          size_t* storage_ix, uint8_t* storage) {\n  static const uint32_t kNumExtraBits[128] = {\n      0,  0,  0,  0,  0,  0,  1,  1,  2,  2,  3,  3,  4,  4,  5,  5,\n      6,  7,  8,  9,  10, 12, 14, 24, 0,  0,  0,  0,  0,  0,  0,  0,\n      1,  1,  2,  2,  3,  3,  4,  4,  0,  0,  0,  0,  0,  0,  0,  0,\n      1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  7,  8,  9,  10, 24,\n      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,\n      1,  1,  2,  2,  3,  3,  4,  4,  5,  5,  6,  6,  7,  7,  8,  8,\n      9,  9,  10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16,\n      17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, 24, 24,\n  };\n  static const uint32_t kInsertOffset[24] = {\n      0,  1,  2,  3,  4,   5,   6,   8,   10,   14,   18,   26,\n      34, 50, 66, 98, 130, 194, 322, 578, 1090, 2114, 6210, 22594,\n  };\n\n  size_t i;\n  memset(s->lit_histo, 0, sizeof(s->lit_histo));\n  /* TODO(eustas): is that necessary? */\n  memset(s->cmd_depth, 0, sizeof(s->cmd_depth));\n  /* TODO(eustas): is that necessary? */\n  memset(s->cmd_bits, 0, sizeof(s->cmd_bits));\n  memset(s->cmd_histo, 0, sizeof(s->cmd_histo));\n  for (i = 0; i < num_literals; ++i) {\n    ++s->lit_histo[literals[i]];\n  }\n  BrotliBuildAndStoreHuffmanTreeFast(s->tmp_tree, s->lit_histo, num_literals,\n                                     /* max_bits = */ 8, s->lit_depth,\n                                     s->lit_bits, storage_ix, storage);\n\n  for (i = 0; i < num_commands; ++i) {\n    const uint32_t code = commands[i] & 0xFF;\n    BROTLI_DCHECK(code < 128);\n    ++s->cmd_histo[code];\n  }\n  s->cmd_histo[1] += 1;\n  s->cmd_histo[2] += 1;\n  s->cmd_histo[64] += 1;\n  s->cmd_histo[84] += 1;\n  BuildAndStoreCommandPrefixCode(s, storage_ix, storage);\n\n  for (i = 0; i < num_commands; ++i) {\n    const uint32_t cmd = commands[i];\n    const uint32_t code = cmd & 0xFF;\n    const uint32_t extra = cmd >> 8;\n    BROTLI_DCHECK(code < 128);\n    BrotliWriteBits(s->cmd_depth[code], s->cmd_bits[code], storage_ix, storage);\n    BrotliWriteBits(kNumExtraBits[code], extra, storage_ix, storage);\n    if (code < 24) {\n      const uint32_t insert = kInsertOffset[code] + extra;\n      uint32_t j;\n      for (j = 0; j < insert; ++j) {\n        const uint8_t lit = *literals;\n        BrotliWriteBits(s->lit_depth[lit], s->lit_bits[lit], storage_ix,\n                        storage);\n        ++literals;\n      }\n    }\n  }\n}\n\n/* Acceptable loss for uncompressible speedup is 2% */\n#define MIN_RATIO 0.98\n#define SAMPLE_RATE 43\n\nstatic BROTLI_BOOL ShouldCompress(BrotliTwoPassArena* s,\n    const uint8_t* input, size_t input_size, size_t num_literals) {\n  double corpus_size = (double)input_size;\n  if ((double)num_literals < MIN_RATIO * corpus_size) {\n    return BROTLI_TRUE;\n  } else {\n    const double max_total_bit_cost = corpus_size * 8 * MIN_RATIO / SAMPLE_RATE;\n    size_t i;\n    memset(s->lit_histo, 0, sizeof(s->lit_histo));\n    for (i = 0; i < input_size; i += SAMPLE_RATE) {\n      ++s->lit_histo[input[i]];\n    }\n    return TO_BROTLI_BOOL(BitsEntropy(s->lit_histo, 256) < max_total_bit_cost);\n  }\n}\n\nstatic void RewindBitPosition(const size_t new_storage_ix,\n                              size_t* storage_ix, uint8_t* storage) {\n  const size_t bitpos = new_storage_ix & 7;\n  const size_t mask = (1u << bitpos) - 1;\n  storage[new_storage_ix >> 3] &= (uint8_t)mask;\n  *storage_ix = new_storage_ix;\n}\n\nstatic void EmitUncompressedMetaBlock(const uint8_t* input, size_t input_size,\n                                      size_t* storage_ix, uint8_t* storage) {\n  BrotliStoreMetaBlockHeader(input_size, 1, storage_ix, storage);\n  *storage_ix = (*storage_ix + 7u) & ~7u;\n  memcpy(&storage[*storage_ix >> 3], input, input_size);\n  *storage_ix += input_size << 3;\n  storage[*storage_ix >> 3] = 0;\n}\n\nstatic BROTLI_INLINE void BrotliCompressFragmentTwoPassImpl(\n    BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,\n    int* table, size_t table_bits, size_t min_match,\n    size_t* storage_ix, uint8_t* storage) {\n  /* Save the start of the first block for position and distance computations.\n  */\n  const uint8_t* base_ip = input;\n  BROTLI_UNUSED(is_last);\n\n  while (input_size > 0) {\n    size_t block_size =\n        BROTLI_MIN(size_t, input_size, kCompressFragmentTwoPassBlockSize);\n    uint32_t* commands = command_buf;\n    uint8_t* literals = literal_buf;\n    size_t num_literals;\n    CreateCommands(input, block_size, input_size, base_ip, table,\n                   table_bits, min_match, &literals, &commands);\n    num_literals = (size_t)(literals - literal_buf);\n    if (ShouldCompress(s, input, block_size, num_literals)) {\n      const size_t num_commands = (size_t)(commands - command_buf);\n      BrotliStoreMetaBlockHeader(block_size, 0, storage_ix, storage);\n      /* No block splits, no contexts. */\n      BrotliWriteBits(13, 0, storage_ix, storage);\n      StoreCommands(s, literal_buf, num_literals, command_buf, num_commands,\n                    storage_ix, storage);\n    } else {\n      /* Since we did not find many backward references and the entropy of\n         the data is close to 8 bits, we can simply emit an uncompressed block.\n         This makes compression speed of uncompressible data about 3x faster. */\n      EmitUncompressedMetaBlock(input, block_size, storage_ix, storage);\n    }\n    input += block_size;\n    input_size -= block_size;\n  }\n}\n\n#define FOR_TABLE_BITS_(X) \\\n  X(8) X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16) X(17)\n\n#define BAKE_METHOD_PARAM_(B)                                                  \\\nstatic BROTLI_NOINLINE void BrotliCompressFragmentTwoPassImpl ## B(            \\\n    BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,            \\\n    BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,          \\\n    int* table, size_t* storage_ix, uint8_t* storage) {                        \\\n  size_t min_match = (B <= 15) ? 4 : 6;                                        \\\n  BrotliCompressFragmentTwoPassImpl(s, input, input_size, is_last, command_buf,\\\n      literal_buf, table, B, min_match, storage_ix, storage);                  \\\n}\nFOR_TABLE_BITS_(BAKE_METHOD_PARAM_)\n#undef BAKE_METHOD_PARAM_\n\nvoid BrotliCompressFragmentTwoPass(\n    BrotliTwoPassArena* s, const uint8_t* input, size_t input_size,\n    BROTLI_BOOL is_last, uint32_t* command_buf, uint8_t* literal_buf,\n    int* table, size_t table_size, size_t* storage_ix, uint8_t* storage) {\n  const size_t initial_storage_ix = *storage_ix;\n  const size_t table_bits = Log2FloorNonZero(table_size);\n  switch (table_bits) {\n#define CASE_(B)                                      \\\n    case B:                                           \\\n      BrotliCompressFragmentTwoPassImpl ## B(         \\\n          s, input, input_size, is_last, command_buf, \\\n          literal_buf, table, storage_ix, storage);   \\\n      break;\n    FOR_TABLE_BITS_(CASE_)\n#undef CASE_\n    default: BROTLI_DCHECK(0); break;\n  }\n\n  /* If output is larger than single uncompressed block, rewrite it. */\n  if (*storage_ix - initial_storage_ix > 31 + (input_size << 3)) {\n    RewindBitPosition(initial_storage_ix, storage_ix, storage);\n    EmitUncompressedMetaBlock(input, input_size, storage_ix, storage);\n  }\n\n  if (is_last) {\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* islast */\n    BrotliWriteBits(1, 1, storage_ix, storage);  /* isempty */\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n  }\n}\n\n#undef FOR_TABLE_BITS_\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/compress_fragment_two_pass.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function for fast encoding of an input fragment, independently from the input\n   history. This function uses two-pass processing: in the first pass we save\n   the found backward matches and literal bytes into a buffer, and in the\n   second pass we emit them into the bit stream using prefix codes built based\n   on the actual command and literal byte histograms. */\n\n#ifndef BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_\n#define BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"entropy_encode.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* TODO(eustas): turn to macro. */\nstatic const size_t kCompressFragmentTwoPassBlockSize = 1 << 17;\n\ntypedef struct BrotliTwoPassArena {\n  uint32_t lit_histo[256];\n  uint8_t lit_depth[256];\n  uint16_t lit_bits[256];\n\n  uint32_t cmd_histo[128];\n  uint8_t cmd_depth[128];\n  uint16_t cmd_bits[128];\n\n  /* BuildAndStoreCommandPrefixCode */\n  HuffmanTree tmp_tree[2 * BROTLI_NUM_LITERAL_SYMBOLS + 1];\n  uint8_t tmp_depth[BROTLI_NUM_COMMAND_SYMBOLS];\n  uint16_t tmp_bits[64];\n} BrotliTwoPassArena;\n\n/* Compresses \"input\" string to the \"*storage\" buffer as one or more complete\n   meta-blocks, and updates the \"*storage_ix\" bit position.\n\n   If \"is_last\" is 1, emits an additional empty last meta-block.\n\n   REQUIRES: \"input_size\" is greater than zero, or \"is_last\" is 1.\n   REQUIRES: \"input_size\" is less or equal to maximal metablock size (1 << 24).\n   REQUIRES: \"command_buf\" and \"literal_buf\" point to at least\n              kCompressFragmentTwoPassBlockSize long arrays.\n   REQUIRES: All elements in \"table[0..table_size-1]\" are initialized to zero.\n   REQUIRES: \"table_size\" is a power of two\n   OUTPUT: maximal copy distance <= |input_size|\n   OUTPUT: maximal copy distance <= BROTLI_MAX_BACKWARD_LIMIT(18) */\nBROTLI_INTERNAL void BrotliCompressFragmentTwoPass(BrotliTwoPassArena* s,\n                                                   const uint8_t* input,\n                                                   size_t input_size,\n                                                   BROTLI_BOOL is_last,\n                                                   uint32_t* command_buf,\n                                                   uint8_t* literal_buf,\n                                                   int* table,\n                                                   size_t table_size,\n                                                   size_t* storage_ix,\n                                                   uint8_t* storage);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_COMPRESS_FRAGMENT_TWO_PASS_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/dictionary_hash.c",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Hash table on the 4-byte prefixes of static dictionary words. */\n\n#include \"../common/platform.h\"\n#include \"dictionary_hash.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* GENERATED CODE START */\nBROTLI_INTERNAL const uint16_t kStaticDictionaryHashWords[32768] = {\n1002,0,0,0,0,0,0,0,0,683,0,0,0,0,0,0,0,1265,0,0,0,0,0,1431,0,0,0,0,0,0,40,0,0,0,\n0,155,8,741,0,624,0,0,0,0,0,0,0,0,0,0,0,0,66,503,0,0,0,451,0,0,0,0,0,0,0,835,70,\n0,0,539,0,0,0,0,0,0,0,0,0,113,0,0,0,0,718,0,0,0,0,0,0,520,0,1070,0,0,0,0,0,1515,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,78,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,610,0,0,750,0,0,0,307,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,964,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,999,0,0,0,0,0,0,0,0,\n645,75,0,649,52,282,0,200,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1621,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,211,225,0,0,687,718,0,0,110,0,58,0,0,0,0,0,0,345,0,0,301,0,0,\n0,203,0,0,1154,674,1949,0,0,0,0,0,0,0,0,0,259,0,0,0,0,0,0,0,1275,0,0,0,1231,254,\n0,0,0,0,0,0,0,277,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,0,0,800,0,0,0,29,\n116,100,490,0,0,0,0,0,1641,0,543,0,0,0,0,41,181,0,657,0,0,202,25,0,0,0,0,0,0,0,\n0,0,0,423,0,0,0,113,0,0,0,927,963,0,976,0,206,0,0,0,0,0,0,0,0,0,2002,0,0,0,0,0,\n0,0,0,0,0,0,696,0,1170,0,0,0,0,226,13,0,769,678,551,0,0,0,0,0,0,57,0,0,0,10,188,\n0,0,0,624,0,0,0,0,0,0,0,0,0,1941,130,0,0,0,0,378,269,0,0,528,0,1146,0,0,0,1105,\n0,1616,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,656,0,1940,0,0,0,0,0,173,0,0,0,0,0,0,0,0,0,\n0,0,457,342,810,0,0,0,0,620,0,0,0,0,0,0,0,967,95,447,406,0,0,0,477,0,1268,944,\n1941,0,0,0,629,0,0,0,0,0,375,0,0,0,1636,0,0,0,0,774,0,1,1034,0,0,0,0,0,824,0,0,\n0,0,0,118,0,0,560,296,0,0,0,0,0,0,0,0,1009,894,0,0,0,0,0,0,0,0,0,0,0,0,0,1474,\n366,0,0,0,0,0,0,0,0,0,79,1723,0,0,200,0,0,0,0,0,0,0,0,1759,372,0,16,0,943,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0,900,1839,707,30,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,2004,0,0,10,115,0,50,0,0,0,0,0,0,0,0,0,0,520,1,0,738,98,482,0,0,0,0,\n0,0,0,0,0,0,701,2,0,0,0,0,0,0,0,0,557,0,0,0,0,0,0,0,0,0,347,0,0,0,0,572,0,0,0,0,\n0,0,0,0,0,832,0,0,797,809,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,861,0,0,294,0,0,0,109,\n0,0,0,0,0,0,0,0,1187,290,266,0,0,0,0,49,50,748,0,0,466,399,0,0,0,0,0,0,0,378,0,\n519,0,0,0,0,0,0,0,0,0,0,0,0,667,351,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,180,\n0,0,869,0,0,0,0,0,0,0,260,0,0,0,0,0,0,0,0,0,0,523,36,0,0,587,510,809,29,260,0,0,\n0,0,0,0,0,0,570,0,565,0,1464,0,0,0,0,0,0,10,0,0,787,399,380,200,0,0,0,0,516,0,\n844,887,0,0,0,0,0,0,0,44,0,0,0,305,1655,0,0,0,0,0,0,0,0,0,0,0,0,0,0,786,10,0,0,\n0,0,0,0,0,0,0,2031,0,0,0,0,0,684,0,0,0,0,0,1480,0,0,0,27,0,0,0,395,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,813,511,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,206,\n496,0,0,0,0,0,909,0,891,0,0,0,0,0,0,0,0,0,687,0,0,0,1342,0,0,0,0,0,0,0,0,0,0,\n160,41,0,0,0,0,0,0,0,0,0,0,0,1718,778,0,0,0,0,0,0,0,0,0,0,1610,0,0,0,0,0,115,0,\n0,0,0,314,294,0,0,0,983,178,193,0,0,0,0,0,0,0,0,0,174,0,0,0,0,0,0,0,0,0,0,848,\n1796,0,0,0,0,0,0,221,0,687,1660,0,0,0,0,262,0,0,179,0,0,0,0,0,66,0,773,0,352,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,152,0,0,1197,0,0,0,0,0,0,0,0,0,0,0,0,560,0,0,\n564,0,0,0,797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,0,819,0,0,0,0,0,0,0,0,719,544,\n637,5,0,0,0,0,0,0,0,0,0,0,0,101,0,1441,0,0,0,893,0,0,0,0,0,0,0,0,0,238,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,1296,0,0,969,1729,314,60,0,0,0,0,0,1144,0,1147,0,0,0,0,0,\n0,0,0,0,0,437,1853,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,828,0,176,0,0,0,0,0,0,434,39,0,\n0,0,0,0,159,0,0,0,902,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,270,0,0,0,0,801,556,0,0,\n0,0,0,0,0,416,19,197,369,0,0,0,0,0,0,0,0,0,28,34,0,757,0,0,898,1553,0,721,0,0,0,\n0,1012,0,0,0,0,1102,0,898,183,0,0,0,0,0,0,0,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,277,0,0,0,435,0,0,0,0,0,1311,0,0,0,0,\n0,0,211,437,0,0,0,28,0,0,750,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2012,0,702,\n0,808,0,0,0,0,739,166,0,0,0,0,0,0,719,170,500,0,0,0,0,0,0,0,0,1500,327,0,0,450,\n0,0,0,1318,0,0,0,1602,0,0,331,754,0,0,0,0,0,1368,0,0,557,0,0,0,799,850,0,0,0,0,\n0,0,0,0,908,0,0,0,0,0,19,62,459,0,0,0,0,0,0,0,0,0,0,0,0,1802,0,0,0,0,0,0,0,0,0,\n1397,0,0,0,0,120,238,0,0,0,0,0,0,0,0,0,0,0,1324,0,0,0,0,0,0,0,0,602,201,0,0,164,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,615,0,0,0,0,0,0,0,0,0,0,0,0,0,1243,0,0,0,0,968,0,0,\n0,0,0,0,882,0,0,0,907,329,100,0,0,0,0,0,0,0,0,0,0,0,176,26,9,0,0,265,256,0,0,0,\n0,0,0,0,0,0,643,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,127,610,0,0,0,0,973,2001,0,\n0,0,0,0,0,522,0,0,0,0,0,0,0,0,0,0,0,553,0,0,0,0,0,0,1582,0,1578,0,0,0,0,0,0,0,0,\n0,0,0,795,0,0,0,432,0,0,0,0,0,0,84,126,0,0,0,0,790,0,377,64,0,1529,0,0,0,0,530,\n1857,539,1104,0,0,0,0,0,0,0,0,0,0,0,0,977,0,0,0,34,0,0,0,0,0,0,0,0,0,0,0,24,26,\n0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,183,379,0,0,0,0,0,0,0,792,\n0,0,0,0,0,0,0,0,0,1920,0,0,0,0,0,0,0,0,0,771,0,0,0,1979,0,901,254,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,0,0,0,0,0,440,37,0,\n508,0,0,0,513,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,533,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,752,920,0,1048,0,153,0,\n0,391,0,0,1952,0,0,0,0,0,0,0,0,0,0,126,0,0,0,0,640,0,483,69,1616,0,0,0,0,0,734,\n0,0,0,0,0,0,480,0,495,0,472,0,0,0,0,0,0,0,0,874,229,0,0,0,0,948,0,0,0,0,0,0,0,0,\n1009,748,0,555,0,0,0,0,0,0,193,0,653,0,0,0,0,0,0,0,0,0,0,984,0,0,0,172,0,0,0,0,\n0,0,0,0,83,1568,0,0,384,0,0,0,0,0,0,0,164,880,0,0,0,0,0,0,0,0,0,0,0,367,121,0,0,\n828,0,0,0,0,0,0,0,1541,0,0,0,0,0,0,0,343,0,0,0,0,0,0,0,0,561,57,0,0,0,0,0,0,0,\n926,0,0,0,0,827,0,194,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,\n0,0,0,896,1249,0,0,0,0,0,1614,0,0,0,860,0,0,0,0,0,0,0,0,964,102,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,569,0,0,0,0,795,2045,0,0,0,\n0,0,0,104,52,0,0,0,0,0,604,0,0,0,0,779,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,0,0,0,0,\n494,0,677,0,0,0,0,0,0,0,508,0,0,0,0,0,0,0,0,0,1014,0,957,0,0,630,310,0,0,0,570,\n0,0,449,0,64,537,0,0,0,0,0,0,0,244,0,0,0,0,0,0,0,0,0,0,0,0,0,0,702,1650,49,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,1279,0,0,0,0,0,0,0,896,0,0,\n178,0,0,0,0,0,0,0,0,0,0,0,0,0,808,695,0,0,0,0,539,1117,0,0,0,0,0,0,0,0,257,0,\n1003,0,0,0,1,448,0,516,0,0,960,0,125,4,0,1268,30,748,0,0,852,0,0,0,6,0,0,848,\n236,1385,862,1811,0,0,0,0,698,803,0,0,0,0,0,0,0,610,992,0,0,878,0,1847,0,0,0,0,\n0,0,0,383,0,1404,0,0,0,0,986,0,347,0,0,0,0,0,0,0,0,0,0,0,592,572,0,1411,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,606,0,0,0,0,0,0,\n0,0,0,0,0,0,0,1829,0,0,0,0,0,0,0,0,0,0,0,0,700,748,0,0,0,0,0,0,365,0,0,127,0,0,\n83,198,0,0,0,0,0,0,864,55,0,0,0,0,726,1752,0,0,0,0,0,0,0,0,0,0,0,0,0,1066,0,764,\n0,0,0,0,683,0,550,309,0,0,874,1212,0,0,0,1364,0,986,381,723,0,0,0,1573,0,0,0,0,\n0,1025,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1559,0,0,0,0,493,133,0,0,0,0,148,\n119,0,0,0,0,0,0,537,14,541,0,635,126,0,0,0,495,0,0,0,0,861,998,1009,0,0,0,0,0,0,\n0,359,368,0,0,0,0,304,1577,0,0,0,0,0,1107,0,0,0,0,0,929,0,0,0,1142,0,0,0,0,289,\n175,0,432,0,219,0,0,0,0,0,785,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,0,0,0,\n931,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1323,0,0,0,0,290,0,559,1751,127,0,0,0,\n934,1167,0,963,0,260,0,0,0,573,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n580,1689,0,0,0,0,0,0,0,0,0,1164,0,0,982,1922,0,63,0,0,0,0,0,793,0,0,0,0,0,0,0,0,\n0,0,0,0,0,67,790,0,0,0,0,0,0,0,0,0,0,391,443,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,271,0,0,0,0,0,0,0,0,0,0,0,1140,0,0,0,0,340,300,0,897,0,0,0,0,0,0,\n0,0,0,0,890,0,0,0,0,818,321,53,0,0,0,0,0,0,0,0,0,468,0,243,0,870,0,0,0,1765,121,\n0,0,0,180,518,0,822,419,634,0,0,0,0,0,0,0,0,0,898,0,0,0,0,454,36,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,0,0,0,0,0,0,1326,0,104,0,0,0,0,0,0,0,\n0,0,260,0,0,0,0,0,0,0,0,0,0,0,0,542,45,0,0,263,1516,42,0,0,0,0,0,468,0,1005,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,288,87,0,0,0,0,0,0,0,0,502,988,133,0,0,0,0,0,0,\n141,0,0,872,1842,0,0,0,0,0,0,0,0,261,619,0,0,0,0,189,246,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,678,0,0,0,0,0,0,0,0,0,0,0,0,285,35,0,517,0,0,0,0,0,0,0,0,0,0,\n540,214,667,0,74,0,0,125,0,0,0,0,0,761,131,0,0,0,0,0,0,0,0,0,0,0,0,0,333,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1338,94,0,0,0,0,0,0,0,0,0,0,0,0,449,0,646,103,\n86,641,2028,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,869,87,277,117,39,0,0,0,0,0,0,0,0,938,\n297,0,0,0,0,558,464,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1608,0,\n0,0,0,0,0,0,1429,0,0,733,1010,0,0,338,1656,0,0,0,1038,979,2010,0,0,0,0,0,0,0,\n1005,0,0,121,0,0,0,219,20,0,0,0,0,0,0,872,1440,0,0,0,683,0,1070,0,0,522,0,0,0,0,\n439,669,0,0,0,0,0,0,0,0,1245,0,0,0,0,0,1218,0,0,547,233,0,0,0,0,0,0,0,0,0,482,0,\n0,0,0,0,0,0,886,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,795,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,371,0,0,0,0,0,0,0,0,0,0,0,0,0,622,0,625,0,0,0,339,29,0,0,338,0,0,0,\n0,130,0,0,0,0,0,0,0,0,0,307,0,0,0,0,0,0,0,0,0,0,2044,0,0,0,0,0,0,0,0,308,770,0,\n0,0,0,0,1266,0,0,0,0,0,0,0,0,0,400,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,690,739,0,0,\n0,0,0,0,0,990,0,0,0,1831,0,0,0,0,0,0,0,0,0,0,0,0,0,613,0,0,0,0,0,0,0,0,0,0,0,0,\n0,763,0,878,0,0,0,977,0,100,0,0,0,0,0,0,0,0,0,463,0,0,0,0,623,318,0,0,296,463,\n137,0,0,454,0,0,0,1527,58,0,0,0,0,0,0,0,18,48,0,0,0,0,0,729,0,0,0,442,0,0,0,0,\n40,449,0,853,0,0,0,0,0,0,227,0,0,0,0,0,0,1491,0,0,0,0,0,0,0,0,0,0,161,55,0,450,\n0,1174,62,0,207,0,0,0,0,0,0,0,0,869,0,0,0,0,80,213,0,0,0,0,0,0,0,0,0,0,354,820,\n0,0,747,0,0,0,954,0,0,1073,0,556,0,0,0,692,0,191,0,804,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,831,162,0,0,35,0,0,0,0,0,0,0,0,1235,0,0,0,0,0,1234,0,0,\n0,0,0,0,0,0,0,0,96,0,0,0,0,0,0,0,149,0,0,0,902,204,0,0,833,0,287,366,0,0,0,0,0,\n0,992,2020,0,0,0,0,0,0,0,0,0,0,0,356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,784,0,0,567,\n630,0,0,0,539,0,0,27,0,0,0,0,0,0,0,0,0,0,755,0,0,0,0,0,0,0,0,0,0,0,0,814,0,0,0,\n0,0,0,0,0,0,0,0,0,0,987,0,0,255,761,194,0,1086,0,0,0,0,0,0,1016,0,0,1396,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,562,271,913,0,0,0,0,0,0,0,0,320,153,45,475,0,0,\n0,0,0,0,0,713,0,327,0,0,0,0,0,0,604,552,3,359,0,0,0,0,853,80,0,0,0,0,0,0,0,2016,\n6,887,0,0,0,0,975,0,961,0,0,0,0,0,916,1891,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,100,101,390,708,0,0,0,587,983,512,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,851,0,0,0,\n0,0,498,140,217,0,0,0,1448,0,0,0,0,0,0,0,0,0,905,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n643,105,0,792,0,0,0,0,0,0,0,0,0,0,0,0,56,0,0,0,0,0,0,0,0,0,0,535,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1748,0,0,0,0,0,754,0,0,0,0,0,0,0,0,0,0,0,0,91,0,0,1565,0,91,792,\n939,3,370,0,0,0,0,95,0,0,0,0,551,7,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1150,0,\n0,0,0,0,0,0,0,0,0,0,0,0,671,0,0,0,0,0,888,368,149,0,0,105,1134,0,983,0,0,458,31,\n0,643,0,0,0,312,0,740,0,0,0,1642,0,0,0,0,0,0,0,236,0,0,0,0,0,0,0,59,68,0,0,0,0,\n0,867,795,0,0,0,0,970,1977,0,0,0,0,0,0,0,1148,0,775,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,970,0,0,0,0,0,0,0,0,0,665,71,0,0,0,0,827,0,0,0,0,0,0,0,0,0,\n0,479,0,0,0,0,0,0,0,0,99,607,0,0,0,0,0,0,0,1960,0,0,0,793,0,0,871,41,0,0,241,94,\n0,0,0,0,209,0,0,1497,0,0,0,0,0,0,0,0,0,98,0,0,0,463,0,0,0,0,291,0,0,0,0,0,0,0,0,\n0,0,984,0,0,0,0,0,205,0,0,0,0,0,0,205,42,0,801,0,0,0,0,0,635,0,0,533,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,371,0,1282,0,0,0,825,0,0,0,0,0,0,0,0,0,357,879,467,0,317,0,0,\n0,0,0,0,0,924,0,0,0,0,849,1795,0,0,0,0,895,1799,43,0,0,0,0,0,0,0,0,0,0,1820,0,0,\n0,0,0,0,0,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,110,0,493,0,174,417,0,0,\n0,0,0,583,733,0,0,0,0,0,0,481,215,0,0,0,0,477,0,0,0,0,0,0,0,0,308,0,0,0,0,0,0,0,\n0,297,126,0,0,361,1551,0,0,0,0,0,0,871,1807,0,0,0,0,0,1307,0,685,0,0,0,0,0,0,0,\n797,0,858,0,565,0,0,0,0,0,0,0,0,0,0,0,0,434,252,826,0,0,0,0,0,0,791,0,0,0,0,509,\n231,178,601,0,0,0,0,0,0,0,0,43,1591,0,0,0,0,0,1683,0,0,0,0,45,0,0,0,0,0,0,0,0,0,\n0,1120,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,556,494,0,398,0,0,0,1030,0,0,0,0,0,0,\n168,0,0,0,0,0,0,0,0,0,0,973,0,642,0,0,0,0,0,0,0,0,0,1615,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,378,594,0,1093,0,679,112,0,0,0,0,1492,540,1374,714,\n1486,0,0,0,0,825,1511,0,0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,736,143,0,700,0,1540,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1557,0,0,0,860,990,0,0,0,807,0,0,0,0,0,131,\n515,0,646,0,0,0,0,117,728,508,121,0,0,0,0,0,0,357,0,0,0,0,0,0,237,0,0,0,0,0,0,0,\n0,0,1784,0,0,0,0,0,0,0,0,0,0,0,713,348,1536,0,738,0,0,0,0,0,0,0,434,0,0,0,0,0,0,\n366,1877,39,0,0,0,0,0,0,580,0,0,0,0,0,0,0,0,0,0,0,0,0,0,873,0,0,0,0,171,0,625,\n550,107,343,943,0,0,0,0,0,0,0,768,0,0,0,0,0,0,0,799,0,0,0,894,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1673,0,0,0,0,0,0,0,0,0,0,0,1052,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n272,0,441,0,0,3,9,0,0,0,1182,0,1346,0,0,0,0,0,0,0,0,682,0,0,1004,24,0,0,968,0,0,\n0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,0,0,0,578,\n474,0,0,0,0,0,0,0,0,0,0,0,0,0,0,113,530,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,556,0,0,0,0,0,0,16,1317,0,0,97,0,0,0,703,0,0,0,0,0,0,0,0,892,0,0,0,1571,0,0,\n426,186,0,1101,0,0,0,0,0,0,0,0,937,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,644,291,\n0,0,0,0,749,0,162,0,0,381,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,762,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,628,21,0,0,0,0,0,0,0,0,919,0,0,0,0,0,0,0,0,0,\n633,0,0,0,0,332,0,0,0,0,0,0,0,0,0,1489,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,832,398,0,645,0,0,0,13,0,0,0,0,0,0,0,0,0,0,20,0,800,0,0,0,0,0,0,0,0,0,\n0,0,0,0,1993,0,0,0,0,769,0,0,0,665,0,0,0,0,0,0,0,0,0,0,1426,0,0,0,0,60,0,0,0,\n641,1874,0,644,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1757,0,0,0,0,0,937,0,1652,0,654,0,\n0,0,0,0,0,0,527,0,0,0,0,0,0,0,0,0,0,0,0,0,226,0,0,0,0,0,1486,0,0,0,0,0,0,0,0,0,\n0,0,325,0,0,0,0,0,0,0,1345,0,0,91,0,404,0,0,0,0,0,0,0,0,0,0,0,0,973,0,0,0,0,0,0,\n0,1176,0,549,0,0,0,0,0,0,0,0,0,0,976,0,0,0,0,0,21,0,0,0,0,0,51,0,0,0,0,314,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,198,6,0,1093,0,0,0,0,0,0,0,0,0,\n0,0,0,0,1776,0,0,0,0,0,1528,0,419,0,0,0,0,0,0,0,0,76,138,0,0,0,0,638,29,0,0,0,0,\n0,0,0,1418,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1710,0,0,0,0,0,\n0,0,0,0,0,0,0,532,23,0,0,0,0,0,0,0,862,0,0,946,592,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,70,0,0,0,0,0,0,0,0,0,812,0,0,0,76,0,0,988,0,442,0,0,0,896,0,0,0,0,0,0,\n483,0,0,0,0,1709,0,0,0,0,0,0,119,0,0,0,117,0,309,0,0,0,0,0,596,976,0,0,0,0,0,0,\n0,0,0,0,0,768,0,0,0,0,0,0,0,0,0,518,0,0,0,0,0,0,0,0,0,0,0,0,0,0,863,0,0,0,24,\n145,1020,0,0,1984,0,0,0,0,0,0,0,658,0,0,0,0,0,0,0,0,0,0,106,1827,0,1010,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,582,87,0,0,0,0,0,0,0,267,0,0,0,703,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,496,0,0,0,0,1121,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,561,0,0,0,0,0,\n0,0,760,0,0,154,0,0,0,255,0,419,323,0,0,0,0,0,368,0,0,0,0,0,0,0,0,0,0,522,0,0,0,\n0,0,0,0,551,562,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,92,0,0,0,0,\n0,0,0,284,525,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,958,0,0,594,0,0,0,0,0,0,6,479,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,820,1641,0,1556,0,0,0,0,0,0,0,302,0,0,\n0,0,0,148,0,0,676,0,0,0,0,0,0,1674,0,0,0,0,0,0,178,0,0,0,0,0,0,0,94,389,0,0,0,0,\n91,8,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,0,0,0,0,0,747,0,0,0,0,0,0,0,1746,0,0,0,0,\n0,24,0,1352,158,1530,0,0,718,130,280,1401,0,0,0,0,0,1946,8,0,0,0,0,1607,0,0,0,0,\n0,0,882,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,417,0,0,0,1597,633,433,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,234,0,0,0,0,0,0,0,0,680,1950,0,0,0,0,249,5,0,0,0,\n0,0,0,0,0,0,1216,0,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,180,0,0,0,0,0,0,0,1002,\n0,0,0,0,0,0,0,0,0,0,0,0,0,931,0,0,0,0,0,0,0,0,747,943,0,1837,0,0,0,0,0,0,0,641,\n0,0,0,0,280,0,0,0,5,0,0,0,0,0,72,545,0,0,0,0,0,0,0,0,0,742,0,0,254,151,872,0,0,\n0,0,0,0,0,0,0,0,0,0,921,0,0,517,833,0,1680,0,0,436,251,584,0,0,0,0,0,0,0,0,0,0,\n0,24,500,0,0,0,0,0,0,0,0,195,1775,514,389,0,0,0,0,0,0,0,743,0,0,0,0,0,0,292,0,0,\n0,227,1283,774,1805,0,0,0,0,0,0,0,0,0,0,119,81,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913,\n1910,0,0,0,1826,490,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1162,700,30,\n0,0,0,721,839,0,0,0,617,0,0,0,0,0,0,0,0,0,169,428,0,0,0,0,0,1648,637,1205,0,0,0,\n1596,0,0,4,266,0,0,0,0,0,0,0,0,0,0,0,862,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0,0,\n0,279,157,391,604,0,0,713,945,877,973,0,0,0,0,0,0,0,0,0,0,0,0,0,0,859,567,628,\n1846,0,0,0,0,0,0,0,0,0,762,0,0,191,0,0,0,0,298,0,0,767,909,0,0,0,0,0,0,0,795,0,\n0,301,0,0,1970,0,0,0,0,0,0,0,0,0,1236,0,0,0,0,0,0,644,369,15,0,160,71,0,0,0,0,0,\n1447,0,0,0,0,0,0,0,0,735,1255,76,0,0,0,0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,0,\n841,0,0,0,0,0,0,0,0,0,0,836,0,0,0,0,0,1622,0,0,735,0,0,0,0,1601,804,1390,394,0,\n0,0,0,0,0,96,0,289,0,0,35,688,0,0,0,667,0,513,0,0,0,0,0,0,0,2034,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,704,0,1524,0,1078,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,306,\n0,0,0,0,0,0,0,431,0,1196,0,0,54,0,15,1448,0,1418,0,0,0,0,0,0,0,0,0,907,0,0,0,0,\n0,0,194,1767,0,0,0,0,0,840,0,900,0,0,0,0,0,0,0,0,0,0,0,1436,0,0,0,0,642,1560,0,\n0,0,0,0,0,94,386,0,0,0,0,0,0,0,0,0,0,830,416,0,0,20,731,0,0,0,0,0,0,0,0,697,0,0,\n662,0,0,0,0,0,0,0,0,0,861,0,0,0,0,0,0,0,871,671,864,0,928,7,0,332,0,0,0,0,1055,\n0,0,0,0,0,0,986,0,0,0,0,0,44,76,0,0,0,0,0,0,0,0,0,0,300,0,0,0,0,0,0,0,175,518,\n831,1108,0,0,0,836,0,1852,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,843,1804,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,246,0,0,0,610,202,0,0,36,0,0,0,240,654,13,0,0,0,0,0,0,0,\n0,391,0,403,0,0,0,0,0,0,0,0,0,0,75,0,366,815,0,0,631,0,0,0,0,0,0,0,0,345,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,952,0,0,0,0,0,0,0,0,0,0,0,673,35,662,0,287,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,5,34,0,0,0,0,0,0,0,0,151,0,427,0,0,382,0,0,0,329,0,0,279,0,0,0,\n0,0,0,0,0,0,0,906,0,0,366,843,0,1443,0,1372,992,0,36,123,0,649,0,0,0,0,0,767,0,\n1018,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,995,0,0,0,0,0,0,0,72,368,0,0,1345,0,0,0,\n589,0,0,0,0,0,0,0,0,0,1988,0,0,220,541,0,0,0,686,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,32,196,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0,0,0,1452,0,\n0,0,616,0,0,0,0,0,0,0,0,0,1229,0,0,0,0,0,0,0,0,0,0,667,120,0,0,0,0,0,0,0,1146,0,\n0,0,0,0,0,0,0,0,0,0,352,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,935,0,1050,0,\n147,88,0,0,923,0,0,0,0,0,934,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,341,222,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,\n637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1159,0,0,0,847,0,0,0,0,0,0,683,0,867,944,0,0,\n0,0,0,1809,0,0,0,0,0,0,0,0,0,0,395,170,0,0,0,0,0,0,0,0,0,0,618,535,0,1625,0,0,0,\n0,0,0,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,778,0,0,0,0,0,46,0,2032,0,0,37,\n1458,0,938,363,34,0,0,0,0,0,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,889,0,0,0,0,0,0,0,\n0,0,0,0,462,0,0,0,0,525,0,0,23,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0,\n0,498,725,0,0,0,0,7,0,0,0,0,773,0,0,0,164,0,0,0,0,0,0,0,0,936,583,659,1462,0,\n220,0,0,0,0,803,0,0,544,119,0,0,0,0,0,0,0,0,0,0,0,181,176,0,1192,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,1878,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,0,0,0,0,0,\n944,0,0,0,0,0,0,0,273,0,0,0,0,0,855,0,0,0,0,5,127,0,0,0,0,0,0,0,0,752,230,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,162,0,654,48,156,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,240,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,197,\n0,0,0,0,0,0,0,963,0,0,0,0,0,0,0,0,0,0,858,0,0,0,0,0,0,0,0,0,0,676,1978,0,0,102,\n972,0,0,0,0,0,0,0,361,0,461,0,0,0,472,0,0,0,0,0,0,0,0,0,0,0,0,0,0,747,905,0,0,0,\n155,0,0,0,0,0,0,0,0,0,0,319,163,0,0,0,0,0,0,0,0,0,848,0,0,36,631,0,0,0,0,0,1769,\n0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,555,247,0,0,\n996,0,0,189,0,0,0,0,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,0,0,0,526,746,0,0,345,0,0,0,\n1017,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,651,428,0,0,0,1162,230,327,546,792,0,0,0,\n1203,0,0,0,0,0,0,0,0,0,672,189,0,0,0,0,0,0,99,0,0,0,298,0,0,0,0,0,0,555,397,0,0,\n0,0,0,1157,0,0,0,0,0,0,0,0,0,0,398,1523,0,366,0,0,787,0,0,0,282,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,157,0,941,0,0,0,0,0,1336,0,0,116,0,0,0,0,0,0,787,0,0,0,0,0,0,0,0,0,\n0,170,160,0,1815,0,0,0,0,0,866,0,0,0,0,0,0,0,0,0,689,0,0,0,0,820,0,498,108,0,0,\n0,1119,0,0,0,244,609,1005,0,581,0,0,0,0,0,895,0,0,0,1898,0,0,0,0,0,926,0,0,0,0,\n0,0,0,0,0,0,0,0,0,538,496,294,301,0,0,0,18,0,0,757,0,0,0,0,0,1263,0,820,0,722,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2028,0,0,0,0,124,1875,0,0,0,881,0,0,0,1348,\n0,0,0,0,0,0,0,911,0,954,0,0,0,0,414,0,0,0,0,517,0,0,0,0,0,816,0,0,0,0,0,0,0,0,\n713,0,0,0,0,0,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,593,150,0,0,0,0,\n0,553,0,0,0,0,0,0,0,0,0,0,108,0,0,0,0,420,0,0,0,0,0,0,0,0,0,0,0,1777,0,0,55,493,\n0,0,81,0,321,980,0,0,0,0,0,0,0,0,0,0,0,0,0,0,362,112,0,74,0,0,0,0,0,0,0,625,0,0,\n0,0,0,0,377,16,0,0,61,281,0,0,0,0,0,0,0,0,0,0,0,0,0,0,224,1031,0,0,0,0,0,0,51,0,\n0,0,0,0,0,0,211,309,15,125,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,789,173,0,439,9,648,\n0,0,294,0,0,0,0,0,0,0,374,8,0,1099,0,0,0,0,0,0,0,575,0,0,0,518,0,0,0,702,0,0,0,\n0,0,0,87,0,0,0,438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,464,122,0,0,0,1802,0,0,0,0,\n0,0,499,0,0,0,87,476,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,840,283,0,0,0,0,1620,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,609,1160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600,\n323,372,0,0,0,0,471,722,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,\n477,1304,0,1774,0,0,88,0,438,12,0,0,0,0,0,0,0,0,671,997,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,639,22,0,0,782,681,0,0,0,0,0,0,0,0,0,0,1013,664,0,942,0,1349,0,0,0,0,0,0,0,\n0,0,0,0,0,356,0,0,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,215,289,0,1975,\n109,450,0,0,0,0,0,0,0,0,0,0,705,0,0,664,0,0,0,0,0,0,0,1238,0,0,318,0,0,0,0,0,0,\n0,0,0,0,0,0,0,960,1872,0,0,0,0,0,0,0,0,0,0,0,0,0,0,103,0,0,0,0,0,0,0,0,0,239,\n777,0,26,0,0,0,0,0,0,0,0,0,0,0,0,375,414,0,17,0,0,0,1350,0,955,0,0,0,0,0,0,0,0,\n887,960,0,0,0,0,0,0,0,0,0,0,708,710,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,919,0,0,0,\n0,502,280,7,45,0,0,0,0,777,0,0,0,0,410,0,1110,0,0,0,0,0,0,414,341,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,787,0,0,0,436,0,0,0,0,0,0,0,1707,613,377,96,0,0,0,0,451,\n0,0,0,0,0,0,0,0,0,0,0,0,0,680,0,483,916,0,0,0,0,0,0,937,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,739,0,0,0,0,0,0,0,0,82,0,0,663,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,128,0,0,0,0,0,0,0,0,1087,0,0,0,0,0,0,0,503,0,0,0,0,0,0,9,113,104,324,0,460,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,935,702,434,485,1014,949,423,0,900,\n0,0,0,0,0,0,0,2018,574,0,0,0,0,0,0,0,0,0,0,0,0,1206,0,0,0,0,0,0,0,0,38,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,1022,0,0,0,0,143,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,2029,0,0,0,0,0,0,0,0,0,0,0,0,523,0,0,0,0,0,0,625,0,0,425,37,0,0,0,1943,0,0,0,\n0,0,765,0,0,0,0,0,0,0,0,0,0,551,0,0,0,0,0,0,0,0,0,0,0,0,168,0,0,1010,0,0,1994,0,\n0,0,91,0,0,0,0,532,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1884,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,240,15,0,0,0,1227,0,1534,0,0,0,0,0,0,0,0,0,0,0,0,0,0,392,0,\n0,0,0,0,0,0,0,0,0,0,0,655,562,395,0,0,0,501,1019,0,0,0,0,509,267,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1099,0,0,0,0,0,0,948,0,0,0,0,0,0,0,\n462,114,0,0,258,404,0,1717,0,0,0,0,82,1061,0,724,0,0,0,0,0,1133,0,0,0,0,0,0,\n1021,841,0,1021,0,0,0,0,0,0,0,0,0,0,488,373,37,0,0,0,0,564,0,0,0,0,0,513,0,0,0,\n825,0,0,899,0,0,778,0,0,12,1417,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,114,545,0,5,\n0,0,0,0,0,0,0,192,0,0,763,0,0,0,0,0,0,0,755,759,0,0,0,0,0,0,0,0,0,370,0,1237,0,\n0,0,0,0,0,298,87,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31,0,0,\n0,0,0,0,814,991,0,757,57,0,0,0,0,0,0,0,0,0,540,0,0,0,0,608,0,0,0,0,0,0,0,0,1014,\n0,0,0,902,0,0,0,0,553,1668,0,0,0,0,0,0,0,0,0,559,60,0,0,0,0,0,511,0,0,675,0,0,\n156,0,0,0,0,0,0,709,0,698,0,0,0,1745,0,0,0,0,0,0,0,0,0,714,0,0,0,0,0,0,0,0,206,\n8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,776,0,0,0,0,0,0,0,0,0,1272,0,0,\n0,0,0,1059,0,0,0,0,0,0,406,0,0,0,0,0,0,0,0,0,0,947,0,0,0,0,0,0,168,0,0,0,0,0,0,\n870,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,554,0,0,0,0,784,908,0,0,0,0,0,0,\n0,396,358,0,0,0,0,0,0,0,0,2,228,0,0,0,0,0,0,0,0,0,0,0,845,14,0,716,1820,594,0,\n81,1428,0,161,0,782,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,998,0,\n0,0,0,0,0,0,0,0,0,0,0,1043,0,1496,0,0,0,0,0,0,0,0,781,0,0,0,0,0,0,0,817,1114,0,\n1814,958,0,0,0,0,812,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,236,643,0,0,0,0,0,0,0,0,0,1172,0,0,0,0,0,0,0,0,0,1338,0,0,0,\n0,0,0,0,0,0,0,0,54,0,0,0,256,0,0,351,0,955,1885,0,469,0,0,0,1270,0,744,0,313,0,\n0,0,0,0,0,0,0,402,969,0,0,0,0,0,0,50,0,0,0,0,572,0,0,0,0,847,0,0,0,0,0,0,0,248,\n43,0,369,0,0,0,0,0,0,0,0,0,0,0,0,0,766,0,363,0,0,0,0,0,0,0,0,0,0,0,678,0,0,409,\n258,82,249,0,0,0,0,0,0,0,0,0,0,0,0,32,393,0,788,0,0,0,1281,509,1968,0,0,0,0,39,\n291,0,0,0,589,0,0,54,1059,0,0,0,0,0,0,824,0,0,0,0,0,0,0,0,0,0,1005,0,1598,0,0,0,\n0,0,919,0,0,0,0,0,0,0,0,52,132,0,0,0,0,0,328,0,0,0,0,173,0,0,0,0,0,65,1411,0,0,\n0,0,0,0,0,0,0,0,442,0,842,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0,0,0,845,\n210,0,0,0,0,0,0,0,0,892,0,0,223,0,0,0,0,529,0,0,0,807,0,137,218,0,1444,0,0,0,0,\n0,332,661,0,0,0,0,0,0,0,76,1517,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,0,0,0,0,0,481,\n379,0,0,0,0,0,149,18,0,0,0,0,0,0,0,0,742,304,142,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,799,925,195,51,0,0,0,0,688,0,0,0,0,697,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,1169,751,0,0,0,452,929,0,221,0,1437,0,0,0,0,955,1251,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,0,132,0,0,0,0,0,865,0,0,0,0,0,0,0,767,\n672,42,0,0,0,1050,0,0,0,0,0,0,0,0,368,44,0,0,0,0,0,0,0,570,29,0,0,0,0,0,0,227,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,522,0,0,0,0,0,0,0,1529,0,0,0,0,0,0,739,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1667,0,0,0,0,0,0,132,511,0,138,208,1020,0,0,23,565,0,344,0,0,0,\n0,0,922,0,0,0,0,0,0,0,240,0,0,415,171,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,402,0,0,754,31,716,0,982,731,0,0,0,0,0,0,0,888,0,0,0,803,847,0,0,823,\n0,0,0,0,0,0,785,0,0,2,0,0,0,0,0,0,0,532,0,0,681,0,0,314,0,384,684,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,649,447,0,1818,1007,0,321,0,66,360,0,0,0,385,0,0,0,0,0,0,\n0,900,73,254,0,0,0,0,683,1959,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,86,0,0,725,0,0,0,0,0,196,0,0,0,0,0,831,0,0,0,0,723,0,0,0,0,0,994,627,0,0,\n0,0,0,0,0,0,0,0,764,66,0,0,0,0,205,36,0,0,0,0,0,0,0,950,0,0,0,887,111,0,0,831,\n388,165,0,0,0,0,0,155,0,0,0,0,0,0,0,0,0,0,0,0,0,0,780,755,0,0,0,0,898,146,0,0,0,\n0,0,0,0,45,7,0,0,0,0,0,0,0,0,607,0,0,0,0,0,0,65,0,0,0,0,0,0,0,0,0,88,0,0,0,0,0,\n621,600,0,367,0,0,0,0,0,0,0,561,0,559,0,585,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,672,157,0,0,0,0,714,0,0,0,\n0,0,456,0,925,0,0,0,0,0,0,0,0,19,0,0,0,0,1473,0,0,0,0,0,0,0,0,0,0,113,0,0,0,0,0,\n0,0,0,0,0,0,0,0,69,463,0,0,82,193,2,471,0,0,0,0,633,0,0,0,0,0,0,1148,129,1392,\n542,803,0,0,0,0,0,0,0,0,0,0,0,0,438,0,0,0,0,0,0,875,0,0,0,0,0,237,0,0,0,0,0,0,0,\n65,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,563,0,0,0,9,444,0,0,43,1260,0,0,0,0,0,0,\n971,0,0,699,0,0,0,0,0,1116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,829,242,0,\n0,593,0,0,0,0,0,0,0,0,201,36,224,0,0,0,0,0,0,1430,0,1806,0,523,0,0,212,1889,0,0,\n0,827,0,0,0,0,0,2043,136,242,0,0,0,0,0,0,284,148,10,0,0,0,0,0,0,1249,0,0,0,807,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,94,0,0,0,494,0,0,0,0,0,0,0,0,1510,0,0,0,0,0,\n0,0,0,0,0,505,1306,0,0,764,268,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,384,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1703,0,0,0,0,159,964,583,0,0,0,\n0,0,0,515,0,0,854,0,0,0,0,0,0,0,0,0,0,0,0,1123,0,0,0,0,0,0,0,136,0,0,0,0,0,1782,\n0,0,44,1287,0,0,0,0,0,732,0,0,0,0,313,679,0,0,316,0,0,0,0,595,0,0,0,0,0,0,753,\n147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,137,0,0,0,0,414,0,1762,0,0,0,0,0,0,0,0,\n0,0,0,599,0,0,0,0,0,0,0,0,0,1749,0,0,0,1627,0,488,0,0,0,0,0,83,0,0,0,0,676,0,0,\n1639,0,0,0,0,0,0,0,0,0,278,0,0,0,0,0,0,97,0,14,1085,0,0,0,0,0,0,781,388,0,849,\n59,229,0,0,0,0,0,1115,0,0,0,0,108,0,0,0,0,700,0,0,0,0,0,0,0,0,0,1414,0,0,0,0,0,\n0,0,0,0,0,0,0,0,660,737,1035,0,0,0,0,0,0,521,690,0,0,0,0,0,0,0,0,0,0,0,0,272,0,\n0,0,0,0,0,0,0,0,0,1744,0,0,0,0,0,0,128,733,0,0,277,0,0,0,0,0,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,0,0,0,0,936,1981,40,0,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,306,0,0,0,0,\n0,0,0,979,0,0,0,0,0,611,0,0,0,0,0,178,0,0,0,1969,0,0,0,0,0,0,0,664,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,390,0,0,0,1510,0,0,0,0,0,0,0,0,0,0,0,493,0,0,37,0,0,0,0,724,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,1537,0,0,168,473,0,0,0,105,0,0,0,0,\n627,438,0,0,0,0,0,0,0,0,0,0,11,1256,0,0,0,1626,0,779,0,0,0,0,25,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,308,0,0,0,0,0,741,0,671,0,0,0,0,649,150,0,0,99,521,0,0,3,339,0,0,0,\n543,0,0,0,0,0,0,0,0,0,1358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,234,155,\n0,0,0,0,0,0,0,1628,0,766,0,0,0,0,0,0,0,0,0,0,0,0,0,829,0,0,0,1445,0,0,0,486,0,0,\n0,0,2,1635,0,0,0,0,558,0,0,0,0,0,0,0,0,0,0,1461,0,0,0,0,0,599,0,0,0,0,0,0,0,0,0,\n1376,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,93,0,0,0,0,0,0,447,0,0,66,1432,0,0,0,0,\n0,0,307,0,413,609,0,0,0,930,0,0,0,0,21,939,0,0,0,0,0,962,4,651,0,0,0,0,15,579,0,\n0,0,0,0,597,0,0,0,0,0,981,0,0,0,545,0,0,0,0,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,800,17,0,0,17,0,907,0,0,0,110,0,0,0,53,458,0,1983,0,0,0,0,0,0,0,0,0,0,443,0,\n0,0,0,0,0,0,0,0,0,0,924,1844,0,1232,0,0,0,0,70,519,0,993,0,0,0,0,0,0,14,530,0,\n907,0,0,0,0,0,733,0,0,0,0,0,0,0,0,55,0,188,531,56,0,0,1693,0,0,0,0,0,0,0,0,441,\n0,192,928,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1525,0,259,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,512,185,0,464,1603,0,0,0,0,0,0,0,0,0,0,0,1113,\n284,720,0,0,722,0,0,0,0,0,13,0,0,0,0,0,0,0,4,289,43,0,0,0,0,0,0,1694,0,0,0,0,\n193,0,0,0,0,409,0,0,0,0,0,0,0,0,0,0,0,0,308,0,0,1863,0,0,0,0,0,0,0,0,0,790,0,0,\n745,1002,0,0,0,0,0,0,0,0,0,289,68,477,13,0,0,0,0,0,0,0,0,0,0,609,0,0,0,0,0,0,0,\n0,0,0,0,367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,528,0,0,0,0,0,0,0,0,0,694,58,\n548,0,0,0,0,0,0,687,0,0,0,0,1749,0,0,0,0,0,0,0,0,1004,661,0,0,0,0,0,0,445,0,0,0,\n74,0,0,0,0,213,0,0,0,0,0,0,0,0,0,0,0,0,0,834,0,0,189,1672,0,0,0,0,0,0,0,1548,\n192,0,0,0,0,0,0,0,0,0,0,0,0,0,32,751,0,78,0,0,0,0,0,0,544,1602,105,473,0,0,0,0,\n0,0,156,1949,0,1779,0,0,0,0,0,0,0,0,0,0,0,763,0,0,0,0,0,0,0,0,29,0,0,0,0,0,0,0,\n0,0,0,883,0,0,0,0,0,0,0,488,0,617,0,0,50,0,694,1518,785,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,546,0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,1016,0,0,0,577,0,0,0,0,0,0,\n184,935,114,720,0,0,100,0,0,0,0,0,0,0,0,0,3,0,0,0,0,0,95,14,0,969,0,0,0,0,0,0,0,\n727,0,1021,0,0,0,0,0,1190,0,0,0,0,0,0,0,0,0,0,0,0,0,153,0,0,0,0,0,0,0,0,0,798,0,\n587,0,0,695,42,0,1929,141,957,0,465,7,908,0,0,450,148,0,0,0,1166,0,0,0,0,0,0,0,\n0,0,0,0,0,253,0,1003,0,0,0,0,0,0,0,0,0,0,0,46,0,0,879,0,806,0,1868,0,0,0,0,0,\n1846,0,0,0,730,0,0,0,0,0,0,0,965,0,0,0,0,506,0,0,0,10,0,0,0,22,0,0,0,0,0,0,0,0,\n0,0,0,0,0,960,296,0,0,0,0,0,0,0,0,0,0,0,587,0,0,0,0,20,0,0,0,32,982,0,0,0,0,0,0,\n0,0,0,0,941,0,0,0,0,435,0,0,0,0,0,0,71,419,0,0,0,0,0,0,688,740,94,345,0,0,679,\n582,0,0,0,0,0,0,0,945,0,0,0,0,0,0,0,0,0,0,0,0,539,0,684,1993,0,0,0,659,0,583,0,\n803,0,704,0,0,0,0,0,198,181,347,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,481,405,203,0,0,99,826,0,0,0,0,0,0,0,492,0,408,0,0,0,0,0,0,0,0,0,0,4,0,0,\n0,0,665,349,137,0,0,0,0,612,1270,0,0,0,0,0,371,0,0,0,826,0,0,0,0,21,1535,858,\n374,0,0,0,0,0,0,311,0,0,0,991,1968,0,0,0,0,494,1647,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,769,0,0,0,0,0,642,0,0,157,123,0,0,0,1435,0,0,0,0,0,0,0,0,0,0,79,0,0,0,\n0,0,0,1425,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,106,393,486,1690,0,0,0,0,\n0,0,0,0,0,0,0,0,756,184,0,0,0,1382,0,0,0,175,0,1493,0,1007,0,0,0,0,0,0,0,0,0,0,\n0,219,0,0,0,0,515,99,0,851,0,0,0,0,0,1278,0,0,0,0,0,0,0,1000,982,0,762,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,910,1819,0,0,0,0,0,0,906,0,0,0,0,0,0,0,0,0,0,1730,0,0,\n0,0,0,0,0,0,0,0,0,1185,0,0,0,0,0,0,0,0,40,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,0,0,\n650,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,56,30,0,553,0,0,20,597,0,1614,0,0,0,0,0,327,\n49,0,0,0,0,0,0,0,78,0,0,786,134,0,0,0,12,496,0,0,0,0,0,0,0,0,0,0,42,204,0,614,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,147,247,0,0,0,0,942,0,0,2023,0,0,0,0,\n0,0,67,285,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,41,532,0,0,0,0,0,0,0,\n1692,0,0,0,0,55,1704,0,0,0,0,988,0,0,0,223,0,0,0,0,0,0,0,57,1123,0,0,0,0,0,1764,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2015,0,0,0,1599,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,0,0,534,0,0,0,0,0,0,0,0,0,0,0,\n0,0,504,621,1248,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1397,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,441,75,0,0,0,0,0,0,0,0,0,0,841,0,0,0,0,0,693,0,650,314,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,913,0,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,475,0,\n0,1016,179,602,111,329,0,0,0,1864,0,0,0,0,846,1888,0,0,780,0,0,0,82,0,0,0,0,821,\n0,0,0,0,0,0,0,0,0,0,0,956,112,0,0,0,261,455,0,0,0,0,0,0,337,385,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,184,1865,0,0,721,16,0,486,0,0,0,265,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,621,0,0,0,0,0,0,0,0,234,0,0,815,0,0,743,\n1987,205,197,0,0,0,0,0,0,0,0,0,314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,219,452,589,0,\n176,333,0,0,0,0,0,0,0,1110,47,0,0,0,0,0,0,0,0,0,0,0,864,0,0,300,0,1237,0,0,0,0,\n0,0,0,0,0,0,0,1685,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,135,395,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,631,0,0,0,0,0,0,835,0,0,0,606,459,0,979,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,612,0,0,0,0,0,0,0,0,158,372,0,854,0,0,0,0,0,\n0,0,1492,0,0,0,833,0,0,0,0,0,0,0,1739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n195,0,0,0,0,0,0,0,0,730,1997,0,0,0,0,0,0,0,0,61,0,0,0,0,0,0,0,266,751,0,0,0,0,0,\n0,0,821,0,0,0,715,0,0,0,868,0,959,0,0,0,0,0,0,0,0,0,0,0,1053,0,0,0,950,0,1081,0,\n1595,0,0,0,0,59,0,0,0,0,0,0,0,0,0,0,47,684,0,0,0,0,0,0,1606,0,777,0,1020,0,0,0,\n1094,0,0,0,0,0,0,0,350,0,0,0,0,0,0,242,1812,0,0,0,967,0,0,0,473,286,0,0,0,0,0,0,\n798,629,222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,513,337,306,0,0,0,0,0,0,0,0,0,\n146,0,0,1646,0,0,0,0,0,465,0,0,0,525,0,0,0,0,0,0,299,165,0,0,0,0,0,0,0,1064,0,0,\n0,0,0,596,0,0,0,0,0,0,0,0,0,0,0,0,0,0,238,1741,0,1233,451,1824,0,0,0,0,733,495,\n0,0,0,0,0,1204,0,0,0,559,341,0,224,21,0,0,0,0,0,0,0,0,97,1446,0,0,0,0,0,0,0,729,\n0,0,565,727,0,1948,0,0,0,519,0,0,0,0,0,0,0,0,0,1193,0,0,0,0,0,0,790,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,323,2,201,0,0,59,0,0,34,0,896,961,0,1285,0,0,46,0,479,0,0,\n0,0,549,0,663,0,0,0,0,0,783,65,682,0,0,0,0,0,11,0,0,0,0,0,522,0,0,0,52,0,0,0,0,\n0,383,0,0,0,0,0,0,0,0,127,0,0,0,0,0,397,194,0,0,635,0,0,0,0,0,0,0,0,0,0,975,0,0,\n0,0,0,0,0,0,0,0,116,0,51,0,0,858,0,1075,535,448,0,0,0,0,0,610,0,0,0,0,0,0,0,0,0,\n0,191,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,267,673,319,94,92,0,551,0,0,218,\n1406,69,256,0,0,952,1980,0,833,0,0,0,0,0,0,0,0,0,0,0,0,39,0,0,0,0,0,0,0,81,0,0,\n0,352,634,0,0,0,0,0,618,0,0,0,0,0,0,73,339,0,0,0,0,0,0,0,0,0,0,0,0,0,0,169,759,\n0,0,0,0,0,0,0,0,0,0,0,0,0,1075,0,0,0,0,0,0,482,649,0,0,0,0,0,0,0,0,386,336,0,0,\n0,1035,0,0,0,0,0,0,0,0,0,0,0,924,0,73,0,0,0,0,0,1971,0,0,0,0,0,0,0,0,0,1344,0,\n501,0,0,0,0,0,0,0,0,46,799,0,0,0,0,0,0,0,276,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,0,\n0,0,0,0,0,158,0,0,0,0,0,1432,0,0,0,0,0,0,0,0,0,0,25,0,0,2001,0,0,0,0,0,0,0,0,0,\n0,0,0,0,478,0,0,0,0,0,0,91,1461,211,602,0,0,0,0,0,0,0,0,0,1068,0,0,124,567,0,0,\n0,1006,0,0,0,0,0,0,0,0,0,735,812,0,0,323,0,0,0,304,0,0,0,0,0,0,0,0,0,148,0,0,0,\n0,0,0,0,0,0,523,0,0,144,730,0,0,981,0,0,111,0,0,132,0,0,0,0,0,0,890,0,0,0,0,0,\n444,0,1787,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,2041,932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,937,0,995,0,0,255,0,0,138,863,965,0,0,631,0,0,0,0,1394,16,652,0,0,0,0,0,0,\n0,0,0,0,0,0,0,897,0,321,0,0,0,0,0,922,0,619,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,844,0,0,0,0,0,0,1659,0,1100,0,0,0,1173,0,1930,268,251,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,390,711,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,0,0,0,0,624,0,0,0,\n1998,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1125,0,0,0,594,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,268,0,0,0,0,0,0,0,563,0,0,0,0,0,0,0,0,2,39,0,0,0,1332,0,0,0,0,0,\n0,0,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,66,796,0,0,0,0,527,0,0,0,0,98,0,0,576,0,\n0,0,0,0,122,0,276,37,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,645,0,0,0,0,\n0,0,0,0,0,0,0,290,0,0,762,1292,0,0,0,1315,0,1955,0,0,0,0,0,0,0,0,0,0,210,131,0,\n0,0,0,797,0,38,0,11,488,0,936,0,441,0,0,0,0,0,595,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n991,0,0,0,0,0,0,0,0,0,0,0,653,0,523,0,0,0,903,0,0,0,0,0,0,0,0,0,0,0,0,80,0,0,0,\n0,0,0,0,0,0,432,0,0,314,0,0,0,0,232,1368,534,0,0,0,0,0,27,0,0,0,12,0,0,0,0,0,0,\n0,0,0,264,736,0,1657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1117,0,127,0,0,0,1208,0,1294,\n0,0,0,0,364,0,0,0,0,0,125,1334,0,0,0,0,0,0,0,0,0,0,0,0,0,0,792,0,0,0,0,0,0,0,\n849,699,0,0,0,0,0,968,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1446,\n124,397,0,0,0,0,0,0,0,0,0,0,0,641,0,0,0,0,0,0,0,0,0,0,0,0,127,346,0,0,517,75,0,\n0,0,0,0,0,0,0,83,0,0,0,0,0,0,1031,0,0,0,0,0,0,0,1470,0,954,0,0,345,304,410,0,0,\n0,0,734,0,0,0,0,0,1822,0,0,0,1798,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,161,\n1865,69,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,0,0,0,541,0,627,0,0,0,0,0,0,0,0,0,166,0,\n0,0,0,0,0,0,0,0,849,0,0,0,0,0,0,0,717,0,0,0,0,0,0,0,0,0,0,0,0,0,0,600,0,0,0,0,0,\n0,654,0,0,188,273,0,0,0,543,0,410,87,0,0,941,0,0,186,250,0,1785,0,0,0,0,0,1339,\n462,961,0,780,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,0,0,474,1276,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,24,948,0,0,0,0,657,753,0,0,0,0,941,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,706,985,837,0,1861,0,0,0,0,0,0,0,0,0,0,0,0,0,0,292,933,0,0,0,0,0,\n0,0,0,0,767,0,0,0,0,0,0,0,641,0,0,0,1233,114,0,883,0,274,2008,0,1794,285,0,0,\n571,0,0,0,0,0,0,0,0,0,0,823,960,16,617,0,431,0,0,0,0,0,0,0,0,0,0,567,0,401,0,2,\n781,424,33,0,2006,0,0,274,0,0,1882,0,794,0,0,0,1848,0,0,0,0,0,0,448,47,0,0,0,\n1199,0,0,0,0,0,0,0,0,417,0,0,0,0,0,0,0,0,0,0,295,0,0,0,0,0,0,0,1019,0,0,0,0,0,0,\n0,0,0,0,0,0,0,620,0,0,0,0,464,0,0,0,0,208,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,442,0,930,0,0,0,0,0,516,68,0,0,0,0,0,1128,104,0,0,0,0,0,0,0,0,787,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,491,0,0,0,0,0,0,711,0,0,9,0,101,441,0,0,0,0,0,0,0,0,\n0,0,160,396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,679,326,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,1128,0,0,0,0,0,737,0,1796,0,0,0,0,0,0,0,0,0,0,0,0,338,574,0,0,\n0,0,0,1096,491,405,0,0,0,0,0,1081,0,0,0,0,0,0,0,0,0,0,0,0,0,1676,0,1207,0,0,0,0,\n0,0,969,354,0,0,0,0,598,0,297,0,0,0,0,0,0,0,0,1772,751,0,37,0,0,1828,0,0,0,0,0,\n0,0,0,0,257,191,582,0,0,0,0,0,0,790,0,0,0,0,0,47,0,0,0,0,0,0,0,449,306,1011,0,0,\n0,0,0,299,0,0,0,0,0,0,837,0,0,0,0,0,0,10,329,0,0,0,0,0,1320,0,0,0,0,0,0,158,657,\n0,1191,0,0,0,0,0,0,7,0,974,1939,0,1665,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,288,\n66,0,0,0,0,494,175,0,1643,0,0,0,0,0,0,0,0,570,750,719,0,0,0,0,0,0,0,0,0,0,0,0,0,\n13,0,0,1247,0,0,221,356,0,0,0,0,0,0,0,0,0,0,694,1809,0,0,0,0,0,0,0,411,0,44,31,\n0,0,0,0,669,0,673,0,0,0,0,0,0,0,0,0,1303,704,299,0,0,0,275,0,0,216,1761,0,0,0,0,\n0,0,0,0,0,0,0,1319,0,0,428,0,0,0,0,0,0,0,0,0,0,514,0,0,0,0,0,0,49,55,102,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,364,0,0,0,0,379,0,921,971,52,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1258,0,0,0,1058,0,0,0,0,0,656,0,0,0,0,0,144,0,0,0,0,0,0,0,0,0,0,\n0,1373,10,605,0,0,0,0,0,0,0,838,0,1012,0,0,0,0,0,0,0,0,0,0,0,0,0,0,154,365,0,0,\n0,0,0,0,0,0,0,340,0,0,0,0,0,810,0,0,0,0,0,0,495,0,0,0,0,0,0,0,0,0,261,0,535,248,\n0,358,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,567,445,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,697,0,0,0,1336,0,0,0,0,0,0,0,0,917,174,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,972,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,351,0,0,0,0,0,0,0,0,0,0,\n0,0,0,286,0,0,56,438,0,0,0,0,0,1950,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,738,0,0,0,0,0,\n0,0,0,0,0,969,2047,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,866,0,0,0,0,0,0,0,1467,0,0,0,\n0,0,0,0,0,0,0,0,0,0,972,0,355,0,0,0,116,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,267,189,104,0,0,0,0,1613,0,0,0,0,0,0,0,116,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,886,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,45,0,0,863,0,0,0,0,0,\n0,0,1953,450,1773,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,381,0,0,0,0,0,0,0,\n0,0,0,0,0,1142,0,1189,0,0,0,663,0,0,0,0,0,0,0,846,0,0,528,0,393,378,0,0,0,0,0,0,\n325,899,680,1880,0,1770,0,0,0,0,0,648,0,0,0,0,0,0,185,167,0,2046,0,0,0,0,0,0,\n249,1645,0,152,0,0,0,1733,0,0,0,0,0,1006,0,0,0,0,0,420,0,0,0,832,0,0,0,0,0,351,\n0,0,0,0,6,40,0,0,60,0,0,0,0,1354,745,724,0,0,0,0,0,0,0,0,772,1951,275,108,639,0,\n0,0,0,0,0,0,0,0,500,1758,0,0,0,0,0,0,0,0,0,0,0,1886,711,205,0,0,965,865,0,0,0,\n534,0,0,0,0,691,0,0,0,237,443,0,878,0,0,0,0,0,1410,0,0,0,0,0,0,0,0,0,0,0,0,0,\n995,0,0,0,0,0,0,0,0,0,0,0,0,0,578,0,0,0,0,881,0,0,0,0,0,0,0,0,822,0,923,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,924,0,0,0,665,0,0,0,0,0,1901,0,0,0,0,0,950,498,93,\n0,0,0,1451,0,0,0,0,0,747,828,788,400,184,0,198,0,0,0,0,0,0,0,0,0,0,0,994,0,0,0,\n0,0,0,0,0,615,320,0,0,0,978,843,905,0,0,0,0,0,0,0,0,850,974,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,509,0,0,0,0,0,273,0,0,0,0,0,0,0,0,0,0,0,0,0,\n201,0,0,0,1041,0,0,0,1040,0,0,0,0,0,0,0,0,0,693,234,774,0,336,0,1399,22,0,805,\n802,777,167,789,0,0,1705,0,0,0,0,0,0,0,0,0,0,0,10,13,11,0,0,204,264,0,0,56,0,0,\n1917,0,470,0,0,0,0,0,0,0,0,0,0,0,1198,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,715,0,0,1002,0,0,0,298,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,867,0,0,724,0,0,0,0,0,0,0,0,0,0,0,0,768,0,0,0,0,0,1066,0,0,0,0,67,0,174,948,\n0,0,0,0,0,0,0,0,0,0,0,0,0,764,0,0,0,0,75,137,0,756,0,0,0,0,0,0,1008,842,643,0,0,\n0,67,0,0,0,0,0,0,0,0,0,0,0,135,821,0,0,0,0,0,0,0,0,736,0,389,355,0,0,786,0,0,0,\n0,0,0,2044,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1030,0,0,0,1083,0,0,0,0,0,\n1226,0,0,0,0,356,319,8,389,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,474,0,0,0,427,\n0,413,0,730,0,0,0,0,0,373,0,0,0,0,0,0,0,0,0,799,0,0,0,1793,0,0,0,322,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,89,290,2,0,0,0,0,0,0,0,0,0,0,672,\n699,1860,0,0,0,737,0,0,0,1612,0,0,0,0,0,0,0,0,0,0,0,145,124,884,0,0,0,0,0,387,0,\n0,0,0,0,0,0,0,0,0,0,679,0,550,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1305,0,0,0,0,0,0,0,\n576,0,0,0,0,0,0,0,686,0,607,0,0,37,0,0,0,0,0,0,0,0,0,101,1726,0,0,0,0,0,958,0,0,\n0,903,0,0,0,0,147,0,0,0,0,0,0,0,0,0,0,0,367,0,0,0,0,690,0,705,273,0,0,887,0,0,0,\n0,0,0,0,0,0,0,0,90,0,0,0,0,0,0,0,908,0,0,0,0,0,0,0,1261,0,0,497,1235,0,429,0,0,\n0,0,904,0,12,125,0,0,0,841,0,0,0,0,0,860,946,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,768,0,770,160,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,271,0,0,0,0,0,0,0,719,0,699,581,0,0,0,0,0,0,0,0,0,0,862,304,0,631,0,0,0,0,880,\n1513,0,0,0,0,0,981,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,434,0,0,0,0,0,550,0,0,476,930,\n824,553,0,0,452,0,151,0,0,0,0,0,0,772,0,292,135,0,0,0,0,0,0,0,504,0,0,1089,0,0,\n0,0,0,0,0,0,0,0,0,783,0,0,0,0,0,0,206,393,0,0,0,0,0,0,0,0,232,912,0,0,0,0,0,977,\n0,0,716,98,0,0,0,0,0,733,0,0,0,0,0,0,0,0,19,0,0,0,0,668,0,360,0,0,0,0,0,0,656,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,726,0,0,0,0,0,0,0,0,0,0,0,0,72,0,0,1269,0,0,463,0,\n0,0,0,0,0,1454,0,1287,245,0,989,0,0,0,0,0,0,0,0,0,107,164,0,0,0,0,0,0,0,1061,0,\n0,0,0,2,484,0,0,0,0,0,0,0,1127,0,0,0,0,0,0,0,460,0,0,0,0,0,932,0,0,0,0,0,0,0,\n588,625,0,0,0,0,76,92,0,0,0,0,0,0,0,0,0,0,0,0,0,104,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n763,0,622,0,0,0,253,0,546,0,0,110,0,256,916,0,0,35,212,0,0,746,0,0,0,150,0,0,\n1466,0,0,0,1299,0,0,0,0,0,0,0,0,0,1518,0,0,0,0,0,0,0,0,0,0,0,0,0,1229,0,0,0,816,\n0,0,0,0,0,0,159,0,0,0,0,0,734,869,126,1716,0,0,0,0,0,0,202,232,0,0,0,0,212,0,0,\n0,0,0,111,1003,0,0,0,0,0,0,0,0,0,0,0,1712,0,0,216,0,0,0,0,516,0,0,0,0,0,650,0,0,\n0,0,57,99,0,0,0,0,300,574,0,0,0,0,1023,0,0,302,0,1871,0,728,252,0,0,461,0,0,0,\n323,0,0,0,0,0,0,775,461,0,0,0,0,0,0,172,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,73,727,0,1023,0,0,0,0,0,0,0,0,0,0,577,0,0,0,0,0,0,0,0,1037,0,0,0,0,0,0,\n0,0,280,677,0,0,0,0,0,0,0,0,0,0,0,799,0,0,0,0,159,0,446,1730,0,0,0,0,0,0,0,0,0,\n395,0,0,0,0,145,0,0,0,0,0,0,0,20,0,0,426,608,0,0,0,0,0,977,0,250,0,0,0,0,0,100,\n0,0,0,0,1982,0,0,0,0,0,476,0,0,0,0,0,0,594,76,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,447,0,0,0,0,526,0,0,14,1124,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,188,0,0,0,0,0,0,0,0,362,301,0,0,0,1743,0,178,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,831,0,0,208,202,0,0,0,0,0,0,0,1954,0,\n0,0,0,516,872,0,0,313,224,0,0,24,0,11,546,0,0,0,1937,242,241,46,0,0,0,830,1273,\n0,0,0,0,0,0,0,825,327,1006,0,0,0,0,0,1580,516,366,0,0,0,0,0,1736,0,0,0,0,0,0,0,\n0,0,0,0,1935,0,826,0,0,0,0,139,331,0,0,0,0,0,0,0,0,0,0,0,288,0,916,0,0,0,0,0,\n1888,0,0,0,0,0,0,0,1471,0,1570,0,394,0,0,0,0,0,0,0,1931,0,1719,0,658,228,0,0,0,\n0,0,374,0,0,0,0,735,0,0,0,0,0,0,323,498,0,1063,0,0,0,0,155,0,0,0,0,0,0,0,0,906,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1139,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,108,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,616,\n902,0,0,0,0,0,692,0,0,0,0,0,0,823,0,0,0,305,0,0,0,0,0,0,0,681,0,0,0,0,0,214,\n1004,0,0,0,0,0,0,0,23,0,0,1703,0,0,0,0,0,0,0,0,0,1443,0,0,19,714,0,0,0,0,64,737,\n0,0,345,1758,0,0,579,47,0,0,539,139,0,0,0,0,388,0,0,0,0,253,0,0,0,0,0,0,252,0,\n745,0,0,0,0,0,0,0,0,0,0,0,504,107,0,871,0,0,0,229,0,0,0,0,0,903,0,0,71,0,0,549,\n6,47,0,0,0,0,0,0,0,0,0,980,865,705,0,0,0,161,0,0,0,0,143,1331,0,0,0,1388,33,724,\n0,0,0,19,0,0,0,395,0,0,0,0,0,846,210,0,0,0,122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,937,497,0,0,0,0,0,718,0,0,0,0,0,0,0,1581,0,\n0,0,0,0,0,161,49,0,0,0,0,0,0,0,0,0,597,0,0,0,1094,0,0,0,811,908,0,0,0,0,0,0,0,0,\n0,0,1471,0,0,0,0,0,0,0,0,0,0,42,1935,0,0,0,2014,66,2007,0,0,586,0,0,0,0,0,0,0,0,\n0,28,1077,0,0,0,1221,0,0,62,0,0,0,0,0,0,0,0,0,0,1766,0,0,0,0,0,0,0,0,0,0,0,0,25,\n0,499,1388,0,0,97,10,0,0,0,0,0,481,0,0,0,0,0,0,0,0,0,0,37,134,155,486,0,1442,0,\n0,0,0,0,591,0,0,0,0,0,0,310,1173,0,0,0,0,409,1156,0,0,0,482,0,0,263,926,0,0,0,0,\n0,0,0,0,0,0,0,0,0,804,0,0,0,0,0,0,0,0,0,0,0,0,0,1265,0,415,0,348,0,0,0,1012,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,165,1803,0,0,0,0,0,0,0,408,\n0,0,0,0,0,0,257,1321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1138,0,0,0,249,0,\n0,0,576,0,0,0,0,231,0,0,0,288,0,0,0,0,0,0,0,0,0,433,1487,569,1678,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,87,0,0,0,0,0,779,538,0,0,0,413,0,0,0,\n0,0,0,0,0,0,0,495,0,0,0,0,0,191,54,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,530,567,\n0,0,0,0,0,1484,0,0,0,0,0,0,815,609,0,0,0,0,0,484,0,0,0,0,0,0,0,0,0,0,900,0,0,0,\n0,1335,0,1724,0,0,0,0,0,0,0,0,0,0,0,640,0,0,0,0,0,0,0,0,0,0,0,1831,0,0,0,0,0,0,\n0,0,0,0,0,0,0,474,0,0,0,0,0,0,0,0,0,1103,0,1504,655,1034,0,0,0,0,0,305,0,0,0,0,\n0,0,0,0,0,1236,0,0,429,217,0,0,0,0,739,278,0,0,0,0,0,0,0,708,0,0,0,0,0,1840,233,\n0,0,0,0,0,0,0,0,2017,0,0,0,0,0,1488,0,0,0,1590,0,0,0,0,0,1800,28,0,0,0,0,0,0,0,\n0,0,45,0,36,0,22,1442,378,0,0,0,0,0,0,1507,0,0,0,0,0,0,0,0,0,0,39,0,0,1054,725,\n1955,0,2036,0,0,0,0,0,0,0,0,0,0,896,1871,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,2046,0,\n0,0,0,17,712,0,617,55,320,271,0,0,0,0,0,0,0,0,0,445,0,184,103,0,0,0,0,0,0,0,0,\n659,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n337,0,0,0,506,0,0,0,0,0,843,77,0,458,0,0,0,0,0,1420,382,109,142,330,0,0,0,0,0,0,\n0,0,0,0,0,0,87,0,0,0,492,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1239,0,0,0,0,0,0,\n211,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1049,0,321,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,1985,0,0,122,0,0,234,0,0,0,1098,0,0,0,0,0,0,549,253,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,522,131,0,0,149,0,0,0,0,0,0,0,0,0,0,0,0,0,0,507,0,0,0,0,811,630,0,0,0,343,\n0,0,0,0,0,448,591,455,0,1381,0,0,0,0,0,0,0,575,0,0,0,0,0,1175,0,0,0,0,0,0,0,0,0,\n653,0,0,0,1761,0,1198,0,0,0,0,297,1127,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,678,0,0,\n164,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,35,0,45,0,0,0,0,0,121,0,0,0,0,0,0,\n0,0,125,0,0,0,1622,0,0,0,0,0,721,145,0,0,0,970,792,0,0,0,715,0,0,0,0,0,1999,0,0,\n74,531,0,0,65,0,0,0,105,220,0,0,0,0,0,0,0,960,0,0,0,0,0,0,428,19,0,0,401,96,0,0,\n0,0,0,1595,116,0,1021,0,0,0,0,0,750,1961,0,0,148,0,0,0,0,0,0,0,0,0,0,0,0,0,75,0,\n0,1383,0,0,0,0,0,0,0,0,0,0,0,0,0,0,779,0,0,0,0,0,0,0,0,598,0,424,0,0,0,0,0,0,0,\n1222,0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,133,0,0,0,0,187,0,8,0,0,0,0,0,\n0,0,429,0,685,0,0,0,0,0,0,0,0,0,0,0,132,472,0,0,0,0,0,0,0,0,0,938,0,0,874,0,0,0,\n0,0,774,0,0,0,0,0,92,0,0,0,0,0,0,830,701,0,0,0,0,0,426,350,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,603,59,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,441,163,4,0,\n0,0,0,0,0,0,0,0,806,0,0,0,0,0,0,233,0,0,0,0,1994,0,1739,0,0,393,0,47,1038,0,0,0,\n309,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,363,0,0,0,175,0,0,0,0,0,0,0,666,\n0,0,1675,0,1600,0,0,0,808,0,0,0,0,0,0,0,0,0,0,0,280,54,0,0,0,0,0,0,0,0,421,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,249,0,0,103,254,0,262,1,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,1630,0,0,0,0,0,0,0,0,0,0,0,0,0,671,972,989,0,0,\n0,0,0,0,0,889,0,0,0,1382,0,0,0,0,0,0,0,775,0,0,0,0,0,0,0,0,0,0,388,202,0,0,0,0,\n16,560,0,0,0,841,0,0,566,0,0,0,938,0,0,0,0,0,0,0,0,0,0,912,0,0,0,1361,0,0,0,0,0,\n0,618,236,0,1854,0,0,318,190,0,1376,0,0,0,0,0,0,0,349,0,0,0,0,951,1972,0,0,0,0,\n0,0,344,0,0,0,0,0,0,0,0,850,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,163,85,0,487,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,145,0,83,0,0,1013,0,0,0,1922,0,0,169,557,66,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,1193,82,0,352,454,57,0,0,1333,396,107,0,370,0,0,0,0,0,0,0,0,0,204,0,0,0,\n0,0,1706,0,0,0,0,0,0,0,0,0,0,0,0,394,1204,0,0,0,0,0,1007,0,0,0,1696,0,1519,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,981,0,0,0,0,1072,0,0,0,712,0,1629,0,0,0,0,0,0,0,728,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1271,0,0,0,1608,16,0,0,0,0,485,0,0,0,0,0,0,\n153,27,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1991,0,0,0,0,0,0,0,0,52,0,21,0,\n0,0,0,0,0,0,0,0,819,0,0,0,0,0,917,0,0,0,0,784,0,0,0,0,135,0,0,0,0,0,454,0,0,0,0,\n0,0,0,0,0,852,1719,0,0,0,0,0,852,0,0,0,0,0,952,0,0,0,0,568,0,0,0,0,0,448,0,0,0,\n67,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1826,657,0,729,666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n669,0,0,0,0,0,0,0,402,0,0,152,0,0,0,0,912,0,0,0,0,0,0,51,320,0,445,0,0,0,0,308,\n0,0,0,0,0,386,0,0,239,0,0,130,83,0,143,0,348,0,0,0,0,0,0,0,958,0,0,0,0,0,210,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,430,0,0,0,0,0,0,0,0,0,0,0,0,7,213,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,801,0,0,0,0,0,0,0,0,0,936,0,108,0,0,\n0,0,0,0,0,0,0,885,587,219,398,364,0,1165,0,0,342,241,303,0,0,0,0,0,0,0,0,0,0,\n1454,0,0,0,0,0,0,0,0,0,0,254,562,0,786,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1294,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,493,216,0,0,0,0,219,341,0,0,0,0,0,\n0,0,0,0,0,130,1734,154,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,701,604,0,0,879,0,195,\n666,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1669,0,0,0,1791,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1228,0,0,0,0,0,623,0,0,0,0,0,0,0,798,0,0,0,0,0,0,0,0,0,0,0,0,84,\n122,0,0,0,837,0,0,0,0,0,0,1013,0,0,577,0,0,0,460,932,0,0,0,0,0,0,0,0,0,0,0,31,\n131,0,0,0,605,0,0,0,1246,0,0,0,0,68,278,165,307,781,0,0,0,0,0,0,33,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,1113,0,0,720,1953,203,0,0,0,0,0,0,0,425,326,0,0,0,0,0,\n0,0,0,0,0,241,1316,0,0,0,0,0,416,0,0,0,1300,0,847,0,0,662,358,0,0,0,0,839,1823,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,654,1522,0,0,0,0,0,0,163,0,0,0,0,0,314,978,0,0,0,\n601,0,0,0,0,0,946,434,0,0,0,402,411,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,1467,\n410,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,677,0,0,0,0,0,0,0,0,0,0,0,0,70,0,0,0,0,1405,0,0,0,0,0,0,108,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,777,0,0,0,0,0,747,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,505,0,326,0,0,164,628,654,0,0,0,\n37,32,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,668,152,0,0,0,0,0,0,0,0,0,0,0,581,\n0,0,0,0,44,126,89,0,0,0,0,0,0,0,0,1531,0,0,0,0,0,0,0,0,203,1167,0,0,0,0,0,0,0,0,\n531,1232,0,0,0,0,0,943,0,670,231,880,0,1617,0,0,0,1957,0,0,0,0,0,0,0,975,0,0,0,\n0,0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,0,0,421,0,0,14,834,0,0,0,0,0,0,0,0,0,0,0,0,\n465,0,0,0,0,0,834,688,413,855,0,0,0,590,0,0,0,0,0,0,0,0,114,0,0,0,0,0,0,0,0,0,0,\n0,45,169,0,0,0,0,0,0,0,0,0,0,0,198,0,0,565,585,0,0,0,0,0,0,0,0,0,0,0,0,0,691,0,\n0,0,593,0,0,0,0,0,0,0,0,0,913,116,0,0,0,0,1360,0,0,0,802,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,673,308,0,709,1006,1895,0,228,0,0,0,1840,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,608,0,0,0,0,0,0,0,0,0,1573,0,2039,136,540,0,0,0,0,0,0,0,\n897,0,0,938,1878,0,0,0,0,0,0,0,0,0,1469,0,999,0,299,0,0,0,0,0,0,0,578,0,0,0,0,0,\n456,0,0,0,1679,163,693,0,0,0,0,0,0,48,755,0,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,\n1091,0,0,0,0,695,0,0,1464,0,0,0,0,0,975,0,0,335,0,0,1979,0,0,0,0,269,1566,630,\n396,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1815,634,0,0,0,966,0,0,0,0,0,0,0,9,\n412,0,958,0,0,579,382,0,212,0,0,0,0,965,681,0,0,16,0,0,0,0,0,0,0,0,0,0,0,0,655,\n0,0,0,0,67,0,0,0,0,0,0,751,0,0,0,0,423,231,0,0,1016,300,0,0,0,0,100,237,0,0,0,\n1370,0,0,0,1208,0,0,0,0,0,1219,129,0,0,0,0,0,0,0,0,0,0,0,0,0,0,199,0,0,427,0,0,\n0,0,949,665,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,712,0,0,0,0,0,1186,0,0,0,0,0,0,0,0,0,0,295,312,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n151,0,0,0,0,588,4,0,0,0,0,0,414,104,0,0,757,263,0,561,0,0,0,320,0,0,0,0,0,0,0,0,\n0,0,0,225,0,0,0,0,37,817,0,974,0,0,0,0,0,0,0,0,0,0,0,0,0,2026,131,235,16,0,590,\n1157,0,0,0,0,0,0,0,0,221,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,140,390,0,0,0,0,\n0,0,0,1144,0,0,0,464,0,0,0,0,0,0,0,0,0,0,0,0,204,407,303,1218,0,0,0,0,5,325,0,0,\n0,0,12,800,0,1783,0,0,0,0,0,0,0,0,0,0,504,621,0,0,0,0,0,0,0,0,0,920,0,376,0,0,0,\n0,0,218,580,0,768,454,0,0,0,0,0,0,0,0,0,0,0,0,676,0,0,0,0,0,0,164,0,0,0,0,0,0,0,\n0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,120,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,343,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,29,0,0,1812,0,0,8,0,0,0,21,1125,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,1327,0,0,0,0,575,1598,0,0,0,0,0,0,0,0,0,895,0,0,0,959,0,0,\n0,0,0,1759,173,0,0,0,0,266,261,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,1427,0,0,300,1033,0,0,0,0,0,0,0,0,0,0,0,584,0,0,0,0,52,734,\n0,0,217,239,0,1129,0,0,0,0,0,0,0,0,732,20,0,0,0,0,0,0,0,0,0,0,0,418,0,0,0,613,0,\n0,0,0,0,0,0,0,0,632,0,0,85,984,0,0,0,0,909,694,7,1109,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,167,0,0,0,0,280,62,0,0,33,0,0,359,186,980,0,0,0,0,0,0,0,0,0,0,0,585,0,0,0,\n211,0,0,336,145,0,1130,0,873,0,0,840,263,0,0,0,0,0,0,0,0,0,916,0,0,0,0,0,0,0,0,\n0,0,155,0,0,0,461,97,0,0,0,0,0,1356,0,0,0,0,0,0,0,593,0,0,0,0,0,1392,0,0,0,0,\n126,0,0,0,0,1179,0,0,0,0,0,162,0,0,0,0,0,765,0,187,0,1286,0,0,0,0,0,0,0,0,0,635,\n0,0,23,215,0,0,0,1306,0,0,97,716,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,657,0,\n0,0,0,0,0,0,0,299,0,0,0,0,0,0,134,0,0,0,0,0,0,0,0,0,0,0,658,1082,0,0,0,0,0,2002,\n0,0,0,0,0,0,833,248,0,0,0,0,0,1654,0,0,531,0,0,0,0,0,0,634,0,0,0,0,0,0,0,0,0,\n853,573,249,0,0,0,0,0,0,0,0,527,0,0,0,0,1419,0,0,0,0,0,0,20,49,0,0,0,992,0,0,0,\n728,0,0,0,0,0,0,0,0,0,0,0,0,497,1579,0,0,0,0,62,268,0,0,0,0,0,0,0,1201,0,0,0,0,\n0,0,0,0,0,0,0,0,495,193,0,0,0,0,106,0,0,859,0,0,23,0,0,0,0,0,0,0,813,925,0,0,\n223,613,953,0,0,0,0,0,0,0,0,666,0,0,0,0,0,0,0,0,0,670,0,0,40,216,0,0,0,0,0,0,\n259,0,0,0,440,1114,0,0,0,0,0,0,0,0,74,475,0,0,188,139,0,797,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,1572,0,0,0,0,39,0,0,0,0,0,0,0,0,0,0,0,0,1594,0,0,0,0,0,0,0,290,0,232,\n0,0,887,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,14,0,0,0,0,0,741,0,0,0,992,0,\n0,0,0,0,0,0,0,111,0,0,425,0,0,0,0,0,789,0,0,0,1593,0,1768,0,0,233,0,0,0,0,943,0,\n0,0,0,0,0,0,955,225,245,0,0,0,0,0,0,241,0,0,0,0,1943,0,0,0,1284,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,709,0,0,0,0,0,0,554,0,0,0,0,0,0,0,0,1564,0,0,0,\n443,0,0,0,0,0,0,280,0,0,0,0,0,0,0,0,729,0,0,0,348,0,0,0,0,0,0,0,758,848,298,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,829,1422,189,121,0,0,632,812,0,0,556,0,0,0,0,0,436,172,\n530,844,232,984,0,0,0,0,0,0,0,0,0,0,147,0,0,0,0,0,0,0,0,537,0,0,0,0,0,859,0,0,\n842,0,0,0,0,0,0,0,0,0,0,1291,0,0,0,0,0,0,0,0,0,0,0,1482,612,392,0,0,0,262,31,0,\n0,0,0,0,0,0,0,0,0,753,549,0,0,0,0,0,0,696,0,0,0,0,0,0,0,834,0,0,0,0,0,771,0,0,0,\n0,0,0,0,0,0,0,0,0,0,921,0,0,0,674,0,0,0,0,0,0,0,0,0,0,308,444,0,0,0,0,0,0,805,\n180,0,0,278,271,0,0,214,505,0,1215,0,0,0,0,0,0,387,271,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,1645,42,92,0,459,0,0,330,1557,0,0,0,0,0,0,0,0,113,18,0,0,0,\n1742,0,0,0,965,0,0,0,0,0,0,0,0,0,0,0,0,0,182,0,0,65,0,0,0,0,0,0,0,0,0,0,0,0,973,\n0,0,0,0,0,328,0,0,588,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1786,\n0,0,962,1985,0,0,0,308,508,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,588,0,0,0,0,0,0,614,793,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,290,0,0,0,0,0,0,0,0,0,0,1136,0,0,0,0,0,0,0,0,0,0,796,719,0,0,\n326,210,0,0,0,701,758,472,0,0,0,1947,278,1079,0,0,0,0,0,0,497,41,0,0,634,46,961,\n0,810,524,0,0,33,0,0,0,0,0,0,0,0,0,0,0,0,532,0,997,0,0,0,0,0,0,0,0,0,0,0,1301,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1298,0,671,0,0,0,306,0,0,0,0,0,0,0,0,0,0,\n693,1823,0,0,0,759,0,0,0,0,0,1932,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,182,0,0,0,1964,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,521,0,0,0,0,0,0,424,857,0,0,0,0,671,328,0,\n529,0,0,0,0,0,716,0,1509,80,67,0,0,0,0,59,141,0,0,0,0,0,0,783,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1498,0,0,0,0,343,430,803,1183,677,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1357,53,0,0,0,0,590,0,0,0,0,0,0,0,0,0,0,\n0,0,0,329,0,0,0,0,0,0,0,469,0,0,0,0,0,0,0,0,0,0,460,0,0,1743,0,0,963,340,0,0,0,\n0,0,1603,0,0,250,0,0,0,0,0,646,218,0,1794,0,0,0,571,0,455,0,0,0,1012,0,0,0,0,0,\n0,0,0,0,0,0,0,597,161,0,349,0,524,0,0,0,0,0,0,0,0,0,0,0,0,322,432,0,0,0,0,0,0,\n325,223,0,0,0,0,0,566,0,0,0,1394,481,436,0,48,457,610,756,618,0,0,0,755,0,1217,\n0,0,0,0,0,197,0,0,0,0,0,0,0,0,0,0,0,0,0,0,544,492,107,414,0,0,0,0,0,0,0,0,0,0,0,\n1007,0,0,0,0,5,0,0,1580,0,0,0,0,0,0,0,0,0,0,0,0,0,673,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,1843,0,0,0,0,0,0,0,0,0,165,0,0,0,0,0,0,809,885,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,498,0,0,0,306,9,0,0,0,0,0,0,0,437,721,146,0,0,0,0,0,0,0,0,0,0,0,177,0,0,0,0,\n0,0,0,1377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,200,0,959,0,0,0,1928,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1435,0,481,0,0,0,0,0,0,142,84,0,0,0,0,0,\n1015,0,0,0,315,0,0,0,0,0,0,759,0,0,0,0,0,0,0,0,712,0,0,0,1722,0,0,0,0,0,0,0,0,0,\n0,0,0,222,0,985,1414,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1273,\n538,706,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,0,0,0,0,1781,0,0,0,0,0,431,97,665,42,\n237,0,0,0,264,0,0,213,0,0,0,0,0,0,0,455,0,0,0,906,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n624,0,574,0,0,0,0,0,0,0,0,0,0,0,0,354,0,0,0,1558,0,0,0,0,0,0,0,0,0,0,0,0,0,0,68,\n235,723,1813,0,0,0,957,0,830,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,496,0,0,0,0,0,0,0,\n547,239,88,0,0,0,0,0,0,0,0,0,1310,0,0,0,0,0,0,0,0,80,1076,0,0,118,0,0,0,479,274,\n0,0,0,0,0,0,0,0,0,0,0,497,0,0,669,261,0,0,0,0,13,0,0,0,0,0,0,791,250,642,0,0,0,\n1429,939,949,0,0,0,0,0,0,0,0,0,0,0,0,0,818,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,982,330,0,0,0,0,545,0,0,0,0,0,0,947,0,1188,0,0,0,0,0,904,0,0,0,0,0,1372,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,693,377,0,0,0,0,0,0,0,0,0,0,0,0,0,0,695,0,0,\n713,386,0,0,0,0,128,1575,0,0,0,0,0,0,424,893,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,904,0,0,0,0,0,552,322,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28,1808,49,0,0,0,0,\n1832,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,421,0,0,442,415,0,0,289,\n0,0,0,0,0,206,110,0,0,0,0,0,205,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n19,1539,0,0,0,0,0,1340,0,1194,0,0,0,0,0,0,0,0,549,0,0,0,0,0,0,0,0,1720,0,0,0,0,\n0,0,0,0,0,319,0,0,0,0,112,1180,0,0,0,0,0,0,0,0,0,0,0,967,0,0,0,0,0,0,0,0,0,1940,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,735,0,0,0,0,0,0,0,0,0,897,132,0,0,0,0,0,0,0,\n0,0,0,38,838,0,0,0,379,218,8,660,1017,0,0,0,0,0,0,111,387,647,877,0,0,53,790,0,\n0,0,0,0,0,0,0,458,0,0,0,0,0,0,954,0,0,0,394,0,1367,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,882,0,0,0,0,0,0,0,1409,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,38,124,342,199,0,0,0,0,\n0,0,0,0,0,0,724,628,0,0,0,0,804,266,0,0,0,0,0,208,0,79,0,0,0,0,0,0,0,0,741,0,0,\n0,0,0,0,0,0,0,0,606,0,1494,821,1553,0,0,135,405,0,0,178,100,0,0,0,0,0,0,0,0,0,0,\n0,0,0,481,0,0,0,1378,0,0,0,0,0,0,0,0,0,0,0,0,0,791,33,1227,857,0,467,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,447,0,0,0,0,0,0,86,128,0,0,0,0,0,0,587,0,0,0,692,1018,0,\n195,0,0,0,0,0,0,0,1546,0,0,0,0,0,0,0,0,0,0,0,684,0,0,345,0,0,0,0,0,0,365,0,1683,\n0,0,472,0,433,0,0,0,0,0,0,0,28,0,0,0,997,0,705,3,0,0,0,0,0,0,0,0,0,229,0,0,0,0,\n102,0,0,0,0,866,1022,0,0,0,0,0,0,0,0,0,55,0,115,0,0,0,0,933,0,0,0,0,0,0,0,702,0,\n0,0,0,0,0,0,1728,26,484,0,0,0,185,618,417,0,803,0,0,0,0,0,0,0,0,0,0,0,1262,0,0,\n0,0,0,0,0,0,0,0,0,0,0,633,0,0,0,0,0,0,0,0,0,0,0,0,0,479,262,0,0,0,0,0,0,830,0,0,\n0,0,26,70,0,0,0,0,0,0,0,0,217,0,640,51,0,0,360,1586,0,0,0,0,0,652,0,0,0,0,0,766,\n0,0,0,0,298,737,0,0,0,0,0,0,0,0,0,0,655,222,906,0,0,1013,991,2009,0,0,0,0,503,0,\n0,0,216,154,0,0,0,716,0,844,0,0,0,0,621,252,0,0,0,0,748,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,103,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,576,0,0,0,648,0,0,0,331,0,0,0,\n0,0,0,0,0,0,0,0,0,632,0,0,0,518,107,0,0,0,0,0,0,0,0,851,0,0,0,0,504,0,0,0,0,0,0,\n0,0,0,0,0,0,7,883,0,0,0,0,0,0,0,922,0,0,0,0,0,0,0,0,91,993,0,0,0,0,0,0,200,131,\n10,0,0,0,0,0,0,0,0,0,0,0,0,0,365,1433,0,0,0,0,28,103,0,0,798,1013,0,0,0,0,0,0,0,\n0,39,1925,0,853,0,0,271,519,0,0,0,0,338,0,0,300,470,419,0,0,0,0,0,0,836,0,0,0,0,\n0,0,1937,0,0,0,0,0,393,0,0,357,0,0,0,0,0,703,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,387,0,0,0,0,0,0,75,708,453,1351,0,303,0,0,772,0,0,0,0,0,0,0,0,749,0,0,\n0,0,0,0,0,0,0,0,0,0,0,1065,0,0,717,226,0,0,0,0,0,890,431,626,0,0,0,0,706,0,0,0,\n51,698,0,0,0,0,0,0,0,0,0,0,0,828,0,0,17,0,0,0,0,1929,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,84,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,871,498,0,101,1793,0,0,0,0,0,0,435,0,\n0,0,0,0,966,0,129,1644,0,0,0,0,0,0,0,0,0,0,0,0,0,997,502,0,0,0,0,0,0,0,0,0,0,0,\n0,823,0,1927,0,0,0,0,98,1756,0,0,0,0,0,0,0,0,0,0,0,0,8,0,160,1046,0,492,0,0,0,0,\n0,0,129,45,0,0,0,0,0,0,353,558,0,0,0,0,0,785,0,0,0,1145,189,0,0,0,26,353,0,0,0,\n0,0,2024,0,0,0,606,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,32,855,0,0,0,0,0,0,0,0,0,0,0,\n0,0,2011,0,0,5,4,0,0,461,764,0,0,0,1449,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1445,0,0,\n0,1168,0,0,0,233,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,0,0,216,0,0,0,286,0,0,0,\n3,0,0,0,723,536,0,0,0,0,0,285,0,0,0,560,0,0,0,0,0,690,0,0,0,0,0,1246,0,0,63,0,\n33,0,0,0,0,0,520,1862,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,0,0,554,0,0,0,0,0,1001,0,\n0,0,0,0,446,0,0,0,0,0,0,0,1313,0,0,837,636,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,278,\n0,0,0,0,0,0,0,0,868,0,0,0,0,1010,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1231,0,304,0,506,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,26,0,93,1408,794,\n843,704,0,285,114,485,898,145,0,19,2035,0,0,0,1933,0,0,0,0,0,0,0,1728,0,0,0,0,0,\n0,0,0,746,0,0,0,0,0,0,0,995,1964,0,0,0,0,0,0,0,0,0,0,0,1550,0,874,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,1018,0,0,0,814,126,0,0,1264,0,0,814,955,0,0,0,0,0,0,\n0,981,0,0,0,0,0,0,0,0,915,56,0,0,100,0,0,0,0,0,0,0,0,0,638,0,0,0,0,738,0,0,0,0,\n0,0,0,0,0,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1112,0,0,214,0,0,0,133,0,196,\n168,0,0,0,0,0,1152,0,1245,0,0,538,169,871,1816,0,0,413,133,0,0,0,978,0,0,43,93,\n371,0,0,0,0,0,0,526,25,0,754,335,0,0,0,0,182,0,0,0,0,0,0,0,0,0,0,0,39,601,0,0,0,\n0,0,0,0,181,370,0,0,1652,358,0,0,0,0,0,0,0,0,0,176,286,0,788,0,0,0,0,0,1223,780,\n254,1003,896,0,0,0,1447,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,744,0,0,0,0,0,126,0,\n41,788,0,0,0,629,0,0,0,0,0,0,0,0,0,0,0,293,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,420,37,1900,0,0,0,0,542,1570,957,0,0,0,0,0,0,\n0,373,31,0,0,0,0,125,325,0,0,0,0,0,0,323,0,0,1547,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1216,0,0,0,0,0,0,198,1905,629,15,0,0,0,0,0,0,20,75,543,1353,0,0,0,533,0,0,6,0,0,\n0,0,0,0,538,0,0,0,0,0,0,0,0,0,0,0,338,0,0,0,0,11,0,0,0,284,659,0,989,0,0,0,0,0,\n0,0,0,0,848,0,0,507,0,0,0,0,0,0,0,0,188,991,884,0,0,0,0,60,959,0,0,0,0,0,1653,0,\n0,922,337,0,638,0,0,500,0,0,0,0,0,0,0,0,0,0,0,166,0,0,0,0,0,0,0,0,0,0,0,0,418,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,760,0,0,0,0,0,0,1277,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,770,0,0,0,0,0,0,0,243,89,0,0,0,0,0,0,0,0,0,1396,0,\n560,0,0,3,1658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,586,0,0,1271,0,0,0,505,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1947,\n41,445,0,0,0,0,0,0,0,0,57,189,0,0,371,0,0,0,0,552,0,883,0,923,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,875,0,0,0,1788,49,0,0,0,0,0,\n0,0,0,0,0,0,661,0,0,1945,0,0,0,0,0,794,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,1135,0,0,0,745,0,0,0,0,0,0,0,84,0,0,0,0,0,0,0,410,0,976,0,0,0,0,0,703,0,0,\n0,0,0,0,187,322,0,0,0,227,0,0,0,0,560,0,31,1395,0,0,0,0,0,466,0,0,0,0,643,167,0,\n0,0,1428,0,412,0,0,0,0,0,0,0,0,0,1118,562,0,0,0,0,0,256,0,0,0,0,0,0,1771,0,0,0,\n0,0,1190,132,0,66,0,0,0,0,0,0,0,0,0,0,317,0,0,0,63,0,0,0,0,0,0,0,1475,0,0,0,0,0,\n0,0,288,0,0,0,0,608,0,0,0,0,0,0,0,0,1225,0,1189,0,0,0,0,0,0,0,1468,0,0,0,0,0,\n689,120,0,0,0,0,0,0,0,1,0,329,0,0,0,0,226,0,0,0,0,0,1855,0,0,461,0,0,0,0,1346,0,\n0,0,0,0,85,0,0,299,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1171,0,0,\n0,980,0,0,0,0,0,0,0,0,637,279,0,0,0,0,0,293,0,0,0,0,528,17,0,0,0,0,5,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,48,0,0,0,0,0,0,0,601,0,0,0,0,0,0,779,0,\n196,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1322,737,752,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,412,192,80,0,0,8,1470,0,0,0,0,0,0,0,0,0,873,0,0,0,0,0,835,0,0,0,0,256,\n38,986,0,0,0,0,0,0,0,0,0,91,257,278,911,0,0,0,0,0,0,0,0,749,151,0,0,0,0,0,0,0,0,\n0,0,0,0,989,0,0,990,0,0,90,194,0,0,0,0,0,425,0,0,0,0,0,774,0,0,0,0,0,0,0,0,0,0,\n646,827,752,0,0,0,662,0,22,21,0,0,0,0,0,0,95,239,0,0,0,431,0,0,0,0,0,874,0,0,\n265,65,0,0,0,1350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1887,0,0,0,0,0,0,0,809,\n0,696,0,1074,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,630,0,0,802,0,0,0,56,776,0,\n970,0,0,797,0,0,0,0,0,400,0,0,1951,0,0,41,0,11,118,0,0,0,0,0,0,0,0,251,615,0,0,\n0,1044,0,0,0,0,0,0,0,0,0,0,0,225,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,370,0,0,0,0,\n104,48,209,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,930,0,0,0,0,\n0,0,0,0,0,0,0,1286,0,759,0,120,385,0,0,0,429,0,0,0,0,0,0,0,0,820,0,0,0,0,0,0,\n199,0,10,151,0,0,0,761,365,0,0,0,0,0,0,0,0,0,46,1086,0,0,0,0,11,1624,58,344,0,0,\n1008,1868,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,711,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,440,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,914,1913,0,958,0,885,0,0,0,0,0,0,0,0,0,0,0,\n0,0,847,276,0,302,65,0,0,0,510,0,1514,0,0,0,0,0,0,152,291,0,0,0,0,0,0,0,0,0,0,0,\n0,282,589,0,0,0,0,0,0,0,0,0,0,0,0,0,130,0,0,463,42,0,0,0,0,0,372,0,0,0,0,0,0,0,\n0,0,680,0,0,0,0,0,0,0,0,977,1997,0,0,0,810,0,0,0,0,0,0,0,0,0,1390,0,0,0,644,0,0,\n867,982,0,0,0,0,0,0,0,540,0,123,0,0,0,1978,0,0,0,0,789,623,0,1723,0,1220,0,0,0,\n0,0,0,0,480,0,0,0,0,0,0,0,0,0,0,0,888,0,0,0,0,0,0,0,0,0,0,0,0,299,1995,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,788,179,0,0,0,0,0,0,431,156,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1373,39,80,196,0,0,507,0,0,0,646,0,0,0,0,\n0,1214,0,0,0,0,926,0,0,0,1,114,0,0,0,0,0,446,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,490,0,0,0,491,0,1584,0,0,507,250,0,0,0,158,\n10,362,1,0,0,0,0,0,0,0,0,0,408,228,860,480,0,779,0,0,0,557,0,0,142,197,0,0,0,0,\n0,0,0,0,0,0,0,1490,11,378,316,1057,0,0,18,579,299,1546,0,177,0,0,0,0,0,0,0,0,0,\n411,0,0,0,0,727,439,0,0,0,0,0,1528,0,0,0,0,0,0,58,0,482,0,0,0,505,1952,0,0,0,0,\n0,0,0,0,0,0,0,242,0,0,0,0,0,0,0,953,0,0,0,0,802,0,0,0,0,0,0,0,0,0,0,290,0,0,791,\n52,0,0,0,0,0,0,0,0,0,0,0,112,0,0,0,0,0,1028,0,0,138,0,0,0,0,1811,0,0,0,0,0,0,\n934,1821,0,0,0,0,371,38,0,0,0,1296,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,723,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1330,0,0,0,0,0,0,0,1255,296,109,0,0,0,0,0,660,0,0,0,0,270,591,0,\n0,0,0,0,0,0,1090,81,0,0,0,0,391,0,0,0,0,249,322,0,0,0,0,0,0,0,1412,0,0,0,0,0,0,\n0,0,0,0,526,632,0,0,0,0,0,0,235,144,0,0,0,0,0,940,0,0,0,52,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,309,196,0,0,0,0,0,1912,0,1290,0,686,0,0,625,0,0,0,0,0,0,0,0,0,0,0,412,0,\n0,0,0,43,0,0,0,0,11,967,758,0,0,0,0,0,0,0,0,0,0,0,0,0,0,220,0,0,0,0,0,0,0,0,0,0,\n873,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,890,0,0,2,0,0,0,0,0,0,0,0,1774,\n393,263,0,0,0,0,0,0,818,456,0,0,251,178,393,97,0,0,0,0,0,674,168,0,0,0,0,0,0,0,\n159,1639,0,0,0,0,0,0,0,0,59,934,0,191,0,0,0,0,346,165,0,877,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,128,0,0,0,0,0,0,1297,0,0,0,0,0,0,164,0,0,0,15,132,241,1073,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,228,324,53,0,0,910,0,0,0,0,0,0,0,0,734,705,\n217,73,0,0,0,0,0,0,0,0,636,389,0,1409,0,0,0,0,0,893,0,0,0,0,21,0,0,0,0,0,0,0,0,\n0,0,0,0,0,721,0,0,0,959,0,0,0,0,1433,0,0,0,0,0,0,0,0,0,0,0,0,174,189,0,0,0,0,0,\n0,0,0,0,0,22,2,0,0,815,354,0,0,0,0,425,0,411,60,13,1611,0,0,0,0,0,0,0,0,0,0,0,0,\n0,1478,596,0,0,398,0,50,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,192,1159,0,0,0,0,0,\n592,223,0,0,0,0,0,0,0,245,64,0,0,0,0,278,0,604,0,0,1502,265,0,0,0,0,0,0,0,310,\n1763,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,129,0,0,0,0,0,0,0,0,0,1356,0,0,0,0,0,0,0,\n0,505,0,0,0,0,0,0,0,1000,0,0,966,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0,\n0,0,0,0,0,0,0,637,0,0,0,0,0,0,0,0,0,0,0,0,0,0,590,0,0,0,0,280,0,0,0,1386,0,0,0,\n281,0,1064,0,0,0,0,0,917,0,0,15,555,0,0,1014,1883,0,0,0,965,0,0,117,33,0,0,0,\n801,0,0,0,0,0,877,0,824,0,0,0,0,0,0,0,0,0,0,0,365,0,0,0,0,0,0,774,7,0,430,0,0,\n231,360,0,0,0,0,0,0,0,0,822,740,0,0,929,1485,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,852,0,0,0,0,17,0,0,0,0,0,0,1001,0,0,0,0,35,831,0,0,384,457,0,0,0,1351,0,27,\n0,0,984,0,264,552,0,401,0,0,0,710,0,1211,0,0,11,205,0,0,0,0,0,0,0,0,0,0,0,0,5,\n579,0,717,0,0,1011,0,0,0,0,0,0,0,0,0,0,0,0,0,0,805,0,0,0,0,0,0,0,0,0,0,0,489,0,\n0,0,1024,0,0,0,0,0,0,0,0,0,892,0,0,0,0,0,0,0,0,0,0,0,0,473,0,0,0,659,864,0,0,0,\n0,0,0,152,819,0,51,0,0,0,0,0,0,0,0,0,0,130,0,0,0,0,0,229,0,0,0,0,674,0,0,0,0,0,\n0,0,0,0,770,52,79,0,0,0,1666,0,409,0,0,0,0,0,0,0,195,0,688,0,0,0,0,0,0,0,0,0,0,\n0,889,174,160,0,0,0,0,0,0,0,0,0,0,0,0,0,872,0,918,569,268,0,0,0,1224,0,1361,0,0,\n0,0,0,0,0,0,0,374,0,0,0,0,0,731,0,0,0,0,190,0,0,0,0,0,0,0,202,506,444,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,835,0,17,1526,0,0,0,0,0,477,0,0,\n994,1374,76,0,0,0,0,0,0,0,355,287,0,1389,0,0,0,0,0,0,455,384,0,0,0,264,0,0,0,0,\n0,0,0,0,0,0,0,0,1001,0,0,0,0,0,0,0,0,0,0,0,0,28,0,0,0,851,175,359,0,0,0,0,0,0,0,\n0,287,740,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,857,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n819,1402,0,0,0,0,0,0,174,224,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1649,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,655,573,0,0,0,0,0,0,0,0,128,351,0,0,0,0,0,0,\n0,0,0,0,0,918,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,687,0,0,0,0,0,0,0,0,0,1525,\n0,0,0,1009,0,0,0,0,0,0,0,340,0,0,0,0,0,0,0,0,0,0,861,0,176,0,0,0,0,0,0,0,0,0,96,\n985,0,615,0,0,0,0,0,0,0,1919,0,0,0,0,0,1131,0,0,0,0,0,0,0,247,0,0,0,0,27,23,0,0,\n0,0,0,0,0,0,38,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1015,0,0,0,0,0,1088,0,0,\n0,0,0,1585,0,0,0,0,227,0,0,0,478,360,0,0,0,95,0,0,0,0,0,0,699,0,0,0,26,0,0,0,0,\n1119,0,0,0,739,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,741,67,0,0,0,0,0,0,464,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,42,0,96,0,0,0,26,342,0,0,0,0,0,0,203,0,0,449,0,\n0,0,0,0,0,0,0,0,0,256,311,0,0,0,0,0,0,758,0,0,0,0,0,0,0,0,827,0,0,0,0,581,64,0,\n1047,0,0,0,0,0,288,0,0,0,0,0,1375,0,0,0,0,0,0,0,0,0,0,0,1309,0,0,0,0,0,0,0,0,\n376,12,0,0,0,0,0,154,0,1520,0,1753,95,502,0,0,0,0,0,0,0,269,291,1197,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,0,0,1341,0,1017,0,0,0,0,0,0,0,\n0,857,1810,533,0,0,1453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,836,211,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,19,0,156,0,0,0,0,1009,0,0,0,0,0,0,0,0,0,0,0,0,0,820,0,0,\n0,0,0,0,0,0,0,228,0,0,0,1131,0,1276,0,0,0,0,0,0,0,0,0,0,0,0,849,1792,0,0,389,\n291,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,525,0,0,\n0,453,0,0,0,0,666,0,0,0,422,0,355,0,0,0,0,165,0,260,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,865,0,0,0,0,0,0,0,1625,0,0,0,234,0,1383,0,0,0,0,0,0,0,0,306,0,0,0,802,1921,\n0,0,0,0,0,0,180,0,0,0,0,1312,814,0,0,0,0,0,0,0,0,0,0,707,0,0,0,1493,11,61,733,0,\n0,0,341,0,0,0,98,0,0,0,0,0,0,0,0,0,0,0,1014,0,0,0,0,0,0,0,142,102,0,0,30,0,0,\n823,0,1045,0,0,0,1930,0,1512,0,0,0,0,0,0,0,87,0,1243,245,0,0,0,0,0,0,0,48,68,0,\n0,0,0,0,0,0,0,126,77,625,938,0,0,351,0,0,0,174,1668,0,707,0,0,0,0,0,0,0,0,0,0,0,\n403,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,282,0,0,0,0,0,0,8,44,0,0,363,115,0,0,0,0,0,0,\n0,0,0,0,0,0,545,761,0,0,835,1254,0,0,0,0,930,1936,0,0,0,0,0,0,0,0,653,0,0,0,0,0,\n344,0,0,1483,673,185,0,0,460,93,753,478,0,0,0,0,0,1020,0,0,0,0,0,0,0,103,0,0,0,\n499,0,0,0,0,0,0,207,0,0,0,0,0,0,0,0,0,0,0,0,0,0,96,0,968,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,3,0,0,0,0,399,0,0,0,0,224,563,0,0,0,0,0,704,0,0,0,0,0,0,0,0,0,0,0,\n1559,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,861,0,0,0,0,946,333,746,0,0,0,0,0,\n0,0,910,0,0,0,0,0,0,0,0,0,0,0,0,0,652,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1393,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1514,0,0,0,0,201,0,510,717,0,0,528,0,0,0,0,\n20,0,0,0,1251,0,0,0,1163,0,0,0,307,0,0,0,0,0,1091,0,0,0,0,0,0,0,0,0,0,0,429,0,0,\n0,881,0,0,0,0,0,621,0,0,0,0,0,0,0,736,0,348,0,868,0,0,0,0,433,0,0,0,771,1495,0,\n0,0,0,215,0,0,0,0,0,124,0,0,0,0,0,0,0,0,0,0,0,55,0,0,0,0,0,0,0,112,62,0,856,270,\n0,572,0,0,0,0,939,0,0,0,0,0,0,0,352,0,0,0,0,0,0,0,0,0,647,0,0,0,0,10,0,0,0,0,0,\n0,0,220,0,0,0,0,0,0,0,0,0,0,0,0,0,464,0,0,109,0,0,0,1746,0,0,0,515,0,0,0,566,0,\n0,0,0,0,0,67,40,0,0,722,992,0,0,923,0,0,0,0,0,0,1145,0,0,0,0,0,0,0,0,0,0,0,568,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,247,0,0,0,0,645,0,0,328,0,0,0,0,0,0,0,0,0,0,0,0,\n1363,0,0,0,0,0,1280,0,0,0,0,0,0,0,0,0,0,7,28,360,162,0,0,0,0,0,0,0,0,0,0,0,764,\n0,0,833,862,0,856,0,0,0,0,0,0,736,92,0,0,948,1944,0,1479,63,590,0,0,0,1521,0,0,\n0,709,0,0,61,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,483,0,0,0,0,1213,\n0,0,0,0,29,1022,0,1712,0,466,0,0,0,0,0,0,0,0,0,0,0,0,0,731,0,0,0,0,0,0,171,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,241,0,0,0,0,0,0,0,0,0,0,0,964,2005,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,1100,0,0,0,954,0,0,0,0,0,0,0,0,0,1958,0,0,34,549,994,0,0,449,\n137,850,0,0,670,146,0,0,0,0,518,159,0,0,0,0,0,0,0,0,151,0,0,1027,0,0,0,0,0,0,0,\n0,0,0,983,0,0,0,0,993,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,141,501,0,0,0,\n0,0,0,0,0,0,452,0,0,0,0,0,0,0,0,0,0,233,149,0,0,0,0,0,0,0,0,582,0,0,0,801,0,0,0,\n0,0,0,70,0,0,369,0,36,0,0,0,0,0,0,0,204,721,430,241,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1817,16,1078,1021,0,0,\n406,0,0,0,0,0,69,0,0,0,0,0,1830,0,0,0,824,0,0,0,0,0,0,0,0,0,826,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,816,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1000,717,1845,0,423,0,0,\n0,0,0,0,0,0,510,0,0,1048,0,0,0,618,0,0,0,520,0,0,0,0,990,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,321,0,0,0,0,0,0,0,1135,0,0,921,0,0,0,24,397,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,856,0,0,0,139,282,981,0,288,0,0,0,1890,651,56,0,0,0,0,0,0,0,\n0,261,0,0,0,0,0,0,0,0,0,0,0,617,1403,0,1205,0,0,563,0,0,0,0,0,0,0,0,333,0,0,0,0,\n0,369,0,0,0,0,0,0,0,0,0,622,0,0,0,1407,0,0,0,0,0,0,0,0,0,0,0,0,624,160,0,363,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,619,0,174,292,0,0,656,616,0,0,0,685,0,0,0,0,0,0,0,0,0,0,0,0,0,647,0,0,0,631,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1267,0,0,0,1797,0,0,0,1684,0,0,469,0,531,\n1230,73,0,0,0,0,0,0,0,0,0,268,0,0,0,0,0,102,558,109,65,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,595,0,0,0,0,0,374,1832,0,0,0,0,0,0,16,0,405,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,881,0,1495,0,0,0,0,0,0,0,0,0,142,0,0,0,0,0,0,0,0,0,0,21,466,23,\n257,0,0,0,0,0,0,77,404,0,0,0,0,0,0,712,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,860,\n1848,0,0,652,629,0,0,0,0,13,377,0,1842,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1501,0,\n0,0,1906,0,0,0,0,0,0,0,0,0,0,0,0,0,491,234,171,0,0,0,0,631,1186,0,0,0,0,0,0,0,0,\n0,0,0,0,931,0,170,0,0,0,0,0,0,0,0,0,0,1587,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n765,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,424,0,0,714,0,0,0,0,685,0,0,0,0,0,\n0,285,0,0,0,0,0,0,429,0,0,0,0,0,0,0,0,0,0,71,18,0,0,0,0,0,0,0,0,0,0,116,828,0,0,\n0,0,0,0,289,0,0,0,0,0,0,0,0,675,0,0,0,1424,0,0,0,0,0,647,0,0,0,1334,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,36,209,0,0,0,0,0,0,0,342,0,0,0,928,0,0,0,0,0,1838,118,856,654,\n318,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,915,895,454,0,0,513,1425,0,0,\n0,0,0,0,791,0,153,0,0,0,0,0,0,796,909,445,345,0,0,0,0,0,0,0,0,578,0,0,0,1387,0,\n0,0,555,0,0,0,0,0,0,766,0,0,0,0,0,0,0,0,0,0,541,0,0,0,0,0,0,0,0,0,0,0,0,0,880,0,\n0,0,0,0,1506,0,0,983,0,768,0,0,0,0,584,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,737,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,226,30,426,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n117,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,462,0,0,0,385,0,398,0,0,0,0,0,0,\n0,0,0,347,0,0,0,0,125,1259,644,136,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,469,0,0,0,0,0,\n1367,0,0,0,0,0,0,0,0,0,0,0,719,0,0,0,0,0,0,0,0,0,0,0,0,0,1423,0,0,0,0,0,0,0,0,0,\n749,0,0,0,0,546,645,0,0,0,0,0,0,277,0,0,1275,0,0,0,0,0,0,0,453,536,555,0,0,987,\n1107,0,0,90,0,0,0,0,0,0,0,0,860,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n257,0,1768,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1071,0,0,0,0,0,0,0,0,0,0,0,0,0,83,\n0,835,0,0,0,0,0,0,0,2006,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,696,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,95,1718,0,0,0,0,0,0,0,26,0,550,0,0,0,0,0,901,0,0,0,0,0,\n0,822,0,0,122,0,0,0,807,0,0,0,0,0,262,0,620,601,34,0,0,170,0,0,0,0,537,0,0,0,0,\n0,0,0,0,0,332,0,0,208,1909,182,261,0,0,0,1721,0,0,0,0,0,933,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,1609,0,895,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,812,0,0,942,1916,0,0,0,0,\n0,0,0,778,0,0,0,137,0,1314,0,0,0,0,0,0,0,1661,0,0,0,0,0,0,0,1591,0,0,0,0,0,0,\n820,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,185,89,0,1160,230,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,63,29,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1740,0,0,177,\n170,0,1961,0,0,0,0,0,0,0,0,0,0,0,0,91,0,17,44,0,0,0,0,0,0,0,0,0,270,0,296,0,0,0,\n0,0,0,0,1523,0,0,0,0,0,0,0,0,0,0,757,7,0,0,0,0,0,0,0,0,0,0,530,588,0,0,0,0,0,0,\n0,0,0,786,0,0,0,0,0,580,627,88,447,57,0,0,0,0,0,0,0,0,845,735,0,0,0,0,0,31,15,0,\n460,521,12,424,0,0,0,1302,0,0,0,0,0,0,0,595,0,0,0,13,548,97,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,1472,452,1767,0,0,0,0,0,0,0,0,0,0,115,0,0,0,0,0,0,1543,0,1111,0,0,0,0,\n1,0,359,488,0,267,0,0,0,1983,0,0,0,0,0,0,0,1155,0,1575,0,1438,31,0,0,377,101,0,\n0,0,0,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,0,0,0,2023,0,0,0,0,0,1836,0,0,0,0,35,843,\n0,0,0,0,0,0,0,554,0,0,0,536,625,207,0,1371,0,0,0,424,785,336,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,896,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27,750,0,0,0,0,238,0,0,\n0,0,0,383,0,0,0,0,0,0,0,0,603,725,11,0,0,0,0,0,0,0,0,0,476,0,0,0,0,0,1552,0,0,0,\n0,0,0,0,680,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,435,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n1431,0,0,13,112,0,0,356,0,0,0,0,0,0,0,0,0,0,1963,0,0,0,1244,18,0,0,0,0,0,0,867,\n0,0,0,0,0,0,50,708,73,592,0,502,0,0,0,0,0,0,161,347,0,0,0,0,470,33,0,246,571,10,\n0,465,614,0,237,0,0,0,0,0,24,18,0,506,0,0,0,0,0,0,33,309,0,0,0,0,0,0,0,0,0,0,\n140,0,0,0,0,1056,0,0,0,1704,0,0,0,0,0,0,0,1036,0,0,0,0,0,0,0,0,0,1315,432,86,\n264,524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,107,0,0,0,0,0,123,927,0,0,957,1149,0,0,\n0,0,0,778,0,502,196,0,0,0,0,1312,0,0,0,0,0,0,0,855,0,0,0,0,0,0,0,0,0,0,45,1400,\n0,0,0,1003,0,0,0,0,0,1097,0,0,0,0,0,0,0,0,545,612,0,0,0,0,0,0,0,0,0,0,0,0,54,0,\n0,0,0,172,0,0,0,1029,0,0,0,0,0,0,0,0,0,568,0,0,0,732,617,0,0,974,94,989,733,0,0,\n0,0,0,0,1789,0,0,665,2015,0,0,0,0,0,0,806,287,0,0,0,0,0,1539,0,0,0,0,0,0,0,0,0,\n0,182,1563,0,0,0,0,0,0,0,0,0,484,0,0,0,0,0,1623,0,0,0,0,0,0,0,0,878,1833,0,1569,\n0,0,0,0,0,0,0,0,93,0,715,994,0,0,0,0,0,63,0,591,0,0,0,0,0,0,0,749,0,0,0,0,547,\n366,0,0,0,1747,0,0,0,0,0,0,0,89,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1463,0,772,\n893,0,0,0,48,0,0,941,0,0,690,1785,106,440,0,0,0,0,0,0,0,0,0,0,32,0,332,216,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,852,0,\n0,416,564,0,918,0,1764,0,0,3,0,0,274,0,0,0,0,501,0,0,0,0,0,0,0,851,743,0,49,0,\n879,0,0,47,0,0,0,0,0,0,865,0,1202,0,0,0,0,0,0,47,272,0,0,0,0,0,0,0,0,0,0,0,1455,\n0,0,0,0,891,1911,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,761,0,0,0,0,0,0,0,0,0,407,0,\n183,0,0,490,0,0,0,0,0,0,0,35,731,0,0,0,0,0,0,0,819,0,0,0,0,0,0,0,0,0,0,0,0,0,\n575,0,0,0,0,45,818,0,0,77,222,0,0,0,0,849,1880,0,0,0,633,0,1308,0,0,0,0,0,0,0,0,\n0,0,86,0,0,0,0,0,0,0,0,0,0,0,0,0,0,817,0,0,0,0,0,0,0,0,0,882,0,0,0,914,0,0,0,0,\n0,0,0,0,0,0,865,0,0,426,399,58,0,0,0,0,0,0,538,102,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,876,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,139,566,0,63,12,0,0,0,\n0,0,0,0,0,0,0,0,0,0,3,114,0,0,0,0,0,0,0,0,576,0,0,0,0,0,0,0,0,933,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,692,0,0,0,0,0,0,0,0,0,0,0,0,752,0,0,0,0,\n0,0,0,0,375,0,1011,0,0,96,0,0,0,0,0,0,0,0,0,148,0,0,0,0,0,0,0,0,0,0,0,337,56,\n666,0,246,394,0,0,0,0,0,0,0,0,437,0,0,0,506,0,0,0,0,1003,0,1163,0,328,0,0,0,0,0,\n0,0,0,1000,0,0,0,0,0,744,101,0,0,0,0,0,726,0,0,176,0,146,9,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,839,0,0,0,0,0,0,223,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,246,1931,29,0,0,1771,0,0,0,0,0,846,6,157,0,0,0,0,0,0,0,0,0,875,0,0,477,\n773,177,639,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1747,0,0,0,0,158,873,0,659,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,391,0,0,0,0,0,0,0,0,0,0,0,0,668,883,0,78,628,0,0,0,\n0,0,0,0,0,0,0,0,0,1460,0,962,0,0,0,0,0,460,0,0,0,0,0,0,0,0,0,0,0,0,0,0,34,199,0,\n0,0,388,474,0,271,0,333,608,0,0,0,0,0,0,49,0,988,0,707,617,0,0,0,0,0,0,0,756,0,\n0,0,0,0,1583,0,0,0,0,0,0,0,0,0,0,285,0,0,0,0,0,0,0,0,0,0,0,0,0,0,344,0,0,0,0,0,\n0,0,0,515,1709,0,0,0,0,0,0,0,0,404,0,0,0,0,500,0,0,0,0,0,0,0,0,0,68,216,0,0,0,0,\n0,0,0,488,353,0,0,177,236,0,0,458,490,0,0,0,0,0,0,756,1504,0,757,0,1735,0,0,108,\n598,0,0,0,0};\nBROTLI_INTERNAL const uint8_t kStaticDictionaryHashLengths[32768] = {\n8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,4,22,5,0,\n4,0,0,0,0,0,0,0,0,0,0,0,0,14,6,0,0,0,5,0,0,0,0,0,0,0,7,13,0,0,4,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,8,0,0,0,0,0,0,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,4,0,5,13,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,9,0,8,0,0,0,0,0,0,6,0,\n0,9,0,0,0,11,0,0,6,8,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,6,8,0,0,0,0,0,\n0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0,8,4,13,7,0,0,0,0,0,\n7,0,5,0,0,0,0,8,5,0,5,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,8,0,0,0,10,4,0,5,0,4,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,8,7,0,4,9,4,0,0,0,0,0,0,\n9,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,7,18,0,0,0,0,4,9,0,0,4,0,6,0,0,0,6,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,0,0,\n0,9,0,0,0,0,0,0,0,8,6,10,6,0,0,0,4,0,6,8,6,0,0,0,4,0,0,0,0,0,5,0,0,0,6,0,0,0,0,\n10,0,12,7,0,0,0,0,0,4,0,0,0,0,0,5,0,0,8,7,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0,\n0,0,0,0,6,11,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,6,10,0,17,0,8,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,6,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n7,0,0,11,4,0,5,0,0,0,0,0,0,0,0,0,0,10,5,0,6,8,5,0,0,0,0,0,0,0,0,0,0,11,5,0,0,0,\n0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,0,0,0,0,\n0,0,0,0,0,0,5,0,0,0,6,0,0,10,0,0,0,20,0,0,0,0,0,0,0,0,6,9,5,0,0,0,0,10,4,8,0,0,\n4,13,0,0,0,0,0,0,0,9,0,9,0,0,0,0,0,0,0,0,0,0,0,0,4,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,12,5,0,0,10,4,10,7,13,\n0,0,0,0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,19,0,0,4,12,6,9,0,0,0,0,4,0,4,11,0,0,0,0,\n0,0,0,12,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,\n0,5,0,0,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,9,6,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,\n6,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,5,0,0,0,0,14,4,0,0,0,4,12,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0,\n0,0,0,0,0,12,0,9,6,0,0,0,0,13,0,0,5,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,13,0,9,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,8,7,8,4,0,0,0,0,0,0,0,0,0,0,0,7,0,7,0,0,0,4,0,\n0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,8,4,0,0,0,0,0,6,0,7,0,\n0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,0,9,5,0,0,\n0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,4,0,0,0,0,0,0,0,4,\n12,5,11,0,0,0,0,0,0,0,0,0,8,7,0,5,0,0,8,7,0,5,0,0,0,0,8,0,0,0,0,7,0,4,10,0,0,0,\n0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n13,5,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,14,5,0,0,0,7,0,0,10,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,6,0,4,0,5,0,0,0,0,8,5,0,0,0,0,0,0,9,5,9,0,0,0,0,0,0,0,0,6,9,0,\n0,4,0,0,0,7,0,0,0,6,0,0,10,4,0,0,0,0,0,6,0,0,10,0,0,0,8,5,0,0,0,0,0,0,0,0,10,0,\n0,0,0,0,18,4,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,7,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,\n0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0,\n0,4,8,7,0,0,8,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,\n0,0,0,8,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,8,7,0,0,0,0,8,0,12,6,0,6,0,0,0,0,9,7,11,7,0,0,0,\n0,0,0,0,0,0,0,0,0,11,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,6,0,0,0,7,0,4,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,14,0,0,0,0,0,8,4,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,20,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,12,5,0,7,0,5,0,0,10,0,0,7,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,6,0,4,9,7,0,0,0,\n0,0,7,0,0,0,0,0,0,10,0,9,0,9,0,0,0,0,0,0,0,0,4,9,0,0,0,0,6,0,0,0,0,0,0,0,0,11,4,\n0,6,0,0,0,0,0,0,8,0,8,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,13,6,0,0,11,\n0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,6,18,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,11,\n4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,0,8,\n6,0,0,0,0,0,0,9,6,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,\n0,6,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,6,0,0,10,6,0,0,0,7,0,0,8,0,8,7,0,\n0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,18,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,\n0,0,0,8,7,0,0,0,0,0,0,0,0,12,0,12,0,0,0,11,6,0,5,0,0,12,0,12,5,0,7,11,6,0,0,11,\n0,0,0,12,0,0,4,12,7,8,6,0,0,0,0,8,5,0,0,0,0,0,0,0,4,11,0,0,6,0,7,0,0,0,0,0,0,0,\n5,0,6,0,0,0,0,8,0,10,0,0,0,0,0,0,0,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,0,10,0,0,5,0,0,12,6,0,0,0,0,0,0,10,6,0,0,0,0,8,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,5,0,0,0,0,11,0,10,6,0,0,8,6,0,0,0,6,0,7,10,6,0,\n0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,10,7,0,0,0,0,\n10,6,0,0,0,0,0,0,8,5,11,0,8,4,0,0,0,4,0,0,0,0,9,4,8,0,0,0,0,0,0,0,11,6,0,0,0,0,\n10,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,7,0,0,11,0,0,\n0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,13,0,8,6,13,0,0,0,11,7,0,7,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,9,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,\n0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0,0,4,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,\n5,11,5,0,0,0,0,0,0,0,0,0,4,0,7,0,6,0,0,0,6,20,0,0,0,10,7,0,5,14,4,0,0,0,0,0,0,0,\n0,0,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,\n0,0,6,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,11,6,15,0,0,0,0,0,\n10,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,9,7,13,0,0,0,0,0,\n0,7,0,0,8,6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,0,0,0,0,0,0,0,0,0,0,12,6,8,0,12,0,0,7,0,0,0,\n0,0,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,\n14,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,8,7,10,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,18,6,\n14,7,0,0,0,0,0,0,0,0,11,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,11,7,0,0,10,7,0,0,0,6,8,6,0,0,0,0,0,0,0,6,0,0,\n19,0,0,0,9,5,0,0,0,0,0,0,11,7,0,0,0,7,0,6,0,0,11,0,0,0,0,4,8,0,0,0,0,0,0,0,0,6,\n0,0,0,0,0,6,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,\n0,7,0,0,0,7,15,0,0,5,0,0,0,0,10,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n11,7,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,\n0,0,5,0,4,0,0,0,4,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,6,0,0,8,5,14,0,0,4,0,0,0,7,\n17,0,0,0,0,0,0,0,13,5,0,0,0,0,0,5,0,0,0,5,0,0,0,0,16,6,0,4,0,0,0,0,0,0,12,0,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,5,0,5,0,6,10,0,12,0,0,0,0,0,0,0,0,7,0,0,0,0,8,4,\n0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,0,0,0,8,0,0,6,0,7,0,0,0,5,0,6,0,4,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,22,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,18,0,0,0,9,4,0,0,8,0,9,7,0,0,0,0,0,0,8,6,0,0,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,7,0,0,0,6,0,0,14,0,0,0,0,\n0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,7,10,4,\n0,6,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,6,0,0,0,0,0,0,\n0,0,11,6,12,7,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,9,6,11,6,0,0,0,0,9,5,0,0,0,0,0,0,\n0,6,8,5,0,0,0,0,8,0,10,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,\n5,10,7,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,8,7,0,0,0,6,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22,\n0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0,\n0,0,0,0,0,17,0,0,6,0,6,12,4,19,6,0,0,0,0,16,0,0,0,0,7,15,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,10,4,0,0,8,7,0,7,0,0,9,\n4,0,6,0,0,0,4,0,5,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,10,0,0,0,0,0,11,7,0,0,\n0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,\n0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,8,7,0,0,\n0,0,0,0,0,6,0,0,0,4,0,0,11,4,0,0,12,7,0,0,0,0,9,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,\n4,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,9,4,0,6,0,0,0,0,0,4,\n0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,7,9,6,0,7,0,\n0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,0,0,10,6,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,4,8,0,0,0,0,0,9,7,0,0,0,0,0,0,\n13,5,0,0,0,0,8,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,5,0,0,11,7,0,0,0,0,0,0,8,6,0,\n0,0,0,0,7,0,4,0,0,0,0,0,0,0,5,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,10,4,9,0,0,0,0,0,\n0,4,0,0,0,0,10,5,10,7,0,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,0,0,0,\n0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,4,0,0,0,7,0,0,0,0,0,0,13,0,0,\n0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,13,7,0,7,0,4,16,0,0,0,0,6,8,7,9,7,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,8,5,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,11,7,0,0,11,\n0,0,0,0,0,9,5,0,4,0,0,0,0,9,7,8,6,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,\n0,7,0,0,0,0,0,0,0,0,0,0,0,4,10,6,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,10,7,10,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,6,8,7,12,4,0,0,0,0,0,0,0,5,14,\n0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,20,4,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0,\n0,6,15,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,12,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0,18,0,0,0,10,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,9,6,0,\n6,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,9,0,9,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,9,5,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,0,8,0,0,0,16,0,0,0,0,0,0,0,\n0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,0,0,11,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,11,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,7,0,6,\n0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,0,0,0,6,0,0,18,0,8,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0,4,0,0,0,\n0,0,0,0,0,0,0,8,0,0,0,0,0,16,0,0,0,0,0,16,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,18,0,0,0,0,0,0,0,0,0,9,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,4,0,\n0,0,0,0,0,0,0,9,4,0,0,0,0,12,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,5,0,0,10,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,9,0,0,0,11,0,0,6,0,6,0,0,\n0,7,0,0,0,0,0,0,8,0,0,0,0,6,0,0,0,0,0,0,19,0,0,0,12,0,9,0,0,0,0,0,10,7,0,0,0,0,\n0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,16,7,12,\n0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,10,5,0,0,0,0,0,0,0,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,4,0,0,9,0,0,0,8,0,12,4,0,0,0,0,\n0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0,\n0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,8,6,0,6,0,0,0,0,0,0,\n0,4,0,0,0,0,0,6,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,10,6,0,0,0,0,8,\n6,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,7,0,6,\n10,7,0,0,10,5,11,6,0,0,0,0,0,7,16,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,\n0,0,0,0,0,8,7,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,12,7,0,7,0,0,0,\n0,0,0,0,6,0,0,0,0,9,0,0,0,23,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,4,0,0,11,7,10,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,7,0,0,8,7,8,0,0,0,0,0,0,0,0,0,0,0,14,5,0,0,0,0,\n0,0,0,0,18,6,8,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11,0,0,0,9,7,12,6,0,0,0,0,0,0,0,0,\n0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,6,10,0,0,0,9,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,6,\n10,7,0,0,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,\n0,0,0,8,7,8,6,0,0,11,7,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,4,8,7,0,0,0,0,0,0,0,0,\n0,5,0,0,13,0,0,0,0,5,0,0,9,7,0,0,0,0,0,0,0,4,0,0,11,0,0,7,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,12,7,19,0,8,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,0,0,12,0,0,0,0,6,9,6,\n14,0,0,0,0,0,0,6,0,5,0,0,8,7,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,4,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,\n7,0,0,10,0,9,7,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,0,0,0,0,5,0,6,0,0,0,0,\n0,0,0,0,0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,13,7,\n0,0,0,0,0,0,0,0,12,0,0,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,11,5,0,5,13,0,8,0,\n0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,11,5,\n9,6,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,10,0,0,0,8,5,0,0,9,0,0,0,8,7,9,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0,\n0,11,0,13,6,0,0,9,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,5,21,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,5,0,0,0,0,0,0,0,0,10,0,8,0,\n0,6,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,4,0,0,8,6,0,6,0,7,10,0,8,4,0,4,0,0,0,0,0,\n5,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,12,0,0,7,0,0,0,5,0,0,\n0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n15,7,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,24,7,0,0,0,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,12,0,0,7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,15,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0,\n0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,9,0,9,6,\n0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,4,0,7,0,0,0,0,0,0,0,0,\n22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,7,0,0,21,7,0,7,9,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,23,0,0,0,0,7,0,0,0,\n4,0,0,0,0,0,0,0,0,9,4,11,7,0,5,0,0,0,0,11,0,0,4,20,0,0,0,0,0,0,0,0,0,0,0,11,5,0,\n7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n21,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,11,6,0,0,0,0,0,0,0,0,9,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,5,0,4,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,\n0,0,0,10,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,11,7,0,0,0,0,0,0,0,4,\n0,4,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,7,0,\n0,0,0,0,0,0,0,0,6,0,0,21,6,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,8,0,0,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,\n0,0,0,8,7,0,0,11,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,13,7,10,4,0,\n0,0,6,0,0,0,0,0,0,0,0,0,5,10,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,8,4,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,\n0,0,0,0,7,0,0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,5,0,6,0,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,4,0,0,0,0,9,0,11,4,0,0,0,6,0,0,0,5,12,7,0,5,0,0,0,0,0,4,0,0,0,7,0,0,0,\n0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,13,6,10,0,0,0,17,0,0,4,0,0,0,0,0,6,0,4,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,11,7,0,0,0,7,0,0,0,6,0,0,0,0,0,0,\n0,6,0,4,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,4,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,0,0,\n0,0,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,16,4,0,0,11,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n8,7,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,8,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,\n7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,12,5,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,\n5,18,7,0,0,14,0,0,0,0,0,0,0,9,4,0,7,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,6,0,0,0,0,0,0,\n8,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,7,0,0,0,0,0,0,11,0,0,0,\n10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,14,6,0,0,0,0,11,4,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,10,7,0,6,0,0,9,0,9,5,0,0,0,0,0,\n0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,8,5,0,0,0,0,0,0,0,0,0,0,11,4,0,6,\n0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,12,4,0,6,8,6,0,0,0,0,0,0,0,0,0,0,8,0,0,5,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0,\n0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,12,7,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,13,4,0,7,0,0,0,7,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0,\n9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,6,21,5,0,0,0,0,8,0,0,0,0,4,0,\n7,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,\n0,7,9,6,11,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,10,0,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,19,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,18,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,9,4,10,4,0,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,9,7,9,7,10,4,0,7,0,0,0,0,0,0,0,6,12,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0,\n0,0,0,0,0,5,0,0,8,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,\n0,0,0,0,4,0,0,8,0,0,6,0,0,0,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,0,4,8,0,0,0,0,6,11,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,13,4,0,0,\n12,6,0,6,0,0,0,0,8,7,0,7,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,4,0,0,0,0,0,0,0,0,0,0,9,\n7,22,0,0,0,0,4,0,0,0,0,0,6,0,0,0,4,0,0,9,0,0,6,0,0,24,7,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,10,6,0,5,0,0,0,0,0,0,0,7,0,0,8,0,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,7,0,\n7,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,0,\n0,0,0,0,0,7,12,0,9,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,4,0,0,0,7,0,\n0,0,0,8,7,0,0,0,0,0,0,0,0,0,4,18,0,0,0,0,0,10,0,0,5,0,0,11,0,0,0,0,0,0,5,0,6,0,\n0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,\n4,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,\n0,0,0,5,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,20,7,0,0,0,0,0,0,0,0,0,0,0,4,9,0,12,\n6,8,0,14,7,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,10,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,9,6,0,7,12,0,0,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,0,9,0,\n12,6,0,5,0,0,0,6,0,4,0,6,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0,\n10,0,0,0,0,0,0,0,8,6,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,12,6,20,5,0,0,0,0,0,0,0,0,0,0,0,0,9,5,0,5,0,0,0,6,13,7,0,0,0,0,15,6,0,0,0,\n6,0,0,13,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,\n10,6,0,0,0,0,0,6,0,0,0,0,9,0,0,0,0,0,19,6,0,0,0,0,0,0,0,0,0,0,13,0,11,0,0,0,0,0,\n0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,10,0,0,6,0,0,0,0,8,0,0,\n0,9,0,15,4,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,14,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,\n0,0,0,0,0,8,7,0,0,0,0,0,6,10,0,0,0,0,0,0,0,0,7,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,10,5,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,6,12,0,0,0,10,7,0,5,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,6,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,4,9,6,0,0,0,7,0,0,0,0,0,0,0,0,8,6,0,0,\n0,0,0,0,0,4,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,6,0,6,9,4,0,0,8,4,0,6,\n0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,8,0,0,6,13,4,0,5,8,0,0,0,0,0,0,0,8,0,0,0,10,5,0,0,9,0,0,0,0,0,0,6,0,0,\n24,0,0,0,0,0,0,0,8,0,0,7,0,0,12,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,\n6,8,0,10,0,9,7,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,4,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,8,0,0,\n0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,10,4,0,0,0,0,0,0,0,6,0,0,0,4,20,0,0,7,\n10,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,9,6,0,0,0,0,0,0,0,4,\n12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,9,4,0,5,0,0,\n0,0,0,0,0,6,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,6,9,0,0,0,0,7,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0,0,9,0,0,0,\n0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,17,7,0,0,13,6,14,6,0,0,0,0,\n8,0,0,0,0,0,0,7,12,7,8,7,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,4,0,0,0,0,0,4,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,12,4,0,0,10,7,0,0,0,\n0,0,0,10,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,12,0,0,6,\n0,0,0,0,0,0,0,0,8,7,12,0,0,0,0,0,0,6,0,6,0,4,0,0,18,6,0,0,0,6,0,0,0,0,0,6,10,6,\n0,0,0,0,0,0,8,7,14,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,\n0,0,0,8,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,8,7,0,0,10,5,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,9,4,8,0,0,0,0,0,0,4,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,\n0,6,0,0,9,7,0,0,0,0,0,5,0,0,0,0,8,7,0,0,14,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n0,0,0,6,0,0,0,6,0,4,0,0,0,0,0,4,0,0,0,0,12,0,0,7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,12,0,16,6,0,0,0,0,0,0,11,7,0,4,8,7,0,0,0,0,0,6,0,0,0,0,16,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,10,7,0,0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,\n0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,13,4,0,0,10,0,0,0,0,0,0,0,0,0,19,0,0,0,\n0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,\n5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,18,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,14,7,0,0,11,5,0,0,0,5,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,24,6,0,0,\n0,7,0,4,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,4,0,0,0,0,8,7,0,0,\n9,6,0,0,14,5,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,12,6,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,5,0,0,\n0,0,12,7,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,13,7,0,0,0,0,0,0,14,0,11,4,0,\n0,0,4,0,0,0,0,14,5,0,0,0,0,0,5,11,5,0,0,0,0,22,5,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0,\n4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,17,0,10,0,0,0,8,0,0,0,19,\n5,18,7,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,10,6,0,6,0,0,0,0,10,4,0,4,0,\n0,0,0,0,0,14,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,0,9,6,12,0,0,6,0,0,0,0,0,0,0,0,\n12,0,10,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,5,13,0,9,7,0,0,0,0,0,0,0,0,0,0,0,7,9,7,0,0,8,0,0,0,0,0,\n22,0,0,0,0,0,0,0,23,6,14,0,0,0,0,0,0,7,0,0,0,0,11,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,10,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,8,5,0,0,0,0,0,0,0,0,0,7,11,6,21,0,0,0,0,0,\n0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,0,4,9,7,0,0,0,0,0,0,12,0,0,0,0,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,9,\n0,0,0,20,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,7,0,0,0,0,0,0,0,6,15,0,0,\n0,0,0,0,0,0,0,0,0,0,0,12,4,0,5,0,0,0,0,0,0,11,7,17,6,0,0,0,0,0,0,15,6,0,7,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,5,\n0,0,11,0,11,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,\n17,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,7,9,6,0,0,14,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,\n8,7,0,4,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,\n0,0,0,5,0,4,0,0,8,7,0,6,12,5,0,7,18,7,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,\n10,0,11,0,0,0,0,0,0,0,0,0,0,0,9,0,0,4,0,6,0,7,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,\n7,0,0,0,0,8,0,0,0,15,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,0,0,23,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,5,0,0,0,0,0,0,8,6,0,0,\n0,0,0,0,12,7,9,7,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,9,0,8,7,0,0,0,\n6,0,6,0,4,0,5,0,0,0,0,0,5,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,7,10,5,0,0,11,6,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,4,9,7,0,\n0,0,0,11,7,0,0,0,0,0,5,0,0,0,7,0,0,0,0,23,6,11,4,0,0,0,0,0,0,9,0,0,0,10,6,0,0,0,\n0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,10,6,0,0,0,7,0,0,\n0,0,0,0,0,0,0,0,20,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,\n6,11,7,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,6,0,0,0,5,0,6,0,6,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,8,7,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,4,10,0,8,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,10,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,11,6,0,4,0,0,14,5,0,7,0,0,0,0,0,6,16,0,0,0,0,0,0,0,10,0,0,7,15,0,0,0,11,7,0,0,\n0,0,0,0,0,0,0,0,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,5,0,0,0,\n0,8,0,0,6,0,0,0,0,0,0,9,5,0,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,6,0,\n0,0,0,0,0,0,7,0,0,0,0,15,7,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,16,7,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,12,6,11,7,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,\n7,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,8,0,0,5,8,7,10,6,0,0,0,7,0,0,0,0,12,6,\n0,0,9,0,0,0,12,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,10,0,0,0,10,5,0,0,0,0,0,0,9,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,9,5,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,0,0,5,0,0,8,7,8,\n6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,10,0,9,4,0,0,0,0,0,0,0,6,\n11,0,0,0,0,0,0,0,0,0,0,0,8,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,8,7,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,\n0,0,0,10,0,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,\n0,0,8,4,0,5,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,8,5,0,0,0,\n0,0,0,0,7,0,0,0,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,6,0,7,0,0,0,0,\n20,0,0,0,0,0,0,0,0,0,0,7,9,0,0,0,0,0,0,6,0,6,0,7,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,\n0,0,0,14,7,0,0,0,5,0,0,22,4,10,0,0,0,0,0,0,4,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,11,5,13,0,0,0,0,0,0,0,0,0,8,0,0,7,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,10,7,0,\n0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,7,14,6,0,0,0,0,9,5,\n0,0,0,0,0,6,0,0,0,5,10,0,8,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,8,4,0,6,0,\n0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,\n14,0,0,5,0,0,18,0,8,4,0,6,0,0,20,0,13,0,0,0,0,7,0,4,0,0,0,0,0,4,8,4,0,0,0,0,0,6,\n0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,14,0,0,0,0,0,9,7,0,0,9,0,0,0,0,\n0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,20,0,14,0,0,4,0,6,8,5,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,4,12,7,0,6,0,0,9,7,10,5,\n0,0,8,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,0,18,0,0,0,14,7,0,0,0,0,0,4,\n0,0,0,0,0,0,17,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,7,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,23,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,0,0,4,0,0,0,0,0,0,12,7,8,4,0,0,0,0,0,0,0,0,0,6,0,0,9,5,0,0,0,7,0,0,0,\n0,0,0,0,0,0,4,10,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,18,7,\n0,0,8,0,0,5,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,5,0,7,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,\n6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,10,0,0,5,10,4,0,0,12,0,0,0,0,\n6,22,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,16,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,12,7,0,0,0,0,9,0,0,0,0,6,0,0,11,0,0,0,0,0,13,0,9,6,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,10,7,0,0,0,7,0,6,0,\n0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,11,0,15,0,22,7,0,4,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,\n18,0,0,0,0,0,0,0,0,0,14,0,0,4,0,0,0,0,8,7,9,0,0,0,0,0,9,0,0,0,14,0,0,0,0,0,0,0,\n0,0,11,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,6,0,6,0,0,0,0,8,0,0,0,0,\n0,11,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,9,4,0,0,0,0,0,4,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,8,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,\n0,0,0,0,0,0,8,6,0,0,9,5,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0,\n0,10,6,9,0,0,0,0,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n11,7,12,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,\n0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,5,0,0,10,6,\n0,0,0,4,0,7,13,0,0,4,0,0,11,4,0,6,0,0,0,0,0,6,8,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,5,0,0,0,0,12,6,0,0,0,0,\n11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,11,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,\n7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,6,17,0,9,0,10,6,0,6,12,0,0,4,0,0,0,\n0,0,0,0,0,0,0,8,5,12,7,0,4,0,0,0,0,0,0,0,0,0,0,11,0,9,0,10,6,11,5,0,7,0,0,8,0,0,\n7,0,4,0,0,0,7,0,0,0,0,0,0,8,6,0,0,0,6,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,10,0,0,0,0,0,8,6,0,0,0,0,0,6,12,0,0,0,0,0,\n0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,16,0,11,5,0,0,0,0,0,\n0,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,9,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,10,\n7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,0,9,5,0,0,0,0,8,0,9,0,0,\n0,0,0,0,0,0,7,10,0,13,0,0,6,0,0,0,0,0,0,0,0,0,6,9,4,0,0,0,0,0,0,10,0,0,0,0,0,10,\n0,0,0,0,0,0,0,10,6,11,0,0,0,0,0,9,0,0,0,0,0,0,4,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0,\n0,0,0,0,0,18,4,0,7,0,0,0,0,0,0,24,0,8,6,0,7,0,0,0,0,15,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,5,0,0,0,0,10,7,0,6,0,0,0,0,0,0,0,0,8,5,10,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,\n6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,4,0,5,15,0,0,0,0,7,0,7,0,0,0,0,\n0,0,0,0,0,6,10,5,0,0,0,6,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,12,0,0,0,0,0,0,0,0,\n0,0,5,0,0,0,0,0,0,14,4,18,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,11,0,10,4,9,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0,\n0,0,0,0,0,0,0,0,7,13,7,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,8,0,10,6,0,4,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,\n0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,9,7,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,0,5,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,11,0,0,0,0,6,0,0,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22,0,0,\n6,0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,\n0,0,0,0,0,0,0,6,0,6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,10,0,11,5,0,0,0,0,0,0,14,7,9,7,\n0,6,0,0,0,0,0,4,0,0,0,0,0,0,11,7,0,6,0,0,0,0,0,0,9,7,0,4,0,0,0,7,0,0,0,0,0,5,0,\n0,0,0,0,5,0,0,0,7,0,0,0,0,0,5,0,0,0,0,17,5,0,0,8,0,0,0,0,6,9,4,0,0,0,0,0,0,0,0,\n8,7,11,7,9,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,9,5,0,0,8,6,0,0,0,5,0,\n0,0,0,9,0,0,0,9,6,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,4,0,0,0,5,0,0,0,0,0,7,0,0,0,0,0,7,13,5,0,0,0,7,0,0,0,0,0,7,9,6,11,7,0,7,0,0,0,\n0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,8,5,0,0,0,5,9,4,0,0,0,0,0,0,0,0,8,4,0,0,0,0,\n24,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,\n0,0,0,0,6,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6,0,4,0,7,20,0,8,5,9,5,9,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,7,23,5,0,0,8,4,0,0,10,0,0,6,0,5,0,0,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,0,0,0,\n10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,\n6,0,0,0,0,14,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,6,0,4,0,0,0,0,0,0,8,4,\n11,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,12,0,10,7,0,0,10,0,0,0,0,\n0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,6,0,0,0,0,8,\n6,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,4,0,6,0,4,0,0,0,0,0,5,0,0,\n0,0,0,0,0,0,0,7,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,17,7,11,0,0,0,0,0,0,0,0,0,0,4,12,6,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,5,12,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,0,20,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,4,\n0,0,0,5,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,4,13,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,12,6,0,7,0,0,0,0,10,0,23,6,0,0,\n0,4,0,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n10,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,11,0,9,7,0,0,\n0,0,0,0,0,0,0,0,9,7,0,4,0,0,0,0,8,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,\n0,0,0,0,0,6,0,0,10,7,10,5,0,0,8,0,8,0,0,0,0,0,0,4,0,5,10,0,0,0,0,0,0,0,9,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,0,0,0,9,4,0,0,0,0,0,6,0,0,8,\n7,0,0,0,0,0,5,0,0,0,0,0,0,0,0,10,0,0,0,0,5,0,4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,24,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,6,0,0,9,0,0,0,0,0,0,7,0,6,13,0,8,\n0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,6,0,0,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,\n4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,4,0,4,0,0,0,5,0,7,0,0,10,0,10,7,0,0,12,5,0,0,9,0,0,0,10,0,\n0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,\n12,0,0,0,0,0,8,5,13,6,0,0,0,0,0,0,9,4,0,0,0,0,8,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,14,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,17,6,0,0,0,0,12,6,0,0,0,0,8,0,0,7,0,\n7,0,4,9,0,0,6,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,0,0,0,11,0,0,4,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,18,7,0,4,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,8,0,11,7,0,0,0,0,0,0,0,0,0,4,0,0,0,0,\n11,0,0,0,0,0,0,0,21,0,0,6,10,0,0,0,0,0,9,0,10,0,0,0,0,0,11,0,0,0,0,6,0,0,0,0,0,\n5,0,0,0,0,0,0,10,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,4,0,0,23,7,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,0,7,\n0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,6,0,0,\n11,6,0,0,0,0,0,0,0,6,0,0,0,0,10,7,0,0,9,4,0,0,11,0,8,5,0,0,0,7,8,5,22,0,0,0,9,6,\n0,0,0,0,0,0,0,6,10,4,0,0,0,0,0,7,9,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,\n0,0,0,11,6,0,0,0,0,0,0,0,0,0,0,0,7,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,6,0,6,0,4,0,0,\n0,0,0,0,0,7,0,7,0,4,13,0,0,0,0,0,8,0,0,0,0,7,0,0,0,0,0,0,11,6,0,7,0,0,0,0,9,0,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,8,0,0,0,0,0,8,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,6,0,0,0,0,13,5,8,0,0,\n0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,17,6,0,0,0,0,13,4,0,0,9,6,0,0,10,5,0,\n0,10,5,0,0,0,0,13,0,0,0,0,6,0,0,0,0,0,0,10,0,12,0,0,0,0,0,0,0,0,0,0,0,8,4,0,4,0,\n0,0,4,0,0,0,0,0,4,0,0,12,0,0,5,9,4,0,0,0,0,0,0,0,0,0,5,8,5,0,0,0,7,0,0,0,0,8,7,\n0,0,0,6,12,5,0,0,0,5,0,0,0,5,0,0,0,0,0,4,12,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,9,6,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,4,11,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,12,7,0,0,0,7,10,7,0,0,11,0,0,0,0,0,0,0,0,0,11,7,0,0,0,6,0,0,11,0,0,0,0,\n0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,22,0,10,7,0,0,8,5,0,0,0,0,0,5,0,0,0,0,0,0,\n0,0,0,0,9,6,8,7,0,6,0,0,0,0,0,5,0,0,0,0,0,0,8,7,0,0,0,0,9,7,0,0,0,6,0,0,8,7,0,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,5,0,0,0,4,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,5,0,0,0,0,14,0,0,0,\n9,0,0,0,0,0,0,0,0,0,9,7,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,12,0,0,0,0,0,12,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,6,0,0,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,9,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0,7,12,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,\n0,7,0,0,8,6,0,0,0,0,10,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,12,0,0,0,0,0,0,0,0,6,0,0,0,\n0,0,6,0,0,0,6,0,0,0,0,0,6,16,0,0,0,0,0,0,0,0,0,9,0,17,0,14,7,8,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,0,0,11,0,0,6,8,7,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,\n9,0,0,0,0,7,0,0,0,0,11,5,0,4,9,6,8,0,0,0,0,0,0,0,0,0,10,0,11,7,0,0,0,0,0,0,0,0,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,\n0,0,0,12,0,0,0,0,0,10,5,0,4,0,0,0,0,0,7,10,6,11,6,0,0,0,0,0,0,0,0,0,0,0,0,17,0,\n0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,8,0,0,4,0,0,0,6,0,0,0,\n0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,4,0,0,0,0,9,6,0,0,0,4,0,0,0,0,0,4,10,7,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,\n0,0,0,0,0,0,6,0,0,0,6,0,6,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,18,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,13,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,\n0,0,0,6,0,0,0,0,0,4,8,0,0,0,11,7,0,0,0,4,0,0,0,0,0,7,0,0,8,5,0,0,16,0,0,0,13,6,\n0,0,0,0,0,0,0,6,0,0,0,0,20,0,11,6,0,0,8,7,0,0,0,0,0,6,17,0,8,0,0,0,0,0,8,7,0,0,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,\n0,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,8,\n0,8,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,6,0,0,9,0,\n0,0,0,0,8,0,0,0,0,0,18,0,0,0,0,0,0,4,9,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,9,6,0,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,7,0,0,0,0,0,0,0,0,\n0,4,0,0,0,0,0,0,14,0,0,0,0,7,0,6,0,0,8,0,20,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,0,0,0,8,0,0,7,0,6,0,0,0,7,0,0,0,0,0,0,0,0,\n0,0,0,4,12,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,6,0,\n5,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,0,0,5,8,4,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,12,7,0,\n0,0,0,13,6,0,0,0,7,0,0,8,0,0,0,8,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,0,0,0,0,0,0,11,5,\n0,6,0,0,8,5,0,7,0,0,0,0,0,0,0,7,0,0,0,0,8,6,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,4,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n14,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,19,0,0,4,0,0,0,7,\n0,0,11,5,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,16,0,10,5,18,0,0,7,9,6,0,5,0,0,0,0,0,\n0,0,0,0,5,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0,0,7,0,6,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,4,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,23,0,0,0,0,5,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,14,0,20,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,\n11,0,0,0,0,7,0,0,0,0,15,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,7,0,0,0,0,\n0,4,0,0,0,0,10,0,0,0,0,0,9,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,0,11,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,5,0,0,11,0,0,0,0,7,0,0,0,0,0,0,8,7,0,\n4,0,0,0,0,11,0,0,0,0,0,11,0,0,5,0,0,8,7,0,4,0,7,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,10,5,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,6,0,5,0,0,0,0,0,0,0,\n0,0,4,11,5,10,7,0,7,0,0,9,6,9,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,9,4,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,8,6,0,0,0,0,11,7,0,0,0,0,0,0,0,0,0,0,11,7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,8,5,0,0,8,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,\n10,7,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,10,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,6,0,\n0,0,6,0,0,0,0,9,5,8,5,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,\n0,8,7,10,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,0,5,0,0,0,6,0,7,0,0,\n10,5,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,11,0,0,0,0,0,13,4,\n0,0,0,4,0,0,0,0,0,5,8,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,7,14,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,7,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,5,0,0,15,6,10,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,14,6,10,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,6,0,5,11,4,0,6,0,0,0,7,0,0,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,8,5,0,0,0,0,0,0,0,0,0,0,\n0,0,10,0,0,0,0,0,9,6,9,4,0,0,0,4,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0,\n0,0,0,0,0,0,0,0,0,0,4,0,0,11,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,\n0,0,0,7,12,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,\n4,9,6,0,4,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,6,0,\n7,8,6,0,0,0,0,0,0,0,4,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,5,0,4,0,0,0,0,0,0,0,5,0,0,0,\n0,0,5,0,0,0,7,12,7,0,0,0,0,0,0,18,4,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,6,0,0,0,\n0,12,0,0,7,0,0,0,0,0,7,0,0,13,0,0,6,0,0,0,0,8,7,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,7,10,5,0,0,8,0,0,0,0,0,0,0,8,6,0,7,0,0,8,4,0,4,0,0,0,0,10,4,0,0,14,0,\n0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,17,0,0,0,0,0,0,6,0,0,0,0,8,6,0,0,10,5,0,0,0,0,8,\n6,0,0,0,6,0,0,0,7,0,0,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,12,0,0,0,0,6,\n8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,24,0,0,\n0,0,0,12,6,0,0,10,6,0,5,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,7,0,5,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,11,5,9,0,8,7,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,10,7,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,5,8,7,0,0,0,\n0,8,5,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,\n0,6,12,0,8,7,0,0,0,0,0,0,0,0,0,0,16,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,22,0,0,0,\n0,0,0,0,0,0,0,0,0,0,13,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,22,0,0,6,0,0,21,0,0,0,22,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,7,8,0,0,0,0,6,14,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,0,8,5,0,0,11,7,0,6,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,5,0,0,0,0,0,0,0,0,0,4,0,0,8,7,0,0,0,0,8,5,11,7,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,8,5,0,0,10,0,0,4,13,7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,13,6,\n0,6,0,7,0,0,8,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,15,0,0,0,10,7,0,0,0,0,0,\n7,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,19,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,5,\n0,7,0,0,0,0,0,0,0,0,0,6,0,0,11,4,0,0,0,6,0,0,13,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,12,6,0,0,0,0,\n0,7,0,0,0,0,0,0,11,7,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,11,6,\n0,0,0,0,0,0,0,0,10,0,0,0,0,6,0,0,0,0,0,0,8,7,0,0,0,5,0,0,0,5,0,0,0,0,0,0,0,0,0,\n0,0,0,8,7,0,0,0,0,9,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,10,0,\n0,6,0,0,13,0,0,0,0,0,0,0,9,6,0,0,8,6,8,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,\n0,9,7,0,0,0,0,0,0,11,0,0,0,10,7,0,0,0,0,0,0,0,0,9,6,0,0,12,4,0,4,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,21,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,5,0,0,\n9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,\n16,0,0,4,0,0,0,0,0,7,0,0,0,6,0,6,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0,\n0,14,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,\n0,0,8,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,\n0,0,0,0,6,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,14,7,0,0,9,7,0,0,11,0,0,0,0,0,10,\n4,11,5,13,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,5,0,0,0,0,0,4,0,0,9,0,0,0,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,12,5,0,0,0,6,14,0,0,0,0,0,0,0,0,0,0,4,9,4,\n0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,5,0,0,\n0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,11,6,0,0,13,7,0,0,13,6,0,7,0,0,0,0,0,0,8,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,10,6,0,4,0,0,12,6,0,0,0,0,0,0,0,0,10,6,\n0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,7,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,6,0,\n0,0,7,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,\n0,0,0,5,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,\n0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,8,7,0,0,8,5,0,0,0,4,9,5,0,0,0,7,10,6,0,0,\n0,0,0,0,9,7,0,0,8,5,8,0,8,4,0,0,13,0,0,0,0,0,0,0,0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,11,7,0,0,0,7,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17,5,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,7,0,0,0,0,8,5,0,4,0,0,0,0,0,6,0,6,14,\n6,0,0,0,0,9,6,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,6,0,0,0,0,14,7,9,7,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,14,0,\n0,6,0,0,8,6,0,0,0,0,0,6,0,0,12,0,0,0,0,0,8,5,0,7,11,0,0,5,0,4,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,9,6,0,4,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,10,5,0,0,0,0,\n0,4,0,0,0,7,11,6,0,4,8,5,9,5,0,0,0,5,0,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,5,14,7,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,16,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,9,6,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,5,0,0,0,0,0,0,0,4,10,5,0,0,0,0,0,0,0,0,0,0,0,6,0,\n0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,4,0,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,10,4,0,0,0,0,0,5,0,0,0,4,\n0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,0,10,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,7,0,0,0,0,0,0,0,0,15,0,0,0,\n0,0,0,0,0,0,0,7,0,0,0,0,0,7,10,7,9,7,0,0,0,7,0,0,8,0,0,0,0,0,0,0,9,0,0,0,8,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,7,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,15,7,12,6,0,0,0,7,0,5,0,0,0,0,0,0,0,0,0,0,0,0,18,0,0,5,0,0,0,0,\n0,0,0,6,9,5,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,9,7,0,0,14,0,0,0,11,7,0,0,0,0,0,\n0,0,0,0,0,0,4,0,0,11,7,0,0,0,0,8,0,0,0,0,0,0,6,8,7,0,0,0,7,10,4,0,0,0,0,0,0,0,0,\n0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,10,0,0,0,0,0,0,\n6,0,6,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,10,7,0,0,0,0,9,7,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,12,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,9,6,0,0,11,0,0,\n0,0,0,14,4,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,23,7,0,0,\n0,0,0,6,0,7,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,20,\n7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,0,0,0,0,0,0,0,0,0,11,5,0,0,0,0,0,0,0,0,0,0,10,4,0,0,0,5,8,5,10,4,0,0,0,0,0,\n0,13,6,9,7,0,0,10,7,0,0,0,0,0,0,0,0,14,0,0,0,0,0,0,6,0,0,0,7,0,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,7,10,7,0,0,\n0,0,0,0,0,0,0,0,12,4,0,0,0,0,8,7,0,0,0,0,0,7,0,6,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,\n0,0,0,0,6,0,6,9,6,0,0,12,5,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,\n0,0,0,0,0,0,0,0,0,5,8,7,9,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,11,\n4,0,0,0,0,0,0,8,0,0,0,10,7,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,0,\n0,0,0,0,0,5,0,6,0,0,10,0,14,0,0,0,0,0,0,0,23,0,0,0,12,0,10,5,0,0,0,0,0,0,0,0,0,\n5,0,0,0,0,8,0,0,0,0,6,8,0,0,0,0,0,0,0,0,0,22,0,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,\n0,0,0,0,0,6,18,4,0,0,0,7,10,6,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,\n0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,7,10,0,0,0,0,0,0,6,0,0,0,0,11,5,0,0,0,0,0,0,0,0,\n15,0,8,6,0,0,13,7,0,0,0,0,0,7,0,0,0,0,0,7,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,9,5,9,\n0,0,6,8,6,0,0,0,0,10,0,0,0,18,5,0,0,0,5,0,7,0,0,0,0,8,6,0,0,0,0,9,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,14,0,23,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,6,0,0,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0,\n0,0,0,0,20,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,9,5,0,0,0,0,0,0,8,4,24,0,0,0,0,0,0,\n0,0,0,0,0,0,0,9,7,0,0,0,0,10,5,0,0,8,5,0,0,0,0,0,0,0,0,12,7,0,6,0,0,10,6,0,0,0,\n0,14,0,0,4,9,5,0,0,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,8,0,0,0,0,0,11,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,8,5,11,7,0,4,0,0,10,0,0,0,0,\n0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,11,6,0,0,0,0,0,5,14,6,0,0,0,0,10,0,0,\n0,13,4,0,0,0,0,0,0,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,12,0,10,6,0,0,0,0,0,0,10,0,0,0,0,0,10,0,9,\n7,0,0,0,0,0,0,0,0,0,0,0,0,0,7,8,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,9,7,0,0,0,\n0,0,0,0,0,0,0,0,0,24,0,11,7,0,7,0,0,0,0,0,0,8,6,0,0,0,0,0,0,8,7,0,0,0,0,0,5,0,0,\n0,6,9,0,0,0,23,5,0,0,0,0,0,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16,7,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,18,4,0,0,11,7,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,9,0,0,0,11,0,0,0,23,0,0,\n0,10,4,0,0,0,0,0,7,0,0,0,7,0,0,0,0,0,4,0,0,0,0,0,7,0,0,19,0,11,0,0,0,0,0,12,7,0,\n0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,\n9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,4,0,0,0,0,10,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,22,0,8,7,10,4,11,0,13,5,8,7,9,0,8,7,0,0,0,7,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,\n0,8,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,4,0,0,0,4,11,0,0,6,0,0,8,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,5,0,0,\n20,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,7,0,0,14,0,0,0,9,0,13,7,0,0,0,0,0,6,0,7,0,0,8,6,10,6,0,0,8,6,0,0,0,6,0,\n0,12,6,9,0,0,0,0,0,0,5,9,0,12,4,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,\n0,0,4,8,0,0,6,8,0,0,0,0,0,0,0,0,0,13,6,0,7,0,0,0,0,0,6,8,7,8,6,0,0,0,7,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,18,0,11,4,0,0,0,5,0,0,0,0,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,14,\n6,0,0,0,0,12,7,8,0,0,0,0,0,0,0,8,7,0,0,0,0,10,4,0,0,0,0,0,0,10,0,0,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,15,6,9,7,0,0,0,0,0,0,15,6,11,7,0,0,0,7,0,0,21,0,0,\n0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,17,6,0,0,10,5,0,5,0,0,0,0,0,0,0,0,0,7,\n0,0,10,0,0,0,0,0,0,0,0,4,11,5,0,0,0,0,16,7,0,0,0,0,0,6,0,0,8,7,0,4,0,0,10,0,0,0,\n0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,\n0,0,0,10,4,0,0,0,0,0,0,0,0,0,6,0,5,0,0,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,\n0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,6,10,7,0,0,0,0,0,0,0,0,8,4,0,0,10,0,0,0,0,4,0,6,0,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,7,17,0,0,0,0,0,\n0,0,0,0,0,0,10,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6,0,0,0,5,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,5,0,4,0,0,0,0,0,6,0,0,0,0,0,0,10,5,0,0,\n0,5,0,0,0,0,9,0,19,7,0,0,0,0,0,7,0,0,0,0,10,6,0,0,0,6,0,5,0,0,0,0,0,0,0,0,0,6,8,\n0,0,0,0,0,11,0,0,0,0,0,0,6,0,0,0,0,0,7,9,0,15,0,0,0,0,0,0,0,0,0,0,4,0,0,0,5,0,0,\n0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,0,0,6,0,7,0,0,0,0,0,0,0,6,0,0,\n0,0,0,6,10,0,0,0,0,0,0,0,23,0,14,0,0,0,0,7,0,0,0,0,0,7,0,0,9,0,0,0,0,7,0,0,0,0,\n0,6,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,4,0,0,0,\n0,0,0,0,0,9,5,0,0,0,0,0,4,0,0,0,0,9,5,0,0,0,0,22,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,22,0,0,0,0,0,0,0,10,0,0,0,0,0,0,5,0,4,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,14,7,0,0,12,7,0,0,0,\n0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,8,6,10,0,0,0,0,0,0,0,0,0,10,7,8,5,0,0,0,0,0,0,\n0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,5,0,0,9,5,0,0,0,0,0,5,0,0,0,0,0,4,0,0,0,\n0,0,0,0,0,0,0,12,4,11,0,0,0,9,0,11,7,0,0,0,0,0,0,10,6,0,0,0,6,0,0,0,0,15,5,0,0,\n11,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,4,0,4,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,8,0,0,0,19,7,0,4,0,0,9,0,0,0,0,0,10,0,\n0,6,0,0,13,0,12,6,0,0,0,0,0,0,0,0,10,7,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,13,7,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,4,9,0,0,0,10,0,0,0,0,0,0,0,\n0,5,0,0,0,0,0,0,10,0,23,6,0,0,0,6,8,0,0,0,0,0,0,0,0,0,17,7,0,0,0,0,11,6,22,5,0,\n0,9,6,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,5,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,4,11,0,9,4,0,0,\n0,7,0,7,0,0,0,0,0,0,12,4,0,0,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n4,0,0,11,5,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,8,6,0,0,0,4,0,0,0,0,\n0,0,0,0,0,7,0,0,0,4,0,0,10,4,0,0,0,0,0,0,0,7,0,7,0,0,0,6,0,0,0,0,8,6,0,6,0,6,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,6,22,6,12,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,11,0,0,0,\n9,7,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,6,0,0,0,6,0,6,0,0,8,7,0,0,0,4,9,7,19,0,0,0,0,0,0,0,0,0,9,6,10,6,0,6,0,0,0,\n4,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,6,16,7,10,6,0,0,23,6,11,7,0,4,0,0,0,0,0,0,0,0,0,\n5,0,0,0,0,10,7,0,0,0,0,0,7,0,0,0,0,0,0,15,0,10,0,0,0,14,6,0,0,0,0,0,0,0,0,0,0,0,\n5,0,0,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,5,0,0,11,5,0,0,0,0,0,0,0,0,0,0,\n0,4,0,0,0,0,0,6,0,0,10,0,0,0,0,7,0,0,0,0,0,0,10,6,0,0,0,0,8,4,0,0,0,7,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,7,12,5,0,0,0,0,\n0,6,0,0,0,0,9,6,0,0,0,0,0,0,0,6,9,0,0,0,0,6,0,0,0,0,8,7,0,0,0,0,0,0,0,6,0,0,0,0,\n0,0,0,0,0,0,10,5,0,0,0,0,0,0,8,6,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,8,5,0,0,0,0,0,7,0,7,0,4,0,0,10,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,5,0,0,0,0,13,\n7,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,13,0,0,0,0,0,0,0,0,7,10,5,0,0,0,0,0,0,9,7,0,0,8,6,9,\n5,0,0,0,0,0,6,12,0,0,0,0,0,0,0,18,6,0,0,0,0,0,0,0,0,19,7,0,4,0,0,0,0,9,5,0,5,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,7,0,0,0,0,0,0,14,0,0,0,23,7,8,7,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,22,0,0,7,0,0,0,0,0,0,0,0,9,7,8,4,0,\n0,0,0,0,0,0,0,8,5,0,6,0,0,0,0,0,6,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,\n8,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,12,5,0,0,0,0,0,0,0,0,0,0,8,6,0,0,11,7,0,0,0,\n0,12,0,8,6,19,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,11,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,11,7,0,0,0,0,0,4,10,0,0,0,0,0,0,0,8,7,0,0,0,0,14,0,8,0,0,6,10,0,0,\n0,0,0,0,0,12,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,6,0,0,0,0,\n0,0,0,0,13,0,0,0,0,0,0,0,11,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,\n0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,5,0,0,0,6,0,0,0,5,0,7,0,0,0,\n0,0,6,0,0,21,7,0,0,9,6,0,0,0,6,0,0,13,7,0,0,0,5,0,0,0,0,0,4,0,6,0,0,0,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,11,5,0,6,0,0,10,5,0,0,0,0,0,0,0,0,9,6,0,0,8,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,0,0,0,0,0,0,6,0,0,0,0,15,4,0,0,12,7,0,0,0,6,\n0,7,0,0,8,0,9,5,0,4,0,0,0,6,0,6,0,0,23,4,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,8,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,12,6,0,0,0,0,0,0,10,7,0,7,0,0,0,0,0,0,0,0,0,0,\n9,0,0,0,0,0,8,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,11,5,0,0,0,6,0,6,0,0,0,0,0,0,0,6,0,\n4,0,0,0,0,0,0,0,0,0,0,0,5,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,8,7,0,0,0,6,0,6,0,\n0,0,0,0,0,0,0,0,5,0,0,0,0,0,5,0,0,0,0,11,0,0,0,0,0,0,0,10,5,9,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,23,7,0,0,0,0,0,7,0,0,10,6,18,0,0,0,\n0,0,0,0,8,7,0,6,0,0,0,0,0,0,8,5,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,\n0,0,0,0,0,6,0,0,0,4,12,7,0,0,0,0,0,0,0,0,10,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,13,5,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,\n11,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,\n0,0,0,0,6,0,0,0,4,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,0,11,0,0,0,0,0,0,0,0,0,\n17,5,0,4,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,0,0,0,8,7,0,0,0,0,0,0,0,\n0,13,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,\n10,0,0,0,8,6,0,0,0,7,0,0,0,0,0,0,8,0,0,0,14,0,0,0,0,7,0,0,0,4,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,9,4,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,14,0,\n10,0,0,0,16,5,0,0,0,0,0,0,8,0,0,4,0,0,0,0,0,0,0,0,0,0,9,6,0,0,0,0,0,0,10,0,0,0,\n0,0,0,0,0,5,0,0,0,0,12,5,0,7,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,7,0,\n0,0,0,0,0,0,0,12,6,0,0,0,0,0,7,0,6,0,6,12,6,0,0,0,0,0,0,0,4,8,7,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,0,0,0,0,6,0,6,0,0,0,0,0,0,0,0,10,6,8,0,0,\n6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n16,0,8,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,23,5,0,0,0,7,0,6,0,\n0,0,0,0,0,0,0,0,0,0,0,10,6,0,0,9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,14,0,0,0,0,7,0,0,0,4,17,5,0,0,0,0,11,0,9,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,6,0,0,0,5,0,7,0,0,0,0,0,0,0,0,8,0,0,0,\n12,6,0,0,0,0,0,0,13,0,0,0,0,7,9,0,0,0,0,0,0,0,0,0,0,5,0,0,0,7,10,7,12,0,0,0,9,0,\n0,0,14,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,0,0,15,6,0,0,23,0,0,7,0,6,0,0,0,7,0,6,\n0,0,0,0,0,0,0,6,0,6,9,0,0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,8,7,9,4,0,0,10,0,0,0,10,\n6,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,23,0,0,6,0,0,0,0,0,0,9,4,\n0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,9,6,0,0,0,0,8,6,0,0,0,0,0,0,0,0,12,0,0,\n0,0,0,8,0,0,6,11,6,0,0,8,7,8,5,0,0,0,0,0,5,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,0,\n10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,\n7,0,0,0,0,9,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,8,0,0,0,0,6,12,5,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,10,0,10,\n7,0,0,8,0,0,0,0,4,0,0,0,6,0,0,0,6,0,0,0,6,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,\n0,0,4,0,0,0,0,0,4,0,0,0,0,0,0,0,6,0,6,0,5,0,0,0,0,8,0,0,0,10,7,0,0,0,0,10,0,0,0,\n0,0,13,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,19,7,0,4,12,0,8,0,0,0,0,6,0,0,0,0,\n0,0,0,6,0,0,0,0,0,0,0,0,0,4,0,0,0,0,18,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,0,0,0,\n0,14,0,0,4,0,0,0,6,0,0,0,6,0,0,0,7,0,0,0,0,0,0,10,4,0,0,9,7,0,0,11,0,0,0,0,0,0,\n7,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,12,0,0,0,\n0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,22,5,9,7,0,0,0,0,0,0,0,0,0,\n0,0,6,0,0,9,6,0,5,0,0,0,0,0,0,10,5,0,0,8,6,0,6,10,5,0,0,0,6,0,0,0,6,0,0,20,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,0,17,4,0,7,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,14,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,\n0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,\n0,0,7,0,0,8,6,12,0,0,7,18,7,0,0,8,4,0,0,0,0,9,6,0,0,0,0,0,0,0,0,13,0,0,6,0,0,0,\n0,0,0,0,0,0,0,10,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,0,\n0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,8,5,0,0,0,0,0,0,0,0,12,0,0,0,8,0,0,0,0,0,0,\n4,0,0,10,0,16,0,0,0,0,0,0,0,12,7,10,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,16,6,10,0,0,5,0,0,0,0,0,6,0,0,0,0,\n0,7,0,0,0,7,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,5,8,7,0,7,0,0,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,4,0,0,0,0,\n8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,7,0,0,8,0,0,0,\n9,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,13,5,0,5,0,0,0,7,8,4,0,0,0,0,0,0,0,\n0,12,0,0,0,0,0,0,0,0,0,0,0,8,6,0,6,0,0,11,0,0,0,0,0,0,0,0,6,0,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,10,7,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,6,0,0,10,6,0,0,\n0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,6,0,0,0,7,0,0,9,0,8,7,11,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,9,6,10,5,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,0,0,0,0,0,10,7,0,0,0,0,0,0,11,0,9,6,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,5,0,6,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,15,5,12,5,\n0,0,0,0,0,0,12,7,0,0,0,0,0,0,8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,12,6,0,\n0,0,0,24,4,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,4,10,4,0,0,0,0,10,7,0,0,0,0,0,0,0,0,0,0,0,0,9,0,11,0,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,\n0,0,8,0,0,0,0,7,0,0,0,0,0,0,10,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,0,0,\n0,0,0,0,0,14,7,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,0,0,6,0,0,0,0,0,6,0,0,0,6,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,0,0,7,20,7,11,4,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19,7,9,6,0,0,12,7,0,0,0,0,0,0,10,0,12,0,\n0,0,0,0,0,4,9,6,13,0,0,0,0,0,0,0,0,6,0,0,0,6,0,0,0,5,0,0,0,0,0,0,8,0,0,0,0,0,0,\n0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,6,0,0,11,0,9,0,0,0,0,4,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,8,5,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,4,0,5,0,0,0,0,0,0,0,0,0,4,0,0,0,0,9,7,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,\n0,0,0,0,8,7,0,0,0,0,0,0,12,0,0,6,0,0,0,0,0,0,0,6,8,4,0,0,10,7,0,0,10,0,0,0,0,0,\n0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,7,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,4,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9,7,0,0,0,0,0,0,0,5,\n0,4,0,0,0,0,0,6,0,0,0,0,0,0,8,0,0,6,0,0,0,6,0,0,0,0,0,7,0,5,8,4,0,0,9,0,0,0,0,4,\n0,0,0,0,0,0,0,0,0,5,0,0,15,6,8,6,0,0,0,6,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,6,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,9,6,0,0,0,0,0,0,0,7,0,0,0,4,0,\n6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,9,5,0,6,12,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,8,7,0,6,0,0,0,0,0,0,0,0,0,0,0,0,11,0,12,7,0,0,0,0,\n0,0,0,0,0,5,0,5,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,4,0,0,0,0,0,0,0,0,0,0,10,\n7,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,7,8,7,9,6,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,5,12,0,\n10,5,12,6,0,0,0,7,0,0,0,0,0,0,0,5,0,0,0,5,9,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,\n11,7,0,0,0,0,0,0,0,0,0,0,17,0,0,0,0,0,0,6,0,7,0,0,0,0,8,0,8,5,0,6,0,0,0,6,0,0,0,\n0,0,0,0,6,0,6,0,6,9,0,0,5,17,0,0,0,0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,0,0,0,0,7,0,0,\n0,0,0,7,0,0,0,0,16,5,0,0,0,0,0,0,0,4,0,0,0,5,11,5,0,7,0,0,0,4,8,7,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,7,0,0,0,0,12,0,0,0,\n0,0,12,0,0,0,0,0,0,0,0,4,10,4,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,6,0,0,0,0,0,0,0,4,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,20,5,0,0,\n10,0,0,0,0,0,0,0,0,0,0,6,0,0,0,6,12,0,0,0,0,0,0,6,0,0,0,0,0,0,9,4,10,7,0,4,0,0,\n0,0,0,0,10,6,0,0,0,0,8,4,0,7,8,6,0,6,8,0,10,0,0,0,0,0,13,5,0,6,0,0,0,0,0,0,22,4,\n0,0,0,0,0,0,0,0,0,0,9,0,0,0,0,6,0,0,0,6,0,0,0,0,0,0,0,6,0,0,0,0,0,0,0,0,0,6,10,\n5,8,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,10,4,0,0,10,7,0,0,0,0,0,5,0,\n5,8,0,0,0,0,6,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,10,7,0,0,0,4,0,0,0,0,0,6,0,0,\n0,0,0,0,0,0,8,7,0,0,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,7,0,0,0,6,0,0,0,0,0,0,0,0,0,\n4,0,0,0,4,10,0,0,6,13,7,8,0,0,0,0,0,0,7,0,0,12,7,0,0,0,0,0,0,10,5,0,0,0,0,0,6,0,\n0,0,0,0,0,0,0,0,0,13,7,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,6,0,0,0,0,0,0,0,0,8,6,0,6,\n0,0,0,0,0,0,0,0,12,0,8,4,0,0,0,0,0,4,0,4,0,0,0,0,0,0,0,5,0,0,0,0,12,5,0,0,0,7,0,\n0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,10,0,0,0,20,0,0,5,0,0,10,\n7,11,7,0,0,0,0,0,0,0,0,0,0,17,0,9,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,10,7,0,4,0,6,0,0,24,0,0,5,0,0,0,0,8,0,0,\n0,0,0,0,0,10,5,0,4,0,6,0,0,8,0,0,0,0,0,0,4,0,6,0,0,0,0,0,0,9,5,0,0,0,0,0,0,0,0,\n0,0,0,6,0,0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,4,0,7,\n0,0,13,0,0,0,0,0,0,0,11,6,0,0,0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,\n17,7,0,0,11,6,0,0,0,0,12,6,0,0,0,6,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,0,0,0,6,0,0,0,0,0,0,0,0,0,0,10,0,0,4,8,6,0,0,0,\n0,0,0,9,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,9,5,0,7,18,0,0,0,0,0,0,0,0,0,0,0,0,0,8,6,0,0,0,0,0,0,0,0,8,0,0,0,\n0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,0,0,0,0,0,0,\n0,0,0,0,0,0,10,0,0,0,0,0,0,0,0,4,0,6,0,0,9,0,0,0,0,0,0,0,0,0,13,0,0,0,0,0,0,0,0,\n0,0,0,8,7,10,0,8,5,0,0,0,0,0,0,0,0,9,0,0,0,10,0,0,0,0,6,0,7,0,4,0,0,0,0,0,0,0,0,\n8,0,0,0,0,0,8,4,0,0,0,0,0,5,0,0,10,0,12,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n4,0,0,0,0,0,0,12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,18,6,11,0,0,\n7,0,0,0,0,0,6,10,5,0,0,0,0,0,0,0,0,0,5,0,0,9,5,12,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,6,0,0,0,0,13,6,0,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,\n0,0,0,8,4,0,6,12,0,0,0,0,0,0,0,0,0,0,0,0,6,0,6,0,0,0,0,0,5,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,11,4,0,0,0,6,14,0,11,0,9,6,0,0,0,0,0,0,22,0,12,0,8,6,0,0,0,0,0,0,0,6,0,\n0,0,0,0,6,0,0,0,0,0,0,0,0,0,0,11,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,0,0,0,0,0,0,\n10,7,0,0,0,0,0,0,0,0,9,0,0,0,0,4,0,0,0,0,0,0,0,0,0,5,11,0,0,0,0,0,0,0,8,6,0,0,9,\n7,0,0,12,4,0,0,0,0,0,0,12,6,0,6,0,7,0,0,8,5,0,0,0,0};\n/* GENERATED CODE END */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/dictionary_hash.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Hash table on the 4-byte prefixes of static dictionary words. */\n\n#ifndef BROTLI_ENC_DICTIONARY_HASH_H_\n#define BROTLI_ENC_DICTIONARY_HASH_H_\n\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nextern const uint16_t kStaticDictionaryHashWords[32768];\nextern const uint8_t kStaticDictionaryHashLengths[32768];\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_DICTIONARY_HASH_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/encode.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Implementation of Brotli compressor. */\n\n#include <brotli/encode.h>\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#include <stdlib.h>  /* free, malloc */\n#include <string.h>  /* memcpy, memset */\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"../common/version.h\"\n#include \"backward_references.h\"\n#include \"backward_references_hq.h\"\n#include \"bit_cost.h\"\n#include \"brotli_bit_stream.h\"\n#include \"compress_fragment.h\"\n#include \"compress_fragment_two_pass.h\"\n#include \"dictionary_hash.h\"\n#include \"encoder_dict.h\"\n#include \"entropy_encode.h\"\n#include \"fast_log.h\"\n#include \"hash.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"metablock.h\"\n#include \"prefix.h\"\n#include \"state.h\"\n#include \"quality.h\"\n#include \"ringbuffer.h\"\n#include \"utf8_util.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define COPY_ARRAY(dst, src) memcpy(dst, src, sizeof(src));\n\nstatic size_t InputBlockSize(BrotliEncoderState* s) {\n  return (size_t)1 << s->params.lgblock;\n}\n\nstatic uint64_t UnprocessedInputSize(BrotliEncoderState* s) {\n  return s->input_pos_ - s->last_processed_pos_;\n}\n\nstatic size_t RemainingInputBlockSize(BrotliEncoderState* s) {\n  const uint64_t delta = UnprocessedInputSize(s);\n  size_t block_size = InputBlockSize(s);\n  if (delta >= block_size) return 0;\n  return block_size - (size_t)delta;\n}\n\nBROTLI_BOOL BrotliEncoderSetParameter(\n    BrotliEncoderState* state, BrotliEncoderParameter p, uint32_t value) {\n  /* Changing parameters on the fly is not implemented yet. */\n  if (state->is_initialized_) return BROTLI_FALSE;\n  /* TODO(eustas): Validate/clamp parameters here. */\n  switch (p) {\n    case BROTLI_PARAM_MODE:\n      state->params.mode = (BrotliEncoderMode)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_QUALITY:\n      state->params.quality = (int)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_LGWIN:\n      state->params.lgwin = (int)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_LGBLOCK:\n      state->params.lgblock = (int)value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING:\n      if ((value != 0) && (value != 1)) return BROTLI_FALSE;\n      state->params.disable_literal_context_modeling = TO_BROTLI_BOOL(!!value);\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_SIZE_HINT:\n      state->params.size_hint = value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_LARGE_WINDOW:\n      state->params.large_window = TO_BROTLI_BOOL(!!value);\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_NPOSTFIX:\n      state->params.dist.distance_postfix_bits = value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_NDIRECT:\n      state->params.dist.num_direct_distance_codes = value;\n      return BROTLI_TRUE;\n\n    case BROTLI_PARAM_STREAM_OFFSET:\n      if (value > (1u << 30)) return BROTLI_FALSE;\n      state->params.stream_offset = value;\n      return BROTLI_TRUE;\n\n    default: return BROTLI_FALSE;\n  }\n}\n\n/* Wraps 64-bit input position to 32-bit ring-buffer position preserving\n   \"not-a-first-lap\" feature. */\nstatic uint32_t WrapPosition(uint64_t position) {\n  uint32_t result = (uint32_t)position;\n  uint64_t gb = position >> 30;\n  if (gb > 2) {\n    /* Wrap every 2GiB; The first 3GB are continuous. */\n    result = (result & ((1u << 30) - 1)) | ((uint32_t)((gb - 1) & 1) + 1) << 30;\n  }\n  return result;\n}\n\nstatic uint8_t* GetBrotliStorage(BrotliEncoderState* s, size_t size) {\n  MemoryManager* m = &s->memory_manager_;\n  if (s->storage_size_ < size) {\n    BROTLI_FREE(m, s->storage_);\n    s->storage_ = BROTLI_ALLOC(m, uint8_t, size);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->storage_)) return NULL;\n    s->storage_size_ = size;\n  }\n  return s->storage_;\n}\n\nstatic size_t HashTableSize(size_t max_table_size, size_t input_size) {\n  size_t htsize = 256;\n  while (htsize < max_table_size && htsize < input_size) {\n    htsize <<= 1;\n  }\n  return htsize;\n}\n\nstatic int* GetHashTable(BrotliEncoderState* s, int quality,\n                         size_t input_size, size_t* table_size) {\n  /* Use smaller hash table when input.size() is smaller, since we\n     fill the table, incurring O(hash table size) overhead for\n     compression, and if the input is short, we won't need that\n     many hash table entries anyway. */\n  MemoryManager* m = &s->memory_manager_;\n  const size_t max_table_size = MaxHashTableSize(quality);\n  size_t htsize = HashTableSize(max_table_size, input_size);\n  int* table;\n  BROTLI_DCHECK(max_table_size >= 256);\n  if (quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n    /* Only odd shifts are supported by fast-one-pass. */\n    if ((htsize & 0xAAAAA) == 0) {\n      htsize <<= 1;\n    }\n  }\n\n  if (htsize <= sizeof(s->small_table_) / sizeof(s->small_table_[0])) {\n    table = s->small_table_;\n  } else {\n    if (htsize > s->large_table_size_) {\n      s->large_table_size_ = htsize;\n      BROTLI_FREE(m, s->large_table_);\n      s->large_table_ = BROTLI_ALLOC(m, int, htsize);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->large_table_)) return 0;\n    }\n    table = s->large_table_;\n  }\n\n  *table_size = htsize;\n  memset(table, 0, htsize * sizeof(*table));\n  return table;\n}\n\nstatic void EncodeWindowBits(int lgwin, BROTLI_BOOL large_window,\n    uint16_t* last_bytes, uint8_t* last_bytes_bits) {\n  if (large_window) {\n    *last_bytes = (uint16_t)(((lgwin & 0x3F) << 8) | 0x11);\n    *last_bytes_bits = 14;\n  } else {\n    if (lgwin == 16) {\n      *last_bytes = 0;\n      *last_bytes_bits = 1;\n    } else if (lgwin == 17) {\n      *last_bytes = 1;\n      *last_bytes_bits = 7;\n    } else if (lgwin > 17) {\n      *last_bytes = (uint16_t)(((lgwin - 17) << 1) | 0x01);\n      *last_bytes_bits = 4;\n    } else {\n      *last_bytes = (uint16_t)(((lgwin - 8) << 4) | 0x01);\n      *last_bytes_bits = 7;\n    }\n  }\n}\n\n/* TODO(eustas): move to compress_fragment.c? */\n/* Initializes the command and distance prefix codes for the first block. */\nstatic void InitCommandPrefixCodes(BrotliOnePassArena* s) {\n  static const uint8_t kDefaultCommandDepths[128] = {\n    0, 4, 4, 5, 6, 6, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8,\n    0, 0, 0, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7,\n    7, 7, 10, 10, 10, 10, 10, 10, 0, 4, 4, 5, 5, 5, 6, 6,\n    7, 8, 8, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,\n    5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4,\n    4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 7, 7, 7, 8, 10,\n    12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n  };\n  static const uint16_t kDefaultCommandBits[128] = {\n    0,   0,   8,   9,   3,  35,   7,   71,\n    39, 103,  23,  47, 175, 111, 239,   31,\n    0,   0,   0,   4,  12,   2,  10,    6,\n    13,  29,  11,  43,  27,  59,  87,   55,\n    15,  79, 319, 831, 191, 703, 447,  959,\n    0,  14,   1,  25,   5,  21,  19,   51,\n    119, 159,  95, 223, 479, 991,  63,  575,\n    127, 639, 383, 895, 255, 767, 511, 1023,\n    14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    27, 59, 7, 39, 23, 55, 30, 1, 17, 9, 25, 5, 0, 8, 4, 12,\n    2, 10, 6, 21, 13, 29, 3, 19, 11, 15, 47, 31, 95, 63, 127, 255,\n    767, 2815, 1791, 3839, 511, 2559, 1535, 3583, 1023, 3071, 2047, 4095,\n  };\n  static const uint8_t kDefaultCommandCode[] = {\n    0xff, 0x77, 0xd5, 0xbf, 0xe7, 0xde, 0xea, 0x9e, 0x51, 0x5d, 0xde, 0xc6,\n    0x70, 0x57, 0xbc, 0x58, 0x58, 0x58, 0xd8, 0xd8, 0x58, 0xd5, 0xcb, 0x8c,\n    0xea, 0xe0, 0xc3, 0x87, 0x1f, 0x83, 0xc1, 0x60, 0x1c, 0x67, 0xb2, 0xaa,\n    0x06, 0x83, 0xc1, 0x60, 0x30, 0x18, 0xcc, 0xa1, 0xce, 0x88, 0x54, 0x94,\n    0x46, 0xe1, 0xb0, 0xd0, 0x4e, 0xb2, 0xf7, 0x04, 0x00,\n  };\n  static const size_t kDefaultCommandCodeNumBits = 448;\n  COPY_ARRAY(s->cmd_depth, kDefaultCommandDepths);\n  COPY_ARRAY(s->cmd_bits, kDefaultCommandBits);\n\n  /* Initialize the pre-compressed form of the command and distance prefix\n     codes. */\n  COPY_ARRAY(s->cmd_code, kDefaultCommandCode);\n  s->cmd_code_numbits = kDefaultCommandCodeNumBits;\n}\n\n/* Decide about the context map based on the ability of the prediction\n   ability of the previous byte UTF8-prefix on the next byte. The\n   prediction ability is calculated as Shannon entropy. Here we need\n   Shannon entropy instead of 'BitsEntropy' since the prefix will be\n   encoded with the remaining 6 bits of the following byte, and\n   BitsEntropy will assume that symbol to be stored alone using Huffman\n   coding. */\nstatic void ChooseContextMap(int quality,\n                             uint32_t* bigram_histo,\n                             size_t* num_literal_contexts,\n                             const uint32_t** literal_context_map) {\n  static const uint32_t kStaticContextMapContinuation[64] = {\n    1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  };\n  static const uint32_t kStaticContextMapSimpleUTF8[64] = {\n    0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,\n  };\n\n  uint32_t monogram_histo[3] = { 0 };\n  uint32_t two_prefix_histo[6] = { 0 };\n  size_t total;\n  size_t i;\n  size_t dummy;\n  double entropy[4];\n  for (i = 0; i < 9; ++i) {\n    monogram_histo[i % 3] += bigram_histo[i];\n    two_prefix_histo[i % 6] += bigram_histo[i];\n  }\n  entropy[1] = ShannonEntropy(monogram_histo, 3, &dummy);\n  entropy[2] = (ShannonEntropy(two_prefix_histo, 3, &dummy) +\n                ShannonEntropy(two_prefix_histo + 3, 3, &dummy));\n  entropy[3] = 0;\n  for (i = 0; i < 3; ++i) {\n    entropy[3] += ShannonEntropy(bigram_histo + 3 * i, 3, &dummy);\n  }\n\n  total = monogram_histo[0] + monogram_histo[1] + monogram_histo[2];\n  BROTLI_DCHECK(total != 0);\n  entropy[0] = 1.0 / (double)total;\n  entropy[1] *= entropy[0];\n  entropy[2] *= entropy[0];\n  entropy[3] *= entropy[0];\n\n  if (quality < MIN_QUALITY_FOR_HQ_CONTEXT_MODELING) {\n    /* 3 context models is a bit slower, don't use it at lower qualities. */\n    entropy[3] = entropy[1] * 10;\n  }\n  /* If expected savings by symbol are less than 0.2 bits, skip the\n     context modeling -- in exchange for faster decoding speed. */\n  if (entropy[1] - entropy[2] < 0.2 &&\n      entropy[1] - entropy[3] < 0.2) {\n    *num_literal_contexts = 1;\n  } else if (entropy[2] - entropy[3] < 0.02) {\n    *num_literal_contexts = 2;\n    *literal_context_map = kStaticContextMapSimpleUTF8;\n  } else {\n    *num_literal_contexts = 3;\n    *literal_context_map = kStaticContextMapContinuation;\n  }\n}\n\n/* Decide if we want to use a more complex static context map containing 13\n   context values, based on the entropy reduction of histograms over the\n   first 5 bits of literals. */\nstatic BROTLI_BOOL ShouldUseComplexStaticContextMap(const uint8_t* input,\n    size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint,\n    size_t* num_literal_contexts, const uint32_t** literal_context_map,\n    uint32_t* arena) {\n  static const uint32_t kStaticContextMapComplexUTF8[64] = {\n    11, 11, 12, 12, /* 0 special */\n    0, 0, 0, 0, /* 4 lf */\n    1, 1, 9, 9, /* 8 space */\n    2, 2, 2, 2, /* !, first after space/lf and after something else. */\n    1, 1, 1, 1, /* \" */\n    8, 3, 3, 3, /* % */\n    1, 1, 1, 1, /* ({[ */\n    2, 2, 2, 2, /* }]) */\n    8, 4, 4, 4, /* :; */\n    8, 7, 4, 4, /* . */\n    8, 0, 0, 0, /* > */\n    3, 3, 3, 3, /* [0..9] */\n    5, 5, 10, 5, /* [A-Z] */\n    5, 5, 10, 5,\n    6, 6, 6, 6, /* [a-z] */\n    6, 6, 6, 6,\n  };\n  BROTLI_UNUSED(quality);\n  /* Try the more complex static context map only for long data. */\n  if (size_hint < (1 << 20)) {\n    return BROTLI_FALSE;\n  } else {\n    const size_t end_pos = start_pos + length;\n    /* To make entropy calculations faster, we collect histograms\n       over the 5 most significant bits of literals. One histogram\n       without context and 13 additional histograms for each context value. */\n    uint32_t* BROTLI_RESTRICT const combined_histo = arena;\n    uint32_t* BROTLI_RESTRICT const context_histo = arena + 32;\n    uint32_t total = 0;\n    double entropy[3];\n    size_t dummy;\n    size_t i;\n    ContextLut utf8_lut = BROTLI_CONTEXT_LUT(CONTEXT_UTF8);\n    memset(arena, 0, sizeof(arena[0]) * 32 * 14);\n    for (; start_pos + 64 <= end_pos; start_pos += 4096) {\n      const size_t stride_end_pos = start_pos + 64;\n      uint8_t prev2 = input[start_pos & mask];\n      uint8_t prev1 = input[(start_pos + 1) & mask];\n      size_t pos;\n      /* To make the analysis of the data faster we only examine 64 byte long\n         strides at every 4kB intervals. */\n      for (pos = start_pos + 2; pos < stride_end_pos; ++pos) {\n        const uint8_t literal = input[pos & mask];\n        const uint8_t context = (uint8_t)kStaticContextMapComplexUTF8[\n            BROTLI_CONTEXT(prev1, prev2, utf8_lut)];\n        ++total;\n        ++combined_histo[literal >> 3];\n        ++context_histo[(context << 5) + (literal >> 3)];\n        prev2 = prev1;\n        prev1 = literal;\n      }\n    }\n    entropy[1] = ShannonEntropy(combined_histo, 32, &dummy);\n    entropy[2] = 0;\n    for (i = 0; i < 13; ++i) {\n      entropy[2] += ShannonEntropy(context_histo + (i << 5), 32, &dummy);\n    }\n    entropy[0] = 1.0 / (double)total;\n    entropy[1] *= entropy[0];\n    entropy[2] *= entropy[0];\n    /* The triggering heuristics below were tuned by compressing the individual\n       files of the silesia corpus. If we skip this kind of context modeling\n       for not very well compressible input (i.e. entropy using context modeling\n       is 60% of maximal entropy) or if expected savings by symbol are less\n       than 0.2 bits, then in every case when it triggers, the final compression\n       ratio is improved. Note however that this heuristics might be too strict\n       for some cases and could be tuned further. */\n    if (entropy[2] > 3.0 || entropy[1] - entropy[2] < 0.2) {\n      return BROTLI_FALSE;\n    } else {\n      *num_literal_contexts = 13;\n      *literal_context_map = kStaticContextMapComplexUTF8;\n      return BROTLI_TRUE;\n    }\n  }\n}\n\nstatic void DecideOverLiteralContextModeling(const uint8_t* input,\n    size_t start_pos, size_t length, size_t mask, int quality, size_t size_hint,\n    size_t* num_literal_contexts, const uint32_t** literal_context_map,\n    uint32_t* arena) {\n  if (quality < MIN_QUALITY_FOR_CONTEXT_MODELING || length < 64) {\n    return;\n  } else if (ShouldUseComplexStaticContextMap(\n      input, start_pos, length, mask, quality, size_hint,\n      num_literal_contexts, literal_context_map, arena)) {\n    /* Context map was already set, nothing else to do. */\n  } else {\n    /* Gather bi-gram data of the UTF8 byte prefixes. To make the analysis of\n       UTF8 data faster we only examine 64 byte long strides at every 4kB\n       intervals. */\n    const size_t end_pos = start_pos + length;\n    uint32_t* BROTLI_RESTRICT const bigram_prefix_histo = arena;\n    memset(bigram_prefix_histo, 0, sizeof(arena[0]) * 9);\n    for (; start_pos + 64 <= end_pos; start_pos += 4096) {\n      static const int lut[4] = { 0, 0, 1, 2 };\n      const size_t stride_end_pos = start_pos + 64;\n      int prev = lut[input[start_pos & mask] >> 6] * 3;\n      size_t pos;\n      for (pos = start_pos + 1; pos < stride_end_pos; ++pos) {\n        const uint8_t literal = input[pos & mask];\n        ++bigram_prefix_histo[prev + lut[literal >> 6]];\n        prev = lut[literal >> 6] * 3;\n      }\n    }\n    ChooseContextMap(quality, &bigram_prefix_histo[0], num_literal_contexts,\n                     literal_context_map);\n  }\n}\n\nstatic BROTLI_BOOL ShouldCompress(\n    const uint8_t* data, const size_t mask, const uint64_t last_flush_pos,\n    const size_t bytes, const size_t num_literals, const size_t num_commands) {\n  /* TODO(eustas): find more precise minimal block overhead. */\n  if (bytes <= 2) return BROTLI_FALSE;\n  if (num_commands < (bytes >> 8) + 2) {\n    if ((double)num_literals > 0.99 * (double)bytes) {\n      uint32_t literal_histo[256] = { 0 };\n      static const uint32_t kSampleRate = 13;\n      static const double kMinEntropy = 7.92;\n      const double bit_cost_threshold =\n          (double)bytes * kMinEntropy / kSampleRate;\n      size_t t = (bytes + kSampleRate - 1) / kSampleRate;\n      uint32_t pos = (uint32_t)last_flush_pos;\n      size_t i;\n      for (i = 0; i < t; i++) {\n        ++literal_histo[data[pos & mask]];\n        pos += kSampleRate;\n      }\n      if (BitsEntropy(literal_histo, 256) > bit_cost_threshold) {\n        return BROTLI_FALSE;\n      }\n    }\n  }\n  return BROTLI_TRUE;\n}\n\n/* Chooses the literal context mode for a metablock */\nstatic ContextType ChooseContextMode(const BrotliEncoderParams* params,\n    const uint8_t* data, const size_t pos, const size_t mask,\n    const size_t length) {\n  /* We only do the computation for the option of something else than\n     CONTEXT_UTF8 for the highest qualities */\n  if (params->quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING &&\n      !BrotliIsMostlyUTF8(data, pos, mask, length, kMinUTF8Ratio)) {\n    return CONTEXT_SIGNED;\n  }\n  return CONTEXT_UTF8;\n}\n\nstatic void WriteMetaBlockInternal(MemoryManager* m,\n                                   const uint8_t* data,\n                                   const size_t mask,\n                                   const uint64_t last_flush_pos,\n                                   const size_t bytes,\n                                   const BROTLI_BOOL is_last,\n                                   ContextType literal_context_mode,\n                                   const BrotliEncoderParams* params,\n                                   const uint8_t prev_byte,\n                                   const uint8_t prev_byte2,\n                                   const size_t num_literals,\n                                   const size_t num_commands,\n                                   Command* commands,\n                                   const int* saved_dist_cache,\n                                   int* dist_cache,\n                                   size_t* storage_ix,\n                                   uint8_t* storage) {\n  const uint32_t wrapped_last_flush_pos = WrapPosition(last_flush_pos);\n  uint16_t last_bytes;\n  uint8_t last_bytes_bits;\n  ContextLut literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);\n  BrotliEncoderParams block_params = *params;\n\n  if (bytes == 0) {\n    /* Write the ISLAST and ISEMPTY bits. */\n    BrotliWriteBits(2, 3, storage_ix, storage);\n    *storage_ix = (*storage_ix + 7u) & ~7u;\n    return;\n  }\n\n  if (!ShouldCompress(data, mask, last_flush_pos, bytes,\n                      num_literals, num_commands)) {\n    /* Restore the distance cache, as its last update by\n       CreateBackwardReferences is now unused. */\n    memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));\n    BrotliStoreUncompressedMetaBlock(is_last, data,\n                                     wrapped_last_flush_pos, mask, bytes,\n                                     storage_ix, storage);\n    return;\n  }\n\n  BROTLI_DCHECK(*storage_ix <= 14);\n  last_bytes = (uint16_t)((storage[1] << 8) | storage[0]);\n  last_bytes_bits = (uint8_t)(*storage_ix);\n  if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) {\n    BrotliStoreMetaBlockFast(m, data, wrapped_last_flush_pos,\n                             bytes, mask, is_last, params,\n                             commands, num_commands,\n                             storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {\n    BrotliStoreMetaBlockTrivial(m, data, wrapped_last_flush_pos,\n                                bytes, mask, is_last, params,\n                                commands, num_commands,\n                                storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n  } else {\n    MetaBlockSplit mb;\n    InitMetaBlockSplit(&mb);\n    if (params->quality < MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {\n      size_t num_literal_contexts = 1;\n      const uint32_t* literal_context_map = NULL;\n      if (!params->disable_literal_context_modeling) {\n        /* TODO(eustas): pull to higher level and reuse. */\n        uint32_t* arena = BROTLI_ALLOC(m, uint32_t, 14 * 32);\n        if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n        DecideOverLiteralContextModeling(\n            data, wrapped_last_flush_pos, bytes, mask, params->quality,\n            params->size_hint, &num_literal_contexts,\n            &literal_context_map, arena);\n        BROTLI_FREE(m, arena);\n      }\n      BrotliBuildMetaBlockGreedy(m, data, wrapped_last_flush_pos, mask,\n          prev_byte, prev_byte2, literal_context_lut, num_literal_contexts,\n          literal_context_map, commands, num_commands, &mb);\n      if (BROTLI_IS_OOM(m)) return;\n    } else {\n      BrotliBuildMetaBlock(m, data, wrapped_last_flush_pos, mask, &block_params,\n                           prev_byte, prev_byte2,\n                           commands, num_commands,\n                           literal_context_mode,\n                           &mb);\n      if (BROTLI_IS_OOM(m)) return;\n    }\n    if (params->quality >= MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS) {\n      /* The number of distance symbols effectively used for distance\n         histograms. It might be less than distance alphabet size\n         for \"Large Window Brotli\" (32-bit). */\n      BrotliOptimizeHistograms(block_params.dist.alphabet_size_limit, &mb);\n    }\n    BrotliStoreMetaBlock(m, data, wrapped_last_flush_pos, bytes, mask,\n                         prev_byte, prev_byte2,\n                         is_last,\n                         &block_params,\n                         literal_context_mode,\n                         commands, num_commands,\n                         &mb,\n                         storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return;\n    DestroyMetaBlockSplit(m, &mb);\n  }\n  if (bytes + 4 < (*storage_ix >> 3)) {\n    /* Restore the distance cache and last byte. */\n    memcpy(dist_cache, saved_dist_cache, 4 * sizeof(dist_cache[0]));\n    storage[0] = (uint8_t)last_bytes;\n    storage[1] = (uint8_t)(last_bytes >> 8);\n    *storage_ix = last_bytes_bits;\n    BrotliStoreUncompressedMetaBlock(is_last, data,\n                                     wrapped_last_flush_pos, mask,\n                                     bytes, storage_ix, storage);\n  }\n}\n\nstatic void ChooseDistanceParams(BrotliEncoderParams* params) {\n  uint32_t distance_postfix_bits = 0;\n  uint32_t num_direct_distance_codes = 0;\n\n  if (params->quality >= MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS) {\n    uint32_t ndirect_msb;\n    if (params->mode == BROTLI_MODE_FONT) {\n      distance_postfix_bits = 1;\n      num_direct_distance_codes = 12;\n    } else {\n      distance_postfix_bits = params->dist.distance_postfix_bits;\n      num_direct_distance_codes = params->dist.num_direct_distance_codes;\n    }\n    ndirect_msb = (num_direct_distance_codes >> distance_postfix_bits) & 0x0F;\n    if (distance_postfix_bits > BROTLI_MAX_NPOSTFIX ||\n        num_direct_distance_codes > BROTLI_MAX_NDIRECT ||\n        (ndirect_msb << distance_postfix_bits) != num_direct_distance_codes) {\n      distance_postfix_bits = 0;\n      num_direct_distance_codes = 0;\n    }\n  }\n\n  BrotliInitDistanceParams(&params->dist, distance_postfix_bits,\n                           num_direct_distance_codes, params->large_window);\n}\n\nstatic BROTLI_BOOL EnsureInitialized(BrotliEncoderState* s) {\n  MemoryManager* m = &s->memory_manager_;\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  if (s->is_initialized_) return BROTLI_TRUE;\n\n  s->last_bytes_bits_ = 0;\n  s->last_bytes_ = 0;\n  s->flint_ = BROTLI_FLINT_DONE;\n  s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;\n\n  SanitizeParams(&s->params);\n  s->params.lgblock = ComputeLgBlock(&s->params);\n  ChooseDistanceParams(&s->params);\n\n  if (s->params.stream_offset != 0) {\n    s->flint_ = BROTLI_FLINT_NEEDS_2_BYTES;\n    /* Poison the distance cache. -16 +- 3 is still less than zero (invalid). */\n    s->dist_cache_[0] = -16;\n    s->dist_cache_[1] = -16;\n    s->dist_cache_[2] = -16;\n    s->dist_cache_[3] = -16;\n    memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));\n  }\n\n  RingBufferSetup(&s->params, &s->ringbuffer_);\n\n  /* Initialize last byte with stream header. */\n  {\n    int lgwin = s->params.lgwin;\n    if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n        s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n      lgwin = BROTLI_MAX(int, lgwin, 18);\n    }\n    if (s->params.stream_offset == 0) {\n      EncodeWindowBits(lgwin, s->params.large_window,\n                       &s->last_bytes_, &s->last_bytes_bits_);\n    } else {\n      /* Bigger values have the same effect, but could cause overflows. */\n      s->params.stream_offset = BROTLI_MIN(size_t,\n          s->params.stream_offset, BROTLI_MAX_BACKWARD_LIMIT(lgwin));\n    }\n  }\n\n  if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n    s->one_pass_arena_ = BROTLI_ALLOC(m, BrotliOnePassArena, 1);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    InitCommandPrefixCodes(s->one_pass_arena_);\n  } else if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    s->two_pass_arena_ = BROTLI_ALLOC(m, BrotliTwoPassArena, 1);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  }\n\n  s->is_initialized_ = BROTLI_TRUE;\n  return BROTLI_TRUE;\n}\n\nstatic void BrotliEncoderInitParams(BrotliEncoderParams* params) {\n  params->mode = BROTLI_DEFAULT_MODE;\n  params->large_window = BROTLI_FALSE;\n  params->quality = BROTLI_DEFAULT_QUALITY;\n  params->lgwin = BROTLI_DEFAULT_WINDOW;\n  params->lgblock = 0;\n  params->stream_offset = 0;\n  params->size_hint = 0;\n  params->disable_literal_context_modeling = BROTLI_FALSE;\n  BrotliInitSharedEncoderDictionary(&params->dictionary);\n  params->dist.distance_postfix_bits = 0;\n  params->dist.num_direct_distance_codes = 0;\n  params->dist.alphabet_size_max =\n      BROTLI_DISTANCE_ALPHABET_SIZE(0, 0, BROTLI_MAX_DISTANCE_BITS);\n  params->dist.alphabet_size_limit = params->dist.alphabet_size_max;\n  params->dist.max_distance = BROTLI_MAX_DISTANCE;\n}\n\nstatic void BrotliEncoderCleanupParams(MemoryManager* m,\n    BrotliEncoderParams* params) {\n  BrotliCleanupSharedEncoderDictionary(m, &params->dictionary);\n}\n\nstatic void BrotliEncoderInitState(BrotliEncoderState* s) {\n  BrotliEncoderInitParams(&s->params);\n  s->input_pos_ = 0;\n  s->num_commands_ = 0;\n  s->num_literals_ = 0;\n  s->last_insert_len_ = 0;\n  s->last_flush_pos_ = 0;\n  s->last_processed_pos_ = 0;\n  s->prev_byte_ = 0;\n  s->prev_byte2_ = 0;\n  s->storage_size_ = 0;\n  s->storage_ = 0;\n  HasherInit(&s->hasher_);\n  s->large_table_ = NULL;\n  s->large_table_size_ = 0;\n  s->one_pass_arena_ = NULL;\n  s->two_pass_arena_ = NULL;\n  s->command_buf_ = NULL;\n  s->literal_buf_ = NULL;\n  s->total_in_ = 0;\n  s->next_out_ = NULL;\n  s->available_out_ = 0;\n  s->total_out_ = 0;\n  s->stream_state_ = BROTLI_STREAM_PROCESSING;\n  s->is_last_block_emitted_ = BROTLI_FALSE;\n  s->is_initialized_ = BROTLI_FALSE;\n\n  RingBufferInit(&s->ringbuffer_);\n\n  s->commands_ = 0;\n  s->cmd_alloc_size_ = 0;\n\n  /* Initialize distance cache. */\n  s->dist_cache_[0] = 4;\n  s->dist_cache_[1] = 11;\n  s->dist_cache_[2] = 15;\n  s->dist_cache_[3] = 16;\n  /* Save the state of the distance cache in case we need to restore it for\n     emitting an uncompressed block. */\n  memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));\n}\n\nBrotliEncoderState* BrotliEncoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  BrotliEncoderState* state = (BrotliEncoderState*)BrotliBootstrapAlloc(\n      sizeof(BrotliEncoderState), alloc_func, free_func, opaque);\n  if (state == NULL) {\n    /* BROTLI_DUMP(); */\n    return 0;\n  }\n  BrotliInitMemoryManager(\n      &state->memory_manager_, alloc_func, free_func, opaque);\n  BrotliEncoderInitState(state);\n  return state;\n}\n\n#ifdef BROTLI_REPORTING\n/* When BROTLI_REPORTING is defined extra reporting module have to be linked. */\nvoid BrotliEncoderOnFinish(const BrotliEncoderState* s);\n#define BROTLI_ENCODER_ON_FINISH(s) BrotliEncoderOnFinish(s);\n#else\n#if !defined(BROTLI_ENCODER_ON_FINISH)\n#define BROTLI_ENCODER_ON_FINISH(s) (void)(s);\n#endif\n#endif\n\nstatic void BrotliEncoderCleanupState(BrotliEncoderState* s) {\n  MemoryManager* m = &s->memory_manager_;\n\n  BROTLI_ENCODER_ON_FINISH(s);\n\n  if (BROTLI_IS_OOM(m)) {\n    BrotliWipeOutMemoryManager(m);\n    return;\n  }\n\n  BROTLI_FREE(m, s->storage_);\n  BROTLI_FREE(m, s->commands_);\n  RingBufferFree(m, &s->ringbuffer_);\n  DestroyHasher(m, &s->hasher_);\n  BROTLI_FREE(m, s->large_table_);\n  BROTLI_FREE(m, s->one_pass_arena_);\n  BROTLI_FREE(m, s->two_pass_arena_);\n  BROTLI_FREE(m, s->command_buf_);\n  BROTLI_FREE(m, s->literal_buf_);\n  BrotliEncoderCleanupParams(m, &s->params);\n}\n\n/* Deinitializes and frees BrotliEncoderState instance. */\nvoid BrotliEncoderDestroyInstance(BrotliEncoderState* state) {\n  if (!state) {\n    return;\n  } else {\n    BrotliEncoderCleanupState(state);\n    BrotliBootstrapFree(state, &state->memory_manager_);\n  }\n}\n\n/*\n   Copies the given input data to the internal ring buffer of the compressor.\n   No processing of the data occurs at this time and this function can be\n   called multiple times before calling WriteBrotliData() to process the\n   accumulated input. At most input_block_size() bytes of input data can be\n   copied to the ring buffer, otherwise the next WriteBrotliData() will fail.\n */\nstatic void CopyInputToRingBuffer(BrotliEncoderState* s,\n                                  const size_t input_size,\n                                  const uint8_t* input_buffer) {\n  RingBuffer* ringbuffer_ = &s->ringbuffer_;\n  MemoryManager* m = &s->memory_manager_;\n  RingBufferWrite(m, input_buffer, input_size, ringbuffer_);\n  if (BROTLI_IS_OOM(m)) return;\n  s->input_pos_ += input_size;\n\n  /* TL;DR: If needed, initialize 7 more bytes in the ring buffer to make the\n     hashing not depend on uninitialized data. This makes compression\n     deterministic and it prevents uninitialized memory warnings in Valgrind.\n     Even without erasing, the output would be valid (but nondeterministic).\n\n     Background information: The compressor stores short (at most 8 bytes)\n     substrings of the input already read in a hash table, and detects\n     repetitions by looking up such substrings in the hash table. If it\n     can find a substring, it checks whether the substring is really there\n     in the ring buffer (or it's just a hash collision). Should the hash\n     table become corrupt, this check makes sure that the output is\n     still valid, albeit the compression ratio would be bad.\n\n     The compressor populates the hash table from the ring buffer as it's\n     reading new bytes from the input. However, at the last few indexes of\n     the ring buffer, there are not enough bytes to build full-length\n     substrings from. Since the hash table always contains full-length\n     substrings, we erase with dummy zeros here to make sure that those\n     substrings will contain zeros at the end instead of uninitialized\n     data.\n\n     Please note that erasing is not necessary (because the\n     memory region is already initialized since he ring buffer\n     has a `tail' that holds a copy of the beginning,) so we\n     skip erasing if we have already gone around at least once in\n     the ring buffer.\n\n     Only clear during the first round of ring-buffer writes. On\n     subsequent rounds data in the ring-buffer would be affected. */\n  if (ringbuffer_->pos_ <= ringbuffer_->mask_) {\n    /* This is the first time when the ring buffer is being written.\n       We clear 7 bytes just after the bytes that have been copied from\n       the input buffer.\n\n       The ring-buffer has a \"tail\" that holds a copy of the beginning,\n       but only once the ring buffer has been fully written once, i.e.,\n       pos <= mask. For the first time, we need to write values\n       in this tail (where index may be larger than mask), so that\n       we have exactly defined behavior and don't read uninitialized\n       memory. Due to performance reasons, hashing reads data using a\n       LOAD64, which can go 7 bytes beyond the bytes written in the\n       ring-buffer. */\n    memset(ringbuffer_->buffer_ + ringbuffer_->pos_, 0, 7);\n  }\n}\n\n/* Marks all input as processed.\n   Returns true if position wrapping occurs. */\nstatic BROTLI_BOOL UpdateLastProcessedPos(BrotliEncoderState* s) {\n  uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);\n  uint32_t wrapped_input_pos = WrapPosition(s->input_pos_);\n  s->last_processed_pos_ = s->input_pos_;\n  return TO_BROTLI_BOOL(wrapped_input_pos < wrapped_last_processed_pos);\n}\n\nstatic void ExtendLastCommand(BrotliEncoderState* s, uint32_t* bytes,\n                              uint32_t* wrapped_last_processed_pos) {\n  Command* last_command = &s->commands_[s->num_commands_ - 1];\n  const uint8_t* data = s->ringbuffer_.buffer_;\n  const uint32_t mask = s->ringbuffer_.mask_;\n  uint64_t max_backward_distance =\n      (((uint64_t)1) << s->params.lgwin) - BROTLI_WINDOW_GAP;\n  uint64_t last_copy_len = last_command->copy_len_ & 0x1FFFFFF;\n  uint64_t last_processed_pos = s->last_processed_pos_ - last_copy_len;\n  uint64_t max_distance = last_processed_pos < max_backward_distance ?\n      last_processed_pos : max_backward_distance;\n  uint64_t cmd_dist = (uint64_t)s->dist_cache_[0];\n  uint32_t distance_code = CommandRestoreDistanceCode(last_command,\n                                                      &s->params.dist);\n  const CompoundDictionary* dict = &s->params.dictionary.compound;\n  size_t compound_dictionary_size = dict->total_size;\n  if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES ||\n      distance_code - (BROTLI_NUM_DISTANCE_SHORT_CODES - 1) == cmd_dist) {\n    if (cmd_dist <= max_distance) {\n      while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==\n             data[(*wrapped_last_processed_pos - cmd_dist) & mask]) {\n        last_command->copy_len_++;\n        (*bytes)--;\n        (*wrapped_last_processed_pos)++;\n      }\n    } else {\n      if ((cmd_dist - max_distance - 1) < compound_dictionary_size &&\n          last_copy_len < cmd_dist - max_distance) {\n        size_t address =\n            compound_dictionary_size - (size_t)(cmd_dist - max_distance) +\n            (size_t)last_copy_len;\n        size_t br_index = 0;\n        size_t br_offset;\n        const uint8_t* chunk;\n        size_t chunk_length;\n        while (address >= dict->chunk_offsets[br_index + 1]) br_index++;\n        br_offset = address - dict->chunk_offsets[br_index];\n        chunk = dict->chunk_source[br_index];\n        chunk_length =\n            dict->chunk_offsets[br_index + 1] - dict->chunk_offsets[br_index];\n        while (*bytes != 0 && data[*wrapped_last_processed_pos & mask] ==\n               chunk[br_offset]) {\n          last_command->copy_len_++;\n          (*bytes)--;\n          (*wrapped_last_processed_pos)++;\n          if (++br_offset == chunk_length) {\n            br_index++;\n            br_offset = 0;\n            if (br_index != dict->num_chunks) {\n              chunk = dict->chunk_source[br_index];\n              chunk_length = dict->chunk_offsets[br_index + 1] -\n                  dict->chunk_offsets[br_index];\n            } else {\n              break;\n            }\n          }\n        }\n      }\n    }\n    /* The copy length is at most the metablock size, and thus expressible. */\n    GetLengthCode(last_command->insert_len_,\n                  (size_t)((int)(last_command->copy_len_ & 0x1FFFFFF) +\n                           (int)(last_command->copy_len_ >> 25)),\n                  TO_BROTLI_BOOL((last_command->dist_prefix_ & 0x3FF) == 0),\n                  &last_command->cmd_prefix_);\n  }\n}\n\n/*\n   Processes the accumulated input data and sets |*out_size| to the length of\n   the new output meta-block, or to zero if no new output meta-block has been\n   created (in this case the processed input data is buffered internally).\n   If |*out_size| is positive, |*output| points to the start of the output\n   data. If |is_last| or |force_flush| is BROTLI_TRUE, an output meta-block is\n   always created. However, until |is_last| is BROTLI_TRUE encoder may retain up\n   to 7 bits of the last byte of output. Byte-alignment could be enforced by\n   emitting an empty meta-data block.\n   Returns BROTLI_FALSE if the size of the input data is larger than\n   input_block_size().\n */\nstatic BROTLI_BOOL EncodeData(\n    BrotliEncoderState* s, const BROTLI_BOOL is_last,\n    const BROTLI_BOOL force_flush, size_t* out_size, uint8_t** output) {\n  const uint64_t delta = UnprocessedInputSize(s);\n  uint32_t bytes = (uint32_t)delta;\n  uint32_t wrapped_last_processed_pos = WrapPosition(s->last_processed_pos_);\n  uint8_t* data;\n  uint32_t mask;\n  MemoryManager* m = &s->memory_manager_;\n  ContextType literal_context_mode;\n  ContextLut literal_context_lut;\n  BROTLI_BOOL fast_compress =\n      s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY;\n\n  data = s->ringbuffer_.buffer_;\n  mask = s->ringbuffer_.mask_;\n\n  if (delta == 0) {  /* No new input; still might want to flush or finish. */\n    if (!data) {  /* No input has been processed so far. */\n      if (is_last) {  /* Emit complete finalized stream. */\n        BROTLI_DCHECK(s->last_bytes_bits_ <= 14);\n        s->last_bytes_ |= (uint16_t)(3u << s->last_bytes_bits_);\n        s->last_bytes_bits_ = (uint8_t)(s->last_bytes_bits_ + 2u);\n        s->tiny_buf_.u8[0] = (uint8_t)s->last_bytes_;\n        s->tiny_buf_.u8[1] = (uint8_t)(s->last_bytes_ >> 8);\n        *output = s->tiny_buf_.u8;\n        *out_size = (s->last_bytes_bits_ + 7u) >> 3u;\n        return BROTLI_TRUE;\n      } else {  /* No data, not last -> no-op. */\n        *out_size = 0;\n        return BROTLI_TRUE;\n      }\n    } else {\n      /* Fast compress performs flush every block -> flush is no-op. */\n      if (!is_last && (!force_flush || fast_compress)) {  /* Another no-op. */\n        *out_size = 0;\n        return BROTLI_TRUE;\n      }\n    }\n  }\n  BROTLI_DCHECK(data);\n\n  if (s->params.quality > s->params.dictionary.max_quality) return BROTLI_FALSE;\n  /* Adding more blocks after \"last\" block is forbidden. */\n  if (s->is_last_block_emitted_) return BROTLI_FALSE;\n  if (is_last) s->is_last_block_emitted_ = BROTLI_TRUE;\n\n  if (delta > InputBlockSize(s)) {\n    return BROTLI_FALSE;\n  }\n  if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY &&\n      !s->command_buf_) {\n    s->command_buf_ =\n        BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize);\n    s->literal_buf_ =\n        BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) ||\n        BROTLI_IS_NULL(s->literal_buf_)) {\n      return BROTLI_FALSE;\n    }\n  }\n\n  if (fast_compress) {\n    uint8_t* storage;\n    size_t storage_ix = s->last_bytes_bits_;\n    size_t table_size;\n    int* table;\n\n    storage = GetBrotliStorage(s, 2 * bytes + 503);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    storage[0] = (uint8_t)s->last_bytes_;\n    storage[1] = (uint8_t)(s->last_bytes_ >> 8);\n    table = GetHashTable(s, s->params.quality, bytes, &table_size);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n      BrotliCompressFragmentFast(\n          s->one_pass_arena_, &data[wrapped_last_processed_pos & mask],\n          bytes, is_last,\n          table, table_size,\n          &storage_ix, storage);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    } else {\n      BrotliCompressFragmentTwoPass(\n          s->two_pass_arena_, &data[wrapped_last_processed_pos & mask],\n          bytes, is_last,\n          s->command_buf_, s->literal_buf_,\n          table, table_size,\n          &storage_ix, storage);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    }\n    s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);\n    s->last_bytes_bits_ = storage_ix & 7u;\n    UpdateLastProcessedPos(s);\n    *output = &storage[0];\n    *out_size = storage_ix >> 3;\n    return BROTLI_TRUE;\n  }\n\n  {\n    /* Theoretical max number of commands is 1 per 2 bytes. */\n    size_t newsize = s->num_commands_ + bytes / 2 + 1;\n    if (newsize > s->cmd_alloc_size_) {\n      Command* new_commands;\n      /* Reserve a bit more memory to allow merging with a next block\n         without reallocation: that would impact speed. */\n      newsize += (bytes / 4) + 16;\n      s->cmd_alloc_size_ = newsize;\n      new_commands = BROTLI_ALLOC(m, Command, newsize);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_commands)) return BROTLI_FALSE;\n      if (s->commands_) {\n        memcpy(new_commands, s->commands_, sizeof(Command) * s->num_commands_);\n        BROTLI_FREE(m, s->commands_);\n      }\n      s->commands_ = new_commands;\n    }\n  }\n\n  InitOrStitchToPreviousBlock(m, &s->hasher_, data, mask, &s->params,\n      wrapped_last_processed_pos, bytes, is_last);\n\n  literal_context_mode = ChooseContextMode(\n      &s->params, data, WrapPosition(s->last_flush_pos_),\n      mask, (size_t)(s->input_pos_ - s->last_flush_pos_));\n  literal_context_lut = BROTLI_CONTEXT_LUT(literal_context_mode);\n\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n\n  if (s->num_commands_ && s->last_insert_len_ == 0) {\n    ExtendLastCommand(s, &bytes, &wrapped_last_processed_pos);\n  }\n\n  if (s->params.quality == ZOPFLIFICATION_QUALITY) {\n    BROTLI_DCHECK(s->params.hasher.type == 10);\n    BrotliCreateZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,\n        data, mask, literal_context_lut, &s->params,\n        &s->hasher_, s->dist_cache_,\n        &s->last_insert_len_, &s->commands_[s->num_commands_],\n        &s->num_commands_, &s->num_literals_);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  } else if (s->params.quality == HQ_ZOPFLIFICATION_QUALITY) {\n    BROTLI_DCHECK(s->params.hasher.type == 10);\n    BrotliCreateHqZopfliBackwardReferences(m, bytes, wrapped_last_processed_pos,\n        data, mask, literal_context_lut, &s->params,\n        &s->hasher_, s->dist_cache_,\n        &s->last_insert_len_, &s->commands_[s->num_commands_],\n        &s->num_commands_, &s->num_literals_);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  } else {\n    BrotliCreateBackwardReferences(bytes, wrapped_last_processed_pos,\n        data, mask, literal_context_lut, &s->params,\n        &s->hasher_, s->dist_cache_,\n        &s->last_insert_len_, &s->commands_[s->num_commands_],\n        &s->num_commands_, &s->num_literals_);\n  }\n\n  {\n    const size_t max_length = MaxMetablockSize(&s->params);\n    const size_t max_literals = max_length / 8;\n    const size_t max_commands = max_length / 8;\n    const size_t processed_bytes = (size_t)(s->input_pos_ - s->last_flush_pos_);\n    /* If maximal possible additional block doesn't fit metablock, flush now. */\n    /* TODO(eustas): Postpone decision until next block arrives? */\n    const BROTLI_BOOL next_input_fits_metablock = TO_BROTLI_BOOL(\n        processed_bytes + InputBlockSize(s) <= max_length);\n    /* If block splitting is not used, then flush as soon as there is some\n       amount of commands / literals produced. */\n    const BROTLI_BOOL should_flush = TO_BROTLI_BOOL(\n        s->params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT &&\n        s->num_literals_ + s->num_commands_ >= MAX_NUM_DELAYED_SYMBOLS);\n    if (!is_last && !force_flush && !should_flush &&\n        next_input_fits_metablock &&\n        s->num_literals_ < max_literals &&\n        s->num_commands_ < max_commands) {\n      /* Merge with next input block. Everything will happen later. */\n      if (UpdateLastProcessedPos(s)) {\n        HasherReset(&s->hasher_);\n      }\n      *out_size = 0;\n      return BROTLI_TRUE;\n    }\n  }\n\n  /* Create the last insert-only command. */\n  if (s->last_insert_len_ > 0) {\n    InitInsertCommand(&s->commands_[s->num_commands_++], s->last_insert_len_);\n    s->num_literals_ += s->last_insert_len_;\n    s->last_insert_len_ = 0;\n  }\n\n  if (!is_last && s->input_pos_ == s->last_flush_pos_) {\n    /* We have no new input data and we don't have to finish the stream, so\n       nothing to do. */\n    *out_size = 0;\n    return BROTLI_TRUE;\n  }\n  BROTLI_DCHECK(s->input_pos_ >= s->last_flush_pos_);\n  BROTLI_DCHECK(s->input_pos_ > s->last_flush_pos_ || is_last);\n  BROTLI_DCHECK(s->input_pos_ - s->last_flush_pos_ <= 1u << 24);\n  {\n    const uint32_t metablock_size =\n        (uint32_t)(s->input_pos_ - s->last_flush_pos_);\n    uint8_t* storage = GetBrotliStorage(s, 2 * metablock_size + 503);\n    size_t storage_ix = s->last_bytes_bits_;\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    storage[0] = (uint8_t)s->last_bytes_;\n    storage[1] = (uint8_t)(s->last_bytes_ >> 8);\n    WriteMetaBlockInternal(\n        m, data, mask, s->last_flush_pos_, metablock_size, is_last,\n        literal_context_mode, &s->params, s->prev_byte_, s->prev_byte2_,\n        s->num_literals_, s->num_commands_, s->commands_, s->saved_dist_cache_,\n        s->dist_cache_, &storage_ix, storage);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);\n    s->last_bytes_bits_ = storage_ix & 7u;\n    s->last_flush_pos_ = s->input_pos_;\n    if (UpdateLastProcessedPos(s)) {\n      HasherReset(&s->hasher_);\n    }\n    if (s->last_flush_pos_ > 0) {\n      s->prev_byte_ = data[((uint32_t)s->last_flush_pos_ - 1) & mask];\n    }\n    if (s->last_flush_pos_ > 1) {\n      s->prev_byte2_ = data[(uint32_t)(s->last_flush_pos_ - 2) & mask];\n    }\n    s->num_commands_ = 0;\n    s->num_literals_ = 0;\n    /* Save the state of the distance cache in case we need to restore it for\n       emitting an uncompressed block. */\n    memcpy(s->saved_dist_cache_, s->dist_cache_, sizeof(s->saved_dist_cache_));\n    *output = &storage[0];\n    *out_size = storage_ix >> 3;\n    return BROTLI_TRUE;\n  }\n}\n\n/* Dumps remaining output bits and metadata header to |header|.\n   Returns number of produced bytes.\n   REQUIRED: |header| should be 8-byte aligned and at least 16 bytes long.\n   REQUIRED: |block_size| <= (1 << 24). */\nstatic size_t WriteMetadataHeader(\n    BrotliEncoderState* s, const size_t block_size, uint8_t* header) {\n  size_t storage_ix;\n  storage_ix = s->last_bytes_bits_;\n  header[0] = (uint8_t)s->last_bytes_;\n  header[1] = (uint8_t)(s->last_bytes_ >> 8);\n  s->last_bytes_ = 0;\n  s->last_bytes_bits_ = 0;\n\n  BrotliWriteBits(1, 0, &storage_ix, header);\n  BrotliWriteBits(2, 3, &storage_ix, header);\n  BrotliWriteBits(1, 0, &storage_ix, header);\n  if (block_size == 0) {\n    BrotliWriteBits(2, 0, &storage_ix, header);\n  } else {\n    uint32_t nbits = (block_size == 1) ? 1 :\n        (Log2FloorNonZero((uint32_t)block_size - 1) + 1);\n    uint32_t nbytes = (nbits + 7) / 8;\n    BrotliWriteBits(2, nbytes, &storage_ix, header);\n    BrotliWriteBits(8 * nbytes, block_size - 1, &storage_ix, header);\n  }\n  return (storage_ix + 7u) >> 3;\n}\n\nsize_t BrotliEncoderMaxCompressedSize(size_t input_size) {\n  /* [window bits / empty metadata] + N * [uncompressed] + [last empty] */\n  size_t num_large_blocks = input_size >> 14;\n  size_t overhead = 2 + (4 * num_large_blocks) + 3 + 1;\n  size_t result = input_size + overhead;\n  if (input_size == 0) return 2;\n  return (result < input_size) ? 0 : result;\n}\n\n/* Wraps data to uncompressed brotli stream with minimal window size.\n   |output| should point at region with at least BrotliEncoderMaxCompressedSize\n   addressable bytes.\n   Returns the length of stream. */\nstatic size_t MakeUncompressedStream(\n    const uint8_t* input, size_t input_size, uint8_t* output) {\n  size_t size = input_size;\n  size_t result = 0;\n  size_t offset = 0;\n  if (input_size == 0) {\n    output[0] = 6;\n    return 1;\n  }\n  output[result++] = 0x21;  /* window bits = 10, is_last = false */\n  output[result++] = 0x03;  /* empty metadata, padding */\n  while (size > 0) {\n    uint32_t nibbles = 0;\n    uint32_t chunk_size;\n    uint32_t bits;\n    chunk_size = (size > (1u << 24)) ? (1u << 24) : (uint32_t)size;\n    if (chunk_size > (1u << 16)) nibbles = (chunk_size > (1u << 20)) ? 2 : 1;\n    bits =\n        (nibbles << 1) | ((chunk_size - 1) << 3) | (1u << (19 + 4 * nibbles));\n    output[result++] = (uint8_t)bits;\n    output[result++] = (uint8_t)(bits >> 8);\n    output[result++] = (uint8_t)(bits >> 16);\n    if (nibbles == 2) output[result++] = (uint8_t)(bits >> 24);\n    memcpy(&output[result], &input[offset], chunk_size);\n    result += chunk_size;\n    offset += chunk_size;\n    size -= chunk_size;\n  }\n  output[result++] = 3;\n  return result;\n}\n\nBROTLI_BOOL BrotliEncoderCompress(\n    int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,\n    const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],\n    size_t* encoded_size,\n    uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]) {\n  BrotliEncoderState* s;\n  size_t out_size = *encoded_size;\n  const uint8_t* input_start = input_buffer;\n  uint8_t* output_start = encoded_buffer;\n  size_t max_out_size = BrotliEncoderMaxCompressedSize(input_size);\n  if (out_size == 0) {\n    /* Output buffer needs at least one byte. */\n    return BROTLI_FALSE;\n  }\n  if (input_size == 0) {\n    /* Handle the special case of empty input. */\n    *encoded_size = 1;\n    *encoded_buffer = 6;\n    return BROTLI_TRUE;\n  }\n\n  s = BrotliEncoderCreateInstance(0, 0, 0);\n  if (!s) {\n    return BROTLI_FALSE;\n  } else {\n    size_t available_in = input_size;\n    const uint8_t* next_in = input_buffer;\n    size_t available_out = *encoded_size;\n    uint8_t* next_out = encoded_buffer;\n    size_t total_out = 0;\n    BROTLI_BOOL result = BROTLI_FALSE;\n    /* TODO(eustas): check that parameters are sane. */\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_QUALITY, (uint32_t)quality);\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_LGWIN, (uint32_t)lgwin);\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_MODE, (uint32_t)mode);\n    BrotliEncoderSetParameter(s, BROTLI_PARAM_SIZE_HINT, (uint32_t)input_size);\n    if (lgwin > BROTLI_MAX_WINDOW_BITS) {\n      BrotliEncoderSetParameter(s, BROTLI_PARAM_LARGE_WINDOW, BROTLI_TRUE);\n    }\n    result = BrotliEncoderCompressStream(s, BROTLI_OPERATION_FINISH,\n        &available_in, &next_in, &available_out, &next_out, &total_out);\n    if (!BrotliEncoderIsFinished(s)) result = 0;\n    *encoded_size = total_out;\n    BrotliEncoderDestroyInstance(s);\n    if (!result || (max_out_size && *encoded_size > max_out_size)) {\n      goto fallback;\n    }\n    return BROTLI_TRUE;\n  }\nfallback:\n  *encoded_size = 0;\n  if (!max_out_size) return BROTLI_FALSE;\n  if (out_size >= max_out_size) {\n    *encoded_size =\n        MakeUncompressedStream(input_start, input_size, output_start);\n    return BROTLI_TRUE;\n  }\n  return BROTLI_FALSE;\n}\n\nstatic void InjectBytePaddingBlock(BrotliEncoderState* s) {\n  uint32_t seal = s->last_bytes_;\n  size_t seal_bits = s->last_bytes_bits_;\n  uint8_t* destination;\n  s->last_bytes_ = 0;\n  s->last_bytes_bits_ = 0;\n  /* is_last = 0, data_nibbles = 11, reserved = 0, meta_nibbles = 00 */\n  seal |= 0x6u << seal_bits;\n  seal_bits += 6;\n  /* If we have already created storage, then append to it.\n     Storage is valid until next block is being compressed. */\n  if (s->next_out_) {\n    destination = s->next_out_ + s->available_out_;\n  } else {\n    destination = s->tiny_buf_.u8;\n    s->next_out_ = destination;\n  }\n  destination[0] = (uint8_t)seal;\n  if (seal_bits > 8) destination[1] = (uint8_t)(seal >> 8);\n  if (seal_bits > 16) destination[2] = (uint8_t)(seal >> 16);\n  s->available_out_ += (seal_bits + 7) >> 3;\n}\n\n/* Fills the |total_out|, if it is not NULL. */\nstatic void SetTotalOut(BrotliEncoderState* s, size_t* total_out) {\n  if (total_out) {\n    /* Saturating conversion uint64_t -> size_t */\n    size_t result = (size_t)-1;\n    if (s->total_out_ < result) {\n      result = (size_t)s->total_out_;\n    }\n    *total_out = result;\n  }\n}\n\n/* Injects padding bits or pushes compressed data to output.\n   Returns false if nothing is done. */\nstatic BROTLI_BOOL InjectFlushOrPushOutput(BrotliEncoderState* s,\n    size_t* available_out, uint8_t** next_out, size_t* total_out) {\n  if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&\n      s->last_bytes_bits_ != 0) {\n    InjectBytePaddingBlock(s);\n    return BROTLI_TRUE;\n  }\n\n  if (s->available_out_ != 0 && *available_out != 0) {\n    size_t copy_output_size =\n        BROTLI_MIN(size_t, s->available_out_, *available_out);\n    memcpy(*next_out, s->next_out_, copy_output_size);\n    *next_out += copy_output_size;\n    *available_out -= copy_output_size;\n    s->next_out_ += copy_output_size;\n    s->available_out_ -= copy_output_size;\n    s->total_out_ += copy_output_size;\n    SetTotalOut(s, total_out);\n    return BROTLI_TRUE;\n  }\n\n  return BROTLI_FALSE;\n}\n\nstatic void CheckFlushComplete(BrotliEncoderState* s) {\n  if (s->stream_state_ == BROTLI_STREAM_FLUSH_REQUESTED &&\n      s->available_out_ == 0) {\n    s->stream_state_ = BROTLI_STREAM_PROCESSING;\n    s->next_out_ = 0;\n  }\n}\n\nstatic BROTLI_BOOL BrotliEncoderCompressStreamFast(\n    BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,\n    const uint8_t** next_in, size_t* available_out, uint8_t** next_out,\n    size_t* total_out) {\n  const size_t block_size_limit = (size_t)1 << s->params.lgwin;\n  const size_t buf_size = BROTLI_MIN(size_t, kCompressFragmentTwoPassBlockSize,\n      BROTLI_MIN(size_t, *available_in, block_size_limit));\n  uint32_t* tmp_command_buf = NULL;\n  uint32_t* command_buf = NULL;\n  uint8_t* tmp_literal_buf = NULL;\n  uint8_t* literal_buf = NULL;\n  MemoryManager* m = &s->memory_manager_;\n  if (s->params.quality != FAST_ONE_PASS_COMPRESSION_QUALITY &&\n      s->params.quality != FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    return BROTLI_FALSE;\n  }\n  if (s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    if (!s->command_buf_ && buf_size == kCompressFragmentTwoPassBlockSize) {\n      s->command_buf_ =\n          BROTLI_ALLOC(m, uint32_t, kCompressFragmentTwoPassBlockSize);\n      s->literal_buf_ =\n          BROTLI_ALLOC(m, uint8_t, kCompressFragmentTwoPassBlockSize);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(s->command_buf_) ||\n          BROTLI_IS_NULL(s->literal_buf_)) {\n        return BROTLI_FALSE;\n      }\n    }\n    if (s->command_buf_) {\n      command_buf = s->command_buf_;\n      literal_buf = s->literal_buf_;\n    } else {\n      tmp_command_buf = BROTLI_ALLOC(m, uint32_t, buf_size);\n      tmp_literal_buf = BROTLI_ALLOC(m, uint8_t, buf_size);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp_command_buf) ||\n          BROTLI_IS_NULL(tmp_literal_buf)) {\n        return BROTLI_FALSE;\n      }\n      command_buf = tmp_command_buf;\n      literal_buf = tmp_literal_buf;\n    }\n  }\n\n  while (BROTLI_TRUE) {\n    if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {\n      continue;\n    }\n\n    /* Compress block only when internal output buffer is empty, stream is not\n       finished, there is no pending flush request, and there is either\n       additional input or pending operation. */\n    if (s->available_out_ == 0 &&\n        s->stream_state_ == BROTLI_STREAM_PROCESSING &&\n        (*available_in != 0 || op != BROTLI_OPERATION_PROCESS)) {\n      size_t block_size = BROTLI_MIN(size_t, block_size_limit, *available_in);\n      BROTLI_BOOL is_last =\n          (*available_in == block_size) && (op == BROTLI_OPERATION_FINISH);\n      BROTLI_BOOL force_flush =\n          (*available_in == block_size) && (op == BROTLI_OPERATION_FLUSH);\n      size_t max_out_size = 2 * block_size + 503;\n      BROTLI_BOOL inplace = BROTLI_TRUE;\n      uint8_t* storage = NULL;\n      size_t storage_ix = s->last_bytes_bits_;\n      size_t table_size;\n      int* table;\n\n      if (force_flush && block_size == 0) {\n        s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;\n        continue;\n      }\n      if (max_out_size <= *available_out) {\n        storage = *next_out;\n      } else {\n        inplace = BROTLI_FALSE;\n        storage = GetBrotliStorage(s, max_out_size);\n        if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      }\n      storage[0] = (uint8_t)s->last_bytes_;\n      storage[1] = (uint8_t)(s->last_bytes_ >> 8);\n      table = GetHashTable(s, s->params.quality, block_size, &table_size);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n\n      if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n        BrotliCompressFragmentFast(s->one_pass_arena_, *next_in, block_size,\n            is_last, table, table_size, &storage_ix, storage);\n        if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      } else {\n        BrotliCompressFragmentTwoPass(s->two_pass_arena_, *next_in, block_size,\n            is_last, command_buf, literal_buf, table, table_size,\n            &storage_ix, storage);\n        if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      }\n      if (block_size != 0) {\n        *next_in += block_size;\n        *available_in -= block_size;\n        s->total_in_ += block_size;\n      }\n      if (inplace) {\n        size_t out_bytes = storage_ix >> 3;\n        BROTLI_DCHECK(out_bytes <= *available_out);\n        BROTLI_DCHECK((storage_ix & 7) == 0 || out_bytes < *available_out);\n        *next_out += out_bytes;\n        *available_out -= out_bytes;\n        s->total_out_ += out_bytes;\n        SetTotalOut(s, total_out);\n      } else {\n        size_t out_bytes = storage_ix >> 3;\n        s->next_out_ = storage;\n        s->available_out_ = out_bytes;\n      }\n      s->last_bytes_ = (uint16_t)(storage[storage_ix >> 3]);\n      s->last_bytes_bits_ = storage_ix & 7u;\n\n      if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;\n      if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;\n      continue;\n    }\n    break;\n  }\n  BROTLI_FREE(m, tmp_command_buf);\n  BROTLI_FREE(m, tmp_literal_buf);\n  CheckFlushComplete(s);\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_BOOL ProcessMetadata(\n    BrotliEncoderState* s, size_t* available_in, const uint8_t** next_in,\n    size_t* available_out, uint8_t** next_out, size_t* total_out) {\n  if (*available_in > (1u << 24)) return BROTLI_FALSE;\n  /* Switch to metadata block workflow, if required. */\n  if (s->stream_state_ == BROTLI_STREAM_PROCESSING) {\n    s->remaining_metadata_bytes_ = (uint32_t)*available_in;\n    s->stream_state_ = BROTLI_STREAM_METADATA_HEAD;\n  }\n  if (s->stream_state_ != BROTLI_STREAM_METADATA_HEAD &&\n      s->stream_state_ != BROTLI_STREAM_METADATA_BODY) {\n    return BROTLI_FALSE;\n  }\n\n  while (BROTLI_TRUE) {\n    if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {\n      continue;\n    }\n    if (s->available_out_ != 0) break;\n\n    if (s->input_pos_ != s->last_flush_pos_) {\n      BROTLI_BOOL result = EncodeData(s, BROTLI_FALSE, BROTLI_TRUE,\n          &s->available_out_, &s->next_out_);\n      if (!result) return BROTLI_FALSE;\n      continue;\n    }\n\n    if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD) {\n      s->next_out_ = s->tiny_buf_.u8;\n      s->available_out_ =\n          WriteMetadataHeader(s, s->remaining_metadata_bytes_, s->next_out_);\n      s->stream_state_ = BROTLI_STREAM_METADATA_BODY;\n      continue;\n    } else {\n      /* Exit workflow only when there is no more input and no more output.\n         Otherwise client may continue producing empty metadata blocks. */\n      if (s->remaining_metadata_bytes_ == 0) {\n        s->remaining_metadata_bytes_ = BROTLI_UINT32_MAX;\n        s->stream_state_ = BROTLI_STREAM_PROCESSING;\n        break;\n      }\n      if (*available_out) {\n        /* Directly copy input to output. */\n        uint32_t copy = (uint32_t)BROTLI_MIN(\n            size_t, s->remaining_metadata_bytes_, *available_out);\n        memcpy(*next_out, *next_in, copy);\n        *next_in += copy;\n        *available_in -= copy;\n        s->total_in_ += copy;  /* not actually data input, though */\n        s->remaining_metadata_bytes_ -= copy;\n        *next_out += copy;\n        *available_out -= copy;\n      } else {\n        /* This guarantees progress in \"TakeOutput\" workflow. */\n        uint32_t copy = BROTLI_MIN(uint32_t, s->remaining_metadata_bytes_, 16);\n        s->next_out_ = s->tiny_buf_.u8;\n        memcpy(s->next_out_, *next_in, copy);\n        *next_in += copy;\n        *available_in -= copy;\n        s->total_in_ += copy;  /* not actually data input, though */\n        s->remaining_metadata_bytes_ -= copy;\n        s->available_out_ = copy;\n      }\n      continue;\n    }\n  }\n\n  return BROTLI_TRUE;\n}\n\nstatic void UpdateSizeHint(BrotliEncoderState* s, size_t available_in) {\n  if (s->params.size_hint == 0) {\n    uint64_t delta = UnprocessedInputSize(s);\n    uint64_t tail = available_in;\n    uint32_t limit = 1u << 30;\n    uint32_t total;\n    if ((delta >= limit) || (tail >= limit) || ((delta + tail) >= limit)) {\n      total = limit;\n    } else {\n      total = (uint32_t)(delta + tail);\n    }\n    s->params.size_hint = total;\n  }\n}\n\nBROTLI_BOOL BrotliEncoderCompressStream(\n    BrotliEncoderState* s, BrotliEncoderOperation op, size_t* available_in,\n    const uint8_t** next_in, size_t* available_out, uint8_t** next_out,\n    size_t* total_out) {\n  if (!EnsureInitialized(s)) return BROTLI_FALSE;\n\n  /* Unfinished metadata block; check requirements. */\n  if (s->remaining_metadata_bytes_ != BROTLI_UINT32_MAX) {\n    if (*available_in != s->remaining_metadata_bytes_) return BROTLI_FALSE;\n    if (op != BROTLI_OPERATION_EMIT_METADATA) return BROTLI_FALSE;\n  }\n\n  if (op == BROTLI_OPERATION_EMIT_METADATA) {\n    UpdateSizeHint(s, 0);  /* First data metablock might be emitted here. */\n    return ProcessMetadata(\n        s, available_in, next_in, available_out, next_out, total_out);\n  }\n\n  if (s->stream_state_ == BROTLI_STREAM_METADATA_HEAD ||\n      s->stream_state_ == BROTLI_STREAM_METADATA_BODY) {\n    return BROTLI_FALSE;\n  }\n\n  if (s->stream_state_ != BROTLI_STREAM_PROCESSING && *available_in != 0) {\n    return BROTLI_FALSE;\n  }\n  if (s->params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      s->params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    return BrotliEncoderCompressStreamFast(s, op, available_in, next_in,\n        available_out, next_out, total_out);\n  }\n  while (BROTLI_TRUE) {\n    size_t remaining_block_size = RemainingInputBlockSize(s);\n    /* Shorten input to flint size. */\n    if (s->flint_ >= 0 && remaining_block_size > (size_t)s->flint_) {\n      remaining_block_size = (size_t)s->flint_;\n    }\n\n    if (remaining_block_size != 0 && *available_in != 0) {\n      size_t copy_input_size =\n          BROTLI_MIN(size_t, remaining_block_size, *available_in);\n      CopyInputToRingBuffer(s, copy_input_size, *next_in);\n      *next_in += copy_input_size;\n      *available_in -= copy_input_size;\n      s->total_in_ += copy_input_size;\n      if (s->flint_ > 0) s->flint_ = (int8_t)(s->flint_ - (int)copy_input_size);\n      continue;\n    }\n\n    if (InjectFlushOrPushOutput(s, available_out, next_out, total_out)) {\n      /* Exit the \"emit flint\" workflow. */\n      if (s->flint_ == BROTLI_FLINT_WAITING_FOR_FLUSHING) {\n        CheckFlushComplete(s);\n        if (s->stream_state_ == BROTLI_STREAM_PROCESSING) {\n          s->flint_ = BROTLI_FLINT_DONE;\n        }\n      }\n      continue;\n    }\n\n    /* Compress data only when internal output buffer is empty, stream is not\n       finished and there is no pending flush request. */\n    if (s->available_out_ == 0 &&\n        s->stream_state_ == BROTLI_STREAM_PROCESSING) {\n      if (remaining_block_size == 0 || op != BROTLI_OPERATION_PROCESS) {\n        BROTLI_BOOL is_last = TO_BROTLI_BOOL(\n            (*available_in == 0) && op == BROTLI_OPERATION_FINISH);\n        BROTLI_BOOL force_flush = TO_BROTLI_BOOL(\n            (*available_in == 0) && op == BROTLI_OPERATION_FLUSH);\n        BROTLI_BOOL result;\n        /* Force emitting (uncompressed) piece containing flint. */\n        if (!is_last && s->flint_ == 0) {\n          s->flint_ = BROTLI_FLINT_WAITING_FOR_FLUSHING;\n          force_flush = BROTLI_TRUE;\n        }\n        UpdateSizeHint(s, *available_in);\n        result = EncodeData(s, is_last, force_flush,\n            &s->available_out_, &s->next_out_);\n        if (!result) return BROTLI_FALSE;\n        if (force_flush) s->stream_state_ = BROTLI_STREAM_FLUSH_REQUESTED;\n        if (is_last) s->stream_state_ = BROTLI_STREAM_FINISHED;\n        continue;\n      }\n    }\n    break;\n  }\n  CheckFlushComplete(s);\n  return BROTLI_TRUE;\n}\n\nBROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* s) {\n  return TO_BROTLI_BOOL(s->stream_state_ == BROTLI_STREAM_FINISHED &&\n      !BrotliEncoderHasMoreOutput(s));\n}\n\nBROTLI_BOOL BrotliEncoderHasMoreOutput(BrotliEncoderState* s) {\n  return TO_BROTLI_BOOL(s->available_out_ != 0);\n}\n\nconst uint8_t* BrotliEncoderTakeOutput(BrotliEncoderState* s, size_t* size) {\n  size_t consumed_size = s->available_out_;\n  uint8_t* result = s->next_out_;\n  if (*size) {\n    consumed_size = BROTLI_MIN(size_t, *size, s->available_out_);\n  }\n  if (consumed_size) {\n    s->next_out_ += consumed_size;\n    s->available_out_ -= consumed_size;\n    s->total_out_ += consumed_size;\n    CheckFlushComplete(s);\n    *size = consumed_size;\n  } else {\n    *size = 0;\n    result = 0;\n  }\n  return result;\n}\n\nuint32_t BrotliEncoderVersion(void) {\n  return BROTLI_VERSION;\n}\n\nBrotliEncoderPreparedDictionary* BrotliEncoderPrepareDictionary(\n    BrotliSharedDictionaryType type, size_t size,\n    const uint8_t data[BROTLI_ARRAY_PARAM(size)], int quality,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  ManagedDictionary* managed_dictionary = NULL;\n  BROTLI_BOOL type_is_known = BROTLI_FALSE;\n  type_is_known |= (type == BROTLI_SHARED_DICTIONARY_RAW);\n#if defined(BROTLI_EXPERIMENTAL)\n  type_is_known |= (type == BROTLI_SHARED_DICTIONARY_SERIALIZED);\n#endif  /* BROTLI_EXPERIMENTAL */\n  if (!type_is_known) {\n    return NULL;\n  }\n  managed_dictionary =\n      BrotliCreateManagedDictionary(alloc_func, free_func, opaque);\n  if (managed_dictionary == NULL) {\n    return NULL;\n  }\n  if (type == BROTLI_SHARED_DICTIONARY_RAW) {\n    managed_dictionary->dictionary = (uint32_t*)CreatePreparedDictionary(\n        &managed_dictionary->memory_manager_, data, size);\n  }\n#if defined(BROTLI_EXPERIMENTAL)\n  if (type == BROTLI_SHARED_DICTIONARY_SERIALIZED) {\n    SharedEncoderDictionary* dict = (SharedEncoderDictionary*)BrotliAllocate(\n        &managed_dictionary->memory_manager_, sizeof(SharedEncoderDictionary));\n    managed_dictionary->dictionary = (uint32_t*)dict;\n    if (dict != NULL) {\n      BROTLI_BOOL ok = BrotliInitCustomSharedEncoderDictionary(\n          &managed_dictionary->memory_manager_, data, size, quality, dict);\n      if (!ok) {\n        BrotliFree(&managed_dictionary->memory_manager_, dict);\n        managed_dictionary->dictionary = NULL;\n      }\n    }\n  }\n#else  /* BROTLI_EXPERIMENTAL */\n  (void)quality;\n#endif  /* BROTLI_EXPERIMENTAL */\n  if (managed_dictionary->dictionary == NULL) {\n    BrotliDestroyManagedDictionary(managed_dictionary);\n    return NULL;\n  }\n  return (BrotliEncoderPreparedDictionary*)managed_dictionary;\n}\n\nvoid BrotliEncoderDestroyPreparedDictionary(\n    BrotliEncoderPreparedDictionary* dictionary) {\n  ManagedDictionary* dict = (ManagedDictionary*)dictionary;\n  if (!dictionary) return;\n  /* First field of dictionary structs. */\n  /* Only managed dictionaries are eligible for destruction by this method. */\n  if (dict->magic != kManagedDictionaryMagic) {\n    return;\n  }\n  if (dict->dictionary == NULL) {\n    /* This should never ever happen. */\n  } else if (*dict->dictionary == kLeanPreparedDictionaryMagic) {\n    DestroyPreparedDictionary(\n        &dict->memory_manager_, (PreparedDictionary*)dict->dictionary);\n  } else if (*dict->dictionary == kSharedDictionaryMagic) {\n    BrotliCleanupSharedEncoderDictionary(&dict->memory_manager_,\n        (SharedEncoderDictionary*)dict->dictionary);\n    BrotliFree(&dict->memory_manager_, dict->dictionary);\n  } else {\n    /* There is also kPreparedDictionaryMagic, but such instances should be\n     * constructed and destroyed by different means. */\n  }\n  dict->dictionary = NULL;\n  BrotliDestroyManagedDictionary(dict);\n}\n\nBROTLI_BOOL BrotliEncoderAttachPreparedDictionary(BrotliEncoderState* state,\n    const BrotliEncoderPreparedDictionary* dictionary) {\n  /* First field of dictionary structs */\n  const BrotliEncoderPreparedDictionary* dict = dictionary;\n  uint32_t magic = *((const uint32_t*)dict);\n  SharedEncoderDictionary* current = NULL;\n  if (magic == kManagedDictionaryMagic) {\n    /* Unwrap managed dictionary. */\n    ManagedDictionary* managed_dictionary = (ManagedDictionary*)dict;\n    magic = *managed_dictionary->dictionary;\n    dict = (BrotliEncoderPreparedDictionary*)managed_dictionary->dictionary;\n  }\n  current = &state->params.dictionary;\n  if (magic == kPreparedDictionaryMagic ||\n      magic == kLeanPreparedDictionaryMagic) {\n    const PreparedDictionary* prepared = (const PreparedDictionary*)dict;\n    if (!AttachPreparedDictionary(&current->compound, prepared)) {\n      return BROTLI_FALSE;\n    }\n  } else if (magic == kSharedDictionaryMagic) {\n    const SharedEncoderDictionary* attached =\n        (const SharedEncoderDictionary*)dict;\n    BROTLI_BOOL was_default = !current->contextual.context_based &&\n        current->contextual.num_dictionaries == 1 &&\n        current->contextual.dict[0]->hash_table_words ==\n        kStaticDictionaryHashWords &&\n        current->contextual.dict[0]->hash_table_lengths ==\n        kStaticDictionaryHashLengths;\n    BROTLI_BOOL new_default = !attached->contextual.context_based &&\n        attached->contextual.num_dictionaries == 1 &&\n        attached->contextual.dict[0]->hash_table_words ==\n        kStaticDictionaryHashWords &&\n        attached->contextual.dict[0]->hash_table_lengths ==\n        kStaticDictionaryHashLengths;\n    size_t i;\n    if (state->is_initialized_) return BROTLI_FALSE;\n    current->max_quality =\n        BROTLI_MIN(int, current->max_quality, attached->max_quality);\n    for (i = 0; i < attached->compound.num_chunks; i++) {\n      if (!AttachPreparedDictionary(&current->compound,\n          attached->compound.chunks[i])) {\n        return BROTLI_FALSE;\n      }\n    }\n    if (!new_default) {\n      if (!was_default) return BROTLI_FALSE;\n      /* Copy by value, but then set num_instances_ to 0 because their memory\n      is managed by attached, not by current */\n      current->contextual = attached->contextual;\n      current->contextual.num_instances_ = 0;\n    }\n  } else {\n    return BROTLI_FALSE;\n  }\n  return BROTLI_TRUE;\n}\n\nsize_t BrotliEncoderEstimatePeakMemoryUsage(int quality, int lgwin,\n                                            size_t input_size) {\n  BrotliEncoderParams params;\n  size_t memory_manager_slots = 0;\n  size_t memory_manager_size = 0;\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n  memory_manager_slots = 256;\n#if defined(BROTLI_EXPERIMENTAL)\n  memory_manager_slots = 32768;\n#endif  /* BROTLI_EXPERIMENTAL */\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n  memory_manager_size = memory_manager_slots * sizeof(void*);\n  BrotliEncoderInitParams(&params);\n  params.quality = quality;\n  params.lgwin = lgwin;\n  params.size_hint = input_size;\n  params.large_window = lgwin > BROTLI_MAX_WINDOW_BITS;\n  SanitizeParams(&params);\n  params.lgblock = ComputeLgBlock(&params);\n  ChooseHasher(&params, &params.hasher);\n  if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    size_t state_size = sizeof(BrotliEncoderState);\n    size_t block_size = BROTLI_MIN(size_t, input_size, (1ul << params.lgwin));\n    size_t hash_table_size =\n        HashTableSize(MaxHashTableSize(params.quality), block_size);\n    size_t hash_size =\n        (hash_table_size < (1u << 10)) ? 0 : sizeof(int) * hash_table_size;\n    size_t cmdbuf_size = params.quality == FAST_TWO_PASS_COMPRESSION_QUALITY ?\n        5 * BROTLI_MIN(size_t, block_size, 1ul << 17) : 0;\n    if (params.quality == FAST_ONE_PASS_COMPRESSION_QUALITY) {\n      state_size += sizeof(BrotliOnePassArena);\n    } else {\n      state_size += sizeof(BrotliTwoPassArena);\n    }\n    return hash_size + cmdbuf_size + state_size;\n  } else {\n    size_t short_ringbuffer_size = (size_t)1 << params.lgblock;\n    int ringbuffer_bits = ComputeRbBits(&params);\n    size_t ringbuffer_size = input_size < short_ringbuffer_size ?\n        input_size : (1u << ringbuffer_bits) + short_ringbuffer_size;\n    size_t hash_size[4] = {0};\n    size_t metablock_size =\n        BROTLI_MIN(size_t, input_size, MaxMetablockSize(&params));\n    size_t inputblock_size =\n        BROTLI_MIN(size_t, input_size, (size_t)1 << params.lgblock);\n    size_t cmdbuf_size = metablock_size * 2 + inputblock_size * 6;\n    size_t outbuf_size = metablock_size * 2 + 503;\n    size_t histogram_size = 0;\n    HasherSize(&params, BROTLI_TRUE, input_size, hash_size);\n    if (params.quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {\n      cmdbuf_size = BROTLI_MIN(size_t, cmdbuf_size,\n          MAX_NUM_DELAYED_SYMBOLS * sizeof(Command) + inputblock_size * 12);\n    }\n    if (params.quality >= MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING) {\n      /* Only a very rough estimation, based on enwik8. */\n      histogram_size = 200 << 20;\n    } else if (params.quality >= MIN_QUALITY_FOR_BLOCK_SPLIT) {\n      size_t literal_histograms =\n          BROTLI_MIN(size_t, metablock_size / 6144, 256);\n      size_t command_histograms =\n          BROTLI_MIN(size_t, metablock_size / 6144, 256);\n      size_t distance_histograms =\n          BROTLI_MIN(size_t, metablock_size / 6144, 256);\n      histogram_size = literal_histograms * sizeof(HistogramLiteral) +\n                       command_histograms * sizeof(HistogramCommand) +\n                       distance_histograms * sizeof(HistogramDistance);\n    }\n    return (memory_manager_size + ringbuffer_size +\n            hash_size[0] + hash_size[1] + hash_size[2] + hash_size[3] +\n            cmdbuf_size +\n            outbuf_size +\n            histogram_size);\n  }\n}\nsize_t BrotliEncoderGetPreparedDictionarySize(\n    const BrotliEncoderPreparedDictionary* prepared_dictionary) {\n  /* First field of dictionary structs */\n  const BrotliEncoderPreparedDictionary* prepared = prepared_dictionary;\n  uint32_t magic = *((const uint32_t*)prepared);\n  size_t overhead = 0;\n  if (magic == kManagedDictionaryMagic) {\n    const ManagedDictionary* managed = (const ManagedDictionary*)prepared;\n    overhead = sizeof(ManagedDictionary);\n    magic = *managed->dictionary;\n    prepared = (const BrotliEncoderPreparedDictionary*)managed->dictionary;\n  }\n\n  if (magic == kPreparedDictionaryMagic) {\n    const PreparedDictionary* dictionary =\n        (const PreparedDictionary*)prepared;\n    /* Keep in sync with step 3 of CreatePreparedDictionary */\n    return sizeof(PreparedDictionary) + dictionary->source_size +\n        (sizeof(uint32_t) << dictionary->slot_bits) +\n        (sizeof(uint16_t) << dictionary->bucket_bits) +\n        (sizeof(uint32_t) * dictionary->num_items) + overhead;\n  } else if (magic == kLeanPreparedDictionaryMagic) {\n    const PreparedDictionary* dictionary =\n        (const PreparedDictionary*)prepared;\n    /* Keep in sync with step 3 of CreatePreparedDictionary */\n    return sizeof(PreparedDictionary) + sizeof(uint8_t*) +\n        (sizeof(uint32_t) << dictionary->slot_bits) +\n        (sizeof(uint16_t) << dictionary->bucket_bits) +\n        (sizeof(uint32_t) * dictionary->num_items) + overhead;\n  } else if (magic == kSharedDictionaryMagic) {\n    const SharedEncoderDictionary* dictionary =\n        (const SharedEncoderDictionary*)prepared;\n    const CompoundDictionary* compound = &dictionary->compound;\n    const ContextualEncoderDictionary* contextual = &dictionary->contextual;\n    size_t result = sizeof(*dictionary);\n    size_t i;\n    size_t num_instances;\n    const BrotliEncoderDictionary* instances;\n    for (i = 0; i < compound->num_prepared_instances_; i++) {\n      size_t size = BrotliEncoderGetPreparedDictionarySize(\n          (const BrotliEncoderPreparedDictionary*)\n          compound->prepared_instances_[i]);\n      if (!size) return 0;  /* error */\n      result += size;\n    }\n    if (contextual->context_based) {\n      num_instances = contextual->num_instances_;\n      instances = contextual->instances_;\n      result += sizeof(*instances) * num_instances;\n    } else {\n      num_instances = 1;\n      instances = &contextual->instance_;\n    }\n    for (i = 0; i < num_instances; i++) {\n      const BrotliEncoderDictionary* dict = &instances[i];\n      result += dict->trie.pool_capacity * sizeof(BrotliTrieNode);\n      if (dict->hash_table_data_words_) {\n        result += sizeof(kStaticDictionaryHashWords);\n      }\n      if (dict->hash_table_data_lengths_) {\n        result += sizeof(kStaticDictionaryHashLengths);\n      }\n      if (dict->buckets_data_) {\n        result += sizeof(*dict->buckets_data_) * dict->buckets_alloc_size_;\n      }\n      if (dict->dict_words_data_) {\n        result += sizeof(*dict->dict_words) * dict->dict_words_alloc_size_;\n      }\n      if (dict->words_instance_) {\n        result += sizeof(*dict->words_instance_);\n        /* data_size not added here: it is never allocated by the\n           SharedEncoderDictionary, instead it always points to the file\n           already loaded in memory. So if the caller wants to include\n           this memory as well, add the size of the loaded dictionary\n           file to this. */\n      }\n    }\n    return result + overhead;\n  }\n  return 0;  /* error */\n}\n\n#if defined(BROTLI_TEST)\nsize_t MakeUncompressedStreamForTest(const uint8_t*, size_t, uint8_t*);\nsize_t MakeUncompressedStreamForTest(\n    const uint8_t* input, size_t input_size, uint8_t* output) {\n  return MakeUncompressedStream(input, input_size, output);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/encoder_dict.c",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"encoder_dict.h\"\n\n#include <stdlib.h>  /* malloc, free */\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/shared_dictionary_internal.h\"\n#include \"../common/transform.h\"\n#include \"compound_dictionary.h\"\n#include \"dictionary_hash.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n#include \"hash.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define NUM_HASH_BITS 15u\n#define NUM_HASH_BUCKETS (1u << NUM_HASH_BITS)\n\nstatic void BrotliTrieInit(BrotliTrie* trie) {\n  trie->pool_capacity = 0;\n  trie->pool_size = 0;\n  trie->pool = 0;\n\n  /* Set up the root node */\n  trie->root.single = 0;\n  trie->root.len_ = 0;\n  trie->root.idx_ = 0;\n  trie->root.sub = 0;\n}\n\nstatic void BrotliTrieFree(MemoryManager* m, BrotliTrie* trie) {\n  BrotliFree(m, trie->pool);\n}\n\n/* Initializes to RFC 7932 static dictionary / transforms. */\nstatic void InitEncoderDictionary(BrotliEncoderDictionary* dict) {\n  dict->words = BrotliGetDictionary();\n  dict->num_transforms = (uint32_t)BrotliGetTransforms()->num_transforms;\n\n  dict->hash_table_words = kStaticDictionaryHashWords;\n  dict->hash_table_lengths = kStaticDictionaryHashLengths;\n  dict->buckets = kStaticDictionaryBuckets;\n  dict->dict_words = kStaticDictionaryWords;\n\n  dict->cutoffTransformsCount = kCutoffTransformsCount;\n  dict->cutoffTransforms = kCutoffTransforms;\n\n  dict->parent = 0;\n\n  dict->hash_table_data_words_ = 0;\n  dict->hash_table_data_lengths_ = 0;\n  dict->buckets_alloc_size_ = 0;\n  dict->buckets_data_ = 0;\n  dict->dict_words_alloc_size_ = 0;\n  dict->dict_words_data_ = 0;\n  dict->words_instance_ = 0;\n  dict->has_words_heavy = BROTLI_FALSE;\n  BrotliTrieInit(&dict->trie);\n}\n\nstatic void BrotliDestroyEncoderDictionary(MemoryManager* m,\n    BrotliEncoderDictionary* dict) {\n  BrotliFree(m, dict->hash_table_data_words_);\n  BrotliFree(m, dict->hash_table_data_lengths_);\n  BrotliFree(m, dict->buckets_data_);\n  BrotliFree(m, dict->dict_words_data_);\n  BrotliFree(m, dict->words_instance_);\n  BrotliTrieFree(m, &dict->trie);\n}\n\n#if defined(BROTLI_EXPERIMENTAL)\n/* Word length must be at least 4 bytes */\nstatic uint32_t Hash(const uint8_t* data, int bits) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - bits);\n}\n\n/* Theoretical max possible word size after transform */\n#define kTransformedBufferSize \\\n    (256 + 256 + SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH)\n\n/* To be safe buffer must have at least kTransformedBufferSize */\nstatic void TransformedDictionaryWord(uint32_t word_idx, int len, int transform,\n    const BrotliTransforms* transforms,\n    const BrotliEncoderDictionary* dict,\n    uint8_t* buffer, size_t* size) {\n  const uint8_t* dict_word = &dict->words->data[\n      dict->words->offsets_by_length[len] + (uint32_t)len * word_idx];\n  *size = (size_t)BrotliTransformDictionaryWord(buffer, dict_word, len,\n      transforms, transform);\n}\n\nstatic DictWord MakeDictWord(uint8_t len, uint8_t transform, uint16_t idx) {\n  DictWord result;\n  result.len = len;\n  result.transform = transform;\n  result.idx = idx;\n  return result;\n}\n\nstatic uint32_t BrotliTrieAlloc(MemoryManager* m, size_t num, BrotliTrie* trie,\n                                BrotliTrieNode** keep) {\n  uint32_t result;\n  uint32_t keep_index = 0;\n  if (keep && *keep != &trie->root) {\n    /* Optional node to keep, since address may change after re-allocating */\n    keep_index = (uint32_t)(*keep - trie->pool);\n  }\n  if (trie->pool_size == 0) {\n    /* Have a dummy node in the front. We do not want the result to be 0, it\n    must be at least 1, 0 represents \"null pointer\" */\n    trie->pool_size = 1;\n  }\n  BROTLI_ENSURE_CAPACITY(m, BrotliTrieNode, trie->pool, trie->pool_capacity,\n                         trie->pool_size + num);\n  if (BROTLI_IS_OOM(m)) return 0;\n  /* Init the new nodes to empty */\n  memset(trie->pool + trie->pool_size, 0, sizeof(*trie->pool) * num);\n  result = (uint32_t)trie->pool_size;\n  trie->pool_size += num;\n  if (keep && *keep != &trie->root) {\n    *keep = trie->pool + keep_index;\n  }\n  return result;\n}\n\n/**\n * len and idx: payload for last node\n * word, size: the string\n * index: position in the string\n */\nstatic BROTLI_BOOL BrotliTrieNodeAdd(MemoryManager* m, uint8_t len,\n    uint32_t idx, const uint8_t* word, size_t size, int index,\n    BrotliTrieNode* node, BrotliTrie* trie) {\n  BrotliTrieNode* child = 0;\n  uint8_t c;\n  if ((size_t)index == size) {\n    if (!node->len_ || idx < node->idx_) {\n      node->len_ = len;\n      node->idx_ = idx;\n    }\n    return BROTLI_TRUE;\n  }\n  c = word[index];\n  if (node->single && c != node->c) {\n    BrotliTrieNode old = trie->pool[node->sub];\n    uint32_t new_nodes = BrotliTrieAlloc(m, 32, trie, &node);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    node->single = 0;\n    node->sub = new_nodes;\n    trie->pool[node->sub + (node->c >> 4)].sub = new_nodes + 16;\n    trie->pool[trie->pool[node->sub + (node->c >> 4)].sub + (node->c & 15)] =\n        old;\n  }\n  if (!node->sub) {\n    uint32_t new_node = BrotliTrieAlloc(m, 1, trie, &node);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    node->single = 1;\n    node->c = c;\n    node->sub = new_node;\n  }\n  if (node->single) {\n    child = &trie->pool[node->sub];\n  } else {\n    if (!trie->pool[node->sub + (c >> 4)].sub) {\n      uint32_t new_nodes = BrotliTrieAlloc(m, 16, trie, &node);\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      trie->pool[node->sub + (c >> 4)].sub = new_nodes;\n    }\n    child = &trie->pool[trie->pool[node->sub + (c >> 4)].sub + (c & 15)];\n  }\n  return BrotliTrieNodeAdd(m, len, idx, word, size, index + 1, child, trie);\n}\n\nstatic BROTLI_BOOL BrotliTrieAdd(MemoryManager* m, uint8_t len, uint32_t idx,\n                          const uint8_t* word, size_t size, BrotliTrie* trie) {\n  return BrotliTrieNodeAdd(m, len, idx, word, size, 0, &trie->root, trie);\n}\n\nconst BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie,\n                                    const BrotliTrieNode* node, uint8_t c) {\n  BrotliTrieNode* temp_node;\n  if (node->single) {\n    if (node->c == c) return &trie->pool[node->sub];\n    return 0;\n  }\n  if (!node->sub) return 0;\n  temp_node = &trie->pool[node->sub + (c >> 4)];\n  if (!temp_node->sub) return 0;\n  return &trie->pool[temp_node->sub + (c & 15)];\n}\n\nstatic const BrotliTrieNode* BrotliTrieFind(const BrotliTrie* trie,\n                                            const uint8_t* word, size_t size) {\n  const BrotliTrieNode* node = &trie->root;\n  size_t i;\n  for (i = 0; i < size; i++) {\n    node = BrotliTrieSub(trie, node, word[i]);\n    if (!node) return 0;\n  }\n  return node;\n}\n\nstatic BROTLI_BOOL BuildDictionaryLut(MemoryManager* m,\n    const BrotliTransforms* transforms,\n    BrotliEncoderDictionary* dict) {\n  uint32_t i;\n  DictWord* dict_words;\n  uint16_t* buckets;\n  DictWord** words_by_hash;\n  size_t* words_by_hash_size;\n  size_t* words_by_hash_capacity;\n  BrotliTrie dedup;\n  uint8_t word[kTransformedBufferSize];\n  size_t word_size;\n  size_t total = 0;\n  uint8_t l;\n  uint16_t idx;\n\n  BrotliTrieInit(&dedup);\n\n  words_by_hash = (DictWord**)BrotliAllocate(m,\n      sizeof(*words_by_hash) * NUM_HASH_BUCKETS);\n  words_by_hash_size = (size_t*)BrotliAllocate(m,\n      sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS);\n  words_by_hash_capacity = (size_t*)BrotliAllocate(m,\n      sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS);\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  memset(words_by_hash, 0, sizeof(*words_by_hash) * NUM_HASH_BUCKETS);\n  memset(words_by_hash_size, 0, sizeof(*words_by_hash_size) * NUM_HASH_BUCKETS);\n  memset(words_by_hash_capacity, 0,\n         sizeof(*words_by_hash_capacity) * NUM_HASH_BUCKETS);\n\n  if (transforms->num_transforms > 0) {\n    for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;\n        l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) {\n      uint16_t n = dict->words->size_bits_by_length[l] ?\n          (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u;\n      for (idx = 0; idx < n; ++idx) {\n        uint32_t key;\n        /* First transform (usually identity) */\n        TransformedDictionaryWord(idx, l, 0, transforms, dict, word,\n                                  &word_size);\n        /* Cannot hash words smaller than 4 bytes */\n        if (word_size < 4) {\n          /* Break instead of continue, all next words of this length will have\n             same length after transform */\n          break;\n        }\n        if (!BrotliTrieAdd(m, 0, idx, word, word_size, &dedup)) {\n          return BROTLI_FALSE;\n        }\n        key = Hash(word, NUM_HASH_BITS);\n        BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],\n            words_by_hash_capacity[key], words_by_hash_size[key],\n            MakeDictWord(l, 0, idx));\n        ++total;\n      }\n    }\n  }\n\n  /* These LUT transforms only supported if no custom transforms. This is\n     ok, we will use the heavy trie instead. */\n  if (transforms == BrotliGetTransforms()) {\n    for (l = SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH;\n        l <= SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH; ++l) {\n      uint16_t n = dict->words->size_bits_by_length[l] ?\n          (uint16_t)(1 << dict->words->size_bits_by_length[l]) : 0u;\n      for (idx = 0; idx < n; ++idx) {\n        int k;\n        BROTLI_BOOL is_ascii = BROTLI_TRUE;\n        size_t offset = dict->words->offsets_by_length[l] + (size_t)l * idx;\n        const uint8_t* data = &dict->words->data[offset];\n        for (k = 0; k < l; ++k) {\n          if (data[k] >= 128) is_ascii = BROTLI_FALSE;\n        }\n        if (data[0] < 128) {\n          int transform = 9;  /* {empty, uppercase first, empty} */\n          uint32_t ix = idx + (uint32_t)transform * n;\n          const BrotliTrieNode* it;\n          TransformedDictionaryWord(idx, l, transform, transforms,\n                                   dict, word, &word_size);\n          it = BrotliTrieFind(&dedup, word, word_size);\n          if (!it || it->idx_ > ix) {\n            uint32_t key = Hash(word, NUM_HASH_BITS);\n            if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) {\n              return BROTLI_FALSE;\n            }\n            BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],\n                words_by_hash_capacity[key], words_by_hash_size[key],\n                MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_FIRST, idx));\n            ++total;\n          }\n        }\n        if (is_ascii) {\n          int transform = 44;  /* {empty, uppercase all, empty} */\n          uint32_t ix = idx + (uint32_t)transform * n;\n          const BrotliTrieNode* it;\n          TransformedDictionaryWord(idx, l, transform, transforms,\n                                    dict, word, &word_size);\n          it = BrotliTrieFind(&dedup, word, word_size);\n          if (!it || it->idx_ > ix) {\n            uint32_t key = Hash(word, NUM_HASH_BITS);\n            if (!BrotliTrieAdd(m, 0, ix, word, word_size, &dedup)) {\n              return BROTLI_FALSE;\n            }\n            BROTLI_ENSURE_CAPACITY_APPEND(m, DictWord, words_by_hash[key],\n                words_by_hash_capacity[key], words_by_hash_size[key],\n                MakeDictWord(l, BROTLI_TRANSFORM_UPPERCASE_ALL, idx));\n            ++total;\n          }\n        }\n      }\n    }\n  }\n\n  dict_words = (DictWord*)BrotliAllocate(m,\n      sizeof(*dict->dict_words) * (total + 1));\n  buckets = (uint16_t*)BrotliAllocate(m,\n      sizeof(*dict->buckets) * NUM_HASH_BUCKETS);\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  dict->dict_words_alloc_size_ = total + 1;\n  dict->dict_words = dict->dict_words_data_ = dict_words;\n  dict->buckets_alloc_size_ = NUM_HASH_BUCKETS;\n  dict->buckets = dict->buckets_data_ = buckets;\n\n  /* Unused; makes offsets start from 1. */\n  dict_words[0] = MakeDictWord(0, 0, 0);\n  total = 1;\n  for (i = 0; i < NUM_HASH_BUCKETS; ++i) {\n    size_t num_words = words_by_hash_size[i];\n    if (num_words > 0) {\n      buckets[i] = (uint16_t)(total);\n      memcpy(&dict_words[total], &words_by_hash[i][0],\n          sizeof(dict_words[0]) * num_words);\n      total += num_words;\n      dict_words[total - 1].len |= 0x80;\n    } else {\n      buckets[i] = 0;\n    }\n  }\n\n  for (i = 0; i < NUM_HASH_BUCKETS; ++i) {\n    BrotliFree(m, words_by_hash[i]);\n  }\n  BrotliFree(m, words_by_hash);\n  BrotliFree(m, words_by_hash_size);\n  BrotliFree(m, words_by_hash_capacity);\n  BrotliTrieFree(m, &dedup);\n\n  return BROTLI_TRUE;\n}\n\nstatic void BuildDictionaryHashTable(uint16_t* hash_table_words,\n    uint8_t* hash_table_lengths, const BrotliDictionary* dict) {\n  int j, len;\n  /* The order of the loops is such that in case of collision, words with\n     shorter length are preferred, and in case of same length, words with\n     smaller index. There is only a single word per bucket. */\n  /* TODO(lode): consider adding optional user-supplied frequency_map to use\n     for preferred words instead, this can make the encoder better for\n     quality 9 and below without affecting the decoder */\n  memset(hash_table_words, 0, sizeof(kStaticDictionaryHashWords));\n  memset(hash_table_lengths, 0, sizeof(kStaticDictionaryHashLengths));\n  for (len = SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH;\n      len >= SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH; --len) {\n    const size_t num_words = dict->size_bits_by_length[len] ?\n        (1u << dict->size_bits_by_length[len]) : 0;\n    for (j = (int)num_words - 1; j >= 0; --j) {\n      size_t offset = dict->offsets_by_length[len] +\n          (size_t)len * (size_t)j;\n      const uint8_t* word = &dict->data[offset];\n      const uint32_t key = Hash(word, 14);\n      int idx = (int)(key << 1) + (len < 8 ? 1 : 0);\n      BROTLI_DCHECK(idx < (int)NUM_HASH_BUCKETS);\n      hash_table_words[idx] = (uint16_t)j;\n      hash_table_lengths[idx] = (uint8_t)len;\n    }\n  }\n}\n\nstatic BROTLI_BOOL GenerateWordsHeavy(MemoryManager* m,\n    const BrotliTransforms* transforms,\n    BrotliEncoderDictionary* dict) {\n  int i, j, l;\n  for (j = (int)transforms->num_transforms - 1; j >= 0 ; --j) {\n    for (l = 0; l < 32; l++) {\n      int num = (int)((1u << dict->words->size_bits_by_length[l]) & ~1u);\n      for (i = 0; i < num; i++) {\n        uint8_t transformed[kTransformedBufferSize];\n        size_t size;\n        TransformedDictionaryWord(\n            (uint32_t)i, l, j, transforms, dict, transformed, &size);\n        if (size < 4) continue;\n        if (!BrotliTrieAdd(m, (uint8_t)l, (uint32_t)(i + num * j),\n            transformed, size, &dict->trie)) {\n          return BROTLI_FALSE;\n        }\n      }\n    }\n  }\n  return BROTLI_TRUE;\n}\n\n/* Computes cutoffTransformsCount (in count) and cutoffTransforms (in data) for\n   the custom transforms, where possible within the limits of the\n   cutoffTransforms encoding. The fast encoder uses this to do fast lookup for\n   transforms that remove the N last characters (OmitLast). */\nstatic void ComputeCutoffTransforms(\n    const BrotliTransforms* transforms,\n    uint32_t* count, uint64_t* data) {\n  int i;\n  /* The encoding in a 64-bit integer of transform N in the data is: (N << 2) +\n     ((cutoffTransforms >> (N * 6)) & 0x3F), so for example the identity\n     transform code must be 0-63, for N=1 the transform code must be 4-67, ...,\n     for N=9 it must be 36-99.\n     TODO(lode): consider a simple flexible uint8_t[10] instead of the uint64_t\n     for the cutoff transforms, so that shared dictionaries can have the\n     OmitLast transforms anywhere without loss. */\n  *count = 0;\n  *data = 0;\n  for (i = 0; i < BROTLI_TRANSFORMS_MAX_CUT_OFF + 1; i++) {\n    int idx = transforms->cutOffTransforms[i];\n    if (idx == -1) break;  /* Not found */\n    if (idx < (i << 2)) break;  /* Too small for the encoding */\n    if (idx >= (i << 2) + 64) break;  /* Too large for the encoding */\n    (*count)++;\n    *data |= (uint64_t)(((uint64_t)idx -\n        ((uint64_t)i << 2u)) << ((uint64_t)i * 6u));\n  }\n}\n\nstatic BROTLI_BOOL ComputeDictionary(MemoryManager* m, int quality,\n    const BrotliTransforms* transforms,\n    BrotliEncoderDictionary* current) {\n  int default_words = current->words == BrotliGetDictionary();\n  int default_transforms = transforms == BrotliGetTransforms();\n\n  if (default_words && default_transforms) {\n    /* hashes are already set to Brotli defaults */\n    return BROTLI_TRUE;\n  }\n\n  current->hash_table_data_words_ = (uint16_t*)BrotliAllocate(\n      m, sizeof(kStaticDictionaryHashWords));\n  current->hash_table_data_lengths_ = (uint8_t*)BrotliAllocate(\n      m, sizeof(kStaticDictionaryHashLengths));\n  if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n  current->hash_table_words = current->hash_table_data_words_;\n  current->hash_table_lengths = current->hash_table_data_lengths_;\n\n  BuildDictionaryHashTable(current->hash_table_data_words_,\n      current->hash_table_data_lengths_, current->words);\n\n  ComputeCutoffTransforms(transforms,\n      &current->cutoffTransformsCount, &current->cutoffTransforms);\n\n  /* Only compute the data for slow encoder if the requested quality is high\n     enough to need it */\n  if (quality >= ZOPFLIFICATION_QUALITY) {\n    if (!BuildDictionaryLut(m, transforms, current)) return BROTLI_FALSE;\n\n    /* For the built-in Brotli transforms, there is a hard-coded function to\n       handle all transforms, but for custom transforms, we use the following\n       large hammer instead */\n    current->has_words_heavy = !default_transforms;\n    if (current->has_words_heavy) {\n      if (!GenerateWordsHeavy(m, transforms, current)) return BROTLI_FALSE;\n    }\n  }\n\n  return BROTLI_TRUE;\n}\n#endif  /* BROTLI_EXPERIMENTAL */\n\nvoid BrotliInitSharedEncoderDictionary(SharedEncoderDictionary* dict) {\n  dict->magic = kSharedDictionaryMagic;\n\n  dict->compound.num_chunks = 0;\n  dict->compound.total_size = 0;\n  dict->compound.chunk_offsets[0] = 0;\n  dict->compound.num_prepared_instances_ = 0;\n\n  dict->contextual.context_based = 0;\n  dict->contextual.num_dictionaries = 1;\n  dict->contextual.instances_ = 0;\n  dict->contextual.num_instances_ = 1;  /* The instance_ field */\n  dict->contextual.dict[0] = &dict->contextual.instance_;\n  InitEncoderDictionary(&dict->contextual.instance_);\n  dict->contextual.instance_.parent = &dict->contextual;\n\n  dict->max_quality = BROTLI_MAX_QUALITY;\n}\n\n#if defined(BROTLI_EXPERIMENTAL)\n/* TODO(eustas): make sure that tooling will warn user if not all the cutoff\n   transforms are available (for low-quality encoder). */\nstatic BROTLI_BOOL InitCustomSharedEncoderDictionary(\n    MemoryManager* m, const BrotliSharedDictionary* decoded_dict,\n    int quality, SharedEncoderDictionary* dict) {\n  ContextualEncoderDictionary* contextual;\n  CompoundDictionary* compound;\n  BrotliEncoderDictionary* instances;\n  int i;\n  BrotliInitSharedEncoderDictionary(dict);\n\n  contextual = &dict->contextual;\n  compound = &dict->compound;\n\n  for (i = 0; i < (int)decoded_dict->num_prefix; i++) {\n    PreparedDictionary* prepared = CreatePreparedDictionary(m,\n        decoded_dict->prefix[i], decoded_dict->prefix_size[i]);\n    AttachPreparedDictionary(compound, prepared);\n    /* remember for cleanup */\n    compound->prepared_instances_[\n        compound->num_prepared_instances_++] = prepared;\n  }\n\n  dict->max_quality = quality;\n  contextual->context_based = decoded_dict->context_based;\n  if (decoded_dict->context_based) {\n    memcpy(contextual->context_map, decoded_dict->context_map,\n        SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS);\n  }\n\n  contextual->num_dictionaries = decoded_dict->num_dictionaries;\n  contextual->num_instances_ = decoded_dict->num_dictionaries;\n  if (contextual->num_instances_ == 1) {\n    instances = &contextual->instance_;\n  } else {\n    contextual->instances_ = (BrotliEncoderDictionary*)\n        BrotliAllocate(m, sizeof(*contextual->instances_) *\n        contextual->num_instances_);\n    if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n    instances = contextual->instances_;\n  }\n  for (i = 0; i < (int)contextual->num_instances_; i++) {\n    BrotliEncoderDictionary* current = &instances[i];\n    InitEncoderDictionary(current);\n    current->parent = &dict->contextual;\n    if (decoded_dict->words[i] == BrotliGetDictionary()) {\n      current->words = BrotliGetDictionary();\n    } else {\n      current->words_instance_ = (BrotliDictionary*)BrotliAllocate(\n          m, sizeof(BrotliDictionary));\n      if (BROTLI_IS_OOM(m)) return BROTLI_FALSE;\n      *current->words_instance_ = *decoded_dict->words[i];\n      current->words = current->words_instance_;\n    }\n    current->num_transforms =\n        (uint32_t)decoded_dict->transforms[i]->num_transforms;\n    if (!ComputeDictionary(\n        m, quality, decoded_dict->transforms[i], current)) {\n      return BROTLI_FALSE;\n    }\n\n    contextual->dict[i] = current;\n  }\n\n  return BROTLI_TRUE;  /* success */\n}\n\nBROTLI_BOOL BrotliInitCustomSharedEncoderDictionary(\n    MemoryManager* m, const uint8_t* encoded_dict, size_t size,\n    int quality, SharedEncoderDictionary* dict) {\n  BROTLI_BOOL success = BROTLI_FALSE;\n  BrotliSharedDictionary* decoded_dict = BrotliSharedDictionaryCreateInstance(\n      m->alloc_func, m->free_func, m->opaque);\n  if (!decoded_dict) {  /* OOM */\n    return BROTLI_FALSE;\n  }\n  success = BrotliSharedDictionaryAttach(\n      decoded_dict, BROTLI_SHARED_DICTIONARY_SERIALIZED, size, encoded_dict);\n  if (success) {\n    success = InitCustomSharedEncoderDictionary(m,\n        decoded_dict, quality, dict);\n  }\n  BrotliSharedDictionaryDestroyInstance(decoded_dict);\n  return success;\n}\n#endif  /* BROTLI_EXPERIMENTAL */\n\nvoid BrotliCleanupSharedEncoderDictionary(MemoryManager* m,\n                                          SharedEncoderDictionary* dict) {\n  size_t i;\n  for (i = 0; i < dict->compound.num_prepared_instances_; i++) {\n    DestroyPreparedDictionary(m,\n        (PreparedDictionary*)dict->compound.prepared_instances_[i]);\n  }\n  if (dict->contextual.num_instances_ == 1) {\n    BrotliDestroyEncoderDictionary(m, &dict->contextual.instance_);\n  } else if (dict->contextual.num_instances_ > 1) {\n    for (i = 0; i < dict->contextual.num_instances_; i++) {\n      BrotliDestroyEncoderDictionary(m, &dict->contextual.instances_[i]);\n    }\n    BrotliFree(m, dict->contextual.instances_);\n  }\n}\n\nManagedDictionary* BrotliCreateManagedDictionary(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  ManagedDictionary* result = (ManagedDictionary*)BrotliBootstrapAlloc(\n      sizeof(ManagedDictionary), alloc_func, free_func, opaque);\n  if (result == NULL) return NULL;\n\n  result->magic = kManagedDictionaryMagic;\n  BrotliInitMemoryManager(\n      &result->memory_manager_, alloc_func, free_func, opaque);\n  result->dictionary = NULL;\n\n  return result;\n}\n\nvoid BrotliDestroyManagedDictionary(ManagedDictionary* dictionary) {\n  if (!dictionary) return;\n  BrotliBootstrapFree(dictionary, &dictionary->memory_manager_);\n}\n\n/* Escalate internal functions visibility; for testing purposes only. */\n#if defined(BROTLI_TEST)\nvoid InitEncoderDictionaryForTest(BrotliEncoderDictionary*);\nvoid InitEncoderDictionaryForTest(BrotliEncoderDictionary* d) {\n  InitEncoderDictionary(d);\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/encoder_dict.h",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#ifndef BROTLI_ENC_ENCODER_DICT_H_\n#define BROTLI_ENC_ENCODER_DICT_H_\n\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"compound_dictionary.h\"\n#include \"memory.h\"\n#include \"static_dict_lut.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/*\nDictionary hierarchy for Encoder:\n-SharedEncoderDictionary\n--CompoundDictionary\n---PreparedDictionary [up to 15x]\n   = prefix dictionary with precomputed hashes\n--ContextualEncoderDictionary\n---BrotliEncoderDictionary [up to 64x]\n   = for each context, precomputed static dictionary with words + transforms\n\nDictionary hiearchy from common: similar, but without precomputed hashes\n-BrotliSharedDictionary\n--BrotliDictionary [up to 64x]\n--BrotliTransforms [up to 64x]\n--const uint8_t* prefix [up to 15x]: compound dictionaries\n*/\n\ntypedef struct BrotliTrieNode {\n  uint8_t single;  /* if 1, sub is a single node for c instead of 256 */\n  uint8_t c;\n  uint8_t len_;  /* untransformed length */\n  uint32_t idx_;  /* word index + num words * transform index */\n  uint32_t sub;  /* index of sub node(s) in the pool */\n} BrotliTrieNode;\n\ntypedef struct BrotliTrie {\n  BrotliTrieNode* pool;\n  size_t pool_capacity;\n  size_t pool_size;\n  BrotliTrieNode root;\n} BrotliTrie;\n\n#if defined(BROTLI_EXPERIMENTAL)\nBROTLI_INTERNAL const BrotliTrieNode* BrotliTrieSub(const BrotliTrie* trie,\n    const BrotliTrieNode* node, uint8_t c);\n#endif  /* BROTLI_EXPERIMENTAL */\n\n/* Dictionary data (words and transforms) for 1 possible context */\ntypedef struct BrotliEncoderDictionary {\n  const BrotliDictionary* words;\n  uint32_t num_transforms;\n\n  /* cut off for fast encoder */\n  uint32_t cutoffTransformsCount;\n  uint64_t cutoffTransforms;\n\n  /* from dictionary_hash.h, for fast encoder */\n  const uint16_t* hash_table_words;\n  const uint8_t* hash_table_lengths;\n\n  /* from static_dict_lut.h, for slow encoder */\n  const uint16_t* buckets;\n  const DictWord* dict_words;\n  /* Heavy version, for use by slow encoder when there are custom transforms.\n     Contains every possible transformed dictionary word in a trie. It encodes\n     about as fast as the non-heavy encoder but consumes a lot of memory and\n     takes time to build. */\n  BrotliTrie trie;\n  BROTLI_BOOL has_words_heavy;\n\n  /* Reference to other dictionaries. */\n  const struct ContextualEncoderDictionary* parent;\n\n  /* Allocated memory, used only when not using the Brotli defaults */\n  uint16_t* hash_table_data_words_;\n  uint8_t* hash_table_data_lengths_;\n  size_t buckets_alloc_size_;\n  uint16_t* buckets_data_;\n  size_t dict_words_alloc_size_;\n  DictWord* dict_words_data_;\n  BrotliDictionary* words_instance_;\n} BrotliEncoderDictionary;\n\n/* Dictionary data for all 64 contexts */\ntypedef struct ContextualEncoderDictionary {\n  BROTLI_BOOL context_based;\n  uint8_t num_dictionaries;\n  uint8_t context_map[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n  const BrotliEncoderDictionary* dict[SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS];\n\n  /* If num_instances_ is 1, instance_ is used, else dynamic allocation with\n     instances_ is used. */\n  size_t num_instances_;\n  BrotliEncoderDictionary instance_;\n  BrotliEncoderDictionary* instances_;\n} ContextualEncoderDictionary;\n\ntypedef struct SharedEncoderDictionary {\n  /* Magic value to distinguish this struct from PreparedDictionary for\n     certain external usages. */\n  uint32_t magic;\n\n  /* LZ77 prefix, compound dictionary */\n  CompoundDictionary compound;\n\n  /* Custom static dictionary (optionally context-based) */\n  ContextualEncoderDictionary contextual;\n\n  /* The maximum quality the dictionary was computed for */\n  int max_quality;\n} SharedEncoderDictionary;\n\ntypedef struct ManagedDictionary {\n  uint32_t magic;\n  MemoryManager memory_manager_;\n  uint32_t* dictionary;\n} ManagedDictionary;\n\n/* Initializes to the brotli built-in dictionary */\nBROTLI_INTERNAL void BrotliInitSharedEncoderDictionary(\n    SharedEncoderDictionary* dict);\n\n#if defined(BROTLI_EXPERIMENTAL)\n/* Initializes to shared dictionary that will be parsed from\n   encoded_dict. Requires that you keep the encoded_dict buffer\n   around, parts of data will point to it. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliInitCustomSharedEncoderDictionary(\n    MemoryManager* m, const uint8_t* encoded_dict, size_t size,\n    int quality, SharedEncoderDictionary* dict);\n#endif  /* BROTLI_EXPERIMENTAL */\n\nBROTLI_INTERNAL void BrotliCleanupSharedEncoderDictionary(\n    MemoryManager* m, SharedEncoderDictionary* dict);\n\nBROTLI_INTERNAL ManagedDictionary* BrotliCreateManagedDictionary(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\nBROTLI_INTERNAL void BrotliDestroyManagedDictionary(\n    ManagedDictionary* dictionary);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENCODER_DICT_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/entropy_encode.c",
    "content": "/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Entropy encoding (Huffman) utilities. */\n\n#include \"entropy_encode.h\"\n\n#include <string.h>  /* memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nconst size_t kBrotliShellGaps[] = {132, 57, 23, 10, 4, 1};\n\nBROTLI_BOOL BrotliSetDepth(\n    int p0, HuffmanTree* pool, uint8_t* depth, int max_depth) {\n  int stack[16];\n  int level = 0;\n  int p = p0;\n  BROTLI_DCHECK(max_depth <= 15);\n  stack[0] = -1;\n  while (BROTLI_TRUE) {\n    if (pool[p].index_left_ >= 0) {\n      level++;\n      if (level > max_depth) return BROTLI_FALSE;\n      stack[level] = pool[p].index_right_or_value_;\n      p = pool[p].index_left_;\n      continue;\n    } else {\n      depth[pool[p].index_right_or_value_] = (uint8_t)level;\n    }\n    while (level >= 0 && stack[level] == -1) level--;\n    if (level < 0) return BROTLI_TRUE;\n    p = stack[level];\n    stack[level] = -1;\n  }\n}\n\n/* Sort the root nodes, least popular first. */\nstatic BROTLI_INLINE BROTLI_BOOL SortHuffmanTree(\n    const HuffmanTree* v0, const HuffmanTree* v1) {\n  if (v0->total_count_ != v1->total_count_) {\n    return TO_BROTLI_BOOL(v0->total_count_ < v1->total_count_);\n  }\n  return TO_BROTLI_BOOL(v0->index_right_or_value_ > v1->index_right_or_value_);\n}\n\n/* This function will create a Huffman tree.\n\n   The catch here is that the tree cannot be arbitrarily deep.\n   Brotli specifies a maximum depth of 15 bits for \"code trees\"\n   and 7 bits for \"code length code trees.\"\n\n   count_limit is the value that is to be faked as the minimum value\n   and this minimum value is raised until the tree matches the\n   maximum length requirement.\n\n   This algorithm is not of excellent performance for very long data blocks,\n   especially when population counts are longer than 2**tree_limit, but\n   we are not planning to use this with extremely long blocks.\n\n   See http://en.wikipedia.org/wiki/Huffman_coding */\nvoid BrotliCreateHuffmanTree(const uint32_t* data,\n                             const size_t length,\n                             const int tree_limit,\n                             HuffmanTree* tree,\n                             uint8_t* depth) {\n  uint32_t count_limit;\n  HuffmanTree sentinel;\n  InitHuffmanTree(&sentinel, BROTLI_UINT32_MAX, -1, -1);\n  /* For block sizes below 64 kB, we never need to do a second iteration\n     of this loop. Probably all of our block sizes will be smaller than\n     that, so this loop is mostly of academic interest. If we actually\n     would need this, we would be better off with the Katajainen algorithm. */\n  for (count_limit = 1; ; count_limit *= 2) {\n    size_t n = 0;\n    size_t i;\n    size_t j;\n    size_t k;\n    for (i = length; i != 0;) {\n      --i;\n      if (data[i]) {\n        const uint32_t count = BROTLI_MAX(uint32_t, data[i], count_limit);\n        InitHuffmanTree(&tree[n++], count, -1, (int16_t)i);\n      }\n    }\n\n    if (n == 1) {\n      depth[tree[0].index_right_or_value_] = 1;  /* Only one element. */\n      break;\n    }\n\n    SortHuffmanTreeItems(tree, n, SortHuffmanTree);\n\n    /* The nodes are:\n       [0, n): the sorted leaf nodes that we start with.\n       [n]: we add a sentinel here.\n       [n + 1, 2n): new parent nodes are added here, starting from\n                    (n+1). These are naturally in ascending order.\n       [2n]: we add a sentinel at the end as well.\n       There will be (2n+1) elements at the end. */\n    tree[n] = sentinel;\n    tree[n + 1] = sentinel;\n\n    i = 0;      /* Points to the next leaf node. */\n    j = n + 1;  /* Points to the next non-leaf node. */\n    for (k = n - 1; k != 0; --k) {\n      size_t left, right;\n      if (tree[i].total_count_ <= tree[j].total_count_) {\n        left = i;\n        ++i;\n      } else {\n        left = j;\n        ++j;\n      }\n      if (tree[i].total_count_ <= tree[j].total_count_) {\n        right = i;\n        ++i;\n      } else {\n        right = j;\n        ++j;\n      }\n\n      {\n        /* The sentinel node becomes the parent node. */\n        size_t j_end = 2 * n - k;\n        tree[j_end].total_count_ =\n            tree[left].total_count_ + tree[right].total_count_;\n        tree[j_end].index_left_ = (int16_t)left;\n        tree[j_end].index_right_or_value_ = (int16_t)right;\n\n        /* Add back the last sentinel node. */\n        tree[j_end + 1] = sentinel;\n      }\n    }\n    if (BrotliSetDepth((int)(2 * n - 1), &tree[0], depth, tree_limit)) {\n      /* We need to pack the Huffman tree in tree_limit bits. If this was not\n         successful, add fake entities to the lowest values and retry. */\n      break;\n    }\n  }\n}\n\nstatic void Reverse(uint8_t* v, size_t start, size_t end) {\n  --end;\n  while (start < end) {\n    uint8_t tmp = v[start];\n    v[start] = v[end];\n    v[end] = tmp;\n    ++start;\n    --end;\n  }\n}\n\nstatic void BrotliWriteHuffmanTreeRepetitions(\n    const uint8_t previous_value,\n    const uint8_t value,\n    size_t repetitions,\n    size_t* tree_size,\n    uint8_t* tree,\n    uint8_t* extra_bits_data) {\n  BROTLI_DCHECK(repetitions > 0);\n  if (previous_value != value) {\n    tree[*tree_size] = value;\n    extra_bits_data[*tree_size] = 0;\n    ++(*tree_size);\n    --repetitions;\n  }\n  if (repetitions == 7) {\n    tree[*tree_size] = value;\n    extra_bits_data[*tree_size] = 0;\n    ++(*tree_size);\n    --repetitions;\n  }\n  if (repetitions < 3) {\n    size_t i;\n    for (i = 0; i < repetitions; ++i) {\n      tree[*tree_size] = value;\n      extra_bits_data[*tree_size] = 0;\n      ++(*tree_size);\n    }\n  } else {\n    size_t start = *tree_size;\n    repetitions -= 3;\n    while (BROTLI_TRUE) {\n      tree[*tree_size] = BROTLI_REPEAT_PREVIOUS_CODE_LENGTH;\n      extra_bits_data[*tree_size] = repetitions & 0x3;\n      ++(*tree_size);\n      repetitions >>= 2;\n      if (repetitions == 0) {\n        break;\n      }\n      --repetitions;\n    }\n    Reverse(tree, start, *tree_size);\n    Reverse(extra_bits_data, start, *tree_size);\n  }\n}\n\nstatic void BrotliWriteHuffmanTreeRepetitionsZeros(\n    size_t repetitions,\n    size_t* tree_size,\n    uint8_t* tree,\n    uint8_t* extra_bits_data) {\n  if (repetitions == 11) {\n    tree[*tree_size] = 0;\n    extra_bits_data[*tree_size] = 0;\n    ++(*tree_size);\n    --repetitions;\n  }\n  if (repetitions < 3) {\n    size_t i;\n    for (i = 0; i < repetitions; ++i) {\n      tree[*tree_size] = 0;\n      extra_bits_data[*tree_size] = 0;\n      ++(*tree_size);\n    }\n  } else {\n    size_t start = *tree_size;\n    repetitions -= 3;\n    while (BROTLI_TRUE) {\n      tree[*tree_size] = BROTLI_REPEAT_ZERO_CODE_LENGTH;\n      extra_bits_data[*tree_size] = repetitions & 0x7;\n      ++(*tree_size);\n      repetitions >>= 3;\n      if (repetitions == 0) {\n        break;\n      }\n      --repetitions;\n    }\n    Reverse(tree, start, *tree_size);\n    Reverse(extra_bits_data, start, *tree_size);\n  }\n}\n\nvoid BrotliOptimizeHuffmanCountsForRle(size_t length, uint32_t* counts,\n                                       uint8_t* good_for_rle) {\n  size_t nonzero_count = 0;\n  size_t stride;\n  size_t limit;\n  size_t sum;\n  const size_t streak_limit = 1240;\n  /* Let's make the Huffman code more compatible with RLE encoding. */\n  size_t i;\n  for (i = 0; i < length; i++) {\n    if (counts[i]) {\n      ++nonzero_count;\n    }\n  }\n  if (nonzero_count < 16) {\n    return;\n  }\n  while (length != 0 && counts[length - 1] == 0) {\n    --length;\n  }\n  if (length == 0) {\n    return;  /* All zeros. */\n  }\n  /* Now counts[0..length - 1] does not have trailing zeros. */\n  {\n    size_t nonzeros = 0;\n    uint32_t smallest_nonzero = 1 << 30;\n    for (i = 0; i < length; ++i) {\n      if (counts[i] != 0) {\n        ++nonzeros;\n        if (smallest_nonzero > counts[i]) {\n          smallest_nonzero = counts[i];\n        }\n      }\n    }\n    if (nonzeros < 5) {\n      /* Small histogram will model it well. */\n      return;\n    }\n    if (smallest_nonzero < 4) {\n      size_t zeros = length - nonzeros;\n      if (zeros < 6) {\n        for (i = 1; i < length - 1; ++i) {\n          if (counts[i - 1] != 0 && counts[i] == 0 && counts[i + 1] != 0) {\n            counts[i] = 1;\n          }\n        }\n      }\n    }\n    if (nonzeros < 28) {\n      return;\n    }\n  }\n  /* 2) Let's mark all population counts that already can be encoded\n     with an RLE code. */\n  memset(good_for_rle, 0, length);\n  {\n    /* Let's not spoil any of the existing good RLE codes.\n       Mark any seq of 0's that is longer as 5 as a good_for_rle.\n       Mark any seq of non-0's that is longer as 7 as a good_for_rle. */\n    uint32_t symbol = counts[0];\n    size_t step = 0;\n    for (i = 0; i <= length; ++i) {\n      if (i == length || counts[i] != symbol) {\n        if ((symbol == 0 && step >= 5) ||\n            (symbol != 0 && step >= 7)) {\n          size_t k;\n          for (k = 0; k < step; ++k) {\n            good_for_rle[i - k - 1] = 1;\n          }\n        }\n        step = 1;\n        if (i != length) {\n          symbol = counts[i];\n        }\n      } else {\n        ++step;\n      }\n    }\n  }\n  /* 3) Let's replace those population counts that lead to more RLE codes.\n     Math here is in 24.8 fixed point representation. */\n  stride = 0;\n  limit = 256 * (counts[0] + counts[1] + counts[2]) / 3 + 420;\n  sum = 0;\n  for (i = 0; i <= length; ++i) {\n    if (i == length || good_for_rle[i] ||\n        (i != 0 && good_for_rle[i - 1]) ||\n        (256 * counts[i] - limit + streak_limit) >= 2 * streak_limit) {\n      if (stride >= 4 || (stride >= 3 && sum == 0)) {\n        size_t k;\n        /* The stride must end, collapse what we have, if we have enough (4). */\n        size_t count = (sum + stride / 2) / stride;\n        if (count == 0) {\n          count = 1;\n        }\n        if (sum == 0) {\n          /* Don't make an all zeros stride to be upgraded to ones. */\n          count = 0;\n        }\n        for (k = 0; k < stride; ++k) {\n          /* We don't want to change value at counts[i],\n             that is already belonging to the next stride. Thus - 1. */\n          counts[i - k - 1] = (uint32_t)count;\n        }\n      }\n      stride = 0;\n      sum = 0;\n      if (i < length - 2) {\n        /* All interesting strides have a count of at least 4, */\n        /* at least when non-zeros. */\n        limit = 256 * (counts[i] + counts[i + 1] + counts[i + 2]) / 3 + 420;\n      } else if (i < length) {\n        limit = 256 * counts[i];\n      } else {\n        limit = 0;\n      }\n    }\n    ++stride;\n    if (i != length) {\n      sum += counts[i];\n      if (stride >= 4) {\n        limit = (256 * sum + stride / 2) / stride;\n      }\n      if (stride == 4) {\n        limit += 120;\n      }\n    }\n  }\n}\n\nstatic void DecideOverRleUse(const uint8_t* depth, const size_t length,\n                             BROTLI_BOOL* use_rle_for_non_zero,\n                             BROTLI_BOOL* use_rle_for_zero) {\n  size_t total_reps_zero = 0;\n  size_t total_reps_non_zero = 0;\n  size_t count_reps_zero = 1;\n  size_t count_reps_non_zero = 1;\n  size_t i;\n  for (i = 0; i < length;) {\n    const uint8_t value = depth[i];\n    size_t reps = 1;\n    size_t k;\n    for (k = i + 1; k < length && depth[k] == value; ++k) {\n      ++reps;\n    }\n    if (reps >= 3 && value == 0) {\n      total_reps_zero += reps;\n      ++count_reps_zero;\n    }\n    if (reps >= 4 && value != 0) {\n      total_reps_non_zero += reps;\n      ++count_reps_non_zero;\n    }\n    i += reps;\n  }\n  *use_rle_for_non_zero =\n      TO_BROTLI_BOOL(total_reps_non_zero > count_reps_non_zero * 2);\n  *use_rle_for_zero = TO_BROTLI_BOOL(total_reps_zero > count_reps_zero * 2);\n}\n\nvoid BrotliWriteHuffmanTree(const uint8_t* depth,\n                            size_t length,\n                            size_t* tree_size,\n                            uint8_t* tree,\n                            uint8_t* extra_bits_data) {\n  uint8_t previous_value = BROTLI_INITIAL_REPEATED_CODE_LENGTH;\n  size_t i;\n  BROTLI_BOOL use_rle_for_non_zero = BROTLI_FALSE;\n  BROTLI_BOOL use_rle_for_zero = BROTLI_FALSE;\n\n  /* Throw away trailing zeros. */\n  size_t new_length = length;\n  for (i = 0; i < length; ++i) {\n    if (depth[length - i - 1] == 0) {\n      --new_length;\n    } else {\n      break;\n    }\n  }\n\n  /* First gather statistics on if it is a good idea to do RLE. */\n  if (length > 50) {\n    /* Find RLE coding for longer codes.\n       Shorter codes seem not to benefit from RLE. */\n    DecideOverRleUse(depth, new_length,\n                     &use_rle_for_non_zero, &use_rle_for_zero);\n  }\n\n  /* Actual RLE coding. */\n  for (i = 0; i < new_length;) {\n    const uint8_t value = depth[i];\n    size_t reps = 1;\n    if ((value != 0 && use_rle_for_non_zero) ||\n        (value == 0 && use_rle_for_zero)) {\n      size_t k;\n      for (k = i + 1; k < new_length && depth[k] == value; ++k) {\n        ++reps;\n      }\n    }\n    if (value == 0) {\n      BrotliWriteHuffmanTreeRepetitionsZeros(\n          reps, tree_size, tree, extra_bits_data);\n    } else {\n      BrotliWriteHuffmanTreeRepetitions(previous_value,\n                                        value, reps, tree_size,\n                                        tree, extra_bits_data);\n      previous_value = value;\n    }\n    i += reps;\n  }\n}\n\nstatic uint16_t BrotliReverseBits(size_t num_bits, uint16_t bits) {\n  static const size_t kLut[16] = {  /* Pre-reversed 4-bit values. */\n    0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E,\n    0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F\n  };\n  size_t retval = kLut[bits & 0x0F];\n  size_t i;\n  for (i = 4; i < num_bits; i += 4) {\n    retval <<= 4;\n    bits = (uint16_t)(bits >> 4);\n    retval |= kLut[bits & 0x0F];\n  }\n  retval >>= ((0 - num_bits) & 0x03);\n  return (uint16_t)retval;\n}\n\n/* 0..15 are values for bits */\n#define MAX_HUFFMAN_BITS 16\n\nvoid BrotliConvertBitDepthsToSymbols(const uint8_t* depth,\n                                     size_t len,\n                                     uint16_t* bits) {\n  /* In Brotli, all bit depths are [1..15]\n     0 bit depth means that the symbol does not exist. */\n  uint16_t bl_count[MAX_HUFFMAN_BITS] = { 0 };\n  uint16_t next_code[MAX_HUFFMAN_BITS];\n  size_t i;\n  int code = 0;\n  for (i = 0; i < len; ++i) {\n    ++bl_count[depth[i]];\n  }\n  bl_count[0] = 0;\n  next_code[0] = 0;\n  for (i = 1; i < MAX_HUFFMAN_BITS; ++i) {\n    code = (code + bl_count[i - 1]) << 1;\n    next_code[i] = (uint16_t)code;\n  }\n  for (i = 0; i < len; ++i) {\n    if (depth[i]) {\n      bits[i] = BrotliReverseBits(depth[i], next_code[depth[i]]++);\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/entropy_encode.h",
    "content": "/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Entropy encoding (Huffman) utilities. */\n\n#ifndef BROTLI_ENC_ENTROPY_ENCODE_H_\n#define BROTLI_ENC_ENTROPY_ENCODE_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* A node of a Huffman tree. */\ntypedef struct HuffmanTree {\n  uint32_t total_count_;\n  int16_t index_left_;\n  int16_t index_right_or_value_;\n} HuffmanTree;\n\nstatic BROTLI_INLINE void InitHuffmanTree(HuffmanTree* self, uint32_t count,\n    int16_t left, int16_t right) {\n  self->total_count_ = count;\n  self->index_left_ = left;\n  self->index_right_or_value_ = right;\n}\n\n/* Returns 1 is assignment of depths succeeded, otherwise 0. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliSetDepth(\n    int p, HuffmanTree* pool, uint8_t* depth, int max_depth);\n\n/* This function will create a Huffman tree.\n\n   The (data,length) contains the population counts.\n   The tree_limit is the maximum bit depth of the Huffman codes.\n\n   The depth contains the tree, i.e., how many bits are used for\n   the symbol.\n\n   The actual Huffman tree is constructed in the tree[] array, which has to\n   be at least 2 * length + 1 long.\n\n   See http://en.wikipedia.org/wiki/Huffman_coding */\nBROTLI_INTERNAL void BrotliCreateHuffmanTree(const uint32_t* data,\n                                             const size_t length,\n                                             const int tree_limit,\n                                             HuffmanTree* tree,\n                                             uint8_t* depth);\n\n/* Change the population counts in a way that the consequent\n   Huffman tree compression, especially its RLE-part will be more\n   likely to compress this data more efficiently.\n\n   length contains the size of the histogram.\n   counts contains the population counts.\n   good_for_rle is a buffer of at least length size */\nBROTLI_INTERNAL void BrotliOptimizeHuffmanCountsForRle(\n    size_t length, uint32_t* counts, uint8_t* good_for_rle);\n\n/* Write a Huffman tree from bit depths into the bit-stream representation\n   of a Huffman tree. The generated Huffman tree is to be compressed once\n   more using a Huffman tree */\nBROTLI_INTERNAL void BrotliWriteHuffmanTree(const uint8_t* depth,\n                                            size_t num,\n                                            size_t* tree_size,\n                                            uint8_t* tree,\n                                            uint8_t* extra_bits_data);\n\n/* Get the actual bit values for a tree of bit depths. */\nBROTLI_INTERNAL void BrotliConvertBitDepthsToSymbols(const uint8_t* depth,\n                                                     size_t len,\n                                                     uint16_t* bits);\n\nBROTLI_INTERNAL extern const size_t kBrotliShellGaps[6];\n/* Input size optimized Shell sort. */\ntypedef BROTLI_BOOL (*HuffmanTreeComparator)(\n    const HuffmanTree*, const HuffmanTree*);\nstatic BROTLI_INLINE void SortHuffmanTreeItems(HuffmanTree* items,\n    const size_t n, HuffmanTreeComparator comparator) {\n  if (n < 13) {\n    /* Insertion sort. */\n    size_t i;\n    for (i = 1; i < n; ++i) {\n      HuffmanTree tmp = items[i];\n      size_t k = i;\n      size_t j = i - 1;\n      while (comparator(&tmp, &items[j])) {\n        items[k] = items[j];\n        k = j;\n        if (!j--) break;\n      }\n      items[k] = tmp;\n    }\n    return;\n  } else {\n    /* Shell sort. */\n    int g = n < 57 ? 2 : 0;\n    for (; g < 6; ++g) {\n      size_t gap = kBrotliShellGaps[g];\n      size_t i;\n      for (i = gap; i < n; ++i) {\n        size_t j = i;\n        HuffmanTree tmp = items[i];\n        for (; j >= gap && comparator(&tmp, &items[j - gap]); j -= gap) {\n          items[j] = items[j - gap];\n        }\n        items[j] = tmp;\n      }\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENTROPY_ENCODE_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/entropy_encode_static.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Static entropy codes used for faster meta-block encoding. */\n\n#ifndef BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_\n#define BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"write_bits.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic const uint8_t kCodeLengthDepth[18] = {\n  4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 0, 4, 4,\n};\n\nstatic const uint8_t kStaticCommandCodeDepth[BROTLI_NUM_COMMAND_SYMBOLS] = {\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n   9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,  9,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n  11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,\n};\n\nstatic const uint8_t kStaticDistanceCodeDepth[64] = {\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,\n};\n\n/* GENERATED CODE START */\nstatic const uint32_t kCodeLengthBits[18] = {\n  0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 15, 31, 0, 11, 7,\n};\n\nstatic BROTLI_INLINE void StoreStaticCodeLengthCode(\n    size_t* storage_ix, uint8_t* storage) {\n  BrotliWriteBits(\n      40, BROTLI_MAKE_UINT64_T(0x0000FFu, 0x55555554u), storage_ix, storage);\n}\n\nstatic const uint64_t kZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = {\n  0x00000000, 0x00000000, 0x00000000, 0x00000007, 0x00000017, 0x00000027,\n  0x00000037, 0x00000047, 0x00000057, 0x00000067, 0x00000077, 0x00000770,\n  0x00000b87, 0x00001387, 0x00001b87, 0x00002387, 0x00002b87, 0x00003387,\n  0x00003b87, 0x00000397, 0x00000b97, 0x00001397, 0x00001b97, 0x00002397,\n  0x00002b97, 0x00003397, 0x00003b97, 0x000003a7, 0x00000ba7, 0x000013a7,\n  0x00001ba7, 0x000023a7, 0x00002ba7, 0x000033a7, 0x00003ba7, 0x000003b7,\n  0x00000bb7, 0x000013b7, 0x00001bb7, 0x000023b7, 0x00002bb7, 0x000033b7,\n  0x00003bb7, 0x000003c7, 0x00000bc7, 0x000013c7, 0x00001bc7, 0x000023c7,\n  0x00002bc7, 0x000033c7, 0x00003bc7, 0x000003d7, 0x00000bd7, 0x000013d7,\n  0x00001bd7, 0x000023d7, 0x00002bd7, 0x000033d7, 0x00003bd7, 0x000003e7,\n  0x00000be7, 0x000013e7, 0x00001be7, 0x000023e7, 0x00002be7, 0x000033e7,\n  0x00003be7, 0x000003f7, 0x00000bf7, 0x000013f7, 0x00001bf7, 0x000023f7,\n  0x00002bf7, 0x000033f7, 0x00003bf7, 0x0001c387, 0x0005c387, 0x0009c387,\n  0x000dc387, 0x0011c387, 0x0015c387, 0x0019c387, 0x001dc387, 0x0001cb87,\n  0x0005cb87, 0x0009cb87, 0x000dcb87, 0x0011cb87, 0x0015cb87, 0x0019cb87,\n  0x001dcb87, 0x0001d387, 0x0005d387, 0x0009d387, 0x000dd387, 0x0011d387,\n  0x0015d387, 0x0019d387, 0x001dd387, 0x0001db87, 0x0005db87, 0x0009db87,\n  0x000ddb87, 0x0011db87, 0x0015db87, 0x0019db87, 0x001ddb87, 0x0001e387,\n  0x0005e387, 0x0009e387, 0x000de387, 0x0011e387, 0x0015e387, 0x0019e387,\n  0x001de387, 0x0001eb87, 0x0005eb87, 0x0009eb87, 0x000deb87, 0x0011eb87,\n  0x0015eb87, 0x0019eb87, 0x001deb87, 0x0001f387, 0x0005f387, 0x0009f387,\n  0x000df387, 0x0011f387, 0x0015f387, 0x0019f387, 0x001df387, 0x0001fb87,\n  0x0005fb87, 0x0009fb87, 0x000dfb87, 0x0011fb87, 0x0015fb87, 0x0019fb87,\n  0x001dfb87, 0x0001c397, 0x0005c397, 0x0009c397, 0x000dc397, 0x0011c397,\n  0x0015c397, 0x0019c397, 0x001dc397, 0x0001cb97, 0x0005cb97, 0x0009cb97,\n  0x000dcb97, 0x0011cb97, 0x0015cb97, 0x0019cb97, 0x001dcb97, 0x0001d397,\n  0x0005d397, 0x0009d397, 0x000dd397, 0x0011d397, 0x0015d397, 0x0019d397,\n  0x001dd397, 0x0001db97, 0x0005db97, 0x0009db97, 0x000ddb97, 0x0011db97,\n  0x0015db97, 0x0019db97, 0x001ddb97, 0x0001e397, 0x0005e397, 0x0009e397,\n  0x000de397, 0x0011e397, 0x0015e397, 0x0019e397, 0x001de397, 0x0001eb97,\n  0x0005eb97, 0x0009eb97, 0x000deb97, 0x0011eb97, 0x0015eb97, 0x0019eb97,\n  0x001deb97, 0x0001f397, 0x0005f397, 0x0009f397, 0x000df397, 0x0011f397,\n  0x0015f397, 0x0019f397, 0x001df397, 0x0001fb97, 0x0005fb97, 0x0009fb97,\n  0x000dfb97, 0x0011fb97, 0x0015fb97, 0x0019fb97, 0x001dfb97, 0x0001c3a7,\n  0x0005c3a7, 0x0009c3a7, 0x000dc3a7, 0x0011c3a7, 0x0015c3a7, 0x0019c3a7,\n  0x001dc3a7, 0x0001cba7, 0x0005cba7, 0x0009cba7, 0x000dcba7, 0x0011cba7,\n  0x0015cba7, 0x0019cba7, 0x001dcba7, 0x0001d3a7, 0x0005d3a7, 0x0009d3a7,\n  0x000dd3a7, 0x0011d3a7, 0x0015d3a7, 0x0019d3a7, 0x001dd3a7, 0x0001dba7,\n  0x0005dba7, 0x0009dba7, 0x000ddba7, 0x0011dba7, 0x0015dba7, 0x0019dba7,\n  0x001ddba7, 0x0001e3a7, 0x0005e3a7, 0x0009e3a7, 0x000de3a7, 0x0011e3a7,\n  0x0015e3a7, 0x0019e3a7, 0x001de3a7, 0x0001eba7, 0x0005eba7, 0x0009eba7,\n  0x000deba7, 0x0011eba7, 0x0015eba7, 0x0019eba7, 0x001deba7, 0x0001f3a7,\n  0x0005f3a7, 0x0009f3a7, 0x000df3a7, 0x0011f3a7, 0x0015f3a7, 0x0019f3a7,\n  0x001df3a7, 0x0001fba7, 0x0005fba7, 0x0009fba7, 0x000dfba7, 0x0011fba7,\n  0x0015fba7, 0x0019fba7, 0x001dfba7, 0x0001c3b7, 0x0005c3b7, 0x0009c3b7,\n  0x000dc3b7, 0x0011c3b7, 0x0015c3b7, 0x0019c3b7, 0x001dc3b7, 0x0001cbb7,\n  0x0005cbb7, 0x0009cbb7, 0x000dcbb7, 0x0011cbb7, 0x0015cbb7, 0x0019cbb7,\n  0x001dcbb7, 0x0001d3b7, 0x0005d3b7, 0x0009d3b7, 0x000dd3b7, 0x0011d3b7,\n  0x0015d3b7, 0x0019d3b7, 0x001dd3b7, 0x0001dbb7, 0x0005dbb7, 0x0009dbb7,\n  0x000ddbb7, 0x0011dbb7, 0x0015dbb7, 0x0019dbb7, 0x001ddbb7, 0x0001e3b7,\n  0x0005e3b7, 0x0009e3b7, 0x000de3b7, 0x0011e3b7, 0x0015e3b7, 0x0019e3b7,\n  0x001de3b7, 0x0001ebb7, 0x0005ebb7, 0x0009ebb7, 0x000debb7, 0x0011ebb7,\n  0x0015ebb7, 0x0019ebb7, 0x001debb7, 0x0001f3b7, 0x0005f3b7, 0x0009f3b7,\n  0x000df3b7, 0x0011f3b7, 0x0015f3b7, 0x0019f3b7, 0x001df3b7, 0x0001fbb7,\n  0x0005fbb7, 0x0009fbb7, 0x000dfbb7, 0x0011fbb7, 0x0015fbb7, 0x0019fbb7,\n  0x001dfbb7, 0x0001c3c7, 0x0005c3c7, 0x0009c3c7, 0x000dc3c7, 0x0011c3c7,\n  0x0015c3c7, 0x0019c3c7, 0x001dc3c7, 0x0001cbc7, 0x0005cbc7, 0x0009cbc7,\n  0x000dcbc7, 0x0011cbc7, 0x0015cbc7, 0x0019cbc7, 0x001dcbc7, 0x0001d3c7,\n  0x0005d3c7, 0x0009d3c7, 0x000dd3c7, 0x0011d3c7, 0x0015d3c7, 0x0019d3c7,\n  0x001dd3c7, 0x0001dbc7, 0x0005dbc7, 0x0009dbc7, 0x000ddbc7, 0x0011dbc7,\n  0x0015dbc7, 0x0019dbc7, 0x001ddbc7, 0x0001e3c7, 0x0005e3c7, 0x0009e3c7,\n  0x000de3c7, 0x0011e3c7, 0x0015e3c7, 0x0019e3c7, 0x001de3c7, 0x0001ebc7,\n  0x0005ebc7, 0x0009ebc7, 0x000debc7, 0x0011ebc7, 0x0015ebc7, 0x0019ebc7,\n  0x001debc7, 0x0001f3c7, 0x0005f3c7, 0x0009f3c7, 0x000df3c7, 0x0011f3c7,\n  0x0015f3c7, 0x0019f3c7, 0x001df3c7, 0x0001fbc7, 0x0005fbc7, 0x0009fbc7,\n  0x000dfbc7, 0x0011fbc7, 0x0015fbc7, 0x0019fbc7, 0x001dfbc7, 0x0001c3d7,\n  0x0005c3d7, 0x0009c3d7, 0x000dc3d7, 0x0011c3d7, 0x0015c3d7, 0x0019c3d7,\n  0x001dc3d7, 0x0001cbd7, 0x0005cbd7, 0x0009cbd7, 0x000dcbd7, 0x0011cbd7,\n  0x0015cbd7, 0x0019cbd7, 0x001dcbd7, 0x0001d3d7, 0x0005d3d7, 0x0009d3d7,\n  0x000dd3d7, 0x0011d3d7, 0x0015d3d7, 0x0019d3d7, 0x001dd3d7, 0x0001dbd7,\n  0x0005dbd7, 0x0009dbd7, 0x000ddbd7, 0x0011dbd7, 0x0015dbd7, 0x0019dbd7,\n  0x001ddbd7, 0x0001e3d7, 0x0005e3d7, 0x0009e3d7, 0x000de3d7, 0x0011e3d7,\n  0x0015e3d7, 0x0019e3d7, 0x001de3d7, 0x0001ebd7, 0x0005ebd7, 0x0009ebd7,\n  0x000debd7, 0x0011ebd7, 0x0015ebd7, 0x0019ebd7, 0x001debd7, 0x0001f3d7,\n  0x0005f3d7, 0x0009f3d7, 0x000df3d7, 0x0011f3d7, 0x0015f3d7, 0x0019f3d7,\n  0x001df3d7, 0x0001fbd7, 0x0005fbd7, 0x0009fbd7, 0x000dfbd7, 0x0011fbd7,\n  0x0015fbd7, 0x0019fbd7, 0x001dfbd7, 0x0001c3e7, 0x0005c3e7, 0x0009c3e7,\n  0x000dc3e7, 0x0011c3e7, 0x0015c3e7, 0x0019c3e7, 0x001dc3e7, 0x0001cbe7,\n  0x0005cbe7, 0x0009cbe7, 0x000dcbe7, 0x0011cbe7, 0x0015cbe7, 0x0019cbe7,\n  0x001dcbe7, 0x0001d3e7, 0x0005d3e7, 0x0009d3e7, 0x000dd3e7, 0x0011d3e7,\n  0x0015d3e7, 0x0019d3e7, 0x001dd3e7, 0x0001dbe7, 0x0005dbe7, 0x0009dbe7,\n  0x000ddbe7, 0x0011dbe7, 0x0015dbe7, 0x0019dbe7, 0x001ddbe7, 0x0001e3e7,\n  0x0005e3e7, 0x0009e3e7, 0x000de3e7, 0x0011e3e7, 0x0015e3e7, 0x0019e3e7,\n  0x001de3e7, 0x0001ebe7, 0x0005ebe7, 0x0009ebe7, 0x000debe7, 0x0011ebe7,\n  0x0015ebe7, 0x0019ebe7, 0x001debe7, 0x0001f3e7, 0x0005f3e7, 0x0009f3e7,\n  0x000df3e7, 0x0011f3e7, 0x0015f3e7, 0x0019f3e7, 0x001df3e7, 0x0001fbe7,\n  0x0005fbe7, 0x0009fbe7, 0x000dfbe7, 0x0011fbe7, 0x0015fbe7, 0x0019fbe7,\n  0x001dfbe7, 0x0001c3f7, 0x0005c3f7, 0x0009c3f7, 0x000dc3f7, 0x0011c3f7,\n  0x0015c3f7, 0x0019c3f7, 0x001dc3f7, 0x0001cbf7, 0x0005cbf7, 0x0009cbf7,\n  0x000dcbf7, 0x0011cbf7, 0x0015cbf7, 0x0019cbf7, 0x001dcbf7, 0x0001d3f7,\n  0x0005d3f7, 0x0009d3f7, 0x000dd3f7, 0x0011d3f7, 0x0015d3f7, 0x0019d3f7,\n  0x001dd3f7, 0x0001dbf7, 0x0005dbf7, 0x0009dbf7, 0x000ddbf7, 0x0011dbf7,\n  0x0015dbf7, 0x0019dbf7, 0x001ddbf7, 0x0001e3f7, 0x0005e3f7, 0x0009e3f7,\n  0x000de3f7, 0x0011e3f7, 0x0015e3f7, 0x0019e3f7, 0x001de3f7, 0x0001ebf7,\n  0x0005ebf7, 0x0009ebf7, 0x000debf7, 0x0011ebf7, 0x0015ebf7, 0x0019ebf7,\n  0x001debf7, 0x0001f3f7, 0x0005f3f7, 0x0009f3f7, 0x000df3f7, 0x0011f3f7,\n  0x0015f3f7, 0x0019f3f7, 0x001df3f7, 0x0001fbf7, 0x0005fbf7, 0x0009fbf7,\n  0x000dfbf7, 0x0011fbf7, 0x0015fbf7, 0x0019fbf7, 0x001dfbf7, 0x00e1c387,\n  0x02e1c387, 0x04e1c387, 0x06e1c387, 0x08e1c387, 0x0ae1c387, 0x0ce1c387,\n  0x0ee1c387, 0x00e5c387, 0x02e5c387, 0x04e5c387, 0x06e5c387, 0x08e5c387,\n  0x0ae5c387, 0x0ce5c387, 0x0ee5c387, 0x00e9c387, 0x02e9c387, 0x04e9c387,\n  0x06e9c387, 0x08e9c387, 0x0ae9c387, 0x0ce9c387, 0x0ee9c387, 0x00edc387,\n  0x02edc387, 0x04edc387, 0x06edc387, 0x08edc387, 0x0aedc387, 0x0cedc387,\n  0x0eedc387, 0x00f1c387, 0x02f1c387, 0x04f1c387, 0x06f1c387, 0x08f1c387,\n  0x0af1c387, 0x0cf1c387, 0x0ef1c387, 0x00f5c387, 0x02f5c387, 0x04f5c387,\n  0x06f5c387, 0x08f5c387, 0x0af5c387, 0x0cf5c387, 0x0ef5c387, 0x00f9c387,\n  0x02f9c387, 0x04f9c387, 0x06f9c387, 0x08f9c387, 0x0af9c387, 0x0cf9c387,\n  0x0ef9c387, 0x00fdc387, 0x02fdc387, 0x04fdc387, 0x06fdc387, 0x08fdc387,\n  0x0afdc387, 0x0cfdc387, 0x0efdc387, 0x00e1cb87, 0x02e1cb87, 0x04e1cb87,\n  0x06e1cb87, 0x08e1cb87, 0x0ae1cb87, 0x0ce1cb87, 0x0ee1cb87, 0x00e5cb87,\n  0x02e5cb87, 0x04e5cb87, 0x06e5cb87, 0x08e5cb87, 0x0ae5cb87, 0x0ce5cb87,\n  0x0ee5cb87, 0x00e9cb87, 0x02e9cb87, 0x04e9cb87, 0x06e9cb87, 0x08e9cb87,\n  0x0ae9cb87, 0x0ce9cb87, 0x0ee9cb87, 0x00edcb87, 0x02edcb87, 0x04edcb87,\n  0x06edcb87, 0x08edcb87, 0x0aedcb87, 0x0cedcb87, 0x0eedcb87, 0x00f1cb87,\n  0x02f1cb87, 0x04f1cb87, 0x06f1cb87, 0x08f1cb87, 0x0af1cb87, 0x0cf1cb87,\n  0x0ef1cb87, 0x00f5cb87, 0x02f5cb87, 0x04f5cb87, 0x06f5cb87, 0x08f5cb87,\n  0x0af5cb87, 0x0cf5cb87, 0x0ef5cb87, 0x00f9cb87, 0x02f9cb87, 0x04f9cb87,\n  0x06f9cb87, 0x08f9cb87,\n};\n\nstatic const uint32_t kZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = {\n   0,  4,  8,  7,  7,  7,  7,  7,  7,  7,  7, 11, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14,\n  14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21,\n  21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n  28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28,\n};\n\nstatic const uint64_t kNonZeroRepsBits[BROTLI_NUM_COMMAND_SYMBOLS] = {\n  0x0000000b, 0x0000001b, 0x0000002b, 0x0000003b, 0x000002cb, 0x000006cb,\n  0x00000acb, 0x00000ecb, 0x000002db, 0x000006db, 0x00000adb, 0x00000edb,\n  0x000002eb, 0x000006eb, 0x00000aeb, 0x00000eeb, 0x000002fb, 0x000006fb,\n  0x00000afb, 0x00000efb, 0x0000b2cb, 0x0001b2cb, 0x0002b2cb, 0x0003b2cb,\n  0x0000b6cb, 0x0001b6cb, 0x0002b6cb, 0x0003b6cb, 0x0000bacb, 0x0001bacb,\n  0x0002bacb, 0x0003bacb, 0x0000becb, 0x0001becb, 0x0002becb, 0x0003becb,\n  0x0000b2db, 0x0001b2db, 0x0002b2db, 0x0003b2db, 0x0000b6db, 0x0001b6db,\n  0x0002b6db, 0x0003b6db, 0x0000badb, 0x0001badb, 0x0002badb, 0x0003badb,\n  0x0000bedb, 0x0001bedb, 0x0002bedb, 0x0003bedb, 0x0000b2eb, 0x0001b2eb,\n  0x0002b2eb, 0x0003b2eb, 0x0000b6eb, 0x0001b6eb, 0x0002b6eb, 0x0003b6eb,\n  0x0000baeb, 0x0001baeb, 0x0002baeb, 0x0003baeb, 0x0000beeb, 0x0001beeb,\n  0x0002beeb, 0x0003beeb, 0x0000b2fb, 0x0001b2fb, 0x0002b2fb, 0x0003b2fb,\n  0x0000b6fb, 0x0001b6fb, 0x0002b6fb, 0x0003b6fb, 0x0000bafb, 0x0001bafb,\n  0x0002bafb, 0x0003bafb, 0x0000befb, 0x0001befb, 0x0002befb, 0x0003befb,\n  0x002cb2cb, 0x006cb2cb, 0x00acb2cb, 0x00ecb2cb, 0x002db2cb, 0x006db2cb,\n  0x00adb2cb, 0x00edb2cb, 0x002eb2cb, 0x006eb2cb, 0x00aeb2cb, 0x00eeb2cb,\n  0x002fb2cb, 0x006fb2cb, 0x00afb2cb, 0x00efb2cb, 0x002cb6cb, 0x006cb6cb,\n  0x00acb6cb, 0x00ecb6cb, 0x002db6cb, 0x006db6cb, 0x00adb6cb, 0x00edb6cb,\n  0x002eb6cb, 0x006eb6cb, 0x00aeb6cb, 0x00eeb6cb, 0x002fb6cb, 0x006fb6cb,\n  0x00afb6cb, 0x00efb6cb, 0x002cbacb, 0x006cbacb, 0x00acbacb, 0x00ecbacb,\n  0x002dbacb, 0x006dbacb, 0x00adbacb, 0x00edbacb, 0x002ebacb, 0x006ebacb,\n  0x00aebacb, 0x00eebacb, 0x002fbacb, 0x006fbacb, 0x00afbacb, 0x00efbacb,\n  0x002cbecb, 0x006cbecb, 0x00acbecb, 0x00ecbecb, 0x002dbecb, 0x006dbecb,\n  0x00adbecb, 0x00edbecb, 0x002ebecb, 0x006ebecb, 0x00aebecb, 0x00eebecb,\n  0x002fbecb, 0x006fbecb, 0x00afbecb, 0x00efbecb, 0x002cb2db, 0x006cb2db,\n  0x00acb2db, 0x00ecb2db, 0x002db2db, 0x006db2db, 0x00adb2db, 0x00edb2db,\n  0x002eb2db, 0x006eb2db, 0x00aeb2db, 0x00eeb2db, 0x002fb2db, 0x006fb2db,\n  0x00afb2db, 0x00efb2db, 0x002cb6db, 0x006cb6db, 0x00acb6db, 0x00ecb6db,\n  0x002db6db, 0x006db6db, 0x00adb6db, 0x00edb6db, 0x002eb6db, 0x006eb6db,\n  0x00aeb6db, 0x00eeb6db, 0x002fb6db, 0x006fb6db, 0x00afb6db, 0x00efb6db,\n  0x002cbadb, 0x006cbadb, 0x00acbadb, 0x00ecbadb, 0x002dbadb, 0x006dbadb,\n  0x00adbadb, 0x00edbadb, 0x002ebadb, 0x006ebadb, 0x00aebadb, 0x00eebadb,\n  0x002fbadb, 0x006fbadb, 0x00afbadb, 0x00efbadb, 0x002cbedb, 0x006cbedb,\n  0x00acbedb, 0x00ecbedb, 0x002dbedb, 0x006dbedb, 0x00adbedb, 0x00edbedb,\n  0x002ebedb, 0x006ebedb, 0x00aebedb, 0x00eebedb, 0x002fbedb, 0x006fbedb,\n  0x00afbedb, 0x00efbedb, 0x002cb2eb, 0x006cb2eb, 0x00acb2eb, 0x00ecb2eb,\n  0x002db2eb, 0x006db2eb, 0x00adb2eb, 0x00edb2eb, 0x002eb2eb, 0x006eb2eb,\n  0x00aeb2eb, 0x00eeb2eb, 0x002fb2eb, 0x006fb2eb, 0x00afb2eb, 0x00efb2eb,\n  0x002cb6eb, 0x006cb6eb, 0x00acb6eb, 0x00ecb6eb, 0x002db6eb, 0x006db6eb,\n  0x00adb6eb, 0x00edb6eb, 0x002eb6eb, 0x006eb6eb, 0x00aeb6eb, 0x00eeb6eb,\n  0x002fb6eb, 0x006fb6eb, 0x00afb6eb, 0x00efb6eb, 0x002cbaeb, 0x006cbaeb,\n  0x00acbaeb, 0x00ecbaeb, 0x002dbaeb, 0x006dbaeb, 0x00adbaeb, 0x00edbaeb,\n  0x002ebaeb, 0x006ebaeb, 0x00aebaeb, 0x00eebaeb, 0x002fbaeb, 0x006fbaeb,\n  0x00afbaeb, 0x00efbaeb, 0x002cbeeb, 0x006cbeeb, 0x00acbeeb, 0x00ecbeeb,\n  0x002dbeeb, 0x006dbeeb, 0x00adbeeb, 0x00edbeeb, 0x002ebeeb, 0x006ebeeb,\n  0x00aebeeb, 0x00eebeeb, 0x002fbeeb, 0x006fbeeb, 0x00afbeeb, 0x00efbeeb,\n  0x002cb2fb, 0x006cb2fb, 0x00acb2fb, 0x00ecb2fb, 0x002db2fb, 0x006db2fb,\n  0x00adb2fb, 0x00edb2fb, 0x002eb2fb, 0x006eb2fb, 0x00aeb2fb, 0x00eeb2fb,\n  0x002fb2fb, 0x006fb2fb, 0x00afb2fb, 0x00efb2fb, 0x002cb6fb, 0x006cb6fb,\n  0x00acb6fb, 0x00ecb6fb, 0x002db6fb, 0x006db6fb, 0x00adb6fb, 0x00edb6fb,\n  0x002eb6fb, 0x006eb6fb, 0x00aeb6fb, 0x00eeb6fb, 0x002fb6fb, 0x006fb6fb,\n  0x00afb6fb, 0x00efb6fb, 0x002cbafb, 0x006cbafb, 0x00acbafb, 0x00ecbafb,\n  0x002dbafb, 0x006dbafb, 0x00adbafb, 0x00edbafb, 0x002ebafb, 0x006ebafb,\n  0x00aebafb, 0x00eebafb, 0x002fbafb, 0x006fbafb, 0x00afbafb, 0x00efbafb,\n  0x002cbefb, 0x006cbefb, 0x00acbefb, 0x00ecbefb, 0x002dbefb, 0x006dbefb,\n  0x00adbefb, 0x00edbefb, 0x002ebefb, 0x006ebefb, 0x00aebefb, 0x00eebefb,\n  0x002fbefb, 0x006fbefb, 0x00afbefb, 0x00efbefb, 0x0b2cb2cb, 0x1b2cb2cb,\n  0x2b2cb2cb, 0x3b2cb2cb, 0x0b6cb2cb, 0x1b6cb2cb, 0x2b6cb2cb, 0x3b6cb2cb,\n  0x0bacb2cb, 0x1bacb2cb, 0x2bacb2cb, 0x3bacb2cb, 0x0becb2cb, 0x1becb2cb,\n  0x2becb2cb, 0x3becb2cb, 0x0b2db2cb, 0x1b2db2cb, 0x2b2db2cb, 0x3b2db2cb,\n  0x0b6db2cb, 0x1b6db2cb, 0x2b6db2cb, 0x3b6db2cb, 0x0badb2cb, 0x1badb2cb,\n  0x2badb2cb, 0x3badb2cb, 0x0bedb2cb, 0x1bedb2cb, 0x2bedb2cb, 0x3bedb2cb,\n  0x0b2eb2cb, 0x1b2eb2cb, 0x2b2eb2cb, 0x3b2eb2cb, 0x0b6eb2cb, 0x1b6eb2cb,\n  0x2b6eb2cb, 0x3b6eb2cb, 0x0baeb2cb, 0x1baeb2cb, 0x2baeb2cb, 0x3baeb2cb,\n  0x0beeb2cb, 0x1beeb2cb, 0x2beeb2cb, 0x3beeb2cb, 0x0b2fb2cb, 0x1b2fb2cb,\n  0x2b2fb2cb, 0x3b2fb2cb, 0x0b6fb2cb, 0x1b6fb2cb, 0x2b6fb2cb, 0x3b6fb2cb,\n  0x0bafb2cb, 0x1bafb2cb, 0x2bafb2cb, 0x3bafb2cb, 0x0befb2cb, 0x1befb2cb,\n  0x2befb2cb, 0x3befb2cb, 0x0b2cb6cb, 0x1b2cb6cb, 0x2b2cb6cb, 0x3b2cb6cb,\n  0x0b6cb6cb, 0x1b6cb6cb, 0x2b6cb6cb, 0x3b6cb6cb, 0x0bacb6cb, 0x1bacb6cb,\n  0x2bacb6cb, 0x3bacb6cb, 0x0becb6cb, 0x1becb6cb, 0x2becb6cb, 0x3becb6cb,\n  0x0b2db6cb, 0x1b2db6cb, 0x2b2db6cb, 0x3b2db6cb, 0x0b6db6cb, 0x1b6db6cb,\n  0x2b6db6cb, 0x3b6db6cb, 0x0badb6cb, 0x1badb6cb, 0x2badb6cb, 0x3badb6cb,\n  0x0bedb6cb, 0x1bedb6cb, 0x2bedb6cb, 0x3bedb6cb, 0x0b2eb6cb, 0x1b2eb6cb,\n  0x2b2eb6cb, 0x3b2eb6cb, 0x0b6eb6cb, 0x1b6eb6cb, 0x2b6eb6cb, 0x3b6eb6cb,\n  0x0baeb6cb, 0x1baeb6cb, 0x2baeb6cb, 0x3baeb6cb, 0x0beeb6cb, 0x1beeb6cb,\n  0x2beeb6cb, 0x3beeb6cb, 0x0b2fb6cb, 0x1b2fb6cb, 0x2b2fb6cb, 0x3b2fb6cb,\n  0x0b6fb6cb, 0x1b6fb6cb, 0x2b6fb6cb, 0x3b6fb6cb, 0x0bafb6cb, 0x1bafb6cb,\n  0x2bafb6cb, 0x3bafb6cb, 0x0befb6cb, 0x1befb6cb, 0x2befb6cb, 0x3befb6cb,\n  0x0b2cbacb, 0x1b2cbacb, 0x2b2cbacb, 0x3b2cbacb, 0x0b6cbacb, 0x1b6cbacb,\n  0x2b6cbacb, 0x3b6cbacb, 0x0bacbacb, 0x1bacbacb, 0x2bacbacb, 0x3bacbacb,\n  0x0becbacb, 0x1becbacb, 0x2becbacb, 0x3becbacb, 0x0b2dbacb, 0x1b2dbacb,\n  0x2b2dbacb, 0x3b2dbacb, 0x0b6dbacb, 0x1b6dbacb, 0x2b6dbacb, 0x3b6dbacb,\n  0x0badbacb, 0x1badbacb, 0x2badbacb, 0x3badbacb, 0x0bedbacb, 0x1bedbacb,\n  0x2bedbacb, 0x3bedbacb, 0x0b2ebacb, 0x1b2ebacb, 0x2b2ebacb, 0x3b2ebacb,\n  0x0b6ebacb, 0x1b6ebacb, 0x2b6ebacb, 0x3b6ebacb, 0x0baebacb, 0x1baebacb,\n  0x2baebacb, 0x3baebacb, 0x0beebacb, 0x1beebacb, 0x2beebacb, 0x3beebacb,\n  0x0b2fbacb, 0x1b2fbacb, 0x2b2fbacb, 0x3b2fbacb, 0x0b6fbacb, 0x1b6fbacb,\n  0x2b6fbacb, 0x3b6fbacb, 0x0bafbacb, 0x1bafbacb, 0x2bafbacb, 0x3bafbacb,\n  0x0befbacb, 0x1befbacb, 0x2befbacb, 0x3befbacb, 0x0b2cbecb, 0x1b2cbecb,\n  0x2b2cbecb, 0x3b2cbecb, 0x0b6cbecb, 0x1b6cbecb, 0x2b6cbecb, 0x3b6cbecb,\n  0x0bacbecb, 0x1bacbecb, 0x2bacbecb, 0x3bacbecb, 0x0becbecb, 0x1becbecb,\n  0x2becbecb, 0x3becbecb, 0x0b2dbecb, 0x1b2dbecb, 0x2b2dbecb, 0x3b2dbecb,\n  0x0b6dbecb, 0x1b6dbecb, 0x2b6dbecb, 0x3b6dbecb, 0x0badbecb, 0x1badbecb,\n  0x2badbecb, 0x3badbecb, 0x0bedbecb, 0x1bedbecb, 0x2bedbecb, 0x3bedbecb,\n  0x0b2ebecb, 0x1b2ebecb, 0x2b2ebecb, 0x3b2ebecb, 0x0b6ebecb, 0x1b6ebecb,\n  0x2b6ebecb, 0x3b6ebecb, 0x0baebecb, 0x1baebecb, 0x2baebecb, 0x3baebecb,\n  0x0beebecb, 0x1beebecb, 0x2beebecb, 0x3beebecb, 0x0b2fbecb, 0x1b2fbecb,\n  0x2b2fbecb, 0x3b2fbecb, 0x0b6fbecb, 0x1b6fbecb, 0x2b6fbecb, 0x3b6fbecb,\n  0x0bafbecb, 0x1bafbecb, 0x2bafbecb, 0x3bafbecb, 0x0befbecb, 0x1befbecb,\n  0x2befbecb, 0x3befbecb, 0x0b2cb2db, 0x1b2cb2db, 0x2b2cb2db, 0x3b2cb2db,\n  0x0b6cb2db, 0x1b6cb2db, 0x2b6cb2db, 0x3b6cb2db, 0x0bacb2db, 0x1bacb2db,\n  0x2bacb2db, 0x3bacb2db, 0x0becb2db, 0x1becb2db, 0x2becb2db, 0x3becb2db,\n  0x0b2db2db, 0x1b2db2db, 0x2b2db2db, 0x3b2db2db, 0x0b6db2db, 0x1b6db2db,\n  0x2b6db2db, 0x3b6db2db, 0x0badb2db, 0x1badb2db, 0x2badb2db, 0x3badb2db,\n  0x0bedb2db, 0x1bedb2db, 0x2bedb2db, 0x3bedb2db, 0x0b2eb2db, 0x1b2eb2db,\n  0x2b2eb2db, 0x3b2eb2db, 0x0b6eb2db, 0x1b6eb2db, 0x2b6eb2db, 0x3b6eb2db,\n  0x0baeb2db, 0x1baeb2db, 0x2baeb2db, 0x3baeb2db, 0x0beeb2db, 0x1beeb2db,\n  0x2beeb2db, 0x3beeb2db, 0x0b2fb2db, 0x1b2fb2db, 0x2b2fb2db, 0x3b2fb2db,\n  0x0b6fb2db, 0x1b6fb2db, 0x2b6fb2db, 0x3b6fb2db, 0x0bafb2db, 0x1bafb2db,\n  0x2bafb2db, 0x3bafb2db, 0x0befb2db, 0x1befb2db, 0x2befb2db, 0x3befb2db,\n  0x0b2cb6db, 0x1b2cb6db, 0x2b2cb6db, 0x3b2cb6db, 0x0b6cb6db, 0x1b6cb6db,\n  0x2b6cb6db, 0x3b6cb6db, 0x0bacb6db, 0x1bacb6db, 0x2bacb6db, 0x3bacb6db,\n  0x0becb6db, 0x1becb6db, 0x2becb6db, 0x3becb6db, 0x0b2db6db, 0x1b2db6db,\n  0x2b2db6db, 0x3b2db6db, 0x0b6db6db, 0x1b6db6db, 0x2b6db6db, 0x3b6db6db,\n  0x0badb6db, 0x1badb6db, 0x2badb6db, 0x3badb6db, 0x0bedb6db, 0x1bedb6db,\n  0x2bedb6db, 0x3bedb6db, 0x0b2eb6db, 0x1b2eb6db, 0x2b2eb6db, 0x3b2eb6db,\n  0x0b6eb6db, 0x1b6eb6db, 0x2b6eb6db, 0x3b6eb6db, 0x0baeb6db, 0x1baeb6db,\n  0x2baeb6db, 0x3baeb6db,\n};\n\nstatic const uint32_t kNonZeroRepsDepth[BROTLI_NUM_COMMAND_SYMBOLS] = {\n   6,  6,  6,  6, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12,\n  12, 12, 12, 12, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18,\n  18, 18, 18, 18, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24,\n  24, 24, 24, 24, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30,\n};\n\nstatic const uint16_t kStaticCommandCodeBits[BROTLI_NUM_COMMAND_SYMBOLS] = {\n    0,  256,  128,  384,   64,  320,  192,  448,\n   32,  288,  160,  416,   96,  352,  224,  480,\n   16,  272,  144,  400,   80,  336,  208,  464,\n   48,  304,  176,  432,  112,  368,  240,  496,\n    8,  264,  136,  392,   72,  328,  200,  456,\n   40,  296,  168,  424,  104,  360,  232,  488,\n   24,  280,  152,  408,   88,  344,  216,  472,\n   56,  312,  184,  440,  120,  376,  248,  504,\n    4,  260,  132,  388,   68,  324,  196,  452,\n   36,  292,  164,  420,  100,  356,  228,  484,\n   20,  276,  148,  404,   84,  340,  212,  468,\n   52,  308,  180,  436,  116,  372,  244,  500,\n   12,  268,  140,  396,   76,  332,  204,  460,\n   44,  300,  172,  428,  108,  364,  236,  492,\n   28,  284,  156,  412,   92,  348,  220,  476,\n   60,  316,  188,  444,  124,  380,  252,  508,\n    2,  258,  130,  386,   66,  322,  194,  450,\n   34,  290,  162,  418,   98,  354,  226,  482,\n   18,  274,  146,  402,   82,  338,  210,  466,\n   50,  306,  178,  434,  114,  370,  242,  498,\n   10,  266,  138,  394,   74,  330,  202,  458,\n   42,  298,  170,  426,  106,  362,  234,  490,\n   26,  282,  154,  410,   90,  346,  218,  474,\n   58,  314,  186,  442,  122,  378,  250,  506,\n    6,  262,  134,  390,   70,  326,  198,  454,\n   38,  294,  166,  422,  102,  358,  230,  486,\n   22,  278,  150,  406,   86,  342,  214,  470,\n   54,  310,  182,  438,  118,  374,  246,  502,\n   14,  270,  142,  398,   78,  334,  206,  462,\n   46,  302,  174,  430,  110,  366,  238,  494,\n   30,  286,  158,  414,   94,  350,  222,  478,\n   62,  318,  190,  446,  126,  382,  254,  510,\n    1,  257,  129,  385,   65,  321,  193,  449,\n   33,  289,  161,  417,   97,  353,  225,  481,\n   17,  273,  145,  401,   81,  337,  209,  465,\n   49,  305,  177,  433,  113,  369,  241,  497,\n    9,  265,  137,  393,   73,  329,  201,  457,\n   41,  297,  169,  425,  105,  361,  233,  489,\n   25,  281,  153,  409,   89,  345,  217,  473,\n   57,  313,  185,  441,  121,  377,  249,  505,\n    5,  261,  133,  389,   69,  325,  197,  453,\n   37,  293,  165,  421,  101,  357,  229,  485,\n   21,  277,  149,  405,   85,  341,  213,  469,\n   53,  309,  181,  437,  117,  373,  245,  501,\n   13,  269,  141,  397,   77,  333,  205,  461,\n   45,  301,  173,  429,  109,  365,  237,  493,\n   29,  285,  157,  413,   93,  349,  221,  477,\n   61,  317,  189,  445,  125,  381,  253,  509,\n    3,  259,  131,  387,   67,  323,  195,  451,\n   35,  291,  163,  419,   99,  355,  227,  483,\n   19,  275,  147,  403,   83,  339,  211,  467,\n   51,  307,  179,  435,  115,  371,  243,  499,\n   11,  267,  139,  395,   75,  331,  203,  459,\n   43,  299,  171,  427,  107,  363,  235,  491,\n   27,  283,  155,  411,   91,  347,  219,  475,\n   59,  315,  187,  443,  123,  379,  251,  507,\n    7, 1031,  519, 1543,  263, 1287,  775, 1799,\n  135, 1159,  647, 1671,  391, 1415,  903, 1927,\n   71, 1095,  583, 1607,  327, 1351,  839, 1863,\n  199, 1223,  711, 1735,  455, 1479,  967, 1991,\n   39, 1063,  551, 1575,  295, 1319,  807, 1831,\n  167, 1191,  679, 1703,  423, 1447,  935, 1959,\n  103, 1127,  615, 1639,  359, 1383,  871, 1895,\n  231, 1255,  743, 1767,  487, 1511,  999, 2023,\n   23, 1047,  535, 1559,  279, 1303,  791, 1815,\n  151, 1175,  663, 1687,  407, 1431,  919, 1943,\n   87, 1111,  599, 1623,  343, 1367,  855, 1879,\n  215, 1239,  727, 1751,  471, 1495,  983, 2007,\n   55, 1079,  567, 1591,  311, 1335,  823, 1847,\n  183, 1207,  695, 1719,  439, 1463,  951, 1975,\n  119, 1143,  631, 1655,  375, 1399,  887, 1911,\n  247, 1271,  759, 1783,  503, 1527, 1015, 2039,\n   15, 1039,  527, 1551,  271, 1295,  783, 1807,\n  143, 1167,  655, 1679,  399, 1423,  911, 1935,\n   79, 1103,  591, 1615,  335, 1359,  847, 1871,\n  207, 1231,  719, 1743,  463, 1487,  975, 1999,\n   47, 1071,  559, 1583,  303, 1327,  815, 1839,\n  175, 1199,  687, 1711,  431, 1455,  943, 1967,\n  111, 1135,  623, 1647,  367, 1391,  879, 1903,\n  239, 1263,  751, 1775,  495, 1519, 1007, 2031,\n   31, 1055,  543, 1567,  287, 1311,  799, 1823,\n  159, 1183,  671, 1695,  415, 1439,  927, 1951,\n   95, 1119,  607, 1631,  351, 1375,  863, 1887,\n  223, 1247,  735, 1759,  479, 1503,  991, 2015,\n   63, 1087,  575, 1599,  319, 1343,  831, 1855,\n  191, 1215,  703, 1727,  447, 1471,  959, 1983,\n  127, 1151,  639, 1663,  383, 1407,  895, 1919,\n  255, 1279,  767, 1791,  511, 1535, 1023, 2047,\n};\n\nstatic BROTLI_INLINE void StoreStaticCommandHuffmanTree(\n    size_t* storage_ix, uint8_t* storage) {\n  BrotliWriteBits(\n      56, BROTLI_MAKE_UINT64_T(0x926244U, 0x16307003U), storage_ix, storage);\n  BrotliWriteBits(3, 0x00000000U, storage_ix, storage);\n}\n\nstatic const uint16_t kStaticDistanceCodeBits[64] = {\n   0, 32, 16, 48,  8, 40, 24, 56,  4, 36, 20, 52, 12, 44, 28, 60,\n   2, 34, 18, 50, 10, 42, 26, 58,  6, 38, 22, 54, 14, 46, 30, 62,\n   1, 33, 17, 49,  9, 41, 25, 57,  5, 37, 21, 53, 13, 45, 29, 61,\n   3, 35, 19, 51, 11, 43, 27, 59,  7, 39, 23, 55, 15, 47, 31, 63,\n};\n\nstatic BROTLI_INLINE void StoreStaticDistanceHuffmanTree(\n    size_t* storage_ix, uint8_t* storage) {\n  BrotliWriteBits(28, 0x0369DC03u, storage_ix, storage);\n}\n/* GENERATED CODE END */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENTROPY_ENCODE_STATIC_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/fast_log.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"fast_log.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* \", \".join([\"%.16ff\" % x for x in [0.0]+[log2(x) for x in range(1, 256)]]) */\nconst double kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE] = {\n  0.0000000000000000f, 0.0000000000000000f, 1.0000000000000000f,\n  1.5849625007211563f, 2.0000000000000000f, 2.3219280948873622f,\n  2.5849625007211561f, 2.8073549220576042f, 3.0000000000000000f,\n  3.1699250014423126f, 3.3219280948873626f, 3.4594316186372978f,\n  3.5849625007211565f, 3.7004397181410922f, 3.8073549220576037f,\n  3.9068905956085187f, 4.0000000000000000f, 4.0874628412503400f,\n  4.1699250014423122f, 4.2479275134435852f, 4.3219280948873626f,\n  4.3923174227787607f, 4.4594316186372973f, 4.5235619560570131f,\n  4.5849625007211570f, 4.6438561897747244f, 4.7004397181410926f,\n  4.7548875021634691f, 4.8073549220576037f, 4.8579809951275728f,\n  4.9068905956085187f, 4.9541963103868758f, 5.0000000000000000f,\n  5.0443941193584534f, 5.0874628412503400f, 5.1292830169449664f,\n  5.1699250014423122f, 5.2094533656289501f, 5.2479275134435852f,\n  5.2854022188622487f, 5.3219280948873626f, 5.3575520046180838f,\n  5.3923174227787607f, 5.4262647547020979f, 5.4594316186372973f,\n  5.4918530963296748f, 5.5235619560570131f, 5.5545888516776376f,\n  5.5849625007211570f, 5.6147098441152083f, 5.6438561897747244f,\n  5.6724253419714961f, 5.7004397181410926f, 5.7279204545631996f,\n  5.7548875021634691f, 5.7813597135246599f, 5.8073549220576046f,\n  5.8328900141647422f, 5.8579809951275719f, 5.8826430493618416f,\n  5.9068905956085187f, 5.9307373375628867f, 5.9541963103868758f,\n  5.9772799234999168f, 6.0000000000000000f, 6.0223678130284544f,\n  6.0443941193584534f, 6.0660891904577721f, 6.0874628412503400f,\n  6.1085244567781700f, 6.1292830169449672f, 6.1497471195046822f,\n  6.1699250014423122f, 6.1898245588800176f, 6.2094533656289510f,\n  6.2288186904958804f, 6.2479275134435861f, 6.2667865406949019f,\n  6.2854022188622487f, 6.3037807481771031f, 6.3219280948873617f,\n  6.3398500028846252f, 6.3575520046180847f, 6.3750394313469254f,\n  6.3923174227787598f, 6.4093909361377026f, 6.4262647547020979f,\n  6.4429434958487288f, 6.4594316186372982f, 6.4757334309663976f,\n  6.4918530963296748f, 6.5077946401986964f, 6.5235619560570131f,\n  6.5391588111080319f, 6.5545888516776376f, 6.5698556083309478f,\n  6.5849625007211561f, 6.5999128421871278f, 6.6147098441152092f,\n  6.6293566200796095f, 6.6438561897747253f, 6.6582114827517955f,\n  6.6724253419714952f, 6.6865005271832185f, 6.7004397181410917f,\n  6.7142455176661224f, 6.7279204545631988f, 6.7414669864011465f,\n  6.7548875021634691f, 6.7681843247769260f, 6.7813597135246599f,\n  6.7944158663501062f, 6.8073549220576037f, 6.8201789624151887f,\n  6.8328900141647422f, 6.8454900509443757f, 6.8579809951275719f,\n  6.8703647195834048f, 6.8826430493618416f, 6.8948177633079437f,\n  6.9068905956085187f, 6.9188632372745955f, 6.9307373375628867f,\n  6.9425145053392399f, 6.9541963103868758f, 6.9657842846620879f,\n  6.9772799234999168f, 6.9886846867721664f, 7.0000000000000000f,\n  7.0112272554232540f, 7.0223678130284544f, 7.0334230015374501f,\n  7.0443941193584534f, 7.0552824355011898f, 7.0660891904577721f,\n  7.0768155970508317f, 7.0874628412503400f, 7.0980320829605272f,\n  7.1085244567781700f, 7.1189410727235076f, 7.1292830169449664f,\n  7.1395513523987937f, 7.1497471195046822f, 7.1598713367783891f,\n  7.1699250014423130f, 7.1799090900149345f, 7.1898245588800176f,\n  7.1996723448363644f, 7.2094533656289492f, 7.2191685204621621f,\n  7.2288186904958804f, 7.2384047393250794f, 7.2479275134435861f,\n  7.2573878426926521f, 7.2667865406949019f, 7.2761244052742384f,\n  7.2854022188622487f, 7.2946207488916270f, 7.3037807481771031f,\n  7.3128829552843557f, 7.3219280948873617f, 7.3309168781146177f,\n  7.3398500028846243f, 7.3487281542310781f, 7.3575520046180847f,\n  7.3663222142458151f, 7.3750394313469254f, 7.3837042924740528f,\n  7.3923174227787607f, 7.4008794362821844f, 7.4093909361377026f,\n  7.4178525148858991f, 7.4262647547020979f, 7.4346282276367255f,\n  7.4429434958487288f, 7.4512111118323299f, 7.4594316186372973f,\n  7.4676055500829976f, 7.4757334309663976f, 7.4838157772642564f,\n  7.4918530963296748f, 7.4998458870832057f, 7.5077946401986964f,\n  7.5156998382840436f, 7.5235619560570131f, 7.5313814605163119f,\n  7.5391588111080319f, 7.5468944598876373f, 7.5545888516776376f,\n  7.5622424242210728f, 7.5698556083309478f, 7.5774288280357487f,\n  7.5849625007211561f, 7.5924570372680806f, 7.5999128421871278f,\n  7.6073303137496113f, 7.6147098441152075f, 7.6220518194563764f,\n  7.6293566200796095f, 7.6366246205436488f, 7.6438561897747244f,\n  7.6510516911789290f, 7.6582114827517955f, 7.6653359171851765f,\n  7.6724253419714952f, 7.6794800995054464f, 7.6865005271832185f,\n  7.6934869574993252f, 7.7004397181410926f, 7.7073591320808825f,\n  7.7142455176661224f, 7.7210991887071856f, 7.7279204545631996f,\n  7.7347096202258392f, 7.7414669864011465f, 7.7481928495894596f,\n  7.7548875021634691f, 7.7615512324444795f, 7.7681843247769260f,\n  7.7747870596011737f, 7.7813597135246608f, 7.7879025593914317f,\n  7.7944158663501062f, 7.8008998999203047f, 7.8073549220576037f,\n  7.8137811912170374f, 7.8201789624151887f, 7.8265484872909159f,\n  7.8328900141647422f, 7.8392037880969445f, 7.8454900509443757f,\n  7.8517490414160571f, 7.8579809951275719f, 7.8641861446542798f,\n  7.8703647195834048f, 7.8765169465650002f, 7.8826430493618425f,\n  7.8887432488982601f, 7.8948177633079446f, 7.9008668079807496f,\n  7.9068905956085187f, 7.9128893362299619f, 7.9188632372745955f,\n  7.9248125036057813f, 7.9307373375628867f, 7.9366379390025719f,\n  7.9425145053392399f, 7.9483672315846778f, 7.9541963103868758f,\n  7.9600019320680806f, 7.9657842846620870f, 7.9715435539507720f,\n  7.9772799234999168f, 7.9829935746943104f, 7.9886846867721664f,\n  7.9943534368588578f\n};\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/fast_log.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Utilities for fast computation of logarithms. */\n\n#ifndef BROTLI_ENC_FAST_LOG_H_\n#define BROTLI_ENC_FAST_LOG_H_\n\n#include <math.h>\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE uint32_t Log2FloorNonZero(size_t n) {\n#if defined(BROTLI_BSR32)\n  return BROTLI_BSR32((uint32_t)n);\n#else\n  uint32_t result = 0;\n  while (n >>= 1) result++;\n  return result;\n#endif\n}\n\n#define BROTLI_LOG2_TABLE_SIZE 256\n\n/* A lookup table for small values of log2(int) to be used in entropy\n   computation. */\nBROTLI_INTERNAL extern const double kBrotliLog2Table[BROTLI_LOG2_TABLE_SIZE];\n\n/* Visual Studio 2012 and Android API levels < 18 do not have the log2()\n * function defined, so we use log() and a multiplication instead. */\n#if !defined(BROTLI_HAVE_LOG2)\n#if ((defined(_MSC_VER) && _MSC_VER <= 1700) || \\\n     (defined(__ANDROID_API__) && __ANDROID_API__ < 18))\n#define BROTLI_HAVE_LOG2 0\n#else\n#define BROTLI_HAVE_LOG2 1\n#endif\n#endif\n\n#define LOG_2_INV 1.4426950408889634\n\n/* Faster logarithm for small integers, with the property of log2(0) == 0. */\nstatic BROTLI_INLINE double FastLog2(size_t v) {\n  if (v < BROTLI_LOG2_TABLE_SIZE) {\n    return kBrotliLog2Table[v];\n  }\n#if !(BROTLI_HAVE_LOG2)\n  return log((double)v) * LOG_2_INV;\n#else\n  return log2((double)v);\n#endif\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_FAST_LOG_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/find_match_length.h",
    "content": "/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Function to find maximal matching prefixes of strings. */\n\n#ifndef BROTLI_ENC_FIND_MATCH_LENGTH_H_\n#define BROTLI_ENC_FIND_MATCH_LENGTH_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Separate implementation for little-endian 64-bit targets, for speed. */\n#if defined(BROTLI_TZCNT64) && BROTLI_64_BITS && BROTLI_LITTLE_ENDIAN\nstatic BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,\n                                                     const uint8_t* s2,\n                                                     size_t limit) {\n  const uint8_t *s1_orig = s1;\n  for (; limit >= 8; limit -= 8) {\n    uint64_t x = BROTLI_UNALIGNED_LOAD64LE(s2) ^\n                 BROTLI_UNALIGNED_LOAD64LE(s1);\n    s2 += 8;\n    if (x != 0) {\n      size_t matching_bits = (size_t)BROTLI_TZCNT64(x);\n      return (size_t)(s1 - s1_orig) + (matching_bits >> 3);\n    }\n    s1 += 8;\n  }\n  while (limit && *s1 == *s2) {\n    limit--;\n    ++s2;\n    ++s1;\n  }\n  return (size_t)(s1 - s1_orig);\n}\n#else\nstatic BROTLI_INLINE size_t FindMatchLengthWithLimit(const uint8_t* s1,\n                                                     const uint8_t* s2,\n                                                     size_t limit) {\n  size_t matched = 0;\n  const uint8_t* s2_limit = s2 + limit;\n  const uint8_t* s2_ptr = s2;\n  /* Find out how long the match is. We loop over the data 32 bits at a\n     time until we find a 32-bit block that doesn't match; then we find\n     the first non-matching bit and use that to calculate the total\n     length of the match. */\n  while (s2_ptr <= s2_limit - 4 &&\n         BrotliUnalignedRead32(s2_ptr) ==\n         BrotliUnalignedRead32(s1 + matched)) {\n    s2_ptr += 4;\n    matched += 4;\n  }\n  while ((s2_ptr < s2_limit) && (s1[matched] == *s2_ptr)) {\n    ++s2_ptr;\n    ++matched;\n  }\n  return matched;\n}\n#endif\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_FIND_MATCH_LENGTH_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/hash.h",
    "content": "/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data. */\n\n#ifndef BROTLI_ENC_HASH_H_\n#define BROTLI_ENC_HASH_H_\n\n#include <stdlib.h>  /* exit */\n#include <string.h>  /* memcmp, memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"compound_dictionary.h\"\n#include \"encoder_dict.h\"\n#include \"fast_log.h\"\n#include \"find_match_length.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n#include \"static_dict.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct {\n  /**\n   * Dynamically allocated areas; regular hasher uses one or two allocations;\n   * \"composite\" hasher uses up to 4 allocations.\n   */\n  void* extra[4];\n\n  /**\n   * False before the fisrt invocation of HasherSetup (where \"extra\" memory)\n   * is allocated.\n   */\n  BROTLI_BOOL is_setup_;\n\n  size_t dict_num_lookups;\n  size_t dict_num_matches;\n\n  BrotliHasherParams params;\n\n  /**\n   * False if hasher needs to be \"prepared\" before use (before the first\n   * invocation of HasherSetup or after HasherReset). \"preparation\" is hasher\n   * data initialization (using input ringbuffer).\n   */\n  BROTLI_BOOL is_prepared_;\n} HasherCommon;\n\n#define score_t size_t\n\nstatic const uint32_t kCutoffTransformsCount = 10;\n/*   0,  12,   27,    23,    42,    63,    56,    48,    59,    64 */\n/* 0+0, 4+8, 8+19, 12+11, 16+26, 20+43, 24+32, 28+20, 32+27, 36+28 */\nstatic const uint64_t kCutoffTransforms =\n    BROTLI_MAKE_UINT64_T(0x071B520A, 0xDA2D3200);\n\ntypedef struct HasherSearchResult {\n  size_t len;\n  size_t distance;\n  score_t score;\n  int len_code_delta; /* == len_code - len */\n} HasherSearchResult;\n\n/* kHashMul32 multiplier has these properties:\n   * The multiplier must be odd. Otherwise we may lose the highest bit.\n   * No long streaks of ones or zeros.\n   * There is no effort to ensure that it is a prime, the oddity is enough\n     for this use.\n   * The number has been tuned heuristically against compression benchmarks. */\nstatic const uint32_t kHashMul32 = 0x1E35A7BD;\nstatic const uint64_t kHashMul64 =\n    BROTLI_MAKE_UINT64_T(0x1FE35A7Bu, 0xD3579BD3u);\n\nstatic BROTLI_INLINE uint32_t Hash14(const uint8_t* data) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - 14);\n}\n\nstatic BROTLI_INLINE void PrepareDistanceCache(\n    int* BROTLI_RESTRICT distance_cache, const int num_distances) {\n  if (num_distances > 4) {\n    int last_distance = distance_cache[0];\n    distance_cache[4] = last_distance - 1;\n    distance_cache[5] = last_distance + 1;\n    distance_cache[6] = last_distance - 2;\n    distance_cache[7] = last_distance + 2;\n    distance_cache[8] = last_distance - 3;\n    distance_cache[9] = last_distance + 3;\n    if (num_distances > 10) {\n      int next_last_distance = distance_cache[1];\n      distance_cache[10] = next_last_distance - 1;\n      distance_cache[11] = next_last_distance + 1;\n      distance_cache[12] = next_last_distance - 2;\n      distance_cache[13] = next_last_distance + 2;\n      distance_cache[14] = next_last_distance - 3;\n      distance_cache[15] = next_last_distance + 3;\n    }\n  }\n}\n\n#define BROTLI_LITERAL_BYTE_SCORE 135\n#define BROTLI_DISTANCE_BIT_PENALTY 30\n/* Score must be positive after applying maximal penalty. */\n#define BROTLI_SCORE_BASE (BROTLI_DISTANCE_BIT_PENALTY * 8 * sizeof(size_t))\n\n/* Usually, we always choose the longest backward reference. This function\n   allows for the exception of that rule.\n\n   If we choose a backward reference that is further away, it will\n   usually be coded with more bits. We approximate this by assuming\n   log2(distance). If the distance can be expressed in terms of the\n   last four distances, we use some heuristic constants to estimate\n   the bits cost. For the first up to four literals we use the bit\n   cost of the literals from the literal cost model, after that we\n   use the average bit cost of the cost model.\n\n   This function is used to sometimes discard a longer backward reference\n   when it is not much longer and the bit cost for encoding it is more\n   than the saved literals.\n\n   backward_reference_offset MUST be positive. */\nstatic BROTLI_INLINE score_t BackwardReferenceScore(\n    size_t copy_length, size_t backward_reference_offset) {\n  return BROTLI_SCORE_BASE + BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length -\n      BROTLI_DISTANCE_BIT_PENALTY * Log2FloorNonZero(backward_reference_offset);\n}\n\nstatic BROTLI_INLINE score_t BackwardReferenceScoreUsingLastDistance(\n    size_t copy_length) {\n  return BROTLI_LITERAL_BYTE_SCORE * (score_t)copy_length +\n      BROTLI_SCORE_BASE + 15;\n}\n\nstatic BROTLI_INLINE score_t BackwardReferencePenaltyUsingLastDistance(\n    size_t distance_short_code) {\n  return (score_t)39 + ((0x1CA10 >> (distance_short_code & 0xE)) & 0xE);\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL TestStaticDictionaryItem(\n    const BrotliEncoderDictionary* dictionary, size_t len, size_t word_idx,\n    const uint8_t* data, size_t max_length, size_t max_backward,\n    size_t max_distance, HasherSearchResult* out) {\n  size_t offset;\n  size_t matchlen;\n  size_t backward;\n  score_t score;\n  offset = dictionary->words->offsets_by_length[len] + len * word_idx;\n  if (len > max_length) {\n    return BROTLI_FALSE;\n  }\n\n  matchlen =\n      FindMatchLengthWithLimit(data, &dictionary->words->data[offset], len);\n  if (matchlen + dictionary->cutoffTransformsCount <= len || matchlen == 0) {\n    return BROTLI_FALSE;\n  }\n  {\n    size_t cut = len - matchlen;\n    size_t transform_id = (cut << 2) +\n        (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);\n    backward = max_backward + 1 + word_idx +\n        (transform_id << dictionary->words->size_bits_by_length[len]);\n  }\n  if (backward > max_distance) {\n    return BROTLI_FALSE;\n  }\n  score = BackwardReferenceScore(matchlen, backward);\n  if (score < out->score) {\n    return BROTLI_FALSE;\n  }\n  out->len = matchlen;\n  out->len_code_delta = (int)len - (int)matchlen;\n  out->distance = backward;\n  out->score = score;\n  return BROTLI_TRUE;\n}\n\nstatic BROTLI_INLINE void SearchInStaticDictionary(\n    const BrotliEncoderDictionary* dictionary,\n    HasherCommon* common, const uint8_t* data, size_t max_length,\n    size_t max_backward, size_t max_distance,\n    HasherSearchResult* out, BROTLI_BOOL shallow) {\n  size_t key;\n  size_t i;\n  if (common->dict_num_matches < (common->dict_num_lookups >> 7)) {\n    return;\n  }\n  key = Hash14(data) << 1;\n  for (i = 0; i < (shallow ? 1u : 2u); ++i, ++key) {\n    common->dict_num_lookups++;\n    if (dictionary->hash_table_lengths[key] != 0) {\n      BROTLI_BOOL item_matches = TestStaticDictionaryItem(\n          dictionary, dictionary->hash_table_lengths[key],\n          dictionary->hash_table_words[key], data,\n          max_length, max_backward, max_distance, out);\n      if (item_matches) {\n        common->dict_num_matches++;\n      }\n    }\n  }\n}\n\ntypedef struct BackwardMatch {\n  uint32_t distance;\n  uint32_t length_and_code;\n} BackwardMatch;\n\nstatic BROTLI_INLINE void InitBackwardMatch(BackwardMatch* self,\n    size_t dist, size_t len) {\n  self->distance = (uint32_t)dist;\n  self->length_and_code = (uint32_t)(len << 5);\n}\n\nstatic BROTLI_INLINE void InitDictionaryBackwardMatch(BackwardMatch* self,\n    size_t dist, size_t len, size_t len_code) {\n  self->distance = (uint32_t)dist;\n  self->length_and_code =\n      (uint32_t)((len << 5) | (len == len_code ? 0 : len_code));\n}\n\nstatic BROTLI_INLINE size_t BackwardMatchLength(const BackwardMatch* self) {\n  return self->length_and_code >> 5;\n}\n\nstatic BROTLI_INLINE size_t BackwardMatchLengthCode(const BackwardMatch* self) {\n  size_t code = self->length_and_code & 31;\n  return code ? code : BackwardMatchLength(self);\n}\n\n#define EXPAND_CAT(a, b) CAT(a, b)\n#define CAT(a, b) a ## b\n#define FN(X) EXPAND_CAT(X, HASHER())\n\n#define HASHER() H10\n#define BUCKET_BITS 17\n#define MAX_TREE_SEARCH_DEPTH 64\n#define MAX_TREE_COMP_LENGTH 128\n#include \"hash_to_binary_tree_inc.h\"  /* NOLINT(build/include) */\n#undef MAX_TREE_SEARCH_DEPTH\n#undef MAX_TREE_COMP_LENGTH\n#undef BUCKET_BITS\n#undef HASHER\n/* MAX_NUM_MATCHES == 64 + MAX_TREE_SEARCH_DEPTH */\n#define MAX_NUM_MATCHES_H10 128\n\n/* For BUCKET_SWEEP_BITS == 0, enabling the dictionary lookup makes compression\n   a little faster (0.5% - 1%) and it compresses 0.15% better on small text\n   and HTML inputs. */\n\n#define HASHER() H2\n#define BUCKET_BITS 16\n#define BUCKET_SWEEP_BITS 0\n#define HASH_LEN 5\n#define USE_DICTIONARY 1\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef BUCKET_SWEEP_BITS\n#undef USE_DICTIONARY\n#undef HASHER\n\n#define HASHER() H3\n#define BUCKET_SWEEP_BITS 1\n#define USE_DICTIONARY 0\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef USE_DICTIONARY\n#undef BUCKET_SWEEP_BITS\n#undef BUCKET_BITS\n#undef HASHER\n\n#define HASHER() H4\n#define BUCKET_BITS 17\n#define BUCKET_SWEEP_BITS 2\n#define USE_DICTIONARY 1\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef USE_DICTIONARY\n#undef HASH_LEN\n#undef BUCKET_SWEEP_BITS\n#undef BUCKET_BITS\n#undef HASHER\n\n#define HASHER() H5\n#include \"hash_longest_match_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n\n#define HASHER() H6\n#include \"hash_longest_match64_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n\n#define BUCKET_BITS 15\n\n#define NUM_LAST_DISTANCES_TO_CHECK 4\n#define NUM_BANKS 1\n#define BANK_BITS 16\n#define HASHER() H40\n#include \"hash_forgetful_chain_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n#undef NUM_LAST_DISTANCES_TO_CHECK\n\n#define NUM_LAST_DISTANCES_TO_CHECK 10\n#define HASHER() H41\n#include \"hash_forgetful_chain_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n#undef NUM_LAST_DISTANCES_TO_CHECK\n#undef NUM_BANKS\n#undef BANK_BITS\n\n#define NUM_LAST_DISTANCES_TO_CHECK 16\n#define NUM_BANKS 512\n#define BANK_BITS 9\n#define HASHER() H42\n#include \"hash_forgetful_chain_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER\n#undef NUM_LAST_DISTANCES_TO_CHECK\n#undef NUM_BANKS\n#undef BANK_BITS\n\n#undef BUCKET_BITS\n\n#define HASHER() H54\n#define BUCKET_BITS 20\n#define BUCKET_SWEEP_BITS 2\n#define HASH_LEN 7\n#define USE_DICTIONARY 0\n#include \"hash_longest_match_quickly_inc.h\"  /* NOLINT(build/include) */\n#undef USE_DICTIONARY\n#undef HASH_LEN\n#undef BUCKET_SWEEP_BITS\n#undef BUCKET_BITS\n#undef HASHER\n\n/* fast large window hashers */\n\n#define HASHER() HROLLING_FAST\n#define CHUNKLEN 32\n#define JUMP 4\n#define NUMBUCKETS 16777216\n#define MASK ((NUMBUCKETS * 64) - 1)\n#include \"hash_rolling_inc.h\"  /* NOLINT(build/include) */\n#undef JUMP\n#undef HASHER\n\n\n#define HASHER() HROLLING\n#define JUMP 1\n#include \"hash_rolling_inc.h\"  /* NOLINT(build/include) */\n#undef MASK\n#undef NUMBUCKETS\n#undef JUMP\n#undef CHUNKLEN\n#undef HASHER\n\n#define HASHER() H35\n#define HASHER_A H3\n#define HASHER_B HROLLING_FAST\n#include \"hash_composite_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER_A\n#undef HASHER_B\n#undef HASHER\n\n#define HASHER() H55\n#define HASHER_A H54\n#define HASHER_B HROLLING_FAST\n#include \"hash_composite_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER_A\n#undef HASHER_B\n#undef HASHER\n\n#define HASHER() H65\n#define HASHER_A H6\n#define HASHER_B HROLLING\n#include \"hash_composite_inc.h\"  /* NOLINT(build/include) */\n#undef HASHER_A\n#undef HASHER_B\n#undef HASHER\n\n#undef FN\n#undef CAT\n#undef EXPAND_CAT\n\n#define FOR_SIMPLE_HASHERS(H) H(2) H(3) H(4) H(5) H(6) H(40) H(41) H(42) H(54)\n#define FOR_COMPOSITE_HASHERS(H) H(35) H(55) H(65)\n#define FOR_GENERIC_HASHERS(H) FOR_SIMPLE_HASHERS(H) FOR_COMPOSITE_HASHERS(H)\n#define FOR_ALL_HASHERS(H) FOR_GENERIC_HASHERS(H) H(10)\n\ntypedef struct {\n  HasherCommon common;\n\n  union {\n#define MEMBER_(N) \\\n    H ## N _H ## N;\n    FOR_ALL_HASHERS(MEMBER_)\n#undef MEMBER_\n  } privat;\n} Hasher;\n\n/* MUST be invoked before any other method. */\nstatic BROTLI_INLINE void HasherInit(Hasher* hasher) {\n  hasher->common.is_setup_ = BROTLI_FALSE;\n  hasher->common.extra[0] = NULL;\n  hasher->common.extra[1] = NULL;\n  hasher->common.extra[2] = NULL;\n  hasher->common.extra[3] = NULL;\n}\n\nstatic BROTLI_INLINE void DestroyHasher(MemoryManager* m, Hasher* hasher) {\n  if (hasher->common.extra[0] != NULL) BROTLI_FREE(m, hasher->common.extra[0]);\n  if (hasher->common.extra[1] != NULL) BROTLI_FREE(m, hasher->common.extra[1]);\n  if (hasher->common.extra[2] != NULL) BROTLI_FREE(m, hasher->common.extra[2]);\n  if (hasher->common.extra[3] != NULL) BROTLI_FREE(m, hasher->common.extra[3]);\n}\n\nstatic BROTLI_INLINE void HasherReset(Hasher* hasher) {\n  hasher->common.is_prepared_ = BROTLI_FALSE;\n}\n\nstatic BROTLI_INLINE void HasherSize(const BrotliEncoderParams* params,\n    BROTLI_BOOL one_shot, const size_t input_size, size_t* alloc_size) {\n  switch (params->hasher.type) {\n#define SIZE_(N)                                                           \\\n    case N:                                                                \\\n      HashMemAllocInBytesH ## N(params, one_shot, input_size, alloc_size); \\\n      break;\n    FOR_ALL_HASHERS(SIZE_)\n#undef SIZE_\n    default:\n      break;\n  }\n}\n\nstatic BROTLI_INLINE void HasherSetup(MemoryManager* m, Hasher* hasher,\n    BrotliEncoderParams* params, const uint8_t* data, size_t position,\n    size_t input_size, BROTLI_BOOL is_last) {\n  BROTLI_BOOL one_shot = (position == 0 && is_last);\n  if (!hasher->common.is_setup_) {\n    size_t alloc_size[4] = {0};\n    size_t i;\n    ChooseHasher(params, &params->hasher);\n    hasher->common.params = params->hasher;\n    hasher->common.dict_num_lookups = 0;\n    hasher->common.dict_num_matches = 0;\n    HasherSize(params, one_shot, input_size, alloc_size);\n    for (i = 0; i < 4; ++i) {\n      if (alloc_size[i] == 0) continue;\n      hasher->common.extra[i] = BROTLI_ALLOC(m, uint8_t, alloc_size[i]);\n      if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(hasher->common.extra[i])) return;\n    }\n    switch (hasher->common.params.type) {\n#define INITIALIZE_(N)                        \\\n      case N:                                 \\\n        InitializeH ## N(&hasher->common,     \\\n            &hasher->privat._H ## N, params); \\\n        break;\n      FOR_ALL_HASHERS(INITIALIZE_);\n#undef INITIALIZE_\n      default:\n        break;\n    }\n    HasherReset(hasher);\n    hasher->common.is_setup_ = BROTLI_TRUE;\n  }\n\n  if (!hasher->common.is_prepared_) {\n    switch (hasher->common.params.type) {\n#define PREPARE_(N)                      \\\n      case N:                            \\\n        PrepareH ## N(                   \\\n            &hasher->privat._H ## N,     \\\n            one_shot, input_size, data); \\\n        break;\n      FOR_ALL_HASHERS(PREPARE_)\n#undef PREPARE_\n      default: break;\n    }\n    hasher->common.is_prepared_ = BROTLI_TRUE;\n  }\n}\n\nstatic BROTLI_INLINE void InitOrStitchToPreviousBlock(\n    MemoryManager* m, Hasher* hasher, const uint8_t* data, size_t mask,\n    BrotliEncoderParams* params, size_t position, size_t input_size,\n    BROTLI_BOOL is_last) {\n  HasherSetup(m, hasher, params, data, position, input_size, is_last);\n  if (BROTLI_IS_OOM(m)) return;\n  switch (hasher->common.params.type) {\n#define INIT_(N)                             \\\n    case N:                                  \\\n      StitchToPreviousBlockH ## N(           \\\n          &hasher->privat._H ## N,           \\\n          input_size, position, data, mask); \\\n    break;\n    FOR_ALL_HASHERS(INIT_)\n#undef INIT_\n    default: break;\n  }\n}\n\n/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget\n       to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */\nstatic BROTLI_INLINE void FindCompoundDictionaryMatch(\n    const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length, const size_t distance_offset,\n    const size_t max_distance, HasherSearchResult* BROTLI_RESTRICT out) {\n  const uint32_t source_size = self->source_size;\n  const size_t boundary = distance_offset - source_size;\n  const uint32_t hash_bits = self->hash_bits;\n  const uint32_t bucket_bits = self->bucket_bits;\n  const uint32_t slot_bits = self->slot_bits;\n\n  const uint32_t hash_shift = 64u - bucket_bits;\n  const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits);\n  const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);\n\n  const uint32_t* slot_offsets = (uint32_t*)(&self[1]);\n  const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]);\n  const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]);\n  const uint8_t* source = NULL;\n\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  const uint64_t h =\n      (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) *\n      kPreparedDictionaryHashMul64Long;\n  const uint32_t key = (uint32_t)(h >> hash_shift);\n  const uint32_t slot = key & slot_mask;\n  const uint32_t head = heads[key];\n  const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head];\n  uint32_t item = (head == 0xFFFF) ? 1 : 0;\n\n  const void* tail = (void*)&items[self->num_items];\n  if (self->magic == kPreparedDictionaryMagic) {\n    source = (const uint8_t*)tail;\n  } else {\n    /* kLeanPreparedDictionaryMagic */\n    source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);\n  }\n\n  for (i = 0; i < 4; ++i) {\n    const size_t distance = (size_t)distance_cache[i];\n    size_t offset;\n    size_t limit;\n    size_t len;\n    if (distance <= boundary || distance > distance_offset) continue;\n    offset = distance_offset - distance;\n    limit = source_size - offset;\n    limit = limit > max_length ? max_length : limit;\n    len = FindMatchLengthWithLimit(&source[offset], &data[cur_ix_masked],\n                                   limit);\n    if (len >= 2) {\n      score_t score = BackwardReferenceScoreUsingLastDistance(len);\n      if (best_score < score) {\n        if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n        if (best_score < score) {\n          best_score = score;\n          if (len > best_len) best_len = len;\n          out->len = len;\n          out->len_code_delta = 0;\n          out->distance = distance;\n          out->score = best_score;\n        }\n      }\n    }\n  }\n  while (item == 0) {\n    size_t offset;\n    size_t distance;\n    size_t limit;\n    item = *chain;\n    chain++;\n    offset = item & 0x7FFFFFFF;\n    item &= 0x80000000;\n    distance = distance_offset - offset;\n    limit = source_size - offset;\n    limit = (limit > max_length) ? max_length : limit;\n    if (distance > max_distance) continue;\n    if (cur_ix_masked + best_len > ring_buffer_mask ||\n        best_len >= limit ||\n        data[cur_ix_masked + best_len] != source[offset + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&source[offset],\n                                                  &data[cur_ix_masked],\n                                                  limit);\n      if (len >= 4) {\n        score_t score = BackwardReferenceScore(len, distance);\n        if (best_score < score) {\n          best_score = score;\n          best_len = len;\n          out->len = best_len;\n          out->len_code_delta = 0;\n          out->distance = distance;\n          out->score = best_score;\n        }\n      }\n    }\n  }\n}\n\n/* NB: when seamless dictionary-ring-buffer copies are implemented, don't forget\n       to add proper guards for non-zero-BROTLI_PARAM_STREAM_OFFSET. */\nstatic BROTLI_INLINE size_t FindAllCompoundDictionaryMatches(\n    const PreparedDictionary* self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const size_t cur_ix, const size_t min_length,\n    const size_t max_length, const size_t distance_offset,\n    const size_t max_distance, BackwardMatch* matches, size_t match_limit) {\n  const uint32_t source_size = self->source_size;\n  const uint32_t hash_bits = self->hash_bits;\n  const uint32_t bucket_bits = self->bucket_bits;\n  const uint32_t slot_bits = self->slot_bits;\n\n  const uint32_t hash_shift = 64u - bucket_bits;\n  const uint32_t slot_mask = (~((uint32_t)0U)) >> (32 - slot_bits);\n  const uint64_t hash_mask = (~((uint64_t)0U)) >> (64 - hash_bits);\n\n  const uint32_t* slot_offsets = (uint32_t*)(&self[1]);\n  const uint16_t* heads = (uint16_t*)(&slot_offsets[1u << slot_bits]);\n  const uint32_t* items = (uint32_t*)(&heads[1u << bucket_bits]);\n  const uint8_t* source = NULL;\n\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  size_t best_len = min_length;\n  const uint64_t h =\n      (BROTLI_UNALIGNED_LOAD64LE(&data[cur_ix_masked]) & hash_mask) *\n      kPreparedDictionaryHashMul64Long;\n  const uint32_t key = (uint32_t)(h >> hash_shift);\n  const uint32_t slot = key & slot_mask;\n  const uint32_t head = heads[key];\n  const uint32_t* BROTLI_RESTRICT chain = &items[slot_offsets[slot] + head];\n  uint32_t item = (head == 0xFFFF) ? 1 : 0;\n  size_t found = 0;\n\n  const void* tail = (void*)&items[self->num_items];\n  if (self->magic == kPreparedDictionaryMagic) {\n    source = (const uint8_t*)tail;\n  } else {\n    /* kLeanPreparedDictionaryMagic */\n    source = (const uint8_t*)BROTLI_UNALIGNED_LOAD_PTR((const uint8_t**)tail);\n  }\n\n  while (item == 0) {\n    size_t offset;\n    size_t distance;\n    size_t limit;\n    size_t len;\n    item = *chain;\n    chain++;\n    offset = item & 0x7FFFFFFF;\n    item &= 0x80000000;\n    distance = distance_offset - offset;\n    limit = source_size - offset;\n    limit = (limit > max_length) ? max_length : limit;\n    if (distance > max_distance) continue;\n    if (cur_ix_masked + best_len > ring_buffer_mask ||\n        best_len >= limit ||\n        data[cur_ix_masked + best_len] != source[offset + best_len]) {\n      continue;\n    }\n    len = FindMatchLengthWithLimit(\n        &source[offset], &data[cur_ix_masked], limit);\n    if (len > best_len) {\n      best_len = len;\n      InitBackwardMatch(matches++, distance, len);\n      found++;\n      if (found == match_limit) break;\n    }\n  }\n  return found;\n}\n\nstatic BROTLI_INLINE void LookupCompoundDictionaryMatch(\n    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length,\n    const size_t max_ring_buffer_distance, const size_t max_distance,\n    HasherSearchResult* sr) {\n  size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;\n  size_t d;\n  for (d = 0; d < addon->num_chunks; ++d) {\n    /* Only one prepared dictionary type is currently supported. */\n    FindCompoundDictionaryMatch(\n        (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask,\n        distance_cache, cur_ix, max_length,\n        base_offset - addon->chunk_offsets[d], max_distance, sr);\n  }\n}\n\nstatic BROTLI_INLINE size_t LookupAllCompoundDictionaryMatches(\n    const CompoundDictionary* addon, const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const size_t cur_ix, size_t min_length,\n    const size_t max_length, const size_t max_ring_buffer_distance,\n    const size_t max_distance, BackwardMatch* matches,\n    size_t match_limit) {\n  size_t base_offset = max_ring_buffer_distance + 1 + addon->total_size - 1;\n  size_t d;\n  size_t total_found = 0;\n  for (d = 0; d < addon->num_chunks; ++d) {\n    /* Only one prepared dictionary type is currently supported. */\n    total_found += FindAllCompoundDictionaryMatches(\n        (const PreparedDictionary*)addon->chunks[d], data, ring_buffer_mask,\n        cur_ix, min_length, max_length, base_offset - addon->chunk_offsets[d],\n        max_distance, matches + total_found, match_limit - total_found);\n    if (total_found == match_limit) break;\n    if (total_found > 0) {\n      min_length = BackwardMatchLength(&matches[total_found - 1]);\n    }\n  }\n  return total_found;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_HASH_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/hash_composite_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2018 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, HASHER_A, HASHER_B */\n\n/* Composite hasher: This hasher allows to combine two other hashers, HASHER_A\n   and HASHER_B. */\n\n#define HashComposite HASHER()\n\n#define FN_A(X) EXPAND_CAT(X, HASHER_A)\n#define FN_B(X) EXPAND_CAT(X, HASHER_B)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) {\n  size_t a =  FN_A(HashTypeLength)();\n  size_t b =  FN_B(HashTypeLength)();\n  return a > b ? a : b;\n}\n\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) {\n  size_t a =  FN_A(StoreLookahead)();\n  size_t b =  FN_B(StoreLookahead)();\n  return a > b ? a : b;\n}\n\ntypedef struct HashComposite {\n  HASHER_A ha;\n  HASHER_B hb;\n  HasherCommon ha_common;\n  HasherCommon hb_common;\n\n  /* Shortcuts. */\n  HasherCommon* common;\n\n  BROTLI_BOOL fresh;\n  const BrotliEncoderParams* params;\n} HashComposite;\n\nstatic void FN(Initialize)(HasherCommon* common,\n    HashComposite* BROTLI_RESTRICT self, const BrotliEncoderParams* params) {\n  self->common = common;\n\n  self->ha_common = *self->common;\n  self->hb_common = *self->common;\n  self->fresh = BROTLI_TRUE;\n  self->params = params;\n  /* TODO(lode): Initialize of the hashers is deferred to Prepare (and params\n     remembered here) because we don't get the one_shot and input_size params\n     here that are needed to know the memory size of them. Instead provide\n     those params to all hashers FN(Initialize) */\n}\n\nstatic void FN(Prepare)(\n    HashComposite* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  if (self->fresh) {\n    self->fresh = BROTLI_FALSE;\n    self->ha_common.extra[0] = self->common->extra[0];\n    self->ha_common.extra[1] = self->common->extra[1];\n    self->ha_common.extra[2] = NULL;\n    self->ha_common.extra[3] = NULL;\n    self->hb_common.extra[0] = self->common->extra[2];\n    self->hb_common.extra[1] = self->common->extra[3];\n    self->hb_common.extra[2] = NULL;\n    self->hb_common.extra[3] = NULL;\n\n    FN_A(Initialize)(&self->ha_common, &self->ha, self->params);\n    FN_B(Initialize)(&self->hb_common, &self->hb, self->params);\n  }\n  FN_A(Prepare)(&self->ha, one_shot, input_size, data);\n  FN_B(Prepare)(&self->hb, one_shot, input_size, data);\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t alloc_size_a[4] = {0};\n  size_t alloc_size_b[4] = {0};\n  FN_A(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_a);\n  FN_B(HashMemAllocInBytes)(params, one_shot, input_size, alloc_size_b);\n  /* Should never happen. */\n  if (alloc_size_a[2] != 0 || alloc_size_a[3] != 0) exit(EXIT_FAILURE);\n  if (alloc_size_b[2] != 0 || alloc_size_b[3] != 0) exit(EXIT_FAILURE);\n  alloc_size[0] = alloc_size_a[0];\n  alloc_size[1] = alloc_size_a[1];\n  alloc_size[2] = alloc_size_b[0];\n  alloc_size[3] = alloc_size_b[1];\n}\n\nstatic BROTLI_INLINE void FN(Store)(HashComposite* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  FN_A(Store)(&self->ha, data, mask, ix);\n  FN_B(Store)(&self->hb, data, mask, ix);\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(\n    HashComposite* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix_start,\n    const size_t ix_end) {\n  FN_A(StoreRange)(&self->ha, data, mask, ix_start, ix_end);\n  FN_B(StoreRange)(&self->hb, data, mask, ix_start, ix_end);\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashComposite* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ring_buffer_mask) {\n  FN_A(StitchToPreviousBlock)(&self->ha, num_bytes, position,\n      ringbuffer, ring_buffer_mask);\n  FN_B(StitchToPreviousBlock)(&self->hb, num_bytes, position,\n      ringbuffer, ring_buffer_mask);\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashComposite* BROTLI_RESTRICT self, int* BROTLI_RESTRICT distance_cache) {\n  FN_A(PrepareDistanceCache)(&self->ha, distance_cache);\n  FN_B(PrepareDistanceCache)(&self->hb, distance_cache);\n}\n\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashComposite* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  FN_A(FindLongestMatch)(&self->ha, dictionary, data, ring_buffer_mask,\n      distance_cache, cur_ix, max_length, max_backward, dictionary_distance,\n      max_distance, out);\n  FN_B(FindLongestMatch)(&self->hb, dictionary, data, ring_buffer_mask,\n      distance_cache, cur_ix, max_length, max_backward, dictionary_distance,\n      max_distance, out);\n}\n\n#undef HashComposite\n"
  },
  {
    "path": "third-party/brotli/enc/hash_forgetful_chain_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, BUCKET_BITS, NUM_BANKS, BANK_BITS,\n                        NUM_LAST_DISTANCES_TO_CHECK */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   Hashes are stored in chains which are bucketed to groups. Group of chains\n   share a storage \"bank\". When more than \"bank size\" chain nodes are added,\n   oldest nodes are replaced; this way several chains may share a tail. */\n\n#define HashForgetfulChain HASHER()\n\n#define BANK_SIZE (1 << BANK_BITS)\n\n/* Number of hash buckets. */\n#define BUCKET_SIZE (1 << BUCKET_BITS)\n\n#define CAPPED_CHAINS 0\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n\n/* HashBytes is the function that chooses the bucket to place the address in.*/\nstatic BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {\n  const uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - BUCKET_BITS);\n}\n\ntypedef struct FN(Slot) {\n  uint16_t delta;\n  uint16_t next;\n} FN(Slot);\n\ntypedef struct FN(Bank) {\n  FN(Slot) slots[BANK_SIZE];\n} FN(Bank);\n\ntypedef struct HashForgetfulChain {\n  uint16_t free_slot_idx[NUM_BANKS];  /* Up to 1KiB. Move to dynamic? */\n  size_t max_hops;\n\n  /* Shortcuts. */\n  void* extra[2];\n  HasherCommon* common;\n\n  /* --- Dynamic size members --- */\n\n  /* uint32_t addr[BUCKET_SIZE]; */\n\n  /* uint16_t head[BUCKET_SIZE]; */\n\n  /* Truncated hash used for quick rejection of \"distance cache\" candidates. */\n  /* uint8_t tiny_hash[65536];*/\n\n  /* FN(Bank) banks[NUM_BANKS]; */\n} HashForgetfulChain;\n\nstatic uint32_t* FN(Addr)(void* extra) {\n  return (uint32_t*)extra;\n}\n\nstatic uint16_t* FN(Head)(void* extra) {\n  return (uint16_t*)(&FN(Addr)(extra)[BUCKET_SIZE]);\n}\n\nstatic uint8_t* FN(TinyHash)(void* extra) {\n  return (uint8_t*)(&FN(Head)(extra)[BUCKET_SIZE]);\n}\n\nstatic FN(Bank)* FN(Banks)(void* extra) {\n  return (FN(Bank)*)(extra);\n}\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashForgetfulChain* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common = common;\n  self->extra[0] = common->extra[0];\n  self->extra[1] = common->extra[1];\n\n  self->max_hops = (params->quality > 6 ? 7u : 8u) << (params->quality - 4);\n}\n\nstatic void FN(Prepare)(\n    HashForgetfulChain* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);\n  uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);\n  uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]);\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = BUCKET_SIZE >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      size_t bucket = FN(HashBytes)(&data[i]);\n      /* See InitEmpty comment. */\n      addr[bucket] = 0xCCCCCCCC;\n      head[bucket] = 0xCCCC;\n    }\n  } else {\n    /* Fill |addr| array with 0xCCCCCCCC value. Because of wrapping, position\n       processed by hasher never reaches 3GB + 64M; this makes all new chains\n       to be terminated after the first node. */\n    memset(addr, 0xCC, sizeof(uint32_t) * BUCKET_SIZE);\n    memset(head, 0, sizeof(uint16_t) * BUCKET_SIZE);\n  }\n  memset(tiny_hash, 0, sizeof(uint8_t) * 65536);\n  memset(self->free_slot_idx, 0, sizeof(self->free_slot_idx));\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  BROTLI_UNUSED(params);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE +\n                  sizeof(uint16_t) * BUCKET_SIZE + sizeof(uint8_t) * 65536;\n  alloc_size[1] = sizeof(FN(Bank)) * NUM_BANKS;\n}\n\n/* Look at 4 bytes at &data[ix & mask]. Compute a hash from these, and prepend\n   node to corresponding chain; also update tiny_hash for current position. */\nstatic BROTLI_INLINE void FN(Store)(HashForgetfulChain* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);\n  uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);\n  uint8_t* BROTLI_RESTRICT tiny_hash = FN(TinyHash)(self->extra[0]);\n  FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]);\n  const size_t key = FN(HashBytes)(&data[ix & mask]);\n  const size_t bank = key & (NUM_BANKS - 1);\n  const size_t idx = self->free_slot_idx[bank]++ & (BANK_SIZE - 1);\n  size_t delta = ix - addr[key];\n  tiny_hash[(uint16_t)ix] = (uint8_t)key;\n  if (delta > 0xFFFF) delta = CAPPED_CHAINS ? 0 : 0xFFFF;\n  banks[bank].slots[idx].delta = (uint16_t)delta;\n  banks[bank].slots[idx].next = head[key];\n  addr[key] = (uint32_t)ix;\n  head[key] = (uint16_t)idx;\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ring_buffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ring_buffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ring_buffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ring_buffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  BROTLI_UNUSED(self);\n  PrepareDistanceCache(distance_cache, NUM_LAST_DISTANCES_TO_CHECK);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashForgetfulChain* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint32_t* BROTLI_RESTRICT addr = FN(Addr)(self->extra[0]);\n  uint16_t* BROTLI_RESTRICT head = FN(Head)(self->extra[0]);\n  uint8_t* BROTLI_RESTRICT tiny_hashes = FN(TinyHash)(self->extra[0]);\n  FN(Bank)* BROTLI_RESTRICT banks = FN(Banks)(self->extra[1]);\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  const size_t key = FN(HashBytes)(&data[cur_ix_masked]);\n  const uint8_t tiny_hash = (uint8_t)(key);\n  out->len = 0;\n  out->len_code_delta = 0;\n  /* Try last distance first. */\n  for (i = 0; i < NUM_LAST_DISTANCES_TO_CHECK; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (cur_ix - backward);\n    /* For distance code 0 we want to consider 2-byte matches. */\n    if (i > 0 && tiny_hashes[(uint16_t)prev_ix] != tiny_hash) continue;\n    if (prev_ix >= cur_ix || backward > max_backward) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 2) {\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  {\n    const size_t bank = key & (NUM_BANKS - 1);\n    size_t backward = 0;\n    size_t hops = self->max_hops;\n    size_t delta = cur_ix - addr[key];\n    size_t slot = head[key];\n    while (hops--) {\n      size_t prev_ix;\n      size_t last = slot;\n      backward += delta;\n      if (backward > max_backward || (CAPPED_CHAINS && !delta)) break;\n      prev_ix = (cur_ix - backward) & ring_buffer_mask;\n      slot = banks[bank].slots[last].next;\n      delta = banks[bank].slots[last].delta;\n      if (cur_ix_masked + best_len > ring_buffer_mask ||\n          prev_ix + best_len > ring_buffer_mask ||\n          data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n        continue;\n      }\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                    &data[cur_ix_masked],\n                                                    max_length);\n        if (len >= 4) {\n          /* Comparing for >= 3 does not change the semantics, but just saves\n             for a few unnecessary binary logarithms in backward reference\n             score, since we are not interested in such short matches. */\n          score_t score = BackwardReferenceScore(len, backward);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n    FN(Store)(self, data, ring_buffer_mask, cur_ix);\n  }\n  if (out->score == min_score) {\n    SearchInStaticDictionary(dictionary,\n        self->common, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef BANK_SIZE\n#undef BUCKET_SIZE\n#undef CAPPED_CHAINS\n\n#undef HashForgetfulChain\n"
  },
  {
    "path": "third-party/brotli/enc/hash_longest_match64_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (bucket_size_) to a ring buffer of\n   fixed size (block_size_). The ring buffer contains the last block_size_\n   index positions of the given hash key in the compressed data. */\n\n#define HashLongestMatch HASHER()\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }\n\n/* HashBytes is the function that chooses the bucket to place the address in. */\nstatic BROTLI_INLINE size_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data,\n                                          uint64_t hash_mul) {\n  const uint64_t h = BROTLI_UNALIGNED_LOAD64LE(data) * hash_mul;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (size_t)(h >> (64 - 15));\n}\n\ntypedef struct HashLongestMatch {\n  /* Number of hash buckets. */\n  size_t bucket_size_;\n  /* Only block_size_ newest backward references are kept,\n     and the older are forgotten. */\n  size_t block_size_;\n  /* Hash multiplier tuned to match length. */\n  uint64_t hash_mul_;\n  /* Mask for accessing entries in a block (in a ring-buffer manner). */\n  uint32_t block_mask_;\n\n  int block_bits_;\n  int num_last_distances_to_check_;\n\n  /* Shortcuts. */\n  HasherCommon* common_;\n\n  /* --- Dynamic size members --- */\n\n  /* Number of entries in a particular bucket. */\n  uint16_t* num_;  /* uint16_t[bucket_size]; */\n\n  /* Buckets containing block_size_ of backward references. */\n  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */\n} HashLongestMatch;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common_ = common;\n\n  BROTLI_UNUSED(params);\n  self->hash_mul_ = kHashMul64 << (64 - 5 * 8);\n  BROTLI_DCHECK(common->params.bucket_bits == 15);\n  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;\n  self->block_bits_ = common->params.block_bits;\n  self->block_size_ = (size_t)1 << common->params.block_bits;\n  self->block_mask_ = (uint32_t)(self->block_size_ - 1);\n  self->num_last_distances_to_check_ =\n      common->params.num_last_distances_to_check;\n  self->num_ = (uint16_t*)common->extra[0];\n  self->buckets_ = (uint32_t*)common->extra[1];\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = self->bucket_size_ >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const size_t key = FN(HashBytes)(&data[i], self->hash_mul_);\n      num[key] = 0;\n    }\n  } else {\n    memset(num, 0, self->bucket_size_ * sizeof(num[0]));\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;\n  size_t block_size = (size_t)1 << params->hasher.block_bits;\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint16_t) * bucket_size;\n  alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size;\n}\n\n/* Look at 4 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value of ix at that position. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t key = FN(HashBytes)(&data[ix & mask], self->hash_mul_);\n  const size_t minor_ix = num[key] & self->block_mask_;\n  const size_t offset = minor_ix + (key << self->block_bits_);\n  ++num[key];\n  buckets[offset] = (uint32_t)ix;\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  out->len = 0;\n  out->len_code_delta = 0;\n  /* Try last distance first. */\n  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (size_t)(cur_ix - backward);\n    if (prev_ix >= cur_ix) {\n      continue;\n    }\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n\n    if (cur_ix_masked + best_len > ring_buffer_mask ||\n        prev_ix + best_len > ring_buffer_mask ||\n        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 3 || (len == 2 && i < 2)) {\n        /* Comparing for >= 2 does not change the semantics, but just saves for\n           a few unnecessary binary logarithms in backward reference score,\n           since we are not interested in such short matches. */\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  {\n    const size_t key = FN(HashBytes)(&data[cur_ix_masked], self->hash_mul_);\n    uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];\n    const size_t down =\n        (num[key] > self->block_size_) ?\n        (num[key] - self->block_size_) : 0u;\n    const uint32_t first4 = BrotliUnalignedRead32(data + cur_ix_masked);\n    const size_t max_length_m4 = max_length - 4;\n    i = num[key];\n    for (; i > down;) {\n      size_t prev_ix = bucket[--i & self->block_mask_];\n      uint32_t current4;\n      const size_t backward = cur_ix - prev_ix;\n      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n        break;\n      }\n      prev_ix &= ring_buffer_mask;\n      if (cur_ix_masked + best_len > ring_buffer_mask ||\n          prev_ix + best_len > ring_buffer_mask ||\n          data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n        continue;\n      }\n      current4 = BrotliUnalignedRead32(data + prev_ix);\n      if (first4 != current4) continue;\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix + 4],\n                                                    &data[cur_ix_masked + 4],\n                                                    max_length_m4) + 4;\n        const score_t score = BackwardReferenceScore(len, backward);\n        if (best_score < score) {\n          best_score = score;\n          best_len = len;\n          out->len = best_len;\n          out->distance = backward;\n          out->score = best_score;\n        }\n      }\n    }\n    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;\n    ++num[key];\n  }\n  if (min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef HashLongestMatch\n"
  },
  {
    "path": "third-party/brotli/enc/hash_longest_match_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (bucket_size_) to a ring buffer of\n   fixed size (block_size_). The ring buffer contains the last block_size_\n   index positions of the given hash key in the compressed data. */\n\n#define HashLongestMatch HASHER()\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n\n/* HashBytes is the function that chooses the bucket to place the address in. */\nstatic uint32_t FN(HashBytes)(\n    const uint8_t* BROTLI_RESTRICT data, const int shift) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (uint32_t)(h >> shift);\n}\n\ntypedef struct HashLongestMatch {\n  /* Number of hash buckets. */\n  size_t bucket_size_;\n  /* Only block_size_ newest backward references are kept,\n     and the older are forgotten. */\n  size_t block_size_;\n  /* Left-shift for computing hash bucket index from hash value. */\n  int hash_shift_;\n  /* Mask for accessing entries in a block (in a ring-buffer manner). */\n  uint32_t block_mask_;\n\n  int block_bits_;\n  int num_last_distances_to_check_;\n\n  /* Shortcuts. */\n  HasherCommon* common_;\n\n  /* --- Dynamic size members --- */\n\n  /* Number of entries in a particular bucket. */\n  uint16_t* num_;  /* uint16_t[bucket_size]; */\n\n  /* Buckets containing block_size_ of backward references. */\n  uint32_t* buckets_;  /* uint32_t[bucket_size * block_size]; */\n} HashLongestMatch;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common_ = common;\n\n  BROTLI_UNUSED(params);\n  self->hash_shift_ = 32 - common->params.bucket_bits;\n  self->bucket_size_ = (size_t)1 << common->params.bucket_bits;\n  self->block_size_ = (size_t)1 << common->params.block_bits;\n  self->block_mask_ = (uint32_t)(self->block_size_ - 1);\n  self->num_ = (uint16_t*)common->extra[0];\n  self->buckets_ = (uint32_t*)common->extra[1];\n  self->block_bits_ = common->params.block_bits;\n  self->num_last_distances_to_check_ =\n      common->params.num_last_distances_to_check;\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatch* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = self->bucket_size_ >> 6;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const uint32_t key = FN(HashBytes)(&data[i], self->hash_shift_);\n      num[key] = 0;\n    }\n  } else {\n    memset(num, 0, self->bucket_size_ * sizeof(num[0]));\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t bucket_size = (size_t)1 << params->hasher.bucket_bits;\n  size_t block_size = (size_t)1 << params->hasher.block_bits;\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint16_t) * bucket_size;\n  alloc_size[1] = sizeof(uint32_t) * bucket_size * block_size;\n}\n\n/* Look at 4 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value of ix at that position. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatch* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  const uint32_t key = FN(HashBytes)(&data[ix & mask], self->hash_shift_);\n  const size_t minor_ix = self->num_[key] & self->block_mask_;\n  const size_t offset = minor_ix + (key << self->block_bits_);\n  self->buckets_[offset] = (uint32_t)ix;\n  ++self->num_[key];\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashLongestMatch* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  PrepareDistanceCache(distance_cache, self->num_last_distances_to_check_);\n}\n\n/* Find a longest backward match of &data[cur_ix] up to the length of\n   max_length and stores the position cur_ix in the hash table.\n\n   REQUIRES: FN(PrepareDistanceCache) must be invoked for current distance cache\n             values; if this method is invoked repeatedly with the same distance\n             cache values, it is enough to invoke FN(PrepareDistanceCache) once.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatch* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint16_t* BROTLI_RESTRICT num = self->num_;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  /* Don't accept a short copy from far away. */\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = out->len;\n  size_t i;\n  out->len = 0;\n  out->len_code_delta = 0;\n  /* Try last distance first. */\n  for (i = 0; i < (size_t)self->num_last_distances_to_check_; ++i) {\n    const size_t backward = (size_t)distance_cache[i];\n    size_t prev_ix = (size_t)(cur_ix - backward);\n    if (prev_ix >= cur_ix) {\n      continue;\n    }\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      continue;\n    }\n    prev_ix &= ring_buffer_mask;\n\n    if (cur_ix_masked + best_len > ring_buffer_mask ||\n        prev_ix + best_len > ring_buffer_mask ||\n        data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n      continue;\n    }\n    {\n      const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                  &data[cur_ix_masked],\n                                                  max_length);\n      if (len >= 3 || (len == 2 && i < 2)) {\n        /* Comparing for >= 2 does not change the semantics, but just saves for\n           a few unnecessary binary logarithms in backward reference score,\n           since we are not interested in such short matches. */\n        score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          if (i != 0) score -= BackwardReferencePenaltyUsingLastDistance(i);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n  }\n  {\n    const uint32_t key =\n        FN(HashBytes)(&data[cur_ix_masked], self->hash_shift_);\n    uint32_t* BROTLI_RESTRICT bucket = &buckets[key << self->block_bits_];\n    const size_t down =\n        (num[key] > self->block_size_) ? (num[key] - self->block_size_) : 0u;\n    for (i = num[key]; i > down;) {\n      size_t prev_ix = bucket[--i & self->block_mask_];\n      const size_t backward = cur_ix - prev_ix;\n      if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n        break;\n      }\n      prev_ix &= ring_buffer_mask;\n      if (cur_ix_masked + best_len > ring_buffer_mask ||\n          prev_ix + best_len > ring_buffer_mask ||\n          data[cur_ix_masked + best_len] != data[prev_ix + best_len]) {\n        continue;\n      }\n      {\n        const size_t len = FindMatchLengthWithLimit(&data[prev_ix],\n                                                    &data[cur_ix_masked],\n                                                    max_length);\n        if (len >= 4) {\n          /* Comparing for >= 3 does not change the semantics, but just saves\n             for a few unnecessary binary logarithms in backward reference\n             score, since we are not interested in such short matches. */\n          score_t score = BackwardReferenceScore(len, backward);\n          if (best_score < score) {\n            best_score = score;\n            best_len = len;\n            out->len = best_len;\n            out->distance = backward;\n            out->score = best_score;\n          }\n        }\n      }\n    }\n    bucket[num[key] & self->block_mask_] = (uint32_t)cur_ix;\n    ++num[key];\n  }\n  if (min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common_, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_FALSE);\n  }\n}\n\n#undef HashLongestMatch\n"
  },
  {
    "path": "third-party/brotli/enc/hash_longest_match_quickly_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, BUCKET_BITS, BUCKET_SWEEP_BITS, HASH_LEN,\n                        USE_DICTIONARY\n */\n\n#define HashLongestMatchQuickly HASHER()\n\n#define BUCKET_SIZE (1 << BUCKET_BITS)\n#define BUCKET_MASK (BUCKET_SIZE - 1)\n#define BUCKET_SWEEP (1 << BUCKET_SWEEP_BITS)\n#define BUCKET_SWEEP_MASK ((BUCKET_SWEEP - 1) << 3)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 8; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 8; }\n\n/* HashBytes is the function that chooses the bucket to place\n   the address in. The HashLongestMatch and HashLongestMatchQuickly\n   classes have separate, different implementations of hashing. */\nstatic uint32_t FN(HashBytes)(const uint8_t* data) {\n  const uint64_t h = ((BROTLI_UNALIGNED_LOAD64LE(data) << (64 - 8 * HASH_LEN)) *\n                      kHashMul64);\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return (uint32_t)(h >> (64 - BUCKET_BITS));\n}\n\n/* A (forgetful) hash table to the data seen by the compressor, to\n   help create backward references to previous data.\n\n   This is a hash map of fixed size (BUCKET_SIZE). */\ntypedef struct HashLongestMatchQuickly {\n  /* Shortcuts. */\n  HasherCommon* common;\n\n  /* --- Dynamic size members --- */\n\n  uint32_t* buckets_;  /* uint32_t[BUCKET_SIZE]; */\n} HashLongestMatchQuickly;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->common = common;\n\n  BROTLI_UNUSED(params);\n  self->buckets_ = (uint32_t*)common->extra[0];\n}\n\nstatic void FN(Prepare)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  /* Partial preparation is 100 times slower (per socket). */\n  size_t partial_prepare_threshold = BUCKET_SIZE >> 5;\n  if (one_shot && input_size <= partial_prepare_threshold) {\n    size_t i;\n    for (i = 0; i < input_size; ++i) {\n      const uint32_t key = FN(HashBytes)(&data[i]);\n      if (BUCKET_SWEEP == 1) {\n        buckets[key] = 0;\n      } else {\n        uint32_t j;\n        for (j = 0; j < BUCKET_SWEEP; ++j) {\n          buckets[(key + (j << 3)) & BUCKET_MASK] = 0;\n        }\n      }\n    }\n  } else {\n    /* It is not strictly necessary to fill this buffer here, but\n       not filling will make the results of the compression stochastic\n       (but correct). This is because random data would cause the\n       system to find accidentally good backward references here and there. */\n    memset(buckets, 0, sizeof(uint32_t) * BUCKET_SIZE);\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  BROTLI_UNUSED(params);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE;\n}\n\n/* Look at 5 bytes at &data[ix & mask].\n   Compute a hash from these, and store the value somewhere within\n   [ix .. ix+3]. */\nstatic BROTLI_INLINE void FN(Store)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  const uint32_t key = FN(HashBytes)(&data[ix & mask]);\n  if (BUCKET_SWEEP == 1) {\n    self->buckets_[key] = (uint32_t)ix;\n  } else {\n    /* Wiggle the value with the bucket sweep range. */\n    const uint32_t off = ix & BUCKET_SWEEP_MASK;\n    self->buckets_[(key + off) & BUCKET_MASK] = (uint32_t)ix;\n  }\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i;\n  for (i = ix_start; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position,\n    const uint8_t* ringbuffer, size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 && position >= 3) {\n    /* Prepare the hashes for three last bytes of the last write.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 3);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 2);\n    FN(Store)(self, ringbuffer, ringbuffer_mask, position - 1);\n  }\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(distance_cache);\n}\n\n/* Find a longest backward match of &data[cur_ix & ring_buffer_mask]\n   up to the length of max_length and stores the position cur_ix in the\n   hash table.\n\n   Does not look for matches longer than max_length.\n   Does not look for matches further away than max_backward.\n   Writes the best match into |out|.\n   |out|->score is updated only if a better match is found. */\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashLongestMatchQuickly* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const int* BROTLI_RESTRICT distance_cache,\n    const size_t cur_ix, const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  const size_t best_len_in = out->len;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  int compare_char = data[cur_ix_masked + best_len_in];\n  size_t key = FN(HashBytes)(&data[cur_ix_masked]);\n  size_t key_out;\n  score_t min_score = out->score;\n  score_t best_score = out->score;\n  size_t best_len = best_len_in;\n  size_t cached_backward = (size_t)distance_cache[0];\n  size_t prev_ix = cur_ix - cached_backward;\n  out->len_code_delta = 0;\n  if (prev_ix < cur_ix) {\n    prev_ix &= (uint32_t)ring_buffer_mask;\n    if (compare_char == data[prev_ix + best_len]) {\n      const size_t len = FindMatchLengthWithLimit(\n          &data[prev_ix], &data[cur_ix_masked], max_length);\n      if (len >= 4) {\n        const score_t score = BackwardReferenceScoreUsingLastDistance(len);\n        if (best_score < score) {\n          out->len = len;\n          out->distance = cached_backward;\n          out->score = score;\n          if (BUCKET_SWEEP == 1) {\n            buckets[key] = (uint32_t)cur_ix;\n            return;\n          } else {\n            best_len = len;\n            best_score = score;\n            compare_char = data[cur_ix_masked + len];\n          }\n        }\n      }\n    }\n  }\n  if (BUCKET_SWEEP == 1) {\n    size_t backward;\n    size_t len;\n    /* Only one to look for, don't bother to prepare for a loop. */\n    prev_ix = buckets[key];\n    buckets[key] = (uint32_t)cur_ix;\n    backward = cur_ix - prev_ix;\n    prev_ix &= (uint32_t)ring_buffer_mask;\n    if (compare_char != data[prev_ix + best_len_in]) {\n      return;\n    }\n    if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) {\n      return;\n    }\n    len = FindMatchLengthWithLimit(&data[prev_ix],\n                                   &data[cur_ix_masked],\n                                   max_length);\n    if (len >= 4) {\n      const score_t score = BackwardReferenceScore(len, backward);\n      if (best_score < score) {\n        out->len = len;\n        out->distance = backward;\n        out->score = score;\n        return;\n      }\n    }\n  } else {\n    size_t keys[BUCKET_SWEEP];\n    size_t i;\n    for (i = 0; i < BUCKET_SWEEP; ++i) {\n      keys[i] = (key + (i << 3)) & BUCKET_MASK;\n    }\n    key_out = keys[(cur_ix & BUCKET_SWEEP_MASK) >> 3];\n    for (i = 0; i < BUCKET_SWEEP; ++i) {\n      size_t len;\n      size_t backward;\n      prev_ix = buckets[keys[i]];\n      backward = cur_ix - prev_ix;\n      prev_ix &= (uint32_t)ring_buffer_mask;\n      if (compare_char != data[prev_ix + best_len]) {\n        continue;\n      }\n      if (BROTLI_PREDICT_FALSE(backward == 0 || backward > max_backward)) {\n        continue;\n      }\n      len = FindMatchLengthWithLimit(&data[prev_ix],\n                                     &data[cur_ix_masked],\n                                     max_length);\n      if (len >= 4) {\n        const score_t score = BackwardReferenceScore(len, backward);\n        if (best_score < score) {\n          best_len = len;\n          out->len = len;\n          compare_char = data[cur_ix_masked + len];\n          best_score = score;\n          out->score = score;\n          out->distance = backward;\n        }\n      }\n    }\n  }\n  if (USE_DICTIONARY && min_score == out->score) {\n    SearchInStaticDictionary(dictionary,\n        self->common, &data[cur_ix_masked], max_length, dictionary_distance,\n        max_distance, out, BROTLI_TRUE);\n  }\n  if (BUCKET_SWEEP != 1) {\n    buckets[key_out] = (uint32_t)cur_ix;\n  }\n}\n\n#undef BUCKET_SWEEP_MASK\n#undef BUCKET_SWEEP\n#undef BUCKET_MASK\n#undef BUCKET_SIZE\n\n#undef HashLongestMatchQuickly\n"
  },
  {
    "path": "third-party/brotli/enc/hash_rolling_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2018 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, JUMP, NUMBUCKETS, MASK, CHUNKLEN */\n/* NUMBUCKETS / (MASK + 1) = probability of storing and using hash code. */\n/* JUMP = skip bytes for speedup */\n\n/* Rolling hash for long distance long string matches. Stores one position\n   per bucket, bucket key is computed over a long region. */\n\n#define HashRolling HASHER()\n\nstatic const uint32_t FN(kRollingHashMul32) = 69069;\nstatic const uint32_t FN(kInvalidPos) = 0xffffffff;\n\n/* This hasher uses a longer forward length, but returning a higher value here\n   will hurt compression by the main hasher when combined with a composite\n   hasher. The hasher tests for forward itself instead. */\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) { return 4; }\n\n/* Computes a code from a single byte. A lookup table of 256 values could be\n   used, but simply adding 1 works about as good. */\nstatic uint32_t FN(HashByte)(uint8_t byte) {\n  return (uint32_t)byte + 1u;\n}\n\nstatic uint32_t FN(HashRollingFunctionInitial)(uint32_t state, uint8_t add,\n                                               uint32_t factor) {\n  return (uint32_t)(factor * state + FN(HashByte)(add));\n}\n\nstatic uint32_t FN(HashRollingFunction)(uint32_t state, uint8_t add,\n                                        uint8_t rem, uint32_t factor,\n                                        uint32_t factor_remove) {\n  return (uint32_t)(factor * state +\n      FN(HashByte)(add) - factor_remove * FN(HashByte)(rem));\n}\n\ntypedef struct HashRolling {\n  uint32_t state;\n  uint32_t* table;\n  size_t next_ix;\n\n  uint32_t chunk_len;\n  uint32_t factor;\n  uint32_t factor_remove;\n} HashRolling;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashRolling* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  size_t i;\n  self->state = 0;\n  self->next_ix = 0;\n\n  self->factor = FN(kRollingHashMul32);\n\n  /* Compute the factor of the oldest byte to remove: factor**steps modulo\n     0xffffffff (the multiplications rely on 32-bit overflow) */\n  self->factor_remove = 1;\n  for (i = 0; i < CHUNKLEN; i += JUMP) {\n    self->factor_remove *= self->factor;\n  }\n\n  self->table = (uint32_t*)common->extra[0];\n  for (i = 0; i < NUMBUCKETS; i++) {\n    self->table[i] = FN(kInvalidPos);\n  }\n\n  BROTLI_UNUSED(params);\n}\n\nstatic void FN(Prepare)(HashRolling* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  size_t i;\n  /* Too small size, cannot use this hasher. */\n  if (input_size < CHUNKLEN) return;\n  self->state = 0;\n  for (i = 0; i < CHUNKLEN; i += JUMP) {\n    self->state = FN(HashRollingFunctionInitial)(\n        self->state, data[i], self->factor);\n  }\n  BROTLI_UNUSED(one_shot);\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  BROTLI_UNUSED(params);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  alloc_size[0] = NUMBUCKETS * sizeof(uint32_t);\n}\n\nstatic BROTLI_INLINE void FN(Store)(HashRolling* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask, const size_t ix) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(data);\n  BROTLI_UNUSED(mask);\n  BROTLI_UNUSED(ix);\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashRolling* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(data);\n  BROTLI_UNUSED(mask);\n  BROTLI_UNUSED(ix_start);\n  BROTLI_UNUSED(ix_end);\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashRolling* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ring_buffer_mask) {\n  /* In this case we must re-initialize the hasher from scratch from the\n     current position. */\n  size_t position_masked;\n  size_t available = num_bytes;\n  if ((position & (JUMP - 1)) != 0) {\n    size_t diff = JUMP - (position & (JUMP - 1));\n    available = (diff > available) ? 0 : (available - diff);\n    position += diff;\n  }\n  position_masked = position & ring_buffer_mask;\n  /* wrapping around ringbuffer not handled. */\n  if (available > ring_buffer_mask - position_masked) {\n    available = ring_buffer_mask - position_masked;\n  }\n\n  FN(Prepare)(self, BROTLI_FALSE, available,\n      ringbuffer + (position & ring_buffer_mask));\n  self->next_ix = position;\n  BROTLI_UNUSED(num_bytes);\n}\n\nstatic BROTLI_INLINE void FN(PrepareDistanceCache)(\n    HashRolling* BROTLI_RESTRICT self,\n    int* BROTLI_RESTRICT distance_cache) {\n  BROTLI_UNUSED(self);\n  BROTLI_UNUSED(distance_cache);\n}\n\nstatic BROTLI_INLINE void FN(FindLongestMatch)(\n    HashRolling* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data, const size_t ring_buffer_mask,\n    const int* BROTLI_RESTRICT distance_cache, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const size_t max_distance,\n    HasherSearchResult* BROTLI_RESTRICT out) {\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  size_t pos;\n\n  if ((cur_ix & (JUMP - 1)) != 0) return;\n\n  /* Not enough lookahead */\n  if (max_length < CHUNKLEN) return;\n\n  for (pos = self->next_ix; pos <= cur_ix; pos += JUMP) {\n    uint32_t code = self->state & MASK;\n\n    uint8_t rem = data[pos & ring_buffer_mask];\n    uint8_t add = data[(pos + CHUNKLEN) & ring_buffer_mask];\n    size_t found_ix = FN(kInvalidPos);\n\n    self->state = FN(HashRollingFunction)(\n        self->state, add, rem, self->factor, self->factor_remove);\n\n    if (code < NUMBUCKETS) {\n      found_ix = self->table[code];\n      self->table[code] = (uint32_t)pos;\n      if (pos == cur_ix && found_ix != FN(kInvalidPos)) {\n        /* The cast to 32-bit makes backward distances up to 4GB work even\n           if cur_ix is above 4GB, despite using 32-bit values in the table. */\n        size_t backward = (uint32_t)(cur_ix - found_ix);\n        if (backward <= max_backward) {\n          const size_t found_ix_masked = found_ix & ring_buffer_mask;\n          const size_t len = FindMatchLengthWithLimit(&data[found_ix_masked],\n                                                      &data[cur_ix_masked],\n                                                      max_length);\n          if (len >= 4 && len > out->len) {\n            score_t score = BackwardReferenceScore(len, backward);\n            if (score > out->score) {\n              out->len = len;\n              out->distance = backward;\n              out->score = score;\n              out->len_code_delta = 0;\n            }\n          }\n        }\n      }\n    }\n  }\n\n  self->next_ix = cur_ix + JUMP;\n\n  /* NOTE: this hasher does not search in the dictionary. It is used as\n     backup-hasher, the main hasher already searches in it. */\n  BROTLI_UNUSED(dictionary);\n  BROTLI_UNUSED(distance_cache);\n  BROTLI_UNUSED(dictionary_distance);\n  BROTLI_UNUSED(max_distance);\n}\n\n#undef HashRolling\n"
  },
  {
    "path": "third-party/brotli/enc/hash_to_binary_tree_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN, BUCKET_BITS, MAX_TREE_COMP_LENGTH,\n                        MAX_TREE_SEARCH_DEPTH */\n\n/* A (forgetful) hash table where each hash bucket contains a binary tree of\n   sequences whose first 4 bytes share the same hash code.\n   Each sequence is MAX_TREE_COMP_LENGTH long and is identified by its starting\n   position in the input data. The binary tree is sorted by the lexicographic\n   order of the sequences, and it is also a max-heap with respect to the\n   starting positions. */\n\n#define HashToBinaryTree HASHER()\n\n#define BUCKET_SIZE (1 << BUCKET_BITS)\n\nstatic BROTLI_INLINE size_t FN(HashTypeLength)(void) { return 4; }\nstatic BROTLI_INLINE size_t FN(StoreLookahead)(void) {\n  return MAX_TREE_COMP_LENGTH;\n}\n\nstatic uint32_t FN(HashBytes)(const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - BUCKET_BITS);\n}\n\ntypedef struct HashToBinaryTree {\n  /* The window size minus 1 */\n  size_t window_mask_;\n\n  /* Hash table that maps the 4-byte hashes of the sequence to the last\n     position where this hash was found, which is the root of the binary\n     tree of sequences that share this hash bucket. */\n  uint32_t* buckets_;  /* uint32_t[BUCKET_SIZE]; */\n\n  /* A position used to mark a non-existent sequence, i.e. a tree is empty if\n     its root is at invalid_pos_ and a node is a leaf if both its children\n     are at invalid_pos_. */\n  uint32_t invalid_pos_;\n\n  /* --- Dynamic size members --- */\n\n  /* The union of the binary trees of each hash bucket. The root of the tree\n     corresponding to a hash is a sequence starting at buckets_[hash] and\n     the left and right children of a sequence starting at pos are\n     forest_[2 * pos] and forest_[2 * pos + 1]. */\n  uint32_t* forest_;  /* uint32_t[2 * num_nodes] */\n} HashToBinaryTree;\n\nstatic void FN(Initialize)(\n    HasherCommon* common, HashToBinaryTree* BROTLI_RESTRICT self,\n    const BrotliEncoderParams* params) {\n  self->buckets_ = (uint32_t*)common->extra[0];\n  self->forest_ = (uint32_t*)common->extra[1];\n\n  self->window_mask_ = (1u << params->lgwin) - 1u;\n  self->invalid_pos_ = (uint32_t)(0 - self->window_mask_);\n}\n\nstatic void FN(Prepare)\n    (HashToBinaryTree* BROTLI_RESTRICT self, BROTLI_BOOL one_shot,\n    size_t input_size, const uint8_t* BROTLI_RESTRICT data) {\n  uint32_t invalid_pos = self->invalid_pos_;\n  uint32_t i;\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  BROTLI_UNUSED(data);\n  BROTLI_UNUSED(one_shot);\n  BROTLI_UNUSED(input_size);\n  for (i = 0; i < BUCKET_SIZE; i++) {\n    buckets[i] = invalid_pos;\n  }\n}\n\nstatic BROTLI_INLINE void FN(HashMemAllocInBytes)(\n    const BrotliEncoderParams* params, BROTLI_BOOL one_shot,\n    size_t input_size, size_t* alloc_size) {\n  size_t num_nodes = (size_t)1 << params->lgwin;\n  if (one_shot && input_size < num_nodes) {\n    num_nodes = input_size;\n  }\n  alloc_size[0] = sizeof(uint32_t) * BUCKET_SIZE;\n  alloc_size[1] = 2 * sizeof(uint32_t) * num_nodes;\n}\n\nstatic BROTLI_INLINE size_t FN(LeftChildIndex)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    const size_t pos) {\n  return 2 * (pos & self->window_mask_);\n}\n\nstatic BROTLI_INLINE size_t FN(RightChildIndex)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    const size_t pos) {\n  return 2 * (pos & self->window_mask_) + 1;\n}\n\n/* Stores the hash of the next 4 bytes and in a single tree-traversal, the\n   hash bucket's binary tree is searched for matches and is re-rooted at the\n   current position.\n\n   If less than MAX_TREE_COMP_LENGTH data is available, the hash bucket of the\n   current position is searched for matches, but the state of the hash table\n   is not changed, since we can not know the final sorting order of the\n   current (incomplete) sequence.\n\n   This function must be called with increasing cur_ix positions. */\nstatic BROTLI_INLINE BackwardMatch* FN(StoreAndFindMatches)(\n    HashToBinaryTree* BROTLI_RESTRICT self, const uint8_t* BROTLI_RESTRICT data,\n    const size_t cur_ix, const size_t ring_buffer_mask, const size_t max_length,\n    const size_t max_backward, size_t* const BROTLI_RESTRICT best_len,\n    BackwardMatch* BROTLI_RESTRICT matches) {\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  const size_t max_comp_len =\n      BROTLI_MIN(size_t, max_length, MAX_TREE_COMP_LENGTH);\n  const BROTLI_BOOL should_reroot_tree =\n      TO_BROTLI_BOOL(max_length >= MAX_TREE_COMP_LENGTH);\n  const uint32_t key = FN(HashBytes)(&data[cur_ix_masked]);\n  uint32_t* BROTLI_RESTRICT buckets = self->buckets_;\n  uint32_t* BROTLI_RESTRICT forest = self->forest_;\n  size_t prev_ix = buckets[key];\n  /* The forest index of the rightmost node of the left subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t node_left = FN(LeftChildIndex)(self, cur_ix);\n  /* The forest index of the leftmost node of the right subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t node_right = FN(RightChildIndex)(self, cur_ix);\n  /* The match length of the rightmost node of the left subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t best_len_left = 0;\n  /* The match length of the leftmost node of the right subtree of the new\n     root, updated as we traverse and re-root the tree of the hash bucket. */\n  size_t best_len_right = 0;\n  size_t depth_remaining;\n  if (should_reroot_tree) {\n    buckets[key] = (uint32_t)cur_ix;\n  }\n  for (depth_remaining = MAX_TREE_SEARCH_DEPTH; ; --depth_remaining) {\n    const size_t backward = cur_ix - prev_ix;\n    const size_t prev_ix_masked = prev_ix & ring_buffer_mask;\n    if (backward == 0 || backward > max_backward || depth_remaining == 0) {\n      if (should_reroot_tree) {\n        forest[node_left] = self->invalid_pos_;\n        forest[node_right] = self->invalid_pos_;\n      }\n      break;\n    }\n    {\n      const size_t cur_len = BROTLI_MIN(size_t, best_len_left, best_len_right);\n      size_t len;\n      BROTLI_DCHECK(cur_len <= MAX_TREE_COMP_LENGTH);\n      len = cur_len +\n          FindMatchLengthWithLimit(&data[cur_ix_masked + cur_len],\n                                   &data[prev_ix_masked + cur_len],\n                                   max_length - cur_len);\n      BROTLI_DCHECK(\n          0 == memcmp(&data[cur_ix_masked], &data[prev_ix_masked], len));\n      if (matches && len > *best_len) {\n        *best_len = len;\n        InitBackwardMatch(matches++, backward, len);\n      }\n      if (len >= max_comp_len) {\n        if (should_reroot_tree) {\n          forest[node_left] = forest[FN(LeftChildIndex)(self, prev_ix)];\n          forest[node_right] = forest[FN(RightChildIndex)(self, prev_ix)];\n        }\n        break;\n      }\n      if (data[cur_ix_masked + len] > data[prev_ix_masked + len]) {\n        best_len_left = len;\n        if (should_reroot_tree) {\n          forest[node_left] = (uint32_t)prev_ix;\n        }\n        node_left = FN(RightChildIndex)(self, prev_ix);\n        prev_ix = forest[node_left];\n      } else {\n        best_len_right = len;\n        if (should_reroot_tree) {\n          forest[node_right] = (uint32_t)prev_ix;\n        }\n        node_right = FN(LeftChildIndex)(self, prev_ix);\n        prev_ix = forest[node_right];\n      }\n    }\n  }\n  return matches;\n}\n\n/* Finds all backward matches of &data[cur_ix & ring_buffer_mask] up to the\n   length of max_length and stores the position cur_ix in the hash table.\n\n   Sets *num_matches to the number of matches found, and stores the found\n   matches in matches[0] to matches[*num_matches - 1]. The matches will be\n   sorted by strictly increasing length and (non-strictly) increasing\n   distance. */\nstatic BROTLI_INLINE size_t FN(FindAllMatches)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* BROTLI_RESTRICT data,\n    const size_t ring_buffer_mask, const size_t cur_ix,\n    const size_t max_length, const size_t max_backward,\n    const size_t dictionary_distance, const BrotliEncoderParams* params,\n    BackwardMatch* matches) {\n  BackwardMatch* const orig_matches = matches;\n  const size_t cur_ix_masked = cur_ix & ring_buffer_mask;\n  size_t best_len = 1;\n  const size_t short_match_max_backward =\n      params->quality != HQ_ZOPFLIFICATION_QUALITY ? 16 : 64;\n  size_t stop = cur_ix - short_match_max_backward;\n  uint32_t dict_matches[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1];\n  size_t i;\n  if (cur_ix < short_match_max_backward) { stop = 0; }\n  for (i = cur_ix - 1; i > stop && best_len <= 2; --i) {\n    size_t prev_ix = i;\n    const size_t backward = cur_ix - prev_ix;\n    if (BROTLI_PREDICT_FALSE(backward > max_backward)) {\n      break;\n    }\n    prev_ix &= ring_buffer_mask;\n    if (data[cur_ix_masked] != data[prev_ix] ||\n        data[cur_ix_masked + 1] != data[prev_ix + 1]) {\n      continue;\n    }\n    {\n      const size_t len =\n          FindMatchLengthWithLimit(&data[prev_ix], &data[cur_ix_masked],\n                                   max_length);\n      if (len > best_len) {\n        best_len = len;\n        InitBackwardMatch(matches++, backward, len);\n      }\n    }\n  }\n  if (best_len < max_length) {\n    matches = FN(StoreAndFindMatches)(self, data, cur_ix,\n        ring_buffer_mask, max_length, max_backward, &best_len, matches);\n  }\n  for (i = 0; i <= BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN; ++i) {\n    dict_matches[i] = kInvalidMatch;\n  }\n  {\n    size_t minlen = BROTLI_MAX(size_t, 4, best_len + 1);\n    if (BrotliFindAllStaticDictionaryMatches(dictionary,\n        &data[cur_ix_masked], minlen, max_length, &dict_matches[0])) {\n      size_t maxlen = BROTLI_MIN(\n          size_t, BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN, max_length);\n      size_t l;\n      for (l = minlen; l <= maxlen; ++l) {\n        uint32_t dict_id = dict_matches[l];\n        if (dict_id < kInvalidMatch) {\n          size_t distance = dictionary_distance + (dict_id >> 5) + 1;\n          if (distance <= params->dist.max_distance) {\n            InitDictionaryBackwardMatch(matches++, distance, l, dict_id & 31);\n          }\n        }\n      }\n    }\n  }\n  return (size_t)(matches - orig_matches);\n}\n\n/* Stores the hash of the next 4 bytes and re-roots the binary tree at the\n   current sequence, without returning any matches.\n   REQUIRES: ix + MAX_TREE_COMP_LENGTH <= end-of-current-block */\nstatic BROTLI_INLINE void FN(Store)(HashToBinaryTree* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data,\n    const size_t mask, const size_t ix) {\n  /* Maximum distance is window size - 16, see section 9.1. of the spec. */\n  const size_t max_backward = self->window_mask_ - BROTLI_WINDOW_GAP + 1;\n  FN(StoreAndFindMatches)(self, data, ix, mask, MAX_TREE_COMP_LENGTH,\n      max_backward, NULL, NULL);\n}\n\nstatic BROTLI_INLINE void FN(StoreRange)(HashToBinaryTree* BROTLI_RESTRICT self,\n    const uint8_t* BROTLI_RESTRICT data, const size_t mask,\n    const size_t ix_start, const size_t ix_end) {\n  size_t i = ix_start;\n  size_t j = ix_start;\n  if (ix_start + 63 <= ix_end) {\n    i = ix_end - 63;\n  }\n  if (ix_start + 512 <= i) {\n    for (; j < i; j += 8) {\n      FN(Store)(self, data, mask, j);\n    }\n  }\n  for (; i < ix_end; ++i) {\n    FN(Store)(self, data, mask, i);\n  }\n}\n\nstatic BROTLI_INLINE void FN(StitchToPreviousBlock)(\n    HashToBinaryTree* BROTLI_RESTRICT self,\n    size_t num_bytes, size_t position, const uint8_t* ringbuffer,\n    size_t ringbuffer_mask) {\n  if (num_bytes >= FN(HashTypeLength)() - 1 &&\n      position >= MAX_TREE_COMP_LENGTH) {\n    /* Store the last `MAX_TREE_COMP_LENGTH - 1` positions in the hasher.\n       These could not be calculated before, since they require knowledge\n       of both the previous and the current block. */\n    const size_t i_start = position - MAX_TREE_COMP_LENGTH + 1;\n    const size_t i_end = BROTLI_MIN(size_t, position, i_start + num_bytes);\n    size_t i;\n    for (i = i_start; i < i_end; ++i) {\n      /* Maximum distance is window size - 16, see section 9.1. of the spec.\n         Furthermore, we have to make sure that we don't look further back\n         from the start of the next block than the window size, otherwise we\n         could access already overwritten areas of the ring-buffer. */\n      const size_t max_backward =\n          self->window_mask_ - BROTLI_MAX(size_t,\n                                          BROTLI_WINDOW_GAP - 1,\n                                          position - i);\n      /* We know that i + MAX_TREE_COMP_LENGTH <= position + num_bytes, i.e. the\n         end of the current block and that we have at least\n         MAX_TREE_COMP_LENGTH tail in the ring-buffer. */\n      FN(StoreAndFindMatches)(self, ringbuffer, i, ringbuffer_mask,\n          MAX_TREE_COMP_LENGTH, max_backward, NULL, NULL);\n    }\n  }\n}\n\n#undef BUCKET_SIZE\n\n#undef HashToBinaryTree\n"
  },
  {
    "path": "third-party/brotli/enc/histogram.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Build per-context histograms of literals, commands and distance codes. */\n\n#include \"histogram.h\"\n\n#include \"../common/context.h\"\n#include \"block_splitter.h\"\n#include \"command.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct BlockSplitIterator {\n  const BlockSplit* split_;  /* Not owned. */\n  size_t idx_;\n  size_t type_;\n  size_t length_;\n} BlockSplitIterator;\n\nstatic void InitBlockSplitIterator(BlockSplitIterator* self,\n    const BlockSplit* split) {\n  self->split_ = split;\n  self->idx_ = 0;\n  self->type_ = 0;\n  self->length_ = split->lengths ? split->lengths[0] : 0;\n}\n\nstatic void BlockSplitIteratorNext(BlockSplitIterator* self) {\n  if (self->length_ == 0) {\n    ++self->idx_;\n    self->type_ = self->split_->types[self->idx_];\n    self->length_ = self->split_->lengths[self->idx_];\n  }\n  --self->length_;\n}\n\nvoid BrotliBuildHistogramsWithContext(\n    const Command* cmds, const size_t num_commands,\n    const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split,\n    const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t start_pos,\n    size_t mask, uint8_t prev_byte, uint8_t prev_byte2,\n    const ContextType* context_modes, HistogramLiteral* literal_histograms,\n    HistogramCommand* insert_and_copy_histograms,\n    HistogramDistance* copy_dist_histograms) {\n  size_t pos = start_pos;\n  BlockSplitIterator literal_it;\n  BlockSplitIterator insert_and_copy_it;\n  BlockSplitIterator dist_it;\n  size_t i;\n\n  InitBlockSplitIterator(&literal_it, literal_split);\n  InitBlockSplitIterator(&insert_and_copy_it, insert_and_copy_split);\n  InitBlockSplitIterator(&dist_it, dist_split);\n  for (i = 0; i < num_commands; ++i) {\n    const Command* cmd = &cmds[i];\n    size_t j;\n    BlockSplitIteratorNext(&insert_and_copy_it);\n    HistogramAddCommand(&insert_and_copy_histograms[insert_and_copy_it.type_],\n        cmd->cmd_prefix_);\n    /* TODO(eustas): unwrap iterator blocks. */\n    for (j = cmd->insert_len_; j != 0; --j) {\n      size_t context;\n      BlockSplitIteratorNext(&literal_it);\n      context = literal_it.type_;\n      if (context_modes) {\n        ContextLut lut = BROTLI_CONTEXT_LUT(context_modes[context]);\n        context = (context << BROTLI_LITERAL_CONTEXT_BITS) +\n            BROTLI_CONTEXT(prev_byte, prev_byte2, lut);\n      }\n      HistogramAddLiteral(&literal_histograms[context],\n          ringbuffer[pos & mask]);\n      prev_byte2 = prev_byte;\n      prev_byte = ringbuffer[pos & mask];\n      ++pos;\n    }\n    pos += CommandCopyLen(cmd);\n    if (CommandCopyLen(cmd)) {\n      prev_byte2 = ringbuffer[(pos - 2) & mask];\n      prev_byte = ringbuffer[(pos - 1) & mask];\n      if (cmd->cmd_prefix_ >= 128) {\n        size_t context;\n        BlockSplitIteratorNext(&dist_it);\n        context = (dist_it.type_ << BROTLI_DISTANCE_CONTEXT_BITS) +\n            CommandDistanceContext(cmd);\n        HistogramAddDistance(&copy_dist_histograms[context],\n            cmd->dist_prefix_ & 0x3FF);\n      }\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/histogram.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Models the histograms of literals, commands and distance codes. */\n\n#ifndef BROTLI_ENC_HISTOGRAM_H_\n#define BROTLI_ENC_HISTOGRAM_H_\n\n#include <string.h>  /* memset */\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"block_splitter.h\"\n#include \"command.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* The distance symbols effectively used by \"Large Window Brotli\" (32-bit). */\n#define BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS 544\n\n#define FN(X) X ## Literal\n#define DATA_SIZE BROTLI_NUM_LITERAL_SYMBOLS\n#define DataType uint8_t\n#include \"histogram_inc.h\"  /* NOLINT(build/include) */\n#undef DataType\n#undef DATA_SIZE\n#undef FN\n\n#define FN(X) X ## Command\n#define DataType uint16_t\n#define DATA_SIZE BROTLI_NUM_COMMAND_SYMBOLS\n#include \"histogram_inc.h\"  /* NOLINT(build/include) */\n#undef DATA_SIZE\n#undef FN\n\n#define FN(X) X ## Distance\n#define DATA_SIZE BROTLI_NUM_HISTOGRAM_DISTANCE_SYMBOLS\n#include \"histogram_inc.h\"  /* NOLINT(build/include) */\n#undef DataType\n#undef DATA_SIZE\n#undef FN\n\nBROTLI_INTERNAL void BrotliBuildHistogramsWithContext(\n    const Command* cmds, const size_t num_commands,\n    const BlockSplit* literal_split, const BlockSplit* insert_and_copy_split,\n    const BlockSplit* dist_split, const uint8_t* ringbuffer, size_t pos,\n    size_t mask, uint8_t prev_byte, uint8_t prev_byte2,\n    const ContextType* context_modes, HistogramLiteral* literal_histograms,\n    HistogramCommand* insert_and_copy_histograms,\n    HistogramDistance* copy_dist_histograms);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_HISTOGRAM_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/histogram_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: Histogram, DATA_SIZE, DataType */\n\n/* A simple container for histograms of data in blocks. */\n\ntypedef struct FN(Histogram) {\n  uint32_t data_[DATA_SIZE];\n  size_t total_count_;\n  double bit_cost_;\n} FN(Histogram);\n\nstatic BROTLI_INLINE void FN(HistogramClear)(FN(Histogram)* self) {\n  memset(self->data_, 0, sizeof(self->data_));\n  self->total_count_ = 0;\n  self->bit_cost_ = HUGE_VAL;\n}\n\nstatic BROTLI_INLINE void FN(ClearHistograms)(\n    FN(Histogram)* array, size_t length) {\n  size_t i;\n  for (i = 0; i < length; ++i) FN(HistogramClear)(array + i);\n}\n\nstatic BROTLI_INLINE void FN(HistogramAdd)(FN(Histogram)* self, size_t val) {\n  ++self->data_[val];\n  ++self->total_count_;\n}\n\nstatic BROTLI_INLINE void FN(HistogramAddVector)(FN(Histogram)* self,\n    const DataType* p, size_t n) {\n  self->total_count_ += n;\n  n += 1;\n  while (--n) ++self->data_[*p++];\n}\n\nstatic BROTLI_INLINE void FN(HistogramAddHistogram)(FN(Histogram)* self,\n    const FN(Histogram)* v) {\n  size_t i;\n  self->total_count_ += v->total_count_;\n  for (i = 0; i < DATA_SIZE; ++i) {\n    self->data_[i] += v->data_[i];\n  }\n}\n\nstatic BROTLI_INLINE size_t FN(HistogramDataSize)(void) { return DATA_SIZE; }\n"
  },
  {
    "path": "third-party/brotli/enc/literal_cost.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Literal cost model to allow backward reference replacement to be efficient.\n*/\n\n#include \"literal_cost.h\"\n\n#include <string.h>  /* memset */\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n#include \"utf8_util.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic size_t UTF8Position(size_t last, size_t c, size_t clamp) {\n  if (c < 128) {\n    return 0;  /* Next one is the 'Byte 1' again. */\n  } else if (c >= 192) {  /* Next one is the 'Byte 2' of utf-8 encoding. */\n    return BROTLI_MIN(size_t, 1, clamp);\n  } else {\n    /* Let's decide over the last byte if this ends the sequence. */\n    if (last < 0xE0) {\n      return 0;  /* Completed two or three byte coding. */\n    } else {  /* Next one is the 'Byte 3' of utf-8 encoding. */\n      return BROTLI_MIN(size_t, 2, clamp);\n    }\n  }\n}\n\nstatic size_t DecideMultiByteStatsLevel(size_t pos, size_t len, size_t mask,\n                                        const uint8_t* data) {\n  size_t counts[3] = { 0 };\n  size_t max_utf8 = 1;  /* should be 2, but 1 compresses better. */\n  size_t last_c = 0;\n  size_t i;\n  for (i = 0; i < len; ++i) {\n    size_t c = data[(pos + i) & mask];\n    ++counts[UTF8Position(last_c, c, 2)];\n    last_c = c;\n  }\n  if (counts[2] < 500) {\n    max_utf8 = 1;\n  }\n  if (counts[1] + counts[2] < 25) {\n    max_utf8 = 0;\n  }\n  return max_utf8;\n}\n\nstatic void EstimateBitCostsForLiteralsUTF8(size_t pos, size_t len, size_t mask,\n                                            const uint8_t* data,\n                                            size_t* histogram, float* cost) {\n  /* max_utf8 is 0 (normal ASCII single byte modeling),\n     1 (for 2-byte UTF-8 modeling), or 2 (for 3-byte UTF-8 modeling). */\n  const size_t max_utf8 = DecideMultiByteStatsLevel(pos, len, mask, data);\n  size_t window_half = 495;\n  size_t in_window = BROTLI_MIN(size_t, window_half, len);\n  size_t in_window_utf8[3] = { 0 };\n  size_t i;\n  memset(histogram, 0, 3 * 256 * sizeof(histogram[0]));\n\n  {  /* Bootstrap histograms. */\n    size_t last_c = 0;\n    size_t utf8_pos = 0;\n    for (i = 0; i < in_window; ++i) {\n      size_t c = data[(pos + i) & mask];\n      ++histogram[256 * utf8_pos + c];\n      ++in_window_utf8[utf8_pos];\n      utf8_pos = UTF8Position(last_c, c, max_utf8);\n      last_c = c;\n    }\n  }\n\n  /* Compute bit costs with sliding window. */\n  for (i = 0; i < len; ++i) {\n    if (i >= window_half) {\n      /* Remove a byte in the past. */\n      size_t c =\n          i < window_half + 1 ? 0 : data[(pos + i - window_half - 1) & mask];\n      size_t last_c =\n          i < window_half + 2 ? 0 : data[(pos + i - window_half - 2) & mask];\n      size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8);\n      --histogram[256 * utf8_pos2 + data[(pos + i - window_half) & mask]];\n      --in_window_utf8[utf8_pos2];\n    }\n    if (i + window_half < len) {\n      /* Add a byte in the future. */\n      size_t c = data[(pos + i + window_half - 1) & mask];\n      size_t last_c = data[(pos + i + window_half - 2) & mask];\n      size_t utf8_pos2 = UTF8Position(last_c, c, max_utf8);\n      ++histogram[256 * utf8_pos2 + data[(pos + i + window_half) & mask]];\n      ++in_window_utf8[utf8_pos2];\n    }\n    {\n      size_t c = i < 1 ? 0 : data[(pos + i - 1) & mask];\n      size_t last_c = i < 2 ? 0 : data[(pos + i - 2) & mask];\n      size_t utf8_pos = UTF8Position(last_c, c, max_utf8);\n      size_t masked_pos = (pos + i) & mask;\n      size_t histo = histogram[256 * utf8_pos + data[masked_pos]];\n      double lit_cost;\n      if (histo == 0) {\n        histo = 1;\n      }\n      lit_cost = FastLog2(in_window_utf8[utf8_pos]) - FastLog2(histo);\n      lit_cost += 0.02905;\n      if (lit_cost < 1.0) {\n        lit_cost *= 0.5;\n        lit_cost += 0.5;\n      }\n      /* Make the first bytes more expensive -- seems to help, not sure why.\n         Perhaps because the entropy source is changing its properties\n         rapidly in the beginning of the file, perhaps because the beginning\n         of the data is a statistical \"anomaly\". */\n      if (i < 2000) {\n        lit_cost += 0.7 - ((double)(2000 - i) / 2000.0 * 0.35);\n      }\n      cost[i] = (float)lit_cost;\n    }\n  }\n}\n\nvoid BrotliEstimateBitCostsForLiterals(size_t pos, size_t len, size_t mask,\n                                       const uint8_t* data,\n                                       size_t* histogram, float* cost) {\n  if (BrotliIsMostlyUTF8(data, pos, mask, len, kMinUTF8Ratio)) {\n    EstimateBitCostsForLiteralsUTF8(pos, len, mask, data, histogram, cost);\n    return;\n  } else {\n    size_t window_half = 2000;\n    size_t in_window = BROTLI_MIN(size_t, window_half, len);\n    size_t i;\n    memset(histogram, 0, 256 * sizeof(histogram[0]));\n\n    /* Bootstrap histogram. */\n    for (i = 0; i < in_window; ++i) {\n      ++histogram[data[(pos + i) & mask]];\n    }\n\n    /* Compute bit costs with sliding window. */\n    for (i = 0; i < len; ++i) {\n      size_t histo;\n      if (i >= window_half) {\n        /* Remove a byte in the past. */\n        --histogram[data[(pos + i - window_half) & mask]];\n        --in_window;\n      }\n      if (i + window_half < len) {\n        /* Add a byte in the future. */\n        ++histogram[data[(pos + i + window_half) & mask]];\n        ++in_window;\n      }\n      histo = histogram[data[(pos + i) & mask]];\n      if (histo == 0) {\n        histo = 1;\n      }\n      {\n        double lit_cost = FastLog2(in_window) - FastLog2(histo);\n        lit_cost += 0.029;\n        if (lit_cost < 1.0) {\n          lit_cost *= 0.5;\n          lit_cost += 0.5;\n        }\n        cost[i] = (float)lit_cost;\n      }\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/literal_cost.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Literal cost model to allow backward reference replacement to be efficient.\n*/\n\n#ifndef BROTLI_ENC_LITERAL_COST_H_\n#define BROTLI_ENC_LITERAL_COST_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Estimates how many bits the literals in the interval [pos, pos + len) in the\n   ring-buffer (data, mask) will take entropy coded and writes these estimates\n   to the cost[0..len) array. */\nBROTLI_INTERNAL void BrotliEstimateBitCostsForLiterals(\n    size_t pos, size_t len, size_t mask, const uint8_t* data, size_t* histogram,\n    float* cost);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_LITERAL_COST_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/memory.c",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Algorithms for distributing the literals and commands of a metablock between\n   block types and contexts. */\n\n#include \"memory.h\"\n\n#include <stdlib.h>  /* exit, free, malloc */\n#include <string.h>  /* memcpy */\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define MAX_NEW_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2)\n#define MAX_NEW_FREED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 2)\n#define MAX_PERM_ALLOCATED (BROTLI_ENCODER_MEMORY_MANAGER_SLOTS >> 1)\n\n#define PERM_ALLOCATED_OFFSET 0\n#define NEW_ALLOCATED_OFFSET MAX_PERM_ALLOCATED\n#define NEW_FREED_OFFSET (MAX_PERM_ALLOCATED + MAX_NEW_ALLOCATED)\n\nvoid BrotliInitMemoryManager(\n    MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func,\n    void* opaque) {\n  if (!alloc_func) {\n    m->alloc_func = BrotliDefaultAllocFunc;\n    m->free_func = BrotliDefaultFreeFunc;\n    m->opaque = 0;\n  } else {\n    m->alloc_func = alloc_func;\n    m->free_func = free_func;\n    m->opaque = opaque;\n  }\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n  m->is_oom = BROTLI_FALSE;\n  m->perm_allocated = 0;\n  m->new_allocated = 0;\n  m->new_freed = 0;\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n}\n\n#if defined(BROTLI_ENCODER_EXIT_ON_OOM)\n\nvoid* BrotliAllocate(MemoryManager* m, size_t n) {\n  void* result = m->alloc_func(m->opaque, n);\n  if (!result) exit(EXIT_FAILURE);\n  return result;\n}\n\nvoid BrotliFree(MemoryManager* m, void* p) {\n  m->free_func(m->opaque, p);\n}\n\nvoid BrotliWipeOutMemoryManager(MemoryManager* m) {\n  BROTLI_UNUSED(m);\n}\n\n#else  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\nstatic void SortPointers(void** items, const size_t n) {\n  /* Shell sort. */\n  /* TODO(eustas): fine-tune for \"many slots\" case */\n  static const size_t gaps[] = {23, 10, 4, 1};\n  int g = 0;\n  for (; g < 4; ++g) {\n    size_t gap = gaps[g];\n    size_t i;\n    for (i = gap; i < n; ++i) {\n      size_t j = i;\n      void* tmp = items[i];\n      for (; j >= gap && tmp < items[j - gap]; j -= gap) {\n        items[j] = items[j - gap];\n      }\n      items[j] = tmp;\n    }\n  }\n}\n\nstatic size_t Annihilate(void** a, size_t a_len, void** b, size_t b_len) {\n  size_t a_read_index = 0;\n  size_t b_read_index = 0;\n  size_t a_write_index = 0;\n  size_t b_write_index = 0;\n  size_t annihilated = 0;\n  while (a_read_index < a_len && b_read_index < b_len) {\n    if (a[a_read_index] == b[b_read_index]) {\n      a_read_index++;\n      b_read_index++;\n      annihilated++;\n    } else if (a[a_read_index] < b[b_read_index]) {\n      a[a_write_index++] = a[a_read_index++];\n    } else {\n      b[b_write_index++] = b[b_read_index++];\n    }\n  }\n  while (a_read_index < a_len) a[a_write_index++] = a[a_read_index++];\n  while (b_read_index < b_len) b[b_write_index++] = b[b_read_index++];\n  return annihilated;\n}\n\nstatic void CollectGarbagePointers(MemoryManager* m) {\n  size_t annihilated;\n  SortPointers(m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated);\n  SortPointers(m->pointers + NEW_FREED_OFFSET, m->new_freed);\n  annihilated = Annihilate(\n      m->pointers + NEW_ALLOCATED_OFFSET, m->new_allocated,\n      m->pointers + NEW_FREED_OFFSET, m->new_freed);\n  m->new_allocated -= annihilated;\n  m->new_freed -= annihilated;\n\n  if (m->new_freed != 0) {\n    annihilated = Annihilate(\n        m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated,\n        m->pointers + NEW_FREED_OFFSET, m->new_freed);\n    m->perm_allocated -= annihilated;\n    m->new_freed -= annihilated;\n    BROTLI_DCHECK(m->new_freed == 0);\n  }\n\n  if (m->new_allocated != 0) {\n    BROTLI_DCHECK(m->perm_allocated + m->new_allocated <= MAX_PERM_ALLOCATED);\n    memcpy(m->pointers + PERM_ALLOCATED_OFFSET + m->perm_allocated,\n           m->pointers + NEW_ALLOCATED_OFFSET,\n           sizeof(void*) * m->new_allocated);\n    m->perm_allocated += m->new_allocated;\n    m->new_allocated = 0;\n    SortPointers(m->pointers + PERM_ALLOCATED_OFFSET, m->perm_allocated);\n  }\n}\n\nvoid* BrotliAllocate(MemoryManager* m, size_t n) {\n  void* result = m->alloc_func(m->opaque, n);\n  if (!result) {\n    m->is_oom = BROTLI_TRUE;\n    return NULL;\n  }\n  if (m->new_allocated == MAX_NEW_ALLOCATED) CollectGarbagePointers(m);\n  m->pointers[NEW_ALLOCATED_OFFSET + (m->new_allocated++)] = result;\n  return result;\n}\n\nvoid BrotliFree(MemoryManager* m, void* p) {\n  if (!p) return;\n  m->free_func(m->opaque, p);\n  if (m->new_freed == MAX_NEW_FREED) CollectGarbagePointers(m);\n  m->pointers[NEW_FREED_OFFSET + (m->new_freed++)] = p;\n}\n\nvoid BrotliWipeOutMemoryManager(MemoryManager* m) {\n  size_t i;\n  CollectGarbagePointers(m);\n  /* Now all unfreed pointers are in perm-allocated list. */\n  for (i = 0; i < m->perm_allocated; ++i) {\n    m->free_func(m->opaque, m->pointers[PERM_ALLOCATED_OFFSET + i]);\n  }\n  m->perm_allocated = 0;\n}\n\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\nvoid* BrotliBootstrapAlloc(size_t size,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque) {\n  if (!alloc_func && !free_func) {\n    return malloc(size);\n  } else if (alloc_func && free_func) {\n    return alloc_func(opaque, size);\n  }\n  return NULL;\n}\n\nvoid BrotliBootstrapFree(void* address, MemoryManager* m) {\n  if (!address) {\n    /* Should not happen! */\n    return;\n  } else {\n    /* Copy values, as those would be freed. */\n    brotli_free_func free_func = m->free_func;\n    void* opaque = m->opaque;\n    free_func(opaque, address);\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/memory.h",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Macros for memory management. */\n\n#ifndef BROTLI_ENC_MEMORY_H_\n#define BROTLI_ENC_MEMORY_H_\n\n#include <string.h>  /* memcpy */\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#if !defined(BROTLI_ENCODER_CLEANUP_ON_OOM) && \\\n    !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#define BROTLI_ENCODER_EXIT_ON_OOM\n#endif\n\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#if defined(BROTLI_EXPERIMENTAL)\n#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 32768\n#else  /* BROTLI_EXPERIMENTAL */\n#define BROTLI_ENCODER_MEMORY_MANAGER_SLOTS 256\n#endif  /* BROTLI_EXPERIMENTAL */\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\ntypedef struct MemoryManager {\n  brotli_alloc_func alloc_func;\n  brotli_free_func free_func;\n  void* opaque;\n#if !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n  BROTLI_BOOL is_oom;\n  size_t perm_allocated;\n  size_t new_allocated;\n  size_t new_freed;\n  void* pointers[BROTLI_ENCODER_MEMORY_MANAGER_SLOTS];\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n} MemoryManager;\n\nBROTLI_INTERNAL void BrotliInitMemoryManager(\n    MemoryManager* m, brotli_alloc_func alloc_func, brotli_free_func free_func,\n    void* opaque);\n\nBROTLI_INTERNAL void* BrotliAllocate(MemoryManager* m, size_t n);\n#define BROTLI_ALLOC(M, T, N)                               \\\n  ((N) > 0 ? ((T*)BrotliAllocate((M), (N) * sizeof(T))) : NULL)\n\nBROTLI_INTERNAL void BrotliFree(MemoryManager* m, void* p);\n#define BROTLI_FREE(M, P) { \\\n  BrotliFree((M), (P));     \\\n  P = NULL;                 \\\n}\n\n#if defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#define BROTLI_IS_OOM(M) (!!0)\n#else  /* BROTLI_ENCODER_EXIT_ON_OOM */\n#define BROTLI_IS_OOM(M) (!!(M)->is_oom)\n#endif  /* BROTLI_ENCODER_EXIT_ON_OOM */\n\n/*\nBROTLI_IS_NULL is a fake check, BROTLI_IS_OOM does the heavy lifting.\nThe only purpose of it is to explain static analyzers the state of things.\nNB: use ONLY together with BROTLI_IS_OOM\n    AND ONLY for allocations in the current scope.\n */\n#if defined(__clang_analyzer__) && !defined(BROTLI_ENCODER_EXIT_ON_OOM)\n#define BROTLI_IS_NULL(A) ((A) == nullptr)\n#else  /* defined(__clang_analyzer__) */\n#define BROTLI_IS_NULL(A) (!!0)\n#endif  /* defined(__clang_analyzer__) */\n\nBROTLI_INTERNAL void BrotliWipeOutMemoryManager(MemoryManager* m);\n\n/*\nDynamically grows array capacity to at least the requested size\nM: MemoryManager\nT: data type\nA: array\nC: capacity\nR: requested size\n*/\n#define BROTLI_ENSURE_CAPACITY(M, T, A, C, R) {                    \\\n  if (C < (R)) {                                                   \\\n    size_t _new_size = (C == 0) ? (R) : C;                         \\\n    T* new_array;                                                  \\\n    while (_new_size < (R)) _new_size *= 2;                        \\\n    new_array = BROTLI_ALLOC((M), T, _new_size);                   \\\n    if (!BROTLI_IS_OOM(M) && !BROTLI_IS_NULL(new_array) && C != 0) \\\n      memcpy(new_array, A, C * sizeof(T));                         \\\n    BROTLI_FREE((M), A);                                           \\\n    A = new_array;                                                 \\\n    C = _new_size;                                                 \\\n  }                                                                \\\n}\n\n/*\nAppends value and dynamically grows array capacity when needed\nM: MemoryManager\nT: data type\nA: array\nC: array capacity\nS: array size\nV: value to append\n*/\n#define BROTLI_ENSURE_CAPACITY_APPEND(M, T, A, C, S, V) { \\\n  (S)++;                                                  \\\n  BROTLI_ENSURE_CAPACITY(M, T, A, C, S);                  \\\n  A[(S) - 1] = (V);                                       \\\n}\n\n/* \"Bootstrap\" allocations are not tracked by memory manager; should be used\n   only to allocate MemoryManager itself (or structure containing it). */\nBROTLI_INTERNAL void* BrotliBootstrapAlloc(size_t size,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\nBROTLI_INTERNAL void BrotliBootstrapFree(void* address, MemoryManager* m);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_MEMORY_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/metablock.c",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Algorithms for distributing the literals and commands of a metablock between\n   block types and contexts. */\n\n#include \"metablock.h\"\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"bit_cost.h\"\n#include \"block_splitter.h\"\n#include \"cluster.h\"\n#include \"entropy_encode.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nvoid BrotliInitDistanceParams(BrotliDistanceParams* dist_params,\n    uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window) {\n  uint32_t alphabet_size_max;\n  uint32_t alphabet_size_limit;\n  uint32_t max_distance;\n\n  dist_params->distance_postfix_bits = npostfix;\n  dist_params->num_direct_distance_codes = ndirect;\n\n  alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n      npostfix, ndirect, BROTLI_MAX_DISTANCE_BITS);\n  alphabet_size_limit = alphabet_size_max;\n  max_distance = ndirect + (1U << (BROTLI_MAX_DISTANCE_BITS + npostfix + 2)) -\n      (1U << (npostfix + 2));\n\n  if (large_window) {\n    BrotliDistanceCodeLimit limit = BrotliCalculateDistanceCodeLimit(\n        BROTLI_MAX_ALLOWED_DISTANCE, npostfix, ndirect);\n    alphabet_size_max = BROTLI_DISTANCE_ALPHABET_SIZE(\n        npostfix, ndirect, BROTLI_LARGE_MAX_DISTANCE_BITS);\n    alphabet_size_limit = limit.max_alphabet_size;\n    max_distance = limit.max_distance;\n  }\n\n  dist_params->alphabet_size_max = alphabet_size_max;\n  dist_params->alphabet_size_limit = alphabet_size_limit;\n  dist_params->max_distance = max_distance;\n}\n\nstatic void RecomputeDistancePrefixes(Command* cmds,\n                                      size_t num_commands,\n                                      const BrotliDistanceParams* orig_params,\n                                      const BrotliDistanceParams* new_params) {\n  size_t i;\n\n  if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&\n      orig_params->num_direct_distance_codes ==\n      new_params->num_direct_distance_codes) {\n    return;\n  }\n\n  for (i = 0; i < num_commands; ++i) {\n    Command* cmd = &cmds[i];\n    if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\n      PrefixEncodeCopyDistance(CommandRestoreDistanceCode(cmd, orig_params),\n                               new_params->num_direct_distance_codes,\n                               new_params->distance_postfix_bits,\n                               &cmd->dist_prefix_,\n                               &cmd->dist_extra_);\n    }\n  }\n}\n\nstatic BROTLI_BOOL ComputeDistanceCost(const Command* cmds,\n                                       size_t num_commands,\n                                       const BrotliDistanceParams* orig_params,\n                                       const BrotliDistanceParams* new_params,\n                                       double* cost,\n                                       HistogramDistance* tmp) {\n  size_t i;\n  BROTLI_BOOL equal_params = BROTLI_FALSE;\n  uint16_t dist_prefix;\n  uint32_t dist_extra;\n  double extra_bits = 0.0;\n  HistogramClearDistance(tmp);\n\n  if (orig_params->distance_postfix_bits == new_params->distance_postfix_bits &&\n      orig_params->num_direct_distance_codes ==\n      new_params->num_direct_distance_codes) {\n    equal_params = BROTLI_TRUE;\n  }\n\n  for (i = 0; i < num_commands; i++) {\n    const Command* cmd = &cmds[i];\n    if (CommandCopyLen(cmd) && cmd->cmd_prefix_ >= 128) {\n      if (equal_params) {\n        dist_prefix = cmd->dist_prefix_;\n      } else {\n        uint32_t distance = CommandRestoreDistanceCode(cmd, orig_params);\n        if (distance > new_params->max_distance) {\n          return BROTLI_FALSE;\n        }\n        PrefixEncodeCopyDistance(distance,\n                                 new_params->num_direct_distance_codes,\n                                 new_params->distance_postfix_bits,\n                                 &dist_prefix,\n                                 &dist_extra);\n      }\n      HistogramAddDistance(tmp, dist_prefix & 0x3FF);\n      extra_bits += dist_prefix >> 10;\n    }\n  }\n\n  *cost = BrotliPopulationCostDistance(tmp) + extra_bits;\n  return BROTLI_TRUE;\n}\n\nvoid BrotliBuildMetaBlock(MemoryManager* m,\n                          const uint8_t* ringbuffer,\n                          const size_t pos,\n                          const size_t mask,\n                          BrotliEncoderParams* params,\n                          uint8_t prev_byte,\n                          uint8_t prev_byte2,\n                          Command* cmds,\n                          size_t num_commands,\n                          ContextType literal_context_mode,\n                          MetaBlockSplit* mb) {\n  /* Histogram ids need to fit in one byte. */\n  static const size_t kMaxNumberOfHistograms = 256;\n  HistogramDistance* distance_histograms;\n  HistogramLiteral* literal_histograms;\n  ContextType* literal_context_modes = NULL;\n  size_t literal_histograms_size;\n  size_t distance_histograms_size;\n  size_t i;\n  size_t literal_context_multiplier = 1;\n  uint32_t npostfix;\n  uint32_t ndirect_msb = 0;\n  BROTLI_BOOL check_orig = BROTLI_TRUE;\n  double best_dist_cost = 1e99;\n  BrotliDistanceParams orig_params = params->dist;\n  BrotliDistanceParams new_params = params->dist;\n  HistogramDistance* tmp = BROTLI_ALLOC(m, HistogramDistance, 1);\n\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(tmp)) return;\n\n  for (npostfix = 0; npostfix <= BROTLI_MAX_NPOSTFIX; npostfix++) {\n    for (; ndirect_msb < 16; ndirect_msb++) {\n      uint32_t ndirect = ndirect_msb << npostfix;\n      BROTLI_BOOL skip;\n      double dist_cost;\n      BrotliInitDistanceParams(&new_params, npostfix, ndirect,\n                               params->large_window);\n      if (npostfix == orig_params.distance_postfix_bits &&\n          ndirect == orig_params.num_direct_distance_codes) {\n        check_orig = BROTLI_FALSE;\n      }\n      skip = !ComputeDistanceCost(\n          cmds, num_commands, &orig_params, &new_params, &dist_cost, tmp);\n      if (skip || (dist_cost > best_dist_cost)) {\n        break;\n      }\n      best_dist_cost = dist_cost;\n      params->dist = new_params;\n    }\n    if (ndirect_msb > 0) ndirect_msb--;\n    ndirect_msb /= 2;\n  }\n  if (check_orig) {\n    double dist_cost;\n    ComputeDistanceCost(cmds, num_commands, &orig_params, &orig_params,\n                        &dist_cost, tmp);\n    if (dist_cost < best_dist_cost) {\n      /* NB: currently unused; uncomment when more param tuning is added. */\n      /* best_dist_cost = dist_cost; */\n      params->dist = orig_params;\n    }\n  }\n  BROTLI_FREE(m, tmp);\n  RecomputeDistancePrefixes(cmds, num_commands, &orig_params, &params->dist);\n\n  BrotliSplitBlock(m, cmds, num_commands,\n                   ringbuffer, pos, mask, params,\n                   &mb->literal_split,\n                   &mb->command_split,\n                   &mb->distance_split);\n  if (BROTLI_IS_OOM(m)) return;\n\n  if (!params->disable_literal_context_modeling) {\n    literal_context_multiplier = 1 << BROTLI_LITERAL_CONTEXT_BITS;\n    literal_context_modes =\n        BROTLI_ALLOC(m, ContextType, mb->literal_split.num_types);\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_context_modes)) return;\n    for (i = 0; i < mb->literal_split.num_types; ++i) {\n      literal_context_modes[i] = literal_context_mode;\n    }\n  }\n\n  literal_histograms_size =\n      mb->literal_split.num_types * literal_context_multiplier;\n  literal_histograms =\n      BROTLI_ALLOC(m, HistogramLiteral, literal_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(literal_histograms)) return;\n  ClearHistogramsLiteral(literal_histograms, literal_histograms_size);\n\n  distance_histograms_size =\n      mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;\n  distance_histograms =\n      BROTLI_ALLOC(m, HistogramDistance, distance_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(distance_histograms)) return;\n  ClearHistogramsDistance(distance_histograms, distance_histograms_size);\n\n  BROTLI_DCHECK(mb->command_histograms == 0);\n  mb->command_histograms_size = mb->command_split.num_types;\n  mb->command_histograms =\n      BROTLI_ALLOC(m, HistogramCommand, mb->command_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->command_histograms)) return;\n  ClearHistogramsCommand(mb->command_histograms, mb->command_histograms_size);\n\n  BrotliBuildHistogramsWithContext(cmds, num_commands,\n      &mb->literal_split, &mb->command_split, &mb->distance_split,\n      ringbuffer, pos, mask, prev_byte, prev_byte2, literal_context_modes,\n      literal_histograms, mb->command_histograms, distance_histograms);\n  BROTLI_FREE(m, literal_context_modes);\n\n  BROTLI_DCHECK(mb->literal_context_map == 0);\n  mb->literal_context_map_size =\n      mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;\n  mb->literal_context_map =\n      BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return;\n\n  BROTLI_DCHECK(mb->literal_histograms == 0);\n  mb->literal_histograms_size = mb->literal_context_map_size;\n  mb->literal_histograms =\n      BROTLI_ALLOC(m, HistogramLiteral, mb->literal_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_histograms)) return;\n\n  BrotliClusterHistogramsLiteral(m, literal_histograms, literal_histograms_size,\n      kMaxNumberOfHistograms, mb->literal_histograms,\n      &mb->literal_histograms_size, mb->literal_context_map);\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_FREE(m, literal_histograms);\n\n  if (params->disable_literal_context_modeling) {\n    /* Distribute assignment to all contexts. */\n    for (i = mb->literal_split.num_types; i != 0;) {\n      size_t j = 0;\n      i--;\n      for (; j < (1 << BROTLI_LITERAL_CONTEXT_BITS); j++) {\n        mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =\n            mb->literal_context_map[i];\n      }\n    }\n  }\n\n  BROTLI_DCHECK(mb->distance_context_map == 0);\n  mb->distance_context_map_size =\n      mb->distance_split.num_types << BROTLI_DISTANCE_CONTEXT_BITS;\n  mb->distance_context_map =\n      BROTLI_ALLOC(m, uint32_t, mb->distance_context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_context_map)) return;\n\n  BROTLI_DCHECK(mb->distance_histograms == 0);\n  mb->distance_histograms_size = mb->distance_context_map_size;\n  mb->distance_histograms =\n      BROTLI_ALLOC(m, HistogramDistance, mb->distance_histograms_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->distance_histograms)) return;\n\n  BrotliClusterHistogramsDistance(m, distance_histograms,\n                                  mb->distance_context_map_size,\n                                  kMaxNumberOfHistograms,\n                                  mb->distance_histograms,\n                                  &mb->distance_histograms_size,\n                                  mb->distance_context_map);\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_FREE(m, distance_histograms);\n}\n\n#define FN(X) X ## Literal\n#include \"metablock_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Command\n#include \"metablock_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define FN(X) X ## Distance\n#include \"metablock_inc.h\"  /* NOLINT(build/include) */\n#undef FN\n\n#define BROTLI_MAX_STATIC_CONTEXTS 13\n\n/* Greedy block splitter for one block category (literal, command or distance).\n   Gathers histograms for all context buckets. */\ntypedef struct ContextBlockSplitter {\n  /* Alphabet size of particular block category. */\n  size_t alphabet_size_;\n  size_t num_contexts_;\n  size_t max_block_types_;\n  /* We collect at least this many symbols for each block. */\n  size_t min_block_size_;\n  /* We merge histograms A and B if\n       entropy(A+B) < entropy(A) + entropy(B) + split_threshold_,\n     where A is the current histogram and B is the histogram of the last or the\n     second last block type. */\n  double split_threshold_;\n\n  size_t num_blocks_;\n  BlockSplit* split_;  /* not owned */\n  HistogramLiteral* histograms_;  /* not owned */\n  size_t* histograms_size_;  /* not owned */\n\n  /* The number of symbols that we want to collect before deciding on whether\n     or not to merge the block with a previous one or emit a new block. */\n  size_t target_block_size_;\n  /* The number of symbols in the current histogram. */\n  size_t block_size_;\n  /* Offset of the current histogram. */\n  size_t curr_histogram_ix_;\n  /* Offset of the histograms of the previous two block types. */\n  size_t last_histogram_ix_[2];\n  /* Entropy of the previous two block types. */\n  double last_entropy_[2 * BROTLI_MAX_STATIC_CONTEXTS];\n  /* The number of times we merged the current block with the last one. */\n  size_t merge_last_count_;\n} ContextBlockSplitter;\n\nstatic void InitContextBlockSplitter(\n    MemoryManager* m, ContextBlockSplitter* self, size_t alphabet_size,\n    size_t num_contexts, size_t min_block_size, double split_threshold,\n    size_t num_symbols, BlockSplit* split, HistogramLiteral** histograms,\n    size_t* histograms_size) {\n  size_t max_num_blocks = num_symbols / min_block_size + 1;\n  size_t max_num_types;\n  BROTLI_DCHECK(num_contexts <= BROTLI_MAX_STATIC_CONTEXTS);\n\n  self->alphabet_size_ = alphabet_size;\n  self->num_contexts_ = num_contexts;\n  self->max_block_types_ = BROTLI_MAX_NUMBER_OF_BLOCK_TYPES / num_contexts;\n  self->min_block_size_ = min_block_size;\n  self->split_threshold_ = split_threshold;\n  self->num_blocks_ = 0;\n  self->split_ = split;\n  self->histograms_size_ = histograms_size;\n  self->target_block_size_ = min_block_size;\n  self->block_size_ = 0;\n  self->curr_histogram_ix_ = 0;\n  self->merge_last_count_ = 0;\n\n  /* We have to allocate one more histogram than the maximum number of block\n     types for the current histogram when the meta-block is too big. */\n  max_num_types =\n      BROTLI_MIN(size_t, max_num_blocks, self->max_block_types_ + 1);\n  BROTLI_ENSURE_CAPACITY(m, uint8_t,\n      split->types, split->types_alloc_size, max_num_blocks);\n  BROTLI_ENSURE_CAPACITY(m, uint32_t,\n      split->lengths, split->lengths_alloc_size, max_num_blocks);\n  if (BROTLI_IS_OOM(m)) return;\n  split->num_blocks = max_num_blocks;\n  if (BROTLI_IS_OOM(m)) return;\n  BROTLI_DCHECK(*histograms == 0);\n  *histograms_size = max_num_types * num_contexts;\n  *histograms = BROTLI_ALLOC(m, HistogramLiteral, *histograms_size);\n  self->histograms_ = *histograms;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return;\n  /* Clear only current histogram. */\n  ClearHistogramsLiteral(&self->histograms_[0], num_contexts);\n  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;\n}\n\n/* Does either of three things:\n     (1) emits the current block with a new block type;\n     (2) emits the current block with the type of the second last block;\n     (3) merges the current block with the last block. */\nstatic void ContextBlockSplitterFinishBlock(\n    ContextBlockSplitter* self, MemoryManager* m, BROTLI_BOOL is_final) {\n  BlockSplit* split = self->split_;\n  const size_t num_contexts = self->num_contexts_;\n  double* last_entropy = self->last_entropy_;\n  HistogramLiteral* histograms = self->histograms_;\n\n  if (self->block_size_ < self->min_block_size_) {\n    self->block_size_ = self->min_block_size_;\n  }\n  if (self->num_blocks_ == 0) {\n    size_t i;\n    /* Create first block. */\n    split->lengths[0] = (uint32_t)self->block_size_;\n    split->types[0] = 0;\n\n    for (i = 0; i < num_contexts; ++i) {\n      last_entropy[i] =\n          BitsEntropy(histograms[i].data_, self->alphabet_size_);\n      last_entropy[num_contexts + i] = last_entropy[i];\n    }\n    ++self->num_blocks_;\n    ++split->num_types;\n    self->curr_histogram_ix_ += num_contexts;\n    if (self->curr_histogram_ix_ < *self->histograms_size_) {\n      ClearHistogramsLiteral(\n          &self->histograms_[self->curr_histogram_ix_], self->num_contexts_);\n    }\n    self->block_size_ = 0;\n  } else if (self->block_size_ > 0) {\n    /* Try merging the set of histograms for the current block type with the\n       respective set of histograms for the last and second last block types.\n       Decide over the split based on the total reduction of entropy across\n       all contexts. */\n    double entropy[BROTLI_MAX_STATIC_CONTEXTS];\n    HistogramLiteral* combined_histo =\n        BROTLI_ALLOC(m, HistogramLiteral, 2 * num_contexts);\n    double combined_entropy[2 * BROTLI_MAX_STATIC_CONTEXTS];\n    double diff[2] = { 0.0 };\n    size_t i;\n    if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(combined_histo)) return;\n    for (i = 0; i < num_contexts; ++i) {\n      size_t curr_histo_ix = self->curr_histogram_ix_ + i;\n      size_t j;\n      entropy[i] = BitsEntropy(histograms[curr_histo_ix].data_,\n                               self->alphabet_size_);\n      for (j = 0; j < 2; ++j) {\n        size_t jx = j * num_contexts + i;\n        size_t last_histogram_ix = self->last_histogram_ix_[j] + i;\n        combined_histo[jx] = histograms[curr_histo_ix];\n        HistogramAddHistogramLiteral(&combined_histo[jx],\n            &histograms[last_histogram_ix]);\n        combined_entropy[jx] = BitsEntropy(\n            &combined_histo[jx].data_[0], self->alphabet_size_);\n        diff[j] += combined_entropy[jx] - entropy[i] - last_entropy[jx];\n      }\n    }\n\n    if (split->num_types < self->max_block_types_ &&\n        diff[0] > self->split_threshold_ &&\n        diff[1] > self->split_threshold_) {\n      /* Create new block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = (uint8_t)split->num_types;\n      self->last_histogram_ix_[1] = self->last_histogram_ix_[0];\n      self->last_histogram_ix_[0] = split->num_types * num_contexts;\n      for (i = 0; i < num_contexts; ++i) {\n        last_entropy[num_contexts + i] = last_entropy[i];\n        last_entropy[i] = entropy[i];\n      }\n      ++self->num_blocks_;\n      ++split->num_types;\n      self->curr_histogram_ix_ += num_contexts;\n      if (self->curr_histogram_ix_ < *self->histograms_size_) {\n        ClearHistogramsLiteral(\n            &self->histograms_[self->curr_histogram_ix_], self->num_contexts_);\n      }\n      self->block_size_ = 0;\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else if (diff[1] < diff[0] - 20.0) {\n      /* Combine this block with second last block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];\n      BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1);\n      for (i = 0; i < num_contexts; ++i) {\n        histograms[self->last_histogram_ix_[0] + i] =\n            combined_histo[num_contexts + i];\n        last_entropy[num_contexts + i] = last_entropy[i];\n        last_entropy[i] = combined_entropy[num_contexts + i];\n        HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]);\n      }\n      ++self->num_blocks_;\n      self->block_size_ = 0;\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else {\n      /* Combine this block with last block. */\n      split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;\n      for (i = 0; i < num_contexts; ++i) {\n        histograms[self->last_histogram_ix_[0] + i] = combined_histo[i];\n        last_entropy[i] = combined_entropy[i];\n        if (split->num_types == 1) {\n          last_entropy[num_contexts + i] = last_entropy[i];\n        }\n        HistogramClearLiteral(&histograms[self->curr_histogram_ix_ + i]);\n      }\n      self->block_size_ = 0;\n      if (++self->merge_last_count_ > 1) {\n        self->target_block_size_ += self->min_block_size_;\n      }\n    }\n    BROTLI_FREE(m, combined_histo);\n  }\n  if (is_final) {\n    *self->histograms_size_ = split->num_types * num_contexts;\n    split->num_blocks = self->num_blocks_;\n  }\n}\n\n/* Adds the next symbol to the current block type and context. When the\n   current block reaches the target size, decides on merging the block. */\nstatic void ContextBlockSplitterAddSymbol(\n    ContextBlockSplitter* self, MemoryManager* m,\n    size_t symbol, size_t context) {\n  HistogramAddLiteral(&self->histograms_[self->curr_histogram_ix_ + context],\n      symbol);\n  ++self->block_size_;\n  if (self->block_size_ == self->target_block_size_) {\n    ContextBlockSplitterFinishBlock(self, m, /* is_final = */ BROTLI_FALSE);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n}\n\nstatic void MapStaticContexts(MemoryManager* m,\n                              size_t num_contexts,\n                              const uint32_t* static_context_map,\n                              MetaBlockSplit* mb) {\n  size_t i;\n  BROTLI_DCHECK(mb->literal_context_map == 0);\n  mb->literal_context_map_size =\n      mb->literal_split.num_types << BROTLI_LITERAL_CONTEXT_BITS;\n  mb->literal_context_map =\n      BROTLI_ALLOC(m, uint32_t, mb->literal_context_map_size);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(mb->literal_context_map)) return;\n\n  for (i = 0; i < mb->literal_split.num_types; ++i) {\n    uint32_t offset = (uint32_t)(i * num_contexts);\n    size_t j;\n    for (j = 0; j < (1u << BROTLI_LITERAL_CONTEXT_BITS); ++j) {\n      mb->literal_context_map[(i << BROTLI_LITERAL_CONTEXT_BITS) + j] =\n          offset + static_context_map[j];\n    }\n  }\n}\n\ntypedef struct GreedyMetablockArena {\n  union {\n    BlockSplitterLiteral plain;\n    ContextBlockSplitter ctx;\n  } lit_blocks;\n  BlockSplitterCommand cmd_blocks;\n  BlockSplitterDistance dist_blocks;\n} GreedyMetablockArena;\n\nstatic BROTLI_INLINE void BrotliBuildMetaBlockGreedyInternal(\n    MemoryManager* m, GreedyMetablockArena* arena, const uint8_t* ringbuffer,\n    size_t pos, size_t mask, uint8_t prev_byte, uint8_t prev_byte2,\n    ContextLut literal_context_lut, const size_t num_contexts,\n    const uint32_t* static_context_map, const Command* commands,\n    size_t n_commands, MetaBlockSplit* mb) {\n  size_t num_literals = 0;\n  size_t i;\n  for (i = 0; i < n_commands; ++i) {\n    num_literals += commands[i].insert_len_;\n  }\n\n  if (num_contexts == 1) {\n    InitBlockSplitterLiteral(m, &arena->lit_blocks.plain, 256, 512, 400.0,\n        num_literals, &mb->literal_split, &mb->literal_histograms,\n        &mb->literal_histograms_size);\n  } else {\n    InitContextBlockSplitter(m, &arena->lit_blocks.ctx, 256, num_contexts, 512,\n        400.0, num_literals, &mb->literal_split, &mb->literal_histograms,\n        &mb->literal_histograms_size);\n  }\n  if (BROTLI_IS_OOM(m)) return;\n  InitBlockSplitterCommand(m, &arena->cmd_blocks, BROTLI_NUM_COMMAND_SYMBOLS,\n      1024, 500.0, n_commands, &mb->command_split, &mb->command_histograms,\n      &mb->command_histograms_size);\n  if (BROTLI_IS_OOM(m)) return;\n  InitBlockSplitterDistance(m, &arena->dist_blocks, 64, 512, 100.0, n_commands,\n      &mb->distance_split, &mb->distance_histograms,\n      &mb->distance_histograms_size);\n  if (BROTLI_IS_OOM(m)) return;\n\n  for (i = 0; i < n_commands; ++i) {\n    const Command cmd = commands[i];\n    size_t j;\n    BlockSplitterAddSymbolCommand(&arena->cmd_blocks, cmd.cmd_prefix_);\n    for (j = cmd.insert_len_; j != 0; --j) {\n      uint8_t literal = ringbuffer[pos & mask];\n      if (num_contexts == 1) {\n        BlockSplitterAddSymbolLiteral(&arena->lit_blocks.plain, literal);\n      } else {\n        size_t context =\n            BROTLI_CONTEXT(prev_byte, prev_byte2, literal_context_lut);\n        ContextBlockSplitterAddSymbol(&arena->lit_blocks.ctx, m, literal,\n                                      static_context_map[context]);\n        if (BROTLI_IS_OOM(m)) return;\n      }\n      prev_byte2 = prev_byte;\n      prev_byte = literal;\n      ++pos;\n    }\n    pos += CommandCopyLen(&cmd);\n    if (CommandCopyLen(&cmd)) {\n      prev_byte2 = ringbuffer[(pos - 2) & mask];\n      prev_byte = ringbuffer[(pos - 1) & mask];\n      if (cmd.cmd_prefix_ >= 128) {\n        BlockSplitterAddSymbolDistance(\n            &arena->dist_blocks, cmd.dist_prefix_ & 0x3FF);\n      }\n    }\n  }\n\n  if (num_contexts == 1) {\n    BlockSplitterFinishBlockLiteral(\n        &arena->lit_blocks.plain, /* is_final = */ BROTLI_TRUE);\n  } else {\n    ContextBlockSplitterFinishBlock(\n        &arena->lit_blocks.ctx, m, /* is_final = */ BROTLI_TRUE);\n    if (BROTLI_IS_OOM(m)) return;\n  }\n  BlockSplitterFinishBlockCommand(\n      &arena->cmd_blocks, /* is_final = */ BROTLI_TRUE);\n  BlockSplitterFinishBlockDistance(\n      &arena->dist_blocks, /* is_final = */ BROTLI_TRUE);\n\n  if (num_contexts > 1) {\n    MapStaticContexts(m, num_contexts, static_context_map, mb);\n  }\n}\n\nvoid BrotliBuildMetaBlockGreedy(MemoryManager* m,\n                                const uint8_t* ringbuffer,\n                                size_t pos,\n                                size_t mask,\n                                uint8_t prev_byte,\n                                uint8_t prev_byte2,\n                                ContextLut literal_context_lut,\n                                size_t num_contexts,\n                                const uint32_t* static_context_map,\n                                const Command* commands,\n                                size_t n_commands,\n                                MetaBlockSplit* mb) {\n  GreedyMetablockArena* arena = BROTLI_ALLOC(m, GreedyMetablockArena, 1);\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(arena)) return;\n  if (num_contexts == 1) {\n    BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,\n        prev_byte, prev_byte2, literal_context_lut, 1, NULL, commands,\n        n_commands, mb);\n  } else {\n    BrotliBuildMetaBlockGreedyInternal(m, arena, ringbuffer, pos, mask,\n        prev_byte, prev_byte2, literal_context_lut, num_contexts,\n        static_context_map, commands, n_commands, mb);\n  }\n  BROTLI_FREE(m, arena);\n}\n\nvoid BrotliOptimizeHistograms(uint32_t num_distance_codes,\n                              MetaBlockSplit* mb) {\n  uint8_t good_for_rle[BROTLI_NUM_COMMAND_SYMBOLS];\n  size_t i;\n  for (i = 0; i < mb->literal_histograms_size; ++i) {\n    BrotliOptimizeHuffmanCountsForRle(256, mb->literal_histograms[i].data_,\n                                      good_for_rle);\n  }\n  for (i = 0; i < mb->command_histograms_size; ++i) {\n    BrotliOptimizeHuffmanCountsForRle(BROTLI_NUM_COMMAND_SYMBOLS,\n                                      mb->command_histograms[i].data_,\n                                      good_for_rle);\n  }\n  for (i = 0; i < mb->distance_histograms_size; ++i) {\n    BrotliOptimizeHuffmanCountsForRle(num_distance_codes,\n                                      mb->distance_histograms[i].data_,\n                                      good_for_rle);\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/metablock.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Algorithms for distributing the literals and commands of a metablock between\n   block types and contexts. */\n\n#ifndef BROTLI_ENC_METABLOCK_H_\n#define BROTLI_ENC_METABLOCK_H_\n\n#include <brotli/types.h>\n\n#include \"../common/context.h\"\n#include \"../common/platform.h\"\n#include \"block_splitter.h\"\n#include \"command.h\"\n#include \"histogram.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct MetaBlockSplit {\n  BlockSplit literal_split;\n  BlockSplit command_split;\n  BlockSplit distance_split;\n  uint32_t* literal_context_map;\n  size_t literal_context_map_size;\n  uint32_t* distance_context_map;\n  size_t distance_context_map_size;\n  HistogramLiteral* literal_histograms;\n  size_t literal_histograms_size;\n  HistogramCommand* command_histograms;\n  size_t command_histograms_size;\n  HistogramDistance* distance_histograms;\n  size_t distance_histograms_size;\n} MetaBlockSplit;\n\nstatic BROTLI_INLINE void InitMetaBlockSplit(MetaBlockSplit* mb) {\n  BrotliInitBlockSplit(&mb->literal_split);\n  BrotliInitBlockSplit(&mb->command_split);\n  BrotliInitBlockSplit(&mb->distance_split);\n  mb->literal_context_map = 0;\n  mb->literal_context_map_size = 0;\n  mb->distance_context_map = 0;\n  mb->distance_context_map_size = 0;\n  mb->literal_histograms = 0;\n  mb->literal_histograms_size = 0;\n  mb->command_histograms = 0;\n  mb->command_histograms_size = 0;\n  mb->distance_histograms = 0;\n  mb->distance_histograms_size = 0;\n}\n\nstatic BROTLI_INLINE void DestroyMetaBlockSplit(\n    MemoryManager* m, MetaBlockSplit* mb) {\n  BrotliDestroyBlockSplit(m, &mb->literal_split);\n  BrotliDestroyBlockSplit(m, &mb->command_split);\n  BrotliDestroyBlockSplit(m, &mb->distance_split);\n  BROTLI_FREE(m, mb->literal_context_map);\n  BROTLI_FREE(m, mb->distance_context_map);\n  BROTLI_FREE(m, mb->literal_histograms);\n  BROTLI_FREE(m, mb->command_histograms);\n  BROTLI_FREE(m, mb->distance_histograms);\n}\n\n/* Uses the slow shortest-path block splitter and does context clustering.\n   The distance parameters are dynamically selected based on the commands\n   which get recomputed under the new distance parameters. The new distance\n   parameters are stored into *params. */\nBROTLI_INTERNAL void BrotliBuildMetaBlock(MemoryManager* m,\n                                          const uint8_t* ringbuffer,\n                                          const size_t pos,\n                                          const size_t mask,\n                                          BrotliEncoderParams* params,\n                                          uint8_t prev_byte,\n                                          uint8_t prev_byte2,\n                                          Command* cmds,\n                                          size_t num_commands,\n                                          ContextType literal_context_mode,\n                                          MetaBlockSplit* mb);\n\n/* Uses a fast greedy block splitter that tries to merge current block with the\n   last or the second last block and uses a static context clustering which\n   is the same for all block types. */\nBROTLI_INTERNAL void BrotliBuildMetaBlockGreedy(\n    MemoryManager* m, const uint8_t* ringbuffer, size_t pos, size_t mask,\n    uint8_t prev_byte, uint8_t prev_byte2, ContextLut literal_context_lut,\n    size_t num_contexts, const uint32_t* static_context_map,\n    const Command* commands, size_t n_commands, MetaBlockSplit* mb);\n\nBROTLI_INTERNAL void BrotliOptimizeHistograms(uint32_t num_distance_codes,\n                                              MetaBlockSplit* mb);\n\nBROTLI_INTERNAL void BrotliInitDistanceParams(BrotliDistanceParams* params,\n    uint32_t npostfix, uint32_t ndirect, BROTLI_BOOL large_window);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_METABLOCK_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/metablock_inc.h",
    "content": "/* NOLINT(build/header_guard) */\n/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* template parameters: FN */\n\n#define HistogramType FN(Histogram)\n\n/* Greedy block splitter for one block category (literal, command or distance).\n*/\ntypedef struct FN(BlockSplitter) {\n  /* Alphabet size of particular block category. */\n  size_t alphabet_size_;\n  /* We collect at least this many symbols for each block. */\n  size_t min_block_size_;\n  /* We merge histograms A and B if\n       entropy(A+B) < entropy(A) + entropy(B) + split_threshold_,\n     where A is the current histogram and B is the histogram of the last or the\n     second last block type. */\n  double split_threshold_;\n\n  size_t num_blocks_;\n  BlockSplit* split_;  /* not owned */\n  HistogramType* histograms_;  /* not owned */\n  size_t* histograms_size_;  /* not owned */\n\n  /* Temporary storage for BlockSplitterFinishBlock. */\n  HistogramType combined_histo[2];\n\n  /* The number of symbols that we want to collect before deciding on whether\n     or not to merge the block with a previous one or emit a new block. */\n  size_t target_block_size_;\n  /* The number of symbols in the current histogram. */\n  size_t block_size_;\n  /* Offset of the current histogram. */\n  size_t curr_histogram_ix_;\n  /* Offset of the histograms of the previous two block types. */\n  size_t last_histogram_ix_[2];\n  /* Entropy of the previous two block types. */\n  double last_entropy_[2];\n  /* The number of times we merged the current block with the last one. */\n  size_t merge_last_count_;\n} FN(BlockSplitter);\n\nstatic void FN(InitBlockSplitter)(\n    MemoryManager* m, FN(BlockSplitter)* self, size_t alphabet_size,\n    size_t min_block_size, double split_threshold, size_t num_symbols,\n    BlockSplit* split, HistogramType** histograms, size_t* histograms_size) {\n  size_t max_num_blocks = num_symbols / min_block_size + 1;\n  /* We have to allocate one more histogram than the maximum number of block\n     types for the current histogram when the meta-block is too big. */\n  size_t max_num_types =\n      BROTLI_MIN(size_t, max_num_blocks, BROTLI_MAX_NUMBER_OF_BLOCK_TYPES + 1);\n  self->alphabet_size_ = alphabet_size;\n  self->min_block_size_ = min_block_size;\n  self->split_threshold_ = split_threshold;\n  self->num_blocks_ = 0;\n  self->split_ = split;\n  self->histograms_size_ = histograms_size;\n  self->target_block_size_ = min_block_size;\n  self->block_size_ = 0;\n  self->curr_histogram_ix_ = 0;\n  self->merge_last_count_ = 0;\n  BROTLI_ENSURE_CAPACITY(m, uint8_t,\n      split->types, split->types_alloc_size, max_num_blocks);\n  BROTLI_ENSURE_CAPACITY(m, uint32_t,\n      split->lengths, split->lengths_alloc_size, max_num_blocks);\n  if (BROTLI_IS_OOM(m)) return;\n  self->split_->num_blocks = max_num_blocks;\n  BROTLI_DCHECK(*histograms == 0);\n  *histograms_size = max_num_types;\n  *histograms = BROTLI_ALLOC(m, HistogramType, *histograms_size);\n  self->histograms_ = *histograms;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(*histograms)) return;\n  /* Clear only current histogram. */\n  FN(HistogramClear)(&self->histograms_[0]);\n  self->last_histogram_ix_[0] = self->last_histogram_ix_[1] = 0;\n}\n\n/* Does either of three things:\n     (1) emits the current block with a new block type;\n     (2) emits the current block with the type of the second last block;\n     (3) merges the current block with the last block. */\nstatic void FN(BlockSplitterFinishBlock)(\n    FN(BlockSplitter)* self, BROTLI_BOOL is_final) {\n  BlockSplit* split = self->split_;\n  double* last_entropy = self->last_entropy_;\n  HistogramType* histograms = self->histograms_;\n  self->block_size_ =\n      BROTLI_MAX(size_t, self->block_size_, self->min_block_size_);\n  if (self->num_blocks_ == 0) {\n    /* Create first block. */\n    split->lengths[0] = (uint32_t)self->block_size_;\n    split->types[0] = 0;\n    last_entropy[0] =\n        BitsEntropy(histograms[0].data_, self->alphabet_size_);\n    last_entropy[1] = last_entropy[0];\n    ++self->num_blocks_;\n    ++split->num_types;\n    ++self->curr_histogram_ix_;\n    if (self->curr_histogram_ix_ < *self->histograms_size_)\n      FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n    self->block_size_ = 0;\n  } else if (self->block_size_ > 0) {\n    double entropy = BitsEntropy(histograms[self->curr_histogram_ix_].data_,\n                                 self->alphabet_size_);\n    double combined_entropy[2];\n    double diff[2];\n    size_t j;\n    for (j = 0; j < 2; ++j) {\n      size_t last_histogram_ix = self->last_histogram_ix_[j];\n      self->combined_histo[j] = histograms[self->curr_histogram_ix_];\n      FN(HistogramAddHistogram)(&self->combined_histo[j],\n          &histograms[last_histogram_ix]);\n      combined_entropy[j] = BitsEntropy(\n          &self->combined_histo[j].data_[0], self->alphabet_size_);\n      diff[j] = combined_entropy[j] - entropy - last_entropy[j];\n    }\n\n    if (split->num_types < BROTLI_MAX_NUMBER_OF_BLOCK_TYPES &&\n        diff[0] > self->split_threshold_ &&\n        diff[1] > self->split_threshold_) {\n      /* Create new block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = (uint8_t)split->num_types;\n      self->last_histogram_ix_[1] = self->last_histogram_ix_[0];\n      self->last_histogram_ix_[0] = (uint8_t)split->num_types;\n      last_entropy[1] = last_entropy[0];\n      last_entropy[0] = entropy;\n      ++self->num_blocks_;\n      ++split->num_types;\n      ++self->curr_histogram_ix_;\n      if (self->curr_histogram_ix_ < *self->histograms_size_)\n        FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n      self->block_size_ = 0;\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else if (diff[1] < diff[0] - 20.0) {\n      /* Combine this block with second last block. */\n      split->lengths[self->num_blocks_] = (uint32_t)self->block_size_;\n      split->types[self->num_blocks_] = split->types[self->num_blocks_ - 2];\n      BROTLI_SWAP(size_t, self->last_histogram_ix_, 0, 1);\n      histograms[self->last_histogram_ix_[0]] = self->combined_histo[1];\n      last_entropy[1] = last_entropy[0];\n      last_entropy[0] = combined_entropy[1];\n      ++self->num_blocks_;\n      self->block_size_ = 0;\n      FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n      self->merge_last_count_ = 0;\n      self->target_block_size_ = self->min_block_size_;\n    } else {\n      /* Combine this block with last block. */\n      split->lengths[self->num_blocks_ - 1] += (uint32_t)self->block_size_;\n      histograms[self->last_histogram_ix_[0]] = self->combined_histo[0];\n      last_entropy[0] = combined_entropy[0];\n      if (split->num_types == 1) {\n        last_entropy[1] = last_entropy[0];\n      }\n      self->block_size_ = 0;\n      FN(HistogramClear)(&histograms[self->curr_histogram_ix_]);\n      if (++self->merge_last_count_ > 1) {\n        self->target_block_size_ += self->min_block_size_;\n      }\n    }\n  }\n  if (is_final) {\n    *self->histograms_size_ = split->num_types;\n    split->num_blocks = self->num_blocks_;\n  }\n}\n\n/* Adds the next symbol to the current histogram. When the current histogram\n   reaches the target size, decides on merging the block. */\nstatic void FN(BlockSplitterAddSymbol)(FN(BlockSplitter)* self, size_t symbol) {\n  FN(HistogramAdd)(&self->histograms_[self->curr_histogram_ix_], symbol);\n  ++self->block_size_;\n  if (self->block_size_ == self->target_block_size_) {\n    FN(BlockSplitterFinishBlock)(self, /* is_final = */ BROTLI_FALSE);\n  }\n}\n\n#undef HistogramType\n"
  },
  {
    "path": "third-party/brotli/enc/params.h",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Parameters for the Brotli encoder with chosen quality levels. */\n\n#ifndef BROTLI_ENC_PARAMS_H_\n#define BROTLI_ENC_PARAMS_H_\n\n#include <brotli/encode.h>\n\n#include \"encoder_dict.h\"\n\ntypedef struct BrotliHasherParams {\n  int type;\n  int bucket_bits;\n  int block_bits;\n  int num_last_distances_to_check;\n} BrotliHasherParams;\n\ntypedef struct BrotliDistanceParams {\n  uint32_t distance_postfix_bits;\n  uint32_t num_direct_distance_codes;\n  uint32_t alphabet_size_max;\n  uint32_t alphabet_size_limit;\n  size_t max_distance;\n} BrotliDistanceParams;\n\n/* Encoding parameters */\ntypedef struct BrotliEncoderParams {\n  BrotliEncoderMode mode;\n  int quality;\n  int lgwin;\n  int lgblock;\n  size_t stream_offset;\n  size_t size_hint;\n  BROTLI_BOOL disable_literal_context_modeling;\n  BROTLI_BOOL large_window;\n  BrotliHasherParams hasher;\n  BrotliDistanceParams dist;\n  /* TODO(eustas): rename to BrotliShared... */\n  SharedEncoderDictionary dictionary;\n} BrotliEncoderParams;\n\n#endif  /* BROTLI_ENC_PARAMS_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/prefix.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Functions for encoding of integers into prefix codes the amount of extra\n   bits, and the actual values of the extra bits. */\n\n#ifndef BROTLI_ENC_PREFIX_H_\n#define BROTLI_ENC_PREFIX_H_\n\n#include <brotli/types.h>\n\n#include \"../common/constants.h\"\n#include \"../common/platform.h\"\n#include \"fast_log.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* Here distance_code is an intermediate code, i.e. one of the special codes or\n   the actual distance increased by BROTLI_NUM_DISTANCE_SHORT_CODES - 1. */\nstatic BROTLI_INLINE void PrefixEncodeCopyDistance(size_t distance_code,\n                                                   size_t num_direct_codes,\n                                                   size_t postfix_bits,\n                                                   uint16_t* code,\n                                                   uint32_t* extra_bits) {\n  if (distance_code < BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes) {\n    *code = (uint16_t)distance_code;\n    *extra_bits = 0;\n    return;\n  } else {\n    size_t dist = ((size_t)1 << (postfix_bits + 2u)) +\n        (distance_code - BROTLI_NUM_DISTANCE_SHORT_CODES - num_direct_codes);\n    size_t bucket = Log2FloorNonZero(dist) - 1;\n    size_t postfix_mask = (1u << postfix_bits) - 1;\n    size_t postfix = dist & postfix_mask;\n    size_t prefix = (dist >> bucket) & 1;\n    size_t offset = (2 + prefix) << bucket;\n    size_t nbits = bucket - postfix_bits;\n    *code = (uint16_t)((nbits << 10) |\n        (BROTLI_NUM_DISTANCE_SHORT_CODES + num_direct_codes +\n         ((2 * (nbits - 1) + prefix) << postfix_bits) + postfix));\n    *extra_bits = (uint32_t)((dist - offset) >> postfix_bits);\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_PREFIX_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/quality.h",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Constants and formulas that affect speed-ratio trade-offs and thus define\n   quality levels. */\n\n#ifndef BROTLI_ENC_QUALITY_H_\n#define BROTLI_ENC_QUALITY_H_\n\n#include <brotli/encode.h>\n\n#include \"../common/platform.h\"\n#include \"params.h\"\n\n#define FAST_ONE_PASS_COMPRESSION_QUALITY 0\n#define FAST_TWO_PASS_COMPRESSION_QUALITY 1\n#define ZOPFLIFICATION_QUALITY 10\n#define HQ_ZOPFLIFICATION_QUALITY 11\n\n#define MAX_QUALITY_FOR_STATIC_ENTROPY_CODES 2\n#define MIN_QUALITY_FOR_BLOCK_SPLIT 4\n#define MIN_QUALITY_FOR_NONZERO_DISTANCE_PARAMS 4\n#define MIN_QUALITY_FOR_OPTIMIZE_HISTOGRAMS 4\n#define MIN_QUALITY_FOR_EXTENSIVE_REFERENCE_SEARCH 5\n#define MIN_QUALITY_FOR_CONTEXT_MODELING 5\n#define MIN_QUALITY_FOR_HQ_CONTEXT_MODELING 7\n#define MIN_QUALITY_FOR_HQ_BLOCK_SPLITTING 10\n\n/* For quality below MIN_QUALITY_FOR_BLOCK_SPLIT there is no block splitting,\n   so we buffer at most this much literals and commands. */\n#define MAX_NUM_DELAYED_SYMBOLS 0x2FFF\n\n/* Returns hash-table size for quality levels 0 and 1. */\nstatic BROTLI_INLINE size_t MaxHashTableSize(int quality) {\n  return quality == FAST_ONE_PASS_COMPRESSION_QUALITY ? 1 << 15 : 1 << 17;\n}\n\n/* The maximum length for which the zopflification uses distinct distances. */\n#define MAX_ZOPFLI_LEN_QUALITY_10 150\n#define MAX_ZOPFLI_LEN_QUALITY_11 325\n\n/* Do not thoroughly search when a long copy is found. */\n#define BROTLI_LONG_COPY_QUICK_STEP 16384\n\nstatic BROTLI_INLINE size_t MaxZopfliLen(const BrotliEncoderParams* params) {\n  return params->quality <= 10 ?\n      MAX_ZOPFLI_LEN_QUALITY_10 :\n      MAX_ZOPFLI_LEN_QUALITY_11;\n}\n\n/* Number of best candidates to evaluate to expand Zopfli chain. */\nstatic BROTLI_INLINE size_t MaxZopfliCandidates(\n  const BrotliEncoderParams* params) {\n  return params->quality <= 10 ? 1 : 5;\n}\n\nstatic BROTLI_INLINE void SanitizeParams(BrotliEncoderParams* params) {\n  params->quality = BROTLI_MIN(int, BROTLI_MAX_QUALITY,\n      BROTLI_MAX(int, BROTLI_MIN_QUALITY, params->quality));\n  if (params->quality <= MAX_QUALITY_FOR_STATIC_ENTROPY_CODES) {\n    params->large_window = BROTLI_FALSE;\n  }\n  if (params->lgwin < BROTLI_MIN_WINDOW_BITS) {\n    params->lgwin = BROTLI_MIN_WINDOW_BITS;\n  } else {\n    int max_lgwin = params->large_window ? BROTLI_LARGE_MAX_WINDOW_BITS :\n                                           BROTLI_MAX_WINDOW_BITS;\n    if (params->lgwin > max_lgwin) params->lgwin = max_lgwin;\n  }\n}\n\n/* Returns optimized lg_block value. */\nstatic BROTLI_INLINE int ComputeLgBlock(const BrotliEncoderParams* params) {\n  int lgblock = params->lgblock;\n  if (params->quality == FAST_ONE_PASS_COMPRESSION_QUALITY ||\n      params->quality == FAST_TWO_PASS_COMPRESSION_QUALITY) {\n    lgblock = params->lgwin;\n  } else if (params->quality < MIN_QUALITY_FOR_BLOCK_SPLIT) {\n    lgblock = 14;\n  } else if (lgblock == 0) {\n    lgblock = 16;\n    if (params->quality >= 9 && params->lgwin > lgblock) {\n      lgblock = BROTLI_MIN(int, 18, params->lgwin);\n    }\n  } else {\n    lgblock = BROTLI_MIN(int, BROTLI_MAX_INPUT_BLOCK_BITS,\n        BROTLI_MAX(int, BROTLI_MIN_INPUT_BLOCK_BITS, lgblock));\n  }\n  return lgblock;\n}\n\n/* Returns log2 of the size of main ring buffer area.\n   Allocate at least lgwin + 1 bits for the ring buffer so that the newly\n   added block fits there completely and we still get lgwin bits and at least\n   read_block_size_bits + 1 bits because the copy tail length needs to be\n   smaller than ring-buffer size. */\nstatic BROTLI_INLINE int ComputeRbBits(const BrotliEncoderParams* params) {\n  return 1 + BROTLI_MAX(int, params->lgwin, params->lgblock);\n}\n\nstatic BROTLI_INLINE size_t MaxMetablockSize(\n    const BrotliEncoderParams* params) {\n  int bits =\n      BROTLI_MIN(int, ComputeRbBits(params), BROTLI_MAX_INPUT_BLOCK_BITS);\n  return (size_t)1 << bits;\n}\n\n/* When searching for backward references and have not seen matches for a long\n   time, we can skip some match lookups. Unsuccessful match lookups are very\n   expensive and this kind of a heuristic speeds up compression quite a lot.\n   At first 8 byte strides are taken and every second byte is put to hasher.\n   After 4x more literals stride by 16 bytes, every put 4-th byte to hasher.\n   Applied only to qualities 2 to 9. */\nstatic BROTLI_INLINE size_t LiteralSpreeLengthForSparseSearch(\n    const BrotliEncoderParams* params) {\n  return params->quality < 9 ? 64 : 512;\n}\n\n/* Quality to hasher mapping:\n\n   - q02: h02 (longest_match_quickly), b16, l5\n\n   - q03: h03 (longest_match_quickly), b17, l5\n\n   - q04: h04 (longest_match_quickly), b17, l5\n   - q04: h54 (longest_match_quickly), b20, l7 | for large files\n\n   - q05: h05 (longest_match        ), b14, l4\n   - q05: h06 (longest_match64      ), b15, l5 | for large files\n   - q05: h40 (forgetful_chain      ), b15, l4 | for small window\n\n   - q06: h05 (longest_match        ), b14, l4\n   - q06: h06 (longest_match64      ), b15, l5 | for large files\n   - q06: h40 (forgetful_chain      ), b15, l4 | for small window\n\n   - q07: h05 (longest_match        ), b15, l4\n   - q07: h06 (longest_match64      ), b15, l5 | for large files\n   - q07: h41 (forgetful_chain      ), b15, l4 | for small window\n\n   - q08: h05 (longest_match        ), b15, l4\n   - q08: h06 (longest_match64      ), b15, l5 | for large files\n   - q08: h41 (forgetful_chain      ), b15, l4 | for small window\n\n   - q09: h05 (longest_match        ), b15, l4\n   - q09: h06 (longest_match64      ), b15, l5 | for large files\n   - q09: h42 (forgetful_chain      ), b15, l4 | for small window\n\n   - q10: t10 (to_binary_tree       ), b17, l128\n\n   - q11: t10 (to_binary_tree       ), b17, l128\n\n  Where \"q\" is quality, \"h\" is hasher type, \"b\" is bucket bits,\n  \"l\" is source len. */\nstatic BROTLI_INLINE void ChooseHasher(const BrotliEncoderParams* params,\n                                       BrotliHasherParams* hparams) {\n  if (params->quality > 9) {\n    hparams->type = 10;\n  } else if (params->quality == 4 && params->size_hint >= (1 << 20)) {\n    hparams->type = 54;\n  } else if (params->quality < 5) {\n    hparams->type = params->quality;\n  } else if (params->lgwin <= 16) {\n    hparams->type = params->quality < 7 ? 40 : params->quality < 9 ? 41 : 42;\n  } else if (params->size_hint >= (1 << 20) && params->lgwin >= 19) {\n    hparams->type = 6;\n    hparams->block_bits = params->quality - 1;\n    hparams->bucket_bits = 15;\n    hparams->num_last_distances_to_check =\n        params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;\n  } else {\n    /* TODO(eustas): often previous setting (H6) is faster and denser; consider\n                     adding an option to use it. */\n    hparams->type = 5;\n    hparams->block_bits = params->quality - 1;\n    hparams->bucket_bits = params->quality < 7 ? 14 : 15;\n    hparams->num_last_distances_to_check =\n        params->quality < 7 ? 4 : params->quality < 9 ? 10 : 16;\n  }\n\n  if (params->lgwin > 24) {\n    /* Different hashers for large window brotli: not for qualities <= 2,\n       these are too fast for large window. Not for qualities >= 10: their\n       hasher already works well with large window. So the changes are:\n       H3 --> H35: for quality 3.\n       H54 --> H55: for quality 4 with size hint > 1MB\n       H6 --> H65: for qualities 5, 6, 7, 8, 9. */\n    if (hparams->type == 3) {\n      hparams->type = 35;\n    }\n    if (hparams->type == 54) {\n      hparams->type = 55;\n    }\n    if (hparams->type == 6) {\n      hparams->type = 65;\n    }\n  }\n}\n\n#endif  /* BROTLI_ENC_QUALITY_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/ringbuffer.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Sliding window over the input data. */\n\n#ifndef BROTLI_ENC_RINGBUFFER_H_\n#define BROTLI_ENC_RINGBUFFER_H_\n\n#include <string.h>  /* memcpy */\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n#include \"memory.h\"\n#include \"quality.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* A RingBuffer(window_bits, tail_bits) contains `1 << window_bits' bytes of\n   data in a circular manner: writing a byte writes it to:\n     `position() % (1 << window_bits)'.\n   For convenience, the RingBuffer array contains another copy of the\n   first `1 << tail_bits' bytes:\n     buffer_[i] == buffer_[i + (1 << window_bits)], if i < (1 << tail_bits),\n   and another copy of the last two bytes:\n     buffer_[-1] == buffer_[(1 << window_bits) - 1] and\n     buffer_[-2] == buffer_[(1 << window_bits) - 2]. */\ntypedef struct RingBuffer {\n  /* Size of the ring-buffer is (1 << window_bits) + tail_size_. */\n  const uint32_t size_;\n  const uint32_t mask_;\n  const uint32_t tail_size_;\n  const uint32_t total_size_;\n\n  uint32_t cur_size_;\n  /* Position to write in the ring buffer. */\n  uint32_t pos_;\n  /* The actual ring buffer containing the copy of the last two bytes, the data,\n     and the copy of the beginning as a tail. */\n  uint8_t* data_;\n  /* The start of the ring-buffer. */\n  uint8_t* buffer_;\n} RingBuffer;\n\nstatic BROTLI_INLINE void RingBufferInit(RingBuffer* rb) {\n  rb->cur_size_ = 0;\n  rb->pos_ = 0;\n  rb->data_ = 0;\n  rb->buffer_ = 0;\n}\n\nstatic BROTLI_INLINE void RingBufferSetup(\n    const BrotliEncoderParams* params, RingBuffer* rb) {\n  int window_bits = ComputeRbBits(params);\n  int tail_bits = params->lgblock;\n  *(uint32_t*)&rb->size_ = 1u << window_bits;\n  *(uint32_t*)&rb->mask_ = (1u << window_bits) - 1;\n  *(uint32_t*)&rb->tail_size_ = 1u << tail_bits;\n  *(uint32_t*)&rb->total_size_ = rb->size_ + rb->tail_size_;\n}\n\nstatic BROTLI_INLINE void RingBufferFree(MemoryManager* m, RingBuffer* rb) {\n  BROTLI_FREE(m, rb->data_);\n}\n\n/* Allocates or re-allocates data_ to the given length + plus some slack\n   region before and after. Fills the slack regions with zeros. */\nstatic BROTLI_INLINE void RingBufferInitBuffer(\n    MemoryManager* m, const uint32_t buflen, RingBuffer* rb) {\n  static const size_t kSlackForEightByteHashingEverywhere = 7;\n  uint8_t* new_data = BROTLI_ALLOC(\n      m, uint8_t, 2 + buflen + kSlackForEightByteHashingEverywhere);\n  size_t i;\n  if (BROTLI_IS_OOM(m) || BROTLI_IS_NULL(new_data)) return;\n  if (rb->data_) {\n    memcpy(new_data, rb->data_,\n        2 + rb->cur_size_ + kSlackForEightByteHashingEverywhere);\n    BROTLI_FREE(m, rb->data_);\n  }\n  rb->data_ = new_data;\n  rb->cur_size_ = buflen;\n  rb->buffer_ = rb->data_ + 2;\n  rb->buffer_[-2] = rb->buffer_[-1] = 0;\n  for (i = 0; i < kSlackForEightByteHashingEverywhere; ++i) {\n    rb->buffer_[rb->cur_size_ + i] = 0;\n  }\n}\n\nstatic BROTLI_INLINE void RingBufferWriteTail(\n    const uint8_t* bytes, size_t n, RingBuffer* rb) {\n  const size_t masked_pos = rb->pos_ & rb->mask_;\n  if (BROTLI_PREDICT_FALSE(masked_pos < rb->tail_size_)) {\n    /* Just fill the tail buffer with the beginning data. */\n    const size_t p = rb->size_ + masked_pos;\n    memcpy(&rb->buffer_[p], bytes,\n        BROTLI_MIN(size_t, n, rb->tail_size_ - masked_pos));\n  }\n}\n\n/* Push bytes into the ring buffer. */\nstatic BROTLI_INLINE void RingBufferWrite(\n    MemoryManager* m, const uint8_t* bytes, size_t n, RingBuffer* rb) {\n  if (rb->pos_ == 0 && n < rb->tail_size_) {\n    /* Special case for the first write: to process the first block, we don't\n       need to allocate the whole ring-buffer and we don't need the tail\n       either. However, we do this memory usage optimization only if the\n       first write is less than the tail size, which is also the input block\n       size, otherwise it is likely that other blocks will follow and we\n       will need to reallocate to the full size anyway. */\n    rb->pos_ = (uint32_t)n;\n    RingBufferInitBuffer(m, rb->pos_, rb);\n    if (BROTLI_IS_OOM(m)) return;\n    memcpy(rb->buffer_, bytes, n);\n    return;\n  }\n  if (rb->cur_size_ < rb->total_size_) {\n    /* Lazily allocate the full buffer. */\n    RingBufferInitBuffer(m, rb->total_size_, rb);\n    if (BROTLI_IS_OOM(m)) return;\n    /* Initialize the last two bytes to zero, so that we don't have to worry\n       later when we copy the last two bytes to the first two positions. */\n    rb->buffer_[rb->size_ - 2] = 0;\n    rb->buffer_[rb->size_ - 1] = 0;\n    /* Initialize tail; might be touched by \"best_len++\" optimization when\n       ring buffer is \"full\". */\n    rb->buffer_[rb->size_] = 241;\n  }\n  {\n    const size_t masked_pos = rb->pos_ & rb->mask_;\n    /* The length of the writes is limited so that we do not need to worry\n       about a write */\n    RingBufferWriteTail(bytes, n, rb);\n    if (BROTLI_PREDICT_TRUE(masked_pos + n <= rb->size_)) {\n      /* A single write fits. */\n      memcpy(&rb->buffer_[masked_pos], bytes, n);\n    } else {\n      /* Split into two writes.\n         Copy into the end of the buffer, including the tail buffer. */\n      memcpy(&rb->buffer_[masked_pos], bytes,\n             BROTLI_MIN(size_t, n, rb->total_size_ - masked_pos));\n      /* Copy into the beginning of the buffer */\n      memcpy(&rb->buffer_[0], bytes + (rb->size_ - masked_pos),\n             n - (rb->size_ - masked_pos));\n    }\n  }\n  {\n    BROTLI_BOOL not_first_lap = (rb->pos_ & (1u << 31)) != 0;\n    uint32_t rb_pos_mask = (1u << 31) - 1;\n    rb->buffer_[-2] = rb->buffer_[rb->size_ - 2];\n    rb->buffer_[-1] = rb->buffer_[rb->size_ - 1];\n    rb->pos_ = (rb->pos_ & rb_pos_mask) + (uint32_t)(n & rb_pos_mask);\n    if (not_first_lap) {\n      /* Wrap, but preserve not-a-first-lap feature. */\n      rb->pos_ |= 1u << 31;\n    }\n  }\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_RINGBUFFER_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/state.h",
    "content": "/* Copyright 2022 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Encoder state. */\n\n#ifndef BROTLI_ENC_STATE_H_\n#define BROTLI_ENC_STATE_H_\n\n#include <brotli/types.h>\n\n#include \"command.h\"\n#include \"compress_fragment.h\"\n#include \"compress_fragment_two_pass.h\"\n#include \"hash.h\"\n#include \"memory.h\"\n#include \"params.h\"\n#include \"ringbuffer.h\"\n\ntypedef enum BrotliEncoderStreamState {\n  /* Default state. */\n  BROTLI_STREAM_PROCESSING = 0,\n  /* Intermediate state; after next block is emitted, byte-padding should be\n     performed before getting back to default state. */\n  BROTLI_STREAM_FLUSH_REQUESTED = 1,\n  /* Last metablock was produced; no more input is acceptable. */\n  BROTLI_STREAM_FINISHED = 2,\n  /* Flushing compressed block and writing meta-data block header. */\n  BROTLI_STREAM_METADATA_HEAD = 3,\n  /* Writing metadata block body. */\n  BROTLI_STREAM_METADATA_BODY = 4\n} BrotliEncoderStreamState;\n\ntypedef enum BrotliEncoderFlintState {\n  BROTLI_FLINT_NEEDS_2_BYTES = 2,\n  BROTLI_FLINT_NEEDS_1_BYTE = 1,\n  BROTLI_FLINT_WAITING_FOR_PROCESSING = 0,\n  BROTLI_FLINT_WAITING_FOR_FLUSHING = -1,\n  BROTLI_FLINT_DONE = -2\n} BrotliEncoderFlintState;\n\ntypedef struct BrotliEncoderStateStruct {\n  BrotliEncoderParams params;\n\n  MemoryManager memory_manager_;\n\n  uint64_t input_pos_;\n  RingBuffer ringbuffer_;\n  size_t cmd_alloc_size_;\n  Command* commands_;\n  size_t num_commands_;\n  size_t num_literals_;\n  size_t last_insert_len_;\n  uint64_t last_flush_pos_;\n  uint64_t last_processed_pos_;\n  int dist_cache_[BROTLI_NUM_DISTANCE_SHORT_CODES];\n  int saved_dist_cache_[4];\n  uint16_t last_bytes_;\n  uint8_t last_bytes_bits_;\n  /* \"Flint\" is a tiny uncompressed block emitted before the continuation\n     block to unwire literal context from previous data. Despite being int8_t,\n     field is actually BrotliEncoderFlintState enum. */\n  int8_t flint_;\n  uint8_t prev_byte_;\n  uint8_t prev_byte2_;\n  size_t storage_size_;\n  uint8_t* storage_;\n\n  Hasher hasher_;\n\n  /* Hash table for FAST_ONE_PASS_COMPRESSION_QUALITY mode. */\n  int small_table_[1 << 10];  /* 4KiB */\n  int* large_table_;          /* Allocated only when needed */\n  size_t large_table_size_;\n\n  BrotliOnePassArena* one_pass_arena_;\n  BrotliTwoPassArena* two_pass_arena_;\n\n  /* Command and literal buffers for FAST_TWO_PASS_COMPRESSION_QUALITY. */\n  uint32_t* command_buf_;\n  uint8_t* literal_buf_;\n\n  uint64_t total_in_;\n  uint8_t* next_out_;\n  size_t available_out_;\n  uint64_t total_out_;\n  /* Temporary buffer for padding flush bits or metadata block header / body. */\n  union {\n    uint64_t u64[2];\n    uint8_t u8[16];\n  } tiny_buf_;\n  uint32_t remaining_metadata_bytes_;\n  BrotliEncoderStreamState stream_state_;\n\n  BROTLI_BOOL is_last_block_emitted_;\n  BROTLI_BOOL is_initialized_;\n} BrotliEncoderStateStruct;\n\ntypedef struct BrotliEncoderStateStruct BrotliEncoderStateInternal;\n#define BrotliEncoderState BrotliEncoderStateInternal\n\n#endif  // BROTLI_ENC_STATE_H_\n"
  },
  {
    "path": "third-party/brotli/enc/static_dict.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n#include \"static_dict.h\"\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"../common/transform.h\"\n#include \"encoder_dict.h\"\n#include \"find_match_length.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic BROTLI_INLINE uint32_t Hash(const uint8_t* data) {\n  uint32_t h = BROTLI_UNALIGNED_LOAD32LE(data) * kDictHashMul32;\n  /* The higher bits contain more mixture from the multiplication,\n     so we take our results from there. */\n  return h >> (32 - kDictNumBits);\n}\n\nstatic BROTLI_INLINE void AddMatch(size_t distance, size_t len, size_t len_code,\n                                   uint32_t* matches) {\n  uint32_t match = (uint32_t)((distance << 5) + len_code);\n  matches[len] = BROTLI_MIN(uint32_t, matches[len], match);\n}\n\nstatic BROTLI_INLINE size_t DictMatchLength(const BrotliDictionary* dictionary,\n                                            const uint8_t* data,\n                                            size_t id,\n                                            size_t len,\n                                            size_t maxlen) {\n  const size_t offset = dictionary->offsets_by_length[len] + len * id;\n  return FindMatchLengthWithLimit(&dictionary->data[offset], data,\n                                  BROTLI_MIN(size_t, len, maxlen));\n}\n\nstatic BROTLI_INLINE BROTLI_BOOL IsMatch(const BrotliDictionary* dictionary,\n    DictWord w, const uint8_t* data, size_t max_length) {\n  if (w.len > max_length) {\n    return BROTLI_FALSE;\n  } else {\n    const size_t offset = dictionary->offsets_by_length[w.len] +\n        (size_t)w.len * (size_t)w.idx;\n    const uint8_t* dict = &dictionary->data[offset];\n    if (w.transform == 0) {\n      /* Match against base dictionary word. */\n      return\n          TO_BROTLI_BOOL(FindMatchLengthWithLimit(dict, data, w.len) == w.len);\n    } else if (w.transform == 10) {\n      /* Match against uppercase first transform.\n         Note that there are only ASCII uppercase words in the lookup table. */\n      return TO_BROTLI_BOOL(dict[0] >= 'a' && dict[0] <= 'z' &&\n              (dict[0] ^ 32) == data[0] &&\n              FindMatchLengthWithLimit(&dict[1], &data[1], w.len - 1u) ==\n              w.len - 1u);\n    } else {\n      /* Match against uppercase all transform.\n         Note that there are only ASCII uppercase words in the lookup table. */\n      size_t i;\n      for (i = 0; i < w.len; ++i) {\n        if (dict[i] >= 'a' && dict[i] <= 'z') {\n          if ((dict[i] ^ 32) != data[i]) return BROTLI_FALSE;\n        } else {\n          if (dict[i] != data[i]) return BROTLI_FALSE;\n        }\n      }\n      return BROTLI_TRUE;\n    }\n  }\n}\n\n/* Finds matches for a single static dictionary */\nstatic BROTLI_BOOL BrotliFindAllStaticDictionaryMatchesFor(\n    const BrotliEncoderDictionary* dictionary, const uint8_t* data,\n    size_t min_length, size_t max_length, uint32_t* matches) {\n  BROTLI_BOOL has_found_match = BROTLI_FALSE;\n#if defined(BROTLI_EXPERIMENTAL)\n  if (dictionary->has_words_heavy) {\n    const BrotliTrieNode* node = &dictionary->trie.root;\n    size_t l = 0;\n    while (node && l < max_length) {\n      uint8_t c;\n      if (l >= min_length && node->len_) {\n        AddMatch(node->idx_, l, node->len_, matches);\n        has_found_match = BROTLI_TRUE;\n      }\n      c = data[l++];\n      node = BrotliTrieSub(&dictionary->trie, node, c);\n    }\n    return has_found_match;\n  }\n#endif  /* BROTLI_EXPERIMENTAL */\n  {\n    size_t offset = dictionary->buckets[Hash(data)];\n    BROTLI_BOOL end = !offset;\n    while (!end) {\n      DictWord w = dictionary->dict_words[offset++];\n      const size_t l = w.len & 0x1F;\n      const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n      const size_t id = w.idx;\n      end = !!(w.len & 0x80);\n      w.len = (uint8_t)l;\n      if (w.transform == 0) {\n        const size_t matchlen =\n            DictMatchLength(dictionary->words, data, id, l, max_length);\n        const uint8_t* s;\n        size_t minlen;\n        size_t maxlen;\n        size_t len;\n        /* Transform \"\" + BROTLI_TRANSFORM_IDENTITY + \"\" */\n        if (matchlen == l) {\n          AddMatch(id, l, l, matches);\n          has_found_match = BROTLI_TRUE;\n        }\n        /* Transforms \"\" + BROTLI_TRANSFORM_OMIT_LAST_1 + \"\" and\n                      \"\" + BROTLI_TRANSFORM_OMIT_LAST_1 + \"ing \" */\n        if (matchlen >= l - 1) {\n          AddMatch(id + 12 * n, l - 1, l, matches);\n          if (l + 2 < max_length &&\n              data[l - 1] == 'i' && data[l] == 'n' && data[l + 1] == 'g' &&\n              data[l + 2] == ' ') {\n            AddMatch(id + 49 * n, l + 3, l, matches);\n          }\n          has_found_match = BROTLI_TRUE;\n        }\n        /* Transform \"\" + BROTLI_TRANSFORM_OMIT_LAST_# + \"\" (# = 2 .. 9) */\n        minlen = min_length;\n        if (l > 9) minlen = BROTLI_MAX(size_t, minlen, l - 9);\n        maxlen = BROTLI_MIN(size_t, matchlen, l - 2);\n        for (len = minlen; len <= maxlen; ++len) {\n          size_t cut = l - len;\n          size_t transform_id = (cut << 2) +\n              (size_t)((dictionary->cutoffTransforms >> (cut * 6)) & 0x3F);\n          AddMatch(id + transform_id * n, len, l, matches);\n          has_found_match = BROTLI_TRUE;\n        }\n        if (matchlen < l || l + 6 >= max_length) {\n          continue;\n        }\n        s = &data[l];\n        /* Transforms \"\" + BROTLI_TRANSFORM_IDENTITY + <suffix> */\n        if (s[0] == ' ') {\n          AddMatch(id + n, l + 1, l, matches);\n          if (s[1] == 'a') {\n            if (s[2] == ' ') {\n              AddMatch(id + 28 * n, l + 3, l, matches);\n            } else if (s[2] == 's') {\n              if (s[3] == ' ') AddMatch(id + 46 * n, l + 4, l, matches);\n            } else if (s[2] == 't') {\n              if (s[3] == ' ') AddMatch(id + 60 * n, l + 4, l, matches);\n            } else if (s[2] == 'n') {\n              if (s[3] == 'd' && s[4] == ' ') {\n                AddMatch(id + 10 * n, l + 5, l, matches);\n              }\n            }\n          } else if (s[1] == 'b') {\n            if (s[2] == 'y' && s[3] == ' ') {\n              AddMatch(id + 38 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'i') {\n            if (s[2] == 'n') {\n              if (s[3] == ' ') AddMatch(id + 16 * n, l + 4, l, matches);\n            } else if (s[2] == 's') {\n              if (s[3] == ' ') AddMatch(id + 47 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'f') {\n            if (s[2] == 'o') {\n              if (s[3] == 'r' && s[4] == ' ') {\n                AddMatch(id + 25 * n, l + 5, l, matches);\n              }\n            } else if (s[2] == 'r') {\n              if (s[3] == 'o' && s[4] == 'm' && s[5] == ' ') {\n                AddMatch(id + 37 * n, l + 6, l, matches);\n              }\n            }\n          } else if (s[1] == 'o') {\n            if (s[2] == 'f') {\n              if (s[3] == ' ') AddMatch(id + 8 * n, l + 4, l, matches);\n            } else if (s[2] == 'n') {\n              if (s[3] == ' ') AddMatch(id + 45 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'n') {\n            if (s[2] == 'o' && s[3] == 't' && s[4] == ' ') {\n              AddMatch(id + 80 * n, l + 5, l, matches);\n            }\n          } else if (s[1] == 't') {\n            if (s[2] == 'h') {\n              if (s[3] == 'e') {\n                if (s[4] == ' ') AddMatch(id + 5 * n, l + 5, l, matches);\n              } else if (s[3] == 'a') {\n                if (s[4] == 't' && s[5] == ' ') {\n                  AddMatch(id + 29 * n, l + 6, l, matches);\n                }\n              }\n            } else if (s[2] == 'o') {\n              if (s[3] == ' ') AddMatch(id + 17 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'w') {\n            if (s[2] == 'i' && s[3] == 't' && s[4] == 'h' && s[5] == ' ') {\n              AddMatch(id + 35 * n, l + 6, l, matches);\n            }\n          }\n        } else if (s[0] == '\"') {\n          AddMatch(id + 19 * n, l + 1, l, matches);\n          if (s[1] == '>') {\n            AddMatch(id + 21 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '.') {\n          AddMatch(id + 20 * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + 31 * n, l + 2, l, matches);\n            if (s[2] == 'T' && s[3] == 'h') {\n              if (s[4] == 'e') {\n                if (s[5] == ' ') AddMatch(id + 43 * n, l + 6, l, matches);\n              } else if (s[4] == 'i') {\n                if (s[5] == 's' && s[6] == ' ') {\n                  AddMatch(id + 75 * n, l + 7, l, matches);\n                }\n              }\n            }\n          }\n        } else if (s[0] == ',') {\n          AddMatch(id + 76 * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + 14 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '\\n') {\n          AddMatch(id + 22 * n, l + 1, l, matches);\n          if (s[1] == '\\t') {\n            AddMatch(id + 50 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == ']') {\n          AddMatch(id + 24 * n, l + 1, l, matches);\n        } else if (s[0] == '\\'') {\n          AddMatch(id + 36 * n, l + 1, l, matches);\n        } else if (s[0] == ':') {\n          AddMatch(id + 51 * n, l + 1, l, matches);\n        } else if (s[0] == '(') {\n          AddMatch(id + 57 * n, l + 1, l, matches);\n        } else if (s[0] == '=') {\n          if (s[1] == '\"') {\n            AddMatch(id + 70 * n, l + 2, l, matches);\n          } else if (s[1] == '\\'') {\n            AddMatch(id + 86 * n, l + 2, l, matches);\n          }\n        } else if (s[0] == 'a') {\n          if (s[1] == 'l' && s[2] == ' ') {\n            AddMatch(id + 84 * n, l + 3, l, matches);\n          }\n        } else if (s[0] == 'e') {\n          if (s[1] == 'd') {\n            if (s[2] == ' ') AddMatch(id + 53 * n, l + 3, l, matches);\n          } else if (s[1] == 'r') {\n            if (s[2] == ' ') AddMatch(id + 82 * n, l + 3, l, matches);\n          } else if (s[1] == 's') {\n            if (s[2] == 't' && s[3] == ' ') {\n              AddMatch(id + 95 * n, l + 4, l, matches);\n            }\n          }\n        } else if (s[0] == 'f') {\n          if (s[1] == 'u' && s[2] == 'l' && s[3] == ' ') {\n            AddMatch(id + 90 * n, l + 4, l, matches);\n          }\n        } else if (s[0] == 'i') {\n          if (s[1] == 'v') {\n            if (s[2] == 'e' && s[3] == ' ') {\n              AddMatch(id + 92 * n, l + 4, l, matches);\n            }\n          } else if (s[1] == 'z') {\n            if (s[2] == 'e' && s[3] == ' ') {\n              AddMatch(id + 100 * n, l + 4, l, matches);\n            }\n          }\n        } else if (s[0] == 'l') {\n          if (s[1] == 'e') {\n            if (s[2] == 's' && s[3] == 's' && s[4] == ' ') {\n              AddMatch(id + 93 * n, l + 5, l, matches);\n            }\n          } else if (s[1] == 'y') {\n            if (s[2] == ' ') AddMatch(id + 61 * n, l + 3, l, matches);\n          }\n        } else if (s[0] == 'o') {\n          if (s[1] == 'u' && s[2] == 's' && s[3] == ' ') {\n            AddMatch(id + 106 * n, l + 4, l, matches);\n          }\n        }\n      } else {\n        /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and\n               is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL)\n           transform. */\n        const BROTLI_BOOL is_all_caps =\n            TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST);\n        const uint8_t* s;\n        if (!IsMatch(dictionary->words, w, data, max_length)) {\n          continue;\n        }\n        /* Transform \"\" + kUppercase{First,All} + \"\" */\n        AddMatch(id + (is_all_caps ? 44 : 9) * n, l, l, matches);\n        has_found_match = BROTLI_TRUE;\n        if (l + 1 >= max_length) {\n          continue;\n        }\n        /* Transforms \"\" + kUppercase{First,All} + <suffix> */\n        s = &data[l];\n        if (s[0] == ' ') {\n          AddMatch(id + (is_all_caps ? 68 : 4) * n, l + 1, l, matches);\n        } else if (s[0] == '\"') {\n          AddMatch(id + (is_all_caps ? 87 : 66) * n, l + 1, l, matches);\n          if (s[1] == '>') {\n            AddMatch(id + (is_all_caps ? 97 : 69) * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '.') {\n          AddMatch(id + (is_all_caps ? 101 : 79) * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 114 : 88) * n, l + 2, l, matches);\n          }\n        } else if (s[0] == ',') {\n          AddMatch(id + (is_all_caps ? 112 : 99) * n, l + 1, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 107 : 58) * n, l + 2, l, matches);\n          }\n        } else if (s[0] == '\\'') {\n          AddMatch(id + (is_all_caps ? 94 : 74) * n, l + 1, l, matches);\n        } else if (s[0] == '(') {\n          AddMatch(id + (is_all_caps ? 113 : 78) * n, l + 1, l, matches);\n        } else if (s[0] == '=') {\n          if (s[1] == '\"') {\n            AddMatch(id + (is_all_caps ? 105 : 104) * n, l + 2, l, matches);\n          } else if (s[1] == '\\'') {\n            AddMatch(id + (is_all_caps ? 116 : 108) * n, l + 2, l, matches);\n          }\n        }\n      }\n    }\n  }\n  /* Transforms with prefixes \" \" and \".\" */\n  if (max_length >= 5 && (data[0] == ' ' || data[0] == '.')) {\n    BROTLI_BOOL is_space = TO_BROTLI_BOOL(data[0] == ' ');\n    size_t offset = dictionary->buckets[Hash(&data[1])];\n    BROTLI_BOOL end = !offset;\n    while (!end) {\n      DictWord w = dictionary->dict_words[offset++];\n      const size_t l = w.len & 0x1F;\n      const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n      const size_t id = w.idx;\n      end = !!(w.len & 0x80);\n      w.len = (uint8_t)l;\n      if (w.transform == 0) {\n        const uint8_t* s;\n        if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) {\n          continue;\n        }\n        /* Transforms \" \" + BROTLI_TRANSFORM_IDENTITY + \"\" and\n                      \".\" + BROTLI_TRANSFORM_IDENTITY + \"\" */\n        AddMatch(id + (is_space ? 6 : 32) * n, l + 1, l, matches);\n        has_found_match = BROTLI_TRUE;\n        if (l + 2 >= max_length) {\n          continue;\n        }\n        /* Transforms \" \" + BROTLI_TRANSFORM_IDENTITY + <suffix> and\n                      \".\" + BROTLI_TRANSFORM_IDENTITY + <suffix>\n        */\n        s = &data[l + 1];\n        if (s[0] == ' ') {\n          AddMatch(id + (is_space ? 2 : 77) * n, l + 2, l, matches);\n        } else if (s[0] == '(') {\n          AddMatch(id + (is_space ? 89 : 67) * n, l + 2, l, matches);\n        } else if (is_space) {\n          if (s[0] == ',') {\n            AddMatch(id + 103 * n, l + 2, l, matches);\n            if (s[1] == ' ') {\n              AddMatch(id + 33 * n, l + 3, l, matches);\n            }\n          } else if (s[0] == '.') {\n            AddMatch(id + 71 * n, l + 2, l, matches);\n            if (s[1] == ' ') {\n              AddMatch(id + 52 * n, l + 3, l, matches);\n            }\n          } else if (s[0] == '=') {\n            if (s[1] == '\"') {\n              AddMatch(id + 81 * n, l + 3, l, matches);\n            } else if (s[1] == '\\'') {\n              AddMatch(id + 98 * n, l + 3, l, matches);\n            }\n          }\n        }\n      } else if (is_space) {\n        /* Set is_all_caps=0 for BROTLI_TRANSFORM_UPPERCASE_FIRST and\n               is_all_caps=1 otherwise (BROTLI_TRANSFORM_UPPERCASE_ALL)\n           transform. */\n        const BROTLI_BOOL is_all_caps =\n            TO_BROTLI_BOOL(w.transform != BROTLI_TRANSFORM_UPPERCASE_FIRST);\n        const uint8_t* s;\n        if (!IsMatch(dictionary->words, w, &data[1], max_length - 1)) {\n          continue;\n        }\n        /* Transforms \" \" + kUppercase{First,All} + \"\" */\n        AddMatch(id + (is_all_caps ? 85 : 30) * n, l + 1, l, matches);\n        has_found_match = BROTLI_TRUE;\n        if (l + 2 >= max_length) {\n          continue;\n        }\n        /* Transforms \" \" + kUppercase{First,All} + <suffix> */\n        s = &data[l + 1];\n        if (s[0] == ' ') {\n          AddMatch(id + (is_all_caps ? 83 : 15) * n, l + 2, l, matches);\n        } else if (s[0] == ',') {\n          if (!is_all_caps) {\n            AddMatch(id + 109 * n, l + 2, l, matches);\n          }\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 111 : 65) * n, l + 3, l, matches);\n          }\n        } else if (s[0] == '.') {\n          AddMatch(id + (is_all_caps ? 115 : 96) * n, l + 2, l, matches);\n          if (s[1] == ' ') {\n            AddMatch(id + (is_all_caps ? 117 : 91) * n, l + 3, l, matches);\n          }\n        } else if (s[0] == '=') {\n          if (s[1] == '\"') {\n            AddMatch(id + (is_all_caps ? 110 : 118) * n, l + 3, l, matches);\n          } else if (s[1] == '\\'') {\n            AddMatch(id + (is_all_caps ? 119 : 120) * n, l + 3, l, matches);\n          }\n        }\n      }\n    }\n  }\n  if (max_length >= 6) {\n    /* Transforms with prefixes \"e \", \"s \", \", \" and \"\\xC2\\xA0\" */\n    if ((data[1] == ' ' &&\n         (data[0] == 'e' || data[0] == 's' || data[0] == ',')) ||\n        (data[0] == 0xC2 && data[1] == 0xA0)) {\n      size_t offset = dictionary->buckets[Hash(&data[2])];\n      BROTLI_BOOL end = !offset;\n      while (!end) {\n        DictWord w = dictionary->dict_words[offset++];\n        const size_t l = w.len & 0x1F;\n        const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n        const size_t id = w.idx;\n        end = !!(w.len & 0x80);\n        w.len = (uint8_t)l;\n        if (w.transform == 0 &&\n            IsMatch(dictionary->words, w, &data[2], max_length - 2)) {\n          if (data[0] == 0xC2) {\n            AddMatch(id + 102 * n, l + 2, l, matches);\n            has_found_match = BROTLI_TRUE;\n          } else if (l + 2 < max_length && data[l + 2] == ' ') {\n            size_t t = data[0] == 'e' ? 18 : (data[0] == 's' ? 7 : 13);\n            AddMatch(id + t * n, l + 3, l, matches);\n            has_found_match = BROTLI_TRUE;\n          }\n        }\n      }\n    }\n  }\n  if (max_length >= 9) {\n    /* Transforms with prefixes \" the \" and \".com/\" */\n    if ((data[0] == ' ' && data[1] == 't' && data[2] == 'h' &&\n         data[3] == 'e' && data[4] == ' ') ||\n        (data[0] == '.' && data[1] == 'c' && data[2] == 'o' &&\n         data[3] == 'm' && data[4] == '/')) {\n      size_t offset = dictionary->buckets[Hash(&data[5])];\n      BROTLI_BOOL end = !offset;\n      while (!end) {\n        DictWord w = dictionary->dict_words[offset++];\n        const size_t l = w.len & 0x1F;\n        const size_t n = (size_t)1 << dictionary->words->size_bits_by_length[l];\n        const size_t id = w.idx;\n        end = !!(w.len & 0x80);\n        w.len = (uint8_t)l;\n        if (w.transform == 0 &&\n            IsMatch(dictionary->words, w, &data[5], max_length - 5)) {\n          AddMatch(id + (data[0] == ' ' ? 41 : 72) * n, l + 5, l, matches);\n          has_found_match = BROTLI_TRUE;\n          if (l + 5 < max_length) {\n            const uint8_t* s = &data[l + 5];\n            if (data[0] == ' ') {\n              if (l + 8 < max_length &&\n                  s[0] == ' ' && s[1] == 'o' && s[2] == 'f' && s[3] == ' ') {\n                AddMatch(id + 62 * n, l + 9, l, matches);\n                if (l + 12 < max_length &&\n                    s[4] == 't' && s[5] == 'h' && s[6] == 'e' && s[7] == ' ') {\n                  AddMatch(id + 73 * n, l + 13, l, matches);\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n  }\n  return has_found_match;\n}\n\n/* Finds matches for one or more dictionaries, if multiple are present\n   in the contextual dictionary */\nBROTLI_BOOL BrotliFindAllStaticDictionaryMatches(\n    const BrotliEncoderDictionary* dictionary, const uint8_t* data,\n    size_t min_length, size_t max_length, uint32_t* matches) {\n  BROTLI_BOOL has_found_match =\n      BrotliFindAllStaticDictionaryMatchesFor(\n          dictionary, data, min_length, max_length, matches);\n\n  if (!!dictionary->parent && dictionary->parent->num_dictionaries > 1) {\n    uint32_t matches2[BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1];\n    int l;\n    const BrotliEncoderDictionary* dictionary2 = dictionary->parent->dict[0];\n    if (dictionary2 == dictionary) {\n      dictionary2 = dictionary->parent->dict[1];\n    }\n\n    for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) {\n      matches2[l] = kInvalidMatch;\n    }\n\n    has_found_match |= BrotliFindAllStaticDictionaryMatchesFor(\n        dictionary2, data, min_length, max_length, matches2);\n\n    for (l = 0; l < BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1; l++) {\n      if (matches2[l] != kInvalidMatch) {\n        uint32_t dist = (uint32_t)(matches2[l] >> 5);\n        uint32_t len_code = matches2[l] & 31;\n        uint32_t skipdist = (uint32_t)((uint32_t)(1 << dictionary->words->\n            size_bits_by_length[len_code]) & ~1u) *\n            (uint32_t)dictionary->num_transforms;\n        /* TODO(lode): check for dist overflow */\n        dist += skipdist;\n        AddMatch(dist, (size_t)l, len_code, matches);\n      }\n    }\n  }\n  return has_found_match;\n}\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/static_dict.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Class to model the static dictionary. */\n\n#ifndef BROTLI_ENC_STATIC_DICT_H_\n#define BROTLI_ENC_STATIC_DICT_H_\n\n#include <brotli/types.h>\n\n#include \"../common/dictionary.h\"\n#include \"../common/platform.h\"\n#include \"encoder_dict.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN 37\nstatic const uint32_t kInvalidMatch = 0xFFFFFFF;\n\n/* Matches data against static dictionary words, and for each length l,\n   for which a match is found, updates matches[l] to be the minimum possible\n     (distance << 5) + len_code.\n   Returns 1 if matches have been found, otherwise 0.\n   Prerequisites:\n     matches array is at least BROTLI_MAX_STATIC_DICTIONARY_MATCH_LEN + 1 long\n     all elements are initialized to kInvalidMatch */\nBROTLI_INTERNAL BROTLI_BOOL BrotliFindAllStaticDictionaryMatches(\n    const BrotliEncoderDictionary* dictionary,\n    const uint8_t* data, size_t min_length, size_t max_length,\n    uint32_t* matches);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_STATIC_DICT_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/static_dict_lut.h",
    "content": "/* Copyright 2015 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Lookup table for static dictionary and transforms. */\n\n#ifndef BROTLI_ENC_STATIC_DICT_LUT_H_\n#define BROTLI_ENC_STATIC_DICT_LUT_H_\n\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\ntypedef struct DictWord {\n  /* Highest bit is used to indicate end of bucket. */\n  uint8_t len;\n  uint8_t transform;\n  uint16_t idx;\n} DictWord;\n\n/* GENERATED CODE START */\nstatic const int kDictNumBits = 15;\nstatic const uint32_t kDictHashMul32 = 0x1E35A7BD;\n\nstatic const uint16_t kStaticDictionaryBuckets[32768] = {\n1,0,0,0,0,0,0,0,0,3,6,0,0,0,0,0,20,0,0,0,21,0,22,0,0,0,0,0,0,0,0,23,0,0,25,0,29,\n0,53,0,0,0,0,0,0,55,0,0,0,0,0,0,61,76,0,0,0,94,0,0,0,0,0,0,96,0,97,0,98,0,0,0,0,\n0,0,0,99,101,106,108,0,0,0,0,0,110,0,111,112,0,113,118,124,0,0,0,0,0,125,128,0,0\n,0,0,129,0,0,131,0,0,0,0,0,0,132,0,0,135,0,0,0,137,0,0,0,0,0,138,139,0,0,0,0,0,0\n,0,142,143,144,0,0,0,0,0,145,0,0,0,146,149,151,152,0,0,153,0,0,0,0,0,0,0,0,0,0,0\n,0,0,0,0,154,0,0,0,0,0,0,155,0,0,0,0,160,182,0,0,0,0,0,0,183,0,0,0,188,189,0,0,\n192,0,0,0,0,0,0,194,0,0,0,0,0,0,0,0,197,202,209,0,0,210,0,224,0,0,0,225,0,0,0,0,\n0,0,0,0,0,0,231,0,0,0,232,0,240,0,0,242,0,0,0,0,0,0,0,0,0,0,0,244,0,0,0,246,0,0,\n249,251,253,0,0,0,0,0,258,0,0,261,263,0,0,0,267,0,0,268,0,269,0,0,0,0,0,0,0,0,0,\n271,0,0,0,0,0,0,272,0,273,0,277,0,278,286,0,0,0,0,287,0,289,290,291,0,0,0,295,0,\n0,296,297,0,0,0,0,0,0,0,0,0,0,298,0,0,0,299,0,0,305,0,324,0,0,0,0,0,327,0,328,\n329,0,0,0,0,336,0,0,340,0,341,342,343,0,0,346,0,348,0,0,0,0,0,0,349,351,0,0,355,\n0,363,0,364,0,368,369,0,370,0,0,0,0,0,0,0,372,0,0,0,0,0,0,0,0,0,0,0,373,0,375,0,\n0,0,0,376,377,0,0,394,395,396,0,0,398,0,0,0,0,400,0,0,408,0,0,0,0,420,0,0,0,0,0,\n0,421,0,0,422,423,0,0,429,435,436,442,0,0,443,0,444,445,453,456,0,457,0,0,0,0,0,\n458,0,0,0,459,0,0,0,460,0,462,463,465,0,0,0,0,0,0,466,469,0,0,0,0,0,0,470,0,0,0,\n474,0,476,0,0,0,0,483,0,485,0,0,0,486,0,0,488,491,492,0,0,497,499,500,0,501,0,0,\n0,505,0,0,506,0,0,0,507,0,0,0,509,0,0,0,0,511,512,519,0,0,0,0,0,0,529,530,0,0,0,\n534,0,0,0,0,543,0,0,0,0,0,0,0,0,0,553,0,0,0,0,557,560,0,0,0,0,0,0,561,0,564,0,0,\n0,0,0,0,565,566,0,575,0,619,0,620,0,0,623,624,0,0,0,625,0,0,626,627,0,0,628,0,0,\n0,0,630,0,631,0,0,0,0,0,0,0,0,0,641,0,0,0,0,643,656,668,0,0,0,673,0,0,0,674,0,0,\n0,0,0,0,0,0,682,0,687,0,690,0,693,699,700,0,0,0,0,0,0,704,705,0,0,0,0,707,710,0,\n711,0,0,0,0,726,0,0,729,0,0,0,730,731,0,0,0,0,0,752,0,0,0,762,0,763,0,0,767,0,0,\n0,770,774,0,0,775,0,0,0,0,0,0,0,0,0,0,776,0,0,0,777,783,0,0,0,785,788,0,0,0,0,\n790,0,0,0,793,0,0,0,0,794,0,0,804,819,821,0,827,0,0,0,834,0,0,835,0,0,0,841,0,\n844,0,850,851,859,0,860,0,0,0,0,0,0,0,874,0,876,0,877,890,0,0,0,0,0,0,0,0,893,\n894,898,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,899,0,0,0,900,904,906,0,0,0,907,0,908,909,\n0,910,0,0,0,0,911,0,0,0,0,0,916,0,0,0,922,925,0,930,0,934,0,0,0,0,0,943,0,0,944,\n0,953,954,0,0,0,0,0,0,955,0,962,963,0,0,976,0,0,977,978,979,980,0,981,0,0,0,0,\n984,0,0,985,0,0,987,989,991,0,0,0,0,0,0,0,0,0,992,0,0,0,993,0,0,0,0,0,0,996,0,0,\n0,1000,0,0,0,0,0,1002,0,0,0,0,1005,1007,0,0,0,1009,0,0,0,1010,0,0,0,0,0,0,1011,0\n,1012,0,0,0,0,1014,1016,0,0,0,1020,0,1021,0,0,0,0,1022,0,0,0,1024,0,0,0,0,0,0,\n1025,0,0,1026,1027,0,0,0,0,0,1031,0,1033,0,0,0,0,1034,0,0,0,1037,1040,0,0,0,1042\n,1043,0,0,1053,0,1054,0,0,1057,0,0,0,1058,0,0,1060,0,0,0,0,0,0,0,1061,0,0,1062,0\n,0,0,0,1063,0,0,0,0,1064,0,0,0,0,0,1065,0,0,0,0,1066,1067,0,0,0,1069,1070,1072,0\n,0,0,0,0,0,1073,0,1075,0,0,0,0,0,0,1080,1084,0,0,0,0,1088,0,0,0,0,0,0,1094,0,\n1095,0,1107,0,0,0,1112,1114,0,1119,0,1122,0,0,1126,0,1129,0,1130,0,0,0,0,0,1132,\n0,0,0,0,0,0,1144,0,0,1145,1146,0,1148,1149,0,0,1150,1151,0,0,0,0,1152,0,1153,0,0\n,0,0,0,1154,0,1163,0,0,0,1164,0,0,0,0,0,1165,0,1167,0,1170,0,0,0,0,0,1171,1172,0\n,0,0,0,0,0,0,0,1173,1175,1177,0,1186,0,0,0,0,0,0,0,0,0,0,1195,0,0,1221,0,0,1224,\n0,0,1227,0,0,0,0,0,1228,1229,0,0,1230,0,0,0,0,0,0,0,0,0,1231,0,0,0,1233,0,0,1243\n,1244,1246,1248,0,0,0,0,1254,1255,1258,1259,0,0,0,1260,0,0,1261,0,0,0,1262,1264,\n0,0,1265,0,0,0,0,0,0,0,0,0,0,0,0,1266,0,1267,0,0,0,0,1273,1274,1276,1289,0,0,\n1291,1292,1293,0,0,1294,1295,1296,0,0,0,0,1302,0,1304,0,0,0,0,0,0,0,0,0,1311,\n1312,0,1314,0,1316,1320,1321,0,0,0,0,0,0,0,1322,1323,1324,0,1335,0,1336,0,0,0,0,\n1341,1342,0,1346,0,1357,0,0,0,1358,1360,0,0,0,0,0,0,1361,0,0,0,1362,1365,0,1366,\n0,0,0,0,0,0,0,1379,0,0,0,0,0,0,0,0,0,0,0,0,1386,0,1388,0,0,0,0,0,0,0,0,0,0,0,0,0\n,0,1395,0,0,0,0,1403,0,1405,0,0,1407,0,0,0,0,0,1408,1409,0,1410,0,0,0,1412,1413,\n1416,0,0,1429,1451,0,0,1454,0,0,0,0,0,0,0,1455,0,0,0,0,0,0,0,1456,0,0,0,0,1459,\n1460,1461,1475,0,0,0,0,0,0,1477,0,1480,0,1481,0,0,1486,0,0,1495,0,0,0,1496,0,0,\n1498,1499,1501,1520,1521,0,0,0,1526,0,0,0,0,1528,1529,0,1533,1536,0,0,0,1537,\n1538,1549,0,1550,1558,1559,1572,0,1573,0,0,0,0,0,0,0,0,0,1575,0,0,0,0,0,1579,0,\n1599,0,1603,0,1604,0,1605,0,0,0,0,0,1608,1610,0,0,0,0,1611,0,1615,0,1616,1618,0,\n1619,0,0,1622,0,0,0,0,1634,0,0,0,1635,0,0,0,1641,0,0,0,0,0,0,0,0,0,1643,0,0,0,\n1650,0,0,1652,0,0,0,0,0,1653,0,0,0,1654,0,0,0,0,1655,0,1662,0,0,1663,1664,0,0,\n1668,0,0,1669,1670,0,1672,1673,0,0,0,0,0,1674,0,0,0,1675,1676,1680,0,1682,0,0,\n1687,0,0,0,0,0,1704,0,0,1705,0,0,1721,0,0,0,0,1734,1735,0,0,0,0,1737,0,0,0,0,\n1739,0,0,1740,0,0,0,0,0,0,0,0,0,0,1741,1743,0,0,0,0,1745,0,0,0,1749,0,0,0,1751,0\n,0,0,0,0,0,1760,0,0,0,0,1765,0,0,0,0,0,1784,0,1785,1787,0,0,0,0,1788,1789,0,0,0,\n0,1790,1791,1793,0,1798,1799,0,0,0,0,1801,0,1803,1805,0,0,0,1806,1811,0,1812,\n1814,0,1821,0,0,0,0,0,1822,1833,0,0,0,0,0,0,1848,0,0,0,0,0,0,1857,0,0,0,1859,0,0\n,0,0,1861,0,0,0,0,0,0,0,1866,0,1921,1925,0,0,0,1929,1930,0,0,0,0,0,0,0,0,0,1931,\n0,0,0,0,1932,0,0,0,1934,0,0,0,0,0,0,0,0,1946,0,0,1948,0,0,0,0,1950,0,1957,0,1958\n,0,0,0,0,0,1965,1967,0,0,0,0,1968,0,1969,0,1971,1972,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n,0,1973,0,0,0,0,1975,0,0,0,0,1976,1979,0,1982,0,0,0,0,1984,1988,0,0,0,0,1990,\n2004,2008,0,0,0,2012,2013,0,0,0,0,0,0,0,0,0,0,2015,0,2016,2017,0,0,0,0,2021,0,0,\n2025,0,0,0,0,0,2029,2036,2040,0,2042,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2043,0,0,0,0,0,\n2045,0,0,0,0,0,0,0,2046,2047,0,2048,2049,0,2059,0,0,2063,0,2064,2065,0,0,2066,0,\n0,0,0,0,0,2069,0,0,0,0,2070,0,2071,0,2072,0,0,0,0,2080,2082,2083,0,0,0,0,0,2085,\n0,2086,2088,2089,2105,0,0,0,0,2107,0,0,2116,2117,0,2120,0,0,2122,0,0,0,0,0,2123,\n0,0,2125,2127,2128,0,0,0,2130,0,0,0,2137,2139,2140,2141,0,0,0,0,0,0,0,0,0,2144,\n2145,0,0,2146,2149,0,0,0,0,2150,0,0,2151,2158,0,2159,0,2160,0,0,0,0,0,0,2161,\n2162,0,0,2194,2202,0,0,0,0,0,0,2205,2217,0,2220,0,2221,0,2222,2224,0,0,0,0,2237,\n0,0,0,0,0,2238,0,2239,2241,0,0,2242,0,0,0,0,0,2243,0,0,0,0,0,0,2252,0,0,2253,0,0\n,0,2257,2258,0,0,0,2260,0,0,0,0,0,0,0,2262,0,2264,0,0,0,0,0,2269,2270,0,0,0,0,0,\n0,0,0,0,2271,0,2273,0,0,0,0,2277,0,0,0,0,2278,0,0,0,0,2279,0,2280,0,2283,0,0,0,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2287,0,0,0,0,0,0,0,2289,2290,0,0,0,0,2291,0,2292,0,\n0,0,2293,2295,2296,0,0,0,0,0,0,0,2298,0,0,0,0,0,2303,0,2305,0,0,2306,0,2307,0,0,\n0,0,0,0,0,0,0,0,0,0,2313,2314,2315,2316,0,0,2318,0,2319,0,2322,0,0,2323,0,2324,0\n,2326,0,0,0,0,0,0,0,2335,0,2336,2338,2339,0,2340,0,0,0,2355,0,2375,0,2382,2386,0\n,2387,0,0,2394,0,0,0,0,2395,0,2397,0,0,0,0,0,2398,0,0,0,0,0,0,0,2399,2402,2404,\n2408,2411,0,0,0,2413,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2415,0,0,2416,2417,2419,0,2420,\n0,0,0,0,0,2425,0,0,0,2426,0,0,0,0,0,0,0,0,0,0,0,0,2427,2428,0,2429,0,0,2430,2434\n,0,2436,0,0,0,0,0,0,2441,2442,0,2445,0,0,2446,2457,0,2459,0,0,2462,0,2464,0,2477\n,0,2478,2486,0,0,0,2491,0,0,2493,0,0,2494,0,2495,0,2513,2523,0,0,0,0,2524,0,0,0,\n0,0,0,2528,2529,2530,0,0,2531,0,2533,0,0,2534,2535,0,2536,2537,0,2538,0,2539,\n2540,0,0,0,2545,2546,0,0,0,0,0,0,0,2548,0,0,2549,0,2550,2555,0,0,0,0,0,2557,0,\n2560,0,0,0,0,0,0,0,0,0,0,0,2561,0,2576,0,0,0,0,0,0,0,0,0,2577,2578,0,0,0,2579,0,\n0,0,0,0,0,0,2580,0,0,0,0,2581,0,0,0,0,2583,0,2584,0,2588,2590,0,0,0,2591,0,0,0,0\n,2593,2594,0,2595,0,2601,2602,0,0,2603,0,2605,0,0,0,2606,2607,2611,0,2615,0,0,0,\n2617,0,0,0,0,0,0,0,0,0,0,0,0,0,2619,0,0,2620,0,0,0,2621,0,2623,0,2625,0,0,2628,\n2629,0,0,2635,2636,2637,0,0,2639,0,0,0,2642,0,0,0,0,2643,0,2644,0,2649,0,0,0,0,0\n,0,2655,2656,0,0,2657,0,0,0,0,0,2658,0,0,0,0,0,2659,0,0,0,0,2664,2685,0,2687,0,\n2688,0,0,2689,0,0,2694,0,2695,0,0,2698,0,2701,2706,0,0,0,2707,0,2709,2710,2711,0\n,0,0,2720,2730,2735,0,0,0,0,2738,2740,0,0,0,0,2747,0,0,0,0,0,0,2748,0,0,2749,0,0\n,0,0,0,2750,0,0,2752,2754,0,0,0,0,0,2758,0,0,0,0,2762,0,0,0,0,2763,0,0,0,0,0,0,0\n,2764,2767,0,0,0,0,2768,0,0,2770,0,0,0,0,0,0,0,2771,0,0,0,0,0,0,0,0,0,2772,0,0,0\n,0,0,2773,2776,0,0,2783,0,0,2784,0,2789,0,2790,0,0,0,2792,0,0,0,0,0,0,0,0,0,0,\n2793,2795,0,0,0,0,0,0,2796,0,0,0,0,0,0,2797,2799,0,0,0,0,2803,0,0,0,0,2806,0,\n2807,2808,2817,2819,0,0,0,0,0,2821,0,0,0,0,2822,2823,0,0,0,0,0,0,0,2824,0,0,2828\n,0,2834,0,0,0,0,0,0,2836,0,2838,0,0,2839,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2841,\n0,0,0,2842,0,0,0,0,0,2843,2844,0,0,0,0,2846,0,0,2847,0,2849,0,2853,0,0,0,0,0,\n2857,0,0,0,0,2858,0,2859,0,0,2860,0,2862,2868,0,0,0,0,2875,0,2876,0,0,2877,2878,\n2884,2889,2890,0,0,2891,0,0,2892,0,0,0,2906,2912,0,2913,0,0,0,0,0,0,0,0,2916,0,\n2934,0,0,0,0,0,2935,0,0,0,0,2939,0,2940,0,0,0,0,0,0,0,2941,0,0,0,2946,0,2949,0,0\n,2950,2954,2955,0,0,0,2959,2961,0,0,2962,0,2963,0,0,0,0,0,0,2964,2965,2966,2967,\n0,0,0,0,0,0,0,2969,0,0,0,0,0,2970,2975,0,2982,2983,2984,0,0,0,0,0,2989,0,0,2990,\n0,0,0,0,0,0,0,2991,0,0,0,0,0,0,0,0,2998,0,3000,3001,0,0,3002,0,0,0,3003,0,0,3012\n,0,0,3022,0,0,3024,0,0,3025,3027,0,0,0,3030,0,0,0,0,3034,3035,0,0,3036,0,3039,0,\n3049,0,0,3050,0,0,0,0,0,0,3051,0,3053,0,0,0,0,3057,0,3058,0,0,0,0,0,0,0,0,3063,0\n,0,3073,3074,3078,3079,0,3080,3086,0,0,0,0,0,0,0,0,3087,0,3092,0,3095,0,3099,0,0\n,0,3100,0,3101,3102,0,3122,0,0,0,3124,0,3125,0,0,0,0,0,0,3132,3134,0,0,3136,0,0,\n0,0,0,0,0,3147,0,0,3149,0,0,0,0,0,3150,3151,3152,0,0,0,0,3158,0,0,3160,0,0,3161,\n0,0,3162,0,3163,3166,3168,0,0,3169,3170,0,0,3171,0,0,0,0,0,0,0,3182,0,3184,0,0,\n3188,0,0,3194,0,0,0,0,0,0,3204,0,0,0,0,3209,0,0,0,0,0,0,0,0,0,0,0,3216,3217,0,0,\n0,0,0,0,0,3219,0,0,3220,3222,0,3223,0,0,0,0,3224,0,3225,3226,0,3228,3233,0,3239,\n3241,3242,0,0,3251,3252,3253,3255,0,0,0,0,0,0,0,0,3260,0,0,3261,0,0,0,3267,0,0,0\n,0,0,0,0,0,3271,0,0,0,3278,0,3282,0,0,0,3284,0,0,0,3285,3286,0,0,0,0,0,0,0,3287,\n3292,0,0,0,0,3294,3296,0,0,3299,3300,3301,0,3302,0,0,0,0,0,3304,3306,0,0,0,0,0,0\n,3308,0,0,0,0,0,0,0,0,0,3311,0,0,0,0,0,0,0,0,3312,3314,3315,0,3318,0,0,0,0,0,0,0\n,0,3319,0,0,0,0,0,3321,0,0,0,0,0,0,0,0,0,3322,0,0,3324,3325,0,0,3326,0,0,3328,\n3329,3331,0,0,3335,0,0,3337,0,3338,0,0,0,0,3343,3347,0,0,0,3348,0,0,3351,0,0,0,0\n,0,0,3354,0,0,0,0,0,0,0,0,0,0,3355,0,0,3365,3366,3367,0,0,0,0,0,0,3368,3369,0,\n3370,0,0,3373,0,0,3376,0,0,3377,0,3379,3387,0,0,0,0,0,3390,0,0,0,0,0,0,0,3402,0,\n3403,3436,3437,3439,0,0,3441,0,0,0,3442,0,0,3449,0,0,0,3450,0,0,0,0,0,0,0,3451,0\n,0,3452,0,3453,3456,0,3457,0,0,3458,0,3459,0,0,0,0,0,0,0,0,0,3460,0,0,3469,3470,\n0,0,3475,0,0,0,3480,3487,3489,0,3490,0,0,3491,3499,0,3500,0,0,3501,0,0,0,3502,0,\n3514,0,0,0,3516,3517,0,0,0,3518,0,0,0,0,3520,3521,3522,0,0,3526,3530,0,0,0,0,\n3531,0,0,0,0,3536,0,0,0,0,0,0,0,3539,3541,0,0,3542,3544,0,3547,3548,0,0,3550,0,\n3553,0,0,0,0,0,0,0,3554,0,3555,0,3558,0,3559,0,0,0,0,0,0,0,0,3563,0,3581,0,0,0,\n3599,0,0,0,3600,0,3601,0,3602,3603,0,0,3606,3608,0,3610,3611,0,0,0,0,0,0,0,0,0,\n3612,3616,3619,0,0,0,0,0,0,0,0,0,0,0,0,0,3624,3628,0,3629,3634,3635,0,0,0,0,0,0,\n3636,0,3637,0,0,3638,3651,0,0,0,0,0,0,3652,3653,0,0,0,0,3656,3657,0,0,0,0,0,3658\n,0,0,0,0,3659,0,3661,3663,3664,0,3665,0,3692,0,0,0,3694,3696,0,0,0,0,0,0,0,0,0,0\n,0,0,3698,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3700,0,0,3701,0,0,0,3708,3709,0,0,0,3711\n,3712,0,0,0,0,0,3723,0,3724,3725,0,0,3726,0,0,0,0,0,0,3728,3729,0,3734,3735,3737\n,0,0,0,3743,0,3745,0,0,3746,0,0,3747,3748,0,3757,0,3759,3766,3767,0,3768,0,0,0,0\n,3769,0,0,3771,0,3774,0,0,0,0,0,0,3775,0,0,0,0,0,0,3776,0,3777,3786,0,3788,3789,\n0,0,0,0,0,0,0,0,0,3791,0,3811,0,0,0,0,0,3814,3815,3816,3820,0,0,0,0,0,0,0,3821,0\n,0,3825,0,0,0,0,3835,0,0,3848,3849,0,0,0,0,3850,3851,3853,0,0,0,0,3859,0,3860,\n3862,0,0,0,0,0,3863,0,0,0,0,0,0,0,0,3873,0,3874,0,3875,3886,0,3887,0,0,0,0,3892,\n3913,0,3914,0,0,0,3925,3931,0,0,0,0,3934,3941,3942,0,0,0,0,3943,0,0,0,3944,0,0,0\n,0,0,3945,0,3947,0,0,0,3956,3957,0,0,0,0,0,0,0,0,0,3958,0,3959,3965,0,0,0,0,3966\n,0,0,0,3967,0,0,0,3968,3974,0,0,0,0,0,3975,3977,3978,0,0,0,0,3980,0,3985,0,0,0,0\n,0,0,0,0,3986,4011,0,0,4017,0,0,0,0,0,0,0,0,0,0,0,4018,0,0,0,0,4019,0,4023,0,0,0\n,4027,4028,0,0,0,0,0,0,0,0,4031,4034,0,0,4035,4037,4039,4040,0,0,0,0,0,4059,0,\n4060,4061,0,4062,4063,4066,0,0,4072,0,0,0,0,0,0,0,0,0,0,0,0,0,4088,0,0,0,0,0,\n4091,0,0,0,0,4094,4095,0,0,4096,0,0,0,0,0,4098,4099,0,0,0,4101,0,4104,0,0,0,4105\n,4108,0,4113,0,0,4115,4116,0,4126,0,0,4127,0,0,0,0,0,0,0,4128,4132,4133,0,4134,0\n,0,0,4137,0,0,4141,0,0,0,0,4144,4146,4147,0,0,0,0,4148,0,0,4311,0,0,0,4314,4329,\n0,4331,4332,0,4333,0,4334,0,0,0,4335,0,4336,0,0,0,4337,0,0,0,4342,4345,4346,4350\n,0,4351,4352,0,4354,4355,0,0,4364,0,0,0,0,4369,0,0,0,4373,0,4374,0,0,0,0,4377,0,\n0,0,0,4378,0,0,0,4380,0,0,0,4381,4382,0,0,0,0,0,0,0,4384,0,0,0,0,4385,0,0,0,4386\n,0,0,0,4391,4398,0,0,0,0,4407,4409,0,0,0,0,4410,0,0,4411,0,4414,4415,4418,0,4427\n,4428,4430,0,4431,0,4448,0,0,0,0,0,4449,0,0,0,4451,4452,0,4453,4454,0,4456,0,0,0\n,0,0,0,0,4459,0,4463,0,0,0,0,0,4466,0,4467,0,4469,0,0,0,0,0,0,0,0,0,0,0,0,0,4470\n,4471,0,4473,0,0,4475,0,0,0,0,4477,4478,0,0,0,4479,4481,0,4482,0,4484,0,0,0,0,0,\n0,0,4486,0,0,4488,0,0,4497,0,4508,0,0,4510,4511,0,4520,4523,0,4524,0,4525,0,4527\n,0,0,4528,0,0,0,0,4530,0,4531,0,0,4532,0,0,0,4533,0,0,0,0,0,4535,0,0,0,4536,0,0,\n0,0,0,4541,4543,4544,4545,4547,0,4548,0,0,0,0,4550,4551,0,4553,0,0,0,0,4562,0,0,\n4571,0,0,0,4574,0,0,0,4575,0,4576,0,4577,0,0,0,4581,0,0,0,0,0,4582,0,0,4586,0,0,\n0,4588,0,0,4597,0,4598,0,0,0,0,4616,4617,0,4618,0,0,0,0,4619,0,4620,0,0,4621,0,\n4624,0,0,0,0,0,4625,0,0,0,0,4657,0,4659,0,4667,0,0,0,4668,4670,0,4672,0,0,0,0,0,\n4673,4676,0,0,0,0,4687,0,0,0,0,4697,0,0,0,0,4699,0,4701,0,0,0,0,4702,0,0,4706,0,\n0,4713,0,0,0,4714,4715,4716,0,0,0,0,0,0,0,0,0,0,0,0,4717,0,0,4720,0,4721,4729,\n4735,0,0,0,4737,0,0,0,4739,0,0,0,4740,0,0,0,4741,0,0,0,0,0,4742,0,4745,4746,4747\n,0,0,0,0,0,0,0,0,4748,0,0,0,4749,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4751,\n4786,0,4787,0,4788,4796,0,0,4797,4798,0,4799,4806,4807,0,0,0,0,4809,4810,0,0,0,0\n,0,0,4811,0,0,0,0,0,4812,0,4813,0,0,4815,0,4821,4822,0,0,0,0,4823,0,0,0,0,0,0,0,\n0,0,0,4824,0,0,0,0,4826,0,0,0,4828,0,4829,0,0,0,4843,0,0,4847,0,4853,4855,4858,0\n,0,0,0,0,4859,0,4864,0,0,4879,0,0,0,0,4880,0,0,0,0,4881,0,4882,0,0,0,0,0,0,0,0,0\n,4883,0,0,0,0,4884,0,0,0,0,0,4886,4887,4888,4894,4896,0,4902,0,0,4905,0,0,4915,0\n,0,0,0,0,0,0,4916,4917,4919,4921,0,0,0,0,0,4926,0,0,0,0,4927,0,0,0,0,0,0,0,0,\n4929,0,4930,4931,0,4938,0,4952,0,4953,4957,4960,4964,0,0,0,0,0,0,0,5019,5020,\n5022,0,0,0,0,0,5023,0,0,0,5024,0,0,0,5025,0,0,0,0,5028,0,0,0,0,5029,5030,5031,0,\n5033,0,0,0,0,0,0,0,0,0,5034,5035,0,5036,0,0,5037,0,0,0,0,5038,0,0,5039,0,0,0,\n5041,5042,0,0,0,0,5044,5049,5054,0,5055,0,5057,0,0,0,5060,0,0,0,0,0,5063,0,5064,\n5065,0,5067,0,0,0,5068,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5076,0,0,0,0,0,0,\n0,5077,0,0,5078,5080,0,0,5083,0,0,0,0,0,0,0,0,5085,0,0,0,0,0,0,5098,5099,5101,\n5105,5107,0,5108,0,5109,0,0,0,0,0,0,0,5110,0,0,0,0,0,5117,5118,0,5121,0,5122,0,0\n,5130,0,0,0,5137,0,0,0,5148,0,0,0,0,0,0,0,5151,5154,0,0,0,5155,0,0,5156,5159,\n5161,0,0,0,0,5162,0,0,0,0,5163,5164,0,5166,0,0,0,0,0,0,0,0,0,0,5167,0,0,0,5172,0\n,0,0,0,0,0,5178,5179,0,0,5190,0,0,5191,5192,5194,0,0,5198,5201,0,0,0,0,0,5203,0,\n5206,5209,0,0,0,0,0,0,5213,0,5214,5216,0,0,0,0,0,5217,0,0,0,0,0,0,0,0,5218,5219,\n0,5231,0,0,5244,5249,0,5254,0,5255,0,0,5257,0,0,0,0,0,5258,0,5260,5270,0,5277,0,\n0,0,0,0,0,5280,5281,5282,5283,0,0,0,0,0,5284,0,5285,0,0,0,0,0,5287,5288,0,0,0,0,\n0,0,0,0,0,0,5289,5291,0,0,5294,0,0,5295,0,0,0,0,0,0,0,5304,0,0,5306,5307,5308,0,\n5309,0,0,5310,0,0,0,0,5311,5312,0,5313,0,0,0,0,0,5316,0,0,0,5317,0,0,0,0,0,0,0,0\n,0,5325,0,0,0,0,0,0,5326,0,5327,5329,0,5332,0,0,0,0,5338,0,0,0,0,0,0,0,0,5340,0,\n0,5341,0,0,0,5342,0,5343,5344,0,0,5345,0,0,0,0,0,0,5347,5348,0,0,0,0,0,0,0,0,0,\n5349,0,5350,0,5354,0,0,0,0,5358,0,0,5359,0,0,5361,0,0,5365,0,5367,0,5373,0,0,0,\n5379,0,0,0,5380,0,0,0,5382,0,5384,0,0,0,0,0,0,5385,0,0,0,0,5387,0,0,0,0,0,0,5388\n,5390,5393,0,0,0,0,0,0,0,0,0,0,0,5396,0,0,0,0,5397,5402,0,0,0,0,0,5403,0,0,0,\n5404,5405,0,0,0,0,0,0,0,0,0,0,0,0,5406,0,0,0,0,5410,0,0,5411,0,5415,0,0,0,0,5416\n,5434,0,0,0,0,0,0,0,0,0,0,0,5438,0,5440,0,0,0,0,0,0,5441,5442,0,0,0,5443,5444,\n5447,0,0,5448,5449,5451,0,0,0,5456,5457,0,0,0,5459,0,0,0,5461,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,5464,0,5466,0,0,5467,0,5470,0,0,5473,0,0,5474,0,0,5476,0,0,0,0,0,0,0,0\n,0,0,0,5477,0,0,0,0,0,0,0,5484,0,0,5485,5486,0,0,0,0,0,5488,0,0,0,0,0,0,0,5489,0\n,0,0,0,0,5507,0,0,0,5510,0,5511,0,0,5512,0,0,0,5513,0,5515,0,0,5516,5517,0,5518,\n0,0,5522,0,0,0,0,0,5534,5535,0,0,5536,0,5538,0,0,5543,0,5544,0,0,5545,0,5547,0,\n5557,0,0,5558,0,5560,5567,0,0,0,0,5568,0,0,0,5571,5573,0,5574,0,5575,0,0,0,0,\n5577,0,0,5598,0,0,0,0,0,0,0,0,0,5600,5609,0,0,0,0,5610,0,0,5612,0,5624,0,5625,0,\n0,0,5629,0,5641,0,5642,5643,0,0,0,0,0,0,5651,0,0,0,5652,5653,0,5661,5662,5678,0,\n5679,0,0,0,0,5685,5686,0,0,0,0,0,5690,5692,0,5703,0,0,0,0,0,5706,0,0,0,0,5707,0,\n0,0,0,0,0,5708,0,0,5709,0,5710,0,0,0,5712,0,5733,0,5734,5735,0,0,5744,5751,0,0,0\n,0,0,0,0,0,0,0,0,0,5752,0,5754,0,0,0,0,0,0,5757,5758,0,5760,5761,0,0,0,0,5763,\n5764,5765,0,5766,0,5767,5768,0,5770,0,0,0,0,5776,5780,0,0,0,0,5782,0,0,0,0,5784,\n0,0,5788,0,0,0,0,0,0,0,0,0,0,0,5797,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5799,0,0,5801,\n0,0,0,5811,0,0,0,0,0,0,5816,0,0,5827,0,0,0,0,0,0,0,0,5830,5831,0,0,5832,0,0,5833\n,0,5835,5844,5845,0,5846,0,0,0,0,0,5850,0,0,0,0,0,5852,0,5855,5857,0,0,5859,0,\n5861,0,0,5863,0,5865,0,0,0,5873,5875,0,0,0,5877,0,5879,0,0,0,5888,0,0,5889,5891,\n0,5894,0,0,0,0,0,0,5895,0,5897,0,0,0,0,0,0,5907,0,5911,0,0,5912,0,5913,5922,5924\n,0,5927,5928,0,0,0,0,5929,5930,0,5933,0,0,0,0,5949,0,0,5951,0,0,0,0,0,0,0,0,5953\n,0,0,5954,0,5959,5960,5961,0,5964,0,0,0,5976,5978,5987,5990,0,0,0,0,0,5991,0,\n5992,0,0,0,5994,5995,0,0,5996,0,0,6001,6003,0,0,0,0,6007,0,0,0,0,0,6008,0,0,6009\n,0,6010,0,0,0,6011,6015,0,6017,0,6019,0,6023,0,0,0,0,0,0,0,6025,0,0,0,0,0,0,0,0,\n0,0,6026,0,6030,0,0,6032,0,0,0,6033,6038,6040,0,0,0,6041,6045,0,0,6046,0,0,6053,\n0,0,6054,0,6055,0,0,0,0,0,0,6057,0,6063,0,0,0,6064,0,6066,6071,6072,0,0,0,0,0,0,\n6075,6076,0,0,6077,0,0,0,0,0,0,0,0,0,6078,6079,0,0,0,0,0,0,0,0,6080,0,6083,0,0,0\n,0,0,6084,0,0,6088,0,6089,0,0,6093,6105,0,0,6107,0,6110,0,0,0,6111,6125,6126,0,0\n,0,6129,0,0,0,0,6130,0,0,0,6131,6134,0,0,0,0,0,0,6142,0,0,0,0,0,6144,0,0,6146,\n6151,6153,0,6156,0,6163,0,6180,6181,0,0,0,0,0,6182,0,0,0,0,6184,6195,0,0,6206,0,\n6208,0,0,6212,6213,6214,0,6215,0,0,0,6228,0,0,0,6234,0,0,0,0,0,0,6235,6240,0,\n6242,6243,6244,0,6250,6255,0,0,0,0,0,6257,0,0,0,6258,6278,0,6284,0,0,0,6285,0,0,\n0,0,0,0,0,0,6286,0,0,0,6320,0,0,6322,6332,0,0,0,0,0,0,0,0,6334,0,0,0,0,0,0,0,\n6335,0,0,6337,0,6338,0,6339,6340,0,0,6356,6357,6369,0,0,0,6370,6371,6372,0,6373,\n0,0,0,0,0,6376,0,0,0,0,0,6382,6383,6384,0,0,0,0,6386,0,6389,6397,6400,6411,0,\n6414,0,0,0,0,0,0,0,6415,6416,0,0,0,0,0,0,6417,0,0,0,0,6418,0,0,0,0,0,0,0,6420,0,\n6421,6423,6425,0,6429,6430,0,6433,6438,0,0,0,0,0,0,0,0,0,0,6439,6440,0,0,6441,0,\n0,6444,0,0,0,0,6446,0,0,0,0,6447,6448,0,0,6450,0,0,0,6454,0,0,6455,0,6461,0,0,0,\n0,0,0,6462,0,0,6463,0,6464,0,6465,6467,0,0,0,6468,0,6479,6480,0,0,0,0,0,0,0,6481\n,0,0,6485,6487,0,0,0,0,0,0,6493,0,0,0,0,0,0,0,0,6494,6495,6496,0,0,0,0,0,6498,0,\n0,0,6507,6508,0,0,0,0,0,0,0,0,0,0,6511,6512,0,0,0,0,6513,0,0,0,6514,0,0,0,0,0,\n6516,0,0,6517,6518,0,0,0,6519,6520,6521,0,6523,0,0,0,0,6524,6528,0,6530,0,0,6532\n,0,6578,0,0,0,6583,0,6584,0,0,0,6587,0,0,0,6590,0,6591,0,0,0,0,0,6592,0,0,0,0,\n6593,6594,0,0,0,0,0,6599,6600,0,0,6601,6602,6604,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6608,0,0,0,0,0,0,0,0,6610,6611,0,6615,0,6616,6618,6620,0,6637,0,0,0,0,6639,0,0,0\n,0,6641,0,6642,0,0,0,6647,0,6660,6663,0,6664,0,6666,6669,0,6675,6676,6677,0,0,0,\n0,0,0,0,0,0,6678,0,0,0,6679,0,6680,0,0,0,0,0,0,0,6693,0,0,0,0,0,0,0,0,0,6704,\n6705,6706,0,0,6711,6713,0,0,0,0,0,6716,0,0,0,6717,0,6719,6724,0,0,0,0,0,0,0,0,\n6725,6726,0,0,0,0,0,6728,6729,6735,0,6737,6742,0,0,6743,6750,0,6751,0,0,6752,\n6753,0,0,0,0,0,0,6754,0,0,0,0,0,6756,0,0,0,0,0,0,6763,0,0,6764,6765,0,0,0,6770,0\n,0,0,6776,6780,0,6781,0,0,0,6783,0,6784,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n6785,0,0,0,6792,0,0,0,6793,0,0,6802,0,0,0,0,0,6803,0,0,0,6804,0,0,0,6812,0,0,\n6823,0,6824,6839,0,0,0,0,6852,0,0,6854,0,6856,6857,0,0,0,0,0,0,0,0,0,6867,0,6868\n,6870,6872,0,0,0,6873,6874,0,0,0,0,0,6875,0,0,6877,0,0,0,0,0,0,0,6878,0,0,0,6879\n,0,6880,0,0,0,0,0,0,0,0,0,0,6887,0,6888,6891,6893,0,6895,0,0,0,0,0,0,0,0,6899,0,\n0,0,0,6901,0,0,0,0,6910,0,6911,0,0,6912,0,0,6913,6914,0,0,0,6915,0,0,0,6916,6919\n,0,0,0,0,0,0,6924,0,6925,0,0,0,6926,6927,6928,0,6929,0,6930,0,0,6931,6935,0,6936\n,0,0,0,0,6939,6940,6941,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6942,6948,6949,0,0,0,0,0,0\n,0,6952,6954,6963,6965,6966,0,0,6967,6968,0,0,0,0,0,0,0,0,0,6969,0,0,6970,6979,0\n,0,6980,0,0,6983,0,0,0,0,0,6984,0,0,0,0,0,0,0,6988,6990,6992,0,0,0,0,0,0,0,6995,\n0,0,0,7012,0,0,0,0,0,0,0,0,0,7019,0,0,0,0,0,0,0,0,7021,0,0,7022,7023,7028,0,7030\n,7033,0,0,0,0,0,0,7038,0,0,0,0,0,0,0,0,0,0,7039,0,0,0,0,0,7046,0,7047,0,0,0,0,0,\n0,0,0,0,0,0,7048,7052,0,0,0,0,0,7054,0,7060,0,0,0,0,7061,0,7065,0,0,0,0,7067,\n7069,0,7070,7071,7072,0,0,7078,0,7080,7081,0,7083,0,0,0,7084,7087,7088,0,0,7090,\n0,7093,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7107,0,0,7108,0,0,0,0,0,0,0,0,7110,0,7114,0\n,0,0,0,0,0,0,7115,0,7116,0,0,0,0,0,7117,0,0,7118,0,0,7124,0,7125,0,0,7126,0,0,0,\n0,7128,0,0,0,0,0,7129,0,7130,0,7132,7133,0,0,7134,0,0,7139,0,7148,7150,0,0,0,0,\n7152,0,0,0,7153,7156,7157,0,0,0,0,0,7158,0,0,0,0,0,0,0,0,0,0,7163,7165,7169,0,\n7171,0,0,0,0,0,0,0,0,0,7172,0,7173,7181,0,0,0,0,0,7182,7185,0,0,0,0,7187,0,7201,\n7204,0,0,0,0,0,7206,7207,0,0,0,0,7211,7216,0,7218,0,0,0,0,7226,7228,7230,7232,\n7233,7235,7237,0,0,0,0,7238,7241,0,7242,0,0,7247,0,0,0,7266,0,0,0,0,0,0,0,7289,0\n,0,7290,7291,0,0,7292,0,7297,0,0,0,0,0,0,0,0,0,0,7300,0,7301,0,0,0,0,0,0,0,0,0,0\n,0,0,7302,0,0,0,0,7305,0,0,0,0,7307,0,7308,0,7310,0,7335,0,0,0,0,0,0,0,7337,0,\n7343,7347,0,0,0,0,0,7348,0,7349,7350,7352,7354,0,0,0,0,7357,0,7358,7366,0,7367,\n7368,0,0,7373,0,0,0,7374,0,0,0,0,0,0,0,7376,0,0,0,7377,0,0,0,0,0,7378,0,7379,\n7380,0,0,0,0,0,7383,0,0,7386,0,0,0,0,7398,0,0,0,7399,7400,0,7401,0,0,0,0,0,0,0,\n7402,0,0,0,0,0,7405,0,0,0,0,0,7406,0,0,0,0,0,0,0,0,7421,7427,7429,0,0,0,7435,0,0\n,7436,0,0,0,7437,0,0,0,0,0,0,7438,7443,0,7446,0,7448,0,0,0,0,0,0,0,0,0,0,7456,0,\n0,0,0,0,7457,0,0,7461,0,0,0,0,0,7462,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7463,7466,7472,\n0,7476,0,0,7490,0,7491,0,0,7493,0,0,0,7498,7499,0,0,7508,0,0,0,0,0,7512,0,0,0,\n7513,7514,7516,0,0,0,0,7518,0,0,7519,7521,7522,0,0,0,7526,0,0,7529,0,0,7531,0,\n7536,0,7538,0,7539,0,0,7541,7542,7546,0,0,0,0,0,7547,0,7548,0,0,0,0,0,7550,0,0,\n7552,7553,0,0,0,0,0,0,0,0,0,0,7554,7563,0,7573,0,0,0,0,0,0,7574,7576,0,7578,7581\n,7583,0,0,0,7584,0,7587,0,0,0,0,0,7589,0,0,0,7594,0,0,7595,0,0,7600,7602,7610,0,\n0,0,0,0,7612,0,7613,7614,0,0,7615,0,0,7616,0,7620,0,7621,7622,0,7623,0,0,0,0,\n7626,0,0,0,0,7627,7629,7631,0,0,7633,0,0,0,0,0,7639,0,7640,7642,0,0,7643,0,0,0,0\n,7644,0,0,0,0,0,0,0,7645,0,0,0,0,0,7661,7662,7663,7665,0,7666,0,7667,0,7684,7688\n,7690,0,7691,0,0,0,0,0,0,7692,0,0,7700,0,7707,0,7708,0,7709,0,7721,0,0,0,7722,0,\n7724,0,0,0,0,0,0,7729,7731,0,7732,0,7733,7735,0,0,0,0,0,0,0,7739,0,0,7741,7745,0\n,7748,0,0,0,7751,0,0,0,7752,0,0,0,0,0,0,0,7753,0,0,7756,0,7757,0,7759,0,7760,0,0\n,0,0,7761,7768,0,0,7769,0,0,7770,0,0,7771,0,0,7772,0,0,7773,0,0,0,0,0,7778,7783,\n0,0,0,0,0,7784,7785,0,7790,0,0,0,0,7792,0,7798,0,0,0,0,0,7799,0,7810,0,0,7813,0,\n7814,0,7816,0,7818,7824,7825,7826,0,7828,7830,0,0,0,7840,0,7842,0,7843,0,0,0,0,\n7844,0,0,0,0,0,0,0,7846,0,0,0,0,0,7856,7857,7858,7862,0,7865,0,0,7866,0,0,7913,0\n,0,0,0,7914,0,0,7915,7917,7918,7919,0,7920,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7921,\n7922,0,7924,0,0,7925,0,0,7927,0,7930,7935,0,0,7937,0,0,0,0,0,0,7939,0,7940,0,0,0\n,0,0,7941,0,0,0,0,7945,0,0,0,0,7949,0,0,0,0,0,0,0,0,7950,0,7953,0,0,0,0,0,0,0,\n7968,0,0,0,0,7969,7972,7992,0,7993,0,0,0,0,0,0,0,0,0,0,0,7994,0,0,0,0,8007,8008,\n0,0,0,0,0,0,0,0,0,0,0,0,8010,0,0,0,8012,0,0,0,0,0,0,0,0,8018,0,8028,8029,0,0,\n8030,0,0,8032,8033,0,0,8034,8036,0,0,0,0,0,0,0,0,0,0,8037,0,0,0,8043,8052,8059,\n8060,0,0,8061,0,0,0,8062,0,8063,0,8064,0,8066,8068,0,0,0,8080,8081,0,8089,0,0,0,\n0,0,8092,0,0,0,0,0,0,8093,8110,0,0,0,0,0,0,0,8111,0,0,0,0,0,8112,8115,0,8117,0,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8120,8121,8122,8128,8129,8130,8131,0,0,8139,0,0,\n8144,0,0,0,0,8145,8146,8153,0,0,0,0,0,0,0,0,8154,0,8157,8160,8162,0,8164,8165,0,\n0,0,0,8166,8167,0,0,8179,0,0,0,8185,0,0,0,8186,0,0,8187,0,0,0,8188,0,0,0,0,0,\n8204,0,0,0,0,8210,0,0,0,0,0,8213,0,8214,0,0,8215,0,0,0,0,0,0,8218,0,0,0,0,0,0,0,\n0,0,8219,0,8221,0,0,8222,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8225,0,0,0,8233,0,0,\n8242,0,0,0,0,0,0,0,0,0,0,0,8247,0,8248,8252,0,8256,8257,0,0,8261,0,8264,8265,0,0\n,0,0,8267,0,0,0,8269,0,0,0,0,0,0,0,0,0,8270,0,0,0,8278,0,8279,8283,0,0,8285,8286\n,8289,8292,0,0,0,0,8293,8295,8299,8300,8301,0,0,0,0,0,0,8304,8307,0,0,0,0,0,0,0,\n8321,0,0,0,8322,8323,8325,8326,8327,0,0,8332,8338,0,0,8340,0,0,0,0,0,8350,0,0,\n8351,0,8354,8355,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8360,8372,0,0,0,0,0,0,0,0,8377,0,0,\n0,0,8380,0,0,0,8383,0,8384,0,0,0,0,8386,8392,0,0,8394,0,0,0,0,0,0,0,8396,8397,0,\n8398,0,8399,0,0,0,0,0,8400,0,8401,8410,8411,0,8412,8413,8422,0,0,0,0,8423,0,0,0,\n0,8424,0,0,8425,0,0,0,0,0,0,0,8441,8442,0,0,0,0,0,0,8443,0,0,8444,0,8447,0,0,0,0\n,8451,0,8458,0,8462,0,0,8468,0,8469,0,0,0,8470,0,8473,8479,8480,0,0,0,0,8481,\n8483,0,0,0,0,0,0,0,0,0,8484,0,0,8490,0,0,0,0,0,0,8491,8493,8494,0,8528,0,0,0,0,0\n,0,0,8530,0,0,0,0,0,0,0,0,8534,8538,8540,0,0,8541,0,0,8545,0,8557,0,0,8569,8570,\n0,0,8571,8574,8575,8579,0,8583,0,0,0,0,8591,0,0,0,0,0,0,0,0,8606,0,8607,0,0,0,0,\n0,0,0,0,0,8608,0,0,8609,0,0,0,8610,0,0,0,8611,0,0,8613,8617,8621,0,0,8622,0,8623\n,0,8624,8625,0,0,0,0,0,0,0,0,0,8637,8638,8639,8650,0,0,0,0,8652,8654,8655,0,0,0,\n0,0,0,0,0,0,0,8656,0,0,0,0,0,8657,0,0,0,0,0,0,0,0,0,8658,0,0,8659,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,8660,0,0,0,0,0,0,8661,8663,8664,0,0,0,0,8665,0,8669,0,\n0,0,0,0,0,0,8671,8674,0,8684,0,8686,0,0,0,8689,0,0,0,8690,0,8706,0,0,0,0,0,0,0,0\n,0,0,0,8710,0,8711,8713,8714,8724,8727,8728,8733,8736,0,8737,8739,0,0,0,0,8742,\n8743,8745,8754,0,0,0,0,8756,0,0,0,0,0,0,8757,8760,0,0,0,0,0,8762,8763,8764,0,\n8766,8769,8770,8773,0,8774,0,8779,0,0,0,0,8780,0,0,8781,0,0,8783,0,0,0,0,0,0,0,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8784,0,0,0,0,0,0,0,0,8785,0,0,0,0,8786,0,0,0,0,8788\n,8790,0,0,0,8803,0,8813,8814,0,0,0,0,0,8815,8816,0,0,0,0,8818,0,0,0,0,8822,8828,\n8829,0,8831,0,0,0,0,8833,0,0,0,8834,0,0,0,8835,0,8836,0,0,0,8837,0,0,0,0,0,0,\n8838,8839,0,0,0,0,0,0,0,0,0,0,0,8840,0,0,0,8841,0,8842,0,0,0,8846,0,0,0,0,0,0,0,\n8847,0,8848,0,0,8864,0,0,8866,0,0,8870,8872,0,0,8873,8874,0,0,0,0,0,0,8875,0,\n8876,0,0,0,0,8896,8900,0,0,0,0,8901,0,0,0,0,0,8904,0,8907,0,0,0,0,8911,8912,8913\n,0,0,0,8914,0,8915,0,0,0,0,0,0,0,0,0,0,0,0,8916,0,0,0,8929,0,0,0,0,0,0,0,0,0,0,\n8930,0,8932,0,8943,0,0,0,8945,8947,0,0,0,0,8949,0,8950,0,8954,8957,0,0,8970,0,0,\n0,0,8971,0,8996,0,0,0,0,8997,9000,0,0,0,0,9001,9002,0,9004,9009,9024,0,0,0,0,0,0\n,0,0,0,0,0,0,9027,9082,0,0,9083,9089,0,0,0,0,0,0,9090,0,0,0,9092,0,0,9093,0,9095\n,0,0,9096,9097,9101,9102,0,0,0,0,0,0,0,0,9112,0,0,0,0,0,0,9114,0,0,9120,0,9121,\n9122,0,0,0,9123,9124,0,0,9125,0,0,9126,0,9127,0,0,9129,9131,0,0,0,9132,0,0,9136,\n0,9144,0,0,9148,0,0,0,0,0,0,9149,0,9152,9163,0,0,9165,0,0,0,0,0,0,0,0,0,0,0,0,0,\n9166,0,9169,0,0,0,0,0,0,0,9170,0,0,0,0,9172,0,9174,9175,9176,0,9177,0,0,0,0,0,0,\n0,0,9186,0,9187,0,0,0,9188,9189,0,0,9190,0,0,0,0,9191,0,0,0,9193,0,0,0,0,9197,\n9198,0,0,0,9208,9211,0,0,0,0,9216,9217,0,9220,0,0,0,0,9221,9222,9223,0,9224,9225\n,0,0,9227,0,9228,9229,0,0,9230,0,9232,0,9233,0,0,0,0,0,9234,9235,0,0,9237,0,0,0,\n0,0,0,0,0,9238,9240,0,0,9241,0,0,0,0,9244,0,0,0,0,9247,0,0,0,0,0,0,0,0,0,0,9248,\n0,0,0,9249,0,0,0,0,0,9250,0,0,0,0,9251,0,0,9252,9255,0,0,0,9256,0,0,0,0,0,0,0,\n9257,0,0,9258,0,0,0,0,0,0,9259,0,0,0,0,0,9262,9263,0,0,9265,9266,0,0,0,0,0,0,0,0\n,9268,9271,0,0,0,0,0,0,0,0,0,9273,0,0,0,9276,9277,9279,0,0,0,0,0,0,0,9280,0,0,\n9293,0,0,0,0,0,9297,9301,0,0,0,0,0,0,0,0,0,0,0,9308,9309,9313,9321,9322,0,9326,\n9327,0,0,9477,0,9479,0,0,0,0,9482,0,0,0,9483,0,9484,0,0,0,0,0,0,0,0,0,9485,0,0,\n9486,0,0,0,9489,0,0,0,0,9490,9491,0,0,0,0,9493,0,9495,9496,0,0,0,0,0,0,0,0,9500,\n0,9502,0,0,0,0,0,9504,9507,0,9509,0,9511,0,0,9513,0,0,0,0,0,0,0,0,9515,0,0,0,0,0\n,0,9516,9517,0,0,0,0,9532,0,0,9533,0,0,9538,0,9539,9540,0,0,0,0,9541,0,0,0,9542,\n0,0,0,0,0,0,0,0,9544,9545,0,9546,0,0,0,0,0,0,9547,9548,0,0,0,9550,0,9557,0,9558,\n0,9561,0,9563,9570,0,9572,9574,9575,0,0,0,9577,9592,0,0,9596,0,0,0,9598,0,9600,0\n,9601,0,0,0,0,0,0,9608,0,9638,9639,0,0,0,0,0,0,0,9641,0,0,9643,9644,9645,9646,0,\n0,0,9648,0,0,0,0,0,0,0,9650,9654,0,0,0,0,0,0,0,0,9655,0,0,0,0,0,9656,0,9657,0,0,\n0,0,9658,0,0,9659,0,0,9664,0,0,9665,0,9667,9669,0,0,0,0,0,0,0,0,0,0,0,0,9671,0,\n9673,9681,0,0,0,0,9682,9683,9684,0,0,0,0,9686,9698,0,0,9700,9701,9702,0,9703,\n9717,0,0,0,0,9718,0,9726,0,0,0,0,9727,0,0,0,9728,0,9742,0,9744,0,0,0,9750,0,9754\n,9755,0,0,0,0,0,9756,0,9757,9768,0,9769,0,0,0,9770,9771,0,9773,0,9774,0,9775,0,0\n,0,9776,9777,9784,0,0,0,9786,0,9789,0,0,0,0,9793,9794,0,0,0,9808,0,0,0,0,0,9811,\n0,0,0,0,0,0,0,0,0,0,0,0,9812,0,9820,0,9823,0,9828,0,0,0,0,9830,0,0,9833,9836,0,0\n,0,9840,0,0,0,9841,0,0,9842,0,9845,0,0,0,9847,9848,0,0,9855,0,0,0,0,0,0,9856,\n9863,9865,0,0,0,0,0,0,0,0,9866,9867,9868,9873,9875,0,0,0,0,0,0,9880,0,9886,0,0,0\n,9887,0,0,9891,0,0,0,0,0,0,0,9906,9907,9908,0,0,0,9909,0,0,0,0,0,0,9910,0,0,0,0,\n9913,0,0,0,0,9914,0,0,0,0,0,9922,0,0,0,0,9923,9925,0,0,0,0,0,0,9930,0,0,0,9931,0\n,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9932,0,9939,0,0,9940,9962,9966,0,9969,9970,0,0,9974\n,0,9979,9981,9982,0,0,0,9985,0,0,0,0,0,0,9987,0,0,0,0,0,0,0,9988,9993,0,0,9994,0\n,0,0,9997,0,10004,0,0,0,0,0,10007,10019,10020,10022,0,0,0,10031,0,0,0,0,0,10032,\n0,0,10034,0,10036,0,0,0,0,10038,0,10039,10040,10041,10042,0,0,0,0,0,10043,0,0,0,\n0,0,10045,10054,0,0,0,0,10055,0,0,10057,10058,0,0,0,0,0,0,10059,0,0,0,0,0,0,0,\n10060,0,0,0,0,0,0,0,10063,0,10066,0,0,0,10070,0,10072,0,0,10076,10077,0,0,10084,\n0,10087,10090,10091,0,0,0,10094,10097,0,0,0,0,0,0,10098,0,0,0,0,0,0,10103,0,\n10104,0,10108,0,0,0,0,0,0,0,0,10120,0,0,0,10122,0,0,10125,0,0,0,0,10127,10128,0,\n0,10134,0,10135,10136,0,10137,0,0,10147,0,10149,10150,0,0,10156,0,10158,10159,\n10160,10168,0,0,10171,0,10173,0,0,0,10176,0,0,0,0,10177,0,0,0,0,10178,0,0,0,0,\n10194,0,10202,0,0,10203,10204,0,10205,10206,0,10207,0,0,0,0,10209,0,0,0,0,0,0,0,\n10213,0,0,0,0,0,0,10217,0,10229,0,10230,10231,0,0,10232,0,0,10237,10238,10244,0,\n0,0,0,0,10250,0,10252,0,0,0,0,0,0,10255,0,0,10257,0,0,0,0,0,0,10258,0,10259,0,0,\n0,0,0,0,0,0,10260,0,0,0,0,0,0,0,10284,10288,10289,0,0,0,10290,0,10296,0,0,0,0,0,\n10297,0,0,0,0,0,0,10298,0,0,0,0,10299,10303,0,0,0,0,0,10306,0,0,0,10307,0,10308,\n0,0,0,0,10311,0,0,0,0,0,0,0,10315,10317,0,0,0,10318,10319,0,10321,0,10326,0,\n10328,0,0,0,0,10329,0,0,10331,0,10332,0,0,0,0,0,0,10334,0,0,10335,10338,0,0,0,0,\n0,10339,10349,0,0,0,0,0,0,10351,0,10353,0,0,0,0,0,0,10362,0,10368,0,10369,0,0,0,\n10372,10373,0,0,0,0,0,10374,0,0,0,10375,0,10376,0,0,10386,10388,10390,0,0,0,0,0,\n0,0,10391,0,0,10392,10394,0,0,10396,0,10397,0,10403,0,0,0,0,0,0,0,0,10404,0,\n10405,10410,0,0,10411,0,10412,0,0,0,0,0,0,0,10421,10422,10423,0,0,0,0,0,0,0,0,0,\n10425,0,0,10427,0,0,10430,0,0,0,0,0,10432,0,10433,10434,0,0,0,0,10436,10437,0,\n10438,0,10439,0,10444,10446,0,0,0,0,0,10448,0,0,0,0,0,10449,0,0,0,0,0,0,0,10451,\n0,10453,0,0,0,10454,10457,0,0,10459,0,10469,0,0,0,0,0,10472,10481,0,0,0,0,0,\n10482,10483,0,10492,0,0,0,0,0,0,0,0,0,0,10499,0,0,0,10502,0,0,10510,0,10521,\n10524,0,0,10525,10526,10528,0,0,0,0,0,0,0,0,10530,0,0,0,0,10533,0,10534,0,0,0,0,\n0,0,0,0,0,0,10535,10536,0,0,10544,0,10553,10556,0,10557,10559,0,0,0,0,0,10562,\n10563,10564,0,10565,0,0,0,10566,0,10567,0,0,0,0,10575,0,0,10576,0,10578,0,0,0,0,\n0,0,0,0,0,0,10585,10586,10587,10589,0,10590,0,0,10594,0,0,0,0,0,10598,0,0,10601,\n0,0,0,10602,0,10603,0,10604,0,10605,0,0,10607,0,10626,0,10627,0,0,0,0,0,10629,\n10630,10631,0,0,0,10646,0,0,0,10647,0,10650,0,10651,0,0,0,10652,10653,10655,0,\n10658,0,0,10659,0,10667,0,0,0,0,10669,0,0,0,0,0,0,0,0,0,10670,0,0,0,10671,0,0,0,\n0,10672,10673,0,10674,0,0,0,10676,0,0,0,0,0,0,10678,0,10682,0,0,10692,0,10697,0,\n0,0,0,10698,0,0,0,10700,0,0,0,0,0,10703,0,10704,0,0,0,0,0,0,0,10705,0,10715,\n10718,10720,0,0,10722,0,0,0,0,0,0,0,0,10723,0,0,0,0,10726,0,0,0,0,0,10727,10730,\n10743,0,0,0,0,0,0,10744,0,0,10745,0,0,0,0,0,0,10748,0,0,0,0,10750,0,0,10752,\n10753,0,0,0,10756,0,0,0,0,0,0,10758,0,0,0,10759,0,10769,0,0,10772,0,0,0,0,0,0,\n10773,0,0,0,10777,0,0,10779,0,0,0,0,0,0,0,0,10780,10784,0,0,0,10789,0,0,0,10791,\n0,0,0,0,0,0,0,0,0,10795,0,0,10796,0,10808,0,10809,0,0,0,10810,0,0,0,10812,0,0,\n10814,0,0,0,0,0,0,0,0,0,10815,0,0,0,0,10816,10817,0,0,0,0,10819,0,10820,0,0,0,0,\n10821,10822,10823,0,10826,10849,0,0,0,0,10850,0,0,10852,0,10853,0,0,10856,0,0,\n10857,10858,10859,10860,0,0,0,0,0,0,10863,0,10866,10867,10872,10890,0,0,10891,\n10892,0,0,0,0,0,10893,0,0,0,10896,10899,0,0,10900,10902,0,0,0,0,0,10903,0,0,0,0,\n0,0,0,0,0,0,0,0,10905,0,10906,0,0,0,0,10908,10911,0,10912,0,0,10916,0,0,0,0,0,\n10917,0,10918,0,0,0,10923,0,0,0,0,0,10924,0,0,10928,10929,0,0,10930,0,0,0,10932,\n0,0,0,0,10939,0,0,10945,0,0,0,10947,0,0,10948,0,0,0,0,0,0,0,0,0,0,0,0,10958,0,\n10960,10962,0,0,10964,0,0,0,10966,0,0,0,0,0,0,0,0,0,0,10967,0,0,0,10968,0,0,0,\n10973,0,0,0,0,0,10975,0,0,0,10976,10978,0,0,10982,10984,10987,0,0,10988,0,10989,\n0,0,10991,0,0,0,0,10992,0,0,0,10993,0,10995,0,0,0,10996,10997,0,0,0,10998,0,\n10999,0,11001,0,0,0,0,0,0,11010,11012,0,11013,11016,11017,0,0,11019,11020,11021,\n0,0,0,0,0,0,0,0,0,0,0,0,11022,0,0,11023,11029,0,0,0,0,11031,0,0,0,11034,0,0,0,0,\n11055,0,0,0,0,0,11056,11060,0,0,0,0,0,0,11061,0,0,11064,11065,0,11066,0,11069,0,\n11085,0,0,0,0,0,11086,0,0,0,11088,0,0,0,11094,0,0,0,11095,11096,0,0,0,0,0,0,\n11097,11098,0,0,0,0,0,0,11099,0,0,11102,11108,0,0,0,11109,0,11114,11119,0,11131,\n0,0,0,11142,0,0,11143,0,11146,0,11147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11148,0,\n11149,11152,11153,11154,0,11156,0,11157,0,0,0,11158,0,0,11159,11160,0,0,0,0,0,0,\n0,0,0,0,0,0,11163,0,0,11164,11166,0,0,0,11172,11174,0,0,0,11176,0,0,0,0,0,11182,\n11183,0,0,0,11184,11187,0,0,11188,11189,0,0,0,0,0,0,11194,0,0,0,0,0,0,0,11200,\n11202,0,0,0,0,0,0,11203,0,11204,0,0,0,0,0,11205,0,0,0,11206,0,11207,0,0,11209,0,\n11211,0,11214,0,0,11231,0,0,0,11293,11295,0,0,11296,11297,11302,0,0,0,11307,0,0,\n0,0,11309,11310,0,11311,0,0,0,11313,0,11314,0,0,0,0,11334,0,11338,0,0,0,11339,0,\n0,0,0,0,11340,0,11341,11342,0,11344,0,11345,0,0,0,11348,11349,0,0,11350,0,0,0,\n11355,0,0,0,0,0,0,11356,0,11357,11370,0,0,11371,0,11374,11376,0,0,0,11377,0,0,\n11378,11383,0,11386,11399,0,11400,11406,0,0,0,11408,0,0,11409,11412,0,0,0,0,\n11417,0,0,0,11418,0,11421,0,11426,11429,0,0,0,0,0,11430,0,11437,0,11438,0,0,0,0,\n0,11440,11453,0,0,0,0,0,0,11454,0,0,0,0,11455,0,0,11456,11460,11461,11463,0,\n11469,0,11473,0,0,0,0,11474,0,0,0,11475,0,11476,11477,11480,0,0,0,0,11481,0,0,\n11484,0,0,11487,0,0,0,0,0,0,0,0,0,0,11497,0,0,11502,0,11509,0,0,11510,11511,\n11513,0,0,0,0,0,0,0,0,0,0,11515,0,0,0,0,11516,0,11520,11521,0,0,0,0,0,0,0,0,0,0,\n0,11529,11530,11531,11534,0,0,11543,0,0,0,0,0,11547,0,11548,0,0,0,0,0,11552,\n11556,0,11557,0,0,11559,0,11560,0,0,0,0,0,0,11561,0,0,11563,11564,0,11565,0,0,0,\n0,11567,0,0,0,11569,0,11574,0,11575,0,0,0,11577,0,11578,0,0,0,11580,11581,0,0,0,\n11582,11584,0,0,0,0,0,0,0,11587,0,11588,11591,0,11595,0,0,0,0,0,0,0,0,11596,0,\n11597,0,0,0,0,11598,11601,0,0,0,11602,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,11603,\n11604,0,11606,0,0,11608,0,0,0,0,11610,0,0,11611,0,0,0,0,11613,0,11622,0,0,0,\n11623,0,0,0,0,11625,0,0,11626,11627,11628,11630,0,0,0,0,0,0,11639,0,0,11646,0,\n11648,11649,0,11650,0,0,0,0,0,0,0,0,0,11651,0,0,11652,11653,11656,0,0,11677,\n11679,0,0,0,0,11680,0,0,11681,0,11685,0,0,0,0,0,0,0,0,11688,0,0,0,11716,0,11719,\n0,0,0,0,0,11721,0,0,11724,11743,0,0,0,0,0,0,0,0,11745,11748,11750,0,0,0,0,0,\n11751,0,0,0,11752,11754,0,11755,0,0,0,0,0,0,0,11759,0,0,0,0,0,0,11760,0,0,0,\n11761,0,0,0,0,0,0,11766,11767,0,11772,11773,0,11774,0,0,11775,0,11777,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,11778,11780,0,0,0,0,0,0,0,11783,0,11784,0,0,0,11785,\n0,0,0,11786,0,0,0,0,11788,0,0,11789,11791,11792,0,0,0,0,11795,11834,11835,11836,\n0,0,11837,0,0,0,11838,0,0,11846,11851,0,11852,0,11869,0,0,0,11871,0,0,0,11872,\n11874,0,0,0,0,0,0,11875,0,11876,11877,0,0,0,0,0,0,0,0,0,0,11883,0,0,0,0,0,0,0,\n11884,0,11885,0,11886,0,0,11887,0,11894,11895,11897,11909,11910,0,11912,11918,0,\n0,11920,0,11922,11924,11927,11928,0,0,0,0,11929,0,11934,0,0,0,0,0,11941,11943,\n11944,0,11945,0,0,0,0,11948,11949,0,0,0,0,11953,0,11954,0,11955,0,11956,0,0,0,0,\n0,11957,0,0,11959,0,0,0,0,0,0,0,0,11961,0,0,0,0,0,11978,0,0,0,11979,11980,11986,\n11987,0,11992,0,0,0,0,0,11993,0,0,0,11994,0,11999,12004,12005,12006,0,0,0,0,0,\n12011,0,0,12012,12014,0,0,12015,0,0,12019,12028,0,0,12029,0,0,12032,12033,0,0,0,\n0,12034,0,12041,12043,0,0,12044,0,0,0,0,0,0,0,12046,0,0,0,0,0,0,0,12054,12055,0,\n12056,0,0,0,12060,12064,0,0,0,0,0,12065,12067,12068,0,0,0,0,0,0,0,0,12074,0,0,0,\n12075,12076,0,0,0,12079,0,12081,12086,12087,0,0,12088,0,0,0,0,12089,0,12092,0,0,\n0,0,12097,0,0,0,0,0,0,0,0,12098,0,0,0,0,0,0,0,0,0,0,0,0,0,12102,12103,12104,\n12111,0,0,12114,12116,0,0,0,12118,0,0,0,12119,12120,12128,0,0,0,0,12130,0,0,0,0,\n0,0,12131,0,0,0,12132,12134,0,0,0,0,12137,0,12139,0,12141,0,0,12142,0,0,0,12144,\n0,0,0,0,0,12145,0,12148,0,12153,0,0,0,0,12154,12171,12173,0,0,0,12175,0,0,0,0,\n12178,0,0,0,0,0,0,0,12183,0,0,0,0,0,0,0,0,12184,0,0,0,12186,0,0,0,0,0,12187,\n12188,0,0,12189,0,12196,0,12197,0,0,12198,0,12201,0,0,0,0,12203,0,12209,0,0,0,0,\n12210,12211,12212,12213,0,12217,12218,0,0,0,0,0,0,0,0,0,12222,0,0,0,0,0,0,0,\n12223,0,0,12229,0,0,0,0,12233,0,0,0,0,12234,0,0,12236,12242,0,0,0,12243,0,0,0,\n12244,12253,0,12254,12256,0,12257,0,0,12275,0,0,0,0,0,12277,0,0,0,0,0,12278,0,\n12289,0,0,12290,0,12292,12293,0,0,12294,0,12295,0,0,12296,0,12297,0,12298,0,0,0,\n0,12301,0,0,0,0,0,0,0,0,0,0,0,0,0,12309,0,12338,12340,0,0,0,0,12341,0,0,0,0,0,0,\n0,0,12342,12343,0,12344,0,0,0,0,0,0,0,0,0,12345,0,0,0,0,0,0,0,0,12346,0,0,0,0,\n12348,0,0,0,0,0,0,0,0,0,0,0,0,12350,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12351,0,12355,\n12356,12357,0,0,12367,12370,12371,0,0,0,0,0,12372,12376,0,0,0,0,0,0,0,0,12379,0,\n12382,0,12383,0,0,12384,0,0,0,0,12393,0,0,12394,0,0,0,0,12398,12403,0,0,12404,0,\n0,0,0,0,0,0,0,0,0,0,0,0,12410,0,0,0,12411,0,0,0,12412,0,0,0,0,12420,0,12421,0,0,\n0,0,0,12423,0,12425,12429,0,0,0,12431,12432,0,0,0,0,0,0,0,0,0,0,0,0,12434,0,0,0,\n0,0,12435,12436,0,0,0,0,0,0,0,0,12437,0,0,0,0,0,12438,0,0,0,0,0,0,0,0,12445,0,0,\n0,12450,12451,0,0,0,0,0,0,0,0,12452,12475,0,0,12493,12494,0,0,0,12495,0,0,0,0,\n12496,12502,12509,0,0,0,0,12510,0,12512,12513,0,0,0,0,12514,0,0,0,12515,0,12520,\n0,0,0,12524,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12527,0,0,0,12528,0,0,0,12529,0,0,0,\n0,0,12530,0,12535,0,0,12536,0,12538,0,0,0,0,0,0,0,0,0,0,0,0,12540,0,12548,0,0,0,\n0,0,12550,0,0,0,12551,12552,0,0,0,12554,0,0,0,0,0,0,0,0,12555,0,0,12562,0,12565,\n0,12566,0,0,0,0,0,0,0,0,0,0,0,0,12569,0,0,0,12571,12574,0,0,0,0,0,0,0,12577,0,0,\n0,0,0,0,0,12578,12579,12603,0,12608,0,0,12611,0,12612,0,12615,0,12625,0,0,0,0,\n12627,12646,0,12648,0,0,12657,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12670,0,0,12671,0,\n12673,12677,0,0,0,0,0,0,0,0,0,0,0,12679,0,12681,0,12682,12693,0,12694,0,12697,0,\n12701,0,0,0,12703,12704,0,0,0,0,12707,12737,0,0,12739,0,0,12740,0,0,12742,12743,\n0,0,0,0,0,0,0,0,0,12745,0,12746,12747,0,12748,0,0,12759,12767,0,0,0,0,12773,0,\n12774,12778,0,0,0,0,0,0,0,12779,0,0,0,0,0,12780,12793,0,12824,0,12825,0,12836,0,\n0,0,0,12839,0,12842,0,0,0,0,0,0,0,0,0,0,0,0,12843,12845,0,12846,0,0,0,0,12847,0,\n0,12850,12852,12853,0,0,0,12854,0,0,0,12855,0,12856,0,12858,0,0,12859,0,12862,0,\n12863,0,0,12866,0,12869,12872,12873,0,0,0,0,0,0,0,0,0,12875,0,12877,0,0,12878,0,\n0,0,0,0,0,0,0,0,12884,12885,12888,0,12889,0,0,0,0,12893,0,0,0,12895,12896,12898,\n0,0,0,0,0,0,0,12902,0,12909,12910,0,12926,0,12928,0,0,0,12929,0,12930,0,0,0,0,\n12931,0,12932,12933,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,12934,0,12942,0,0,0,0,12944,\n0,0,0,0,0,0,0,0,12946,0,0,12948,0,0,12949,0,0,0,0,12950,0,0,0,0,12951,0,12952,0,\n12953,0,0,0,12954,12958,12959,0,0,0,0,0,12960,12964,0,0,0,0,0,12966,0,0,0,0,0,0,\n0,0,12970,0,12971,0,0,0,0,0,0,12972,0,0,12982,0,0,0,12984,12985,0,12986,12996,\n12997,13001,13002,0,0,0,0,13004,0,0,13005,0,0,13007,13009,0,13017,0,0,0,13020,0,\n13021,0,0,0,0,0,0,0,0,0,0,13022,0,0,0,0,0,0,0,0,13024,13027,0,0,0,0,0,13028,0,0,\n13029,0,0,0,0,0,0,0,13032,0,13037,0,0,0,0,0,0,13040,0,0,13041,0,0,0,13043,13044,\n13046,0,0,0,0,13047,0,0,0,0,0,0,0,13049,13054,0,13056,0,0,13060,13061,0,0,0,0,0,\n13067,0,0,13068,0,13071,0,0,0,0,0,13077,13078,0,0,0,0,0,13079,13080,13081,0,\n13082,0,0,0,13085,0,0,0,0,0,0,0,13086,0,13087,13088,0,0,0,0,0,13094,0,13099,0,\n13100,0,0,0,13101,0,13125,13126,13128,13129,0,0,13130,0,13131,0,0,0,0,0,0,13134,\n0,0,0,0,0,0,0,0,0,0,0,13150,0,13168,0,0,0,0,0,0,0,0,0,13169,0,0,13170,0,0,0,0,\n13174,0,0,0,13176,0,0,0,0,0,13177,0,13178,13183,13187,0,0,0,13189,0,0,13190,0,0,\n13191,0,0,13206,0,0,0,13207,0,0,0,0,0,0,0,0,0,0,13212,0,0,13219,13232,0,0,0,\n13241,0,13249,13253,0,0,0,0,0,13255,13259,0,13260,13261,0,13262,0,13272,0,0,0,0,\n13276,0,0,0,0,13277,13299,0,0,13301,13302,0,0,13303,0,0,13305,0,13310,0,0,0,\n13311,0,0,0,0,13325,0,13328,0,0,0,13329,0,0,0,0,0,0,13330,0,0,13331,0,13335,0,0,\n13342,0,0,0,0,0,13343,0,13354,0,13362,0,13366,13367,13369,0,0,13371,13372,0,\n13373,13374,0,13376,0,13380,13381,13386,0,13387,13388,0,13389,13391,13395,0,0,0,\n0,0,13401,13409,0,13410,0,0,0,0,13420,0,0,0,0,0,13422,0,0,0,0,13423,0,0,0,0,\n13425,0,0,0,0,0,13427,0,0,0,13428,0,0,13430,13438,0,13439,0,13445,0,13448,13449,\n0,0,0,0,0,0,13451,0,13457,0,0,0,0,13458,13459,0,13460,0,0,0,0,13464,13465,13466,\n13470,0,13471,13472,13474,13475,0,13476,0,0,13478,13479,0,13481,0,0,0,0,13487,0,\n13490,0,13493,0,0,13494,0,0,13495,0,0,0,0,0,0,0,0,0,0,0,0,0,0,13496,13497,0,\n13500,0,0,13516,13522,0,0,13525,13528,0,0,0,13530,13535,0,13537,13539,0,13540,0,\n13543,0,13544,0,0,0,0,0,0,13545,0,0,0,0,0,0,13547,0,0,0,13549,13555,0,0,0,13556,\n13557,0,0,0,0,0,0,0,13558,0,13563,0,0,0,0,13564,0,0,0,0,0,0,0,0,13566,0,0,0,0,0,\n0,13569,0,0,13571,0,0,0,0,13573,0,0,0,0,0,0,13578,0,0,0,0,0,0,0,0,0,0,13581,0,\n13586,0,13595,0,13600,0,0,0,0,0,0,0,0,13601,13603,0,13604,13605,13606,13607,0,0,\n13617,13618,0,0,0,0,0,0,0,13623,0,13625,13627,0,0,0,0,0,0,0,0,13629,0,0,0,13634,\n0,0,0,13638,0,0,0,0,0,0,0,0,13654,0,0,0,0,0,0,0,0,0,0,13656,0,13659,0,0,13660,0,\n0,13662,0,0,0,13663,0,13664,0,0,0,0,0,13668,0,13669,13671,0,0,13672,0,0,0,0,0,0,\n13675,13685,0,13686,0,0,0,13687,0,0,0,13692,13694,13697,0,0,0,13702,0,0,0,0,0,\n13705,0,0,0,0,13707,0,0,0,13714,0,0,0,0,0,0,0,0,0,13715,0,13716,13717,0,0,13719,\n13724,13730,13731,0,0,0,0,0,0,0,0,13732,0,0,0,0,0,0,0,13734,0,13736,0,0,13737,\n13738,13747,0,13751,0,0,13752,0,0,0,13753,0,13757,0,0,13762,13763,0,13764,13765,\n0,13766,0,0,13767,0,0,0,13768,0,0,0,0,0,0,0,13769,0,0,13772,0,13775,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,13776,13778,13787,0,0,0,13797,0,13798,0,13801,0,13804,\n13806,0,0,0,0,13816,13817,0,0,0,0,0,0,0,0,0,0,0,0,0,13834,0,13836,0,0,13838,0,0,\n13839,0,13840,0,0,0,0,13842,0,0,0,0,0,0,13843,0,0,0,0,0,0,0,0,0,13845,0,0,0,0,0,\n13858,0,0,13860,0,0,13861,0,0,13862,13863,0,13868,0,13869,13870,0,0,0,0,0,0,0,0,\n0,0,13872,0,0,0,0,13873,13878,0,0,0,0,0,0,0,0,0,0,13886,0,13888,13889,13890,0,0,\n13891,13894,0,13897,13899,13900,13904,0,0,13906,0,0,0,13909,0,0,0,13910,0,0,0,\n13911,0,0,0,0,0,13912,13917,0,0,0,0,13918,0,13919,0,0,13920,0,0,0,13921,0,0,\n13922,0,0,0,0,0,0,0,13924,0,13927,0,0,0,0,0,13932,0,13933,0,13934,0,0,13935,0,\n13944,0,0,0,13954,0,0,13955,0,0,0,0,13956,0,13957,0,13967,13969,0,0,0,0,0,0,0,0,\n0,0,0,0,13970,13990,0,13991,13994,0,13995,0,0,0,0,13996,0,0,13999,0,0,0,14018,0,\n14019,0,14021,0,0,0,0,0,0,14041,0,0,0,0,0,0,0,0,14043,0,0,0,0,14046,0,0,0,14048,\n14049,0,0,0,0,0,0,0,0,0,0,14051,0,0,14052,14056,0,14063,0,14064,14066,0,0,14067,\n0,0,0,0,0,0,0,0,0,14068,0,0,0,14072,0,14074,14075,0,14076,14079,14085,14086,\n14087,14093,0,0,0,0,14095,0,0,0,0,0,0,14096,14097,0,0,0,0,0,0,0,14098,0,14102,0,\n0,0,0,0,14103,0,0,0,14104,0,0,14105,0,0,0,14107,14108,0,0,14109,0,0,0,0,0,0,0,0,\n14117,0,0,0,0,14118,0,0,0,0,14119,0,0,14120,0,0,14121,0,14122,14127,0,14128,\n14136,0,0,14138,0,14140,0,0,0,14141,14142,0,0,0,0,14146,0,0,14149,0,14151,0,0,0,\n14152,0,0,14153,0,0,0,0,0,0,0,0,0,14154,0,14156,14157,0,0,14159,0,14161,0,0,0,0,\n14162,0,0,0,0,0,0,14163,0,0,14173,0,0,0,0,0,0,14174,0,0,14176,0,0,14178,0,0,\n14179,14181,0,0,14182,14185,14187,0,14190,0,0,14197,0,0,0,0,0,0,0,0,0,0,0,0,\n14198,0,0,0,0,0,0,14199,14200,0,0,0,14204,0,0,14208,0,0,0,0,0,0,0,0,0,0,0,14231,\n0,0,0,0,0,0,0,0,0,14234,0,0,14235,0,0,0,14240,14241,0,0,0,14246,0,0,0,14247,0,\n14250,0,0,14251,0,0,14254,0,0,14256,0,0,0,14260,0,14261,0,0,0,0,14262,14267,\n14269,0,0,14277,0,0,14278,0,14279,14282,0,0,0,14283,0,0,0,14284,14285,0,0,0,0,\n14286,0,0,0,14288,0,0,0,14289,0,14290,0,14293,14301,14302,14304,14305,0,14307,0,\n14308,14309,0,0,0,0,0,0,0,0,0,0,0,14311,14312,0,0,14317,0,0,0,0,0,0,0,14318,0,0,\n0,0,14320,0,0,0,0,14321,14322,0,0,0,0,0,14326,14329,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n14330,14331,0,0,0,0,14332,0,0,0,14333,0,0,14337,14340,0,14341,0,0,14342,0,14345,\n14346,0,0,14347,0,14362,0,0,0,0,0,14364,14365,14371,0,14373,0,0,14374,0,14379,0,\n14400,0,0,0,0,0,14401,0,0,14405,0,14406,0,14408,14409,0,0,0,14417,0,0,14424,0,0,\n0,0,0,0,0,0,0,14430,0,0,0,14431,0,0,14435,0,14440,0,0,0,0,0,0,14442,0,0,14443,0,\n0,0,0,0,14446,0,0,0,0,0,0,0,14454,0,14457,0,14460,0,0,14466,0,0,0,0,0,14467,0,0,\n0,0,0,0,14469,0,14477,0,0,0,0,0,0,14478,14482,0,0,0,14483,0,0,0,14485,14486,0,0,\n0,14487,14488,14489,14492,14493,14494,14495,14496,14497,0,14499,0,14501,0,0,0,0,\n0,0,0,0,0,0,14502,0,14507,14512,14513,14514,0,0,0,0,0,0,0,0,0,0,0,14515,14526,\n14530,0,14537,0,14544,0,14547,0,0,14548,14550,14551,0,0,14552,0,0,0,14553,0,\n14554,0,0,0,0,14556,14564,0,0,14565,14566,0,0,0,0,0,0,14568,0,0,14569,0,0,0,\n14571,14576,0,0,14577,14578,14579,0,0,14580,0,0,0,0,14582,0,0,0,0,0,0,0,0,0,0,0,\n0,14583,0,0,0,0,0,14587,0,14588,0,0,14600,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,14601,0,0,14604,14605,14611,0,14613,0,0,0,0,14615,0,0,0,0,0,0,14627,0,14628,0,\n0,0,0,14631,0,14633,14634,0,0,0,0,14635,0,0,0,0,0,0,0,0,14636,0,0,14639,14642,0,\n0,0,0,14644,0,0,0,0,14645,14646,0,14653,0,0,14654,0,14658,0,14661,0,0,0,14665,0,\n0,0,14668,0,0,0,0,0,0,0,0,0,14669,0,0,14670,0,0,0,14680,0,0,14681,0,0,0,0,0,\n14682,14683,0,0,0,0,14686,0,0,0,0,14687,14697,0,0,0,0,14699,14705,14711,0,0,0,0,\n0,0,0,0,0,0,14712,0,0,0,14713,0,0,0,0,14719,0,14720,14721,14726,0,0,0,14728,\n14729,0,0,0,0,14731,0,0,0,0,0,0,0,14733,14736,14737,0,0,14740,14742,0,0,0,14744,\n14753,0,0,0,0,14755,14758,14760,0,0,0,0,0,14761,14762,14765,14771,0,14772,0,\n14773,14774,0,0,14775,0,0,14776,0,0,0,0,14777,0,14779,0,0,14782,0,0,14785,14786,\n14788,0,0,0,0,0,14795,0,0,0,0,0,0,14798,0,14803,14804,14806,0,0,0,14809,0,0,0,0,\n0,0,14810,0,0,0,0,14811,0,14812,0,0,0,0,0,14815,0,0,0,0,0,0,0,0,14816,0,14818,0,\n0,0,0,0,0,14819,0,14820,0,14823,0,0,0,14824,0,0,14826,14827,0,0,0,0,0,0,0,0,0,0,\n0,0,14830,0,0,0,0,0,14833,0,14845,0,0,0,0,0,14846,0,0,14847,14871,0,14873,0,\n14876,0,14877,14878,14880,0,0,0,0,0,14881,0,14882,14894,0,0,0,0,14895,0,14907,0,\n14908,0,0,0,0,0,0,0,14911,0,0,0,0,14920,0,0,14931,0,14932,14934,14935,0,0,14936,\n0,14945,0,0,0,0,0,0,0,14947,0,0,14948,14949,14951,0,0,14952,0,0,0,14964,14973,0,\n0,14990,0,0,0,0,14995,0,0,14998,15001,0,0,15002,15020,0,0,0,0,0,0,15021,0,15022,\n0,0,0,0,15023,0,0,15025,15029,15033,0,0,0,15034,0,0,0,15035,0,0,0,0,0,15043,\n15044,0,0,0,15045,15046,15048,15050,0,15065,0,0,0,0,15066,0,0,15075,15082,15084,\n0,0,15085,15086,0,0,0,0,0,0,0,0,15088,0,0,0,15089,0,0,0,0,15094,0,15096,0,15097,\n0,15100,0,0,15102,0,0,0,0,0,0,0,0,15105,0,0,15106,0,15109,15113,0,0,0,15115,0,\n15118,0,0,0,0,0,0,15119,0,0,15120,0,0,0,0,0,15123,15129,0,0,0,15130,0,15131,0,0,\n15134,0,15135,0,0,0,15137,15138,0,0,0,0,0,0,15139,0,0,0,0,0,15140,0,0,15154,\n15162,0,15169,15170,0,15175,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15177,0,15178,15179,0,\n0,0,0,0,15183,0,0,0,0,0,0,0,0,0,0,0,0,15185,15187,0,15194,15195,15196,0,0,0,0,0,\n0,0,15204,0,0,0,0,15206,0,0,0,0,0,15207,0,0,0,0,0,0,0,0,0,15213,0,15214,0,0,0,0,\n0,0,0,15232,0,0,0,0,15234,0,15238,15240,0,15248,0,0,0,0,15250,15251,0,0,0,0,0,0,\n0,15252,0,0,0,15255,15262,15266,0,0,0,15267,0,0,0,15277,15279,0,0,0,15280,15281,\n15282,0,0,0,0,0,15285,0,0,0,0,15289,0,0,15291,0,0,0,0,0,0,0,15296,15297,0,0,\n15304,0,0,0,0,15306,0,0,0,0,0,0,15307,15308,0,15309,0,0,15311,0,0,15312,15313,0,\n0,0,0,0,0,0,0,0,0,0,0,15314,15317,0,0,0,15318,15319,0,0,0,0,15320,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,15321,0,0,0,0,0,15324,0,15325,15326,0,15330,0,0,0,0,15334,0,\n15335,0,15341,0,0,15342,0,0,15343,15344,0,0,0,0,15345,0,0,0,0,15347,0,0,15348,\n15349,15350,0,15356,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15357,0,15358,0,0,0,0,0,0,0,\n15359,15360,15364,0,15380,0,0,0,0,0,15392,0,0,15393,0,15395,0,0,0,0,0,0,0,0,\n15396,0,0,15397,15398,0,0,0,0,0,0,0,0,0,15399,0,15400,0,0,0,15402,0,15405,15410,\n0,0,0,0,15411,0,0,0,15412,0,15416,0,0,0,0,0,0,0,15428,0,15435,0,0,15438,0,0,0,0,\n15439,0,0,0,15440,0,0,0,15441,15449,15451,0,0,0,0,0,0,0,15452,0,0,15455,0,0,0,\n15456,0,0,15458,0,15460,15461,0,0,0,0,0,15462,15464,0,15465,0,0,15466,0,0,15467,\n0,0,0,0,0,15468,0,0,0,0,15481,0,0,15484,0,15485,15486,0,0,0,15487,0,0,0,0,0,\n15488,0,15492,15498,0,0,0,15499,0,0,0,15500,0,15501,0,0,15512,0,15522,0,0,0,\n15524,0,15525,15526,0,0,15527,0,0,15545,15546,0,15548,15552,0,15553,0,0,0,15554,\n0,15555,0,15557,15565,15573,15577,15578,0,15582,0,15583,0,0,0,0,0,0,0,0,0,0,0,0,\n0,15586,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15588,0,0,0,0,0,15589,0,0,0,0,0,0,0,15593,\n15594,0,0,0,0,15595,0,0,0,0,0,0,15596,0,0,0,15597,0,0,0,0,15600,0,0,15601,0,0,0,\n0,15602,15603,0,0,0,0,0,0,15604,0,15609,0,0,15612,0,0,15613,0,0,15615,15617,\n15618,0,0,15620,0,15636,15637,0,0,15649,0,0,0,0,0,0,0,15650,0,0,15651,0,0,0,\n15656,0,15658,0,0,0,15664,0,0,15665,0,0,15668,0,0,0,0,0,15669,0,0,15674,0,0,\n15675,0,0,0,0,15676,0,0,0,0,0,0,0,0,0,0,0,15677,0,0,0,0,15678,0,0,0,0,0,15679,0,\n0,15681,0,15686,0,0,0,0,15687,0,15688,0,0,15690,0,0,0,15697,0,15699,15700,0,0,0,\n0,0,0,0,0,0,15701,0,15702,15703,0,15704,0,15705,0,15707,0,15709,0,15712,15716,0,\n15717,0,15718,15720,0,0,0,0,0,15724,0,0,0,15725,0,15726,0,0,0,15740,0,15745,\n15746,0,0,15747,0,15748,0,0,0,0,0,15749,0,0,0,15752,0,15753,0,0,0,0,0,0,15759,0,\n0,0,15765,0,0,0,0,0,0,0,0,0,15767,0,0,0,15771,0,0,15784,0,0,0,0,15785,15790,\n15791,0,0,15792,0,0,0,15807,0,15811,0,0,0,0,0,0,0,0,0,0,0,0,15818,0,0,0,15819,0,\n0,0,0,15821,0,0,0,0,0,15822,15824,0,0,15827,0,0,15829,15831,0,15832,0,0,15833,0,\n15835,15838,15839,15843,0,0,0,0,0,0,0,0,0,0,0,15844,0,0,0,0,15845,15851,15856,0,\n0,0,0,0,0,0,15858,15860,0,15861,0,0,0,15864,0,0,0,0,15865,0,0,0,0,0,0,15866,0,\n15872,0,0,15876,0,0,0,0,15877,15878,15883,15885,0,0,15888,0,0,0,0,0,15889,15890,\n0,0,0,0,0,0,0,0,15892,0,0,0,0,0,0,0,15893,0,0,15894,0,0,0,15895,0,15896,15897,0,\n15898,15901,15902,0,15911,15915,0,15916,0,15924,15935,0,15937,0,0,0,0,0,15950,0,\n0,0,0,0,0,0,15958,0,0,0,15961,0,0,15966,0,15967,0,0,15977,0,0,15978,0,0,15981,\n15982,15983,0,0,0,0,0,0,0,15986,0,0,0,15990,0,15991,15995,15998,0,15999,0,16000,\n0,0,0,0,16008,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,16009,16011,0,16013,0,0,0,0,\n0,0,0,0,16014,0,0,16015,16023,16024,16025,0,0,16026,0,16030,0,16032,0,16033,0,0,\n0,0,0,0,16035,16036,16037,0,0,0,0,0,16039,0,0,0,0,16041,0,0,0,0,0,16043,16044,0,\n0,16047,0,0,0,16048,0,0,16049,16050,16052,0,0,0,0,0,16055,0,0,0,0,0,0,0,0,16056,\n0,0,0,0,0,0,0,16058,16060,16061,0,0,16063,0,0,16064,0,0,0,16067,16068,0,0,16069,\n16078,0,0,0,16079,0,0,0,16080,0,16081,0,0,0,16088,0,0,0,0,0,0,0,0,0,0,0,16089,\n16093,0,16097,0,16103,0,16104,16105,0,0,16256,0,0,16259,0,0,0,0,0,0,0,16260,\n16261,0,0,16262,0,0,16263,0,16268,0,0,0,0,0,0,0,16269,0,0,16270,16273,0,16274,0,\n0,0,0,16275,16276,16277,16280,0,0,0,16281,16284,0,0,0,16286,0,16289,0,0,0,0,0,0,\n0,0,0,16290,0,0,0,0,16291,0,0,0,0,0,0,0,16292,0,0,0,0,0,0,0,0,16293,16295,16297,\n0,16302,0,16304,0,16305,0,16306,0,0,0,0,0,0,0,0,0,0,0,0,16307,16308,16312,0,0,0,\n0,0,0,16313,16315,0,16318,0,0,0,16321,0,0,0,0,0,0,0,16326,16333,16336,0,0,0,0,\n16337,16340,0,0,0,0,0,16345,0,0,16346,0,0,0,0,0,0,0,0,0,16347,0,0,16348,0,0,0,0,\n16349,0,0,0,16350,0,16357,0,0,0,0,16359,16360,0,0,0,0,16362,16363,16364,16365,0,\n0,16366,0,0,0,0,16367,16368,0,16369,16374,0,0,0,0,0,0,0,16376,0,0,0,0,16378,\n16379,0,16380,0,0,0,16381,16383,0,0,0,0,0,16390,0,0,0,16399,0,16402,16404,16406,\n16407,0,0,0,16409,16411,0,0,0,0,16412,0,16413,16415,16423,0,0,0,0,0,16424,0,0,0,\n16428,16434,16435,16449,0,16450,16451,0,0,0,16453,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n16454,0,0,16456,16458,0,0,16459,0,0,16460,0,0,0,0,16462,0,16463,0,0,16466,0,0,0,\n0,0,16479,0,0,16480,0,16481,16484,0,0,0,0,0,0,0,0,0,0,16485,0,0,0,0,0,0,16489,0,\n0,0,0,0,16491,0,0,16498,0,0,16503,0,16505,0,0,0,0,0,0,0,0,16506,0,0,0,16508,\n16509,0,0,0,0,0,0,0,0,16511,16513,0,0,0,16516,0,16517,0,16519,0,16529,0,0,16531,\n0,0,0,0,0,0,16534,0,0,16541,16542,0,0,0,0,0,0,0,0,0,16543,16547,16548,0,0,0,\n16551,0,16552,0,0,0,16553,0,0,16558,0,0,16562,16565,0,0,0,16570,0,0,0,16573,\n16585,0,0,0,16586,16587,16595,0,16596,0,16598,0,0,0,16600,0,0,0,0,0,0,0,0,0,0,0,\n0,0,16601,0,0,0,0,16603,0,0,0,0,0,0,0,16604,16612,0,0,0,0,16613,0,16618,0,0,0,\n16640,0,0,16641,0,0,0,0,0,0,16645,0,0,0,0,16646,0,0,0,0,0,0,16651,0,0,0,0,16653,\n16654,0,0,0,16655,0,0,16656,16667,0,0,0,0,16671,0,16672,0,0,0,16673,0,0,0,0,0,\n16676,0,16686,0,0,0,0,16689,0,16690,0,16692,0,16693,0,16694,0,16696,0,0,0,16705,\n0,0,0,0,0,0,16707,0,0,0,16709,0,0,0,0,16711,0,16712,16713,0,0,0,16715,0,0,0,0,\n16716,0,0,0,0,0,0,0,0,0,16718,16724,0,0,16726,16727,0,0,0,0,0,0,0,16728,0,16729,\n0,0,16730,0,0,0,0,0,16731,0,0,0,16732,0,0,0,0,16734,16738,0,0,0,0,0,0,0,0,16743,\n0,0,16745,0,0,0,0,0,16749,0,16752,0,0,0,0,16756,0,0,16758,0,16759,0,0,0,0,0,\n16760,0,0,0,0,0,0,0,16762,0,16769,0,16770,0,16772,0,0,0,16777,16780,0,0,0,0,0,0,\n16781,0,0,16782,0,16784,0,0,16785,16787,16792,0,0,16794,0,0,0,16798,0,0,16809,0,\n0,16814,16816,16817,0,16819,0,0,0,0,0,0,0,0,0,0,16820,0,0,16836,16839,0,0,16841,\n16851,16857,0,0,16858,16859,0,0,16860,0,0,0,0,0,0,0,0,16862,0,16863,0,0,0,0,0,0,\n0,16864,0,0,0,0,0,0,0,16876,0,16881,16882,0,16885,16886,0,16887,0,0,0,16889,\n16891,0,0,0,0,0,16894,16895,0,0,0,0,0,0,0,0,0,0,0,16897,0,16898,0,0,0,0,0,16913,\n0,0,16924,16925,16926,0,0,16927,0,0,0,16937,16938,0,0,0,16940,16941,0,0,0,16942,\n16945,0,16946,16949,16950,0,0,0,16952,16955,0,0,0,16965,0,16969,0,0,16975,0,0,\n16976,0,0,0,0,16978,0,0,16981,0,16983,16989,0,0,0,0,16990,0,0,16991,0,0,0,16993,\n0,16994,16996,17000,0,0,0,0,0,17002,17004,0,17006,0,0,17007,0,0,0,0,17008,17013,\n17014,0,0,0,0,0,0,0,0,0,17021,0,17031,0,0,0,0,0,17033,17036,0,17038,0,0,17039,0,\n17045,0,0,17046,17047,0,0,0,0,17048,0,17049,17050,0,17051,17053,0,17054,0,17055,\n0,0,0,0,0,17063,0,0,17064,0,0,0,0,0,0,0,17065,0,0,17068,0,0,0,0,0,17072,0,0,0,0,\n0,0,17073,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17074,0,17080,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,17081,17083,17084,0,0,0,17085,0,0,0,0,17092,0,0,0,0,0,0,0,\n0,0,17093,0,17095,17102,0,0,0,0,0,0,17103,0,0,17105,0,17107,0,0,0,0,17114,0,0,0,\n0,0,17115,17125,17127,0,0,17128,0,0,0,17129,17130,0,17131,0,0,0,0,0,17132,17135,\n17145,0,0,0,0,0,0,0,0,17146,0,17147,0,17148,0,0,0,0,0,0,17149,17150,0,17151,\n17153,0,17155,0,0,0,0,17163,17171,0,17174,0,0,0,0,17179,0,0,17182,17185,0,0,0,0,\n0,17186,0,0,17188,0,0,0,0,0,0,0,17189,17191,0,17194,0,0,0,0,0,0,0,0,0,17195,\n17196,17203,17204,0,0,17205,17217,0,0,0,0,0,17218,0,0,0,0,17219,0,17220,0,17221,\n0,0,17230,0,0,0,0,0,17236,0,17238,17239,0,0,0,17241,17244,0,0,17245,0,17248,0,0,\n17251,0,17252,0,0,17264,0,17266,0,0,0,17268,0,0,0,0,17271,17272,0,17273,0,17295,\n0,17302,0,17305,0,0,0,17306,0,0,0,0,0,0,0,17308,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n17309,0,17310,17313,0,0,0,0,17314,17315,0,17317,0,0,0,0,17318,0,0,0,0,0,0,0,\n17320,0,0,0,0,0,0,17334,0,17344,17348,0,0,0,17350,17351,0,0,17353,0,0,17354,0,0,\n0,0,0,0,0,0,0,17355,0,0,0,0,0,0,17356,17357,0,0,17359,0,0,0,17371,0,17372,0,0,0,\n17393,0,0,0,0,17394,0,0,0,0,0,17395,0,0,17399,0,0,0,17401,17417,0,17418,0,17419,\n0,0,0,0,0,17422,17423,0,0,0,0,0,17424,0,0,0,0,0,17428,17429,17433,0,0,0,17437,0,\n0,17441,0,0,17442,0,0,17453,0,0,0,0,0,0,0,0,17454,17456,17462,0,0,17466,0,0,\n17468,0,0,17469,0,0,0,0,17470,0,17475,0,0,0,0,0,17479,0,0,0,17483,17484,0,17485,\n0,17486,0,17491,17492,0,0,17493,0,17494,17495,0,0,0,17496,0,0,0,17497,0,0,0,\n17502,0,0,0,0,0,17503,0,17505,0,17507,0,0,0,17512,17513,17514,0,0,17515,0,0,0,\n17519,0,0,0,17522,0,0,17523,0,0,0,0,0,0,0,0,0,17527,0,0,0,17528,0,0,0,17534,0,0,\n0,0,17536,0,0,0,17539,0,17540,17543,17549,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17556,\n0,0,17558,0,17559,0,0,17560,0,0,0,17563,0,0,0,0,0,0,17564,0,0,17565,17566,0,\n17567,0,0,0,0,0,0,17569,17570,0,17575,0,0,0,0,0,0,0,0,0,0,0,17581,0,0,0,17582,\n17583,0,17586,0,0,17587,0,0,0,0,0,0,0,17588,0,0,0,0,17596,17597,0,0,17598,17600,\n0,0,0,0,0,0,17601,0,0,0,17604,0,0,17605,0,0,17607,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,17612,0,0,17618,0,17621,17622,0,0,0,0,17623,0,0,17624,0,0,17630,0,0,\n17631,17633,17634,0,0,0,0,0,0,0,17635,0,0,17636,0,0,17637,0,17638,0,17640,0,0,0,\n0,0,0,0,0,0,0,17641,0,0,0,0,0,0,0,0,0,0,17643,0,0,0,0,17645,0,0,0,0,0,0,0,0,\n17646,17662,0,0,0,0,0,0,0,0,0,17663,17664,0,17665,17666,0,0,0,17669,17671,17673,\n0,17679,0,0,0,0,0,0,0,17684,0,0,0,17686,0,17714,0,0,17720,17722,17726,0,0,17728,\n0,0,17729,0,0,0,17732,0,17733,0,17734,0,0,0,17735,0,0,0,0,17737,0,0,0,0,17739,0,\n0,0,17741,17742,0,0,0,0,17743,17744,17745,0,0,0,17749,0,17750,17751,17752,17754,\n17761,17762,0,17763,0,17766,0,17772,0,0,0,0,0,17775,0,0,0,0,0,0,0,17776,0,0,\n17777,0,0,17778,17779,0,17782,17783,0,0,0,0,0,0,0,0,0,0,17784,0,0,0,0,0,0,0,\n17821,0,0,0,17822,0,0,0,17823,17825,0,0,0,0,0,17826,17831,17832,17833,0,0,17845,\n0,0,0,17846,0,0,0,17848,17850,17854,0,17855,0,0,17859,0,0,0,0,0,0,17860,17861,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,17870,17871,0,0,0,0,0,0,17872,0,0,0,17879,0,\n0,0,17881,17883,0,17884,0,17885,0,0,17886,0,0,17887,17891,17953,0,0,0,0,17954,0,\n0,17955,0,17968,0,0,17972,0,0,0,0,0,17974,0,0,0,0,17976,17978,0,0,17983,0,0,0,0,\n18003,0,0,0,0,0,18007,0,0,0,0,0,18009,0,0,0,0,0,0,0,18010,0,0,0,0,0,0,18012,0,0,\n18014,0,0,0,18015,0,0,0,18016,0,18017,0,0,0,18030,0,0,0,0,0,0,0,18031,0,0,18036,\n18037,18038,0,0,18049,18056,0,18057,18058,0,18059,0,0,0,0,0,0,0,0,18062,0,0,0,0,\n18064,0,0,0,0,0,0,0,0,18067,0,0,0,18068,0,0,18075,0,0,18078,18093,18094,0,0,0,0,\n0,0,0,0,18097,0,0,0,0,0,18098,18100,0,0,0,18108,0,18111,0,0,18112,0,18113,0,0,\n18115,18116,0,18118,0,0,0,0,18121,0,0,0,0,18123,0,0,0,0,0,0,0,0,0,18124,0,0,0,0,\n18125,18126,0,18127,0,0,18128,18135,0,0,0,0,0,0,0,0,0,18150,0,0,0,0,0,18151,\n18152,0,0,18156,18164,0,18166,18171,0,0,0,0,0,0,0,0,0,18172,18183,0,18184,0,0,0,\n0,18185,0,18187,0,0,0,0,0,18188,0,0,0,0,0,0,0,0,18189,0,0,18190,0,0,18191,18192,\n0,0,18194,18195,18196,0,0,0,18197,0,18203,0,18204,0,0,0,0,18205,0,0,0,18207,\n18208,0,0,18214,0,0,0,18215,18216,0,0,0,18220,0,0,18222,0,0,0,0,0,18223,0,18225,\n18231,0,18234,0,18235,0,0,0,0,18240,0,0,18241,18242,0,0,0,0,0,18243,18251,0,\n18253,0,18254,0,0,0,18266,0,0,0,0,0,0,18269,18270,18271,18273,18281,0,0,0,0,0,0,\n0,0,0,0,0,0,18282,0,18283,0,18284,0,0,0,0,0,0,18285,0,18287,18289,0,0,18290,0,0,\n0,0,18308,0,0,0,18310,0,0,0,0,0,0,0,0,0,0,0,0,18311,0,18312,18313,0,18315,0,0,\n18316,18320,0,18331,0,18332,0,18336,0,0,0,0,18337,0,18340,0,0,0,0,0,0,0,0,0,\n18341,0,18344,18345,0,18346,0,0,0,0,0,18348,0,18351,0,0,18356,0,0,0,0,0,0,18357,\n0,0,0,0,0,18367,0,0,0,18368,0,18369,0,18370,18371,0,0,0,18437,18444,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,18445,18450,0,0,0,0,18451,0,18452,0,0,0,18453,0,0,0,0,0,18455,0,\n0,0,18456,0,18457,0,18460,0,0,18461,0,0,0,0,0,0,0,0,18466,0,0,18467,0,0,0,0,\n18473,0,0,0,18476,0,18477,0,0,0,18478,18479,18480,0,0,0,18485,0,0,0,18486,0,0,0,\n0,0,0,18488,18490,0,0,0,0,0,0,18491,0,0,0,0,0,18495,0,0,18496,0,0,0,0,0,0,18505,\n0,18521,0,18522,18523,0,0,0,18525,18526,0,0,0,0,0,18527,0,0,0,0,18532,18533,0,\n18534,0,0,0,0,0,0,18535,18537,0,18538,0,0,0,0,0,0,18540,18541,18542,18543,0,\n18546,0,0,0,0,18553,18556,0,0,18558,0,0,18569,18571,0,0,0,18572,0,18574,0,0,0,0,\n18586,0,0,0,0,0,18588,0,0,18589,0,0,0,0,0,0,18590,0,18592,0,0,0,0,18594,0,0,0,\n18596,0,0,18597,18598,0,0,18601,0,0,0,0,18602,0,0,0,18603,18604,0,18605,0,0,0,0,\n18608,0,0,18611,0,0,0,0,0,0,0,0,0,18612,0,18616,0,0,18617,18619,0,0,0,18628,0,0,\n0,18629,0,0,18630,0,0,0,0,0,0,0,18631,0,18632,0,0,18635,18637,0,0,0,0,0,0,18641,\n18643,18648,0,18652,0,0,18653,0,18655,18656,0,0,0,18657,0,0,18666,18674,0,0,0,0,\n18677,18684,18685,0,0,18686,0,0,18690,0,0,0,0,0,0,0,18695,18696,0,0,0,0,0,0,0,0,\n0,0,18697,0,0,18700,0,0,0,0,0,0,18702,0,18708,0,0,18709,0,18710,0,0,18711,0,\n18714,0,0,18718,0,0,0,0,0,0,18719,0,0,18722,0,18726,0,0,0,0,0,0,0,0,0,0,0,0,0,\n18731,0,0,0,0,0,18739,18741,0,0,18742,0,18743,18744,18746,18748,0,18752,18753,0,\n0,18754,18763,0,18765,0,0,0,18766,0,0,0,18769,0,0,0,0,0,18773,18778,18779,18781,\n0,0,18784,18787,0,18788,0,18793,0,0,0,0,0,0,18795,0,0,18800,0,0,0,0,0,18801,\n18804,0,0,0,0,0,0,0,18806,0,0,0,18811,18815,18816,0,0,0,0,18825,0,0,18827,18829,\n0,0,18830,0,0,0,0,18831,0,0,18832,0,0,0,0,18833,0,18840,0,18841,0,18842,0,0,0,0,\n18843,0,18844,0,0,0,0,0,0,18845,18846,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n18848,0,0,0,18853,18860,0,0,18862,18866,0,0,18867,18869,0,0,18874,18881,18891,0,\n0,0,0,0,0,0,0,0,0,18892,0,0,0,0,0,0,0,0,18895,0,18896,0,0,0,18900,0,0,0,18901,0,\n18902,18915,18916,0,0,0,0,0,0,0,0,18919,0,0,0,0,0,18920,0,0,0,18921,18929,0,0,0,\n0,18930,0,0,0,0,0,0,18932,0,0,0,0,18934,18942,0,0,0,18951,18957,0,0,0,0,18958,0,\n0,0,0,18959,18960,0,0,18961,0,0,18962,0,0,0,0,18963,18964,0,0,0,18965,0,18967,0,\n0,0,0,0,0,0,0,0,18968,0,18969,0,18970,18973,18976,0,0,0,0,0,0,18977,0,0,0,18981,\n0,0,0,18990,0,18998,0,0,0,0,0,18999,19003,0,0,19005,0,0,0,19006,0,0,0,0,0,0,\n19008,19011,0,0,19018,0,0,19019,0,19024,0,19031,19032,0,19039,0,19041,19050,0,0,\n0,19051,19055,19056,0,19059,19063,19064,0,0,19088,0,0,0,19093,19094,0,0,0,0,\n19095,0,19096,0,0,0,19097,0,0,19098,0,19099,19100,0,0,19103,0,0,0,0,0,0,0,19111,\n0,0,0,0,0,0,19112,0,0,0,19116,19117,0,19121,19122,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,19123,19124,0,0,0,0,0,0,0,19125,19126,0,19128,0,0,0,0,0,0,0,0,0,0,\n19129,19130,19131,19132,0,0,19146,0,0,19147,19156,19158,0,0,0,0,0,0,0,0,19182,\n19185,0,0,19187,0,0,0,19193,0,0,0,0,0,19194,0,19197,0,0,0,0,19198,0,0,0,0,0,0,0,\n0,0,0,19202,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19203,0,19205,19210,\n0,0,0,19213,0,19218,0,0,0,19223,19229,0,0,19230,0,0,19231,19232,19233,19239,0,0,\n0,0,0,19240,0,19248,19249,0,0,0,0,19254,0,19256,19258,19259,0,0,19261,0,19266,0,\n0,0,19272,0,19278,19281,19282,0,0,0,0,0,0,0,0,0,0,0,0,19283,0,0,19284,0,0,19285,\n19287,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19288,19291,0,19292,0,0,0,0,19297,0,19298,0,0,\n0,0,19302,19303,0,0,0,0,19304,19305,0,0,0,0,19314,0,0,19315,0,0,19321,0,0,0,0,0,\n0,0,19322,0,19333,0,19334,19335,0,19336,19337,0,0,0,0,0,0,0,0,0,0,0,19346,0,0,\n19353,0,19354,19362,0,19366,19367,0,0,19369,0,19375,0,19377,19380,19388,0,0,0,0,\n0,19389,19390,0,0,0,0,19392,0,0,0,0,0,19402,0,0,0,0,0,0,0,0,19412,0,0,19413,\n19422,0,19424,0,0,0,19425,0,0,0,19428,0,0,0,0,19431,0,0,0,0,0,19432,0,0,0,0,0,\n19448,19459,0,0,19461,0,19462,19463,0,19467,19474,19482,0,0,0,0,19494,0,0,0,0,\n19501,0,0,0,0,0,0,0,0,0,0,19502,19504,0,0,0,0,0,0,0,19505,0,0,0,0,19506,19507,0,\n0,0,19508,0,0,19511,0,0,19514,0,19515,0,19516,0,19518,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,19530,0,19537,19538,0,19543,19546,0,19547,19551,0,0,0,0,0,0,19552,\n19553,0,0,0,0,0,0,0,0,0,0,0,0,19555,0,0,19556,0,0,0,0,0,0,0,0,0,0,0,0,19560,\n19561,0,0,19562,0,0,0,0,0,0,19565,19567,0,19568,0,0,0,19569,19570,0,19578,0,0,0,\n0,19580,0,0,0,0,19581,19584,0,0,0,0,0,0,0,19585,19586,0,0,0,19587,19588,0,19589,\n0,0,0,0,0,0,19592,19593,19599,0,19600,0,0,19604,0,0,19605,0,19606,19608,19610,0,\n19613,19614,0,0,0,0,0,0,19616,19617,0,0,19618,0,0,19619,0,0,0,19620,19621,19631,\n0,0,19632,19634,19636,0,19643,0,0,19644,19658,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,19659,0,0,0,0,0,0,0,0,0,0,0,19675,19677,0,0,0,0,19679,0,19683,0,19684,0,0,\n0,0,0,0,19687,0,0,0,0,0,0,0,0,19688,19689,19692,0,0,0,0,0,0,0,19695,19697,0,0,0,\n0,0,19698,19699,0,0,19700,0,19702,0,0,19703,0,0,0,0,0,0,19704,19708,0,19710,0,\n19713,0,0,0,19715,0,0,0,0,19718,0,0,0,0,0,0,0,19720,0,19722,0,0,19725,0,0,0,0,0,\n0,0,0,0,0,0,0,0,19730,0,0,0,0,0,19731,0,19734,19735,19739,0,0,19740,0,19741,0,0,\n0,19746,0,0,19747,0,19771,0,0,0,0,0,0,0,0,19772,19775,0,0,0,0,0,0,19778,0,0,0,0,\n0,19779,0,0,19780,19790,0,19791,0,0,19792,0,0,0,19793,0,0,19796,19797,0,0,0,\n19799,0,0,0,19801,0,0,0,0,19803,0,19804,0,19805,0,0,19807,0,0,0,19808,0,0,0,0,0,\n0,19809,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,19816,0,19821,0,19822,19830,19831,0,0,\n0,19833,0,0,0,0,0,0,0,0,0,0,19838,0,0,0,0,19839,0,0,19843,0,0,0,0,19845,0,0,0,0,\n19847,0,0,19848,0,19849,0,0,0,0,0,0,0,19851,0,0,0,19854,0,0,0,0,0,0,0,0,0,19864,\n0,19865,0,19866,0,0,0,0,0,0,0,19868,0,0,19870,0,0,19871,0,0,19872,19873,19875,0,\n19880,19882,19884,0,0,19885,19886,19888,0,0,0,0,0,0,0,0,0,0,0,0,19890,19892,\n19893,0,0,19894,0,0,0,19895,0,19896,19902,0,0,19903,0,0,19905,0,0,0,19906,0,\n19908,0,19909,19911,0,0,0,19913,19920,0,19938,19939,19940,0,0,0,0,0,0,0,19942,0,\n19943,0,19945,0,0,0,19951,19952,19954,19960,0,19965,0,19971,0,0,0,0,0,19975,0,\n19976,0,19990,0,0,19991,0,19993,0,19995,0,0,0,19998,19999,20001,0,20003,20005,0,\n20011,20012,0,0,0,0,0,0,20014,0,20020,0,0,0,0,20021,0,0,0,0,0,20023,20024,0,0,0,\n0,0,20025,0,0,20027,0,0,20029,0,0,20032,0,0,0,0,20044,20045,0,20048,20049,0,0,\n20050,0,20052,0,0,20054,20057,0,0,0,0,0,0,0,0,0,20059,0,0,20061,0,20062,0,20064,\n0,0,20066,0,0,20067,0,0,0,0,20069,0,0,0,0,0,0,20070,20071,0,0,0,0,0,0,0,0,0,0,0,\n20072,0,0,20073,20074,0,0,0,0,0,20075,0,20078,0,0,0,0,20080,0,20081,0,0,0,0,0,0,\n20095,0,20098,0,0,0,0,0,0,0,20107,0,0,0,0,0,0,0,0,20112,0,0,0,20113,20114,0,0,0,\n20115,20123,20124,0,0,0,20131,20133,20134,0,0,0,0,20136,0,0,20137,20138,20150,0,\n20152,0,0,0,20153,0,0,20154,0,0,0,20158,0,20163,0,0,20164,0,0,0,0,0,0,0,20166,0,\n20168,0,20170,0,20175,0,0,20178,0,0,0,0,20223,0,0,0,0,20224,0,20226,0,0,20230,0,\n20231,0,0,0,0,20232,0,0,20233,20234,0,20244,0,20247,0,0,0,0,0,0,20249,0,0,0,\n20250,0,0,0,0,20251,0,20253,0,20254,0,0,0,0,20256,0,0,20264,0,0,0,0,20266,0,0,0,\n20278,0,0,20279,20282,0,0,0,0,0,20283,0,20284,0,20285,0,20287,20290,0,0,0,0,\n20292,0,0,0,0,20293,20297,0,0,0,0,0,0,20299,0,20300,20303,0,0,0,0,0,0,20307,0,0,\n20308,0,20309,0,20310,0,0,0,0,0,0,20312,0,0,0,20314,0,0,0,0,20315,20316,0,20322,\n0,0,0,0,0,0,20339,0,0,0,20342,0,0,0,0,20352,0,0,0,0,0,0,0,0,0,0,20362,0,0,20365,\n0,20375,20377,0,0,0,0,0,0,0,0,0,0,0,20378,20379,0,20380,0,0,20381,0,20382,0,\n20383,0,20388,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20390,20392,20393,0,0,20395,0,0,0,0,0,\n20396,0,0,0,0,0,0,0,0,20398,20415,0,0,0,20417,0,0,20420,0,0,20426,20428,0,20431,\n0,0,20432,0,20433,20434,20435,0,0,0,0,20440,0,0,0,0,0,20442,0,20443,0,20446,0,0,\n0,0,20448,0,20451,0,0,0,0,0,0,0,0,0,20452,20453,0,0,20454,0,0,0,0,0,0,20457,0,\n20458,0,0,0,20465,0,0,0,0,0,20469,0,0,0,20473,0,20476,0,0,0,0,0,0,0,0,20477,0,0,\n20485,0,0,20486,0,0,20487,0,20496,0,20497,0,0,20498,0,0,0,0,0,0,0,0,0,0,20499,\n20500,0,20501,0,0,0,0,0,20520,20527,0,20529,0,0,0,0,20539,0,0,20540,0,0,0,20543,\n0,0,0,20546,0,0,0,0,0,20548,0,0,20563,0,0,20564,0,20566,0,0,0,0,0,20589,0,0,0,0,\n20590,0,0,20593,20594,0,0,0,0,20595,0,20597,20598,0,0,0,20618,20620,0,0,0,0,\n20621,0,0,0,0,20627,0,0,0,0,0,20628,0,0,0,20629,0,20630,0,0,20639,0,0,0,0,0,\n20707,0,0,20709,0,0,0,20713,20714,0,0,0,0,0,20724,20725,0,0,0,0,20726,20728,\n20729,0,20733,0,20734,0,20735,20736,0,20737,0,0,20744,0,20745,0,20748,0,0,20749,\n0,0,0,0,0,0,0,0,20750,0,0,0,0,20754,0,0,0,20761,0,0,20763,0,0,0,0,0,0,0,20766,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,20767,0,0,0,0,20768,0,20769,20777,0,0,0,0,0,0,20785,0,\n0,0,20786,20795,20801,0,20802,0,20807,0,0,20808,0,0,20810,0,0,20811,0,20812,0,0,\n0,0,0,20813,0,0,20818,20820,20821,0,0,0,20822,0,20823,0,0,0,20826,0,0,0,0,0,0,0,\n20829,20830,20831,0,20832,20836,0,0,20839,0,0,20840,20842,0,20843,0,20844,0,\n20854,0,0,0,20855,0,0,0,0,20856,0,0,0,20869,0,0,20871,0,0,0,0,0,0,0,20873,0,0,0,\n0,0,20876,0,0,0,0,0,20880,0,0,20882,0,0,0,0,20883,20884,0,0,20890,0,0,0,0,0,0,0,\n0,0,20891,0,0,0,0,0,20905,0,20906,20910,0,0,20912,20915,0,0,0,0,0,20916,0,20917,\n0,20919,20920,20922,0,20927,0,20928,20929,20930,0,0,20935,0,0,20939,0,0,20941,0,\n0,0,20943,0,0,0,20946,20947,0,0,0,0,0,20950,0,20954,0,0,20955,20964,0,0,20967,0,\n0,0,0,0,20973,20975,0,0,0,20984,0,20987,20988,0,0,0,0,0,20989,0,0,0,20995,0,\n20998,0,20999,0,0,0,0,21000,21001,0,0,0,0,21008,0,21010,0,21016,0,0,0,21017,\n21018,0,0,0,0,0,21021,21026,21027,21028,0,0,21029,0,0,0,0,0,21030,0,0,0,0,0,0,0,\n0,0,0,0,0,0,21031,21032,0,0,0,0,0,21037,0,0,21038,0,0,0,0,0,0,0,0,0,21039,0,\n21041,0,21046,21047,0,0,0,21049,21053,0,0,21057,21064,21065,0,0,21066,21067,0,0,\n0,21069,0,0,0,21071,21072,0,0,21073,0,21074,0,0,21078,0,0,0,0,21079,0,0,21080,\n21081,0,0,21086,21087,0,21089,0,0,0,0,0,0,0,21091,0,21093,0,21094,0,0,0,0,0,0,0,\n0,21095,0,0,0,0,0,21096,0,21098,0,0,0,0,0,0,0,21099,0,0,21100,21101,21102,0,0,0,\n0,0,21103,0,21104,0,0,0,0,0,21105,21108,21109,0,0,21112,21113,0,0,0,0,0,0,21115,\n21122,21123,0,0,0,0,0,21125,0,0,0,0,0,0,0,0,21129,21131,0,0,21134,0,0,0,21137,\n21142,0,21143,0,0,21144,0,21145,21146,0,21152,21154,21155,21156,0,0,0,21160,0,0,\n0,0,0,0,21161,0,21164,0,21166,0,0,0,0,21170,0,0,0,0,21171,0,0,21172,0,21174,0,\n21175,0,0,0,0,0,21176,21179,21188,0,0,0,21189,0,0,21190,0,0,0,21192,0,0,21193,0,\n0,0,21198,0,21212,0,0,21213,0,0,0,0,0,0,21215,21216,0,0,21223,21225,0,21226,0,0,\n0,0,21227,21228,0,0,21229,0,0,0,0,21230,21236,0,0,0,0,0,0,0,0,0,0,0,0,0,21237,0,\n0,21238,21239,0,0,0,0,21256,0,0,0,0,0,21257,0,0,0,0,0,0,0,21259,0,0,0,21263,0,\n21272,0,21274,0,21282,0,0,0,0,0,0,0,0,21283,0,0,0,0,0,0,0,0,21294,0,0,21297,0,0,\n0,0,21298,0,0,0,21299,0,21300,21302,0,21316,0,21318,21322,21323,0,21324,0,21326,\n0,0,0,21327,21328,0,0,0,21352,0,0,21354,21361,0,0,0,0,0,0,0,0,0,0,0,0,0,21362,0,\n0,0,21363,0,0,0,0,0,0,0,0,0,21366,0,0,21367,21372,21374,0,0,0,21375,21377,0,\n21378,0,0,0,21380,0,0,0,0,0,0,0,0,0,0,21381,0,0,0,0,0,0,21382,0,21383,0,0,21384,\n0,0,21385,0,0,0,0,21389,21390,0,0,0,0,0,0,0,0,0,0,0,0,0,21397,21398,0,0,0,0,0,0,\n0,0,0,0,21399,0,21400,0,0,0,0,21402,0,0,0,21403,21404,0,21405,21406,0,0,0,21407,\n0,0,0,0,0,0,0,0,0,0,0,0,21408,0,0,0,0,21409,0,21421,0,21422,0,0,0,21425,21428,0,\n0,0,0,21429,0,0,0,0,0,21433,0,0,0,0,0,0,0,0,0,0,21434,0,21443,0,21444,21449,0,\n21452,0,21453,21454,0,0,0,21457,0,0,21458,0,0,0,21460,21461,0,0,21464,0,0,0,\n21473,21478,0,0,21479,0,0,21481,21483,0,0,0,0,0,0,0,0,21484,0,0,21485,21486,0,0,\n21488,0,0,0,0,0,0,21523,0,0,21525,0,0,0,0,0,0,0,21526,0,0,0,0,0,0,21529,21530,0,\n0,21531,0,0,21533,0,0,21539,21564,0,21567,0,0,0,0,0,0,0,0,21575,0,0,0,0,21577,0,\n0,0,0,0,21591,0,0,21604,0,0,0,0,0,0,0,0,0,21605,0,21606,0,0,21617,21618,21619,\n21620,0,0,0,0,0,0,0,0,0,0,0,0,0,21623,0,0,0,0,21631,0,21635,0,0,0,0,21639,21646,\n21653,21662,0,0,21663,21664,0,21666,0,0,21667,0,21670,21672,21673,0,21674,21683,\n0,0,0,0,0,21684,0,21694,0,0,0,0,21695,21700,0,21703,0,21704,0,0,21709,0,0,0,\n21710,0,0,0,0,0,0,0,0,21711,0,0,0,21712,0,21717,0,21730,0,0,0,21731,21733,0,0,0,\n0,21737,21741,21742,0,21747,0,0,0,21749,0,0,0,0,0,0,0,0,0,0,0,0,0,21750,0,0,0,0,\n0,21752,0,0,0,0,21753,0,0,0,0,0,0,21755,21756,0,21757,0,0,0,0,0,0,21760,0,0,\n21763,0,0,0,0,0,0,0,0,0,21764,0,0,21766,0,0,21767,0,0,0,0,0,0,0,0,0,21773,0,\n21774,0,0,21775,0,0,0,0,21776,0,0,21777,0,0,0,0,0,0,0,0,0,21780,21787,21788,\n21791,0,0,0,21797,0,0,0,0,0,21805,0,0,0,0,21806,0,21807,21809,0,21810,21811,0,\n21817,21819,21820,0,21823,0,21824,0,0,21825,0,0,21826,21832,0,0,0,0,0,21833,\n21848,21849,0,0,21867,21870,21871,21873,0,0,0,21874,0,0,0,0,0,0,0,0,0,21875,0,\n21878,0,0,0,21879,0,21881,21886,0,0,0,0,21887,0,0,21888,21894,21895,21897,0,\n21901,0,21904,0,0,21906,0,0,0,21909,21910,21911,0,0,21912,0,0,21913,21914,21915,\n0,21919,0,0,0,0,0,0,0,21921,0,0,21922,21933,21939,0,0,0,0,0,0,0,0,0,0,0,21944,0,\n0,0,0,0,21945,0,21947,0,0,0,0,0,0,0,0,0,0,21949,0,0,0,21950,0,0,0,0,0,0,0,0,0,0,\n0,0,0,21951,0,21952,0,0,0,0,0,0,0,0,0,21954,21957,0,0,0,0,21958,0,21959,0,0,0,0,\n0,0,21962,21963,0,0,0,0,0,0,0,0,21964,21965,0,0,21969,21970,0,0,0,21974,0,0,\n21980,21981,0,21982,0,0,0,0,0,21985,0,21988,0,21992,0,21999,0,0,0,0,0,0,22001,0,\n22002,0,0,0,0,0,0,22003,0,0,0,0,0,22004,0,0,0,22008,0,22009,22015,0,0,22016,0,0,\n0,22017,22019,0,0,0,0,0,0,0,0,0,22020,0,0,0,0,0,0,0,0,0,0,22021,22037,0,22039,0,\n0,0,22040,0,0,0,22048,22049,0,0,22053,22055,22056,22059,0,0,22060,22061,0,0,\n22064,0,0,0,0,22066,0,0,0,0,0,0,0,22073,0,0,0,22074,22075,0,0,0,0,0,0,0,22076,0,\n0,0,0,22077,22084,22099,0,0,0,0,0,0,0,22104,0,0,22107,0,22108,0,22109,0,22110,0,\n0,0,0,0,0,0,22111,22119,0,22120,22122,0,0,0,0,22125,0,0,0,22128,22129,0,0,0,0,0,\n0,22141,0,0,0,22142,0,0,22144,22146,0,22148,22149,22151,22154,0,0,0,22162,0,0,0,\n0,22164,22177,0,0,0,0,22179,0,22182,22183,0,0,22184,22188,0,0,0,0,0,0,0,0,22190,\n0,22194,22201,0,0,22208,0,22209,0,22212,0,0,22215,0,22223,22231,0,0,22232,0,\n22234,0,0,22235,22236,0,22237,0,22240,0,0,0,0,0,22241,0,0,0,22242,22246,22247,0,\n0,0,22259,22268,0,22269,0,0,0,0,0,0,0,22270,0,0,0,0,22271,0,22272,0,22277,0,0,0,\n0,0,22278,22280,22283,22286,0,0,22287,22289,0,0,22290,0,22293,0,0,0,0,0,0,0,0,0,\n0,22295,0,22301,22302,0,0,0,22305,0,22308,0,0,0,0,0,0,0,0,0,0,22315,0,0,0,22317,\n0,22334,0,0,0,22335,0,0,0,0,0,22336,0,22338,22344,0,22347,22349,0,22350,0,0,0,0,\n0,0,0,22357,0,0,0,0,0,22358,0,0,0,0,0,0,0,0,0,0,22359,22360,0,0,0,0,0,0,0,0,\n22361,22366,0,0,22369,0,22370,22373,0,0,0,0,0,22375,0,22377,0,0,0,0,0,22378,0,0,\n0,0,22381,0,0,0,0,22382,0,22383,0,0,0,0,0,0,0,0,0,22391,0,0,22392,22395,22396,\n22402,0,0,0,0,0,0,0,0,0,0,0,0,0,22405,0,0,22406,0,0,22408,0,0,22409,22410,0,0,0,\n0,0,0,22424,0,0,0,0,22426,0,0,0,22427,0,22428,0,22432,0,22435,22442,22443,0,0,0,\n0,22444,0,0,0,0,0,22446,0,22454,0,22455,0,0,0,22465,0,22470,0,22471,0,0,0,0,\n22472,22473,0,22487,0,0,0,22488,0,0,0,0,22489,0,0,22499,0,0,0,0,0,0,22514,0,0,\n22515,0,0,0,0,0,0,0,22516,0,0,0,22517,22520,0,0,0,22534,0,0,22535,0,0,22536,0,\n22540,22553,0,22555,0,0,0,0,22561,0,0,22562,0,0,0,0,0,0,0,0,0,0,0,22566,0,0,0,0,\n22567,22568,0,0,22575,0,22579,0,22582,22583,22585,0,0,0,0,0,22586,0,0,22587,0,0,\n22590,0,0,0,0,0,22591,0,22592,0,0,0,0,0,22593,0,22602,0,0,22604,0,0,22609,0,0,\n22618,0,0,0,0,0,0,22619,0,22624,22625,0,0,22638,0,0,0,0,0,22639,0,0,22640,0,0,0,\n0,0,0,0,22644,0,22645,22647,0,0,0,0,22652,22653,0,0,0,22654,0,22655,0,0,0,22656,\n0,0,0,0,0,0,0,0,0,0,22673,22675,22676,0,0,22678,22679,0,22691,0,0,0,0,0,0,0,\n22693,0,0,22696,0,22699,22707,22708,0,0,0,0,0,0,0,0,22718,0,22719,0,0,0,0,22723,\n0,0,0,22724,22725,0,0,0,0,0,0,0,0,0,0,0,0,0,0,22726,22728,0,0,0,0,0,0,0,0,22729,\n0,0,22731,0,0,0,0,22732,22735,22736,0,0,0,0,22739,0,22749,0,0,22751,0,0,0,0,0,0,\n0,0,0,0,0,22758,0,0,0,0,0,22760,0,0,0,0,0,22764,22765,22766,0,22768,0,0,0,0,0,\n22769,22770,0,0,0,0,0,0,22771,0,0,22772,22775,0,22776,22777,22780,0,0,22782,\n22784,0,22787,0,22789,22796,0,0,0,0,0,22798,0,0,0,0,0,0,22802,0,22803,22804,0,0,\n0,0,0,0,0,0,0,0,22805,0,0,22810,22811,22814,22816,0,22825,22826,0,22831,22833,0,\n0,0,0,0,0,0,0,0,22834,0,22836,22838,0,22839,0,0,0,0,0,22840,0,22847,0,0,0,0,0,\n22856,22857,0,22858,22859,0,0,22862,0,0,22864,0,0,0,0,22865,0,0,0,0,0,0,0,0,0,0,\n0,22866,0,22867,22868,0,0,0,0,22869,0,22871,0,22872,0,22873,22881,22882,22884,\n22885,0,0,0,0,0,0,0,22886,22887,0,22894,0,22895,0,0,0,22900,0,22901,0,0,0,0,\n22904,0,0,0,0,22905,22907,0,0,0,22915,22917,0,0,22918,0,0,0,22920,0,0,0,22929,\n22930,0,0,0,22941,22942,0,0,0,22943,0,0,0,22944,0,0,0,0,0,0,0,22946,0,22947,0,0,\n22954,0,22956,0,0,22962,0,0,0,0,0,0,0,22963,0,0,22964,0,0,0,0,0,0,0,22965,0,\n22968,0,0,0,22969,0,0,0,0,0,22970,0,22971,0,0,0,0,0,22978,0,0,22979,0,22987,0,0,\n22989,0,0,0,0,0,0,22990,0,23005,0,0,0,0,0,0,0,23006,23007,23008,0,0,23023,23024,\n23029,0,0,0,0,23030,0,0,0,0,0,23032,0,0,0,0,0,23035,0,0,0,0,23038,0,0,0,23048,0,\n23049,23052,23053,23060,23061,0,23063,0,0,0,0,23067,23068,0,0,0,23069,23073,0,0,\n0,23127,0,23128,0,0,0,0,0,23129,0,23138,23141,0,23149,0,0,23150,0,0,0,23152,0,0,\n0,0,0,0,0,0,23154,0,0,0,0,23157,23159,23160,0,0,0,0,0,0,0,0,0,0,0,0,23180,0,0,0,\n0,23181,0,0,23188,0,23189,0,0,0,0,0,0,0,0,0,0,0,0,23195,0,0,23196,23199,0,0,0,0,\n0,0,0,0,0,23202,0,23204,0,23207,0,23209,23210,0,0,0,0,0,0,23227,23229,0,0,23230,\n23234,23238,0,0,0,23245,23246,23248,0,0,0,0,23249,23254,0,0,0,23265,0,0,0,0,0,0,\n0,23268,0,23276,0,0,0,0,23277,0,23297,0,23298,0,0,0,0,23299,0,23302,0,0,23303,\n23312,0,0,23314,0,23320,0,0,0,0,23324,0,23325,0,23328,0,23334,0,0,0,23337,0,0,0,\n0,23343,23344,23346,0,23348,0,0,0,0,0,0,0,0,23353,0,0,0,0,23355,0,23356,23358,0,\n0,0,23359,23360,0,23361,0,23367,0,23369,0,0,23373,0,23378,23379,0,23382,23383,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,23387,0,0,0,0,0,0,23388,23390,0,0,23393,23398,0,0,0,\n23399,0,0,0,23400,0,0,0,0,23401,0,0,0,23415,0,0,0,0,0,0,0,0,23416,0,23422,0,\n23443,23444,0,0,0,0,23448,0,23454,0,0,0,0,0,0,23456,0,0,23458,23464,0,0,0,0,0,0,\n23465,0,0,0,23470,23471,0,0,23472,0,0,0,23473,23496,0,0,0,0,0,0,0,0,23497,0,\n23499,0,0,23502,0,0,23503,0,0,23513,0,0,23515,0,0,0,23517,0,0,0,0,23518,23519,\n23521,23524,0,23525,23528,23539,0,0,0,0,0,23541,0,0,23544,0,0,23556,0,0,23557,0,\n0,0,0,0,0,0,0,0,0,0,0,0,23559,0,23560,0,0,23561,0,0,23566,0,0,0,0,0,23568,23569,\n23570,0,0,0,0,23571,0,23574,0,0,0,0,0,0,0,0,0,0,0,23575,0,23579,0,0,23581,0,0,0,\n0,0,0,23587,0,0,0,0,0,0,0,23596,23598,0,0,0,0,23602,23606,0,0,23607,0,23608,0,0,\n0,23614,23616,0,0,0,0,0,23618,0,0,23619,0,0,0,0,23621,23626,0,23627,0,0,0,0,0,0,\n0,23629,0,23630,0,0,0,0,23634,0,23636,0,0,0,0,0,0,23638,0,0,0,0,23640,23667,0,\n23669,0,0,0,23681,0,0,0,0,0,0,0,23682,0,23683,0,0,0,0,0,23684,0,0,0,23685,23689,\n0,23693,23694,23700,0,23702,0,23709,0,0,0,0,0,0,0,23712,0,0,0,0,0,23714,0,0,\n23715,0,0,0,0,23718,0,0,23720,0,0,0,0,23722,0,0,0,23726,23729,0,23741,23746,0,\n23748,0,0,0,0,23749,0,0,0,0,0,23750,0,0,0,0,23751,0,23753,0,0,0,0,23757,23765,0,\n0,0,23770,0,0,0,0,0,0,0,23771,0,23772,23781,0,0,23796,0,0,0,0,23798,0,23799,0,0,\n0,23802,0,0,23806,0,23807,0,0,23808,0,23809,0,23819,0,0,0,23821,0,23827,0,0,0,\n23829,0,0,0,0,0,0,0,23830,0,0,0,0,0,0,23832,23833,23834,23835,0,0,0,0,23837,\n23838,0,0,0,0,0,23846,0,0,0,0,0,0,23847,0,0,0,0,0,23879,23881,0,0,23882,23883,\n23895,0,23899,0,0,0,0,23901,0,0,0,0,0,0,23902,0,0,0,0,0,23903,23905,0,23906,0,\n23907,23918,23919,23920,0,23922,0,23924,0,23927,0,23934,0,23937,23941,0,23942,\n23946,0,0,0,0,0,23955,23956,23958,0,0,0,0,0,0,23959,0,23962,23965,0,23966,0,0,0,\n0,23967,23968,0,0,23973,0,0,23974,0,0,0,0,23975,0,23976,0,0,0,0,0,0,0,0,0,0,0,0,\n0,23977,0,0,0,0,0,0,0,0,23980,0,0,23984,0,23985,0,0,23987,0,0,23988,23990,23991,\n0,0,0,0,0,0,23992,0,0,0,0,0,0,0,0,23994,0,0,0,23998,0,0,0,0,0,0,0,0,0,23999,0,0,\n24003,0,24004,0,24006,0,0,0,24007,0,0,24008,0,0,0,0,0,0,0,24009,0,0,24010,0,0,\n24011,0,0,24013,24014,0,0,24015,24016,24027,0,24028,24029,0,24030,0,0,0,0,0,\n24033,24034,0,24035,0,0,24036,0,0,24044,0,24048,24049,24063,24067,0,24068,24070,\n0,0,24071,24078,24087,0,24090,0,0,0,24095,0,24098,24101,24104,24106,0,24107,0,0,\n0,24108,0,0,0,0,24110,24111,0,24113,0,0,24115,24120,0,0,0,0,0,0,24124,0,24125,0,\n24126,0,24127,0,0,0,0,0,24135,0,0,24136,0,24137,24142,0,0,0,24146,0,0,24147,\n24149,24154,0,24163,0,0,0,24165,24166,24167,0,0,0,0,0,0,0,0,0,0,24169,24170,\n24175,0,0,0,24178,0,0,24179,0,0,24181,0,24184,24197,0,24201,24204,0,0,0,0,0,0,\n24206,24212,24220,0,0,0,24224,0,0,0,0,0,0,0,0,24226,0,24234,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,24235,0,24236,0,0,0,0,0,24239,24240,24241,0,0,24248,0,0,24249,0,\n24251,0,0,0,0,0,0,24253,0,24268,0,0,0,24269,0,24271,24272,0,0,0,0,24273,0,0,\n24274,0,0,24279,0,0,0,0,0,0,0,24280,0,24293,24294,0,0,0,0,0,0,24296,0,0,24323,0,\n0,0,24329,24330,24331,24339,0,24351,0,0,24369,24370,0,0,0,24371,0,0,0,0,24372,\n24373,24374,0,0,0,0,0,24378,0,0,0,0,24379,0,24381,0,24383,24389,0,24390,0,0,\n24394,24395,24400,0,0,0,24401,24402,0,24406,0,0,0,24411,0,0,0,24415,0,24416,0,0,\n0,0,0,24417,0,24419,0,24422,0,24423,24428,0,24435,0,0,0,24439,0,0,0,24440,24442,\n24446,0,0,0,24447,24448,24449,24452,0,0,0,0,24453,24457,0,0,24458,24459,24460,0,\n24465,0,0,0,0,0,0,0,24470,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24471,0,24473,\n24474,24475,24476,0,24478,0,0,0,0,24480,0,0,0,0,0,0,0,0,0,0,24481,0,0,0,0,0,0,0,\n0,0,0,24482,24485,0,0,0,0,24486,0,0,0,24488,0,0,0,24494,0,0,0,0,24497,0,0,24498,\n0,0,0,24499,24506,0,0,0,24507,0,0,24511,0,0,24513,24514,0,0,0,0,0,24517,0,24518,\n0,24520,0,24521,24524,24525,0,0,0,0,0,24527,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24528,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24537,24539,0,24540,0,0,0,24548,0,0,0,0,0,24549,\n24550,0,0,0,24553,24554,0,24555,0,24556,0,24558,0,0,0,0,0,24560,0,0,0,24561,0,0,\n0,0,0,24562,0,0,0,0,0,0,0,0,0,0,0,0,0,24567,0,0,0,0,0,24569,0,0,0,24574,0,24575,\n0,0,0,0,0,0,0,0,0,0,0,24577,24581,0,24584,0,0,0,0,0,24585,0,0,0,0,0,24586,0,0,\n24587,0,24588,0,0,0,0,0,0,0,0,0,0,24590,24591,0,0,0,0,24592,0,0,0,0,0,0,0,24594,\n0,0,0,0,0,0,0,24596,24597,0,0,0,0,24602,24603,0,0,0,0,24604,0,0,24605,0,24610,0,\n0,24611,0,0,0,0,24612,24615,24616,24624,0,0,0,24627,0,24638,24639,0,0,0,0,24640,\n0,0,0,24655,24656,24657,0,0,0,0,0,0,0,0,24662,0,24663,24664,0,0,0,0,0,24665,0,0,\n0,0,24667,0,0,0,0,0,0,24668,24669,0,24670,24674,0,0,0,24675,0,24678,0,0,24679,0,\n0,0,24681,0,24683,0,0,0,0,24684,0,24685,0,0,24686,0,0,24688,24689,0,0,0,0,24690,\n24691,0,0,0,0,0,0,0,24697,0,24698,0,0,0,0,0,0,0,0,24709,0,0,0,0,0,24710,0,24712,\n0,0,0,0,0,0,24713,24714,0,24715,0,24716,24718,0,24719,0,0,0,0,24720,0,0,24725,0,\n0,24738,0,24749,24750,0,0,0,24752,0,0,0,24753,0,0,0,24758,0,0,0,0,0,24762,0,\n24763,0,0,0,0,0,0,0,24764,0,0,0,0,0,24765,24767,24768,0,24772,0,0,0,0,24773,0,0,\n0,0,24777,0,0,0,0,0,24785,0,24786,24788,0,0,0,24789,0,0,0,0,24794,24798,0,24799,\n24800,0,0,0,24803,0,24804,24806,0,24807,0,0,0,24810,0,0,0,0,0,0,24827,24828,0,\n24835,0,0,0,0,0,0,24836,0,0,0,0,0,24839,0,24843,24844,0,0,0,0,0,0,0,0,0,0,24847,\n0,0,24848,0,0,0,0,0,0,24849,0,24850,24851,0,0,0,24852,0,24853,0,0,0,0,0,0,0,0,0,\n24854,0,24855,0,0,24868,0,0,0,24883,0,0,0,24884,0,24895,24897,0,0,0,0,0,24899,0,\n0,0,0,0,24900,0,24913,0,0,0,0,0,0,24914,0,0,24917,24930,24931,0,0,0,24932,0,0,\n24939,0,0,24942,0,0,0,0,0,0,0,0,0,24945,24950,0,24951,0,0,24953,0,0,0,24954,0,\n24959,0,0,0,24961,0,0,24962,0,24964,24968,24970,24972,0,0,0,0,0,24976,0,0,0,\n24977,0,24982,0,0,24983,0,0,24984,0,0,0,24993,0,0,0,24994,0,0,25001,0,0,0,25003,\n0,0,25018,0,0,25023,0,0,0,25034,0,0,25035,25036,0,25037,0,0,0,0,0,0,0,25039,0,0,\n0,0,0,25040,0,0,0,0,0,0,0,25042,0,0,25043,25045,0,0,0,0,0,0,25049,0,0,25051,0,\n25052,25053,0,0,25054,0,0,0,25055,0,0,0,0,25057,25059,0,0,25060,25064,0,25065,\n25069,25070,0,0,0,0,25072,0,25073,0,25090,0,0,25092,25093,25101,0,0,0,0,0,0,\n25105,25108,0,0,25113,0,0,25115,25116,0,0,0,0,0,0,25117,0,0,0,25120,25121,0,0,0,\n0,0,0,0,25125,0,0,0,25126,0,25130,25134,0,25139,0,25143,0,0,0,25151,0,25161,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,25163,0,0,0,0,0,0,0,25174,0,25175,0,25207,0,0,\n0,25209,0,0,0,0,25213,0,25219,0,25223,0,25225,0,0,0,25227,0,0,0,25228,0,0,0,\n25229,0,0,0,0,0,0,0,25231,25233,0,0,0,0,25237,25239,0,0,0,25243,0,0,0,25252,0,\n25257,25258,0,0,0,0,25260,25265,0,25268,0,0,25273,25324,0,25325,0,25326,0,0,0,0,\n0,0,0,0,25327,0,0,0,0,0,25328,0,0,0,0,0,0,25332,0,0,0,25333,0,0,0,25336,25337,\n25338,0,0,25343,0,25350,0,0,0,0,0,0,0,25352,0,25354,0,25375,0,25379,0,0,0,0,\n25384,0,0,0,0,0,0,0,0,0,25386,0,25388,0,25390,0,0,25399,0,0,25401,0,0,0,25402,0,\n0,0,25407,0,0,0,0,0,0,0,0,0,0,0,25413,25415,0,0,25417,0,0,0,0,0,0,0,25419,0,0,0,\n25421,0,0,0,25424,0,0,0,0,25433,0,0,0,0,0,0,0,0,0,25435,0,0,0,0,0,0,25436,0,0,0,\n25437,0,0,25440,0,0,0,0,0,0,25442,0,0,25443,0,25446,0,0,25449,0,0,0,25450,0,0,0,\n0,25452,0,25453,25454,25455,0,0,0,25456,0,25457,0,0,0,25459,0,25461,0,25468,0,0,\n0,0,0,0,0,0,25469,0,0,0,0,0,25471,0,0,0,0,0,25474,0,0,0,0,0,0,0,0,25475,0,0,0,0,\n25477,0,0,0,0,25483,0,0,0,0,0,25484,0,0,0,0,0,0,0,0,0,0,0,0,25485,0,25497,0,0,\n25498,0,25504,0,25510,0,25512,0,0,25513,25514,0,0,0,0,0,0,25517,25518,25519,0,\n25520,0,0,0,0,0,0,0,25521,0,25522,25527,25534,0,25536,0,25537,0,0,25548,25550,0,\n0,25551,0,25552,0,0,0,0,0,25554,0,25555,0,25556,25557,25568,0,0,0,25570,25571,0,\n0,0,0,0,0,25574,0,0,0,0,25579,0,0,0,25581,0,0,0,25582,0,0,0,0,0,0,0,0,0,25588,0,\n0,0,0,25589,0,0,0,0,25590,0,25591,25592,25593,0,25594,0,0,0,25596,0,25597,25615,\n0,0,0,0,0,25618,0,0,0,0,25619,25623,0,0,25629,0,0,25631,0,0,0,25635,25636,0,0,\n25649,0,0,0,0,25654,0,0,0,25661,25663,0,0,25671,0,0,25678,25698,0,25699,25702,\n25703,0,0,0,0,0,0,0,0,25704,0,0,0,0,0,25706,0,0,25710,0,25711,0,25712,0,25715,\n25716,25717,0,0,25718,25728,25732,0,0,0,25734,0,0,0,0,0,0,0,0,0,25737,0,0,25739,\n0,0,0,25740,0,25741,25745,0,25746,0,25748,25772,25778,0,0,0,0,0,25780,0,0,0,0,\n25781,0,25782,25784,25785,0,0,0,25789,0,0,0,0,0,0,25797,25801,0,0,0,25808,25809,\n0,0,25811,25814,25815,0,0,25817,0,0,0,0,0,0,0,0,25820,0,0,0,0,25832,25833,0,0,0,\n25846,0,0,0,25847,25848,0,0,0,0,0,0,0,0,0,25849,25850,0,0,25851,0,0,25852,0,\n25862,0,0,0,25863,25865,0,0,0,0,0,0,0,25867,25868,0,25869,25874,0,25875,0,25876,\n25877,0,0,0,0,25878,25902,0,0,0,0,0,0,0,25903,25904,25905,0,0,0,25908,25909,0,0,\n0,0,25910,0,0,0,0,0,0,0,25912,0,25913,0,0,0,0,0,0,0,0,25914,0,0,25916,0,0,0,0,0,\n25917,25927,0,0,0,0,25928,0,0,25930,0,0,0,25933,0,0,25938,25942,0,0,0,0,0,0,0,\n25945,0,25950,0,25956,0,0,25961,25962,0,0,25963,0,25964,25965,25966,0,0,0,0,0,\n25967,0,0,0,0,25968,0,0,0,25969,25971,0,0,0,0,0,25973,25975,0,0,0,0,0,0,0,25978,\n0,25981,0,0,0,25982,0,0,0,25984,0,0,0,0,0,0,0,25993,0,0,0,0,0,0,0,0,0,0,0,0,0,\n26002,0,0,0,26005,0,0,0,26006,26007,0,0,26014,26015,26016,0,0,0,0,0,0,26017,\n26018,26020,0,26022,26023,0,0,0,26024,26028,0,26029,26033,26034,26044,0,0,0,0,0,\n26046,0,0,26047,0,0,26049,0,26050,0,26051,0,0,0,0,0,26053,0,0,0,0,26054,26059,0,\n0,0,0,0,0,26060,0,26066,0,0,0,0,0,0,0,0,0,0,0,0,26067,0,26069,0,0,26071,0,0,0,\n26073,0,26074,26077,0,0,0,0,26078,0,0,0,26079,0,26090,0,0,26094,0,0,0,0,0,0,0,0,\n26095,0,0,0,0,0,0,0,0,0,0,0,26096,26101,0,26107,26122,0,26124,0,0,26125,0,0,0,0,\n0,0,26136,26141,26155,0,0,0,0,0,0,0,0,0,26164,26166,0,0,0,26167,0,26170,26171,0,\n0,26172,0,0,26174,0,0,0,0,0,0,0,0,0,0,0,0,0,26175,0,0,0,26176,26177,0,26321,\n26322,0,26323,0,0,26324,0,0,0,0,0,0,0,26325,0,26331,0,0,0,0,0,0,26335,0,0,0,\n26350,0,0,0,26379,0,0,26382,26383,26385,0,0,26392,26406,0,0,0,0,26411,0,0,0,0,0,\n26412,0,0,26420,0,0,26423,0,26424,26426,26432,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n26435,0,26436,0,0,0,0,0,26441,0,26444,0,0,0,26446,0,0,0,0,26447,0,0,0,0,26449,0,\n26450,26452,0,26453,26454,0,0,0,26455,0,0,0,26456,0,0,26458,0,0,26460,0,26463,0,\n0,0,0,0,0,0,0,26464,26470,0,0,0,0,0,0,0,0,0,26473,0,0,26474,0,0,0,0,0,0,0,26475,\n0,0,0,0,0,0,0,26477,0,26485,0,0,26486,0,26487,0,0,26488,26493,26494,0,0,26495,0,\n26497,26504,26506,0,0,0,0,0,26507,0,0,0,0,0,26509,0,0,26510,0,0,0,0,0,0,0,0,0,0,\n0,0,0,26512,0,26513,26515,0,0,0,26518,0,0,0,26519,0,26524,26526,0,0,0,26527,0,\n26532,0,26533,26537,26558,0,0,0,26559,0,0,0,26571,0,0,26573,0,26588,0,26593,0,0,\n0,0,0,0,26603,0,26604,0,0,0,0,0,0,0,0,0,0,26606,0,0,0,0,0,0,0,26607,26609,26611,\n26614,0,0,0,26616,26620,0,26621,0,0,0,0,0,26627,0,26629,0,0,26630,0,0,26632,\n26643,0,0,0,26644,0,0,0,0,0,0,0,0,0,26646,26647,0,0,0,26650,0,0,26656,0,0,0,0,\n26663,26670,26671,0,0,0,26685,26686,26687,0,26689,0,0,0,0,26744,0,26745,0,26747,\n26748,0,26749,26750,26751,0,0,0,0,26752,26755,0,0,0,26756,26769,0,0,0,26774,0,0,\n0,0,0,26775,0,26777,26778,0,26786,0,0,0,26787,0,0,0,0,0,0,0,0,0,0,0,0,0,26788,0,\n0,26789,0,0,0,0,0,26791,0,26792,26793,0,0,0,26794,0,26797,26798,0,0,0,26800,0,0,\n26803,0,26804,0,0,0,0,0,0,0,0,0,26805,0,0,26808,0,0,26809,0,0,0,0,0,0,0,26812,0,\n26825,0,0,0,0,0,0,0,26826,0,0,26827,26829,26834,0,0,0,0,26835,0,0,26849,0,26851,\n0,0,0,0,0,0,0,0,0,26852,0,26853,26857,0,26858,0,26859,0,0,0,0,0,0,0,26876,0,\n26878,26882,26883,0,0,0,0,26890,26894,0,0,0,0,26895,26896,0,0,0,0,0,26900,0,0,0,\n0,0,0,0,26911,26913,26914,26915,26916,26919,0,0,0,26921,26922,0,0,26925,0,0,0,\n26928,0,0,26929,26930,0,0,0,26931,0,26932,0,0,0,0,0,26933,0,0,0,0,0,0,26937,0,0,\n26943,0,0,26944,0,0,0,26946,0,0,0,0,0,0,0,26956,0,26958,0,0,26963,0,0,0,0,0,0,0,\n26965,0,26969,26970,26972,0,0,0,0,0,26973,0,26974,0,26978,0,26980,0,0,0,0,0,0,\n26982,0,26986,26987,0,26990,0,0,0,0,27003,27006,0,0,27007,27010,27012,27013,0,0,\n0,0,0,0,0,0,27014,27015,27018,0,27019,0,0,0,0,0,27025,0,0,0,27026,0,0,0,0,27029,\n27030,27031,27034,0,0,27036,27037,0,0,0,27038,27042,0,0,0,27044,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,27045,0,0,0,0,0,0,0,27046,0,0,0,0,0,0,0,27047,27049,0,27050,0,0,0,\n27051,27052,0,27055,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,27056,27058,27059,0,\n27061,0,27064,0,0,0,0,0,27069,0,0,27070,0,0,0,0,0,0,0,27072,0,0,0,0,0,0,0,0,\n27076,0,0,0,0,0,27078,0,27079,0,0,0,27081,0,0,0,0,0,0,27082,0,27083,27086,0,0,0,\n0,27087,0,0,0,0,0,27088,27090,0,27094,0,0,27095,0,27099,27102,0,0,0,27103,0,0,0,\n0,27105,0,0,0,27106,0,0,0,0,0,0,27107,0,0,0,0,27108,27117,0,0,0,0,27118,0,0,\n27124,0,27126,0,0,27130,27131,0,0,0,0,0,0,27147,0,0,0,0,27148,27149,0,0,0,0,\n27150,27151,0,27152,0,27159,0,0,0,27164,0,0,0,0,0,0,0,27175,0,27189,0,0,27191,0,\n27193,0,27195,0,27198,0,0,0,0,0,27200,0,0,0,0,27202,0,0,0,0,27203,0,0,27204,0,0,\n27206,0,27207,0,0,0,0,27209,0,0,0,27213,0,0,27216,27219,27220,27222,27223,0,\n27224,0,27225,27226,0,0,27233,0,0,0,0,27235,0,27237,0,27238,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,27239,0,27242,27243,0,27250,0,0,0,27251,0,27253,0,0,0,0,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,27254,27255,27258,0,0,0,27259,0,0,0,0,0,0,27267,0,27276,27278,\n0,0,0,0,0,0,0,0,0,27296,27297,27301,0,0,0,0,0,0,27302,0,0,0,0,0,0,27312,27313,0,\n0,0,0,0,27318,0,27320,0,27329,0,27330,27331,0,27332,0,0,0,0,27340,0,0,0,27348,0,\n0,0,0,0,0,27350,0,27351,0,0,0,0,27355,0,0,27358,27359,27361,0,0,0,27365,0,27367,\n0,27376,27378,0,0,27379,0,0,0,0,0,0,27396,0,27397,27404,0,0,0,0,0,27408,0,0,0,0,\n27453,0,0,0,27456,0,0,0,27458,0,0,0,0,0,0,0,27459,0,0,0,27460,0,0,27461,0,27465,\n27467,0,0,27469,0,27470,0,27471,0,27477,27482,0,0,0,0,0,0,27484,0,0,0,0,0,0,\n27485,0,0,0,0,0,27493,0,27494,27502,0,0,0,0,0,0,0,0,0,0,0,0,27511,27532,0,0,0,\n27533,27545,0,0,0,27546,0,0,0,0,0,0,0,0,0,0,27547,0,0,27549,27550,0,27551,0,0,0,\n0,0,0,0,27555,0,0,27571,0,27573,27574,27575,27577,0,27578,0,0,27579,27585,0,0,0,\n0,0,27586,0,0,27588,27589,0,0,0,0,27596,0,0,27600,0,0,0,0,0,0,0,0,0,0,0,27608,0,\n0,0,0,0,0,0,0,0,0,0,27610,0,0,0,27618,0,0,27620,0,0,0,27631,0,0,27632,27634,0,\n27636,27638,0,0,0,27643,0,27644,27649,0,0,0,0,0,0,0,0,0,0,0,0,0,27651,27660,0,\n27661,0,0,0,0,0,0,0,27662,0,0,27664,0,27665,0,0,0,27669,0,27671,0,0,0,27673,\n27674,0,0,0,27682,0,0,0,27711,0,27712,27713,27719,27720,0,0,27728,0,27729,0,0,0,\n0,0,0,0,0,0,27731,0,0,27732,0,27733,0,27738,0,0,0,27742,0,0,0,27743,27744,0,0,0,\n0,0,0,27745,27746,0,0,0,27747,27748,27751,27752,0,0,0,27768,27770,0,0,0,27774,\n27775,0,27776,27777,0,0,27781,0,27784,0,27786,0,0,27791,0,27792,27793,27804,0,\n27812,27813,0,0,0,0,0,0,0,0,27814,0,27825,0,27827,0,0,0,0,27828,27861,27862,0,0,\n0,27864,0,0,0,27865,27884,0,27889,0,0,0,0,0,27890,0,27891,0,0,0,27892,0,0,0,0,0,\n27897,27898,0,0,27899,0,0,0,27901,27905,0,0,27920,0,0,27921,0,27922,0,0,0,27931,\n27934,0,0,0,0,0,0,0,0,0,0,27941,0,27942,0,27945,0,27947,27954,0,0,0,0,27960,\n27963,0,0,0,0,0,0,0,0,27964,27965,0,0,0,27967,0,27969,27975,0,27976,27977,0,\n27981,0,27983,28051,28052,0,0,0,0,0,28056,0,0,0,0,0,0,28058,28059,0,0,28061,0,0,\n0,0,0,0,0,28063,0,0,0,0,0,0,28066,0,0,0,0,0,0,28069,28070,28072,0,28073,0,0,\n28074,0,0,0,0,28075,0,0,0,0,0,0,0,28078,0,0,0,0,28085,0,0,0,0,28086,0,0,0,0,0,0,\n28088,0,0,0,0,0,0,0,0,28090,0,28097,28114,28115,0,0,0,0,0,0,0,28116,0,0,0,0,0,\n28118,0,28129,0,28131,0,0,28135,0,0,0,28140,28141,0,0,0,28146,0,0,0,0,28152,0,0,\n0,0,28155,28157,28161,0,0,0,0,28166,0,28167,0,0,0,0,0,0,0,0,0,0,0,28172,0,0,0,0,\n0,0,28173,0,0,28175,0,0,0,0,0,0,0,0,0,28178,28188,0,28190,0,0,0,0,0,28191,0,\n28193,28206,0,0,28207,28209,0,28211,0,28213,0,0,0,28215,28216,28217,0,28222,0,\n28223,28225,0,0,0,28226,0,28227,28229,28232,0,0,0,0,0,0,0,0,0,28235,0,28241,0,0,\n28242,0,0,0,0,28243,0,0,0,28245,0,0,0,28248,28250,0,28251,28252,0,0,0,0,0,0,\n28253,0,0,28254,28255,0,0,28256,0,0,28258,0,0,0,0,0,28259,0,0,28260,0,0,28261,0,\n0,0,0,28262,28263,0,0,28264,0,0,0,28266,0,28268,28269,0,28270,28272,28274,0,\n28277,28278,0,0,0,28279,0,28280,28281,28283,0,28292,0,28294,0,28297,0,0,0,0,\n28299,0,0,0,0,0,28300,0,0,0,0,0,0,0,28301,0,0,0,0,0,0,0,0,0,0,0,0,0,28302,28303,\n0,0,0,0,28304,0,0,28305,0,28312,0,28313,28314,0,0,0,0,0,0,28315,0,0,0,28320,\n28321,0,0,28328,0,0,0,28329,28338,0,28339,0,0,28344,0,0,0,0,0,0,0,0,28347,0,0,0,\n0,0,0,0,0,28348,0,0,0,0,0,28411,0,28412,28413,0,28416,0,0,0,28420,0,0,0,0,0,\n28421,0,0,0,0,28423,0,0,0,28424,0,0,28428,0,0,0,0,0,28429,0,0,0,28431,28434,0,\n28458,0,0,0,0,0,0,0,0,0,0,0,28464,0,0,0,0,28465,0,28467,0,0,0,0,0,0,28471,0,0,0,\n0,28474,0,28480,0,28481,0,0,28485,0,0,0,0,28486,28488,0,0,28489,0,0,0,0,28492,0,\n0,0,28495,0,28497,0,28499,0,0,0,0,28500,0,0,28502,28503,0,0,0,28508,0,0,0,28510,\n0,0,28512,28513,28514,28521,0,28526,0,28527,28528,0,0,0,0,28529,0,0,28532,0,0,\n28537,28538,0,0,0,28539,0,28548,0,28553,28554,0,0,0,0,0,0,0,0,0,0,0,0,28560,\n28563,0,0,28564,0,0,0,0,28565,0,0,0,0,0,0,0,28566,28568,0,0,0,0,0,0,28569,0,0,0,\n28570,0,28572,28573,0,0,0,0,28575,0,0,0,0,28576,28581,28588,0,0,28589,0,0,0,\n28590,28595,0,28598,0,0,28601,0,0,28605,0,0,0,0,28614,28615,28619,0,0,0,0,0,0,\n28620,0,28626,0,0,28628,0,28631,0,28632,0,0,0,0,0,0,28635,0,0,0,28637,28638,0,0,\n0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,28639,0,28643,0,0,28652,0,0,0,28662,0,\n28670,28671,0,0,0,0,0,0,0,0,0,28672,28673,28675,28676,0,0,0,0,0,0,0,28691,0,0,0,\n28695,0,0,0,28696,0,28697,28698,0,28705,0,28707,28708,28710,0,0,0,0,0,0,0,28711,\n28728,0,0,0,28736,0,0,0,28737,0,0,0,0,0,0,0,0,0,28738,0,28739,0,28741,0,0,28742,\n0,0,0,0,0,0,0,0,0,0,0,28745,0,0,0,0,0,0,28749,28750,28752,28754,28756,0,28757,0,\n0,0,0,28759,28760,0,0,0,0,0,0,28762,0,0,0,28764,0,0,0,0,0,0,28766,0,28767,28768,\n0,0,0,0,28769,28770,0,0,0,0,0,0,0,0,0,0,0,0,0,28771,0,0,0,0,0,0,0,0,0,0,0,0,0,0,\n0,28772,0,28773,0,28782,0,0,0,0,0,0,28784,0,28785,0,28786,0,0,0,28787,0,0,0,\n28797,0,0,0,0,0,0,28799,0,0,28801,0,0,0,0,28802,0,28805,0,0,28806,0,0,28807,0,0,\n0,0,0,0,0,28808,0,0,0,0,0,28810,28812,0,0,28816,28819,0,0,28821,0,28826,0,0,0,\n28842,28852,0,0,28853,0,28854,28855,0,0,0,28857,0,0,0,28858,0,28867,28868,28869,\n0,0,0,28874,28880,28882,28890,28892,0,0,0,0,0,0,0,28895,0,0,0,28898,28899,0,0,0,\n28900,0,0,28904,0,28906,0,0,0,0,28907,0,0,0,0,0,0,28908,0,0,0,28910,0,28914,0,0,\n0,0,0,0,0,28915,28916,28919,0,0,28920,0,28921,0,0,0,0,0,0,0,0,28924,0,0,0,0,\n28926,28929,0,0,0,28930,0,28936,0,28939,0,0,0,0,28942,0,0,0,0,0,0,28956,0,0,0,\n28966,0,0,0,0,28967,0,0,0,0,0,0,0,0,0,28968,0,28971,0,28975,28976,0,28982,28983,\n0,0,28984,28989,28996,28997,28998,0,0,0,0,0,0,28999,0,0,0,0,0,29000,0,29001,0,0,\n0,29009,0,0,29011,0,0,29021,0,0,0,0,29024,0,29025,0,0,0,0,0,29026,0,0,0,29036,0,\n0,0,29037,0,0,0,0,29038,0,29045,0,29047,0,0,0,0,0,0,0,0,0,29051,0,0,0,29054,\n29056,29062,0,29070,29082,0,0,0,29083,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29084,0,0,\n0,0,29085,29088,0,0,0,0,0,0,0,29090,29097,0,0,0,29103,0,0,0,0,0,0,0,0,29105,0,0,\n0,0,0,29107,0,29109,0,0,0,29115,0,0,29120,0,0,29138,29140,0,0,0,0,0,0,0,0,0,\n29152,0,29160,29174,0,29176,0,0,29180,0,29181,0,0,0,0,0,0,0,0,29228,0,0,29229,0,\n0,29230,0,0,0,0,0,0,0,0,0,0,29234,0,0,0,29241,0,29245,0,29248,0,29250,29256,\n29280,0,29282,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29285,0,0,29286,29291,29292,0,0,0,0,\n29294,0,29295,0,0,0,0,0,29296,29297,29298,29300,0,29302,0,0,29304,29307,0,29312,\n0,0,0,29322,0,0,29323,0,0,29324,29326,29328,0,29335,0,0,0,0,0,0,0,29338,29339,0,\n0,0,0,0,29341,29343,0,0,0,0,29344,0,0,0,0,0,29345,0,0,0,0,29346,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,29347,29348,29349,0,0,29354,0,0,29355,0,0,0,0,0,0,0,0,29357,0,0,\n0,0,29364,0,29365,0,0,0,0,0,0,0,29366,0,0,29368,0,0,0,0,0,0,0,0,29378,0,29381,0,\n0,0,0,0,0,0,0,29386,0,0,0,0,0,0,29389,0,0,0,29390,0,0,29391,29397,0,29398,29412,\n29414,29418,29419,0,0,0,0,0,0,0,29420,0,0,0,0,0,0,0,29423,0,0,0,29435,0,0,0,\n29437,0,0,29439,0,29441,0,0,0,0,29443,0,29446,29450,29452,0,0,0,0,0,29456,0,0,0,\n0,0,29461,0,0,0,29464,0,0,0,0,0,0,0,0,29468,0,29473,0,0,0,29486,0,0,0,29490,0,0,\n0,29491,29492,0,0,29497,0,0,0,29498,0,29499,0,29502,29505,0,29509,0,0,0,29510,0,\n0,0,29512,0,0,0,29516,0,0,0,0,0,0,0,0,29518,0,29519,0,0,0,0,0,29520,29521,29529,\n0,0,0,0,0,0,0,0,29530,0,0,29531,29538,0,29540,0,0,0,29542,0,29543,29544,29547,0,\n0,29548,0,0,0,29549,0,0,0,29550,0,0,29552,0,0,0,0,29558,29561,0,29562,29564,0,0,\n29565,0,0,29566,0,0,0,0,0,0,0,0,0,0,29578,29584,29586,29591,0,0,0,0,29593,29594,\n0,0,29597,0,0,29613,0,29614,0,29615,0,0,0,0,29616,29617,0,0,29625,0,0,0,29632,0,\n0,0,0,0,0,0,29633,0,0,0,0,0,29634,29635,29637,0,29638,0,29641,29643,0,0,0,0,0,0,\n29644,0,29645,0,29649,0,0,0,29650,0,29653,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29656,\n29659,0,0,29660,0,0,0,29661,0,0,0,0,0,29664,0,0,0,29671,29673,0,0,0,0,0,0,0,\n29675,0,29677,29679,0,0,29684,0,0,0,0,0,29685,0,0,0,29687,0,0,0,29688,0,29689,\n29690,29700,0,29701,0,0,0,29702,0,29706,0,0,0,0,0,0,0,29720,0,29721,0,29727,0,\n29733,29734,0,29750,29761,0,29763,0,0,0,0,0,29764,0,0,29765,0,0,0,29771,0,0,0,0,\n0,0,0,0,0,0,0,0,29772,0,0,0,29773,29774,29775,0,0,0,0,0,0,0,0,0,0,0,29822,0,0,0,\n29824,0,29825,0,0,0,0,0,29827,0,0,0,0,0,0,0,0,29829,0,29832,29834,0,0,29835,0,0,\n29837,29838,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,29843,0,0,0,0,29844,29845,0,0,0,\n0,0,0,0,0,0,29849,0,0,29869,29872,29890,29905,0,0,0,0,0,29907,29921,0,29922,0,0,\n29923,29926,29944,29946,0,0,0,0,0,0,0,29947,29948,0,0,0,29951,0,0,0,0,0,29953,0,\n0,29956,0,29957,0,0,29962,0,0,0,0,29971,0,0,0,29972,0,0,0,0,0,29978,0,29979,\n29992,30007,30008,30010,0,0,0,30013,0,0,0,0,30014,30016,0,0,0,0,0,0,0,0,0,0,0,\n30017,0,0,0,0,0,30023,30031,0,0,30033,0,0,0,0,0,0,0,0,0,0,30034,0,30038,0,30039,\n0,30040,0,0,0,0,0,0,30067,30068,0,0,0,30069,0,30072,0,0,0,30073,0,0,0,0,30075,0,\n0,0,0,0,0,30079,0,0,30080,0,0,0,0,0,30082,0,0,0,0,0,0,0,0,0,0,0,30084,30090,0,0,\n30091,0,0,0,0,30098,30118,0,30119,0,30121,30130,0,0,0,0,0,0,0,0,0,0,0,0,0,30131,\n30132,30133,0,0,0,0,0,0,30135,0,0,0,0,0,0,0,0,0,0,0,30136,0,0,30137,30138,0,0,0,\n30139,30146,0,0,0,0,0,30147,0,0,30148,30151,0,0,0,30168,0,30172,30173,0,0,0,0,0,\n0,0,0,30180,30181,0,30192,0,0,0,0,0,0,0,30194,30196,0,0,30199,0,0,30202,0,0,0,0,\n30203,0,0,0,0,0,0,0,0,0,0,30213,0,0,0,30216,0,0,30217,0,0,0,30218,0,0,0,0,30219,\n0,30220,0,30222,30227,0,0,0,0,0,30231,0,0,30233,30235,0,0,0,0,30238,0,30240,\n30243,30245,0,30250,30252,0,0,0,30269,0,0,30271,30272,0,0,0,30278,30280,0,0,\n30282,0,30284,0,30294,0,0,0,0,30295,30296,0,0,0,0,0,30298,30299,30302,30304,\n30306,0,0,0,0,0,0,30316,30317,0,0,0,30318,0,0,0,30319,0,30320,30322,30326,0,0,0,\n0,0,30327,0,30332,30348,30349,0,0,30356,0,0,0,0,0,0,0,0,30357,0,30358,0,30359,\n30360,0,0,30365,30366,30378,0,0,0,0,30379,0,0,30381,0,30385,0,30388,30397,0,0,0,\n30401,0,0,0,0,30403,0,0,0,0,0,30404,0,0,30405,0,30406,30408,0,30409,0,30410,0,0,\n0,30417,0,0,30418,30419,0,30420,0,30424,0,0,0,30427,30430,30432,0,0,0,0,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,0,30433,0,0,0,0,0,0,0,30436,0,30437,30438,0,30441,30442,0,0,\n0,30445,0,0,0,0,30452,30456,30457,0,0,0,30458,0,30464,0,0,0,0,0,0,30467,0,30469,\n0,0,0,0,0,30477,0,0,30484,0,0,0,0,0,30485,0,0,0,0,0,30486,30487,30497,30498,0,0,\n0,0,0,0,0,0,0,0,30505,0,30508,0,0,0,30509,30510,0,30514,30516,0,0,0,0,0,0,0,0,0,\n0,0,30523,0,30524,0,30525,0,0,0,0,30537,0,0,30538,0,0,0,0,0,30553,0,0,30555,\n30556,30558,30559,30560,0,0,30561,0,30562,0,0,0,0,0,0,0,0,30563,30570,30571,0,\n30586,30587,0,0,30590,0,0,30594,0,0,0,0,30611,30612,30623,30634,0,0,30636,30640,\n30655,30656,0,30657,0,0,30658,30669,0,30670,0,30676,30678,0,0,0,0,0,0,0,30679,0,\n0,0,0,0,0,0,0,0,0,0,30695,0,0,30698,0,0,0,0,30700,0,0,0,0,30701,0,30702,30703,0,\n0,0,0,30707,0,0,0,30709,0,0,30710,30719,30729,0,0,0,0,0,0,0,0,0,30731,0,0,30733,\n0,0,0,30734,0,0,0,0,0,30736,30737,0,0,0,30740,0,0,0,30743,0,30746,0,30747,30748,\n0,0,30751,30752,30753,0,0,0,30754,0,0,30760,0,0,0,0,0,0,0,30763,0,30764,0,0,\n30766,0,30769,30770,30771,30774,30777,0,0,30779,30780,30781,0,0,0,0,30790,0,0,0,\n30792,0,0,0,0,30810,0,0,0,0,0,0,0,30812,30819,0,0,30823,30824,0,30825,0,30827,0,\n0,0,0,0,0,30828,0,0,30830,0,0,0,30834,0,30835,0,30837,30838,0,30845,0,0,0,0,0,\n30846,30847,0,0,30849,0,30851,0,0,0,0,0,30852,30858,0,0,30859,0,30865,0,0,30866,\n0,0,30868,0,0,30869,0,0,0,30881,30883,0,0,0,0,0,30889,0,30891,0,0,0,0,30894,0,\n30895,0,30897,0,30898,0,0,0,30904,30906,0,30909,0,0,0,0,0,0,30910,0,0,0,30915,\n30933,30942,0,0,0,0,30943,0,0,30945,0,0,0,0,0,0,30946,0,0,30947,0,0,30955,30956,\n0,0,30960,0,0,30961,30962,30966,0,0,30969,30974,0,0,0,30976,0,0,30977,0,30978,\n30982,0,0,0,0,0,0,0,30994,30995,30998,0,31000,0,0,31001,0,0,31003,31005,0,0,\n31006,31011,0,0,31014,0,31016,0,0,0,0,31018,0,0,31020,31023,31024,31025,0,0,0,0,\n0,0,0,0,0,0,0,0,0,0,31027,31028,31029,0,0,0,0,0,0,31032,0,0,0,0,0,0,0,0,0,0,0,\n31036,31037,31038,0,0,0,31041,31043,31045,0,31047,0,0,0,31048,0,31049,0,0,0,\n31053,31054,31055,0,0,31063,0,0,0,0,0,31066,0,31068,31071,0,0,0,31072,31073,0,0,\n0,0,31075,0,0,31076,0,0,0,31077,31079,0,31080,0,0,0,0,0,0,0,0,0,0,31087,0,31142,\n0,31144,0,0,31145,31146,31147,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31149,0,31151,31152,0,\n0,0,0,0,0,0,31162,31171,31174,31175,0,0,0,31176,0,0,0,0,0,0,0,31179,0,0,0,31186,\n0,0,0,31192,31195,0,0,31196,0,0,0,0,0,0,0,0,31198,0,0,0,0,0,31199,0,0,0,31205,0,\n0,0,0,31211,31215,0,0,0,0,31231,0,31232,0,0,0,0,0,0,0,0,0,0,31233,31236,31253,0,\n31254,0,0,0,0,0,0,31255,0,0,31257,0,0,0,0,0,0,0,0,0,31258,31259,0,0,31260,0,\n31261,0,0,0,0,0,31262,31263,0,0,31264,0,31266,0,31267,0,0,0,0,0,31281,0,31282,0,\n31284,0,0,31285,31287,31288,0,0,31290,0,0,0,31292,31295,0,31299,0,31300,0,0,0,0,\n0,31302,0,0,0,0,31303,0,0,0,0,0,0,31304,0,0,0,0,0,31305,31308,31309,31315,0,\n31317,0,0,0,0,0,31323,0,31324,0,0,0,0,0,31325,31327,0,0,31331,0,0,0,0,0,31333,0,\n0,0,0,0,31336,0,0,31337,0,0,0,0,0,0,31338,0,0,0,0,0,0,0,0,0,0,0,0,31339,0,0,0,0,\n0,0,0,31342,0,0,0,0,31345,0,0,0,0,0,0,0,0,31347,0,0,0,0,0,0,31348,0,0,31350,\n31351,0,31352,0,0,31354,0,0,0,0,31355,0,0,31356,0,0,0,0,0,0,0,0,0,0,31363,0,\n31372,0,0,31373,0,0,0,0,0,0,0,0,0,31376,0,31388,0,31389,0,31392,0,31401,0,31405,\n31407,31408,0,31409,0,0,0,0,0,0,31413,31415,0,0,0,31416,31418,0,0,0,0,0,0,31422,\n31423,0,0,31424,0,31425,31432,0,0,0,0,0,0,0,0,0,31433,0,0,0,0,0,0,0,0,31434,0,0,\n0,0,0,0,31435,0,0,0,0,31438,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,31442,0,31444,0,\n31448,0,0,31451,0,0,0,0,31452,0,31461,31465,0,0,31466,0,0,31467,0,0,31468,0,0,0,\n31469,31473,0,31476,0,0,0,0,31489,31490,0,0,0,0,0,0,0,31492,31493,31494,0,0,0,0,\n31501,31504,31505,0,0,0,0,0,0,0,0,0,31509,0,0,0,0,31510,0,0,31511,0,0,31513,0,0,\n0,0,0,0,0,0,0,31514,0,31522,31536,31539,31540,0,31541,0,0,0,0,0,0,31546,31553,\n31559,0,0,0,31560,31561,31562,0,0,31564,31567,0,31569,0,0,0,31570,0,0,0,0,31571,\n0,0,0,0,0,0,31572,31574,31580,31581,0,0,31582,31584,31585,31586,31595,0,31596,0,\n0,0,0,31597,0,31599,0,31600,31601,0,0,31603,31604,0,0,31608,31610,0,0,0,31611,0,\n31615,0,0,0,0,31616,0,0,0,0,0,0,31617,0,0,0,0,0,31618,0,0,0,0,0,0,31621,0,0,0,0,\n0,0,0,0,0,31622,31625,0,0,0,0,31627,0,31641,0,0,31642,0,0,31643,0,0,0,0,0,0,0,0,\n0,31644,0,31646,0,0,0,0,31648,0,0,0,31652,0,0,0,31657,0,0,31676,0,0,0,0,0,0,0,\n31689,31691,31692,0,31694,0,0,0,31696,0,31702,0,31703,0};\n\nstatic const DictWord kStaticDictionaryWords[31705] = {\n{0,0,0},{8,0,1002},{136,0,1015},{4,0,683},{4,10,325},{138,10,125},{7,11,572},{9,\n11,592},{11,11,680},{11,11,842},{11,11,924},{12,11,356},{12,11,550},{13,11,317},\n{13,11,370},{13,11,469},{13,11,471},{14,11,397},{18,11,69},{146,11,145},{134,0,\n1265},{136,11,534},{134,0,1431},{11,0,138},{140,0,40},{4,0,155},{7,0,1689},{4,10\n,718},{135,10,1216},{4,0,245},{5,0,151},{5,0,741},{6,0,1147},{7,0,498},{7,0,870}\n,{7,0,1542},{12,0,213},{14,0,36},{14,0,391},{17,0,111},{18,0,6},{18,0,46},{18,0,\n151},{19,0,36},{20,0,32},{20,0,56},{20,0,69},{20,0,102},{21,0,4},{22,0,8},{22,0,\n10},{22,0,14},{150,0,31},{4,0,624},{135,0,1752},{5,10,124},{5,10,144},{6,10,548}\n,{7,10,15},{7,10,153},{137,10,629},{6,0,503},{9,0,586},{13,0,468},{14,0,66},{16,\n0,58},{7,10,1531},{8,10,416},{9,10,275},{10,10,100},{11,10,658},{11,10,979},{12,\n10,86},{14,10,207},{15,10,20},{143,10,25},{5,0,603},{7,0,1212},{9,0,565},{14,0,\n301},{5,10,915},{6,10,1783},{7,10,211},{7,10,1353},{9,10,83},{10,10,376},{10,10,\n431},{11,10,543},{12,10,664},{13,10,280},{13,10,428},{14,10,128},{17,10,52},{145\n,10,81},{4,0,492},{133,0,451},{135,0,835},{141,0,70},{132,0,539},{7,11,748},{139\n,11,700},{7,11,1517},{11,11,597},{14,11,76},{14,11,335},{148,11,33},{6,0,113},{\n135,0,436},{4,10,338},{133,10,400},{136,0,718},{133,11,127},{133,11,418},{6,0,\n1505},{7,0,520},{6,11,198},{11,10,892},{140,11,83},{4,10,221},{5,10,659},{5,10,\n989},{7,10,697},{7,10,1211},{138,10,284},{135,0,1070},{5,11,276},{6,11,55},{135,\n11,1369},{134,0,1515},{6,11,1752},{136,11,726},{138,10,507},{15,0,78},{4,10,188}\n,{135,10,805},{5,10,884},{139,10,991},{133,11,764},{134,10,1653},{6,11,309},{7,\n11,331},{138,11,550},{135,11,1861},{132,11,348},{135,11,986},{135,11,1573},{12,0\n,610},{13,0,431},{144,0,59},{9,11,799},{140,10,166},{134,0,1530},{132,0,750},{\n132,0,307},{133,0,964},{6,11,194},{7,11,133},{10,11,493},{10,11,570},{139,11,664\n},{5,11,24},{5,11,569},{6,11,3},{6,11,119},{6,11,143},{6,11,440},{7,11,295},{7,\n11,599},{7,11,1686},{7,11,1854},{8,11,424},{9,11,43},{9,11,584},{9,11,760},{10,\n11,148},{10,11,328},{11,11,159},{11,11,253},{11,11,506},{12,11,487},{12,11,531},\n{144,11,33},{136,10,760},{5,11,14},{5,11,892},{6,11,283},{7,11,234},{136,11,537}\n,{135,11,1251},{4,11,126},{8,11,635},{147,11,34},{4,11,316},{135,11,1561},{6,0,\n999},{6,0,1310},{137,11,861},{4,11,64},{5,11,352},{5,11,720},{6,11,368},{139,11,\n359},{4,0,75},{5,0,180},{6,0,500},{7,0,58},{7,0,710},{10,0,645},{136,10,770},{\n133,0,649},{6,0,276},{7,0,282},{7,0,879},{7,0,924},{8,0,459},{9,0,599},{9,0,754}\n,{11,0,574},{12,0,128},{12,0,494},{13,0,52},{13,0,301},{15,0,30},{143,0,132},{\n132,0,200},{4,10,89},{5,10,489},{6,10,315},{7,10,553},{7,10,1745},{138,10,243},{\n135,11,1050},{7,0,1621},{6,10,1658},{9,10,3},{10,10,154},{11,10,641},{13,10,85},\n{13,10,201},{141,10,346},{6,11,175},{137,11,289},{5,11,432},{133,11,913},{6,0,\n225},{137,0,211},{7,0,718},{8,0,687},{139,0,374},{4,10,166},{133,10,505},{9,0,\n110},{134,10,1670},{8,0,58},{9,0,724},{11,0,809},{13,0,113},{145,0,72},{6,0,345}\n,{7,0,1247},{144,11,82},{5,11,931},{134,11,1698},{8,0,767},{8,0,803},{9,0,301},{\n137,0,903},{139,0,203},{134,0,1154},{7,0,1949},{136,0,674},{134,0,259},{135,0,\n1275},{5,11,774},{6,11,1637},{6,11,1686},{134,11,1751},{134,0,1231},{7,10,445},{\n8,10,307},{8,10,704},{10,10,41},{10,10,439},{11,10,237},{11,10,622},{140,10,201}\n,{136,0,254},{6,11,260},{135,11,1484},{139,0,277},{135,10,1977},{4,10,189},{5,10\n,713},{6,11,573},{136,10,57},{138,10,371},{132,10,552},{134,11,344},{133,0,248},\n{9,0,800},{10,0,693},{11,0,482},{11,0,734},{11,0,789},{134,11,240},{4,0,116},{5,\n0,95},{5,0,445},{7,0,1688},{8,0,29},{9,0,272},{11,0,509},{11,0,915},{4,11,292},{\n4,11,736},{5,11,871},{6,11,171},{6,11,1689},{7,11,1324},{7,11,1944},{9,11,415},{\n9,11,580},{14,11,230},{146,11,68},{7,0,490},{13,0,100},{143,0,75},{135,0,1641},{\n133,0,543},{7,11,209},{8,11,661},{10,11,42},{11,11,58},{12,11,58},{12,11,118},{\n141,11,32},{5,0,181},{8,0,41},{6,11,63},{135,11,920},{133,0,657},{133,11,793},{\n138,0,709},{7,0,25},{8,0,202},{138,0,536},{5,11,665},{135,10,1788},{145,10,49},{\n9,0,423},{140,0,89},{5,11,67},{6,11,62},{6,11,374},{135,11,1391},{8,0,113},{9,0,\n877},{10,0,554},{11,0,83},{12,0,136},{19,0,109},{9,11,790},{140,11,47},{138,10,\n661},{4,0,963},{10,0,927},{14,0,442},{135,10,1945},{133,0,976},{132,0,206},{4,11\n,391},{135,11,1169},{134,0,2002},{6,0,696},{134,0,1008},{134,0,1170},{132,11,271\n},{7,0,13},{8,0,226},{10,0,537},{11,0,570},{11,0,605},{11,0,799},{11,0,804},{12,\n0,85},{12,0,516},{12,0,623},{13,0,112},{13,0,361},{14,0,77},{14,0,78},{17,0,28},\n{19,0,110},{140,11,314},{132,0,769},{134,0,1544},{4,0,551},{137,0,678},{5,10,84}\n,{134,10,163},{9,0,57},{9,0,459},{10,0,425},{11,0,119},{12,0,184},{12,0,371},{13\n,0,358},{145,0,51},{5,0,188},{5,0,814},{8,0,10},{9,0,421},{9,0,729},{10,0,609},{\n11,0,689},{4,11,253},{5,10,410},{5,11,544},{7,11,300},{137,11,340},{134,0,624},{\n138,11,321},{135,0,1941},{18,0,130},{5,10,322},{8,10,186},{9,10,262},{10,10,187}\n,{142,10,208},{5,11,53},{5,11,541},{6,11,94},{6,11,499},{7,11,230},{139,11,321},\n{133,10,227},{4,0,378},{4,11,920},{5,11,25},{5,11,790},{6,11,457},{135,11,853},{\n137,0,269},{132,0,528},{134,0,1146},{7,10,1395},{8,10,486},{9,10,236},{9,10,878}\n,{10,10,218},{11,10,95},{19,10,17},{147,10,31},{7,10,2043},{8,10,672},{141,10,\n448},{134,0,1105},{134,0,1616},{134,11,1765},{140,11,163},{5,10,412},{133,11,822\n},{132,11,634},{6,0,656},{134,11,1730},{134,0,1940},{5,0,104},{6,0,173},{135,0,\n1631},{136,10,562},{6,11,36},{7,11,658},{8,11,454},{147,11,86},{5,0,457},{134,10\n,1771},{7,0,810},{8,0,138},{8,0,342},{9,0,84},{10,0,193},{11,0,883},{140,0,359},\n{9,0,620},{135,10,1190},{137,10,132},{7,11,975},{137,11,789},{6,0,95},{6,0,1934}\n,{136,0,967},{141,11,335},{6,0,406},{10,0,409},{10,0,447},{11,0,44},{140,0,100},\n{4,10,317},{135,10,1279},{132,0,477},{134,0,1268},{6,0,1941},{8,0,944},{5,10,63}\n,{133,10,509},{132,0,629},{132,11,104},{4,0,246},{133,0,375},{6,0,1636},{132,10,\n288},{135,11,1614},{9,0,49},{10,0,774},{8,10,89},{8,10,620},{11,10,628},{12,10,\n322},{143,10,124},{4,0,282},{7,0,1034},{11,0,398},{11,0,634},{12,0,1},{12,0,79},\n{12,0,544},{14,0,237},{17,0,10},{146,0,20},{132,0,824},{7,11,45},{9,11,542},{9,\n11,566},{138,11,728},{5,0,118},{5,0,499},{6,0,476},{6,0,665},{6,0,1176},{6,0,\n1196},{7,0,600},{7,0,888},{135,0,1096},{7,0,296},{7,0,596},{8,0,560},{8,0,586},{\n9,0,612},{11,0,304},{12,0,46},{13,0,89},{14,0,112},{145,0,122},{5,0,894},{6,0,\n1772},{9,0,1009},{138,10,120},{5,11,533},{7,11,755},{138,11,780},{151,10,1},{6,0\n,1474},{7,11,87},{142,11,288},{139,0,366},{137,10,461},{7,11,988},{7,11,1939},{9\n,11,64},{9,11,502},{12,11,7},{12,11,34},{13,11,12},{13,11,234},{147,11,77},{7,0,\n1599},{7,0,1723},{8,0,79},{8,0,106},{8,0,190},{8,0,302},{8,0,383},{8,0,713},{9,0\n,119},{9,0,233},{9,0,419},{9,0,471},{10,0,181},{10,0,406},{11,0,57},{11,0,85},{\n11,0,120},{11,0,177},{11,0,296},{11,0,382},{11,0,454},{11,0,758},{11,0,999},{12,\n0,27},{12,0,98},{12,0,131},{12,0,245},{12,0,312},{12,0,446},{12,0,454},{13,0,25}\n,{13,0,98},{13,0,426},{13,0,508},{14,0,70},{14,0,163},{14,0,272},{14,0,277},{14,\n0,370},{15,0,95},{15,0,138},{15,0,167},{17,0,38},{148,0,96},{135,10,1346},{10,0,\n200},{19,0,2},{151,0,22},{135,11,141},{134,10,85},{134,0,1759},{138,0,372},{145,\n0,16},{8,0,943},{132,11,619},{139,11,88},{5,11,246},{8,11,189},{9,11,355},{9,11,\n512},{10,11,124},{10,11,453},{11,11,143},{11,11,416},{11,11,859},{141,11,341},{5\n,0,258},{134,0,719},{6,0,1798},{6,0,1839},{8,0,900},{10,0,874},{10,0,886},{12,0,\n698},{12,0,732},{12,0,770},{16,0,106},{18,0,163},{18,0,170},{18,0,171},{152,0,20\n},{9,0,707},{11,0,326},{11,0,339},{12,0,423},{12,0,502},{20,0,62},{9,11,707},{11\n,11,326},{11,11,339},{12,11,423},{12,11,502},{148,11,62},{5,0,30},{7,0,495},{8,0\n,134},{9,0,788},{140,0,438},{133,11,678},{5,10,279},{6,10,235},{7,10,468},{8,10,\n446},{9,10,637},{10,10,717},{11,10,738},{140,10,514},{5,11,35},{6,11,287},{7,11,\n862},{7,11,1886},{138,11,179},{7,0,1948},{7,0,2004},{132,11,517},{5,10,17},{6,10\n,371},{137,10,528},{4,0,115},{5,0,669},{6,0,407},{8,0,311},{11,0,10},{141,0,5},{\n137,0,381},{5,0,50},{6,0,439},{7,0,780},{135,0,1040},{136,11,667},{11,11,403},{\n146,11,83},{5,0,1},{6,0,81},{138,0,520},{134,0,738},{5,0,482},{8,0,98},{9,0,172}\n,{10,0,360},{10,0,700},{10,0,822},{11,0,302},{11,0,778},{12,0,50},{12,0,127},{12\n,0,396},{13,0,62},{13,0,328},{14,0,122},{147,0,72},{9,11,157},{10,11,131},{140,\n11,72},{135,11,714},{135,11,539},{5,0,2},{6,0,512},{7,0,797},{7,0,1494},{8,0,253\n},{8,0,589},{9,0,77},{10,0,1},{10,0,129},{10,0,225},{11,0,118},{11,0,226},{11,0,\n251},{11,0,430},{11,0,701},{11,0,974},{11,0,982},{12,0,64},{12,0,260},{12,0,488}\n,{140,0,690},{5,11,394},{7,11,367},{7,11,487},{7,11,857},{7,11,1713},{8,11,246},\n{9,11,537},{10,11,165},{12,11,219},{140,11,561},{136,0,557},{5,10,779},{5,10,807\n},{6,10,1655},{134,10,1676},{4,10,196},{5,10,558},{133,10,949},{11,11,827},{12,\n11,56},{14,11,34},{143,11,148},{137,0,347},{133,0,572},{134,0,832},{4,0,12},{7,0\n,504},{7,0,522},{7,0,809},{8,0,797},{141,0,88},{4,10,752},{133,11,449},{7,11,86}\n,{8,11,103},{145,11,69},{7,11,2028},{138,11,641},{5,0,528},{6,11,1},{142,11,2},{\n134,0,861},{10,0,294},{4,10,227},{5,10,159},{5,10,409},{7,10,80},{10,10,479},{12\n,10,418},{14,10,50},{14,10,249},{142,10,295},{7,10,1470},{8,10,66},{8,10,137},{8\n,10,761},{9,10,638},{11,10,80},{11,10,212},{11,10,368},{11,10,418},{12,10,8},{13\n,10,15},{16,10,61},{17,10,59},{19,10,28},{148,10,84},{20,0,109},{135,11,1148},{6\n,11,277},{7,11,1274},{7,11,1386},{7,11,1392},{12,11,129},{146,11,87},{6,11,187},\n{7,11,39},{7,11,1203},{8,11,380},{8,11,542},{14,11,117},{149,11,28},{134,0,1187}\n,{5,0,266},{9,0,290},{9,0,364},{10,0,293},{11,0,606},{142,0,45},{6,11,297},{7,11\n,793},{139,11,938},{4,0,50},{6,0,594},{9,0,121},{10,0,49},{10,0,412},{139,0,834}\n,{136,0,748},{7,11,464},{8,11,438},{11,11,105},{11,11,363},{12,11,231},{14,11,\n386},{15,11,102},{148,11,75},{132,0,466},{13,0,399},{14,0,337},{6,10,38},{7,10,\n1220},{8,10,185},{8,10,256},{9,10,22},{9,10,331},{10,10,738},{11,10,205},{11,10,\n540},{11,10,746},{13,10,465},{142,10,194},{9,0,378},{141,0,162},{137,0,519},{4,\n10,159},{6,10,115},{7,10,252},{7,10,257},{7,10,1928},{8,10,69},{9,10,384},{10,10\n,91},{10,10,615},{12,10,375},{14,10,235},{18,10,117},{147,10,123},{5,11,604},{5,\n10,911},{136,10,278},{132,0,667},{8,0,351},{9,0,322},{4,10,151},{135,10,1567},{\n134,0,902},{133,10,990},{12,0,180},{5,10,194},{7,10,1662},{137,10,90},{4,0,869},\n{134,0,1996},{134,0,813},{133,10,425},{137,11,761},{132,0,260},{133,10,971},{5,\n11,20},{6,11,298},{7,11,659},{7,11,1366},{137,11,219},{4,0,39},{5,0,36},{7,0,\n1843},{8,0,407},{11,0,144},{140,0,523},{4,0,510},{10,0,587},{139,10,752},{7,0,29\n},{7,0,66},{7,0,1980},{10,0,487},{138,0,809},{13,0,260},{14,0,82},{18,0,63},{137\n,10,662},{5,10,72},{6,10,264},{7,10,21},{7,10,46},{7,10,2013},{8,10,215},{8,10,\n513},{10,10,266},{139,10,22},{134,0,570},{6,0,565},{7,0,1667},{4,11,439},{10,10,\n95},{11,10,603},{12,11,242},{13,10,443},{14,10,160},{143,10,4},{134,0,1464},{134\n,10,431},{9,0,372},{15,0,2},{19,0,10},{19,0,18},{5,10,874},{6,10,1677},{143,10,0\n},{132,0,787},{6,0,380},{12,0,399},{21,0,19},{7,10,939},{7,10,1172},{7,10,1671},\n{9,10,540},{10,10,696},{11,10,265},{11,10,732},{11,10,928},{11,10,937},{141,10,\n438},{137,0,200},{132,11,233},{132,0,516},{134,11,577},{132,0,844},{11,0,887},{\n14,0,365},{142,0,375},{132,11,482},{8,0,821},{140,0,44},{7,0,1655},{136,0,305},{\n5,10,682},{135,10,1887},{135,11,346},{132,10,696},{4,0,10},{7,0,917},{139,0,786}\n,{5,11,795},{6,11,1741},{8,11,417},{137,11,782},{4,0,1016},{134,0,2031},{5,0,684\n},{4,10,726},{133,10,630},{6,0,1021},{134,0,1480},{8,10,802},{136,10,838},{134,0\n,27},{134,0,395},{135,11,622},{7,11,625},{135,11,1750},{4,11,203},{135,11,1936},\n{6,10,118},{7,10,215},{7,10,1521},{140,10,11},{132,0,813},{136,0,511},{7,10,615}\n,{138,10,251},{135,10,1044},{145,0,56},{133,10,225},{6,0,342},{6,0,496},{8,0,275\n},{137,0,206},{4,0,909},{133,0,940},{132,0,891},{7,11,311},{9,11,308},{140,11,\n255},{4,10,370},{5,10,756},{135,10,1326},{4,0,687},{134,0,1596},{134,0,1342},{6,\n10,1662},{7,10,48},{8,10,771},{10,10,116},{13,10,104},{14,10,105},{14,10,184},{\n15,10,168},{19,10,92},{148,10,68},{138,10,209},{4,11,400},{5,11,267},{135,11,232\n},{151,11,12},{6,0,41},{141,0,160},{141,11,314},{134,0,1718},{136,0,778},{142,11\n,261},{134,0,1610},{133,0,115},{132,0,294},{14,0,314},{132,10,120},{132,0,983},{\n5,0,193},{140,0,178},{138,10,429},{5,10,820},{135,10,931},{6,0,994},{6,0,1051},{\n6,0,1439},{7,0,174},{133,11,732},{4,11,100},{7,11,679},{8,11,313},{138,10,199},{\n6,10,151},{6,10,1675},{7,10,383},{151,10,10},{6,0,1796},{8,0,848},{8,0,867},{8,0\n,907},{10,0,855},{140,0,703},{140,0,221},{4,0,122},{5,0,796},{5,0,952},{6,0,1660\n},{6,0,1671},{8,0,567},{9,0,687},{9,0,742},{10,0,686},{11,0,682},{11,0,909},{140\n,0,281},{5,11,362},{5,11,443},{6,11,318},{7,11,1019},{139,11,623},{5,11,463},{\n136,11,296},{11,0,583},{13,0,262},{6,10,1624},{12,10,422},{142,10,360},{5,0,179}\n,{7,0,1095},{135,0,1213},{4,10,43},{4,11,454},{5,10,344},{133,10,357},{4,0,66},{\n7,0,722},{135,0,904},{134,0,773},{7,0,352},{133,10,888},{5,11,48},{5,11,404},{6,\n11,557},{7,11,458},{8,11,597},{10,11,455},{10,11,606},{11,11,49},{11,11,548},{12\n,11,476},{13,11,18},{141,11,450},{134,11,418},{132,10,711},{5,11,442},{135,11,\n1984},{141,0,35},{137,0,152},{134,0,1197},{135,11,1093},{137,11,203},{137,10,440\n},{10,0,592},{10,0,753},{12,0,317},{12,0,355},{12,0,465},{12,0,469},{12,0,560},{\n12,0,578},{141,0,243},{133,0,564},{134,0,797},{5,10,958},{133,10,987},{5,11,55},\n{7,11,376},{140,11,161},{133,11,450},{134,0,556},{134,0,819},{11,10,276},{142,10\n,293},{7,0,544},{138,0,61},{8,0,719},{4,10,65},{5,10,479},{5,10,1004},{7,10,1913\n},{8,10,317},{9,10,302},{10,10,612},{141,10,22},{4,0,5},{5,0,498},{8,0,637},{9,0\n,521},{4,11,213},{4,10,261},{7,11,223},{7,10,510},{136,11,80},{5,0,927},{7,0,101\n},{4,10,291},{7,11,381},{7,11,806},{7,11,820},{8,11,354},{8,11,437},{8,11,787},{\n9,10,515},{9,11,657},{10,11,58},{10,11,339},{10,11,749},{11,11,914},{12,10,152},\n{12,11,162},{12,10,443},{13,11,75},{13,10,392},{14,11,106},{14,11,198},{14,11,\n320},{14,10,357},{14,11,413},{146,11,43},{6,0,1153},{7,0,1441},{136,11,747},{4,0\n,893},{5,0,780},{133,0,893},{138,11,654},{133,11,692},{133,0,238},{134,11,191},{\n4,10,130},{135,10,843},{6,0,1296},{5,10,42},{5,10,879},{7,10,245},{7,10,324},{7,\n10,1532},{11,10,463},{11,10,472},{13,10,363},{144,10,52},{134,0,1729},{6,0,1999}\n,{136,0,969},{4,10,134},{133,10,372},{4,0,60},{7,0,941},{7,0,1800},{8,0,314},{9,\n0,700},{139,0,487},{134,0,1144},{6,11,162},{7,11,1960},{136,11,831},{132,11,706}\n,{135,0,1147},{138,11,426},{138,11,89},{7,0,1853},{138,0,437},{136,0,419},{135,\n10,1634},{133,0,828},{5,0,806},{7,0,176},{7,0,178},{7,0,1240},{7,0,1976},{132,10\n,644},{135,11,1877},{5,11,420},{135,11,1449},{4,0,51},{5,0,39},{6,0,4},{7,0,591}\n,{7,0,849},{7,0,951},{7,0,1613},{7,0,1760},{7,0,1988},{9,0,434},{10,0,754},{11,0\n,25},{139,0,37},{10,11,57},{138,11,277},{135,10,540},{132,11,204},{135,0,159},{\n139,11,231},{133,0,902},{7,0,928},{7,11,366},{9,11,287},{12,11,199},{12,11,556},\n{140,11,577},{6,10,623},{136,10,789},{4,10,908},{5,10,359},{5,10,508},{6,10,1723\n},{7,10,343},{7,10,1996},{135,10,2026},{134,0,270},{4,10,341},{135,10,480},{5,11\n,356},{135,11,224},{11,11,588},{11,11,864},{11,11,968},{143,11,160},{132,0,556},\n{137,0,801},{132,0,416},{142,0,372},{5,0,152},{5,0,197},{7,0,340},{7,0,867},{10,\n0,548},{10,0,581},{11,0,6},{12,0,3},{12,0,19},{14,0,110},{142,0,289},{139,0,369}\n,{7,11,630},{9,11,567},{11,11,150},{11,11,444},{141,11,119},{134,11,539},{7,10,\n1995},{8,10,299},{11,10,890},{140,10,674},{7,0,34},{7,0,190},{8,0,28},{8,0,141},\n{8,0,444},{8,0,811},{9,0,468},{11,0,334},{12,0,24},{12,0,386},{140,0,576},{133,0\n,757},{7,0,1553},{136,0,898},{133,0,721},{136,0,1012},{4,0,789},{5,0,647},{135,0\n,1102},{132,0,898},{10,0,183},{4,10,238},{5,10,503},{6,10,179},{7,10,2003},{8,10\n,381},{8,10,473},{9,10,149},{10,10,788},{15,10,45},{15,10,86},{20,10,110},{150,\n10,57},{9,0,136},{19,0,107},{4,10,121},{5,10,156},{5,10,349},{10,10,605},{142,10\n,342},{4,11,235},{135,11,255},{4,11,194},{5,11,584},{6,11,384},{7,11,583},{10,11\n,761},{11,11,760},{139,11,851},{6,10,80},{6,10,1694},{7,10,173},{7,10,1974},{9,\n10,547},{10,10,730},{14,10,18},{150,10,39},{4,10,923},{134,10,1711},{5,0,277},{\n141,0,247},{132,0,435},{133,11,562},{134,0,1311},{5,11,191},{137,11,271},{132,10\n,595},{7,11,1537},{14,11,96},{143,11,73},{5,0,437},{7,0,502},{7,0,519},{7,0,1122\n},{7,0,1751},{14,0,211},{6,10,459},{7,10,1753},{7,10,1805},{8,10,658},{9,10,1},{\n11,10,959},{141,10,446},{6,0,814},{4,11,470},{5,11,473},{6,11,153},{7,11,1503},{\n7,11,1923},{10,11,701},{11,11,132},{11,11,168},{11,11,227},{11,11,320},{11,11,\n436},{11,11,525},{11,11,855},{12,11,41},{12,11,286},{13,11,103},{13,11,284},{14,\n11,255},{14,11,262},{15,11,117},{143,11,127},{5,0,265},{6,0,212},{135,0,28},{138\n,0,750},{133,11,327},{6,11,552},{7,11,1754},{137,11,604},{134,0,2012},{132,0,702\n},{5,11,80},{6,11,405},{7,11,403},{7,11,1502},{7,11,1626},{8,11,456},{9,11,487},\n{9,11,853},{9,11,889},{10,11,309},{11,11,721},{11,11,994},{12,11,430},{141,11,\n165},{5,0,808},{135,0,2045},{5,0,166},{8,0,739},{140,0,511},{134,10,490},{4,11,\n453},{5,11,887},{6,11,535},{8,11,6},{136,11,543},{4,0,119},{5,0,170},{5,0,447},{\n7,0,1708},{7,0,1889},{9,0,357},{9,0,719},{12,0,486},{140,0,596},{137,0,500},{7,\n10,250},{136,10,507},{132,10,158},{6,0,809},{134,0,1500},{9,0,327},{11,0,350},{\n11,0,831},{13,0,352},{4,10,140},{7,10,362},{8,10,209},{9,10,10},{9,10,503},{9,10\n,614},{10,10,689},{11,10,327},{11,10,725},{12,10,252},{12,10,583},{13,10,192},{\n14,10,269},{14,10,356},{148,10,50},{135,11,741},{4,0,450},{7,0,1158},{19,10,1},{\n19,10,26},{150,10,9},{6,0,597},{135,0,1318},{134,0,1602},{6,10,228},{7,10,1341},\n{9,10,408},{138,10,343},{7,0,1375},{7,0,1466},{138,0,331},{132,0,754},{132,10,\n557},{5,11,101},{6,11,88},{6,11,543},{7,11,1677},{9,11,100},{10,11,677},{14,11,\n169},{14,11,302},{14,11,313},{15,11,48},{143,11,84},{134,0,1368},{4,11,310},{9,\n11,795},{10,11,733},{11,11,451},{12,11,249},{14,11,115},{14,11,286},{143,11,100}\n,{132,10,548},{10,0,557},{7,10,197},{8,10,142},{8,10,325},{9,10,150},{9,10,596},\n{10,10,353},{11,10,74},{11,10,315},{12,10,662},{12,10,681},{14,10,423},{143,10,\n141},{133,11,587},{5,0,850},{136,0,799},{10,0,908},{12,0,701},{12,0,757},{142,0,\n466},{4,0,62},{5,0,275},{18,0,19},{6,10,399},{6,10,579},{7,10,692},{7,10,846},{7\n,10,1015},{7,10,1799},{8,10,403},{9,10,394},{10,10,133},{12,10,4},{12,10,297},{\n12,10,452},{16,10,81},{18,10,25},{21,10,14},{22,10,12},{151,10,18},{12,0,459},{7\n,10,1546},{11,10,299},{142,10,407},{132,10,177},{132,11,498},{7,11,217},{8,11,\n140},{138,11,610},{5,10,411},{135,10,653},{134,0,1802},{7,10,439},{10,10,727},{\n11,10,260},{139,10,684},{133,11,905},{11,11,580},{142,11,201},{134,0,1397},{5,10\n,208},{7,10,753},{135,10,1528},{7,0,238},{7,0,2033},{8,0,120},{8,0,188},{8,0,659\n},{9,0,598},{10,0,466},{12,0,342},{12,0,588},{13,0,503},{14,0,246},{143,0,92},{\n135,11,1041},{4,11,456},{7,11,105},{7,11,358},{7,11,1637},{8,11,643},{139,11,483\n},{6,0,1318},{134,0,1324},{4,0,201},{7,0,1744},{8,0,602},{11,0,247},{11,0,826},{\n17,0,65},{133,10,242},{8,0,164},{146,0,62},{133,10,953},{139,10,802},{133,0,615}\n,{7,11,1566},{8,11,269},{9,11,212},{9,11,718},{14,11,15},{14,11,132},{142,11,227\n},{133,10,290},{132,10,380},{5,10,52},{7,10,277},{9,10,368},{139,10,791},{135,0,\n1243},{133,11,539},{11,11,919},{141,11,409},{136,0,968},{133,11,470},{134,0,882}\n,{132,0,907},{5,0,100},{10,0,329},{12,0,416},{149,0,29},{10,10,138},{139,10,476}\n,{5,10,725},{5,10,727},{6,11,91},{7,11,435},{135,10,1811},{4,11,16},{5,11,316},{\n5,11,842},{6,11,370},{6,11,1778},{8,11,166},{11,11,812},{12,11,206},{12,11,351},\n{14,11,418},{16,11,15},{16,11,34},{18,11,3},{19,11,3},{19,11,7},{20,11,4},{149,\n11,21},{132,0,176},{5,0,636},{5,0,998},{7,0,9},{7,0,1508},{8,0,26},{9,0,317},{9,\n0,358},{10,0,210},{10,0,292},{10,0,533},{11,0,555},{12,0,526},{12,0,607},{13,0,\n263},{13,0,459},{142,0,271},{6,0,256},{8,0,265},{4,10,38},{7,10,307},{7,10,999},\n{7,10,1481},{7,10,1732},{7,10,1738},{9,10,414},{11,10,316},{12,10,52},{13,10,420\n},{147,10,100},{135,10,1296},{4,11,611},{133,11,606},{4,0,643},{142,11,21},{133,\n11,715},{133,10,723},{6,0,610},{135,11,597},{10,0,127},{141,0,27},{6,0,1995},{6,\n0,2001},{8,0,119},{136,0,973},{4,11,149},{138,11,368},{12,0,522},{4,11,154},{5,\n10,109},{6,10,1784},{7,11,1134},{7,10,1895},{8,11,105},{12,10,296},{140,10,302},\n{4,11,31},{6,11,429},{7,11,962},{9,11,458},{139,11,691},{10,0,553},{11,0,876},{\n13,0,193},{13,0,423},{14,0,166},{19,0,84},{4,11,312},{5,10,216},{7,10,1879},{9,\n10,141},{9,10,270},{9,10,679},{10,10,159},{11,10,197},{12,10,538},{12,10,559},{\n14,10,144},{14,10,167},{143,10,67},{134,0,1582},{7,0,1578},{135,11,1578},{137,10\n,81},{132,11,236},{134,10,391},{134,0,795},{7,10,322},{136,10,249},{5,11,836},{5\n,11,857},{6,11,1680},{7,11,59},{147,11,53},{135,0,432},{10,11,68},{139,11,494},{\n4,11,81},{139,11,867},{7,0,126},{136,0,84},{142,11,280},{5,11,282},{8,11,650},{9\n,11,295},{9,11,907},{138,11,443},{136,0,790},{5,10,632},{138,10,526},{6,0,64},{\n12,0,377},{13,0,309},{14,0,141},{14,0,429},{14,11,141},{142,11,429},{134,0,1529}\n,{6,0,321},{7,0,1857},{9,0,530},{19,0,99},{7,10,948},{7,10,1042},{8,10,235},{8,\n10,461},{9,10,453},{10,10,354},{145,10,77},{7,0,1104},{11,0,269},{11,0,539},{11,\n0,627},{11,0,706},{11,0,975},{12,0,248},{12,0,434},{12,0,600},{12,0,622},{13,0,\n297},{13,0,485},{14,0,69},{14,0,409},{143,0,108},{4,10,362},{7,10,52},{7,10,303}\n,{10,11,70},{12,11,26},{14,11,17},{14,11,178},{15,11,34},{149,11,12},{11,0,977},\n{141,0,507},{9,0,34},{139,0,484},{5,10,196},{6,10,486},{7,10,212},{8,10,309},{\n136,10,346},{6,0,1700},{7,0,26},{7,0,293},{7,0,382},{7,0,1026},{7,0,1087},{7,0,\n2027},{8,0,24},{8,0,114},{8,0,252},{8,0,727},{8,0,729},{9,0,30},{9,0,199},{9,0,\n231},{9,0,251},{9,0,334},{9,0,361},{9,0,712},{10,0,55},{10,0,60},{10,0,232},{10,\n0,332},{10,0,384},{10,0,396},{10,0,504},{10,0,542},{10,0,652},{11,0,20},{11,0,48\n},{11,0,207},{11,0,291},{11,0,298},{11,0,342},{11,0,365},{11,0,394},{11,0,620},{\n11,0,705},{11,0,1017},{12,0,123},{12,0,340},{12,0,406},{12,0,643},{13,0,61},{13,\n0,269},{13,0,311},{13,0,319},{13,0,486},{14,0,234},{15,0,62},{15,0,85},{16,0,71}\n,{18,0,119},{20,0,105},{135,10,1912},{4,11,71},{5,11,376},{7,11,119},{138,11,665\n},{10,0,918},{10,0,926},{4,10,686},{136,11,55},{138,10,625},{136,10,706},{132,11\n,479},{4,10,30},{133,10,43},{6,0,379},{7,0,270},{8,0,176},{8,0,183},{9,0,432},{9\n,0,661},{12,0,247},{12,0,617},{18,0,125},{7,11,607},{8,11,99},{152,11,4},{5,0,\n792},{133,0,900},{4,11,612},{133,11,561},{4,11,41},{4,10,220},{5,11,74},{7,10,\n1535},{7,11,1627},{11,11,871},{140,11,619},{135,0,1920},{7,11,94},{11,11,329},{\n11,11,965},{12,11,241},{14,11,354},{15,11,22},{148,11,63},{9,11,209},{137,11,300\n},{134,0,771},{135,0,1979},{4,0,901},{133,0,776},{142,0,254},{133,11,98},{9,11,\n16},{141,11,386},{133,11,984},{4,11,182},{6,11,205},{135,11,220},{7,10,1725},{7,\n10,1774},{138,10,393},{5,10,263},{134,10,414},{4,11,42},{9,11,205},{9,11,786},{\n138,11,659},{14,0,140},{148,0,41},{8,0,440},{10,0,359},{6,10,178},{6,11,289},{6,\n10,1750},{7,11,1670},{9,10,690},{10,10,155},{10,10,373},{11,10,698},{12,11,57},{\n13,10,155},{20,10,93},{151,11,4},{4,0,37},{5,0,334},{7,0,1253},{151,11,25},{4,0,\n508},{4,11,635},{5,10,97},{137,10,393},{139,11,533},{4,0,640},{133,0,513},{134,\n10,1639},{132,11,371},{4,11,272},{7,11,836},{7,11,1651},{145,11,89},{5,11,825},{\n6,11,444},{6,11,1640},{136,11,308},{4,10,191},{7,10,934},{8,10,647},{145,10,97},\n{12,0,246},{15,0,162},{19,0,64},{20,0,8},{20,0,95},{22,0,24},{152,0,17},{4,0,533\n},{5,10,165},{9,10,346},{138,10,655},{5,11,737},{139,10,885},{133,10,877},{8,10,\n128},{139,10,179},{137,11,307},{140,0,752},{133,0,920},{135,0,1048},{5,0,153},{6\n,0,580},{6,10,1663},{7,10,132},{7,10,1154},{7,10,1415},{7,10,1507},{12,10,493},{\n15,10,105},{151,10,15},{5,10,459},{7,10,1073},{8,10,241},{136,10,334},{138,0,391\n},{135,0,1952},{133,11,525},{8,11,641},{11,11,388},{140,11,580},{142,0,126},{134\n,0,640},{132,0,483},{7,0,1616},{9,0,69},{6,10,324},{6,10,520},{7,10,338},{7,10,\n1729},{8,10,228},{139,10,750},{5,11,493},{134,11,528},{135,0,734},{4,11,174},{\n135,11,911},{138,0,480},{9,0,495},{146,0,104},{135,10,705},{9,0,472},{4,10,73},{\n6,10,612},{7,10,927},{7,10,1330},{7,10,1822},{8,10,217},{9,10,765},{9,10,766},{\n10,10,408},{11,10,51},{11,10,793},{12,10,266},{15,10,158},{20,10,89},{150,10,32}\n,{7,11,548},{137,11,58},{4,11,32},{5,11,215},{6,11,269},{7,11,1782},{7,11,1892},\n{10,11,16},{11,11,822},{11,11,954},{141,11,481},{132,0,874},{9,0,229},{5,10,389}\n,{136,10,636},{7,11,1749},{136,11,477},{134,0,948},{5,11,308},{135,11,1088},{4,0\n,748},{139,0,1009},{136,10,21},{6,0,555},{135,0,485},{5,11,126},{8,11,297},{9,11\n,366},{9,11,445},{12,11,53},{12,11,374},{141,11,492},{7,11,1551},{139,11,361},{\n136,0,193},{136,0,472},{8,0,653},{13,0,93},{147,0,14},{132,0,984},{132,11,175},{\n5,0,172},{6,0,1971},{132,11,685},{149,11,8},{133,11,797},{13,0,83},{5,10,189},{7\n,10,442},{7,10,443},{8,10,281},{12,10,174},{141,10,261},{134,0,1568},{133,11,565\n},{139,0,384},{133,0,260},{7,0,758},{7,0,880},{7,0,1359},{9,0,164},{9,0,167},{10\n,0,156},{10,0,588},{12,0,101},{14,0,48},{15,0,70},{6,10,2},{7,10,1262},{7,10,\n1737},{8,10,22},{8,10,270},{8,10,612},{9,10,312},{9,10,436},{10,10,311},{10,10,\n623},{11,10,72},{11,10,330},{11,10,455},{12,10,321},{12,10,504},{12,10,530},{12,\n10,543},{13,10,17},{13,10,156},{13,10,334},{17,10,60},{148,10,64},{4,11,252},{7,\n11,1068},{10,11,434},{11,11,228},{11,11,426},{13,11,231},{18,11,106},{148,11,87}\n,{7,10,354},{10,10,410},{139,10,815},{6,0,367},{7,10,670},{7,10,1327},{8,10,411}\n,{8,10,435},{9,10,653},{9,10,740},{10,10,385},{11,10,222},{11,10,324},{11,10,829\n},{140,10,611},{7,0,1174},{6,10,166},{135,10,374},{146,0,121},{132,0,828},{5,11,\n231},{138,11,509},{7,11,601},{9,11,277},{9,11,674},{10,11,178},{10,11,257},{10,\n11,418},{11,11,531},{11,11,544},{11,11,585},{12,11,113},{12,11,475},{13,11,99},{\n142,11,428},{134,0,1541},{135,11,1779},{5,0,343},{134,10,398},{135,10,50},{135,\n11,1683},{4,0,440},{7,0,57},{8,0,167},{8,0,375},{9,0,82},{9,0,561},{9,0,744},{10\n,0,620},{137,11,744},{134,0,926},{6,10,517},{7,10,1159},{10,10,621},{139,10,192}\n,{137,0,827},{8,0,194},{136,0,756},{10,10,223},{139,10,645},{7,10,64},{136,10,\n245},{4,11,399},{5,11,119},{5,11,494},{7,11,751},{137,11,556},{132,0,808},{135,0\n,22},{7,10,1763},{140,10,310},{5,0,639},{7,0,1249},{11,0,896},{134,11,584},{134,\n0,1614},{135,0,860},{135,11,1121},{5,10,129},{6,10,61},{135,10,947},{4,0,102},{7\n,0,815},{7,0,1699},{139,0,964},{13,10,505},{141,10,506},{139,10,1000},{132,11,\n679},{132,0,899},{132,0,569},{5,11,694},{137,11,714},{136,0,795},{6,0,2045},{139\n,11,7},{6,0,52},{9,0,104},{9,0,559},{12,0,308},{147,0,87},{4,0,301},{132,0,604},\n{133,10,637},{136,0,779},{5,11,143},{5,11,769},{6,11,1760},{7,11,682},{7,11,1992\n},{136,11,736},{137,10,590},{147,0,32},{137,11,527},{5,10,280},{135,10,1226},{\n134,0,494},{6,0,677},{6,0,682},{134,0,1044},{133,10,281},{135,10,1064},{7,0,508}\n,{133,11,860},{6,11,422},{7,11,0},{7,11,1544},{9,11,577},{11,11,990},{12,11,141}\n,{12,11,453},{13,11,47},{141,11,266},{134,0,1014},{5,11,515},{137,11,131},{134,0\n,957},{132,11,646},{6,0,310},{7,0,1849},{8,0,72},{8,0,272},{8,0,431},{9,0,12},{9\n,0,376},{10,0,563},{10,0,630},{10,0,796},{10,0,810},{11,0,367},{11,0,599},{11,0,\n686},{140,0,672},{7,0,570},{4,11,396},{7,10,120},{7,11,728},{8,10,489},{9,11,117\n},{9,10,319},{10,10,820},{11,10,1004},{12,10,379},{12,10,679},{13,10,117},{13,11\n,202},{13,10,412},{14,10,25},{15,10,52},{15,10,161},{16,10,47},{20,11,51},{149,\n10,2},{6,11,121},{6,11,124},{6,11,357},{7,11,1138},{7,11,1295},{8,11,162},{139,\n11,655},{8,0,449},{4,10,937},{5,10,801},{136,11,449},{139,11,958},{6,0,181},{7,0\n,537},{8,0,64},{9,0,127},{10,0,496},{12,0,510},{141,0,384},{138,11,253},{4,0,244\n},{135,0,233},{133,11,237},{132,10,365},{6,0,1650},{10,0,702},{139,0,245},{5,10,\n7},{139,10,774},{13,0,463},{20,0,49},{13,11,463},{148,11,49},{4,10,734},{5,10,\n662},{134,10,430},{4,10,746},{135,10,1090},{5,10,360},{136,10,237},{137,0,338},{\n143,11,10},{7,11,571},{138,11,366},{134,0,1279},{9,11,513},{10,11,22},{10,11,39}\n,{12,11,122},{140,11,187},{133,0,896},{146,0,178},{134,0,695},{137,0,808},{134,\n11,587},{7,11,107},{7,11,838},{8,11,550},{138,11,401},{7,0,1117},{136,0,539},{4,\n10,277},{5,10,608},{6,10,493},{7,10,457},{140,10,384},{133,11,768},{12,0,257},{7\n,10,27},{135,10,316},{140,0,1003},{4,0,207},{5,0,586},{5,0,676},{6,0,448},{8,0,\n244},{11,0,1},{13,0,3},{16,0,54},{17,0,4},{18,0,13},{133,10,552},{4,10,401},{137\n,10,264},{5,0,516},{7,0,1883},{135,11,1883},{12,0,960},{132,11,894},{5,0,4},{5,0\n,810},{6,0,13},{6,0,538},{6,0,1690},{6,0,1726},{7,0,499},{7,0,1819},{8,0,148},{8\n,0,696},{8,0,791},{12,0,125},{143,0,9},{135,0,1268},{11,0,30},{14,0,315},{9,10,\n543},{10,10,524},{12,10,524},{16,10,18},{20,10,26},{148,10,65},{6,0,748},{4,10,\n205},{5,10,623},{7,10,104},{136,10,519},{11,0,542},{139,0,852},{140,0,6},{132,0,\n848},{7,0,1385},{11,0,582},{11,0,650},{11,0,901},{11,0,949},{12,0,232},{12,0,236\n},{13,0,413},{13,0,501},{18,0,116},{7,10,579},{9,10,41},{9,10,244},{9,10,669},{\n10,10,5},{11,10,861},{11,10,951},{139,10,980},{4,0,945},{6,0,1811},{6,0,1845},{6\n,0,1853},{6,0,1858},{8,0,862},{12,0,782},{12,0,788},{18,0,160},{148,0,117},{132,\n10,717},{4,0,925},{5,0,803},{8,0,698},{138,0,828},{134,0,1416},{132,0,610},{139,\n0,992},{6,0,878},{134,0,1477},{135,0,1847},{138,11,531},{137,11,539},{134,11,272\n},{133,0,383},{134,0,1404},{132,10,489},{4,11,9},{5,11,128},{7,11,368},{11,11,\n480},{148,11,3},{136,0,986},{9,0,660},{138,0,347},{135,10,892},{136,11,682},{7,0\n,572},{9,0,592},{11,0,680},{12,0,356},{140,0,550},{7,0,1411},{138,11,527},{4,11,\n2},{7,11,545},{135,11,894},{137,10,473},{11,0,64},{7,11,481},{7,10,819},{9,10,26\n},{9,10,392},{9,11,792},{10,10,152},{10,10,226},{12,10,276},{12,10,426},{12,10,\n589},{13,10,460},{15,10,97},{19,10,48},{148,10,104},{135,10,51},{136,11,445},{\n136,11,646},{135,0,606},{132,10,674},{6,0,1829},{134,0,1830},{132,10,770},{5,10,\n79},{7,10,1027},{7,10,1477},{139,10,52},{5,11,530},{142,11,113},{134,10,1666},{7\n,0,748},{139,0,700},{134,10,195},{133,10,789},{9,0,87},{10,0,365},{4,10,251},{4,\n10,688},{7,10,513},{135,10,1284},{136,11,111},{133,0,127},{6,0,198},{140,0,83},{\n133,11,556},{133,10,889},{4,10,160},{5,10,330},{7,10,1434},{136,10,174},{5,0,276\n},{6,0,55},{7,0,1369},{138,0,864},{8,11,16},{140,11,568},{6,0,1752},{136,0,726},\n{135,0,1066},{133,0,764},{6,11,186},{137,11,426},{11,0,683},{139,11,683},{6,0,\n309},{7,0,331},{138,0,550},{133,10,374},{6,0,1212},{6,0,1852},{7,0,1062},{8,0,\n874},{8,0,882},{138,0,936},{132,11,585},{134,0,1364},{7,0,986},{133,10,731},{6,0\n,723},{6,0,1408},{138,0,381},{135,0,1573},{134,0,1025},{4,10,626},{5,10,642},{6,\n10,425},{10,10,202},{139,10,141},{4,11,93},{5,11,252},{6,11,229},{7,11,291},{9,\n11,550},{139,11,644},{137,11,749},{137,11,162},{132,11,381},{135,0,1559},{6,0,\n194},{7,0,133},{10,0,493},{10,0,570},{139,0,664},{5,0,24},{5,0,569},{6,0,3},{6,0\n,119},{6,0,143},{6,0,440},{7,0,295},{7,0,599},{7,0,1686},{7,0,1854},{8,0,424},{9\n,0,43},{9,0,584},{9,0,760},{10,0,148},{10,0,328},{11,0,159},{11,0,253},{11,0,506\n},{12,0,487},{140,0,531},{6,0,661},{134,0,1517},{136,10,835},{151,10,17},{5,0,14\n},{5,0,892},{6,0,283},{7,0,234},{136,0,537},{139,0,541},{4,0,126},{8,0,635},{147\n,0,34},{4,0,316},{4,0,495},{135,0,1561},{4,11,187},{5,11,184},{5,11,690},{7,11,\n1869},{138,11,756},{139,11,783},{4,0,998},{137,0,861},{136,0,1009},{139,11,292},\n{5,11,21},{6,11,77},{6,11,157},{7,11,974},{7,11,1301},{7,11,1339},{7,11,1490},{7\n,11,1873},{137,11,628},{7,11,1283},{9,11,227},{9,11,499},{10,11,341},{11,11,325}\n,{11,11,408},{14,11,180},{15,11,144},{18,11,47},{147,11,49},{4,0,64},{5,0,352},{\n5,0,720},{6,0,368},{139,0,359},{5,10,384},{8,10,455},{140,10,48},{5,10,264},{134\n,10,184},{7,0,1577},{10,0,304},{10,0,549},{12,0,365},{13,0,220},{13,0,240},{142,\n0,33},{134,0,1107},{134,0,929},{135,0,1142},{6,0,175},{137,0,289},{5,0,432},{133\n,0,913},{6,0,279},{7,0,219},{5,10,633},{135,10,1323},{7,0,785},{7,10,359},{8,10,\n243},{140,10,175},{139,0,595},{132,10,105},{8,11,398},{9,11,681},{139,11,632},{\n140,0,80},{5,0,931},{134,0,1698},{142,11,241},{134,11,20},{134,0,1323},{11,0,526\n},{11,0,939},{141,0,290},{5,0,774},{6,0,780},{6,0,1637},{6,0,1686},{6,0,1751},{8\n,0,559},{141,0,109},{141,0,127},{7,0,1167},{11,0,934},{13,0,391},{17,0,76},{135,\n11,709},{135,0,963},{6,0,260},{135,0,1484},{134,0,573},{4,10,758},{139,11,941},{\n135,10,1649},{145,11,36},{4,0,292},{137,0,580},{4,0,736},{5,0,871},{6,0,1689},{\n135,0,1944},{7,11,945},{11,11,713},{139,11,744},{134,0,1164},{135,11,937},{6,0,\n1922},{9,0,982},{15,0,173},{15,0,178},{15,0,200},{18,0,189},{18,0,207},{21,0,47}\n,{135,11,1652},{7,0,1695},{139,10,128},{6,0,63},{135,0,920},{133,0,793},{143,11,\n134},{133,10,918},{5,0,67},{6,0,62},{6,0,374},{135,0,1391},{9,0,790},{12,0,47},{\n4,11,579},{5,11,226},{5,11,323},{135,11,960},{10,11,784},{141,11,191},{4,0,391},\n{135,0,1169},{137,0,443},{13,11,232},{146,11,35},{132,10,340},{132,0,271},{137,\n11,313},{5,11,973},{137,11,659},{134,0,1140},{6,11,135},{135,11,1176},{4,0,253},\n{5,0,544},{7,0,300},{137,0,340},{7,0,897},{5,10,985},{7,10,509},{145,10,96},{138\n,11,735},{135,10,1919},{138,0,890},{5,0,818},{134,0,1122},{5,0,53},{5,0,541},{6,\n0,94},{6,0,499},{7,0,230},{139,0,321},{4,0,920},{5,0,25},{5,0,790},{6,0,457},{7,\n0,853},{8,0,788},{142,11,31},{132,10,247},{135,11,314},{132,0,468},{7,0,243},{6,\n10,337},{7,10,494},{8,10,27},{8,10,599},{138,10,153},{4,10,184},{5,10,390},{7,10\n,618},{7,10,1456},{139,10,710},{134,0,870},{134,0,1238},{134,0,1765},{10,0,853},\n{10,0,943},{14,0,437},{14,0,439},{14,0,443},{14,0,446},{14,0,452},{14,0,469},{14\n,0,471},{14,0,473},{16,0,93},{16,0,102},{16,0,110},{148,0,121},{4,0,605},{7,0,\n518},{7,0,1282},{7,0,1918},{10,0,180},{139,0,218},{133,0,822},{4,0,634},{11,0,\n916},{142,0,419},{6,11,281},{7,11,6},{8,11,282},{8,11,480},{8,11,499},{9,11,198}\n,{10,11,143},{10,11,169},{10,11,211},{10,11,417},{10,11,574},{11,11,147},{11,11,\n395},{12,11,75},{12,11,407},{12,11,608},{13,11,500},{142,11,251},{134,0,898},{6,\n0,36},{7,0,658},{8,0,454},{150,11,48},{133,11,674},{135,11,1776},{4,11,419},{10,\n10,227},{11,10,497},{11,10,709},{140,10,415},{6,10,360},{7,10,1664},{136,10,478}\n,{137,0,806},{12,11,508},{14,11,102},{14,11,226},{144,11,57},{135,11,1123},{4,11\n,138},{7,11,1012},{7,11,1280},{137,11,76},{5,11,29},{140,11,638},{136,10,699},{\n134,0,1326},{132,0,104},{135,11,735},{132,10,739},{134,0,1331},{7,0,260},{135,11\n,260},{135,11,1063},{7,0,45},{9,0,542},{9,0,566},{10,0,728},{137,10,869},{4,10,\n67},{5,10,422},{7,10,1037},{7,10,1289},{7,10,1555},{9,10,741},{145,10,108},{139,\n0,263},{134,0,1516},{14,0,146},{15,0,42},{16,0,23},{17,0,86},{146,0,17},{138,0,\n468},{136,0,1005},{4,11,17},{5,11,23},{7,11,995},{11,11,383},{11,11,437},{12,11,\n460},{140,11,532},{7,0,87},{142,0,288},{138,10,96},{135,11,626},{144,10,26},{7,0\n,988},{7,0,1939},{9,0,64},{9,0,502},{12,0,22},{12,0,34},{13,0,12},{13,0,234},{\n147,0,77},{13,0,133},{8,10,203},{11,10,823},{11,10,846},{12,10,482},{13,10,277},\n{13,10,302},{13,10,464},{14,10,205},{142,10,221},{4,10,449},{133,10,718},{135,0,\n141},{6,0,1842},{136,0,872},{8,11,70},{12,11,171},{141,11,272},{4,10,355},{6,10,\n311},{9,10,256},{138,10,404},{132,0,619},{137,0,261},{10,11,233},{10,10,758},{\n139,11,76},{5,0,246},{8,0,189},{9,0,355},{9,0,512},{10,0,124},{10,0,453},{11,0,\n143},{11,0,416},{11,0,859},{141,0,341},{134,11,442},{133,10,827},{5,10,64},{140,\n10,581},{4,10,442},{7,10,1047},{7,10,1352},{135,10,1643},{134,11,1709},{5,0,678}\n,{6,0,305},{7,0,775},{7,0,1065},{133,10,977},{11,11,69},{12,11,105},{12,11,117},\n{13,11,213},{14,11,13},{14,11,62},{14,11,177},{14,11,421},{15,11,19},{146,11,141\n},{137,11,309},{5,0,35},{7,0,862},{7,0,1886},{138,0,179},{136,0,285},{132,0,517}\n,{7,11,976},{9,11,146},{10,11,206},{10,11,596},{13,11,218},{142,11,153},{132,10,\n254},{6,0,214},{12,0,540},{4,10,275},{7,10,1219},{140,10,376},{8,0,667},{11,0,\n403},{146,0,83},{12,0,74},{10,11,648},{11,11,671},{143,11,46},{135,0,125},{134,\n10,1753},{133,0,761},{6,0,912},{4,11,518},{6,10,369},{6,10,502},{7,10,1036},{7,\n11,1136},{8,10,348},{9,10,452},{10,10,26},{11,10,224},{11,10,387},{11,10,772},{\n12,10,95},{12,10,629},{13,10,195},{13,10,207},{13,10,241},{14,10,260},{14,10,270\n},{143,10,140},{10,0,131},{140,0,72},{132,10,269},{5,10,480},{7,10,532},{7,10,\n1197},{7,10,1358},{8,10,291},{11,10,349},{142,10,396},{8,11,689},{137,11,863},{8\n,0,333},{138,0,182},{4,11,18},{7,11,145},{7,11,444},{7,11,1278},{8,11,49},{8,11,\n400},{9,11,71},{9,11,250},{10,11,459},{12,11,160},{144,11,24},{14,11,35},{142,11\n,191},{135,11,1864},{135,0,1338},{148,10,15},{14,0,94},{15,0,65},{16,0,4},{16,0,\n77},{16,0,80},{145,0,5},{12,11,82},{143,11,36},{133,11,1010},{133,0,449},{133,0,\n646},{7,0,86},{8,0,103},{135,10,657},{7,0,2028},{138,0,641},{136,10,533},{134,0,\n1},{139,11,970},{5,11,87},{7,11,313},{7,11,1103},{10,11,112},{10,11,582},{11,11,\n389},{11,11,813},{12,11,385},{13,11,286},{14,11,124},{146,11,108},{6,0,869},{132\n,11,267},{6,0,277},{7,0,1274},{7,0,1386},{146,0,87},{6,0,187},{7,0,39},{7,0,1203\n},{8,0,380},{14,0,117},{149,0,28},{4,10,211},{4,10,332},{5,10,335},{6,10,238},{7\n,10,269},{7,10,811},{7,10,1797},{8,10,836},{9,10,507},{141,10,242},{4,0,785},{5,\n0,368},{6,0,297},{7,0,793},{139,0,938},{7,0,464},{8,0,558},{11,0,105},{12,0,231}\n,{14,0,386},{15,0,102},{148,0,75},{133,10,1009},{8,0,877},{140,0,731},{139,11,\n289},{10,11,249},{139,11,209},{132,11,561},{134,0,1608},{132,11,760},{134,0,1429\n},{9,11,154},{140,11,485},{5,10,228},{6,10,203},{7,10,156},{8,10,347},{137,10,\n265},{7,0,1010},{11,0,733},{11,0,759},{13,0,34},{14,0,427},{146,0,45},{7,10,1131\n},{135,10,1468},{136,11,255},{7,0,1656},{9,0,369},{10,0,338},{10,0,490},{11,0,\n154},{11,0,545},{11,0,775},{13,0,77},{141,0,274},{133,11,621},{134,0,1038},{4,11\n,368},{135,11,641},{6,0,2010},{8,0,979},{8,0,985},{10,0,951},{138,0,1011},{134,0\n,1005},{19,0,121},{5,10,291},{5,10,318},{7,10,765},{9,10,389},{140,10,548},{5,0,\n20},{6,0,298},{7,0,659},{137,0,219},{7,0,1440},{11,0,854},{11,0,872},{11,0,921},\n{12,0,551},{13,0,472},{142,0,367},{5,0,490},{6,0,615},{6,0,620},{135,0,683},{6,0\n,1070},{134,0,1597},{139,0,522},{132,0,439},{136,0,669},{6,0,766},{6,0,1143},{6,\n0,1245},{10,10,525},{139,10,82},{9,11,92},{147,11,91},{6,0,668},{134,0,1218},{6,\n11,525},{9,11,876},{140,11,284},{132,0,233},{136,0,547},{132,10,422},{5,10,355},\n{145,10,0},{6,11,300},{135,11,1515},{4,0,482},{137,10,905},{4,0,886},{7,0,346},{\n133,11,594},{133,10,865},{5,10,914},{134,10,1625},{135,0,334},{5,0,795},{6,0,\n1741},{133,10,234},{135,10,1383},{6,11,1641},{136,11,820},{135,0,371},{7,11,1313\n},{138,11,660},{135,10,1312},{135,0,622},{7,0,625},{135,0,1750},{135,0,339},{4,0\n,203},{135,0,1936},{15,0,29},{16,0,38},{15,11,29},{144,11,38},{5,0,338},{135,0,\n1256},{135,10,1493},{10,0,130},{6,10,421},{7,10,61},{7,10,1540},{138,10,501},{6,\n11,389},{7,11,149},{9,11,142},{138,11,94},{137,10,341},{11,0,678},{12,0,307},{\n142,10,98},{6,11,8},{7,11,1881},{136,11,91},{135,0,2044},{6,0,770},{6,0,802},{6,\n0,812},{7,0,311},{9,0,308},{12,0,255},{6,10,102},{7,10,72},{15,10,142},{147,10,\n67},{151,10,30},{135,10,823},{135,0,1266},{135,11,1746},{135,10,1870},{4,0,400},\n{5,0,267},{135,0,232},{7,11,24},{11,11,542},{139,11,852},{135,11,1739},{4,11,503\n},{135,11,1661},{5,11,130},{7,11,1314},{9,11,610},{10,11,718},{11,11,601},{11,11\n,819},{11,11,946},{140,11,536},{10,11,149},{11,11,280},{142,11,336},{7,0,739},{\n11,0,690},{7,11,1946},{8,10,48},{8,10,88},{8,10,582},{8,10,681},{9,10,373},{9,10\n,864},{11,10,157},{11,10,843},{148,10,27},{134,0,990},{4,10,88},{5,10,137},{5,10\n,174},{5,10,777},{6,10,1664},{6,10,1725},{7,10,77},{7,10,426},{7,10,1317},{7,10,\n1355},{8,10,126},{8,10,563},{9,10,523},{9,10,750},{10,10,310},{10,10,836},{11,10\n,42},{11,10,318},{11,10,731},{12,10,68},{12,10,92},{12,10,507},{12,10,692},{13,\n10,81},{13,10,238},{13,10,374},{14,10,436},{18,10,138},{19,10,78},{19,10,111},{\n20,10,55},{20,10,77},{148,10,92},{141,10,418},{7,0,1831},{132,10,938},{6,0,776},\n{134,0,915},{138,10,351},{5,11,348},{6,11,522},{6,10,1668},{7,10,1499},{8,10,117\n},{9,10,314},{138,10,174},{135,10,707},{132,0,613},{133,10,403},{132,11,392},{5,\n11,433},{9,11,633},{139,11,629},{133,0,763},{132,0,878},{132,0,977},{132,0,100},\n{6,0,463},{4,10,44},{5,10,311},{7,10,639},{7,10,762},{7,10,1827},{9,10,8},{9,10,\n462},{148,10,83},{134,11,234},{4,10,346},{7,10,115},{9,10,180},{9,10,456},{138,\n10,363},{5,0,362},{5,0,443},{6,0,318},{7,0,1019},{139,0,623},{5,0,463},{8,0,296}\n,{7,11,140},{7,11,1950},{8,11,680},{11,11,817},{147,11,88},{7,11,1222},{138,11,\n386},{142,0,137},{132,0,454},{7,0,1914},{6,11,5},{7,10,1051},{9,10,545},{11,11,\n249},{12,11,313},{16,11,66},{145,11,26},{135,0,1527},{145,0,58},{148,11,59},{5,0\n,48},{5,0,404},{6,0,557},{7,0,458},{8,0,597},{10,0,455},{10,0,606},{11,0,49},{11\n,0,548},{12,0,476},{13,0,18},{141,0,450},{5,11,963},{134,11,1773},{133,0,729},{\n138,11,586},{5,0,442},{135,0,1984},{134,0,449},{144,0,40},{4,0,853},{7,11,180},{\n8,11,509},{136,11,792},{6,10,185},{7,10,1899},{9,10,875},{139,10,673},{134,11,\n524},{12,0,227},{4,10,327},{5,10,478},{7,10,1332},{136,10,753},{6,0,1491},{5,10,\n1020},{133,10,1022},{4,10,103},{133,10,401},{132,11,931},{4,10,499},{135,10,1421\n},{5,0,55},{7,0,376},{140,0,161},{133,0,450},{6,0,1174},{134,0,1562},{10,0,62},{\n13,0,400},{135,11,1837},{140,0,207},{135,0,869},{4,11,773},{5,11,618},{137,11,\n756},{132,10,96},{4,0,213},{7,0,223},{8,0,80},{135,10,968},{4,11,90},{5,11,337},\n{5,11,545},{7,11,754},{9,11,186},{10,11,72},{10,11,782},{11,11,513},{11,11,577},\n{11,11,610},{11,11,889},{11,11,961},{12,11,354},{12,11,362},{12,11,461},{12,11,\n595},{13,11,79},{143,11,121},{7,0,381},{7,0,806},{7,0,820},{8,0,354},{8,0,437},{\n8,0,787},{9,0,657},{10,0,58},{10,0,339},{10,0,749},{11,0,914},{12,0,162},{13,0,\n75},{14,0,106},{14,0,198},{14,0,320},{14,0,413},{146,0,43},{136,0,747},{136,0,\n954},{134,0,1073},{135,0,556},{7,11,151},{9,11,329},{139,11,254},{5,0,692},{134,\n0,1395},{6,10,563},{137,10,224},{134,0,191},{132,0,804},{9,11,187},{10,11,36},{\n17,11,44},{146,11,64},{7,11,165},{7,11,919},{136,11,517},{4,11,506},{5,11,295},{\n7,11,1680},{15,11,14},{144,11,5},{4,0,706},{6,0,162},{7,0,1960},{136,0,831},{135\n,11,1376},{7,11,987},{9,11,688},{10,11,522},{11,11,788},{140,11,566},{150,0,35},\n{138,0,426},{135,0,1235},{135,11,1741},{7,11,389},{7,11,700},{7,11,940},{8,11,\n514},{9,11,116},{9,11,535},{10,11,118},{11,11,107},{11,11,148},{11,11,922},{12,\n11,254},{12,11,421},{142,11,238},{134,0,1234},{132,11,743},{4,10,910},{5,10,832}\n,{135,11,1335},{141,0,96},{135,11,185},{146,0,149},{4,0,204},{137,0,902},{4,11,\n784},{133,11,745},{136,0,833},{136,0,949},{7,0,366},{9,0,287},{12,0,199},{12,0,\n556},{12,0,577},{5,11,81},{7,11,146},{7,11,1342},{7,11,1446},{8,11,53},{8,11,561\n},{8,11,694},{8,11,754},{9,11,97},{9,11,115},{9,11,894},{10,11,462},{10,11,813},\n{11,11,230},{11,11,657},{11,11,699},{11,11,748},{12,11,119},{12,11,200},{12,11,\n283},{14,11,273},{145,11,15},{5,11,408},{137,11,747},{9,11,498},{140,11,181},{6,\n0,2020},{136,0,992},{5,0,356},{135,0,224},{134,0,784},{7,0,630},{9,0,567},{11,0,\n150},{11,0,444},{13,0,119},{8,10,528},{137,10,348},{134,0,539},{4,10,20},{133,10\n,616},{142,0,27},{7,11,30},{8,11,86},{8,11,315},{8,11,700},{9,11,576},{9,11,858}\n,{11,11,310},{11,11,888},{11,11,904},{12,11,361},{141,11,248},{138,11,839},{134,\n0,755},{134,0,1063},{7,10,1091},{135,10,1765},{134,11,428},{7,11,524},{8,11,169}\n,{8,11,234},{9,11,480},{138,11,646},{139,0,814},{7,11,1462},{139,11,659},{4,10,\n26},{5,10,429},{6,10,245},{7,10,704},{7,10,1379},{135,10,1474},{7,11,1205},{138,\n11,637},{139,11,803},{132,10,621},{136,0,987},{4,11,266},{8,11,4},{9,11,39},{10,\n11,166},{11,11,918},{12,11,635},{20,11,10},{22,11,27},{150,11,43},{4,0,235},{135\n,0,255},{4,0,194},{5,0,584},{6,0,384},{7,0,583},{10,0,761},{11,0,760},{139,0,851\n},{133,10,542},{134,0,1086},{133,10,868},{8,0,1016},{136,0,1018},{7,0,1396},{7,\n11,1396},{136,10,433},{135,10,1495},{138,10,215},{141,10,124},{7,11,157},{8,11,\n279},{9,11,759},{16,11,31},{16,11,39},{16,11,75},{18,11,24},{20,11,42},{152,11,1\n},{5,0,562},{134,11,604},{134,0,913},{5,0,191},{137,0,271},{4,0,470},{6,0,153},{\n7,0,1503},{7,0,1923},{10,0,701},{11,0,132},{11,0,227},{11,0,320},{11,0,436},{11,\n0,525},{11,0,855},{11,0,873},{12,0,41},{12,0,286},{13,0,103},{13,0,284},{14,0,\n255},{14,0,262},{15,0,117},{143,0,127},{7,0,475},{12,0,45},{147,10,112},{132,11,\n567},{137,11,859},{6,0,713},{6,0,969},{6,0,1290},{134,0,1551},{133,0,327},{6,0,\n552},{6,0,1292},{7,0,1754},{137,0,604},{4,0,223},{6,0,359},{11,0,3},{13,0,108},{\n14,0,89},{16,0,22},{5,11,762},{7,11,1880},{9,11,680},{139,11,798},{5,0,80},{6,0,\n405},{7,0,403},{7,0,1502},{8,0,456},{9,0,487},{9,0,853},{9,0,889},{10,0,309},{11\n,0,721},{11,0,994},{12,0,430},{141,0,165},{133,11,298},{132,10,647},{134,0,2016}\n,{18,10,10},{146,11,10},{4,0,453},{5,0,887},{6,0,535},{8,0,6},{8,0,543},{136,0,\n826},{136,0,975},{10,0,961},{138,0,962},{138,10,220},{6,0,1891},{6,0,1893},{9,0,\n916},{9,0,965},{9,0,972},{12,0,801},{12,0,859},{12,0,883},{15,0,226},{149,0,51},\n{132,10,109},{135,11,267},{7,11,92},{7,11,182},{8,11,453},{9,11,204},{11,11,950}\n,{12,11,94},{12,11,644},{16,11,20},{16,11,70},{16,11,90},{147,11,55},{134,10,\n1746},{6,11,71},{7,11,845},{7,11,1308},{8,11,160},{137,11,318},{5,0,101},{6,0,88\n},{7,0,263},{7,0,628},{7,0,1677},{8,0,349},{9,0,100},{10,0,677},{14,0,169},{14,0\n,302},{14,0,313},{15,0,48},{15,0,84},{7,11,237},{8,11,664},{9,11,42},{9,11,266},\n{9,11,380},{9,11,645},{10,11,177},{138,11,276},{138,11,69},{4,0,310},{7,0,708},{\n7,0,996},{9,0,795},{10,0,390},{10,0,733},{11,0,451},{12,0,249},{14,0,115},{14,0,\n286},{143,0,100},{5,0,587},{4,10,40},{10,10,67},{11,10,117},{11,10,768},{139,10,\n935},{6,0,1942},{7,0,512},{136,0,983},{7,10,992},{8,10,301},{9,10,722},{12,10,63\n},{13,10,29},{14,10,161},{143,10,18},{136,11,76},{139,10,923},{134,0,645},{134,0\n,851},{4,0,498},{132,11,293},{7,0,217},{8,0,140},{10,0,610},{14,11,352},{17,11,\n53},{18,11,146},{18,11,152},{19,11,11},{150,11,54},{134,0,1448},{138,11,841},{\n133,0,905},{4,11,605},{7,11,518},{7,11,1282},{7,11,1918},{10,11,180},{139,11,218\n},{139,11,917},{135,10,825},{140,10,328},{4,0,456},{7,0,105},{7,0,358},{7,0,1637\n},{8,0,643},{139,0,483},{134,0,792},{6,11,96},{135,11,1426},{137,11,691},{4,11,\n651},{133,11,289},{7,11,688},{8,11,35},{9,11,511},{10,11,767},{147,11,118},{150,\n0,56},{5,0,243},{5,0,535},{6,10,204},{10,10,320},{10,10,583},{13,10,502},{14,10,\n72},{14,10,274},{14,10,312},{14,10,344},{15,10,159},{16,10,62},{16,10,69},{17,10\n,30},{18,10,42},{18,10,53},{18,10,84},{18,10,140},{19,10,68},{19,10,85},{20,10,5\n},{20,10,45},{20,10,101},{22,10,7},{150,10,20},{4,10,558},{6,10,390},{7,10,162},\n{7,10,689},{9,10,360},{138,10,653},{146,11,23},{135,0,1748},{5,10,856},{6,10,\n1672},{6,10,1757},{134,10,1781},{5,0,539},{5,0,754},{6,0,876},{132,11,704},{135,\n11,1078},{5,10,92},{10,10,736},{140,10,102},{17,0,91},{5,10,590},{137,10,213},{\n134,0,1565},{6,0,91},{135,0,435},{4,0,939},{140,0,792},{134,0,1399},{4,0,16},{5,\n0,316},{5,0,842},{6,0,370},{6,0,1778},{8,0,166},{11,0,812},{12,0,206},{12,0,351}\n,{14,0,418},{16,0,15},{16,0,34},{18,0,3},{19,0,3},{19,0,7},{20,0,4},{21,0,21},{4\n,11,720},{133,11,306},{144,0,95},{133,11,431},{132,11,234},{135,0,551},{4,0,999}\n,{6,0,1966},{134,0,2042},{7,0,619},{10,0,547},{11,0,122},{12,0,601},{15,0,7},{\n148,0,20},{5,11,464},{6,11,236},{7,11,276},{7,11,696},{7,11,914},{7,11,1108},{7,\n11,1448},{9,11,15},{9,11,564},{10,11,14},{12,11,565},{13,11,449},{14,11,53},{15,\n11,13},{16,11,64},{145,11,41},{6,0,884},{6,0,1019},{134,0,1150},{6,11,1767},{12,\n11,194},{145,11,107},{136,10,503},{133,11,840},{7,0,671},{134,10,466},{132,0,888\n},{4,0,149},{138,0,368},{4,0,154},{7,0,1134},{136,0,105},{135,0,983},{9,11,642},\n{11,11,236},{142,11,193},{4,0,31},{6,0,429},{7,0,962},{9,0,458},{139,0,691},{6,0\n,643},{134,0,1102},{132,0,312},{4,11,68},{5,11,634},{6,11,386},{7,11,794},{8,11,\n273},{9,11,563},{10,11,105},{10,11,171},{11,11,94},{139,11,354},{133,0,740},{135\n,0,1642},{4,11,95},{7,11,416},{8,11,211},{139,11,830},{132,0,236},{138,10,241},{\n7,11,731},{13,11,20},{143,11,11},{5,0,836},{5,0,857},{6,0,1680},{135,0,59},{10,0\n,68},{11,0,494},{152,11,6},{4,0,81},{139,0,867},{135,0,795},{133,11,689},{4,0,\n1001},{5,0,282},{6,0,1932},{6,0,1977},{6,0,1987},{6,0,1992},{8,0,650},{8,0,919},\n{8,0,920},{8,0,923},{8,0,926},{8,0,927},{8,0,931},{8,0,939},{8,0,947},{8,0,956},\n{8,0,997},{9,0,907},{10,0,950},{10,0,953},{10,0,954},{10,0,956},{10,0,958},{10,0\n,959},{10,0,964},{10,0,970},{10,0,972},{10,0,973},{10,0,975},{10,0,976},{10,0,\n980},{10,0,981},{10,0,984},{10,0,988},{10,0,990},{10,0,995},{10,0,999},{10,0,\n1002},{10,0,1003},{10,0,1005},{10,0,1006},{10,0,1008},{10,0,1009},{10,0,1012},{\n10,0,1014},{10,0,1015},{10,0,1019},{10,0,1020},{10,0,1022},{12,0,959},{12,0,961}\n,{12,0,962},{12,0,963},{12,0,964},{12,0,965},{12,0,967},{12,0,968},{12,0,969},{\n12,0,970},{12,0,971},{12,0,972},{12,0,973},{12,0,974},{12,0,975},{12,0,976},{12,\n0,977},{12,0,979},{12,0,981},{12,0,982},{12,0,983},{12,0,984},{12,0,985},{12,0,\n986},{12,0,987},{12,0,989},{12,0,990},{12,0,992},{12,0,993},{12,0,995},{12,0,998\n},{12,0,999},{12,0,1000},{12,0,1001},{12,0,1002},{12,0,1004},{12,0,1005},{12,0,\n1006},{12,0,1007},{12,0,1008},{12,0,1009},{12,0,1010},{12,0,1011},{12,0,1012},{\n12,0,1014},{12,0,1015},{12,0,1016},{12,0,1017},{12,0,1018},{12,0,1019},{12,0,\n1022},{12,0,1023},{14,0,475},{14,0,477},{14,0,478},{14,0,479},{14,0,480},{14,0,\n482},{14,0,483},{14,0,484},{14,0,485},{14,0,486},{14,0,487},{14,0,488},{14,0,489\n},{14,0,490},{14,0,491},{14,0,492},{14,0,493},{14,0,494},{14,0,495},{14,0,496},{\n14,0,497},{14,0,498},{14,0,499},{14,0,500},{14,0,501},{14,0,502},{14,0,503},{14,\n0,504},{14,0,506},{14,0,507},{14,0,508},{14,0,509},{14,0,510},{14,0,511},{16,0,\n113},{16,0,114},{16,0,115},{16,0,117},{16,0,118},{16,0,119},{16,0,121},{16,0,122\n},{16,0,123},{16,0,124},{16,0,125},{16,0,126},{16,0,127},{18,0,242},{18,0,243},{\n18,0,244},{18,0,245},{18,0,248},{18,0,249},{18,0,250},{18,0,251},{18,0,252},{18,\n0,253},{18,0,254},{18,0,255},{20,0,125},{20,0,126},{148,0,127},{7,11,1717},{7,11\n,1769},{138,11,546},{7,11,1127},{7,11,1572},{10,11,297},{10,11,422},{11,11,764},\n{11,11,810},{12,11,264},{13,11,102},{13,11,300},{13,11,484},{14,11,147},{14,11,\n229},{17,11,71},{18,11,118},{147,11,120},{6,0,1148},{134,0,1586},{132,0,775},{\n135,10,954},{133,11,864},{133,11,928},{138,11,189},{135,10,1958},{6,10,549},{8,\n10,34},{8,10,283},{9,10,165},{138,10,475},{5,10,652},{5,10,701},{135,10,449},{\n135,11,695},{4,10,655},{7,10,850},{17,10,75},{146,10,137},{140,11,682},{133,11,\n523},{8,0,970},{136,10,670},{136,11,555},{7,11,76},{8,11,44},{9,11,884},{10,11,\n580},{11,11,399},{11,11,894},{15,11,122},{18,11,144},{147,11,61},{6,10,159},{6,\n10,364},{7,10,516},{7,10,1439},{137,10,518},{4,0,71},{5,0,376},{7,0,119},{138,0,\n665},{141,10,151},{11,0,827},{14,0,34},{143,0,148},{133,11,518},{4,0,479},{135,\n11,1787},{135,11,1852},{135,10,993},{7,0,607},{136,0,99},{134,0,1960},{132,0,793\n},{4,0,41},{5,0,74},{7,0,1627},{11,0,871},{140,0,619},{7,0,94},{11,0,329},{11,0,\n965},{12,0,241},{14,0,354},{15,0,22},{148,0,63},{7,10,501},{9,10,111},{10,10,141\n},{11,10,332},{13,10,43},{13,10,429},{14,10,130},{14,10,415},{145,10,102},{9,0,\n209},{137,0,300},{134,0,1497},{138,11,255},{4,11,934},{5,11,138},{136,11,610},{\n133,0,98},{6,0,1316},{10,11,804},{138,11,832},{8,11,96},{9,11,36},{10,11,607},{\n11,11,423},{11,11,442},{12,11,309},{14,11,199},{15,11,90},{145,11,110},{132,0,\n463},{5,10,149},{136,10,233},{133,10,935},{4,11,652},{8,11,320},{9,11,13},{9,11,\n398},{9,11,727},{10,11,75},{10,11,184},{10,11,230},{10,11,564},{10,11,569},{11,\n11,973},{12,11,70},{12,11,189},{13,11,57},{13,11,257},{22,11,6},{150,11,16},{142\n,0,291},{12,10,582},{146,10,131},{136,10,801},{133,0,984},{145,11,116},{4,11,692\n},{133,11,321},{4,0,182},{6,0,205},{135,0,220},{4,0,42},{9,0,205},{9,0,786},{138\n,0,659},{6,0,801},{11,11,130},{140,11,609},{132,0,635},{5,11,345},{135,11,1016},\n{139,0,533},{132,0,371},{4,0,272},{135,0,836},{6,0,1282},{135,11,1100},{5,0,825}\n,{134,0,1640},{135,11,1325},{133,11,673},{4,11,287},{133,11,1018},{135,0,357},{6\n,0,467},{137,0,879},{7,0,317},{135,0,569},{6,0,924},{134,0,1588},{5,11,34},{5,10\n,406},{10,11,724},{12,11,444},{13,11,354},{18,11,32},{23,11,24},{23,11,31},{152,\n11,5},{6,0,1795},{6,0,1835},{6,0,1836},{6,0,1856},{8,0,844},{8,0,849},{8,0,854},\n{8,0,870},{8,0,887},{10,0,852},{138,0,942},{6,10,69},{135,10,117},{137,0,307},{4\n,0,944},{6,0,1799},{6,0,1825},{10,0,848},{10,0,875},{10,0,895},{10,0,899},{10,0,\n902},{140,0,773},{11,0,43},{13,0,72},{141,0,142},{135,10,1830},{134,11,382},{4,\n10,432},{135,10,824},{132,11,329},{7,0,1820},{139,11,124},{133,10,826},{133,0,\n525},{132,11,906},{7,11,1940},{136,11,366},{138,11,10},{4,11,123},{4,11,649},{5,\n11,605},{7,11,1509},{136,11,36},{6,0,110},{135,0,1681},{133,0,493},{133,11,767},\n{4,0,174},{135,0,911},{138,11,786},{8,0,417},{137,0,782},{133,10,1000},{7,0,733}\n,{137,0,583},{4,10,297},{6,10,529},{7,10,152},{7,10,713},{7,10,1845},{8,10,710},\n{8,10,717},{12,10,639},{140,10,685},{4,0,32},{5,0,215},{6,0,269},{7,0,1782},{7,0\n,1892},{10,0,16},{11,0,822},{11,0,954},{141,0,481},{4,11,273},{5,11,658},{133,11\n,995},{136,0,477},{134,11,72},{135,11,1345},{5,0,308},{7,0,1088},{4,10,520},{135\n,10,575},{133,11,589},{5,0,126},{8,0,297},{9,0,366},{140,0,374},{7,0,1551},{139,\n0,361},{5,11,117},{6,11,514},{6,11,541},{7,11,1164},{7,11,1436},{8,11,220},{8,11\n,648},{10,11,688},{139,11,560},{133,11,686},{4,0,946},{6,0,1807},{8,0,871},{10,0\n,854},{10,0,870},{10,0,888},{10,0,897},{10,0,920},{12,0,722},{12,0,761},{12,0,\n763},{12,0,764},{14,0,454},{14,0,465},{16,0,107},{18,0,167},{18,0,168},{146,0,\n172},{132,0,175},{135,0,1307},{132,0,685},{135,11,1834},{133,0,797},{6,0,745},{6\n,0,858},{134,0,963},{133,0,565},{5,10,397},{6,10,154},{7,11,196},{7,10,676},{8,\n10,443},{8,10,609},{9,10,24},{9,10,325},{10,10,35},{10,11,765},{11,11,347},{11,\n10,535},{11,11,552},{11,11,576},{11,10,672},{11,11,790},{11,10,1018},{12,11,263}\n,{12,10,637},{13,11,246},{13,11,270},{13,11,395},{14,11,74},{14,11,176},{14,11,\n190},{14,11,398},{14,11,412},{15,11,32},{15,11,63},{16,10,30},{16,11,88},{147,11\n,105},{13,11,84},{141,11,122},{4,0,252},{7,0,1068},{10,0,434},{11,0,228},{11,0,\n426},{13,0,231},{18,0,106},{148,0,87},{137,0,826},{4,11,589},{139,11,282},{5,11,\n381},{135,11,1792},{132,0,791},{5,0,231},{10,0,509},{133,10,981},{7,0,601},{9,0,\n277},{9,0,674},{10,0,178},{10,0,418},{10,0,571},{11,0,531},{12,0,113},{12,0,475}\n,{13,0,99},{142,0,428},{4,10,56},{7,11,616},{7,10,1791},{8,10,607},{8,10,651},{\n10,11,413},{11,10,465},{11,10,835},{12,10,337},{141,10,480},{7,0,1591},{144,0,43\n},{9,10,158},{138,10,411},{135,0,1683},{8,0,289},{11,0,45},{12,0,278},{140,0,537\n},{6,11,120},{7,11,1188},{7,11,1710},{8,11,286},{9,11,667},{11,11,592},{139,11,\n730},{136,10,617},{135,0,1120},{135,11,1146},{139,10,563},{4,11,352},{4,10,369},\n{135,11,687},{143,11,38},{4,0,399},{5,0,119},{5,0,494},{7,0,751},{9,0,556},{14,\n11,179},{15,11,151},{150,11,11},{4,11,192},{5,11,49},{6,11,200},{6,11,293},{6,11\n,1696},{135,11,488},{4,0,398},{133,0,660},{7,0,1030},{134,10,622},{135,11,595},{\n141,0,168},{132,11,147},{7,0,973},{10,10,624},{142,10,279},{132,10,363},{132,0,\n642},{133,11,934},{134,0,1615},{7,11,505},{135,11,523},{7,0,594},{7,0,851},{7,0,\n1858},{9,0,411},{9,0,574},{9,0,666},{9,0,737},{10,0,346},{10,0,712},{11,0,246},{\n11,0,432},{11,0,517},{11,0,647},{11,0,679},{11,0,727},{12,0,304},{12,0,305},{12,\n0,323},{12,0,483},{12,0,572},{12,0,593},{12,0,602},{13,0,95},{13,0,101},{13,0,\n171},{13,0,315},{13,0,378},{13,0,425},{13,0,475},{14,0,63},{14,0,380},{14,0,384}\n,{15,0,133},{18,0,112},{148,0,72},{135,0,1093},{132,0,679},{8,0,913},{10,0,903},\n{10,0,915},{12,0,648},{12,0,649},{14,0,455},{16,0,112},{138,11,438},{137,0,203},\n{134,10,292},{134,0,1492},{7,0,1374},{8,0,540},{5,10,177},{6,10,616},{7,10,827},\n{9,10,525},{138,10,656},{135,0,1486},{9,0,714},{138,10,31},{136,0,825},{134,0,\n1511},{132,11,637},{134,0,952},{4,10,161},{133,10,631},{5,0,143},{5,0,769},{6,0,\n1760},{7,0,682},{7,0,1992},{136,0,736},{132,0,700},{134,0,1540},{132,11,777},{9,\n11,867},{138,11,837},{7,0,1557},{135,10,1684},{133,0,860},{6,0,422},{7,0,0},{7,0\n,1544},{9,0,605},{11,0,990},{12,0,235},{12,0,453},{13,0,47},{13,0,266},{9,10,469\n},{9,10,709},{12,10,512},{14,10,65},{145,10,12},{11,0,807},{10,10,229},{11,10,73\n},{139,10,376},{6,11,170},{7,11,1080},{8,11,395},{8,11,487},{11,11,125},{141,11,\n147},{5,0,515},{137,0,131},{7,0,1605},{11,0,962},{146,0,139},{132,0,646},{4,0,\n396},{7,0,728},{9,0,117},{13,0,202},{148,0,51},{6,0,121},{6,0,124},{6,0,357},{7,\n0,1138},{7,0,1295},{8,0,162},{8,0,508},{11,0,655},{4,11,535},{6,10,558},{7,10,\n651},{8,11,618},{9,10,0},{10,10,34},{139,10,1008},{135,11,1245},{138,0,357},{150\n,11,23},{133,0,237},{135,0,1784},{7,10,1832},{138,10,374},{132,0,713},{132,11,46\n},{6,0,1536},{10,0,348},{5,11,811},{6,11,1679},{6,11,1714},{135,11,2032},{11,11,\n182},{142,11,195},{6,0,523},{7,0,738},{7,10,771},{7,10,1731},{9,10,405},{138,10,\n421},{7,11,1458},{9,11,407},{139,11,15},{6,11,34},{7,11,69},{7,11,640},{7,11,\n1089},{8,11,708},{8,11,721},{9,11,363},{9,11,643},{10,11,628},{148,11,98},{133,0\n,434},{135,0,1877},{7,0,571},{138,0,366},{5,10,881},{133,10,885},{9,0,513},{10,0\n,25},{10,0,39},{12,0,122},{140,0,187},{132,0,580},{5,10,142},{134,10,546},{132,\n11,462},{137,0,873},{5,10,466},{11,10,571},{12,10,198},{13,10,283},{14,10,186},{\n15,10,21},{143,10,103},{7,0,171},{4,10,185},{5,10,257},{5,10,839},{5,10,936},{9,\n10,399},{10,10,258},{10,10,395},{10,10,734},{11,10,1014},{12,10,23},{13,10,350},\n{14,10,150},{147,10,6},{134,0,625},{7,0,107},{7,0,838},{8,0,550},{138,0,401},{5,\n11,73},{6,11,23},{134,11,338},{4,0,943},{6,0,1850},{12,0,713},{142,0,434},{11,0,\n588},{11,0,864},{11,0,936},{11,0,968},{12,0,73},{12,0,343},{12,0,394},{13,0,275}\n,{14,0,257},{15,0,160},{7,10,404},{7,10,1377},{7,10,1430},{7,10,2017},{8,10,149}\n,{8,10,239},{8,10,512},{8,10,793},{8,10,818},{9,10,474},{9,10,595},{10,10,122},{\n10,10,565},{10,10,649},{10,10,783},{11,10,239},{11,10,295},{11,10,447},{11,10,\n528},{11,10,639},{11,10,800},{12,10,25},{12,10,157},{12,10,316},{12,10,390},{12,\n10,391},{12,10,395},{12,10,478},{12,10,503},{12,10,592},{12,10,680},{13,10,50},{\n13,10,53},{13,10,132},{13,10,198},{13,10,322},{13,10,415},{13,10,511},{14,10,71}\n,{14,10,395},{15,10,71},{15,10,136},{17,10,123},{18,10,93},{147,10,58},{133,0,\n768},{11,0,103},{142,0,0},{136,10,712},{132,0,799},{132,0,894},{7,11,725},{8,11,\n498},{139,11,268},{135,11,1798},{135,11,773},{141,11,360},{4,10,377},{152,10,13}\n,{135,0,1673},{132,11,583},{134,0,1052},{133,11,220},{140,11,69},{132,11,544},{4\n,10,180},{135,10,1906},{134,0,272},{4,0,441},{134,0,1421},{4,0,9},{5,0,128},{7,0\n,368},{11,0,480},{148,0,3},{5,11,176},{6,11,437},{6,11,564},{11,11,181},{141,11,\n183},{132,10,491},{7,0,1182},{141,11,67},{6,0,1346},{4,10,171},{138,10,234},{4,\n10,586},{7,10,1186},{138,10,631},{136,0,682},{134,0,1004},{15,0,24},{143,11,24},\n{134,0,968},{4,0,2},{6,0,742},{6,0,793},{7,0,545},{7,0,894},{9,10,931},{10,10,\n334},{148,10,71},{136,11,600},{133,10,765},{9,0,769},{140,0,185},{4,11,790},{5,\n11,273},{134,11,394},{7,0,474},{137,0,578},{4,11,135},{6,11,127},{7,11,1185},{7,\n11,1511},{8,11,613},{11,11,5},{12,11,133},{12,11,495},{12,11,586},{14,11,385},{\n15,11,118},{17,11,20},{146,11,98},{133,10,424},{5,0,530},{142,0,113},{6,11,230},\n{7,11,961},{7,11,1085},{136,11,462},{7,11,1954},{137,11,636},{136,10,714},{149,\n11,6},{135,10,685},{9,10,420},{10,10,269},{10,10,285},{10,10,576},{11,10,397},{\n13,10,175},{145,10,90},{132,10,429},{5,0,556},{5,11,162},{136,11,68},{132,11,654\n},{4,11,156},{7,11,998},{7,11,1045},{7,11,1860},{9,11,48},{9,11,692},{11,11,419}\n,{139,11,602},{6,0,1317},{8,0,16},{9,0,825},{12,0,568},{7,11,1276},{8,11,474},{\n137,11,652},{18,0,97},{7,10,18},{7,10,699},{7,10,1966},{8,10,752},{9,10,273},{9,\n10,412},{9,10,703},{10,10,71},{10,10,427},{138,10,508},{10,0,703},{7,11,1454},{\n138,11,703},{4,10,53},{5,10,186},{135,10,752},{134,0,892},{134,0,1571},{8,10,575\n},{10,10,289},{139,10,319},{6,0,186},{137,0,426},{134,0,1101},{132,10,675},{132,\n0,585},{6,0,1870},{137,0,937},{152,11,10},{9,11,197},{10,11,300},{12,11,473},{13\n,11,90},{141,11,405},{4,0,93},{5,0,252},{6,0,229},{7,0,291},{9,0,550},{139,0,644\n},{137,0,749},{9,0,162},{6,10,209},{8,10,468},{9,10,210},{11,10,36},{12,10,28},{\n12,10,630},{13,10,21},{13,10,349},{14,10,7},{145,10,13},{132,0,381},{132,11,606}\n,{4,10,342},{135,10,1179},{7,11,1587},{7,11,1707},{10,11,528},{139,11,504},{12,\n11,39},{13,11,265},{141,11,439},{4,10,928},{133,10,910},{7,10,1838},{7,11,1978},\n{136,11,676},{6,0,762},{6,0,796},{134,0,956},{4,10,318},{4,10,496},{7,10,856},{\n139,10,654},{137,11,242},{4,11,361},{133,11,315},{132,11,461},{132,11,472},{132,\n0,857},{5,0,21},{6,0,77},{6,0,157},{7,0,974},{7,0,1301},{7,0,1339},{7,0,1490},{7\n,0,1873},{9,0,628},{7,10,915},{8,10,247},{147,10,0},{4,10,202},{5,10,382},{6,10,\n454},{7,10,936},{7,10,1803},{8,10,758},{9,10,375},{9,10,895},{10,10,743},{10,10,\n792},{11,10,978},{11,10,1012},{142,10,109},{7,11,617},{10,11,498},{11,11,501},{\n12,11,16},{140,11,150},{7,10,1150},{7,10,1425},{7,10,1453},{10,11,747},{140,10,\n513},{133,11,155},{11,0,919},{141,0,409},{138,10,791},{10,0,633},{139,11,729},{7\n,11,163},{8,11,319},{9,11,402},{10,11,24},{10,11,681},{11,11,200},{11,11,567},{\n12,11,253},{12,11,410},{142,11,219},{5,11,475},{7,11,1780},{9,11,230},{11,11,297\n},{11,11,558},{14,11,322},{147,11,76},{7,0,332},{6,10,445},{137,10,909},{135,11,\n1956},{136,11,274},{134,10,578},{135,0,1489},{135,11,1848},{5,11,944},{134,11,\n1769},{132,11,144},{136,10,766},{4,0,832},{135,10,541},{8,0,398},{9,0,681},{139,\n0,632},{136,0,645},{9,0,791},{10,0,93},{16,0,13},{17,0,23},{18,0,135},{19,0,12},\n{20,0,1},{20,0,12},{148,0,14},{6,11,247},{137,11,555},{134,0,20},{132,0,800},{\n135,0,1841},{139,10,983},{137,10,768},{132,10,584},{141,11,51},{6,0,1993},{4,11,\n620},{138,11,280},{136,0,769},{11,0,290},{11,0,665},{7,11,1810},{11,11,866},{12,\n11,103},{13,11,495},{17,11,67},{147,11,74},{134,0,1426},{139,0,60},{4,10,326},{\n135,10,1770},{7,0,1874},{9,0,641},{132,10,226},{6,0,644},{5,10,426},{8,10,30},{9\n,10,2},{11,10,549},{147,10,122},{5,11,428},{138,11,442},{135,11,1871},{135,0,\n1757},{147,10,117},{135,0,937},{135,0,1652},{6,0,654},{134,0,1476},{133,11,99},{\n135,0,527},{132,10,345},{4,10,385},{4,11,397},{7,10,265},{135,10,587},{4,0,579},\n{5,0,226},{5,0,323},{135,0,960},{134,0,1486},{8,11,502},{144,11,9},{4,10,347},{5\n,10,423},{5,10,996},{135,10,1329},{7,11,727},{146,11,73},{4,11,485},{7,11,353},{\n7,10,1259},{7,11,1523},{9,10,125},{139,10,65},{6,0,325},{5,10,136},{6,11,366},{7\n,11,1384},{7,11,1601},{136,10,644},{138,11,160},{6,0,1345},{137,11,282},{18,0,91\n},{147,0,70},{136,0,404},{4,11,157},{133,11,471},{133,0,973},{6,0,135},{135,0,\n1176},{8,11,116},{11,11,551},{142,11,159},{4,0,549},{4,10,433},{133,10,719},{136\n,0,976},{5,11,160},{7,11,363},{7,11,589},{10,11,170},{141,11,55},{144,0,21},{144\n,0,51},{135,0,314},{135,10,1363},{4,11,108},{7,11,405},{10,11,491},{139,11,498},\n{146,0,4},{4,10,555},{8,10,536},{10,10,288},{139,10,1005},{135,11,1005},{6,0,281\n},{7,0,6},{8,0,282},{8,0,480},{8,0,499},{9,0,198},{10,0,143},{10,0,169},{10,0,\n211},{10,0,417},{10,0,574},{11,0,147},{11,0,395},{12,0,75},{12,0,407},{12,0,608}\n,{13,0,500},{142,0,251},{6,0,1093},{6,0,1405},{9,10,370},{138,10,90},{4,11,926},\n{133,11,983},{135,0,1776},{134,0,1528},{132,0,419},{132,11,538},{6,11,294},{7,11\n,1267},{136,11,624},{135,11,1772},{138,11,301},{4,10,257},{135,10,2031},{4,0,138\n},{7,0,1012},{7,0,1280},{9,0,76},{135,10,1768},{132,11,757},{5,0,29},{140,0,638}\n,{7,11,655},{135,11,1844},{7,0,1418},{6,11,257},{135,11,1522},{8,11,469},{138,11\n,47},{142,11,278},{6,10,83},{6,10,1733},{135,10,1389},{11,11,204},{11,11,243},{\n140,11,293},{135,11,1875},{6,0,1710},{135,0,2038},{137,11,299},{4,0,17},{5,0,23}\n,{7,0,995},{11,0,383},{11,0,437},{12,0,460},{140,0,532},{133,0,862},{137,10,696}\n,{6,0,592},{138,0,946},{138,11,599},{7,10,1718},{9,10,95},{9,10,274},{10,10,279}\n,{10,10,317},{10,10,420},{11,10,303},{11,10,808},{12,10,134},{12,10,367},{13,10,\n149},{13,10,347},{14,10,349},{14,10,406},{18,10,22},{18,10,89},{18,10,122},{147,\n10,47},{8,0,70},{12,0,171},{141,0,272},{133,10,26},{132,10,550},{137,0,812},{10,\n0,233},{139,0,76},{134,0,988},{134,0,442},{136,10,822},{7,0,896},{4,10,902},{5,\n10,809},{134,10,122},{5,11,150},{7,11,106},{8,11,603},{9,11,593},{9,11,634},{10,\n11,44},{10,11,173},{11,11,462},{11,11,515},{13,11,216},{13,11,288},{142,11,400},\n{136,0,483},{135,10,262},{6,0,1709},{133,10,620},{4,10,34},{5,10,574},{7,10,279}\n,{7,10,1624},{136,10,601},{137,10,170},{147,0,119},{12,11,108},{141,11,291},{11,\n0,69},{12,0,105},{12,0,117},{13,0,213},{14,0,13},{14,0,62},{14,0,177},{14,0,421}\n,{15,0,19},{146,0,141},{137,0,309},{11,11,278},{142,11,73},{7,0,608},{7,0,976},{\n9,0,146},{10,0,206},{10,0,596},{13,0,218},{142,0,153},{133,10,332},{6,10,261},{8\n,10,182},{139,10,943},{4,11,493},{144,11,55},{134,10,1721},{132,0,768},{4,10,933\n},{133,10,880},{7,11,555},{7,11,1316},{7,11,1412},{7,11,1839},{9,11,192},{9,11,\n589},{11,11,241},{11,11,676},{11,11,811},{11,11,891},{12,11,140},{12,11,346},{12\n,11,479},{13,11,30},{13,11,49},{13,11,381},{14,11,188},{15,11,150},{16,11,76},{\n18,11,30},{148,11,52},{4,0,518},{135,0,1136},{6,11,568},{7,11,112},{7,11,1804},{\n8,11,362},{8,11,410},{8,11,830},{9,11,514},{11,11,649},{142,11,157},{135,11,673}\n,{8,0,689},{137,0,863},{4,0,18},{7,0,145},{7,0,444},{7,0,1278},{8,0,49},{8,0,400\n},{9,0,71},{9,0,250},{10,0,459},{12,0,160},{16,0,24},{132,11,625},{140,0,1020},{\n4,0,997},{6,0,1946},{6,0,1984},{134,0,1998},{6,11,16},{6,11,158},{7,11,43},{7,11\n,129},{7,11,181},{8,11,276},{8,11,377},{10,11,523},{11,11,816},{12,11,455},{13,\n11,303},{142,11,135},{133,10,812},{134,0,658},{4,11,1},{7,11,1143},{7,11,1463},{\n8,11,61},{9,11,207},{9,11,390},{9,11,467},{139,11,836},{150,11,26},{140,0,106},{\n6,0,1827},{10,0,931},{18,0,166},{20,0,114},{4,10,137},{7,10,1178},{7,11,1319},{\n135,10,1520},{133,0,1010},{4,11,723},{5,11,895},{7,11,1031},{8,11,199},{8,11,340\n},{9,11,153},{9,11,215},{10,11,21},{10,11,59},{10,11,80},{10,11,224},{11,11,229}\n,{11,11,652},{12,11,192},{13,11,146},{142,11,91},{132,11,295},{6,11,619},{7,11,\n898},{7,11,1092},{8,11,485},{18,11,28},{147,11,116},{137,11,51},{6,10,1661},{7,\n10,1975},{7,10,2009},{135,10,2011},{5,11,309},{140,11,211},{5,0,87},{7,0,313},{7\n,0,1103},{10,0,208},{10,0,582},{11,0,389},{11,0,813},{12,0,385},{13,0,286},{14,0\n,124},{146,0,108},{5,11,125},{8,11,77},{138,11,15},{132,0,267},{133,0,703},{137,\n11,155},{133,11,439},{11,11,164},{140,11,76},{9,0,496},{5,10,89},{7,10,1915},{9,\n10,185},{9,10,235},{10,10,64},{10,10,270},{10,10,403},{10,10,469},{10,10,529},{\n10,10,590},{11,10,140},{11,10,860},{13,10,1},{13,10,422},{14,10,341},{14,10,364}\n,{17,10,93},{18,10,113},{19,10,97},{147,10,113},{133,10,695},{135,0,1121},{5,10,\n6},{6,10,183},{7,10,680},{7,10,978},{7,10,1013},{7,10,1055},{12,10,230},{13,10,\n172},{146,10,29},{4,11,8},{7,11,1152},{7,11,1153},{7,11,1715},{9,11,374},{10,11,\n478},{139,11,648},{135,11,1099},{6,10,29},{139,10,63},{4,0,561},{10,0,249},{139,\n0,209},{132,0,760},{7,11,799},{138,11,511},{136,11,87},{9,0,154},{140,0,485},{\n136,0,255},{132,0,323},{140,0,419},{132,10,311},{134,10,1740},{4,0,368},{135,0,\n641},{7,10,170},{8,10,90},{8,10,177},{8,10,415},{11,10,714},{142,10,281},{4,11,\n69},{5,11,122},{9,11,656},{138,11,464},{5,11,849},{134,11,1633},{8,0,522},{142,0\n,328},{11,10,91},{13,10,129},{15,10,101},{145,10,125},{7,0,562},{8,0,551},{4,10,\n494},{6,10,74},{7,10,44},{11,11,499},{12,10,17},{15,10,5},{148,10,11},{4,10,276}\n,{133,10,296},{9,0,92},{147,0,91},{4,10,7},{5,10,90},{5,10,158},{6,10,542},{7,10\n,221},{7,10,1574},{9,10,490},{10,10,540},{11,10,443},{139,10,757},{6,0,525},{6,0\n,1976},{8,0,806},{9,0,876},{140,0,284},{5,11,859},{7,10,588},{7,11,1160},{8,11,\n107},{9,10,175},{9,11,291},{9,11,439},{10,10,530},{10,11,663},{11,11,609},{140,\n11,197},{7,11,168},{13,11,196},{141,11,237},{139,0,958},{133,0,594},{135,10,580}\n,{7,10,88},{136,10,627},{6,0,479},{6,0,562},{7,0,1060},{13,0,6},{5,10,872},{6,10\n,57},{7,10,471},{9,10,447},{137,10,454},{136,11,413},{145,11,19},{4,11,117},{6,\n11,372},{7,11,1905},{142,11,323},{4,11,722},{139,11,471},{17,0,61},{5,10,31},{\n134,10,614},{8,10,330},{140,10,477},{7,10,1200},{138,10,460},{6,10,424},{135,10,\n1866},{6,0,1641},{136,0,820},{6,0,1556},{134,0,1618},{9,11,5},{12,11,216},{12,11\n,294},{12,11,298},{12,11,400},{12,11,518},{13,11,229},{143,11,139},{15,11,155},{\n144,11,79},{4,0,302},{135,0,1766},{5,10,13},{134,10,142},{6,0,148},{7,0,1313},{7\n,10,116},{8,10,322},{8,10,755},{9,10,548},{10,10,714},{11,10,884},{141,10,324},{\n137,0,676},{9,11,88},{139,11,270},{5,11,12},{7,11,375},{137,11,438},{134,0,1674}\n,{7,10,1472},{135,10,1554},{11,0,178},{7,10,1071},{7,10,1541},{7,10,1767},{7,10,\n1806},{11,10,162},{11,10,242},{12,10,605},{15,10,26},{144,10,44},{6,0,389},{7,0,\n149},{9,0,142},{138,0,94},{140,11,71},{145,10,115},{6,0,8},{7,0,1881},{8,0,91},{\n11,11,966},{12,11,287},{13,11,342},{13,11,402},{15,11,110},{143,11,163},{4,11,\n258},{136,11,639},{6,11,22},{7,11,903},{138,11,577},{133,11,681},{135,10,1111},{\n135,11,1286},{9,0,112},{8,10,1},{138,10,326},{5,10,488},{6,10,527},{7,10,489},{7\n,10,1636},{8,10,121},{8,10,144},{8,10,359},{9,10,193},{9,10,241},{9,10,336},{9,\n10,882},{11,10,266},{11,10,372},{11,10,944},{12,10,401},{140,10,641},{4,11,664},\n{133,11,804},{6,0,747},{134,0,1015},{135,0,1746},{9,10,31},{10,10,244},{10,10,\n699},{12,10,149},{141,10,497},{133,10,377},{135,0,24},{6,0,1352},{5,11,32},{145,\n10,101},{7,0,1530},{10,0,158},{13,0,13},{13,0,137},{13,0,258},{14,0,111},{14,0,\n225},{14,0,253},{14,0,304},{14,0,339},{14,0,417},{146,0,33},{4,0,503},{135,0,\n1661},{5,0,130},{6,0,845},{7,0,1314},{9,0,610},{10,0,718},{11,0,601},{11,0,819},\n{11,0,946},{140,0,536},{10,0,149},{11,0,280},{142,0,336},{134,0,1401},{135,0,\n1946},{8,0,663},{144,0,8},{134,0,1607},{135,10,2023},{4,11,289},{7,11,629},{7,11\n,1698},{7,11,1711},{140,11,215},{6,11,450},{136,11,109},{10,0,882},{10,0,883},{\n10,0,914},{138,0,928},{133,10,843},{136,11,705},{132,10,554},{133,10,536},{5,0,\n417},{9,10,79},{11,10,625},{145,10,7},{7,11,1238},{142,11,37},{4,0,392},{135,0,\n1597},{5,0,433},{9,0,633},{11,0,629},{132,10,424},{7,10,336},{136,10,785},{134,\n11,355},{6,0,234},{7,0,769},{9,0,18},{138,0,358},{4,10,896},{134,10,1777},{138,\n11,323},{7,0,140},{7,0,1950},{8,0,680},{11,0,817},{147,0,88},{7,0,1222},{138,0,\n386},{139,11,908},{11,0,249},{12,0,313},{16,0,66},{145,0,26},{134,0,5},{7,10,750\n},{9,10,223},{11,10,27},{11,10,466},{12,10,624},{14,10,265},{146,10,61},{134,11,\n26},{134,0,1216},{5,0,963},{134,0,1773},{4,11,414},{5,11,467},{9,11,654},{10,11,\n451},{12,11,59},{141,11,375},{135,11,17},{4,10,603},{133,10,661},{4,10,11},{6,10\n,128},{7,10,231},{7,10,1533},{138,10,725},{135,11,955},{7,0,180},{8,0,509},{136,\n0,792},{132,10,476},{132,0,1002},{133,11,538},{135,10,1807},{132,0,931},{7,0,943\n},{11,0,614},{140,0,747},{135,0,1837},{9,10,20},{10,10,324},{10,10,807},{139,10,\n488},{134,0,641},{6,11,280},{10,11,502},{11,11,344},{140,11,38},{5,11,45},{7,11,\n1161},{11,11,448},{11,11,880},{13,11,139},{13,11,407},{15,11,16},{17,11,95},{18,\n11,66},{18,11,88},{18,11,123},{149,11,7},{9,0,280},{138,0,134},{22,0,22},{23,0,5\n},{151,0,29},{136,11,777},{4,0,90},{5,0,545},{7,0,754},{9,0,186},{10,0,72},{10,0\n,782},{11,0,577},{11,0,610},{11,0,960},{12,0,354},{12,0,362},{12,0,595},{4,11,\n410},{135,11,521},{135,11,1778},{5,10,112},{6,10,103},{134,10,150},{138,10,356},\n{132,0,742},{7,0,151},{9,0,329},{139,0,254},{8,0,853},{8,0,881},{8,0,911},{8,0,\n912},{10,0,872},{12,0,741},{12,0,742},{152,0,18},{4,11,573},{136,11,655},{6,0,\n921},{134,0,934},{9,0,187},{10,0,36},{11,0,1016},{17,0,44},{146,0,64},{7,0,833},\n{136,0,517},{4,0,506},{5,0,295},{135,0,1680},{4,10,708},{8,10,15},{9,10,50},{9,\n10,386},{11,10,18},{11,10,529},{140,10,228},{7,0,251},{7,0,1701},{8,0,436},{4,10\n,563},{7,10,592},{7,10,637},{7,10,770},{8,10,463},{9,10,60},{9,10,335},{9,10,904\n},{10,10,73},{11,10,434},{12,10,585},{13,10,331},{18,10,110},{148,10,60},{132,10\n,502},{136,0,584},{6,10,347},{138,10,161},{7,0,987},{9,0,688},{10,0,522},{11,0,\n788},{12,0,137},{12,0,566},{14,0,9},{14,0,24},{14,0,64},{7,11,899},{142,11,325},\n{4,0,214},{5,0,500},{5,10,102},{6,10,284},{7,10,1079},{7,10,1423},{7,10,1702},{8\n,10,470},{9,10,554},{9,10,723},{139,10,333},{7,10,246},{135,10,840},{6,10,10},{8\n,10,571},{9,10,739},{143,10,91},{133,10,626},{146,0,195},{134,0,1775},{7,0,389},\n{7,0,700},{7,0,940},{8,0,514},{9,0,116},{9,0,535},{10,0,118},{11,0,107},{11,0,\n148},{11,0,922},{12,0,254},{12,0,421},{142,0,238},{5,10,18},{6,10,526},{13,10,24\n},{13,10,110},{19,10,5},{147,10,44},{132,0,743},{11,0,292},{4,10,309},{5,10,462}\n,{7,10,970},{135,10,1097},{22,10,30},{150,10,33},{139,11,338},{135,11,1598},{7,0\n,1283},{9,0,227},{11,0,325},{11,0,408},{14,0,180},{146,0,47},{4,0,953},{6,0,1805\n},{6,0,1814},{6,0,1862},{140,0,774},{6,11,611},{135,11,1733},{135,11,1464},{5,0,\n81},{7,0,146},{7,0,1342},{8,0,53},{8,0,561},{8,0,694},{8,0,754},{9,0,115},{9,0,\n179},{9,0,894},{10,0,462},{10,0,813},{11,0,230},{11,0,657},{11,0,699},{11,0,748}\n,{12,0,119},{12,0,200},{12,0,283},{142,0,273},{5,0,408},{6,0,789},{6,0,877},{6,0\n,1253},{6,0,1413},{137,0,747},{134,10,1704},{135,11,663},{6,0,1910},{6,0,1915},{\n6,0,1923},{9,0,913},{9,0,928},{9,0,950},{9,0,954},{9,0,978},{9,0,993},{12,0,812}\n,{12,0,819},{12,0,831},{12,0,833},{12,0,838},{12,0,909},{12,0,928},{12,0,931},{\n12,0,950},{15,0,186},{15,0,187},{15,0,195},{15,0,196},{15,0,209},{15,0,215},{15,\n0,236},{15,0,241},{15,0,249},{15,0,253},{18,0,180},{18,0,221},{18,0,224},{18,0,\n227},{18,0,229},{149,0,60},{7,0,1826},{135,0,1938},{11,0,490},{18,0,143},{5,10,\n86},{7,10,743},{9,10,85},{10,10,281},{10,10,432},{12,10,251},{13,10,118},{142,10\n,378},{5,10,524},{133,10,744},{141,11,442},{10,10,107},{140,10,436},{135,11,503}\n,{134,0,1162},{132,10,927},{7,0,30},{8,0,86},{8,0,315},{8,0,700},{9,0,576},{9,0,\n858},{10,0,414},{11,0,310},{11,0,888},{11,0,904},{12,0,361},{13,0,248},{13,0,371\n},{14,0,142},{12,10,670},{146,10,94},{134,0,721},{4,11,113},{5,11,163},{5,11,735\n},{7,11,1009},{7,10,1149},{9,11,9},{9,10,156},{9,11,771},{12,11,90},{13,11,138},\n{13,11,410},{143,11,128},{138,0,839},{133,10,778},{137,0,617},{133,10,502},{8,10\n,196},{10,10,283},{139,10,406},{6,0,428},{7,0,524},{8,0,169},{8,0,234},{9,0,480}\n,{138,0,646},{133,10,855},{134,0,1648},{7,0,1205},{138,0,637},{7,0,1596},{4,11,\n935},{133,11,823},{5,11,269},{7,11,434},{7,11,891},{8,11,339},{9,11,702},{11,11,\n594},{11,11,718},{145,11,100},{7,11,878},{9,11,485},{141,11,264},{4,0,266},{8,0,\n4},{9,0,39},{10,0,166},{11,0,918},{12,0,635},{20,0,10},{22,0,27},{22,0,43},{22,0\n,52},{134,11,1713},{7,10,1400},{9,10,446},{138,10,45},{135,11,900},{132,0,862},{\n134,0,1554},{135,11,1033},{19,0,16},{147,11,16},{135,11,1208},{7,0,157},{136,0,\n279},{6,0,604},{136,0,391},{13,10,455},{15,10,99},{15,10,129},{144,10,68},{135,\n10,172},{7,0,945},{11,0,713},{139,0,744},{4,0,973},{10,0,877},{10,0,937},{10,0,\n938},{140,0,711},{139,0,1022},{132,10,568},{142,11,143},{4,0,567},{9,0,859},{132\n,10,732},{7,0,1846},{136,0,628},{136,10,733},{133,0,762},{4,10,428},{135,10,1789\n},{10,0,784},{13,0,191},{7,10,2015},{140,10,665},{133,0,298},{7,0,633},{7,0,905}\n,{7,0,909},{7,0,1538},{9,0,767},{140,0,636},{138,10,806},{132,0,795},{139,0,301}\n,{135,0,1970},{5,11,625},{135,11,1617},{135,11,275},{7,11,37},{8,11,425},{8,11,\n693},{9,11,720},{10,11,380},{10,11,638},{11,11,273},{11,11,307},{11,11,473},{12,\n11,61},{143,11,43},{135,11,198},{134,0,1236},{7,0,369},{12,0,644},{12,0,645},{\n144,0,90},{19,0,15},{149,0,27},{6,0,71},{7,0,845},{8,0,160},{9,0,318},{6,10,1623\n},{134,10,1681},{134,0,1447},{134,0,1255},{138,0,735},{8,0,76},{132,11,168},{6,\n10,1748},{8,10,715},{9,10,802},{10,10,46},{10,10,819},{13,10,308},{14,10,351},{\n14,10,363},{146,10,67},{135,11,91},{6,0,474},{4,10,63},{133,10,347},{133,10,749}\n,{138,0,841},{133,10,366},{6,0,836},{132,11,225},{135,0,1622},{135,10,89},{140,0\n,735},{134,0,1601},{138,11,145},{6,0,1390},{137,0,804},{142,0,394},{6,11,15},{7,\n11,70},{10,11,240},{147,11,93},{6,0,96},{135,0,1426},{4,0,651},{133,0,289},{7,11\n,956},{7,10,977},{7,11,1157},{7,11,1506},{7,11,1606},{7,11,1615},{7,11,1619},{7,\n11,1736},{7,11,1775},{8,11,590},{9,11,324},{9,11,736},{9,11,774},{9,11,776},{9,\n11,784},{10,11,567},{10,11,708},{11,11,518},{11,11,613},{11,11,695},{11,11,716},\n{11,11,739},{11,11,770},{11,11,771},{11,11,848},{11,11,857},{11,11,931},{11,11,\n947},{12,11,326},{12,11,387},{12,11,484},{12,11,528},{12,11,552},{12,11,613},{13\n,11,189},{13,11,256},{13,11,340},{13,11,432},{13,11,436},{13,11,440},{13,11,454}\n,{14,11,174},{14,11,220},{14,11,284},{14,11,390},{145,11,121},{7,0,688},{8,0,35}\n,{9,0,511},{10,0,767},{147,0,118},{134,0,667},{4,0,513},{5,10,824},{133,10,941},\n{7,10,440},{8,10,230},{139,10,106},{134,0,2034},{135,11,1399},{143,11,66},{135,\n11,1529},{4,11,145},{6,11,176},{7,11,395},{9,11,562},{144,11,28},{132,11,501},{\n132,0,704},{134,0,1524},{7,0,1078},{134,11,464},{6,11,509},{10,11,82},{20,11,91}\n,{151,11,13},{4,0,720},{133,0,306},{133,0,431},{7,0,1196},{4,10,914},{5,10,800},\n{133,10,852},{135,11,1189},{10,0,54},{141,10,115},{7,10,564},{142,10,168},{5,0,\n464},{6,0,236},{7,0,696},{7,0,914},{7,0,1108},{7,0,1448},{9,0,15},{9,0,564},{10,\n0,14},{12,0,565},{13,0,449},{14,0,53},{15,0,13},{16,0,64},{17,0,41},{4,10,918},{\n133,10,876},{6,0,1418},{134,10,1764},{4,10,92},{133,10,274},{134,0,907},{4,11,\n114},{8,10,501},{9,11,492},{13,11,462},{142,11,215},{4,11,77},{5,11,361},{6,11,\n139},{6,11,401},{6,11,404},{7,11,413},{7,11,715},{7,11,1716},{11,11,279},{12,11,\n179},{12,11,258},{13,11,244},{142,11,358},{6,0,1767},{12,0,194},{145,0,107},{134\n,11,1717},{5,10,743},{142,11,329},{4,10,49},{7,10,280},{135,10,1633},{5,0,840},{\n7,11,1061},{8,11,82},{11,11,250},{12,11,420},{141,11,184},{135,11,724},{134,0,\n900},{136,10,47},{134,0,1436},{144,11,0},{6,0,675},{7,0,1008},{7,0,1560},{9,0,\n642},{11,0,236},{14,0,193},{5,10,272},{5,10,908},{5,10,942},{8,10,197},{9,10,47}\n,{11,10,538},{139,10,742},{4,0,68},{5,0,628},{5,0,634},{6,0,386},{7,0,794},{8,0,\n273},{9,0,563},{10,0,105},{10,0,171},{11,0,94},{139,0,354},{135,10,1911},{137,10\n,891},{4,0,95},{6,0,1297},{6,0,1604},{7,0,416},{139,0,830},{6,11,513},{135,11,\n1052},{7,0,731},{13,0,20},{143,0,11},{137,11,899},{10,0,850},{140,0,697},{4,0,\n662},{7,11,1417},{12,11,382},{17,11,48},{152,11,12},{133,0,736},{132,0,861},{4,\n10,407},{132,10,560},{141,10,490},{6,11,545},{7,11,565},{7,11,1669},{10,11,114},\n{11,11,642},{140,11,618},{6,0,871},{134,0,1000},{5,0,864},{10,0,648},{11,0,671},\n{15,0,46},{133,11,5},{133,0,928},{11,0,90},{13,0,7},{4,10,475},{11,10,35},{13,10\n,71},{13,10,177},{142,10,422},{136,0,332},{135,11,192},{134,0,1055},{136,11,763}\n,{11,0,986},{140,0,682},{7,0,76},{8,0,44},{9,0,884},{10,0,580},{11,0,399},{11,0,\n894},{143,0,122},{135,11,1237},{135,10,636},{11,0,300},{6,10,222},{7,10,1620},{8\n,10,409},{137,10,693},{4,11,87},{5,11,250},{10,11,601},{13,11,298},{13,11,353},{\n141,11,376},{5,0,518},{10,0,340},{11,0,175},{149,0,16},{140,0,771},{6,0,1108},{\n137,0,831},{132,0,836},{135,0,1852},{4,0,957},{6,0,1804},{8,0,842},{8,0,843},{8,\n0,851},{8,0,855},{140,0,767},{135,11,814},{4,11,57},{7,11,1195},{7,11,1438},{7,\n11,1548},{7,11,1835},{7,11,1904},{9,11,757},{10,11,604},{139,11,519},{133,10,882\n},{138,0,246},{4,0,934},{5,0,202},{8,0,610},{7,11,1897},{12,11,290},{13,11,80},{\n13,11,437},{145,11,74},{8,0,96},{9,0,36},{10,0,607},{10,0,804},{10,0,832},{11,0,\n423},{11,0,442},{12,0,309},{14,0,199},{15,0,90},{145,0,110},{132,10,426},{7,0,\n654},{8,0,240},{6,10,58},{7,10,745},{7,10,1969},{8,10,675},{9,10,479},{9,10,731}\n,{10,10,330},{10,10,593},{10,10,817},{11,10,32},{11,10,133},{11,10,221},{145,10,\n68},{9,0,13},{9,0,398},{9,0,727},{10,0,75},{10,0,184},{10,0,230},{10,0,564},{10,\n0,569},{11,0,973},{12,0,70},{12,0,189},{13,0,57},{141,0,257},{4,11,209},{135,11,\n902},{7,0,391},{137,10,538},{134,0,403},{6,11,303},{7,11,335},{7,11,1437},{7,11,\n1668},{8,11,553},{8,11,652},{8,11,656},{9,11,558},{11,11,743},{149,11,18},{132,\n11,559},{11,0,75},{142,0,267},{6,0,815},{141,11,2},{141,0,366},{137,0,631},{133,\n11,1017},{5,0,345},{135,0,1016},{133,11,709},{134,11,1745},{133,10,566},{7,0,952\n},{6,10,48},{9,10,139},{10,10,399},{11,10,469},{12,10,634},{141,10,223},{133,0,\n673},{9,0,850},{7,11,8},{136,11,206},{6,0,662},{149,0,35},{4,0,287},{133,0,1018}\n,{6,10,114},{7,10,1224},{7,10,1556},{136,10,3},{8,10,576},{137,10,267},{4,0,884}\n,{5,0,34},{10,0,724},{12,0,444},{13,0,354},{18,0,32},{23,0,24},{23,0,31},{152,0,\n5},{133,10,933},{132,11,776},{138,0,151},{136,0,427},{134,0,382},{132,0,329},{9,\n0,846},{10,0,827},{138,11,33},{9,0,279},{10,0,407},{14,0,84},{22,0,18},{135,11,\n1297},{136,11,406},{132,0,906},{136,0,366},{134,0,843},{134,0,1443},{135,0,1372}\n,{138,0,992},{4,0,123},{5,0,605},{7,0,1509},{136,0,36},{132,0,649},{8,11,175},{\n10,11,168},{138,11,573},{133,0,767},{134,0,1018},{135,11,1305},{12,10,30},{13,10\n,148},{14,10,87},{14,10,182},{16,10,42},{148,10,70},{134,11,607},{4,0,273},{5,0,\n658},{133,0,995},{6,0,72},{139,11,174},{10,0,483},{12,0,368},{7,10,56},{7,10,\n1989},{8,10,337},{8,10,738},{9,10,600},{13,10,447},{142,10,92},{5,11,784},{138,\n10,666},{135,0,1345},{139,11,882},{134,0,1293},{133,0,589},{134,0,1988},{5,0,117\n},{6,0,514},{6,0,541},{7,0,1164},{7,0,1436},{8,0,220},{8,0,648},{10,0,688},{139,\n0,560},{136,0,379},{5,0,686},{7,10,866},{135,10,1163},{132,10,328},{9,11,14},{9,\n11,441},{10,11,306},{139,11,9},{4,10,101},{135,10,1171},{5,10,833},{136,10,744},\n{5,11,161},{7,11,839},{135,11,887},{7,0,196},{10,0,765},{11,0,347},{11,0,552},{\n11,0,790},{12,0,263},{13,0,246},{13,0,270},{13,0,395},{14,0,176},{14,0,190},{14,\n0,398},{14,0,412},{15,0,32},{15,0,63},{16,0,88},{147,0,105},{6,10,9},{6,10,397},\n{7,10,53},{7,10,1742},{10,10,632},{11,10,828},{140,10,146},{5,0,381},{135,0,1792\n},{134,0,1452},{135,11,429},{8,0,367},{10,0,760},{14,0,79},{20,0,17},{152,0,0},{\n7,0,616},{138,0,413},{11,10,417},{12,10,223},{140,10,265},{7,11,1611},{13,11,14}\n,{15,11,44},{19,11,13},{148,11,76},{135,0,1229},{6,0,120},{7,0,1188},{7,0,1710},\n{8,0,286},{9,0,667},{11,0,592},{139,0,730},{135,11,1814},{135,0,1146},{4,10,186}\n,{5,10,157},{8,10,168},{138,10,6},{4,0,352},{135,0,687},{4,0,192},{5,0,49},{6,0,\n200},{6,0,293},{6,0,1696},{135,0,1151},{133,10,875},{5,10,773},{5,10,991},{6,10,\n1635},{134,10,1788},{7,10,111},{136,10,581},{6,0,935},{134,0,1151},{134,0,1050},\n{132,0,650},{132,0,147},{11,0,194},{12,0,62},{12,0,88},{11,11,194},{12,11,62},{\n140,11,88},{6,0,339},{135,0,923},{134,10,1747},{7,11,643},{136,11,236},{133,0,\n934},{7,10,1364},{7,10,1907},{141,10,158},{132,10,659},{4,10,404},{135,10,675},{\n7,11,581},{9,11,644},{137,11,699},{13,0,211},{14,0,133},{14,0,204},{15,0,64},{15\n,0,69},{15,0,114},{16,0,10},{19,0,23},{19,0,35},{19,0,39},{19,0,51},{19,0,71},{\n19,0,75},{152,0,15},{133,10,391},{5,11,54},{135,11,1513},{7,0,222},{8,0,341},{5,\n10,540},{134,10,1697},{134,10,78},{132,11,744},{136,0,293},{137,11,701},{7,11,\n930},{10,11,402},{10,11,476},{13,11,452},{18,11,55},{147,11,104},{132,0,637},{\n133,10,460},{8,11,50},{137,11,624},{132,11,572},{134,0,1159},{4,10,199},{139,10,\n34},{134,0,847},{134,10,388},{6,11,43},{7,11,38},{8,11,248},{9,11,504},{138,11,\n513},{9,0,683},{4,10,511},{6,10,608},{9,10,333},{10,10,602},{11,10,441},{11,10,\n723},{11,10,976},{140,10,357},{9,0,867},{138,0,837},{6,0,944},{135,11,326},{135,\n0,1809},{5,10,938},{7,11,783},{136,10,707},{133,11,766},{133,11,363},{6,0,170},{\n7,0,1080},{8,0,395},{8,0,487},{141,0,147},{6,11,258},{140,11,409},{4,0,535},{8,0\n,618},{5,11,249},{148,11,82},{6,0,1379},{149,11,15},{135,0,1625},{150,0,23},{5,\n11,393},{6,11,378},{7,11,1981},{9,11,32},{9,11,591},{10,11,685},{10,11,741},{142\n,11,382},{133,11,788},{7,11,1968},{10,11,19},{139,11,911},{7,11,1401},{135,11,\n1476},{4,11,61},{5,11,58},{5,11,171},{5,11,635},{5,11,683},{5,11,700},{6,11,291}\n,{6,11,566},{7,11,1650},{11,11,523},{12,11,273},{12,11,303},{15,11,39},{143,11,\n111},{6,10,469},{7,10,1709},{138,10,515},{4,0,778},{134,11,589},{132,0,46},{5,0,\n811},{6,0,1679},{6,0,1714},{135,0,2032},{7,0,1458},{9,0,407},{11,0,15},{12,0,651\n},{149,0,37},{7,0,938},{132,10,500},{6,0,34},{7,0,69},{7,0,1089},{7,0,1281},{8,0\n,708},{8,0,721},{9,0,363},{148,0,98},{10,11,231},{147,11,124},{7,11,726},{152,11\n,9},{5,10,68},{134,10,383},{136,11,583},{4,11,917},{133,11,1005},{11,10,216},{\n139,10,340},{135,11,1675},{8,0,441},{10,0,314},{143,0,3},{132,11,919},{4,10,337}\n,{6,10,353},{7,10,1934},{8,10,488},{137,10,429},{7,0,889},{7,10,1795},{8,10,259}\n,{9,10,135},{9,10,177},{9,10,860},{10,10,825},{11,10,115},{11,10,370},{11,10,405\n},{11,10,604},{12,10,10},{12,10,667},{12,10,669},{13,10,76},{14,10,310},{15,10,\n76},{15,10,147},{148,10,23},{4,10,15},{4,11,255},{5,10,22},{5,11,302},{6,11,132}\n,{6,10,244},{7,10,40},{7,11,128},{7,10,200},{7,11,283},{7,10,906},{7,10,1199},{7\n,11,1299},{9,10,616},{10,11,52},{10,11,514},{10,10,716},{11,10,635},{11,10,801},\n{11,11,925},{12,10,458},{13,11,92},{142,11,309},{132,0,462},{137,11,173},{135,10\n,1735},{8,0,525},{5,10,598},{7,10,791},{8,10,108},{137,10,123},{5,0,73},{6,0,23}\n,{134,0,338},{132,0,676},{132,10,683},{7,0,725},{8,0,498},{139,0,268},{12,0,21},\n{151,0,7},{135,0,773},{4,10,155},{135,10,1689},{4,0,164},{5,0,730},{5,10,151},{5\n,10,741},{6,11,210},{7,10,498},{7,10,870},{7,10,1542},{12,10,213},{14,10,36},{14\n,10,391},{17,10,111},{18,10,6},{18,10,46},{18,10,151},{19,10,36},{20,10,32},{20,\n10,56},{20,10,69},{20,10,102},{21,10,4},{22,10,8},{22,10,10},{22,10,14},{150,10,\n31},{4,10,624},{135,10,1752},{4,0,583},{9,0,936},{15,0,214},{18,0,199},{24,0,26}\n,{134,11,588},{7,0,1462},{11,0,659},{4,11,284},{134,11,223},{133,0,220},{139,0,\n803},{132,0,544},{4,10,492},{133,10,451},{16,0,98},{148,0,119},{4,11,218},{7,11,\n526},{143,11,137},{135,10,835},{4,11,270},{5,11,192},{6,11,332},{7,11,1322},{13,\n11,9},{13,10,70},{14,11,104},{142,11,311},{132,10,539},{140,11,661},{5,0,176},{6\n,0,437},{6,0,564},{11,0,181},{141,0,183},{135,0,1192},{6,10,113},{135,10,436},{\n136,10,718},{135,10,520},{135,0,1878},{140,11,196},{7,11,379},{8,11,481},{137,11\n,377},{5,11,1003},{6,11,149},{137,11,746},{8,11,262},{9,11,627},{10,11,18},{11,\n11,214},{11,11,404},{11,11,457},{11,11,780},{11,11,849},{11,11,913},{13,11,330},\n{13,11,401},{142,11,200},{149,0,26},{136,11,304},{132,11,142},{135,0,944},{4,0,\n790},{5,0,273},{134,0,394},{134,0,855},{4,0,135},{6,0,127},{7,0,1185},{7,0,1511}\n,{8,0,613},{11,0,5},{12,0,336},{12,0,495},{12,0,586},{12,0,660},{12,0,668},{14,0\n,385},{15,0,118},{17,0,20},{146,0,98},{6,0,230},{9,0,752},{18,0,109},{12,10,610}\n,{13,10,431},{144,10,59},{7,0,1954},{135,11,925},{4,11,471},{5,11,51},{6,11,602}\n,{8,11,484},{10,11,195},{140,11,159},{132,10,307},{136,11,688},{132,11,697},{7,\n11,812},{7,11,1261},{7,11,1360},{9,11,632},{140,11,352},{5,0,162},{8,0,68},{133,\n10,964},{4,0,654},{136,11,212},{4,0,156},{7,0,998},{7,0,1045},{7,0,1860},{9,0,48\n},{9,0,692},{11,0,419},{139,0,602},{133,11,221},{4,11,373},{5,11,283},{6,11,480}\n,{135,11,609},{142,11,216},{132,0,240},{6,11,192},{9,11,793},{145,11,55},{4,10,\n75},{5,10,180},{6,10,500},{7,10,58},{7,10,710},{138,10,645},{4,11,132},{5,11,69}\n,{5,10,649},{135,11,1242},{6,10,276},{7,10,282},{7,10,879},{7,10,924},{8,10,459}\n,{9,10,599},{9,10,754},{11,10,574},{12,10,128},{12,10,494},{13,10,52},{13,10,301\n},{15,10,30},{143,10,132},{132,10,200},{4,11,111},{135,11,302},{9,0,197},{10,0,\n300},{12,0,473},{13,0,90},{141,0,405},{132,11,767},{6,11,42},{7,11,1416},{7,11,\n1590},{7,11,2005},{8,11,131},{8,11,466},{9,11,672},{13,11,252},{148,11,103},{8,0\n,958},{8,0,999},{10,0,963},{138,0,1001},{135,10,1621},{135,0,858},{4,0,606},{137\n,11,444},{6,11,44},{136,11,368},{139,11,172},{4,11,570},{133,11,120},{139,11,624\n},{7,0,1978},{8,0,676},{6,10,225},{137,10,211},{7,0,972},{11,0,102},{136,10,687}\n,{6,11,227},{135,11,1589},{8,10,58},{9,10,724},{11,10,809},{13,10,113},{145,10,\n72},{4,0,361},{133,0,315},{132,0,461},{6,10,345},{135,10,1247},{132,0,472},{8,10\n,767},{8,10,803},{9,10,301},{137,10,903},{135,11,1333},{135,11,477},{7,10,1949},\n{136,10,674},{6,0,905},{138,0,747},{133,0,155},{134,10,259},{7,0,163},{8,0,319},\n{9,0,402},{10,0,24},{10,0,681},{11,0,200},{12,0,253},{12,0,410},{142,0,219},{5,0\n,475},{7,0,1780},{9,0,230},{11,0,297},{11,0,558},{14,0,322},{19,0,76},{6,11,1667\n},{7,11,2036},{138,11,600},{136,10,254},{6,0,848},{135,0,1956},{6,11,511},{140,\n11,132},{5,11,568},{6,11,138},{135,11,1293},{6,0,631},{137,0,838},{149,0,36},{4,\n11,565},{8,11,23},{136,11,827},{5,0,944},{134,0,1769},{4,0,144},{6,0,842},{6,0,\n1400},{4,11,922},{133,11,1023},{133,10,248},{9,10,800},{10,10,693},{11,10,482},{\n11,10,734},{139,10,789},{7,11,1002},{139,11,145},{4,10,116},{5,10,95},{5,10,445}\n,{7,10,1688},{8,10,29},{9,10,272},{11,10,509},{139,10,915},{14,0,369},{146,0,72}\n,{135,10,1641},{132,11,740},{133,10,543},{140,11,116},{6,0,247},{9,0,555},{5,10,\n181},{136,10,41},{133,10,657},{136,0,996},{138,10,709},{7,0,189},{8,10,202},{138\n,10,536},{136,11,402},{4,11,716},{141,11,31},{10,0,280},{138,0,797},{9,10,423},{\n140,10,89},{8,10,113},{9,10,877},{10,10,554},{11,10,83},{12,10,136},{147,10,109}\n,{133,10,976},{7,0,746},{132,10,206},{136,0,526},{139,0,345},{136,0,1017},{8,11,\n152},{9,11,53},{9,11,268},{9,11,901},{10,11,518},{10,11,829},{11,11,188},{13,11,\n74},{14,11,46},{15,11,17},{15,11,33},{17,11,40},{18,11,36},{19,11,20},{22,11,1},\n{152,11,2},{133,11,736},{136,11,532},{5,0,428},{138,0,651},{135,11,681},{135,0,\n1162},{7,0,327},{13,0,230},{17,0,113},{8,10,226},{10,10,537},{11,10,570},{11,10,\n605},{11,10,799},{11,10,804},{12,10,85},{12,10,516},{12,10,623},{12,11,677},{13,\n10,361},{14,10,77},{14,10,78},{147,10,110},{4,0,792},{7,0,1717},{10,0,546},{132,\n10,769},{4,11,684},{136,11,384},{132,10,551},{134,0,1203},{9,10,57},{9,10,459},{\n10,10,425},{11,10,119},{12,10,184},{12,10,371},{13,10,358},{145,10,51},{5,0,672}\n,{5,10,814},{8,10,10},{9,10,421},{9,10,729},{10,10,609},{139,10,689},{138,0,189}\n,{134,10,624},{7,11,110},{7,11,188},{8,11,290},{8,11,591},{9,11,382},{9,11,649},\n{11,11,71},{11,11,155},{11,11,313},{12,11,5},{13,11,325},{142,11,287},{133,0,99}\n,{6,0,1053},{135,0,298},{7,11,360},{7,11,425},{9,11,66},{9,11,278},{138,11,644},\n{4,0,397},{136,0,555},{137,10,269},{132,10,528},{4,11,900},{133,11,861},{6,0,\n1157},{5,11,254},{7,11,985},{136,11,73},{7,11,1959},{136,11,683},{12,0,398},{20,\n0,39},{21,0,11},{150,0,41},{4,0,485},{7,0,353},{135,0,1523},{6,0,366},{7,0,1384}\n,{135,0,1601},{138,0,787},{137,0,282},{5,10,104},{6,10,173},{135,10,1631},{139,\n11,146},{4,0,157},{133,0,471},{134,0,941},{132,11,725},{7,0,1336},{8,10,138},{8,\n10,342},{9,10,84},{10,10,193},{11,10,883},{140,10,359},{134,11,196},{136,0,116},\n{133,11,831},{134,0,787},{134,10,95},{6,10,406},{10,10,409},{10,10,447},{11,10,\n44},{140,10,100},{5,0,160},{7,0,363},{7,0,589},{10,0,170},{141,0,55},{134,0,1815\n},{132,0,866},{6,0,889},{6,0,1067},{6,0,1183},{4,11,321},{134,11,569},{5,11,848}\n,{134,11,66},{4,11,36},{6,10,1636},{7,11,1387},{10,11,205},{11,11,755},{141,11,\n271},{132,0,689},{9,0,820},{4,10,282},{7,10,1034},{11,10,398},{11,10,634},{12,10\n,1},{12,10,79},{12,10,544},{14,10,237},{17,10,10},{146,10,20},{4,0,108},{7,0,804\n},{139,0,498},{132,11,887},{6,0,1119},{135,11,620},{6,11,165},{138,11,388},{5,0,\n244},{5,10,499},{6,10,476},{7,10,600},{7,10,888},{135,10,1096},{140,0,609},{135,\n0,1005},{4,0,412},{133,0,581},{4,11,719},{135,11,155},{7,10,296},{7,10,596},{8,\n10,560},{8,10,586},{9,10,612},{11,10,304},{12,10,46},{13,10,89},{14,10,112},{145\n,10,122},{4,0,895},{133,0,772},{142,11,307},{135,0,1898},{4,0,926},{133,0,983},{\n4,11,353},{6,11,146},{6,11,1789},{7,11,288},{7,11,990},{7,11,1348},{9,11,665},{9\n,11,898},{11,11,893},{142,11,212},{132,0,538},{133,11,532},{6,0,294},{7,0,1267},\n{8,0,624},{141,0,496},{7,0,1325},{4,11,45},{135,11,1257},{138,0,301},{9,0,298},{\n12,0,291},{13,0,276},{14,0,6},{17,0,18},{21,0,32},{7,10,1599},{7,10,1723},{8,10,\n79},{8,10,106},{8,10,190},{8,10,302},{8,10,383},{8,10,713},{9,10,119},{9,10,233}\n,{9,10,419},{9,10,471},{10,10,181},{10,10,406},{11,10,57},{11,10,85},{11,10,120}\n,{11,10,177},{11,10,296},{11,10,382},{11,10,454},{11,10,758},{11,10,999},{12,10,\n27},{12,10,131},{12,10,245},{12,10,312},{12,10,446},{12,10,454},{13,10,98},{13,\n10,426},{13,10,508},{14,10,163},{14,10,272},{14,10,277},{14,10,370},{15,10,95},{\n15,10,138},{15,10,167},{17,10,38},{148,10,96},{132,0,757},{134,0,1263},{4,0,820}\n,{134,10,1759},{133,0,722},{136,11,816},{138,10,372},{145,10,16},{134,0,1039},{4\n,0,991},{134,0,2028},{133,10,258},{7,0,1875},{139,0,124},{6,11,559},{6,11,1691},\n{135,11,586},{5,0,324},{7,0,881},{8,10,134},{9,10,788},{140,10,438},{7,11,1823},\n{139,11,693},{6,0,1348},{134,0,1545},{134,0,911},{132,0,954},{8,0,329},{8,0,414}\n,{7,10,1948},{135,10,2004},{5,0,517},{6,10,439},{7,10,780},{135,10,1040},{132,0,\n816},{5,10,1},{6,10,81},{138,10,520},{9,0,713},{10,0,222},{5,10,482},{8,10,98},{\n10,10,700},{10,10,822},{11,10,302},{11,10,778},{12,10,50},{12,10,127},{12,10,396\n},{13,10,62},{13,10,328},{14,10,122},{147,10,72},{137,0,33},{5,10,2},{7,10,1494}\n,{136,10,589},{6,10,512},{7,10,797},{8,10,253},{9,10,77},{10,10,1},{10,11,108},{\n10,10,129},{10,10,225},{11,11,116},{11,10,118},{11,10,226},{11,10,251},{11,10,\n430},{11,10,701},{11,10,974},{11,10,982},{12,10,64},{12,10,260},{12,10,488},{140\n,10,690},{134,11,456},{133,11,925},{5,0,150},{7,0,106},{7,0,774},{8,0,603},{9,0,\n593},{9,0,634},{10,0,44},{10,0,173},{11,0,462},{11,0,515},{13,0,216},{13,0,288},\n{142,0,400},{137,10,347},{5,0,748},{134,0,553},{12,0,108},{141,0,291},{7,0,420},\n{4,10,12},{7,10,522},{7,10,809},{8,10,797},{141,10,88},{6,11,193},{7,11,240},{7,\n11,1682},{10,11,51},{10,11,640},{11,11,410},{13,11,82},{14,11,247},{14,11,331},{\n142,11,377},{133,10,528},{135,0,1777},{4,0,493},{144,0,55},{136,11,633},{139,0,\n81},{6,0,980},{136,0,321},{148,10,109},{5,10,266},{9,10,290},{9,10,364},{10,10,\n293},{11,10,606},{142,10,45},{6,0,568},{7,0,112},{7,0,1804},{8,0,362},{8,0,410},\n{8,0,830},{9,0,514},{11,0,649},{142,0,157},{4,0,74},{6,0,510},{6,10,594},{9,10,\n121},{10,10,49},{10,10,412},{139,10,834},{134,0,838},{136,10,748},{132,10,466},{\n132,0,625},{135,11,1443},{4,11,237},{135,11,514},{9,10,378},{141,10,162},{6,0,16\n},{6,0,158},{7,0,43},{7,0,129},{7,0,181},{8,0,276},{8,0,377},{10,0,523},{11,0,\n816},{12,0,455},{13,0,303},{142,0,135},{135,0,281},{4,0,1},{7,0,1143},{7,0,1463}\n,{8,0,61},{9,0,207},{9,0,390},{9,0,467},{139,0,836},{6,11,392},{7,11,65},{135,11\n,2019},{132,10,667},{4,0,723},{5,0,895},{7,0,1031},{8,0,199},{8,0,340},{9,0,153}\n,{9,0,215},{10,0,21},{10,0,59},{10,0,80},{10,0,224},{10,0,838},{11,0,229},{11,0,\n652},{12,0,192},{13,0,146},{142,0,91},{132,0,295},{137,0,51},{9,11,222},{10,11,\n43},{139,11,900},{5,0,309},{140,0,211},{5,0,125},{8,0,77},{138,0,15},{136,11,604\n},{138,0,789},{5,0,173},{4,10,39},{7,10,1843},{8,10,407},{11,10,144},{140,10,523\n},{138,11,265},{133,0,439},{132,10,510},{7,0,648},{7,0,874},{11,0,164},{12,0,76}\n,{18,0,9},{7,10,1980},{10,10,487},{138,10,809},{12,0,111},{14,0,294},{19,0,45},{\n13,10,260},{146,10,63},{133,11,549},{134,10,570},{4,0,8},{7,0,1152},{7,0,1153},{\n7,0,1715},{9,0,374},{10,0,478},{139,0,648},{135,0,1099},{5,0,575},{6,0,354},{135\n,0,701},{7,11,36},{8,11,201},{136,11,605},{4,10,787},{136,11,156},{6,0,518},{149\n,11,13},{140,11,224},{134,0,702},{132,10,516},{5,11,724},{10,11,305},{11,11,151}\n,{12,11,33},{12,11,121},{12,11,381},{17,11,3},{17,11,27},{17,11,78},{18,11,18},{\n19,11,54},{149,11,5},{8,0,87},{4,11,523},{5,11,638},{11,10,887},{14,10,365},{142\n,10,375},{138,0,438},{136,10,821},{135,11,1908},{6,11,242},{7,11,227},{7,11,1581\n},{8,11,104},{9,11,113},{9,11,220},{9,11,427},{10,11,74},{10,11,239},{11,11,579}\n,{11,11,1023},{13,11,4},{13,11,204},{13,11,316},{18,11,95},{148,11,86},{4,0,69},\n{5,0,122},{5,0,849},{6,0,1633},{9,0,656},{138,0,464},{7,0,1802},{4,10,10},{139,\n10,786},{135,11,861},{139,0,499},{7,0,476},{7,0,1592},{138,0,87},{133,10,684},{4\n,0,840},{134,10,27},{142,0,283},{6,0,1620},{7,11,1328},{136,11,494},{5,0,859},{7\n,0,1160},{8,0,107},{9,0,291},{9,0,439},{10,0,663},{11,0,609},{140,0,197},{7,11,\n1306},{8,11,505},{9,11,482},{10,11,126},{11,11,225},{12,11,347},{12,11,449},{13,\n11,19},{142,11,218},{5,11,268},{10,11,764},{12,11,120},{13,11,39},{145,11,127},{\n145,10,56},{7,11,1672},{10,11,472},{11,11,189},{143,11,51},{6,10,342},{6,10,496}\n,{8,10,275},{137,10,206},{133,0,600},{4,0,117},{6,0,372},{7,0,1905},{142,0,323},\n{4,10,909},{5,10,940},{135,11,1471},{132,10,891},{4,0,722},{139,0,471},{4,11,384\n},{135,11,1022},{132,10,687},{9,0,5},{12,0,216},{12,0,294},{12,0,298},{12,0,400}\n,{12,0,518},{13,0,229},{143,0,139},{135,11,1703},{7,11,1602},{10,11,698},{12,11,\n212},{141,11,307},{6,10,41},{141,10,160},{135,11,1077},{9,11,159},{11,11,28},{\n140,11,603},{4,0,514},{7,0,1304},{138,0,477},{134,0,1774},{9,0,88},{139,0,270},{\n5,0,12},{7,0,375},{9,0,438},{134,10,1718},{132,11,515},{136,10,778},{8,11,632},{\n8,11,697},{137,11,854},{6,0,362},{6,0,997},{146,0,51},{7,0,816},{7,0,1241},{9,0,\n283},{9,0,520},{10,0,213},{10,0,307},{10,0,463},{10,0,671},{10,0,746},{11,0,401}\n,{11,0,794},{12,0,517},{18,0,107},{147,0,115},{133,10,115},{150,11,28},{4,11,136\n},{133,11,551},{142,10,314},{132,0,258},{6,0,22},{7,0,903},{7,0,1963},{8,0,639},\n{138,0,577},{5,0,681},{8,0,782},{13,0,130},{17,0,84},{5,10,193},{140,10,178},{9,\n11,17},{138,11,291},{7,11,1287},{9,11,44},{10,11,552},{10,11,642},{11,11,839},{\n12,11,274},{12,11,275},{12,11,372},{13,11,91},{142,11,125},{135,10,174},{4,0,664\n},{5,0,804},{139,0,1013},{134,0,942},{6,0,1349},{6,0,1353},{6,0,1450},{7,11,1518\n},{139,11,694},{11,0,356},{4,10,122},{5,10,796},{5,10,952},{6,10,1660},{6,10,\n1671},{8,10,567},{9,10,687},{9,10,742},{10,10,686},{11,10,682},{140,10,281},{5,0\n,32},{6,11,147},{7,11,886},{9,11,753},{138,11,268},{5,10,179},{7,10,1095},{135,\n10,1213},{4,10,66},{7,10,722},{135,10,904},{135,10,352},{9,11,245},{138,11,137},\n{4,0,289},{7,0,629},{7,0,1698},{7,0,1711},{12,0,215},{133,11,414},{6,0,1975},{\n135,11,1762},{6,0,450},{136,0,109},{141,10,35},{134,11,599},{136,0,705},{133,0,\n664},{134,11,1749},{11,11,402},{12,11,109},{12,11,431},{13,11,179},{13,11,206},{\n14,11,175},{14,11,217},{16,11,3},{148,11,53},{135,0,1238},{134,11,1627},{132,11,\n488},{13,0,318},{10,10,592},{10,10,753},{12,10,317},{12,10,355},{12,10,465},{12,\n10,469},{12,10,560},{140,10,578},{133,10,564},{132,11,83},{140,11,676},{6,0,1872\n},{6,0,1906},{6,0,1907},{9,0,934},{9,0,956},{9,0,960},{9,0,996},{12,0,794},{12,0\n,876},{12,0,880},{12,0,918},{15,0,230},{18,0,234},{18,0,238},{21,0,38},{149,0,62\n},{134,10,556},{134,11,278},{137,0,103},{7,10,544},{8,10,719},{138,10,61},{4,10,\n5},{5,10,498},{8,10,637},{137,10,521},{7,0,777},{12,0,229},{12,0,239},{15,0,12},\n{12,11,229},{12,11,239},{143,11,12},{6,0,26},{7,11,388},{7,11,644},{139,11,781},\n{7,11,229},{8,11,59},{9,11,190},{9,11,257},{10,11,378},{140,11,191},{133,10,927}\n,{135,10,1441},{4,10,893},{5,10,780},{133,10,893},{4,0,414},{5,0,467},{9,0,654},\n{10,0,451},{12,0,59},{141,0,375},{142,0,173},{135,0,17},{7,0,1350},{133,10,238},\n{135,0,955},{4,0,960},{10,0,887},{12,0,753},{18,0,161},{18,0,162},{152,0,19},{\n136,11,344},{6,10,1729},{137,11,288},{132,11,660},{4,0,217},{5,0,710},{7,0,760},\n{7,0,1926},{9,0,428},{9,0,708},{10,0,254},{10,0,296},{10,0,720},{11,0,109},{11,0\n,255},{12,0,165},{12,0,315},{13,0,107},{13,0,203},{14,0,54},{14,0,99},{14,0,114}\n,{14,0,388},{16,0,85},{17,0,9},{17,0,33},{20,0,25},{20,0,28},{20,0,29},{21,0,9},\n{21,0,10},{21,0,34},{22,0,17},{4,10,60},{7,10,1800},{8,10,314},{9,10,700},{139,\n10,487},{7,11,1035},{138,11,737},{7,11,690},{9,11,217},{9,11,587},{140,11,521},{\n6,0,919},{7,11,706},{7,11,1058},{138,11,538},{7,10,1853},{138,10,437},{136,10,\n419},{6,0,280},{10,0,502},{11,0,344},{140,0,38},{5,0,45},{7,0,1161},{11,0,448},{\n11,0,880},{13,0,139},{13,0,407},{15,0,16},{17,0,95},{18,0,66},{18,0,88},{18,0,\n123},{149,0,7},{11,11,92},{11,11,196},{11,11,409},{11,11,450},{11,11,666},{11,11\n,777},{12,11,262},{13,11,385},{13,11,393},{15,11,115},{16,11,45},{145,11,82},{\n136,0,777},{134,11,1744},{4,0,410},{7,0,521},{133,10,828},{134,0,673},{7,0,1110}\n,{7,0,1778},{7,10,176},{135,10,178},{5,10,806},{7,11,268},{7,10,1976},{136,11,\n569},{4,11,733},{9,11,194},{10,11,92},{11,11,198},{12,11,84},{12,11,87},{13,11,\n128},{144,11,74},{5,0,341},{7,0,1129},{11,0,414},{4,10,51},{6,10,4},{7,10,591},{\n7,10,849},{7,10,951},{7,10,1613},{7,10,1760},{7,10,1988},{9,10,434},{10,10,754},\n{11,10,25},{139,10,37},{133,10,902},{135,10,928},{135,0,787},{132,0,436},{134,10\n,270},{7,0,1587},{135,0,1707},{6,0,377},{7,0,1025},{9,0,613},{145,0,104},{7,11,\n982},{7,11,1361},{10,11,32},{143,11,56},{139,0,96},{132,0,451},{132,10,416},{142\n,10,372},{5,10,152},{5,10,197},{7,11,306},{7,10,340},{7,10,867},{10,10,548},{10,\n10,581},{11,10,6},{12,10,3},{12,10,19},{14,10,110},{142,10,289},{134,0,680},{134\n,11,609},{7,0,483},{7,10,190},{8,10,28},{8,10,141},{8,10,444},{8,10,811},{9,10,\n468},{11,10,334},{12,10,24},{12,10,386},{140,10,576},{10,0,916},{133,10,757},{5,\n10,721},{135,10,1553},{133,11,178},{134,0,937},{132,10,898},{133,0,739},{147,0,\n82},{135,0,663},{146,0,128},{5,10,277},{141,10,247},{134,0,1087},{132,10,435},{6\n,11,381},{7,11,645},{7,11,694},{136,11,546},{7,0,503},{135,0,1885},{6,0,1965},{8\n,0,925},{138,0,955},{4,0,113},{5,0,163},{5,0,735},{7,0,1009},{9,0,9},{9,0,771},{\n12,0,90},{13,0,138},{13,0,410},{143,0,128},{4,0,324},{138,0,104},{7,0,460},{5,10\n,265},{134,10,212},{133,11,105},{7,11,261},{7,11,1107},{7,11,1115},{7,11,1354},{\n7,11,1588},{7,11,1705},{7,11,1902},{9,11,465},{10,11,248},{10,11,349},{10,11,647\n},{11,11,527},{11,11,660},{11,11,669},{12,11,529},{141,11,305},{5,11,438},{9,11,\n694},{12,11,627},{141,11,210},{152,11,11},{4,0,935},{133,0,823},{132,10,702},{5,\n0,269},{7,0,434},{7,0,891},{8,0,339},{9,0,702},{11,0,594},{11,0,718},{17,0,100},\n{5,10,808},{135,10,2045},{7,0,1014},{9,0,485},{141,0,264},{134,0,1713},{7,0,1810\n},{11,0,866},{12,0,103},{13,0,495},{140,11,233},{4,0,423},{10,0,949},{138,0,1013\n},{135,0,900},{8,11,25},{138,11,826},{5,10,166},{8,10,739},{140,10,511},{134,0,\n2018},{7,11,1270},{139,11,612},{4,10,119},{5,10,170},{5,10,447},{7,10,1708},{7,\n10,1889},{9,10,357},{9,10,719},{12,10,486},{140,10,596},{12,0,574},{140,11,574},\n{132,11,308},{6,0,964},{6,0,1206},{134,0,1302},{4,10,450},{135,10,1158},{135,11,\n150},{136,11,649},{14,0,213},{148,0,38},{9,11,45},{9,11,311},{141,11,42},{134,11\n,521},{7,10,1375},{7,10,1466},{138,10,331},{132,10,754},{5,11,339},{7,11,1442},{\n14,11,3},{15,11,41},{147,11,66},{136,11,378},{134,0,1022},{5,10,850},{136,10,799\n},{142,0,143},{135,0,2029},{134,11,1628},{8,0,523},{150,0,34},{5,0,625},{135,0,\n1617},{7,0,275},{7,10,238},{7,10,2033},{8,10,120},{8,10,188},{8,10,659},{9,10,\n598},{10,10,466},{12,10,342},{12,10,588},{13,10,503},{14,10,246},{143,10,92},{7,\n0,37},{8,0,425},{8,0,693},{9,0,720},{10,0,380},{10,0,638},{11,0,273},{11,0,473},\n{12,0,61},{143,0,43},{135,11,829},{135,0,1943},{132,0,765},{5,11,486},{135,11,\n1349},{7,11,1635},{8,11,17},{10,11,217},{138,11,295},{4,10,201},{7,10,1744},{8,\n10,602},{11,10,247},{11,10,826},{145,10,65},{138,11,558},{11,0,551},{142,0,159},\n{8,10,164},{146,10,62},{139,11,176},{132,0,168},{136,0,1010},{134,0,1994},{135,0\n,91},{138,0,532},{135,10,1243},{135,0,1884},{132,10,907},{5,10,100},{10,10,329},\n{12,10,416},{149,10,29},{134,11,447},{132,10,176},{5,10,636},{5,10,998},{7,10,9}\n,{7,10,1508},{8,10,26},{9,10,317},{9,10,358},{10,10,210},{10,10,292},{10,10,533}\n,{11,10,555},{12,10,526},{12,10,607},{13,10,263},{13,10,459},{142,10,271},{4,11,\n609},{135,11,756},{6,0,15},{7,0,70},{10,0,240},{147,0,93},{4,11,930},{133,11,947\n},{134,0,1227},{134,0,1534},{133,11,939},{133,11,962},{5,11,651},{8,11,170},{9,\n11,61},{9,11,63},{10,11,23},{10,11,37},{10,11,834},{11,11,4},{11,11,187},{11,11,\n281},{11,11,503},{11,11,677},{12,11,96},{12,11,130},{12,11,244},{14,11,5},{14,11\n,40},{14,11,162},{14,11,202},{146,11,133},{4,11,406},{5,11,579},{12,11,492},{150\n,11,15},{139,0,392},{6,10,610},{10,10,127},{141,10,27},{7,0,655},{7,0,1844},{136\n,10,119},{4,0,145},{6,0,176},{7,0,395},{137,0,562},{132,0,501},{140,11,145},{136\n,0,1019},{134,0,509},{139,0,267},{6,11,17},{7,11,16},{7,11,1001},{7,11,1982},{9,\n11,886},{10,11,489},{10,11,800},{11,11,782},{12,11,320},{13,11,467},{14,11,145},\n{14,11,387},{143,11,119},{145,11,17},{6,0,1099},{133,11,458},{7,11,1983},{8,11,0\n},{8,11,171},{9,11,120},{9,11,732},{10,11,473},{11,11,656},{11,11,998},{18,11,0}\n,{18,11,2},{147,11,21},{12,11,427},{146,11,38},{10,0,948},{138,0,968},{7,10,126}\n,{136,10,84},{136,10,790},{4,0,114},{9,0,492},{13,0,462},{142,0,215},{6,10,64},{\n12,10,377},{141,10,309},{4,0,77},{5,0,361},{6,0,139},{6,0,401},{6,0,404},{7,0,\n413},{7,0,715},{7,0,1716},{11,0,279},{12,0,179},{12,0,258},{13,0,244},{142,0,358\n},{134,0,1717},{7,0,772},{7,0,1061},{7,0,1647},{8,0,82},{11,0,250},{11,0,607},{\n12,0,311},{12,0,420},{13,0,184},{13,0,367},{7,10,1104},{11,10,269},{11,10,539},{\n11,10,627},{11,10,706},{11,10,975},{12,10,248},{12,10,434},{12,10,600},{12,10,\n622},{13,10,297},{13,10,485},{14,10,69},{14,10,409},{143,10,108},{135,0,724},{4,\n11,512},{4,11,519},{133,11,342},{134,0,1133},{145,11,29},{11,10,977},{141,10,507\n},{6,0,841},{6,0,1042},{6,0,1194},{10,0,993},{140,0,1021},{6,11,31},{7,11,491},{\n7,11,530},{8,11,592},{9,10,34},{11,11,53},{11,10,484},{11,11,779},{12,11,167},{\n12,11,411},{14,11,14},{14,11,136},{15,11,72},{16,11,17},{144,11,72},{4,0,1021},{\n6,0,2037},{133,11,907},{7,0,373},{8,0,335},{8,0,596},{9,0,488},{6,10,1700},{7,10\n,293},{7,10,382},{7,10,1026},{7,10,1087},{7,10,2027},{8,10,252},{8,10,727},{8,10\n,729},{9,10,30},{9,10,199},{9,10,231},{9,10,251},{9,10,334},{9,10,361},{9,10,712\n},{10,10,55},{10,10,60},{10,10,232},{10,10,332},{10,10,384},{10,10,396},{10,10,\n504},{10,10,542},{10,10,652},{11,10,20},{11,10,48},{11,10,207},{11,10,291},{11,\n10,298},{11,10,342},{11,10,365},{11,10,394},{11,10,620},{11,10,705},{11,10,1017}\n,{12,10,123},{12,10,340},{12,10,406},{12,10,643},{13,10,61},{13,10,269},{13,10,\n311},{13,10,319},{13,10,486},{14,10,234},{15,10,62},{15,10,85},{16,10,71},{18,10\n,119},{148,10,105},{150,0,37},{4,11,208},{5,11,106},{6,11,531},{8,11,408},{9,11,\n188},{138,11,572},{132,0,564},{6,0,513},{135,0,1052},{132,0,825},{9,0,899},{140,\n11,441},{134,0,778},{133,11,379},{7,0,1417},{12,0,382},{17,0,48},{152,0,12},{132\n,11,241},{7,0,1116},{6,10,379},{7,10,270},{8,10,176},{8,10,183},{9,10,432},{9,10\n,661},{12,10,247},{12,10,617},{146,10,125},{5,10,792},{133,10,900},{6,0,545},{7,\n0,565},{7,0,1669},{10,0,114},{11,0,642},{140,0,618},{133,0,5},{138,11,7},{132,11\n,259},{135,0,192},{134,0,701},{136,0,763},{135,10,1979},{4,10,901},{133,10,776},\n{10,0,755},{147,0,29},{133,0,759},{4,11,173},{5,11,312},{5,11,512},{135,11,1285}\n,{7,11,1603},{7,11,1691},{9,11,464},{11,11,195},{12,11,279},{12,11,448},{14,11,\n11},{147,11,102},{7,0,370},{7,0,1007},{7,0,1177},{135,0,1565},{135,0,1237},{4,0,\n87},{5,0,250},{141,0,298},{4,11,452},{5,11,583},{5,11,817},{6,11,433},{7,11,593}\n,{7,11,720},{7,11,1378},{8,11,161},{9,11,284},{10,11,313},{139,11,886},{4,11,547\n},{135,11,1409},{136,11,722},{4,10,37},{5,10,334},{135,10,1253},{132,10,508},{12\n,0,107},{146,0,31},{8,11,420},{139,11,193},{135,0,814},{135,11,409},{140,0,991},\n{4,0,57},{7,0,1195},{7,0,1438},{7,0,1548},{7,0,1835},{7,0,1904},{9,0,757},{10,0,\n604},{139,0,519},{132,0,540},{138,11,308},{132,10,533},{136,0,608},{144,11,65},{\n4,0,1014},{134,0,2029},{4,0,209},{7,0,902},{5,11,1002},{136,11,745},{134,0,2030}\n,{6,0,303},{7,0,335},{7,0,1437},{7,0,1668},{8,0,553},{8,0,652},{8,0,656},{9,0,\n558},{11,0,743},{149,0,18},{5,11,575},{6,11,354},{135,11,701},{4,11,239},{6,11,\n477},{7,11,1607},{11,11,68},{139,11,617},{132,0,559},{8,0,527},{18,0,60},{147,0,\n24},{133,10,920},{138,0,511},{133,0,1017},{133,0,675},{138,10,391},{11,0,156},{\n135,10,1952},{138,11,369},{132,11,367},{133,0,709},{6,0,698},{134,0,887},{142,10\n,126},{134,0,1745},{132,10,483},{13,11,299},{142,11,75},{133,0,714},{7,0,8},{136\n,0,206},{138,10,480},{4,11,694},{9,10,495},{146,10,104},{7,11,1248},{11,11,621},\n{139,11,702},{140,11,687},{132,0,776},{139,10,1009},{135,0,1272},{134,0,1059},{8\n,10,653},{13,10,93},{147,10,14},{135,11,213},{136,0,406},{133,10,172},{132,0,947\n},{8,0,175},{10,0,168},{138,0,573},{132,0,870},{6,0,1567},{151,11,28},{134,11,\n472},{5,10,260},{136,11,132},{4,11,751},{11,11,390},{140,11,32},{4,11,409},{133,\n11,78},{12,0,554},{6,11,473},{145,11,105},{133,0,784},{8,0,908},{136,11,306},{\n139,0,882},{6,0,358},{7,0,1393},{8,0,396},{10,0,263},{14,0,154},{16,0,48},{17,0,\n8},{7,11,1759},{8,11,396},{10,11,263},{14,11,154},{16,11,48},{145,11,8},{13,11,\n163},{13,11,180},{18,11,78},{148,11,35},{14,0,32},{18,0,85},{20,0,2},{152,0,16},\n{7,0,228},{10,0,770},{8,10,167},{8,10,375},{9,10,82},{9,10,561},{138,10,620},{\n132,0,845},{9,0,14},{9,0,441},{10,0,306},{139,0,9},{11,0,966},{12,0,287},{13,0,\n342},{13,0,402},{15,0,110},{15,0,163},{8,10,194},{136,10,756},{134,0,1578},{4,0,\n967},{6,0,1820},{6,0,1847},{140,0,716},{136,0,594},{7,0,1428},{7,0,1640},{7,0,\n1867},{9,0,169},{9,0,182},{9,0,367},{9,0,478},{9,0,506},{9,0,551},{9,0,557},{9,0\n,648},{9,0,697},{9,0,705},{9,0,725},{9,0,787},{9,0,794},{10,0,198},{10,0,214},{\n10,0,267},{10,0,275},{10,0,456},{10,0,551},{10,0,561},{10,0,613},{10,0,627},{10,\n0,668},{10,0,675},{10,0,691},{10,0,695},{10,0,707},{10,0,715},{11,0,183},{11,0,\n201},{11,0,244},{11,0,262},{11,0,352},{11,0,439},{11,0,493},{11,0,572},{11,0,591\n},{11,0,608},{11,0,611},{11,0,646},{11,0,674},{11,0,711},{11,0,751},{11,0,761},{\n11,0,776},{11,0,785},{11,0,850},{11,0,853},{11,0,862},{11,0,865},{11,0,868},{11,\n0,875},{11,0,898},{11,0,902},{11,0,903},{11,0,910},{11,0,932},{11,0,942},{11,0,\n957},{11,0,967},{11,0,972},{12,0,148},{12,0,195},{12,0,220},{12,0,237},{12,0,318\n},{12,0,339},{12,0,393},{12,0,445},{12,0,450},{12,0,474},{12,0,505},{12,0,509},{\n12,0,533},{12,0,591},{12,0,594},{12,0,597},{12,0,621},{12,0,633},{12,0,642},{13,\n0,59},{13,0,60},{13,0,145},{13,0,239},{13,0,250},{13,0,329},{13,0,344},{13,0,365\n},{13,0,372},{13,0,387},{13,0,403},{13,0,414},{13,0,456},{13,0,470},{13,0,478},{\n13,0,483},{13,0,489},{14,0,55},{14,0,57},{14,0,81},{14,0,90},{14,0,148},{14,0,\n239},{14,0,266},{14,0,321},{14,0,326},{14,0,327},{14,0,330},{14,0,347},{14,0,355\n},{14,0,401},{14,0,404},{14,0,411},{14,0,414},{14,0,416},{14,0,420},{15,0,61},{\n15,0,74},{15,0,87},{15,0,88},{15,0,94},{15,0,96},{15,0,116},{15,0,149},{15,0,154\n},{16,0,50},{16,0,63},{16,0,73},{17,0,2},{17,0,66},{17,0,92},{17,0,103},{17,0,\n112},{17,0,120},{18,0,50},{18,0,54},{18,0,82},{18,0,86},{18,0,90},{18,0,111},{18\n,0,115},{18,0,156},{19,0,40},{19,0,79},{20,0,78},{21,0,22},{135,11,883},{5,0,161\n},{135,0,839},{4,0,782},{13,11,293},{142,11,56},{133,11,617},{139,11,50},{135,10\n,22},{145,0,64},{5,10,639},{7,10,1249},{139,10,896},{138,0,998},{135,11,2042},{4\n,11,546},{142,11,233},{6,0,1043},{134,0,1574},{134,0,1496},{4,10,102},{7,10,815}\n,{7,10,1699},{139,10,964},{12,0,781},{142,0,461},{4,11,313},{133,11,577},{6,0,\n639},{6,0,1114},{137,0,817},{8,11,184},{141,11,433},{7,0,1814},{135,11,935},{10,\n0,997},{140,0,958},{4,0,812},{137,11,625},{132,10,899},{136,10,795},{5,11,886},{\n6,11,46},{6,11,1790},{7,11,14},{7,11,732},{7,11,1654},{8,11,95},{8,11,327},{8,11\n,616},{10,11,598},{10,11,769},{11,11,134},{11,11,747},{12,11,378},{142,11,97},{\n136,0,139},{6,10,52},{9,10,104},{9,10,559},{12,10,308},{147,10,87},{133,11,1021}\n,{132,10,604},{132,10,301},{136,10,779},{7,0,643},{136,0,236},{132,11,153},{134,\n0,1172},{147,10,32},{133,11,798},{6,0,1338},{132,11,587},{6,11,598},{7,11,42},{8\n,11,695},{10,11,212},{11,11,158},{14,11,196},{145,11,85},{135,10,508},{5,11,957}\n,{5,11,1008},{135,11,249},{4,11,129},{135,11,465},{5,0,54},{7,11,470},{7,11,1057\n},{7,11,1201},{9,11,755},{11,11,906},{140,11,527},{7,11,908},{146,11,7},{5,11,\n148},{136,11,450},{144,11,1},{4,0,256},{135,0,1488},{9,0,351},{6,10,310},{7,10,\n1849},{8,10,72},{8,10,272},{8,10,431},{9,10,12},{10,10,563},{10,10,630},{10,10,\n796},{10,10,810},{11,10,367},{11,10,599},{11,10,686},{140,10,672},{6,0,1885},{6,\n0,1898},{6,0,1899},{140,0,955},{4,0,714},{133,0,469},{6,0,1270},{134,0,1456},{\n132,0,744},{6,0,313},{7,10,537},{8,10,64},{9,10,127},{10,10,496},{12,10,510},{\n141,10,384},{4,11,217},{4,10,244},{5,11,710},{7,10,233},{7,11,1926},{9,11,428},{\n9,11,708},{10,11,254},{10,11,296},{10,11,720},{11,11,109},{11,11,255},{12,11,165\n},{12,11,315},{13,11,107},{13,11,203},{14,11,54},{14,11,99},{14,11,114},{14,11,\n388},{16,11,85},{17,11,9},{17,11,33},{20,11,25},{20,11,28},{20,11,29},{21,11,9},\n{21,11,10},{21,11,34},{150,11,17},{138,0,402},{7,0,969},{146,0,55},{8,0,50},{137\n,0,624},{134,0,1355},{132,0,572},{134,10,1650},{10,10,702},{139,10,245},{10,0,\n847},{142,0,445},{6,0,43},{7,0,38},{8,0,248},{138,0,513},{133,0,369},{137,10,338\n},{133,0,766},{133,0,363},{133,10,896},{8,11,392},{11,11,54},{13,11,173},{13,11,\n294},{148,11,7},{134,0,678},{7,11,1230},{136,11,531},{6,0,258},{140,0,409},{5,0,\n249},{148,0,82},{7,10,1117},{136,10,539},{5,0,393},{6,0,378},{7,0,1981},{9,0,32}\n,{9,0,591},{10,0,685},{10,0,741},{142,0,382},{133,0,788},{134,0,1281},{134,0,\n1295},{7,0,1968},{141,0,509},{4,0,61},{5,0,58},{5,0,171},{5,0,683},{6,0,291},{6,\n0,566},{7,0,1650},{11,0,523},{12,0,273},{12,0,303},{15,0,39},{143,0,111},{6,0,\n706},{134,0,1283},{134,0,589},{135,11,1433},{133,11,435},{7,0,1059},{13,0,54},{5\n,10,4},{5,10,810},{6,10,13},{6,10,538},{6,10,1690},{6,10,1726},{7,10,1819},{8,10\n,148},{8,10,696},{8,10,791},{12,10,125},{143,10,9},{135,10,1268},{5,11,85},{6,11\n,419},{7,11,134},{7,11,305},{7,11,361},{7,11,1337},{8,11,71},{140,11,519},{137,0\n,824},{140,11,688},{5,11,691},{7,11,345},{7,10,1385},{9,11,94},{11,10,582},{11,\n10,650},{11,10,901},{11,10,949},{12,11,169},{12,10,232},{12,10,236},{13,10,413},\n{13,10,501},{146,10,116},{4,0,917},{133,0,1005},{7,0,1598},{5,11,183},{6,11,582}\n,{9,11,344},{10,11,679},{140,11,435},{4,10,925},{5,10,803},{8,10,698},{138,10,\n828},{132,0,919},{135,11,511},{139,10,992},{4,0,255},{5,0,302},{6,0,132},{7,0,\n128},{7,0,283},{7,0,1299},{10,0,52},{10,0,514},{11,0,925},{13,0,92},{142,0,309},\n{134,0,1369},{135,10,1847},{134,0,328},{7,11,1993},{136,11,684},{133,10,383},{\n137,0,173},{134,11,583},{134,0,1411},{19,0,65},{5,11,704},{8,11,357},{10,11,745}\n,{14,11,426},{17,11,94},{147,11,57},{9,10,660},{138,10,347},{4,11,179},{5,11,198\n},{133,11,697},{7,11,347},{7,11,971},{8,11,181},{138,11,711},{141,0,442},{11,0,\n842},{11,0,924},{13,0,317},{13,0,370},{13,0,469},{13,0,471},{14,0,397},{18,0,69}\n,{18,0,145},{7,10,572},{9,10,592},{11,10,680},{12,10,356},{140,10,550},{14,11,19\n},{14,11,28},{144,11,29},{136,0,534},{4,11,243},{5,11,203},{7,11,19},{7,11,71},{\n7,11,113},{10,11,405},{11,11,357},{142,11,240},{6,0,210},{10,0,845},{138,0,862},\n{7,11,1351},{9,11,581},{10,11,639},{11,11,453},{140,11,584},{7,11,1450},{139,11,\n99},{10,0,892},{12,0,719},{144,0,105},{4,0,284},{6,0,223},{134,11,492},{5,11,134\n},{6,11,408},{6,11,495},{135,11,1593},{136,0,529},{137,0,807},{4,0,218},{7,0,526\n},{143,0,137},{6,0,1444},{142,11,4},{132,11,665},{4,0,270},{5,0,192},{6,0,332},{\n7,0,1322},{4,11,248},{7,11,137},{137,11,349},{140,0,661},{7,0,1517},{11,0,597},{\n14,0,76},{14,0,335},{20,0,33},{7,10,748},{139,10,700},{5,11,371},{135,11,563},{\n146,11,57},{133,10,127},{133,0,418},{4,11,374},{7,11,547},{7,11,1700},{7,11,1833\n},{139,11,858},{6,10,198},{140,10,83},{7,11,1812},{13,11,259},{13,11,356},{14,11\n,242},{147,11,114},{7,0,379},{8,0,481},{9,0,377},{5,10,276},{6,10,55},{135,10,\n1369},{138,11,286},{5,0,1003},{6,0,149},{6,10,1752},{136,10,726},{8,0,262},{9,0,\n627},{10,0,18},{11,0,214},{11,0,404},{11,0,457},{11,0,780},{11,0,913},{13,0,401}\n,{14,0,200},{6,11,1647},{7,11,1552},{7,11,2010},{9,11,494},{137,11,509},{135,0,\n742},{136,0,304},{132,0,142},{133,10,764},{6,10,309},{7,10,331},{138,10,550},{\n135,10,1062},{6,11,123},{7,11,214},{7,10,986},{9,11,728},{10,11,157},{11,11,346}\n,{11,11,662},{143,11,106},{135,10,1573},{7,0,925},{137,0,799},{4,0,471},{5,0,51}\n,{6,0,602},{8,0,484},{138,0,195},{136,0,688},{132,0,697},{6,0,1169},{6,0,1241},{\n6,10,194},{7,10,133},{10,10,493},{10,10,570},{139,10,664},{140,0,751},{7,0,929},\n{10,0,452},{11,0,878},{16,0,33},{5,10,24},{5,10,569},{6,10,3},{6,10,119},{6,10,\n143},{6,10,440},{7,10,599},{7,10,1686},{7,10,1854},{8,10,424},{9,10,43},{9,10,\n584},{9,10,760},{10,10,328},{11,10,159},{11,10,253},{12,10,487},{140,10,531},{4,\n11,707},{13,11,106},{18,11,49},{147,11,41},{5,0,221},{5,11,588},{134,11,393},{\n134,0,1437},{6,11,211},{7,11,1690},{11,11,486},{140,11,369},{5,10,14},{5,10,892}\n,{6,10,283},{7,10,234},{136,10,537},{4,0,988},{136,0,955},{135,0,1251},{4,10,126\n},{8,10,635},{147,10,34},{4,10,316},{135,10,1561},{137,10,861},{4,10,64},{5,10,\n352},{5,10,720},{6,10,368},{139,10,359},{134,0,192},{4,0,132},{5,0,69},{135,0,\n1242},{7,10,1577},{10,10,304},{10,10,549},{12,10,365},{13,10,220},{13,10,240},{\n142,10,33},{4,0,111},{7,0,865},{134,11,219},{5,11,582},{6,11,1646},{7,11,99},{7,\n11,1962},{7,11,1986},{8,11,515},{8,11,773},{9,11,23},{9,11,491},{12,11,620},{14,\n11,52},{145,11,50},{132,0,767},{7,11,568},{148,11,21},{6,0,42},{7,0,1416},{7,0,\n2005},{8,0,131},{8,0,466},{9,0,672},{13,0,252},{20,0,103},{133,11,851},{135,0,\n1050},{6,10,175},{137,10,289},{5,10,432},{133,10,913},{6,0,44},{136,0,368},{135,\n11,784},{132,0,570},{133,0,120},{139,10,595},{140,0,29},{6,0,227},{135,0,1589},{\n4,11,98},{7,11,1365},{9,11,422},{9,11,670},{10,11,775},{11,11,210},{13,11,26},{\n13,11,457},{141,11,476},{140,10,80},{5,10,931},{134,10,1698},{133,0,522},{134,0,\n1120},{135,0,1529},{12,0,739},{14,0,448},{142,0,467},{11,10,526},{11,10,939},{\n141,10,290},{5,10,774},{6,10,1637},{6,10,1686},{134,10,1751},{6,0,1667},{135,0,\n2036},{7,10,1167},{11,10,934},{13,10,391},{145,10,76},{137,11,147},{6,10,260},{7\n,10,1484},{11,11,821},{12,11,110},{12,11,153},{18,11,41},{150,11,19},{6,0,511},{\n12,0,132},{134,10,573},{5,0,568},{6,0,138},{135,0,1293},{132,0,1020},{8,0,258},{\n9,0,208},{137,0,359},{4,0,565},{8,0,23},{136,0,827},{134,0,344},{4,0,922},{5,0,\n1023},{13,11,477},{14,11,120},{148,11,61},{134,0,240},{5,11,209},{6,11,30},{11,\n11,56},{139,11,305},{6,0,171},{7,0,1002},{7,0,1324},{9,0,415},{14,0,230},{18,0,\n68},{4,10,292},{4,10,736},{5,10,871},{6,10,1689},{7,10,1944},{137,10,580},{9,11,\n635},{139,11,559},{4,11,150},{5,11,303},{134,11,327},{6,10,63},{135,10,920},{133\n,10,793},{8,11,192},{10,11,78},{10,11,555},{11,11,308},{13,11,359},{147,11,95},{\n135,11,786},{135,11,1712},{136,0,402},{6,0,754},{6,11,1638},{7,11,79},{7,11,496}\n,{9,11,138},{10,11,336},{11,11,12},{12,11,412},{12,11,440},{142,11,305},{4,0,716\n},{141,0,31},{133,0,982},{8,0,691},{8,0,731},{5,10,67},{6,10,62},{6,10,374},{135\n,10,1391},{9,10,790},{140,10,47},{139,11,556},{151,11,1},{7,11,204},{7,11,415},{\n8,11,42},{10,11,85},{11,11,33},{11,11,564},{12,11,571},{149,11,1},{8,0,888},{7,\n11,610},{135,11,1501},{4,10,391},{135,10,1169},{5,0,847},{9,0,840},{138,0,803},{\n137,0,823},{134,0,785},{8,0,152},{9,0,53},{9,0,268},{9,0,901},{10,0,518},{10,0,\n829},{11,0,188},{13,0,74},{14,0,46},{15,0,17},{15,0,33},{17,0,40},{18,0,36},{19,\n0,20},{22,0,1},{152,0,2},{4,11,3},{5,11,247},{5,11,644},{7,11,744},{7,11,1207},{\n7,11,1225},{7,11,1909},{146,11,147},{136,0,532},{135,0,681},{132,10,271},{140,0,\n314},{140,0,677},{4,0,684},{136,0,384},{5,11,285},{9,11,67},{13,11,473},{143,11,\n82},{4,10,253},{5,10,544},{7,10,300},{137,10,340},{7,0,110},{7,0,447},{8,0,290},\n{8,0,591},{9,0,382},{9,0,649},{11,0,71},{11,0,155},{11,0,313},{12,0,5},{13,0,325\n},{142,0,287},{134,0,1818},{136,0,1007},{138,0,321},{7,0,360},{7,0,425},{9,0,66}\n,{9,0,278},{138,0,644},{133,10,818},{5,0,385},{5,10,541},{6,10,94},{6,10,499},{7\n,10,230},{139,10,321},{4,10,920},{5,10,25},{5,10,790},{6,10,457},{7,10,853},{136\n,10,788},{4,0,900},{133,0,861},{5,0,254},{7,0,985},{136,0,73},{7,0,1959},{136,0,\n683},{134,10,1765},{133,10,822},{132,10,634},{4,11,29},{6,11,532},{7,11,1628},{7\n,11,1648},{9,11,303},{9,11,350},{10,11,433},{11,11,97},{11,11,557},{11,11,745},{\n12,11,289},{12,11,335},{12,11,348},{12,11,606},{13,11,116},{13,11,233},{13,11,\n466},{14,11,181},{14,11,209},{14,11,232},{14,11,236},{14,11,300},{16,11,41},{148\n,11,97},{19,0,86},{6,10,36},{7,10,658},{136,10,454},{135,11,1692},{132,0,725},{5\n,11,501},{7,11,1704},{9,11,553},{11,11,520},{12,11,557},{141,11,249},{134,0,196}\n,{133,0,831},{136,0,723},{7,0,1897},{13,0,80},{13,0,437},{145,0,74},{4,0,992},{6\n,0,627},{136,0,994},{135,11,1294},{132,10,104},{5,0,848},{6,0,66},{136,0,764},{4\n,0,36},{7,0,1387},{10,0,205},{139,0,755},{6,0,1046},{134,0,1485},{134,0,950},{\n132,0,887},{14,0,450},{148,0,111},{7,0,620},{7,0,831},{9,10,542},{9,10,566},{138\n,10,728},{6,0,165},{138,0,388},{139,10,263},{4,0,719},{135,0,155},{138,10,468},{\n6,11,453},{144,11,36},{134,11,129},{5,0,533},{7,0,755},{138,0,780},{134,0,1465},\n{4,0,353},{6,0,146},{6,0,1789},{7,0,427},{7,0,990},{7,0,1348},{9,0,665},{9,0,898\n},{11,0,893},{142,0,212},{7,10,87},{142,10,288},{4,0,45},{135,0,1257},{12,0,7},{\n7,10,988},{7,10,1939},{9,10,64},{9,10,502},{12,10,34},{13,10,12},{13,10,234},{\n147,10,77},{4,0,607},{5,11,60},{6,11,504},{7,11,614},{7,11,1155},{140,11,0},{135\n,10,141},{8,11,198},{11,11,29},{140,11,534},{140,0,65},{136,0,816},{132,10,619},\n{139,0,88},{5,10,246},{8,10,189},{9,10,355},{9,10,512},{10,10,124},{10,10,453},{\n11,10,143},{11,10,416},{11,10,859},{141,10,341},{4,11,379},{135,11,1397},{4,0,\n600},{137,0,621},{133,0,367},{134,0,561},{6,0,559},{134,0,1691},{6,0,585},{134,\n11,585},{135,11,1228},{4,11,118},{5,10,678},{6,11,274},{6,11,361},{7,11,75},{141\n,11,441},{135,11,1818},{137,11,841},{5,0,573},{6,0,287},{7,10,862},{7,10,1886},{\n138,10,179},{132,10,517},{140,11,693},{5,11,314},{6,11,221},{7,11,419},{10,11,\n650},{11,11,396},{12,11,156},{13,11,369},{14,11,333},{145,11,47},{140,10,540},{\n136,10,667},{11,10,403},{146,10,83},{6,0,672},{133,10,761},{9,0,157},{10,10,131}\n,{140,10,72},{7,0,714},{134,11,460},{134,0,456},{133,0,925},{5,11,682},{135,11,\n1887},{136,11,510},{136,11,475},{133,11,1016},{9,0,19},{7,11,602},{8,11,179},{10\n,11,781},{140,11,126},{6,11,329},{138,11,111},{6,0,822},{134,0,1473},{144,11,86}\n,{11,0,113},{139,11,113},{5,11,821},{134,11,1687},{133,10,449},{7,0,463},{17,0,\n69},{136,10,103},{7,10,2028},{138,10,641},{6,0,193},{7,0,240},{7,0,1682},{10,0,\n51},{10,0,640},{11,0,410},{13,0,82},{14,0,247},{14,0,331},{142,0,377},{6,0,471},\n{11,0,411},{142,0,2},{5,11,71},{7,11,1407},{9,11,388},{9,11,704},{10,11,261},{10\n,11,619},{11,11,547},{11,11,619},{143,11,157},{136,0,633},{135,0,1148},{6,0,554}\n,{7,0,1392},{12,0,129},{7,10,1274},{7,10,1386},{7,11,2008},{9,11,337},{10,11,517\n},{146,10,87},{7,0,803},{8,0,542},{6,10,187},{7,10,1203},{8,10,380},{14,10,117},\n{149,10,28},{6,10,297},{7,10,793},{139,10,938},{8,0,438},{11,0,363},{7,10,464},{\n11,10,105},{12,10,231},{14,10,386},{15,10,102},{148,10,75},{5,11,16},{6,11,86},{\n6,11,603},{7,11,292},{7,11,561},{8,11,257},{8,11,382},{9,11,721},{9,11,778},{11,\n11,581},{140,11,466},{6,0,717},{4,11,486},{133,11,491},{132,0,875},{132,11,72},{\n6,11,265},{135,11,847},{4,0,237},{135,0,514},{6,0,392},{7,0,65},{135,0,2019},{\n140,11,261},{135,11,922},{137,11,404},{12,0,563},{14,0,101},{18,0,129},{7,10,\n1010},{11,10,733},{11,10,759},{13,10,34},{146,10,45},{7,10,1656},{9,10,369},{10,\n10,338},{10,10,490},{11,10,154},{11,10,545},{11,10,775},{13,10,77},{141,10,274},\n{4,0,444},{10,0,146},{140,0,9},{139,11,163},{7,0,1260},{135,0,1790},{9,0,222},{\n10,0,43},{139,0,900},{137,11,234},{138,0,971},{137,0,761},{134,0,699},{136,11,\n434},{6,0,1116},{7,0,1366},{5,10,20},{6,11,197},{6,10,298},{7,10,659},{8,11,205}\n,{137,10,219},{132,11,490},{11,11,820},{150,11,51},{7,10,1440},{11,10,854},{11,\n10,872},{11,10,921},{12,10,551},{13,10,472},{142,10,367},{140,11,13},{132,0,829}\n,{12,0,242},{132,10,439},{136,10,669},{6,0,593},{6,11,452},{7,11,312},{138,11,\n219},{4,11,333},{9,11,176},{12,11,353},{141,11,187},{7,0,36},{8,0,201},{136,0,\n605},{140,0,224},{132,10,233},{134,0,1430},{134,0,1806},{4,0,523},{133,0,638},{6\n,0,1889},{9,0,958},{9,0,971},{9,0,976},{12,0,796},{12,0,799},{12,0,808},{12,0,\n835},{12,0,836},{12,0,914},{12,0,946},{15,0,216},{15,0,232},{18,0,183},{18,0,187\n},{18,0,194},{18,0,212},{18,0,232},{149,0,49},{132,10,482},{6,0,827},{134,0,1434\n},{135,10,346},{134,0,2043},{6,0,242},{7,0,227},{7,0,1581},{8,0,104},{9,0,113},{\n9,0,220},{9,0,427},{10,0,136},{10,0,239},{11,0,579},{11,0,1023},{13,0,4},{13,0,\n204},{13,0,316},{148,0,86},{134,11,1685},{7,0,148},{8,0,284},{141,0,63},{142,0,\n10},{135,11,584},{134,0,1249},{7,0,861},{135,10,334},{5,10,795},{6,10,1741},{137\n,11,70},{132,0,807},{7,11,135},{8,11,7},{8,11,62},{9,11,243},{10,11,658},{10,11,\n697},{11,11,456},{139,11,756},{9,11,395},{138,11,79},{137,11,108},{147,0,94},{\n136,0,494},{135,11,631},{135,10,622},{7,0,1510},{135,10,1750},{4,10,203},{135,10\n,1936},{7,11,406},{7,11,459},{8,11,606},{139,11,726},{7,0,1306},{8,0,505},{9,0,\n482},{10,0,126},{11,0,225},{12,0,347},{12,0,449},{13,0,19},{14,0,218},{142,0,435\n},{5,0,268},{10,0,764},{12,0,120},{13,0,39},{145,0,127},{142,11,68},{11,10,678},\n{140,10,307},{12,11,268},{12,11,640},{142,11,119},{135,10,2044},{133,11,612},{4,\n11,372},{7,11,482},{8,11,158},{9,11,602},{9,11,615},{10,11,245},{10,11,678},{10,\n11,744},{11,11,248},{139,11,806},{7,10,311},{9,10,308},{140,10,255},{4,0,384},{\n135,0,1022},{5,11,854},{135,11,1991},{135,10,1266},{4,10,400},{5,10,267},{135,10\n,232},{135,0,1703},{9,0,159},{11,0,661},{140,0,603},{4,0,964},{14,0,438},{14,0,\n444},{14,0,456},{22,0,60},{22,0,63},{9,11,106},{9,11,163},{9,11,296},{10,11,167}\n,{10,11,172},{10,11,777},{139,11,16},{136,0,583},{132,0,515},{8,0,632},{8,0,697}\n,{137,0,854},{5,11,195},{135,11,1685},{6,0,1123},{134,0,1365},{134,11,328},{7,11\n,1997},{8,11,730},{139,11,1006},{4,0,136},{133,0,551},{134,0,1782},{7,0,1287},{9\n,0,44},{10,0,552},{10,0,642},{11,0,839},{12,0,274},{12,0,275},{12,0,372},{13,0,\n91},{142,0,125},{5,11,751},{11,11,797},{140,11,203},{133,0,732},{7,0,679},{8,0,\n313},{4,10,100},{135,11,821},{10,0,361},{142,0,316},{134,0,595},{6,0,147},{7,0,\n886},{9,0,753},{138,0,268},{5,10,362},{5,10,443},{6,10,318},{7,10,1019},{139,10,\n623},{5,10,463},{136,10,296},{4,10,454},{5,11,950},{5,11,994},{134,11,351},{138,\n0,137},{5,10,48},{5,10,404},{6,10,557},{7,10,458},{8,10,597},{10,10,455},{10,10,\n606},{11,10,49},{11,10,548},{12,10,476},{13,10,18},{141,10,450},{133,0,414},{135\n,0,1762},{5,11,421},{135,11,47},{5,10,442},{135,10,1984},{134,0,599},{134,0,1749\n},{134,0,1627},{4,0,488},{132,11,350},{137,11,751},{132,0,83},{140,0,676},{133,\n11,967},{7,0,1639},{5,10,55},{140,10,161},{4,11,473},{7,11,623},{8,11,808},{9,11\n,871},{9,11,893},{11,11,38},{11,11,431},{12,11,112},{12,11,217},{12,11,243},{12,\n11,562},{12,11,683},{13,11,141},{13,11,197},{13,11,227},{13,11,406},{13,11,487},\n{14,11,156},{14,11,203},{14,11,224},{14,11,256},{18,11,58},{150,11,0},{133,10,\n450},{7,11,736},{139,11,264},{134,0,278},{4,11,222},{7,11,286},{136,11,629},{135\n,10,869},{140,0,97},{144,0,14},{134,0,1085},{4,10,213},{7,10,223},{136,10,80},{7\n,0,388},{7,0,644},{139,0,781},{132,0,849},{7,0,229},{8,0,59},{9,0,190},{10,0,378\n},{140,0,191},{7,10,381},{7,10,806},{7,10,820},{8,10,354},{8,10,437},{8,10,787},\n{9,10,657},{10,10,58},{10,10,339},{10,10,749},{11,10,914},{12,10,162},{13,10,75}\n,{14,10,106},{14,10,198},{14,10,320},{14,10,413},{146,10,43},{141,11,306},{136,\n10,747},{134,0,1115},{16,0,94},{16,0,108},{136,11,146},{6,0,700},{6,0,817},{134,\n0,1002},{133,10,692},{4,11,465},{135,11,1663},{134,10,191},{6,0,1414},{135,11,\n913},{132,0,660},{7,0,1035},{138,0,737},{6,10,162},{7,10,1960},{136,10,831},{132\n,10,706},{7,0,690},{9,0,217},{9,0,587},{140,0,521},{138,10,426},{135,10,1235},{6\n,11,82},{7,11,138},{7,11,517},{9,11,673},{139,11,238},{138,0,272},{5,11,495},{7,\n11,834},{9,11,733},{139,11,378},{134,0,1744},{132,0,1011},{7,11,828},{142,11,116\n},{4,0,733},{9,0,194},{10,0,92},{11,0,198},{12,0,84},{13,0,128},{133,11,559},{10\n,0,57},{10,0,277},{6,11,21},{6,11,1737},{7,11,1444},{136,11,224},{4,10,204},{137\n,10,902},{136,10,833},{11,0,348},{12,0,99},{18,0,1},{18,0,11},{19,0,4},{7,10,366\n},{9,10,287},{12,10,199},{12,10,556},{140,10,577},{6,0,1981},{136,0,936},{21,0,\n33},{150,0,40},{5,11,519},{138,11,204},{5,10,356},{135,10,224},{134,0,775},{135,\n0,306},{7,10,630},{9,10,567},{11,10,150},{11,10,444},{141,10,119},{5,0,979},{134\n,10,539},{133,0,611},{4,11,402},{135,11,1679},{5,0,178},{7,11,2},{8,11,323},{136\n,11,479},{5,11,59},{135,11,672},{4,0,1010},{6,0,1969},{138,11,237},{133,11,412},\n{146,11,34},{7,11,1740},{146,11,48},{134,0,664},{139,10,814},{4,11,85},{135,11,\n549},{133,11,94},{133,11,457},{132,0,390},{134,0,1510},{4,10,235},{135,10,255},{\n4,10,194},{5,10,584},{6,11,11},{6,10,384},{7,11,187},{7,10,583},{10,10,761},{11,\n10,760},{139,10,851},{4,11,522},{139,11,802},{135,0,493},{10,11,776},{13,11,345}\n,{142,11,425},{146,0,37},{4,11,52},{135,11,661},{134,0,724},{134,0,829},{133,11,\n520},{133,10,562},{4,11,281},{5,11,38},{7,11,194},{7,11,668},{7,11,1893},{137,11\n,397},{5,10,191},{137,10,271},{7,0,1537},{14,0,96},{143,0,73},{5,0,473},{11,0,\n168},{4,10,470},{6,10,153},{7,10,1503},{7,10,1923},{10,10,701},{11,10,132},{11,\n10,227},{11,10,320},{11,10,436},{11,10,525},{11,10,855},{12,10,41},{12,10,286},{\n13,10,103},{13,10,284},{14,10,255},{14,10,262},{15,10,117},{143,10,127},{133,0,\n105},{5,0,438},{9,0,694},{12,0,627},{141,0,210},{133,10,327},{6,10,552},{7,10,\n1754},{137,10,604},{134,0,1256},{152,0,11},{5,11,448},{11,11,98},{139,11,524},{7\n,0,1626},{5,10,80},{6,10,405},{7,10,403},{7,10,1502},{8,10,456},{9,10,487},{9,10\n,853},{9,10,889},{10,10,309},{11,10,721},{11,10,994},{12,10,430},{13,10,165},{14\n,11,16},{146,11,44},{132,0,779},{8,0,25},{138,0,826},{4,10,453},{5,10,887},{6,10\n,535},{8,10,6},{8,10,543},{136,10,826},{137,11,461},{140,11,632},{132,0,308},{\n135,0,741},{132,0,671},{7,0,150},{8,0,649},{136,0,1020},{9,0,99},{6,11,336},{8,\n11,552},{9,11,285},{10,11,99},{139,11,568},{134,0,521},{5,0,339},{14,0,3},{15,0,\n41},{15,0,166},{147,0,66},{6,11,423},{7,11,665},{7,11,1210},{9,11,218},{141,11,\n222},{6,0,543},{5,10,101},{5,11,256},{6,10,88},{7,10,1677},{9,10,100},{10,10,677\n},{14,10,169},{14,10,302},{14,10,313},{15,10,48},{143,10,84},{4,10,310},{7,10,\n708},{7,10,996},{9,10,795},{10,10,390},{10,10,733},{11,10,451},{12,10,249},{14,\n10,115},{14,10,286},{143,10,100},{133,10,587},{13,11,417},{14,11,129},{143,11,15\n},{134,0,1358},{136,11,554},{132,10,498},{7,10,217},{8,10,140},{138,10,610},{135\n,11,989},{135,11,634},{6,0,155},{140,0,234},{135,11,462},{132,11,618},{134,0,\n1628},{132,0,766},{4,11,339},{5,10,905},{135,11,259},{135,0,829},{4,11,759},{141\n,11,169},{7,0,1445},{4,10,456},{7,10,358},{7,10,1637},{8,10,643},{139,10,483},{5\n,0,486},{135,0,1349},{5,11,688},{135,11,712},{7,0,1635},{8,0,17},{10,0,217},{10,\n0,295},{12,0,2},{140,11,2},{138,0,558},{150,10,56},{4,11,278},{5,11,465},{135,11\n,1367},{136,11,482},{133,10,535},{6,0,1362},{6,0,1461},{10,11,274},{10,11,625},{\n139,11,530},{5,0,599},{5,11,336},{6,11,341},{6,11,478},{6,11,1763},{136,11,386},\n{7,10,1748},{137,11,151},{134,0,1376},{133,10,539},{135,11,73},{135,11,1971},{\n139,11,283},{9,0,93},{139,0,474},{6,10,91},{135,10,435},{6,0,447},{5,11,396},{\n134,11,501},{4,10,16},{5,10,316},{5,10,842},{6,10,370},{6,10,1778},{8,10,166},{\n11,10,812},{12,10,206},{12,10,351},{14,10,418},{16,10,15},{16,10,34},{18,10,3},{\n19,10,3},{19,10,7},{20,10,4},{149,10,21},{7,0,577},{7,0,1432},{9,0,475},{9,0,505\n},{9,0,526},{9,0,609},{9,0,689},{9,0,726},{9,0,735},{9,0,738},{10,0,556},{10,0,\n674},{10,0,684},{11,0,89},{11,0,202},{11,0,272},{11,0,380},{11,0,415},{11,0,505}\n,{11,0,537},{11,0,550},{11,0,562},{11,0,640},{11,0,667},{11,0,688},{11,0,847},{\n11,0,927},{11,0,930},{11,0,940},{12,0,144},{12,0,325},{12,0,329},{12,0,389},{12,\n0,403},{12,0,451},{12,0,515},{12,0,604},{12,0,616},{12,0,626},{13,0,66},{13,0,\n131},{13,0,167},{13,0,236},{13,0,368},{13,0,411},{13,0,434},{13,0,453},{13,0,461\n},{13,0,474},{14,0,59},{14,0,60},{14,0,139},{14,0,152},{14,0,276},{14,0,353},{14\n,0,402},{15,0,28},{15,0,81},{15,0,123},{15,0,152},{18,0,136},{148,0,88},{4,11,\n929},{133,11,799},{136,11,46},{142,0,307},{4,0,609},{7,0,756},{9,0,544},{11,0,\n413},{144,0,25},{10,0,687},{7,10,619},{10,10,547},{11,10,122},{140,10,601},{4,0,\n930},{133,0,947},{133,0,939},{142,0,21},{4,11,892},{133,11,770},{133,0,962},{5,0\n,651},{8,0,170},{9,0,61},{9,0,63},{10,0,23},{10,0,37},{10,0,834},{11,0,4},{11,0,\n187},{11,0,281},{11,0,503},{11,0,677},{12,0,96},{12,0,130},{12,0,244},{14,0,5},{\n14,0,40},{14,0,162},{14,0,202},{146,0,133},{4,0,406},{5,0,579},{12,0,492},{150,0\n,15},{135,11,158},{135,0,597},{132,0,981},{132,10,888},{4,10,149},{138,10,368},{\n132,0,545},{4,10,154},{7,10,1134},{136,10,105},{135,11,2001},{134,0,1558},{4,10,\n31},{6,10,429},{7,10,962},{9,10,458},{139,10,691},{132,10,312},{135,10,1642},{6,\n0,17},{6,0,1304},{7,0,16},{7,0,1001},{9,0,886},{10,0,489},{10,0,800},{11,0,782},\n{12,0,320},{13,0,467},{14,0,145},{14,0,387},{143,0,119},{135,0,1982},{17,0,17},{\n7,11,1461},{140,11,91},{4,10,236},{132,11,602},{138,0,907},{136,0,110},{7,0,272}\n,{19,0,53},{5,10,836},{5,10,857},{134,10,1680},{5,0,458},{7,11,1218},{136,11,303\n},{7,0,1983},{8,0,0},{8,0,171},{9,0,120},{9,0,732},{10,0,473},{11,0,656},{11,0,\n998},{18,0,0},{18,0,2},{19,0,21},{10,10,68},{139,10,494},{137,11,662},{4,11,13},\n{5,11,567},{7,11,1498},{9,11,124},{11,11,521},{140,11,405},{4,10,81},{139,10,867\n},{135,11,1006},{7,11,800},{7,11,1783},{138,11,12},{9,0,295},{10,0,443},{5,10,\n282},{8,10,650},{137,10,907},{132,11,735},{4,11,170},{4,10,775},{135,11,323},{6,\n0,1844},{10,0,924},{11,11,844},{12,11,104},{140,11,625},{5,11,304},{7,11,1403},{\n140,11,498},{134,0,1232},{4,0,519},{10,0,70},{12,0,26},{14,0,17},{14,0,178},{15,\n0,34},{149,0,12},{132,0,993},{4,11,148},{133,11,742},{6,0,31},{7,0,491},{7,0,530\n},{8,0,592},{11,0,53},{11,0,779},{12,0,167},{12,0,411},{14,0,14},{14,0,136},{15,\n0,72},{16,0,17},{144,0,72},{133,0,907},{134,0,733},{133,11,111},{4,10,71},{5,10,\n376},{7,10,119},{138,10,665},{136,0,55},{8,0,430},{136,11,430},{4,0,208},{5,0,\n106},{6,0,531},{8,0,408},{9,0,188},{138,0,572},{12,0,56},{11,10,827},{14,10,34},\n{143,10,148},{134,0,1693},{133,11,444},{132,10,479},{140,0,441},{9,0,449},{10,0,\n192},{138,0,740},{134,0,928},{4,0,241},{7,10,607},{136,10,99},{8,11,123},{15,11,\n6},{144,11,7},{6,11,285},{8,11,654},{11,11,749},{12,11,190},{12,11,327},{13,11,\n120},{13,11,121},{13,11,327},{15,11,47},{146,11,40},{4,10,41},{5,10,74},{7,10,\n1627},{11,10,871},{140,10,619},{7,0,1525},{11,10,329},{11,10,965},{12,10,241},{\n14,10,354},{15,10,22},{148,10,63},{132,0,259},{135,11,183},{9,10,209},{137,10,\n300},{5,11,937},{135,11,100},{133,10,98},{4,0,173},{5,0,312},{5,0,512},{135,0,\n1285},{141,0,185},{7,0,1603},{7,0,1691},{9,0,464},{11,0,195},{12,0,279},{12,0,\n448},{14,0,11},{147,0,102},{135,0,1113},{133,10,984},{4,0,452},{5,0,583},{135,0,\n720},{4,0,547},{5,0,817},{6,0,433},{7,0,593},{7,0,1378},{8,0,161},{9,0,284},{10,\n0,313},{139,0,886},{8,0,722},{4,10,182},{6,10,205},{135,10,220},{150,0,13},{4,10\n,42},{9,10,205},{9,10,786},{138,10,659},{6,0,289},{7,0,1670},{12,0,57},{151,0,4}\n,{132,10,635},{14,0,43},{146,0,21},{139,10,533},{135,0,1694},{8,0,420},{139,0,\n193},{135,0,409},{132,10,371},{4,10,272},{135,10,836},{5,10,825},{134,10,1640},{\n5,11,251},{5,11,956},{8,11,268},{9,11,214},{146,11,142},{138,0,308},{6,0,1863},{\n141,11,37},{137,10,879},{7,10,317},{135,10,569},{132,11,294},{134,0,790},{5,0,\n1002},{136,0,745},{5,11,346},{5,11,711},{136,11,390},{135,0,289},{5,0,504},{11,0\n,68},{137,10,307},{4,0,239},{6,0,477},{7,0,1607},{139,0,617},{149,0,13},{133,0,\n609},{133,11,624},{5,11,783},{7,11,1998},{135,11,2047},{133,10,525},{132,0,367},\n{132,11,594},{6,0,528},{133,10,493},{4,10,174},{135,10,911},{8,10,417},{137,10,\n782},{132,0,694},{7,0,548},{137,0,58},{4,10,32},{5,10,215},{6,10,269},{7,10,1782\n},{7,10,1892},{10,10,16},{11,10,822},{11,10,954},{141,10,481},{140,0,687},{7,0,\n1749},{136,10,477},{132,11,569},{133,10,308},{135,10,1088},{4,0,661},{138,0,1004\n},{5,11,37},{6,11,39},{6,11,451},{7,11,218},{7,11,667},{7,11,1166},{7,11,1687},{\n8,11,662},{144,11,2},{9,0,445},{12,0,53},{13,0,492},{5,10,126},{8,10,297},{9,10,\n366},{140,10,374},{7,10,1551},{139,10,361},{148,0,74},{134,11,508},{135,0,213},{\n132,10,175},{132,10,685},{6,0,760},{6,0,834},{134,0,1248},{7,11,453},{7,11,635},\n{7,11,796},{8,11,331},{9,11,328},{9,11,330},{9,11,865},{10,11,119},{10,11,235},{\n11,11,111},{11,11,129},{11,11,240},{12,11,31},{12,11,66},{12,11,222},{12,11,269}\n,{12,11,599},{12,11,689},{13,11,186},{13,11,364},{142,11,345},{7,0,1672},{139,0,\n189},{133,10,797},{133,10,565},{6,0,1548},{6,11,98},{7,11,585},{135,11,702},{9,0\n,968},{15,0,192},{149,0,56},{4,10,252},{6,11,37},{7,11,299},{7,10,1068},{7,11,\n1666},{8,11,195},{8,11,316},{9,11,178},{9,11,276},{9,11,339},{9,11,536},{10,11,\n102},{10,11,362},{10,10,434},{10,11,785},{11,11,55},{11,11,149},{11,10,228},{11,\n10,426},{11,11,773},{13,10,231},{13,11,416},{13,11,419},{14,11,38},{14,11,41},{\n14,11,210},{18,10,106},{148,10,87},{4,0,751},{11,0,390},{140,0,32},{4,0,409},{\n133,0,78},{11,11,458},{12,11,15},{140,11,432},{7,0,1602},{10,0,257},{10,0,698},{\n11,0,544},{11,0,585},{12,0,212},{13,0,307},{5,10,231},{7,10,601},{9,10,277},{9,\n10,674},{10,10,178},{10,10,418},{10,10,509},{11,10,531},{12,10,113},{12,10,475},\n{13,10,99},{142,10,428},{6,0,473},{145,0,105},{6,0,1949},{15,0,156},{133,11,645}\n,{7,10,1591},{144,10,43},{135,0,1779},{135,10,1683},{4,11,290},{135,11,1356},{\n134,0,763},{6,11,70},{7,11,1292},{10,11,762},{139,11,288},{142,0,29},{140,11,428\n},{7,0,883},{7,11,131},{7,11,422},{8,11,210},{140,11,573},{134,0,488},{4,10,399}\n,{5,10,119},{5,10,494},{7,10,751},{137,10,556},{133,0,617},{132,11,936},{139,0,\n50},{7,0,1518},{139,0,694},{137,0,785},{4,0,546},{135,0,2042},{7,11,716},{13,11,\n97},{141,11,251},{132,11,653},{145,0,22},{134,0,1016},{4,0,313},{133,0,577},{136\n,11,657},{8,0,184},{141,0,433},{135,0,935},{6,0,720},{9,0,114},{146,11,80},{12,0\n,186},{12,0,292},{14,0,100},{18,0,70},{7,10,594},{7,10,851},{7,10,1858},{9,10,\n411},{9,10,574},{9,10,666},{9,10,737},{10,10,346},{10,10,712},{11,10,246},{11,10\n,432},{11,10,517},{11,10,647},{11,10,679},{11,10,727},{12,10,304},{12,10,305},{\n12,10,323},{12,10,483},{12,10,572},{12,10,593},{12,10,602},{13,10,95},{13,10,101\n},{13,10,171},{13,10,315},{13,10,378},{13,10,425},{13,10,475},{14,10,63},{14,10,\n380},{14,10,384},{15,10,133},{18,10,112},{148,10,72},{135,10,1093},{135,11,1836}\n,{132,10,679},{137,10,203},{11,0,402},{12,0,109},{12,0,431},{13,0,179},{13,0,206\n},{14,0,217},{16,0,3},{148,0,53},{7,11,1368},{8,11,232},{8,11,361},{10,11,682},{\n138,11,742},{137,10,714},{5,0,886},{6,0,46},{6,0,1790},{7,0,14},{7,0,732},{7,0,\n1654},{8,0,95},{8,0,327},{8,0,616},{9,0,892},{10,0,598},{10,0,769},{11,0,134},{\n11,0,747},{12,0,378},{14,0,97},{137,11,534},{4,0,969},{136,10,825},{137,11,27},{\n6,0,727},{142,11,12},{133,0,1021},{134,0,1190},{134,11,1657},{5,10,143},{5,10,\n769},{6,10,1760},{7,10,682},{7,10,1992},{136,10,736},{132,0,153},{135,11,127},{\n133,0,798},{132,0,587},{6,0,598},{7,0,42},{8,0,695},{10,0,212},{11,0,158},{14,0,\n196},{145,0,85},{133,10,860},{6,0,1929},{134,0,1933},{5,0,957},{5,0,1008},{9,0,\n577},{12,0,141},{6,10,422},{7,10,0},{7,10,1544},{8,11,364},{11,10,990},{12,10,\n453},{13,10,47},{141,10,266},{134,0,1319},{4,0,129},{135,0,465},{7,0,470},{7,0,\n1057},{7,0,1201},{9,0,755},{11,0,906},{140,0,527},{7,0,908},{146,0,7},{5,0,148},\n{136,0,450},{5,10,515},{137,10,131},{7,10,1605},{11,10,962},{146,10,139},{132,10\n,646},{134,0,1166},{4,10,396},{7,10,728},{9,10,117},{13,10,202},{148,10,51},{6,\n10,121},{6,10,124},{6,10,357},{7,10,1138},{7,10,1295},{8,10,162},{139,10,655},{\n14,0,374},{142,11,374},{138,0,253},{139,0,1003},{5,11,909},{9,11,849},{138,11,\n805},{133,10,237},{7,11,525},{7,11,1579},{8,11,497},{136,11,573},{137,0,46},{132\n,0,879},{134,0,806},{135,0,1868},{6,0,1837},{134,0,1846},{6,0,730},{134,0,881},{\n7,0,965},{7,0,1460},{7,0,1604},{7,11,193},{7,11,397},{7,11,1105},{8,11,124},{8,\n11,619},{9,11,305},{10,11,264},{11,11,40},{12,11,349},{13,11,134},{13,11,295},{\n14,11,155},{15,11,120},{146,11,105},{136,0,506},{143,0,10},{4,11,262},{7,11,342}\n,{7,10,571},{7,10,1877},{10,10,366},{141,11,23},{133,11,641},{10,0,22},{9,10,513\n},{10,10,39},{12,10,122},{140,10,187},{135,11,1431},{150,11,49},{4,11,99},{6,11,\n250},{6,11,346},{8,11,127},{138,11,81},{6,0,2014},{8,0,928},{10,0,960},{10,0,979\n},{140,0,996},{134,0,296},{132,11,915},{5,11,75},{9,11,517},{10,11,470},{12,11,\n155},{141,11,224},{137,10,873},{4,0,854},{140,11,18},{134,0,587},{7,10,107},{7,\n10,838},{8,10,550},{138,10,401},{11,0,636},{15,0,145},{17,0,34},{19,0,50},{23,0,\n20},{11,10,588},{11,10,864},{11,10,968},{143,10,160},{135,11,216},{7,0,982},{10,\n0,32},{143,0,56},{133,10,768},{133,11,954},{6,11,304},{7,11,1114},{8,11,418},{10\n,11,345},{11,11,341},{11,11,675},{141,11,40},{9,11,410},{139,11,425},{136,0,941}\n,{5,0,435},{132,10,894},{5,0,85},{6,0,419},{7,0,134},{7,0,305},{7,0,361},{7,0,\n1337},{8,0,71},{140,0,519},{140,0,688},{135,0,740},{5,0,691},{7,0,345},{9,0,94},\n{140,0,169},{5,0,183},{6,0,582},{10,0,679},{140,0,435},{134,11,14},{6,0,945},{\n135,0,511},{134,11,1708},{5,11,113},{6,11,243},{7,11,1865},{11,11,161},{16,11,37\n},{145,11,99},{132,11,274},{137,0,539},{7,0,1993},{8,0,684},{134,10,272},{6,0,\n659},{134,0,982},{4,10,9},{5,10,128},{7,10,368},{11,10,480},{148,10,3},{134,0,\n583},{132,0,803},{133,0,704},{4,0,179},{5,0,198},{133,0,697},{7,0,347},{7,0,971}\n,{8,0,181},{10,0,711},{135,11,166},{136,10,682},{4,10,2},{7,10,545},{7,10,894},{\n136,11,521},{135,0,481},{132,0,243},{5,0,203},{7,0,19},{7,0,71},{7,0,113},{10,0,\n405},{11,0,357},{142,0,240},{5,11,725},{5,11,727},{135,11,1811},{6,0,826},{137,\n11,304},{7,0,1450},{139,0,99},{133,11,654},{134,0,492},{5,0,134},{6,0,408},{6,0,\n495},{7,0,1593},{6,11,273},{10,11,188},{13,11,377},{146,11,77},{9,10,769},{140,\n10,185},{135,11,410},{142,0,4},{4,0,665},{134,11,1785},{4,0,248},{7,0,137},{137,\n0,349},{5,10,530},{142,10,113},{7,0,1270},{139,0,612},{132,11,780},{5,0,371},{\n135,0,563},{135,0,826},{6,0,1535},{23,0,21},{151,0,23},{4,0,374},{7,0,547},{7,0,\n1700},{7,0,1833},{139,0,858},{133,10,556},{7,11,612},{8,11,545},{8,11,568},{8,11\n,642},{9,11,717},{10,11,541},{10,11,763},{11,11,449},{12,11,489},{13,11,153},{13\n,11,296},{14,11,138},{14,11,392},{15,11,50},{16,11,6},{16,11,12},{148,11,9},{9,0\n,311},{141,0,42},{8,10,16},{140,10,568},{6,0,1968},{6,0,2027},{138,0,991},{6,0,\n1647},{7,0,1552},{7,0,2010},{9,0,494},{137,0,509},{133,11,948},{6,10,186},{137,\n10,426},{134,0,769},{134,0,642},{132,10,585},{6,0,123},{7,0,214},{9,0,728},{10,0\n,157},{11,0,346},{11,0,662},{143,0,106},{142,11,381},{135,0,1435},{4,11,532},{5,\n11,706},{135,11,662},{5,11,837},{134,11,1651},{4,10,93},{5,10,252},{6,10,229},{7\n,10,291},{9,10,550},{139,10,644},{148,0,79},{137,10,749},{134,0,1425},{137,10,\n162},{4,11,362},{7,11,52},{7,11,303},{140,11,166},{132,10,381},{4,11,330},{7,11,\n933},{7,11,2012},{136,11,292},{135,11,767},{4,0,707},{5,0,588},{6,0,393},{13,0,\n106},{18,0,49},{147,0,41},{6,0,211},{7,0,1690},{11,0,486},{140,0,369},{137,11,\n883},{4,11,703},{135,11,207},{4,0,187},{5,0,184},{5,0,690},{7,0,1869},{10,0,756}\n,{139,0,783},{132,11,571},{134,0,1382},{5,0,175},{6,10,77},{6,10,157},{7,10,974}\n,{7,10,1301},{7,10,1339},{7,10,1490},{7,10,1873},{137,10,628},{134,0,1493},{5,11\n,873},{133,11,960},{134,0,1007},{12,11,93},{12,11,501},{13,11,362},{14,11,151},{\n15,11,40},{15,11,59},{16,11,46},{17,11,25},{18,11,14},{18,11,134},{19,11,25},{19\n,11,69},{20,11,16},{20,11,19},{20,11,66},{21,11,23},{21,11,25},{150,11,42},{11,\n10,919},{141,10,409},{134,0,219},{5,0,582},{6,0,1646},{7,0,99},{7,0,1962},{7,0,\n1986},{8,0,515},{8,0,773},{9,0,23},{9,0,491},{12,0,620},{142,0,93},{133,0,851},{\n5,11,33},{134,11,470},{135,11,1291},{134,0,1278},{135,11,1882},{135,10,1489},{\n132,0,1000},{138,0,982},{8,0,762},{8,0,812},{137,0,910},{6,11,47},{7,11,90},{7,\n11,664},{7,11,830},{7,11,1380},{7,11,2025},{8,11,448},{136,11,828},{4,0,98},{4,0\n,940},{6,0,1819},{6,0,1834},{6,0,1841},{7,0,1365},{8,0,859},{8,0,897},{8,0,918},\n{9,0,422},{9,0,670},{10,0,775},{10,0,894},{10,0,909},{10,0,910},{10,0,935},{11,0\n,210},{12,0,750},{12,0,755},{13,0,26},{13,0,457},{13,0,476},{16,0,100},{16,0,109\n},{18,0,173},{18,0,175},{8,10,398},{9,10,681},{139,10,632},{9,11,417},{137,11,\n493},{136,10,645},{138,0,906},{134,0,1730},{134,10,20},{133,11,1019},{134,0,1185\n},{10,0,40},{136,10,769},{9,0,147},{134,11,208},{140,0,650},{5,0,209},{6,0,30},{\n11,0,56},{139,0,305},{132,0,553},{138,11,344},{6,11,68},{7,11,398},{7,11,448},{7\n,11,1629},{7,11,1813},{8,11,387},{8,11,442},{9,11,710},{10,11,282},{138,11,722},\n{5,0,597},{14,0,20},{142,11,20},{135,0,1614},{135,10,1757},{4,0,150},{5,0,303},{\n6,0,327},{135,10,937},{16,0,49},{7,10,1652},{144,11,49},{8,0,192},{10,0,78},{141\n,0,359},{135,0,786},{143,0,134},{6,0,1638},{7,0,79},{7,0,496},{9,0,138},{10,0,\n336},{11,0,12},{12,0,412},{12,0,440},{142,0,305},{136,11,491},{4,10,579},{5,10,\n226},{5,10,323},{135,10,960},{7,0,204},{7,0,415},{8,0,42},{10,0,85},{139,0,564},\n{132,0,614},{4,11,403},{5,11,441},{7,11,450},{11,11,101},{12,11,193},{141,11,430\n},{135,11,1927},{135,11,1330},{4,0,3},{5,0,247},{5,0,644},{7,0,744},{7,0,1207},{\n7,0,1225},{7,0,1909},{146,0,147},{136,0,942},{4,0,1019},{134,0,2023},{5,11,679},\n{133,10,973},{5,0,285},{9,0,67},{13,0,473},{143,0,82},{7,11,328},{137,11,326},{\n151,0,8},{6,10,135},{135,10,1176},{135,11,1128},{134,0,1309},{135,11,1796},{135,\n10,314},{4,11,574},{7,11,350},{7,11,1024},{8,11,338},{9,11,677},{10,11,808},{139\n,11,508},{7,11,818},{17,11,14},{17,11,45},{18,11,75},{148,11,18},{146,10,4},{135\n,11,1081},{4,0,29},{6,0,532},{7,0,1628},{7,0,1648},{9,0,350},{10,0,433},{11,0,97\n},{11,0,557},{11,0,745},{12,0,289},{12,0,335},{12,0,348},{12,0,606},{13,0,116},{\n13,0,233},{13,0,466},{14,0,181},{14,0,209},{14,0,232},{14,0,236},{14,0,300},{16,\n0,41},{148,0,97},{7,0,318},{6,10,281},{8,10,282},{8,10,480},{8,10,499},{9,10,198\n},{10,10,143},{10,10,169},{10,10,211},{10,10,417},{10,10,574},{11,10,147},{11,10\n,395},{12,10,75},{12,10,407},{12,10,608},{13,10,500},{142,10,251},{135,11,1676},\n{135,11,2037},{135,0,1692},{5,0,501},{7,0,1704},{9,0,553},{11,0,520},{12,0,557},\n{141,0,249},{6,0,1527},{14,0,324},{15,0,55},{15,0,80},{14,11,324},{15,11,55},{\n143,11,80},{135,10,1776},{8,0,988},{137,11,297},{132,10,419},{142,0,223},{139,11\n,234},{7,0,1123},{12,0,508},{14,0,102},{14,0,226},{144,0,57},{4,10,138},{7,10,\n1012},{7,10,1280},{137,10,76},{7,0,1764},{5,10,29},{140,10,638},{134,0,2015},{\n134,0,1599},{138,11,56},{6,11,306},{7,11,1140},{7,11,1340},{8,11,133},{138,11,\n449},{139,11,1011},{6,10,1710},{135,10,2038},{7,11,1763},{140,11,310},{6,0,129},\n{4,10,17},{5,10,23},{7,10,995},{11,10,383},{11,10,437},{12,10,460},{140,10,532},\n{5,11,329},{136,11,260},{133,10,862},{132,0,534},{6,0,811},{135,0,626},{132,11,\n657},{4,0,25},{5,0,60},{6,0,504},{7,0,614},{7,0,1155},{12,0,0},{152,11,7},{7,0,\n1248},{11,0,621},{139,0,702},{137,0,321},{8,10,70},{12,10,171},{141,10,272},{10,\n10,233},{139,10,76},{4,0,379},{7,0,1397},{134,10,442},{5,11,66},{7,11,1896},{136\n,11,288},{134,11,1643},{134,10,1709},{4,11,21},{5,11,91},{5,11,570},{5,11,648},{\n5,11,750},{5,11,781},{6,11,54},{6,11,112},{6,11,402},{6,11,1732},{7,11,315},{7,\n11,749},{7,11,1347},{7,11,1900},{9,11,78},{9,11,508},{10,11,611},{11,11,510},{11\n,11,728},{13,11,36},{14,11,39},{16,11,83},{17,11,124},{148,11,30},{4,0,118},{6,0\n,274},{6,0,361},{7,0,75},{141,0,441},{10,11,322},{10,11,719},{139,11,407},{147,\n10,119},{12,11,549},{14,11,67},{147,11,60},{11,10,69},{12,10,105},{12,10,117},{\n13,10,213},{14,10,13},{14,10,62},{14,10,177},{14,10,421},{15,10,19},{146,10,141}\n,{9,0,841},{137,10,309},{7,10,608},{7,10,976},{8,11,125},{8,11,369},{8,11,524},{\n9,10,146},{10,10,206},{10,11,486},{10,10,596},{11,11,13},{11,11,381},{11,11,736}\n,{11,11,766},{11,11,845},{13,11,114},{13,10,218},{13,11,292},{14,11,47},{142,10,\n153},{12,0,693},{135,11,759},{5,0,314},{6,0,221},{7,0,419},{10,0,650},{11,0,396}\n,{12,0,156},{13,0,369},{14,0,333},{145,0,47},{6,11,1684},{6,11,1731},{7,11,356},\n{7,11,1932},{8,11,54},{8,11,221},{9,11,225},{9,11,356},{10,11,77},{10,11,446},{\n10,11,731},{12,11,404},{141,11,491},{132,11,375},{4,10,518},{135,10,1136},{4,0,\n913},{4,11,411},{11,11,643},{140,11,115},{4,11,80},{133,11,44},{8,10,689},{137,\n10,863},{138,0,880},{4,10,18},{7,10,145},{7,10,444},{7,10,1278},{8,10,49},{8,10,\n400},{9,10,71},{9,10,250},{10,10,459},{12,10,160},{144,10,24},{136,0,475},{5,0,\n1016},{5,11,299},{135,11,1083},{7,0,602},{8,0,179},{10,0,781},{140,0,126},{6,0,\n329},{138,0,111},{135,0,1864},{4,11,219},{7,11,1761},{137,11,86},{6,0,1888},{6,0\n,1892},{6,0,1901},{6,0,1904},{9,0,953},{9,0,985},{9,0,991},{9,0,1001},{12,0,818}\n,{12,0,846},{12,0,847},{12,0,861},{12,0,862},{12,0,873},{12,0,875},{12,0,877},{\n12,0,879},{12,0,881},{12,0,884},{12,0,903},{12,0,915},{12,0,926},{12,0,939},{15,\n0,182},{15,0,219},{15,0,255},{18,0,191},{18,0,209},{18,0,211},{149,0,41},{5,11,\n328},{135,11,918},{137,0,780},{12,0,82},{143,0,36},{133,10,1010},{5,0,821},{134,\n0,1687},{133,11,514},{132,0,956},{134,0,1180},{10,0,112},{5,10,87},{7,10,313},{7\n,10,1103},{10,10,582},{11,10,389},{11,10,813},{12,10,385},{13,10,286},{14,10,124\n},{146,10,108},{5,0,71},{7,0,1407},{9,0,704},{10,0,261},{10,0,619},{11,0,547},{\n11,0,619},{143,0,157},{4,0,531},{5,0,455},{5,11,301},{6,11,571},{14,11,49},{146,\n11,102},{132,10,267},{6,0,385},{7,0,2008},{9,0,337},{138,0,517},{133,11,726},{\n133,11,364},{4,11,76},{7,11,1550},{9,11,306},{9,11,430},{9,11,663},{10,11,683},{\n11,11,427},{11,11,753},{12,11,334},{12,11,442},{14,11,258},{14,11,366},{143,11,\n131},{6,0,1865},{6,0,1879},{6,0,1881},{6,0,1894},{6,0,1908},{9,0,915},{9,0,926},\n{9,0,940},{9,0,943},{9,0,966},{9,0,980},{9,0,989},{9,0,1005},{9,0,1010},{12,0,\n813},{12,0,817},{12,0,840},{12,0,843},{12,0,855},{12,0,864},{12,0,871},{12,0,872\n},{12,0,899},{12,0,905},{12,0,924},{15,0,171},{15,0,181},{15,0,224},{15,0,235},{\n15,0,251},{146,0,184},{137,11,52},{5,0,16},{6,0,86},{6,0,603},{7,0,292},{7,0,561\n},{8,0,257},{8,0,382},{9,0,721},{9,0,778},{11,0,581},{140,0,466},{4,0,486},{5,0,\n491},{135,10,1121},{4,0,72},{6,0,265},{135,0,1300},{135,11,1183},{10,10,249},{\n139,10,209},{132,10,561},{137,11,519},{4,11,656},{4,10,760},{135,11,779},{9,10,\n154},{140,10,485},{135,11,1793},{135,11,144},{136,10,255},{133,0,621},{4,10,368}\n,{135,10,641},{135,11,1373},{7,11,554},{7,11,605},{141,11,10},{137,0,234},{5,0,\n815},{6,0,1688},{134,0,1755},{5,11,838},{5,11,841},{134,11,1649},{7,0,1987},{7,0\n,2040},{136,0,743},{133,11,1012},{6,0,197},{136,0,205},{6,0,314},{134,11,314},{\n144,11,53},{6,11,251},{7,11,365},{7,11,1357},{7,11,1497},{8,11,154},{141,11,281}\n,{133,11,340},{6,0,452},{7,0,312},{138,0,219},{138,0,589},{4,0,333},{9,0,176},{\n12,0,353},{141,0,187},{9,10,92},{147,10,91},{134,0,1110},{11,0,47},{139,11,495},\n{6,10,525},{8,10,806},{9,10,876},{140,10,284},{8,11,261},{9,11,144},{9,11,466},{\n10,11,370},{12,11,470},{13,11,144},{142,11,348},{137,11,897},{8,0,863},{8,0,864}\n,{8,0,868},{8,0,884},{10,0,866},{10,0,868},{10,0,873},{10,0,911},{10,0,912},{10,\n0,944},{12,0,727},{6,11,248},{9,11,546},{10,11,535},{11,11,681},{141,11,135},{6,\n0,300},{135,0,1515},{134,0,1237},{139,10,958},{133,10,594},{140,11,250},{134,0,\n1685},{134,11,567},{7,0,135},{8,0,7},{8,0,62},{9,0,243},{10,0,658},{10,0,697},{\n11,0,456},{139,0,756},{9,0,395},{138,0,79},{6,10,1641},{136,10,820},{4,10,302},{\n135,10,1766},{134,11,174},{135,10,1313},{135,0,631},{134,10,1674},{134,11,395},{\n138,0,835},{7,0,406},{7,0,459},{8,0,606},{139,0,726},{134,11,617},{134,0,979},{6\n,10,389},{7,10,149},{9,10,142},{138,10,94},{5,11,878},{133,11,972},{6,10,8},{7,\n10,1881},{8,10,91},{136,11,511},{133,0,612},{132,11,351},{4,0,372},{7,0,482},{8,\n0,158},{9,0,602},{9,0,615},{10,0,245},{10,0,678},{10,0,744},{11,0,248},{139,0,\n806},{5,0,854},{135,0,1991},{132,11,286},{135,11,344},{7,11,438},{7,11,627},{7,\n11,1516},{8,11,40},{9,11,56},{9,11,294},{10,11,30},{10,11,259},{11,11,969},{146,\n11,148},{135,0,1492},{5,11,259},{7,11,414},{7,11,854},{142,11,107},{135,10,1746}\n,{6,0,833},{134,0,998},{135,10,24},{6,0,750},{135,0,1739},{4,10,503},{135,10,\n1661},{5,10,130},{7,10,1314},{9,10,610},{10,10,718},{11,10,601},{11,10,819},{11,\n10,946},{140,10,536},{10,10,149},{11,10,280},{142,10,336},{132,11,738},{135,10,\n1946},{5,0,195},{135,0,1685},{7,0,1997},{8,0,730},{139,0,1006},{151,11,17},{133,\n11,866},{14,0,463},{14,0,470},{150,0,61},{5,0,751},{8,0,266},{11,0,578},{4,10,\n392},{135,10,1597},{5,10,433},{9,10,633},{139,10,629},{135,0,821},{6,0,715},{134\n,0,1325},{133,11,116},{6,0,868},{132,11,457},{134,0,959},{6,10,234},{138,11,199}\n,{7,0,1053},{7,10,1950},{8,10,680},{11,10,817},{147,10,88},{7,10,1222},{138,10,\n386},{5,0,950},{5,0,994},{6,0,351},{134,0,1124},{134,0,1081},{7,0,1595},{6,10,5}\n,{11,10,249},{12,10,313},{16,10,66},{145,10,26},{148,0,59},{5,11,527},{6,11,189}\n,{135,11,859},{5,10,963},{6,10,1773},{11,11,104},{11,11,554},{15,11,60},{143,11,\n125},{135,0,47},{137,0,684},{134,11,116},{134,0,1606},{134,0,777},{7,0,1020},{8,\n10,509},{136,10,792},{135,0,1094},{132,0,350},{133,11,487},{4,11,86},{5,11,667},\n{5,11,753},{6,11,316},{6,11,455},{135,11,946},{7,0,1812},{13,0,259},{13,0,356},{\n14,0,242},{147,0,114},{132,10,931},{133,0,967},{4,0,473},{7,0,623},{8,0,808},{9,\n0,871},{9,0,893},{11,0,38},{11,0,431},{12,0,112},{12,0,217},{12,0,243},{12,0,562\n},{12,0,663},{12,0,683},{13,0,141},{13,0,197},{13,0,227},{13,0,406},{13,0,487},{\n14,0,156},{14,0,203},{14,0,224},{14,0,256},{18,0,58},{150,0,0},{138,0,286},{7,10\n,943},{139,10,614},{135,10,1837},{150,11,45},{132,0,798},{4,0,222},{7,0,286},{\n136,0,629},{4,11,79},{7,11,1773},{10,11,450},{11,11,589},{13,11,332},{13,11,493}\n,{14,11,183},{14,11,334},{14,11,362},{14,11,368},{14,11,376},{14,11,379},{19,11,\n90},{19,11,103},{19,11,127},{148,11,90},{5,0,337},{11,0,513},{11,0,889},{11,0,\n961},{12,0,461},{13,0,79},{15,0,121},{4,10,90},{5,10,545},{7,10,754},{9,10,186},\n{10,10,72},{10,10,782},{11,10,577},{11,10,610},{12,10,354},{12,10,362},{140,10,\n595},{141,0,306},{136,0,146},{7,0,1646},{9,10,329},{11,10,254},{141,11,124},{4,0\n,465},{135,0,1663},{132,0,525},{133,11,663},{10,0,299},{18,0,74},{9,10,187},{11,\n10,1016},{145,10,44},{7,0,165},{7,0,919},{4,10,506},{136,10,517},{5,10,295},{135\n,10,1680},{133,11,846},{134,0,1064},{5,11,378},{7,11,1402},{7,11,1414},{8,11,465\n},{9,11,286},{10,11,185},{10,11,562},{10,11,635},{11,11,31},{11,11,393},{12,11,\n456},{13,11,312},{18,11,65},{18,11,96},{147,11,89},{132,0,596},{7,10,987},{9,10,\n688},{10,10,522},{11,10,788},{140,10,566},{6,0,82},{7,0,138},{7,0,517},{7,0,1741\n},{11,0,238},{4,11,648},{134,10,1775},{7,0,1233},{7,10,700},{7,10,940},{8,10,514\n},{9,10,116},{9,10,535},{10,10,118},{11,10,107},{11,10,148},{11,10,922},{12,10,\n254},{12,10,421},{142,10,238},{4,0,962},{6,0,1824},{8,0,894},{12,0,708},{12,0,\n725},{14,0,451},{20,0,94},{22,0,59},{150,0,62},{5,11,945},{6,11,1656},{6,11,1787\n},{7,11,167},{8,11,824},{9,11,391},{10,11,375},{139,11,185},{5,0,495},{7,0,834},\n{9,0,733},{139,0,378},{4,10,743},{135,11,1273},{6,0,1204},{7,11,1645},{8,11,352}\n,{137,11,249},{139,10,292},{133,0,559},{132,11,152},{9,0,499},{10,0,341},{15,0,\n144},{19,0,49},{7,10,1283},{9,10,227},{11,10,325},{11,10,408},{14,10,180},{146,\n10,47},{6,0,21},{6,0,1737},{7,0,1444},{136,0,224},{133,11,1006},{7,0,1446},{9,0,\n97},{17,0,15},{5,10,81},{7,10,146},{7,10,1342},{8,10,53},{8,10,561},{8,10,694},{\n8,10,754},{9,10,115},{9,10,894},{10,10,462},{10,10,813},{11,10,230},{11,10,657},\n{11,10,699},{11,10,748},{12,10,119},{12,10,200},{12,10,283},{142,10,273},{5,10,\n408},{137,10,747},{135,11,431},{135,11,832},{6,0,729},{134,0,953},{4,0,727},{8,0\n,565},{5,11,351},{7,11,264},{136,11,565},{134,0,1948},{5,0,519},{5,11,40},{7,11,\n598},{7,11,1638},{8,11,78},{9,11,166},{9,11,640},{9,11,685},{9,11,773},{11,11,\n215},{13,11,65},{14,11,172},{14,11,317},{145,11,6},{8,11,60},{9,11,343},{139,11,\n769},{137,11,455},{134,0,1193},{140,0,790},{7,11,1951},{8,11,765},{8,11,772},{\n140,11,671},{7,11,108},{8,11,219},{8,11,388},{9,11,639},{9,11,775},{11,11,275},{\n140,11,464},{132,11,468},{7,10,30},{8,10,86},{8,10,315},{8,10,700},{9,10,576},{9\n,10,858},{11,10,310},{11,10,888},{11,10,904},{12,10,361},{141,10,248},{5,11,15},\n{6,11,56},{7,11,1758},{8,11,500},{9,11,730},{11,11,331},{13,11,150},{142,11,282}\n,{4,0,402},{7,0,2},{8,0,323},{136,0,479},{138,10,839},{11,0,580},{142,0,201},{5,\n0,59},{135,0,672},{137,10,617},{146,0,34},{134,11,1886},{4,0,961},{136,0,896},{6\n,0,1285},{5,11,205},{6,11,438},{137,11,711},{134,10,428},{7,10,524},{8,10,169},{\n8,10,234},{9,10,480},{138,10,646},{148,0,46},{141,0,479},{133,11,534},{6,0,2019}\n,{134,10,1648},{4,0,85},{7,0,549},{7,10,1205},{138,10,637},{4,0,663},{5,0,94},{7\n,11,235},{7,11,1475},{15,11,68},{146,11,120},{6,11,443},{9,11,237},{9,11,571},{9\n,11,695},{10,11,139},{11,11,715},{12,11,417},{141,11,421},{132,0,783},{4,0,682},\n{8,0,65},{9,10,39},{10,10,166},{11,10,918},{12,10,635},{20,10,10},{22,10,27},{22\n,10,43},{150,10,52},{6,0,11},{135,0,187},{132,0,522},{4,0,52},{135,0,661},{4,0,\n383},{133,0,520},{135,11,546},{11,0,343},{142,0,127},{4,11,578},{7,10,157},{7,11\n,624},{7,11,916},{8,10,279},{10,11,256},{11,11,87},{139,11,703},{134,10,604},{4,\n0,281},{5,0,38},{7,0,194},{7,0,668},{7,0,1893},{137,0,397},{7,10,945},{11,10,713\n},{139,10,744},{139,10,1022},{9,0,635},{139,0,559},{5,11,923},{7,11,490},{12,11,\n553},{13,11,100},{14,11,118},{143,11,75},{132,0,975},{132,10,567},{137,10,859},{\n7,10,1846},{7,11,1846},{8,10,628},{136,11,628},{148,0,116},{138,11,750},{14,0,51\n},{14,11,51},{15,11,7},{148,11,20},{132,0,858},{134,0,1075},{4,11,924},{133,10,\n762},{136,0,535},{133,0,448},{10,10,784},{141,10,191},{133,10,298},{7,0,610},{\n135,0,1501},{7,10,633},{7,10,905},{7,10,909},{7,10,1538},{9,10,767},{140,10,636}\n,{4,11,265},{7,11,807},{135,11,950},{5,11,93},{12,11,267},{144,11,26},{136,0,191\n},{139,10,301},{135,10,1970},{135,0,267},{4,0,319},{5,0,699},{138,0,673},{6,0,\n336},{7,0,92},{7,0,182},{8,0,453},{8,0,552},{9,0,204},{9,0,285},{10,0,99},{11,0,\n568},{11,0,950},{12,0,94},{16,0,20},{16,0,70},{19,0,55},{12,10,644},{144,10,90},\n{6,0,551},{7,0,1308},{7,10,845},{7,11,994},{8,10,160},{137,10,318},{19,11,1},{19\n,11,26},{150,11,9},{7,0,1406},{9,0,218},{141,0,222},{5,0,256},{138,0,69},{5,11,\n233},{5,11,320},{6,11,140},{7,11,330},{136,11,295},{6,0,1980},{136,0,952},{4,0,\n833},{137,11,678},{133,11,978},{4,11,905},{6,11,1701},{137,11,843},{138,10,735},\n{136,10,76},{17,0,39},{148,0,36},{18,0,81},{146,11,81},{14,0,352},{17,0,53},{18,\n0,146},{18,0,152},{19,0,11},{150,0,54},{135,0,634},{138,10,841},{132,0,618},{4,0\n,339},{7,0,259},{17,0,73},{4,11,275},{140,11,376},{132,11,509},{7,11,273},{139,\n11,377},{4,0,759},{13,0,169},{137,10,804},{6,10,96},{135,10,1426},{4,10,651},{\n133,10,289},{7,0,1075},{8,10,35},{9,10,511},{10,10,767},{147,10,118},{6,0,649},{\n6,0,670},{136,0,482},{5,0,336},{6,0,341},{6,0,478},{6,0,1763},{136,0,386},{5,11,\n802},{7,11,2021},{8,11,805},{14,11,94},{15,11,65},{16,11,4},{16,11,77},{16,11,80\n},{145,11,5},{6,0,1035},{5,11,167},{5,11,899},{6,11,410},{137,11,777},{134,11,\n1705},{5,0,924},{133,0,969},{132,10,704},{135,0,73},{135,11,10},{135,10,1078},{5\n,11,11},{6,11,117},{6,11,485},{7,11,1133},{9,11,582},{9,11,594},{11,11,21},{11,\n11,818},{12,11,535},{141,11,86},{135,0,1971},{4,11,264},{7,11,1067},{8,11,204},{\n8,11,385},{139,11,953},{6,0,1458},{135,0,1344},{5,0,396},{134,0,501},{4,10,720},\n{133,10,306},{4,0,929},{5,0,799},{8,0,46},{8,0,740},{133,10,431},{7,11,646},{7,\n11,1730},{11,11,446},{141,11,178},{7,0,276},{5,10,464},{6,10,236},{7,10,696},{7,\n10,914},{7,10,1108},{7,10,1448},{9,10,15},{9,10,564},{10,10,14},{12,10,565},{13,\n10,449},{14,10,53},{15,10,13},{16,10,64},{145,10,41},{4,0,892},{133,0,770},{6,10\n,1767},{12,10,194},{145,10,107},{135,0,158},{5,10,840},{138,11,608},{134,0,1432}\n,{138,11,250},{8,11,794},{9,11,400},{10,11,298},{142,11,228},{151,0,25},{7,11,\n1131},{135,11,1468},{135,0,2001},{9,10,642},{11,10,236},{142,10,193},{4,10,68},{\n5,10,634},{6,10,386},{7,10,794},{8,10,273},{9,10,563},{10,10,105},{10,10,171},{\n11,10,94},{139,10,354},{136,11,724},{132,0,478},{11,11,512},{13,11,205},{19,11,\n30},{22,11,36},{151,11,19},{7,0,1461},{140,0,91},{6,11,190},{7,11,768},{135,11,\n1170},{4,0,602},{8,0,211},{4,10,95},{7,10,416},{139,10,830},{7,10,731},{13,10,20\n},{143,10,11},{6,0,1068},{135,0,1872},{4,0,13},{5,0,567},{7,0,1498},{9,0,124},{\n11,0,521},{12,0,405},{135,11,1023},{135,0,1006},{132,0,735},{138,0,812},{4,0,170\n},{135,0,323},{6,11,137},{9,11,75},{9,11,253},{10,11,194},{138,11,444},{5,0,304}\n,{7,0,1403},{5,10,864},{10,10,648},{11,10,671},{143,10,46},{135,11,1180},{133,10\n,928},{4,0,148},{133,0,742},{11,10,986},{140,10,682},{133,0,523},{135,11,1743},{\n7,0,730},{18,0,144},{19,0,61},{8,10,44},{9,10,884},{10,10,580},{11,10,399},{11,\n10,894},{143,10,122},{5,11,760},{7,11,542},{8,11,135},{136,11,496},{136,0,981},{\n133,0,111},{10,0,132},{11,0,191},{11,0,358},{139,0,460},{7,11,319},{7,11,355},{7\n,11,763},{10,11,389},{145,11,43},{134,0,890},{134,0,1420},{136,11,557},{133,10,\n518},{133,0,444},{135,0,1787},{135,10,1852},{8,0,123},{15,0,6},{144,0,7},{6,0,\n2041},{10,11,38},{139,11,784},{136,0,932},{5,0,937},{135,0,100},{6,0,995},{4,11,\n58},{5,11,286},{6,11,319},{7,11,402},{7,11,1254},{7,11,1903},{8,11,356},{140,11,\n408},{4,11,389},{9,11,181},{9,11,255},{10,11,8},{10,11,29},{10,11,816},{11,11,\n311},{11,11,561},{12,11,67},{141,11,181},{138,0,255},{5,0,138},{4,10,934},{136,\n10,610},{4,0,965},{10,0,863},{138,0,898},{10,10,804},{138,10,832},{12,0,631},{8,\n10,96},{9,10,36},{10,10,607},{11,10,423},{11,10,442},{12,10,309},{14,10,199},{15\n,10,90},{145,10,110},{134,0,1394},{4,0,652},{8,0,320},{22,0,6},{22,0,16},{9,10,\n13},{9,10,398},{9,10,727},{10,10,75},{10,10,184},{10,10,230},{10,10,564},{10,10,\n569},{11,10,973},{12,10,70},{12,10,189},{13,10,57},{141,10,257},{6,0,897},{134,0\n,1333},{4,0,692},{133,0,321},{133,11,373},{135,0,922},{5,0,619},{133,0,698},{137\n,10,631},{5,10,345},{135,10,1016},{9,0,957},{9,0,1018},{12,0,828},{12,0,844},{12\n,0,897},{12,0,901},{12,0,943},{15,0,180},{18,0,197},{18,0,200},{18,0,213},{18,0,\n214},{146,0,226},{5,0,917},{134,0,1659},{135,0,1100},{134,0,1173},{134,0,1930},{\n5,0,251},{5,0,956},{8,0,268},{9,0,214},{146,0,142},{133,10,673},{137,10,850},{4,\n10,287},{133,10,1018},{132,11,672},{5,0,346},{5,0,711},{8,0,390},{11,11,752},{\n139,11,885},{5,10,34},{10,10,724},{12,10,444},{13,10,354},{18,10,32},{23,10,24},\n{23,10,31},{152,10,5},{4,11,710},{134,11,606},{134,0,744},{134,10,382},{133,11,\n145},{4,10,329},{7,11,884},{140,11,124},{4,11,467},{5,11,405},{134,11,544},{9,10\n,846},{138,10,827},{133,0,624},{9,11,372},{15,11,2},{19,11,10},{147,11,18},{4,11\n,387},{135,11,1288},{5,0,783},{7,0,1998},{135,0,2047},{132,10,906},{136,10,366},\n{135,11,550},{4,10,123},{4,10,649},{5,10,605},{7,10,1509},{136,10,36},{134,0,\n1125},{132,0,594},{133,10,767},{135,11,1227},{136,11,467},{4,11,576},{135,11,\n1263},{4,0,268},{7,0,1534},{135,11,1534},{4,10,273},{5,10,658},{5,11,919},{5,10,\n995},{134,11,1673},{133,0,563},{134,10,72},{135,10,1345},{4,11,82},{5,11,333},{5\n,11,904},{6,11,207},{7,11,325},{7,11,1726},{8,11,101},{10,11,778},{139,11,220},{\n5,0,37},{6,0,39},{6,0,451},{7,0,218},{7,0,667},{7,0,1166},{7,0,1687},{8,0,662},{\n16,0,2},{133,10,589},{134,0,1332},{133,11,903},{134,0,508},{5,10,117},{6,10,514}\n,{6,10,541},{7,10,1164},{7,10,1436},{8,10,220},{8,10,648},{10,10,688},{11,10,560\n},{140,11,147},{6,11,555},{135,11,485},{133,10,686},{7,0,453},{7,0,635},{7,0,796\n},{8,0,331},{9,0,330},{9,0,865},{10,0,119},{10,0,235},{11,0,111},{11,0,129},{11,\n0,240},{12,0,31},{12,0,66},{12,0,222},{12,0,269},{12,0,599},{12,0,684},{12,0,689\n},{12,0,691},{142,0,345},{135,0,1834},{4,11,705},{7,11,615},{138,11,251},{136,11\n,345},{137,0,527},{6,0,98},{7,0,702},{135,0,991},{11,0,576},{14,0,74},{7,10,196}\n,{10,10,765},{11,10,347},{11,10,552},{11,10,790},{12,10,263},{13,10,246},{13,10,\n270},{13,10,395},{14,10,176},{14,10,190},{14,10,398},{14,10,412},{15,10,32},{15,\n10,63},{16,10,88},{147,10,105},{134,11,90},{13,0,84},{141,0,122},{6,0,37},{7,0,\n299},{7,0,1666},{8,0,195},{8,0,316},{9,0,178},{9,0,276},{9,0,339},{9,0,536},{10,\n0,102},{10,0,362},{10,0,785},{11,0,55},{11,0,149},{11,0,773},{13,0,416},{13,0,\n419},{14,0,38},{14,0,41},{142,0,210},{5,10,381},{135,10,1792},{7,11,813},{12,11,\n497},{141,11,56},{7,10,616},{138,10,413},{133,0,645},{6,11,125},{135,11,1277},{\n132,0,290},{6,0,70},{7,0,1292},{10,0,762},{139,0,288},{6,10,120},{7,10,1188},{7,\n10,1710},{8,10,286},{9,10,667},{11,10,592},{139,10,730},{135,11,1784},{7,0,1315}\n,{135,11,1315},{134,0,1955},{135,10,1146},{7,0,131},{7,0,422},{8,0,210},{140,0,\n573},{4,10,352},{135,10,687},{139,0,797},{143,0,38},{14,0,179},{15,0,151},{150,0\n,11},{7,0,488},{4,10,192},{5,10,49},{6,10,200},{6,10,293},{134,10,1696},{132,0,\n936},{135,11,703},{6,11,160},{7,11,1106},{9,11,770},{10,11,618},{11,11,112},{140\n,11,413},{5,0,453},{134,0,441},{135,0,595},{132,10,650},{132,10,147},{6,0,991},{\n6,0,1182},{12,11,271},{145,11,109},{133,10,934},{140,11,221},{132,0,653},{7,0,\n505},{135,0,523},{134,0,903},{135,11,479},{7,11,304},{9,11,646},{9,11,862},{10,\n11,262},{11,11,696},{12,11,208},{15,11,79},{147,11,108},{146,0,80},{135,11,981},\n{142,0,432},{132,0,314},{137,11,152},{7,0,1368},{8,0,232},{8,0,361},{10,0,682},{\n138,0,742},{135,11,1586},{9,0,534},{4,11,434},{11,11,663},{12,11,210},{13,11,166\n},{13,11,310},{14,11,373},{147,11,43},{7,11,1091},{135,11,1765},{6,11,550},{135,\n11,652},{137,0,27},{142,0,12},{4,10,637},{5,11,553},{7,11,766},{138,11,824},{7,\n11,737},{8,11,298},{136,11,452},{7,0,736},{139,0,264},{134,0,1657},{133,11,292},\n{138,11,135},{6,0,844},{134,0,1117},{135,0,127},{9,10,867},{138,10,837},{6,0,\n1184},{134,0,1208},{134,0,1294},{136,0,364},{6,0,1415},{7,0,1334},{11,0,125},{6,\n10,170},{7,11,393},{8,10,395},{8,10,487},{10,11,603},{11,11,206},{141,10,147},{\n137,11,748},{4,11,912},{137,11,232},{4,10,535},{136,10,618},{137,0,792},{7,11,\n1973},{136,11,716},{135,11,98},{5,0,909},{9,0,849},{138,0,805},{4,0,630},{132,0,\n699},{5,11,733},{14,11,103},{150,10,23},{12,11,158},{18,11,8},{19,11,62},{20,11,\n6},{22,11,4},{23,11,2},{151,11,9},{132,0,968},{132,10,778},{132,10,46},{5,10,811\n},{6,10,1679},{6,10,1714},{135,10,2032},{6,0,1446},{7,10,1458},{9,10,407},{139,\n10,15},{7,0,206},{7,0,397},{7,0,621},{7,0,640},{8,0,124},{8,0,619},{9,0,305},{9,\n0,643},{10,0,264},{10,0,628},{11,0,40},{12,0,349},{13,0,134},{13,0,295},{14,0,\n155},{15,0,120},{18,0,105},{6,10,34},{7,10,1089},{8,10,708},{8,10,721},{9,10,363\n},{148,10,98},{4,0,262},{5,0,641},{135,0,342},{137,11,72},{4,0,99},{6,0,250},{6,\n0,346},{8,0,127},{138,0,81},{132,0,915},{5,0,75},{9,0,517},{10,0,470},{12,0,155}\n,{141,0,224},{132,10,462},{11,11,600},{11,11,670},{141,11,245},{142,0,83},{5,10,\n73},{6,10,23},{134,10,338},{6,0,1031},{139,11,923},{7,11,164},{7,11,1571},{9,11,\n107},{140,11,225},{134,0,1470},{133,0,954},{6,0,304},{8,0,418},{10,0,345},{11,0,\n341},{139,0,675},{9,0,410},{139,0,425},{4,11,27},{5,11,484},{5,11,510},{6,11,434\n},{7,11,1000},{7,11,1098},{8,11,2},{136,11,200},{134,0,734},{140,11,257},{7,10,\n725},{8,10,498},{139,10,268},{134,0,1822},{135,0,1798},{135,10,773},{132,11,460}\n,{4,11,932},{133,11,891},{134,0,14},{132,10,583},{7,10,1462},{8,11,625},{139,10,\n659},{5,0,113},{6,0,243},{6,0,1708},{7,0,1865},{11,0,161},{16,0,37},{17,0,99},{\n133,10,220},{134,11,76},{5,11,461},{135,11,1925},{140,0,69},{8,11,92},{137,11,\n221},{139,10,803},{132,10,544},{4,0,274},{134,0,922},{132,0,541},{5,0,627},{6,10\n,437},{6,10,564},{11,10,181},{141,10,183},{135,10,1192},{7,0,166},{132,11,763},{\n133,11,253},{134,0,849},{9,11,73},{10,11,110},{14,11,185},{145,11,119},{5,11,212\n},{12,11,35},{141,11,382},{133,0,717},{137,0,304},{136,0,600},{133,0,654},{6,0,\n273},{10,0,188},{13,0,377},{146,0,77},{4,10,790},{5,10,273},{134,10,394},{132,0,\n543},{135,0,410},{11,0,98},{11,0,524},{141,0,87},{132,0,941},{135,11,1175},{4,0,\n250},{7,0,1612},{11,0,186},{12,0,133},{6,10,127},{7,10,1511},{8,10,613},{12,10,\n495},{12,10,586},{12,10,660},{12,10,668},{14,10,385},{15,10,118},{17,10,20},{146\n,10,98},{6,0,1785},{133,11,816},{134,0,1339},{7,0,961},{7,0,1085},{7,0,1727},{8,\n0,462},{6,10,230},{135,11,1727},{9,0,636},{135,10,1954},{132,0,780},{5,11,869},{\n5,11,968},{6,11,1626},{8,11,734},{136,11,784},{4,11,542},{6,11,1716},{6,11,1727}\n,{7,11,1082},{7,11,1545},{8,11,56},{8,11,118},{8,11,412},{8,11,564},{9,11,888},{\n9,11,908},{10,11,50},{10,11,423},{11,11,685},{11,11,697},{11,11,933},{12,11,299}\n,{13,11,126},{13,11,136},{13,11,170},{141,11,190},{134,11,226},{4,11,232},{9,11,\n202},{10,11,474},{140,11,433},{137,11,500},{5,0,529},{136,10,68},{132,10,654},{4\n,10,156},{7,10,998},{7,10,1045},{7,10,1860},{9,10,48},{9,10,692},{11,10,419},{\n139,10,602},{7,0,1276},{8,0,474},{9,0,652},{6,11,108},{7,11,1003},{7,11,1181},{\n136,11,343},{7,11,1264},{7,11,1678},{11,11,945},{12,11,341},{12,11,471},{140,11,\n569},{134,11,1712},{5,0,948},{12,0,468},{19,0,96},{148,0,24},{4,11,133},{7,11,\n711},{7,11,1298},{7,11,1585},{135,11,1929},{6,0,753},{140,0,657},{139,0,941},{6,\n11,99},{7,11,1808},{145,11,57},{6,11,574},{7,11,428},{7,11,1250},{10,11,669},{11\n,11,485},{11,11,840},{12,11,300},{142,11,250},{4,0,532},{5,0,706},{135,0,662},{5\n,0,837},{6,0,1651},{139,0,985},{7,0,1861},{9,10,197},{10,10,300},{12,10,473},{13\n,10,90},{141,10,405},{137,11,252},{6,11,323},{135,11,1564},{4,0,330},{4,0,863},{\n7,0,933},{7,0,2012},{8,0,292},{7,11,461},{8,11,775},{138,11,435},{132,10,606},{4\n,11,655},{7,11,850},{17,11,75},{146,11,137},{135,0,767},{7,10,1978},{136,10,676}\n,{132,0,641},{135,11,1559},{134,0,1233},{137,0,242},{17,0,114},{4,10,361},{133,\n10,315},{137,0,883},{132,10,461},{138,0,274},{134,0,2008},{134,0,1794},{4,0,703}\n,{135,0,207},{12,0,285},{132,10,472},{132,0,571},{5,0,873},{5,0,960},{8,0,823},{\n9,0,881},{136,11,577},{7,0,617},{10,0,498},{11,0,501},{12,0,16},{140,0,150},{138\n,10,747},{132,0,431},{133,10,155},{11,0,283},{11,0,567},{7,10,163},{8,10,319},{9\n,10,402},{10,10,24},{10,10,681},{11,10,200},{12,10,253},{12,10,410},{142,10,219}\n,{4,11,413},{5,11,677},{8,11,432},{140,11,280},{9,0,401},{5,10,475},{7,10,1780},\n{11,10,297},{11,10,558},{14,10,322},{147,10,76},{6,0,781},{9,0,134},{10,0,2},{10\n,0,27},{10,0,333},{11,0,722},{143,0,1},{5,0,33},{6,0,470},{139,0,424},{135,0,\n2006},{12,0,783},{135,10,1956},{136,0,274},{135,0,1882},{132,0,794},{135,0,1848}\n,{5,10,944},{134,10,1769},{6,0,47},{7,0,90},{7,0,664},{7,0,830},{7,0,1380},{7,0,\n2025},{8,0,448},{136,0,828},{132,10,144},{134,0,1199},{4,11,395},{139,11,762},{\n135,11,1504},{9,0,417},{137,0,493},{9,11,174},{10,11,164},{11,11,440},{11,11,841\n},{143,11,98},{134,11,426},{139,11,1002},{134,0,295},{134,0,816},{6,10,247},{137\n,10,555},{133,0,1019},{4,0,620},{5,11,476},{10,10,280},{138,10,797},{139,0,464},\n{5,11,76},{6,11,458},{6,11,497},{7,11,764},{7,11,868},{9,11,658},{10,11,594},{11\n,11,173},{11,11,566},{12,11,20},{12,11,338},{141,11,200},{134,0,208},{4,11,526},\n{7,11,1029},{135,11,1054},{132,11,636},{6,11,233},{7,11,660},{7,11,1124},{17,11,\n31},{19,11,22},{151,11,14},{10,0,442},{133,10,428},{10,0,930},{140,0,778},{6,0,\n68},{7,0,448},{7,0,1629},{7,0,1769},{7,0,1813},{8,0,442},{8,0,516},{9,0,710},{10\n,0,282},{10,0,722},{7,10,1717},{138,10,546},{134,0,1128},{11,0,844},{12,0,104},{\n140,0,625},{4,11,432},{135,11,824},{138,10,189},{133,0,787},{133,10,99},{4,11,\n279},{7,11,301},{137,11,362},{8,0,491},{4,10,397},{136,10,555},{4,11,178},{133,\n11,399},{134,0,711},{144,0,9},{4,0,403},{5,0,441},{7,0,450},{10,0,840},{11,0,101\n},{12,0,193},{141,0,430},{135,11,1246},{12,10,398},{20,10,39},{21,10,11},{150,10\n,41},{4,10,485},{7,10,353},{135,10,1523},{6,10,366},{7,10,1384},{7,10,1601},{135\n,11,1912},{7,0,396},{10,0,160},{135,11,396},{137,10,282},{134,11,1692},{4,10,157\n},{5,10,471},{6,11,202},{10,11,448},{11,11,208},{12,11,360},{17,11,117},{17,11,\n118},{18,11,27},{148,11,67},{133,0,679},{137,0,326},{136,10,116},{7,11,872},{10,\n11,516},{139,11,167},{132,11,224},{5,11,546},{7,11,35},{8,11,11},{8,11,12},{9,11\n,315},{9,11,533},{10,11,802},{11,11,166},{12,11,525},{142,11,243},{7,0,1128},{\n135,11,1920},{5,11,241},{8,11,242},{9,11,451},{10,11,667},{11,11,598},{140,11,\n429},{6,0,737},{5,10,160},{7,10,363},{7,10,589},{10,10,170},{141,10,55},{135,0,\n1796},{142,11,254},{4,0,574},{7,0,350},{7,0,1024},{8,0,338},{9,0,677},{138,0,808\n},{134,0,1096},{137,11,516},{7,0,405},{10,0,491},{4,10,108},{4,11,366},{139,10,\n498},{11,11,337},{142,11,303},{134,11,1736},{7,0,1081},{140,11,364},{7,10,1005},\n{140,10,609},{7,0,1676},{4,10,895},{133,10,772},{135,0,2037},{6,0,1207},{11,11,\n916},{142,11,419},{14,11,140},{148,11,41},{6,11,331},{136,11,623},{9,0,944},{9,0\n,969},{9,0,1022},{12,0,913},{12,0,936},{15,0,177},{15,0,193},{4,10,926},{133,10,\n983},{5,0,354},{135,11,506},{8,0,598},{9,0,664},{138,0,441},{4,11,640},{133,11,\n513},{137,0,297},{132,10,538},{6,10,294},{7,10,1267},{136,10,624},{7,0,1772},{7,\n11,1888},{8,11,289},{11,11,45},{12,11,278},{140,11,537},{135,10,1325},{138,0,751\n},{141,0,37},{134,0,1828},{132,10,757},{132,11,394},{6,0,257},{135,0,1522},{4,0,\n582},{9,0,191},{135,11,1931},{7,11,574},{7,11,1719},{137,11,145},{132,11,658},{\n10,0,790},{132,11,369},{9,11,781},{10,11,144},{11,11,385},{13,11,161},{13,11,228\n},{13,11,268},{148,11,107},{8,0,469},{10,0,47},{136,11,374},{6,0,306},{7,0,1140}\n,{7,0,1340},{8,0,133},{138,0,449},{139,0,1011},{7,10,1875},{139,10,124},{4,11,\n344},{6,11,498},{139,11,323},{137,0,299},{132,0,837},{133,11,906},{5,0,329},{8,0\n,260},{138,0,10},{134,0,1320},{4,0,657},{146,0,158},{135,0,1191},{152,0,7},{6,0,\n1939},{8,0,974},{138,0,996},{135,0,1665},{11,11,126},{139,11,287},{143,0,8},{14,\n11,149},{14,11,399},{143,11,57},{5,0,66},{7,0,1896},{136,0,288},{7,0,175},{10,0,\n494},{5,10,150},{8,10,603},{9,10,593},{9,10,634},{10,10,173},{11,10,462},{11,10,\n515},{13,10,216},{13,10,288},{142,10,400},{134,0,1643},{136,11,21},{4,0,21},{5,0\n,91},{5,0,648},{5,0,750},{5,0,781},{6,0,54},{6,0,112},{6,0,402},{6,0,1732},{7,0,\n315},{7,0,749},{7,0,1427},{7,0,1900},{9,0,78},{9,0,508},{10,0,611},{10,0,811},{\n11,0,510},{11,0,728},{13,0,36},{14,0,39},{16,0,83},{17,0,124},{148,0,30},{4,0,\n668},{136,0,570},{10,0,322},{10,0,719},{139,0,407},{135,11,1381},{136,11,193},{\n12,10,108},{141,10,291},{132,11,616},{136,11,692},{8,0,125},{8,0,369},{8,0,524},\n{10,0,486},{11,0,13},{11,0,381},{11,0,736},{11,0,766},{11,0,845},{13,0,114},{13,\n0,292},{142,0,47},{134,0,1247},{6,0,1684},{6,0,1731},{7,0,356},{8,0,54},{8,0,221\n},{9,0,225},{9,0,356},{10,0,77},{10,0,446},{10,0,731},{12,0,404},{141,0,491},{\n135,10,1777},{4,11,305},{4,10,493},{144,10,55},{4,0,951},{6,0,1809},{6,0,1849},{\n8,0,846},{8,0,866},{8,0,899},{10,0,896},{12,0,694},{142,0,468},{5,11,214},{7,11,\n603},{8,11,611},{9,11,686},{10,11,88},{11,11,459},{11,11,496},{12,11,463},{12,11\n,590},{13,11,0},{142,11,214},{132,0,411},{4,0,80},{133,0,44},{140,11,74},{143,0,\n31},{7,0,669},{6,10,568},{7,10,1804},{8,10,362},{8,10,410},{8,10,830},{9,10,514}\n,{11,10,649},{142,10,157},{7,0,673},{134,11,1703},{132,10,625},{134,0,1303},{5,0\n,299},{135,0,1083},{138,0,704},{6,0,275},{7,0,408},{6,10,158},{7,10,129},{7,10,\n181},{8,10,276},{8,10,377},{10,10,523},{11,10,816},{12,10,455},{13,10,303},{142,\n10,135},{4,0,219},{7,0,367},{7,0,1713},{7,0,1761},{9,0,86},{9,0,537},{10,0,165},\n{12,0,219},{140,0,561},{8,0,216},{4,10,1},{4,11,737},{6,11,317},{7,10,1143},{7,\n10,1463},{9,10,207},{9,10,390},{9,10,467},{10,11,98},{11,11,294},{11,10,836},{12\n,11,60},{12,11,437},{13,11,64},{13,11,380},{142,11,430},{6,11,1758},{8,11,520},{\n9,11,345},{9,11,403},{142,11,350},{5,11,47},{10,11,242},{138,11,579},{5,11,139},\n{7,11,1168},{138,11,539},{135,0,1319},{4,10,295},{4,10,723},{5,10,895},{7,10,\n1031},{8,10,199},{8,10,340},{9,10,153},{9,10,215},{10,10,21},{10,10,59},{10,10,\n80},{10,10,224},{10,10,838},{11,10,229},{11,10,652},{12,10,192},{13,10,146},{142\n,10,91},{140,0,428},{137,10,51},{133,0,514},{5,10,309},{140,10,211},{6,0,1010},{\n5,10,125},{8,10,77},{138,10,15},{4,0,55},{5,0,301},{6,0,571},{142,0,49},{146,0,\n102},{136,11,370},{4,11,107},{7,11,613},{8,11,358},{8,11,439},{8,11,504},{9,11,\n501},{10,11,383},{139,11,477},{132,11,229},{133,0,364},{133,10,439},{4,11,903},{\n135,11,1816},{11,0,379},{140,10,76},{4,0,76},{4,0,971},{7,0,1550},{9,0,306},{9,0\n,430},{9,0,663},{10,0,683},{10,0,921},{11,0,427},{11,0,753},{12,0,334},{12,0,442\n},{14,0,258},{14,0,366},{143,0,131},{137,0,52},{4,11,47},{6,11,373},{7,11,452},{\n7,11,543},{7,11,1714},{7,11,1856},{9,11,6},{11,11,257},{139,11,391},{4,10,8},{7,\n10,1152},{7,10,1153},{7,10,1715},{9,10,374},{10,10,478},{139,10,648},{4,11,785},\n{133,11,368},{135,10,1099},{135,11,860},{5,11,980},{134,11,1754},{134,0,1258},{6\n,0,1058},{6,0,1359},{7,11,536},{7,11,1331},{136,11,143},{4,0,656},{135,0,779},{\n136,10,87},{5,11,19},{6,11,533},{146,11,126},{7,0,144},{138,10,438},{5,11,395},{\n5,11,951},{134,11,1776},{135,0,1373},{7,0,554},{7,0,605},{141,0,10},{4,10,69},{5\n,10,122},{9,10,656},{138,10,464},{5,10,849},{134,10,1633},{5,0,838},{5,0,841},{\n134,0,1649},{133,0,1012},{139,10,499},{7,10,476},{7,10,1592},{138,10,87},{6,0,\n251},{7,0,365},{7,0,1357},{7,0,1497},{8,0,154},{141,0,281},{132,11,441},{132,11,\n695},{7,11,497},{9,11,387},{147,11,81},{133,0,340},{14,10,283},{142,11,283},{134\n,0,810},{135,11,1894},{139,0,495},{5,11,284},{6,11,49},{6,11,350},{7,11,1},{7,11\n,377},{7,11,1693},{8,11,18},{8,11,678},{9,11,161},{9,11,585},{9,11,671},{9,11,\n839},{11,11,912},{141,11,427},{5,10,859},{7,10,1160},{8,10,107},{9,10,291},{9,10\n,439},{10,10,663},{11,10,609},{140,10,197},{8,0,261},{9,0,144},{9,0,466},{10,0,\n370},{12,0,470},{13,0,144},{142,0,348},{137,0,897},{6,0,248},{9,0,546},{10,0,535\n},{11,0,681},{141,0,135},{4,0,358},{135,0,1496},{134,0,567},{136,0,445},{4,10,\n117},{6,10,372},{7,10,1905},{142,10,323},{4,10,722},{139,10,471},{6,0,697},{134,\n0,996},{7,11,2007},{9,11,101},{9,11,450},{10,11,66},{10,11,842},{11,11,536},{140\n,11,587},{132,0,577},{134,0,1336},{9,10,5},{12,10,216},{12,10,294},{12,10,298},{\n12,10,400},{12,10,518},{13,10,229},{143,10,139},{6,0,174},{138,0,917},{134,10,\n1774},{5,10,12},{7,10,375},{9,10,88},{9,10,438},{11,11,62},{139,10,270},{134,11,\n1766},{6,11,0},{7,11,84},{7,10,816},{7,10,1241},{9,10,283},{9,10,520},{10,10,213\n},{10,10,307},{10,10,463},{10,10,671},{10,10,746},{11,10,401},{11,10,794},{11,11\n,895},{12,10,517},{17,11,11},{18,10,107},{147,10,115},{5,0,878},{133,0,972},{6,\n11,1665},{7,11,256},{7,11,1388},{138,11,499},{4,10,258},{136,10,639},{4,11,22},{\n5,11,10},{6,10,22},{7,11,848},{7,10,903},{7,10,1963},{8,11,97},{138,10,577},{5,\n10,681},{136,10,782},{133,11,481},{132,0,351},{4,10,664},{5,10,804},{139,10,1013\n},{6,11,134},{7,11,437},{7,11,959},{9,11,37},{14,11,285},{14,11,371},{144,11,60}\n,{7,11,486},{8,11,155},{11,11,93},{140,11,164},{132,0,286},{7,0,438},{7,0,627},{\n7,0,1516},{8,0,40},{9,0,56},{9,0,294},{10,0,30},{11,0,969},{11,0,995},{146,0,148\n},{5,11,591},{135,11,337},{134,0,1950},{133,10,32},{138,11,500},{5,11,380},{5,11\n,650},{136,11,310},{4,11,364},{7,11,1156},{7,11,1187},{137,11,409},{4,0,738},{\n134,11,482},{4,11,781},{6,11,487},{7,11,926},{8,11,263},{139,11,500},{135,11,418\n},{6,0,2047},{10,0,969},{4,10,289},{7,10,629},{7,10,1698},{7,10,1711},{140,10,\n215},{6,10,450},{136,10,109},{134,0,818},{136,10,705},{133,0,866},{4,11,94},{135\n,11,1265},{132,11,417},{134,0,1467},{135,10,1238},{4,0,972},{6,0,1851},{134,0,\n1857},{134,0,355},{133,0,116},{132,0,457},{135,11,1411},{4,11,408},{4,11,741},{\n135,11,500},{134,10,26},{142,11,137},{5,0,527},{6,0,189},{7,0,859},{136,0,267},{\n11,0,104},{11,0,554},{15,0,60},{143,0,125},{134,0,1613},{4,10,414},{5,10,467},{9\n,10,654},{10,10,451},{12,10,59},{141,10,375},{135,10,17},{134,0,116},{135,11,541\n},{135,10,955},{6,11,73},{135,11,177},{133,11,576},{134,0,886},{133,0,487},{4,0,\n86},{5,0,667},{5,0,753},{6,0,316},{6,0,455},{135,0,946},{142,11,231},{150,0,45},\n{134,0,863},{134,0,1953},{6,10,280},{10,10,502},{11,10,344},{140,10,38},{4,0,79}\n,{7,0,1773},{10,0,450},{11,0,589},{13,0,332},{13,0,493},{14,0,183},{14,0,334},{\n14,0,362},{14,0,368},{14,0,376},{14,0,379},{19,0,90},{19,0,103},{19,0,127},{148,\n0,90},{5,10,45},{7,10,1161},{11,10,448},{11,10,880},{13,10,139},{13,10,407},{15,\n10,16},{17,10,95},{18,10,66},{18,10,88},{18,10,123},{149,10,7},{136,10,777},{4,\n10,410},{135,10,521},{135,10,1778},{135,11,538},{142,0,381},{133,11,413},{134,0,\n1142},{6,0,1189},{136,11,495},{5,0,663},{6,0,1962},{134,0,2003},{7,11,54},{8,11,\n312},{10,11,191},{10,11,614},{140,11,567},{132,10,436},{133,0,846},{10,0,528},{\n11,0,504},{7,10,1587},{135,10,1707},{5,0,378},{8,0,465},{9,0,286},{10,0,185},{10\n,0,562},{10,0,635},{11,0,31},{11,0,393},{13,0,312},{18,0,65},{18,0,96},{147,0,89\n},{7,0,899},{14,0,325},{6,11,468},{7,11,567},{7,11,1478},{8,11,530},{142,11,290}\n,{7,0,1880},{9,0,680},{139,0,798},{134,0,1770},{132,0,648},{150,11,35},{5,0,945}\n,{6,0,1656},{6,0,1787},{7,0,167},{8,0,824},{9,0,391},{10,0,375},{139,0,185},{6,\n11,484},{135,11,822},{134,0,2046},{7,0,1645},{8,0,352},{137,0,249},{132,0,152},{\n6,0,611},{135,0,1733},{6,11,1724},{135,11,2022},{133,0,1006},{141,11,96},{5,0,\n420},{135,0,1449},{146,11,149},{135,0,832},{135,10,663},{133,0,351},{5,0,40},{7,\n0,598},{7,0,1638},{8,0,78},{9,0,166},{9,0,640},{9,0,685},{9,0,773},{11,0,215},{\n13,0,65},{14,0,172},{14,0,317},{145,0,6},{8,0,60},{9,0,343},{139,0,769},{134,0,\n1354},{132,0,724},{137,0,745},{132,11,474},{7,0,1951},{8,0,765},{8,0,772},{140,0\n,671},{7,0,108},{8,0,219},{8,0,388},{9,0,775},{11,0,275},{140,0,464},{137,0,639}\n,{135,10,503},{133,11,366},{5,0,15},{6,0,56},{7,0,1758},{8,0,500},{9,0,730},{11,\n0,331},{13,0,150},{14,0,282},{5,11,305},{9,11,560},{141,11,208},{4,10,113},{5,10\n,163},{5,10,735},{7,10,1009},{9,10,9},{9,10,771},{12,10,90},{13,10,138},{13,10,\n410},{143,10,128},{4,10,324},{138,10,104},{135,11,466},{142,11,27},{134,0,1886},\n{5,0,205},{6,0,438},{9,0,711},{4,11,480},{6,11,167},{6,11,302},{6,11,1642},{7,11\n,130},{7,11,656},{7,11,837},{7,11,1547},{7,11,1657},{8,11,429},{9,11,228},{10,11\n,643},{13,11,289},{13,11,343},{147,11,101},{134,0,865},{6,0,2025},{136,0,965},{7\n,11,278},{10,11,739},{11,11,708},{141,11,348},{133,0,534},{135,11,1922},{137,0,\n691},{4,10,935},{133,10,823},{6,0,443},{9,0,237},{9,0,571},{9,0,695},{10,0,139},\n{11,0,715},{12,0,417},{141,0,421},{5,10,269},{7,10,434},{7,10,891},{8,10,339},{9\n,10,702},{11,10,594},{11,10,718},{145,10,100},{6,0,1555},{7,0,878},{9,10,485},{\n141,10,264},{134,10,1713},{7,10,1810},{11,10,866},{12,10,103},{141,10,495},{135,\n10,900},{6,0,1410},{9,11,316},{139,11,256},{4,0,995},{135,0,1033},{132,0,578},{\n10,0,881},{12,0,740},{12,0,743},{140,0,759},{132,0,822},{133,0,923},{142,10,143}\n,{135,11,1696},{6,11,363},{7,11,1955},{136,11,725},{132,0,924},{133,0,665},{135,\n10,2029},{135,0,1901},{4,0,265},{6,0,1092},{6,0,1417},{7,0,807},{135,0,950},{5,0\n,93},{12,0,267},{141,0,498},{135,0,1451},{5,11,813},{135,11,2046},{5,10,625},{\n135,10,1617},{135,0,747},{6,0,788},{137,0,828},{7,0,184},{11,0,307},{11,0,400},{\n15,0,130},{5,11,712},{7,11,1855},{8,10,425},{8,10,693},{9,10,720},{10,10,380},{\n10,10,638},{11,11,17},{11,10,473},{12,10,61},{13,11,321},{144,11,67},{135,0,198}\n,{6,11,320},{7,11,781},{7,11,1921},{9,11,55},{10,11,186},{10,11,273},{10,11,664}\n,{10,11,801},{11,11,996},{11,11,997},{13,11,157},{142,11,170},{136,11,271},{135,\n0,994},{7,11,103},{7,11,863},{11,11,184},{14,11,299},{145,11,62},{11,10,551},{\n142,10,159},{5,0,233},{5,0,320},{6,0,140},{8,0,295},{8,0,615},{136,11,615},{133,\n0,978},{4,0,905},{6,0,1701},{137,0,843},{132,10,168},{4,0,974},{8,0,850},{12,0,\n709},{12,0,768},{140,0,786},{135,10,91},{152,0,6},{138,10,532},{135,10,1884},{\n132,0,509},{6,0,1307},{135,0,273},{5,11,77},{7,11,1455},{10,11,843},{19,11,73},{\n150,11,5},{132,11,458},{135,11,1420},{6,11,109},{138,11,382},{6,0,201},{6,11,330\n},{7,10,70},{7,11,1084},{10,10,240},{11,11,142},{147,10,93},{7,0,1041},{140,11,\n328},{133,11,354},{134,0,1040},{133,0,693},{134,0,774},{139,0,234},{132,0,336},{\n7,0,1399},{139,10,392},{20,0,22},{148,11,22},{5,0,802},{7,0,2021},{136,0,805},{5\n,0,167},{5,0,899},{6,0,410},{137,0,777},{137,0,789},{134,0,1705},{7,10,655},{135\n,10,1844},{4,10,145},{6,10,176},{7,10,395},{137,10,562},{132,10,501},{135,0,10},\n{5,0,11},{6,0,117},{6,0,485},{7,0,1133},{9,0,582},{9,0,594},{10,0,82},{11,0,21},\n{11,0,818},{12,0,535},{13,0,86},{20,0,91},{23,0,13},{134,10,509},{4,0,264},{7,0,\n1067},{8,0,204},{8,0,385},{139,0,953},{139,11,737},{138,0,56},{134,0,1917},{133,\n0,470},{10,11,657},{14,11,297},{142,11,361},{135,11,412},{7,0,1198},{7,11,1198},\n{8,11,556},{14,11,123},{14,11,192},{143,11,27},{7,11,1985},{14,11,146},{15,11,42\n},{16,11,23},{17,11,86},{146,11,17},{11,0,1015},{136,11,122},{4,10,114},{9,10,\n492},{13,10,462},{142,10,215},{4,10,77},{5,10,361},{6,10,139},{6,10,401},{6,10,\n404},{7,10,413},{7,10,715},{7,10,1716},{11,10,279},{12,10,179},{12,10,258},{13,\n10,244},{142,10,358},{134,10,1717},{7,10,1061},{8,10,82},{11,10,250},{12,10,420}\n,{141,10,184},{133,0,715},{135,10,724},{9,0,919},{9,0,922},{9,0,927},{9,0,933},{\n9,0,962},{9,0,1000},{9,0,1002},{9,0,1021},{12,0,890},{12,0,907},{12,0,930},{15,0\n,207},{15,0,228},{15,0,238},{149,0,61},{8,0,794},{9,0,400},{10,0,298},{142,0,228\n},{5,11,430},{5,11,932},{6,11,131},{7,11,417},{9,11,522},{11,11,314},{141,11,390\n},{132,0,867},{8,0,724},{132,11,507},{137,11,261},{4,11,343},{133,11,511},{6,0,\n190},{7,0,768},{135,0,1170},{6,10,513},{135,10,1052},{7,11,455},{138,11,591},{\n134,0,1066},{137,10,899},{14,0,67},{147,0,60},{4,0,948},{18,0,174},{146,0,176},{\n135,0,1023},{7,10,1417},{12,10,382},{17,10,48},{152,10,12},{134,11,575},{132,0,\n764},{6,10,545},{7,10,565},{7,10,1669},{10,10,114},{11,10,642},{140,10,618},{6,0\n,137},{9,0,75},{9,0,253},{10,0,194},{138,0,444},{4,0,756},{133,10,5},{8,0,1008},\n{135,10,192},{132,0,842},{11,0,643},{12,0,115},{136,10,763},{139,0,67},{133,10,\n759},{4,0,821},{5,0,760},{7,0,542},{8,0,135},{8,0,496},{135,11,580},{7,10,370},{\n7,10,1007},{7,10,1177},{135,10,1565},{135,10,1237},{140,0,736},{7,0,319},{7,0,\n355},{7,0,763},{10,0,389},{145,0,43},{8,11,333},{138,11,182},{4,10,87},{5,10,250\n},{141,10,298},{138,0,786},{134,0,2044},{8,11,330},{140,11,477},{135,11,1338},{\n132,11,125},{134,0,1030},{134,0,1083},{132,11,721},{135,10,814},{7,11,776},{8,11\n,145},{147,11,56},{134,0,1226},{4,10,57},{7,10,1195},{7,10,1438},{7,10,1548},{7,\n10,1835},{7,10,1904},{9,10,757},{10,10,604},{139,10,519},{7,11,792},{8,11,147},{\n10,11,821},{139,11,1021},{137,11,797},{4,0,58},{5,0,286},{6,0,319},{7,0,402},{7,\n0,1254},{7,0,1903},{8,0,356},{140,0,408},{4,0,389},{4,0,815},{9,0,181},{9,0,255}\n,{10,0,8},{10,0,29},{10,0,816},{11,0,311},{11,0,561},{12,0,67},{141,0,181},{7,11\n,1472},{135,11,1554},{7,11,1071},{7,11,1541},{7,11,1767},{7,11,1806},{7,11,1999}\n,{9,11,248},{10,11,400},{11,11,162},{11,11,178},{11,11,242},{12,11,605},{15,11,\n26},{144,11,44},{5,11,168},{5,11,930},{8,11,74},{9,11,623},{12,11,500},{12,11,\n579},{13,11,41},{143,11,93},{6,11,220},{7,11,1101},{141,11,105},{5,0,474},{7,0,\n507},{4,10,209},{7,11,507},{135,10,902},{132,0,427},{6,0,413},{7,10,335},{7,10,\n1437},{7,10,1668},{8,10,553},{8,10,652},{8,10,656},{9,10,558},{11,10,743},{149,\n10,18},{132,0,730},{6,11,19},{7,11,1413},{139,11,428},{133,0,373},{132,10,559},{\n7,11,96},{8,11,401},{137,11,896},{7,0,799},{7,0,1972},{5,10,1017},{138,10,511},{\n135,0,1793},{7,11,1961},{7,11,1965},{8,11,702},{136,11,750},{8,11,150},{8,11,737\n},{140,11,366},{132,0,322},{133,10,709},{8,11,800},{9,11,148},{9,11,872},{9,11,\n890},{11,11,309},{11,11,1001},{13,11,267},{141,11,323},{134,10,1745},{7,0,290},{\n136,10,206},{7,0,1651},{145,0,89},{139,0,2},{132,0,672},{6,0,1860},{8,0,905},{10\n,0,844},{10,0,846},{10,0,858},{12,0,699},{12,0,746},{140,0,772},{135,11,424},{\n133,11,547},{133,0,737},{5,11,490},{6,11,615},{6,11,620},{135,11,683},{6,0,746},\n{134,0,1612},{132,10,776},{9,11,385},{149,11,17},{133,0,145},{135,10,1272},{7,0,\n884},{140,0,124},{4,0,387},{135,0,1288},{5,11,133},{136,10,406},{136,11,187},{6,\n0,679},{8,11,8},{138,11,0},{135,0,550},{135,11,798},{136,11,685},{7,11,1086},{\n145,11,46},{8,10,175},{10,10,168},{138,10,573},{135,0,1305},{4,0,576},{135,0,\n1263},{6,0,686},{134,0,1563},{134,0,607},{5,0,919},{134,0,1673},{148,0,37},{8,11\n,774},{10,11,670},{140,11,51},{133,10,784},{139,10,882},{4,0,82},{5,0,333},{5,0,\n904},{6,0,207},{7,0,325},{7,0,1726},{8,0,101},{10,0,778},{139,0,220},{135,11,371\n},{132,0,958},{133,0,903},{4,11,127},{5,11,350},{6,11,356},{8,11,426},{9,11,572}\n,{10,11,247},{139,11,312},{140,0,147},{6,11,59},{7,11,885},{9,11,603},{141,11,\n397},{10,0,367},{9,10,14},{9,10,441},{139,10,9},{11,10,966},{12,10,287},{13,10,\n342},{13,10,402},{15,10,110},{143,10,163},{134,0,690},{132,0,705},{9,0,651},{11,\n0,971},{13,0,273},{7,10,1428},{7,10,1640},{7,10,1867},{9,10,169},{9,10,182},{9,\n10,367},{9,10,478},{9,10,506},{9,10,551},{9,10,557},{9,10,648},{9,10,697},{9,10,\n705},{9,10,725},{9,10,787},{9,10,794},{10,10,198},{10,10,214},{10,10,267},{10,10\n,275},{10,10,456},{10,10,551},{10,10,561},{10,10,613},{10,10,627},{10,10,668},{\n10,10,675},{10,10,691},{10,10,695},{10,10,707},{10,10,715},{11,10,183},{11,10,\n201},{11,10,262},{11,10,352},{11,10,439},{11,10,493},{11,10,572},{11,10,591},{11\n,10,608},{11,10,611},{11,10,646},{11,10,674},{11,10,711},{11,10,751},{11,10,761}\n,{11,10,776},{11,10,785},{11,10,850},{11,10,853},{11,10,862},{11,10,865},{11,10,\n868},{11,10,875},{11,10,898},{11,10,902},{11,10,903},{11,10,910},{11,10,932},{11\n,10,942},{11,10,957},{11,10,967},{11,10,972},{12,10,148},{12,10,195},{12,10,220}\n,{12,10,237},{12,10,318},{12,10,339},{12,10,393},{12,10,445},{12,10,450},{12,10,\n474},{12,10,505},{12,10,509},{12,10,533},{12,10,591},{12,10,594},{12,10,597},{12\n,10,621},{12,10,633},{12,10,642},{13,10,59},{13,10,60},{13,10,145},{13,10,239},{\n13,10,250},{13,10,329},{13,10,344},{13,10,365},{13,10,372},{13,10,387},{13,10,\n403},{13,10,414},{13,10,456},{13,10,470},{13,10,478},{13,10,483},{13,10,489},{14\n,10,55},{14,10,57},{14,10,81},{14,10,90},{14,10,148},{14,10,239},{14,10,266},{14\n,10,321},{14,10,326},{14,10,327},{14,10,330},{14,10,347},{14,10,355},{14,10,401}\n,{14,10,404},{14,10,411},{14,10,414},{14,10,416},{14,10,420},{15,10,61},{15,10,\n74},{15,10,87},{15,10,88},{15,10,94},{15,10,96},{15,10,116},{15,10,149},{15,10,\n154},{16,10,50},{16,10,63},{16,10,73},{17,10,2},{17,10,66},{17,10,92},{17,10,103\n},{17,10,112},{17,10,120},{18,10,50},{18,10,54},{18,10,82},{18,10,86},{18,10,90}\n,{18,10,111},{18,10,115},{18,10,156},{19,10,40},{19,10,79},{20,10,78},{149,10,22\n},{7,0,887},{5,10,161},{135,10,839},{142,11,98},{134,0,90},{138,11,356},{135,11,\n441},{6,11,111},{7,11,4},{8,11,163},{8,11,776},{138,11,566},{134,0,908},{134,0,\n1261},{7,0,813},{12,0,497},{141,0,56},{134,0,1235},{135,0,429},{135,11,1994},{\n138,0,904},{6,0,125},{7,0,1277},{137,0,772},{151,0,12},{4,0,841},{5,0,386},{133,\n11,386},{5,11,297},{135,11,1038},{6,0,860},{6,0,1069},{135,11,309},{136,0,946},{\n135,10,1814},{141,11,418},{136,11,363},{10,0,768},{139,0,787},{22,11,30},{150,11\n,33},{6,0,160},{7,0,1106},{9,0,770},{11,0,112},{140,0,413},{11,11,216},{139,11,\n340},{136,10,139},{135,11,1390},{135,11,808},{132,11,280},{12,0,271},{17,0,109},\n{7,10,643},{136,10,236},{140,11,54},{4,11,421},{133,11,548},{11,0,719},{12,0,36}\n,{141,0,337},{7,0,581},{9,0,644},{137,0,699},{11,11,511},{13,11,394},{14,11,298}\n,{14,11,318},{146,11,103},{7,0,304},{9,0,646},{9,0,862},{11,0,696},{12,0,208},{\n15,0,79},{147,0,108},{4,0,631},{7,0,1126},{135,0,1536},{135,11,1527},{8,0,880},{\n10,0,869},{138,0,913},{7,0,1513},{5,10,54},{6,11,254},{9,11,109},{138,11,103},{\n135,0,981},{133,11,729},{132,10,744},{132,0,434},{134,0,550},{7,0,930},{10,0,476\n},{13,0,452},{19,0,104},{6,11,1630},{10,10,402},{146,10,55},{5,0,553},{138,0,824\n},{136,0,452},{8,0,151},{137,10,624},{132,10,572},{132,0,772},{133,11,671},{133,\n0,292},{138,0,135},{132,11,889},{140,11,207},{9,0,504},{6,10,43},{7,10,38},{8,10\n,248},{138,10,513},{6,0,1089},{135,11,1910},{4,11,627},{133,11,775},{135,0,783},\n{133,10,766},{133,10,363},{7,0,387},{135,11,387},{7,0,393},{10,0,603},{11,0,206}\n,{7,11,202},{11,11,362},{11,11,948},{140,11,388},{6,11,507},{7,11,451},{8,11,389\n},{12,11,490},{13,11,16},{13,11,215},{13,11,351},{18,11,132},{147,11,125},{4,0,\n912},{9,0,232},{135,11,841},{6,10,258},{140,10,409},{5,10,249},{148,10,82},{136,\n11,566},{6,0,977},{135,11,1214},{7,0,1973},{136,0,716},{135,0,98},{133,0,733},{5\n,11,912},{134,11,1695},{5,10,393},{6,10,378},{7,10,1981},{9,10,32},{9,10,591},{\n10,10,685},{10,10,741},{142,10,382},{133,10,788},{10,0,19},{11,0,911},{7,10,1968\n},{141,10,509},{5,0,668},{5,11,236},{6,11,572},{8,11,492},{11,11,618},{144,11,56\n},{135,11,1789},{4,0,360},{5,0,635},{5,0,700},{5,10,58},{5,10,171},{5,10,683},{6\n,10,291},{6,10,566},{7,10,1650},{11,10,523},{12,10,273},{12,10,303},{15,10,39},{\n143,10,111},{133,0,901},{134,10,589},{5,11,190},{136,11,318},{140,0,656},{7,0,\n726},{152,0,9},{4,10,917},{133,10,1005},{135,10,1598},{134,11,491},{4,10,919},{\n133,11,434},{137,0,72},{6,0,1269},{6,0,1566},{134,0,1621},{9,0,463},{10,0,595},{\n4,10,255},{5,10,302},{6,10,132},{7,10,128},{7,10,283},{7,10,1299},{10,10,52},{10\n,10,514},{11,10,925},{13,10,92},{142,10,309},{135,0,1454},{134,0,1287},{11,0,600\n},{13,0,245},{137,10,173},{136,0,989},{7,0,164},{7,0,1571},{9,0,107},{140,0,225}\n,{6,0,1061},{141,10,442},{4,0,27},{5,0,484},{5,0,510},{6,0,434},{7,0,1000},{7,0,\n1098},{136,0,2},{7,11,85},{7,11,247},{8,11,585},{10,11,163},{138,11,316},{11,11,\n103},{142,11,0},{134,0,1127},{4,0,460},{134,0,852},{134,10,210},{4,0,932},{133,0\n,891},{6,0,588},{147,11,83},{8,0,625},{4,10,284},{134,10,223},{134,0,76},{8,0,92\n},{137,0,221},{4,11,124},{10,11,457},{11,11,121},{11,11,169},{11,11,422},{11,11,\n870},{12,11,214},{13,11,389},{14,11,187},{143,11,77},{9,11,618},{138,11,482},{4,\n10,218},{7,10,526},{143,10,137},{13,0,9},{14,0,104},{14,0,311},{4,10,270},{5,10,\n192},{6,10,332},{135,10,1322},{140,10,661},{135,11,1193},{6,11,107},{7,11,638},{\n7,11,1632},{137,11,396},{132,0,763},{4,0,622},{5,11,370},{134,11,1756},{133,0,\n253},{135,0,546},{9,0,73},{10,0,110},{14,0,185},{17,0,119},{133,11,204},{7,0,624\n},{7,0,916},{10,0,256},{139,0,87},{7,10,379},{8,10,481},{137,10,377},{5,0,212},{\n12,0,35},{13,0,382},{5,11,970},{134,11,1706},{9,0,746},{5,10,1003},{134,10,149},\n{10,0,150},{11,0,849},{13,0,330},{8,10,262},{9,10,627},{11,10,214},{11,10,404},{\n11,10,457},{11,10,780},{11,10,913},{13,10,401},{142,10,200},{134,0,1466},{135,11\n,3},{6,0,1299},{4,11,35},{5,11,121},{5,11,483},{5,11,685},{6,11,489},{7,11,1204}\n,{136,11,394},{135,10,742},{4,10,142},{136,10,304},{4,11,921},{133,11,1007},{134\n,0,1518},{6,0,1229},{135,0,1175},{133,0,816},{12,0,159},{4,10,471},{4,11,712},{5\n,10,51},{6,10,602},{7,10,925},{8,10,484},{138,10,195},{134,11,1629},{5,0,869},{5\n,0,968},{6,0,1626},{8,0,734},{136,0,784},{4,0,542},{6,0,1716},{6,0,1727},{7,0,\n1082},{7,0,1545},{8,0,56},{8,0,118},{8,0,412},{8,0,564},{9,0,888},{9,0,908},{10,\n0,50},{10,0,423},{11,0,685},{11,0,697},{11,0,933},{12,0,299},{13,0,126},{13,0,\n136},{13,0,170},{13,0,190},{136,10,688},{132,10,697},{4,0,232},{9,0,202},{10,0,\n474},{140,0,433},{136,0,212},{6,0,108},{7,0,1003},{7,0,1181},{8,0,111},{136,0,\n343},{5,10,221},{135,11,1255},{133,11,485},{134,0,1712},{142,0,216},{5,0,643},{6\n,0,516},{4,11,285},{5,11,317},{6,11,301},{7,11,7},{8,11,153},{10,11,766},{11,11,\n468},{12,11,467},{141,11,143},{4,0,133},{7,0,711},{7,0,1298},{135,0,1585},{134,0\n,650},{135,11,512},{6,0,99},{7,0,1808},{145,0,57},{6,0,246},{6,0,574},{7,0,428},\n{9,0,793},{10,0,669},{11,0,485},{11,0,840},{12,0,300},{14,0,250},{145,0,55},{4,\n10,132},{5,10,69},{135,10,1242},{136,0,1023},{7,0,302},{132,10,111},{135,0,1871}\n,{132,0,728},{9,0,252},{132,10,767},{6,0,461},{7,0,1590},{7,10,1416},{7,10,2005}\n,{8,10,131},{8,10,466},{9,10,672},{13,10,252},{148,10,103},{6,0,323},{135,0,1564\n},{7,0,461},{136,0,775},{6,10,44},{136,10,368},{139,0,172},{132,0,464},{4,10,570\n},{133,10,120},{137,11,269},{6,10,227},{135,10,1589},{6,11,1719},{6,11,1735},{7,\n11,2016},{7,11,2020},{8,11,837},{137,11,852},{7,0,727},{146,0,73},{132,0,1023},{\n135,11,852},{135,10,1529},{136,0,577},{138,11,568},{134,0,1037},{8,11,67},{138,\n11,419},{4,0,413},{5,0,677},{8,0,432},{140,0,280},{10,0,600},{6,10,1667},{7,11,\n967},{7,10,2036},{141,11,11},{6,10,511},{140,10,132},{6,0,799},{5,10,568},{6,10,\n138},{135,10,1293},{8,0,159},{4,10,565},{136,10,827},{7,0,646},{7,0,1730},{11,0,\n446},{141,0,178},{4,10,922},{133,10,1023},{135,11,11},{132,0,395},{11,0,145},{\n135,10,1002},{9,0,174},{10,0,164},{11,0,440},{11,0,514},{11,0,841},{15,0,98},{\n149,0,20},{134,0,426},{10,0,608},{139,0,1002},{7,11,320},{8,11,51},{12,11,481},{\n12,11,570},{148,11,106},{9,0,977},{9,0,983},{132,11,445},{138,0,250},{139,0,100}\n,{6,0,1982},{136,10,402},{133,11,239},{4,10,716},{141,10,31},{5,0,476},{7,11,83}\n,{7,11,1990},{8,11,130},{139,11,720},{8,10,691},{136,10,731},{5,11,123},{6,11,\n530},{7,11,348},{135,11,1419},{5,0,76},{6,0,458},{6,0,497},{7,0,868},{9,0,658},{\n10,0,594},{11,0,173},{11,0,566},{12,0,20},{12,0,338},{141,0,200},{9,11,139},{10,\n11,399},{11,11,469},{12,11,634},{141,11,223},{9,10,840},{138,10,803},{133,10,847\n},{11,11,223},{140,11,168},{132,11,210},{8,0,447},{9,10,53},{9,10,268},{9,10,901\n},{10,10,518},{10,10,829},{11,10,188},{13,10,74},{14,10,46},{15,10,17},{15,10,33\n},{17,10,40},{18,10,36},{19,10,20},{22,10,1},{152,10,2},{4,0,526},{7,0,1029},{\n135,0,1054},{19,11,59},{150,11,2},{4,0,636},{6,0,1875},{6,0,1920},{9,0,999},{12,\n0,807},{12,0,825},{15,0,179},{15,0,190},{18,0,182},{136,10,532},{6,0,1699},{7,0,\n660},{7,0,1124},{17,0,31},{19,0,22},{151,0,14},{135,10,681},{132,11,430},{140,10\n,677},{4,10,684},{136,10,384},{132,11,756},{133,11,213},{7,0,188},{7,10,110},{8,\n10,290},{8,10,591},{9,10,382},{9,10,649},{11,10,71},{11,10,155},{11,10,313},{12,\n10,5},{13,10,325},{142,10,287},{7,10,360},{7,10,425},{9,10,66},{9,10,278},{138,\n10,644},{142,11,164},{4,0,279},{7,0,301},{137,0,362},{134,11,586},{135,0,1743},{\n4,0,178},{133,0,399},{4,10,900},{133,10,861},{5,10,254},{7,10,985},{136,10,73},{\n133,11,108},{7,10,1959},{136,10,683},{133,11,219},{4,11,193},{5,11,916},{7,11,\n364},{10,11,398},{10,11,726},{11,11,317},{11,11,626},{12,11,142},{12,11,288},{12\n,11,678},{13,11,313},{15,11,113},{18,11,114},{21,11,30},{150,11,53},{6,11,241},{\n7,11,907},{8,11,832},{9,11,342},{10,11,729},{11,11,284},{11,11,445},{11,11,651},\n{11,11,863},{13,11,398},{146,11,99},{132,0,872},{134,0,831},{134,0,1692},{6,0,\n202},{6,0,1006},{9,0,832},{10,0,636},{11,0,208},{12,0,360},{17,0,118},{18,0,27},\n{20,0,67},{137,11,734},{132,10,725},{7,11,993},{138,11,666},{134,0,1954},{134,10\n,196},{7,0,872},{10,0,516},{139,0,167},{133,10,831},{4,11,562},{9,11,254},{139,\n11,879},{137,0,313},{4,0,224},{132,11,786},{11,0,24},{12,0,170},{136,10,723},{5,\n0,546},{7,0,35},{8,0,11},{8,0,12},{9,0,315},{9,0,533},{10,0,802},{11,0,166},{12,\n0,525},{142,0,243},{7,0,1937},{13,10,80},{13,10,437},{145,10,74},{5,0,241},{8,0,\n242},{9,0,451},{10,0,667},{11,0,598},{140,0,429},{150,0,46},{6,0,1273},{137,0,\n830},{5,10,848},{6,10,66},{136,10,764},{6,0,825},{134,0,993},{4,0,1006},{10,0,\n327},{13,0,271},{4,10,36},{7,10,1387},{139,10,755},{134,0,1023},{135,0,1580},{4,\n0,366},{137,0,516},{132,10,887},{6,0,1736},{135,0,1891},{6,11,216},{7,11,901},{7\n,11,1343},{136,11,493},{6,10,165},{138,10,388},{7,11,341},{139,11,219},{4,10,719\n},{135,10,155},{134,0,1935},{132,0,826},{6,0,331},{6,0,1605},{8,0,623},{11,0,139\n},{139,0,171},{135,11,1734},{10,11,115},{11,11,420},{12,11,154},{13,11,404},{14,\n11,346},{15,11,54},{143,11,112},{7,0,288},{4,10,353},{6,10,146},{6,10,1789},{7,\n10,990},{7,10,1348},{9,10,665},{9,10,898},{11,10,893},{142,10,212},{6,0,916},{\n134,0,1592},{7,0,1888},{4,10,45},{135,10,1257},{5,11,1011},{136,11,701},{139,11,\n596},{4,11,54},{5,11,666},{7,11,1039},{7,11,1130},{9,11,195},{138,11,302},{134,0\n,1471},{134,0,1570},{132,0,394},{140,10,65},{136,10,816},{135,0,1931},{7,0,574},\n{135,0,1719},{134,11,467},{132,0,658},{9,0,781},{10,0,144},{11,0,385},{13,0,161}\n,{13,0,228},{13,0,268},{20,0,107},{134,11,1669},{136,0,374},{135,0,735},{4,0,344\n},{6,0,498},{139,0,323},{7,0,586},{7,0,1063},{6,10,559},{134,10,1691},{137,0,155\n},{133,0,906},{7,11,122},{9,11,259},{10,11,84},{11,11,470},{12,11,541},{141,11,\n379},{134,0,1139},{10,0,108},{139,0,116},{134,10,456},{133,10,925},{5,11,82},{5,\n11,131},{7,11,1755},{8,11,31},{9,11,168},{9,11,764},{139,11,869},{134,11,605},{5\n,11,278},{137,11,68},{4,11,163},{5,11,201},{5,11,307},{5,11,310},{6,11,335},{7,\n11,284},{136,11,165},{135,11,1660},{6,11,33},{135,11,1244},{4,0,616},{136,11,483\n},{8,0,857},{8,0,902},{8,0,910},{10,0,879},{12,0,726},{4,11,199},{139,11,34},{\n136,0,692},{6,10,193},{7,10,240},{7,10,1682},{10,10,51},{10,10,640},{11,10,410},\n{13,10,82},{14,10,247},{14,10,331},{142,10,377},{6,0,823},{134,0,983},{139,10,\n411},{132,0,305},{136,10,633},{138,11,203},{134,0,681},{6,11,326},{7,11,677},{\n137,11,425},{5,0,214},{7,0,603},{8,0,611},{9,0,686},{10,0,88},{11,0,459},{11,0,\n496},{12,0,463},{12,0,590},{141,0,0},{136,0,1004},{142,0,23},{134,0,1703},{147,\n11,8},{145,11,56},{135,0,1443},{4,10,237},{135,10,514},{6,0,714},{145,0,19},{5,\n11,358},{7,11,473},{7,11,1184},{10,11,662},{13,11,212},{13,11,304},{13,11,333},{\n145,11,98},{4,0,737},{10,0,98},{11,0,294},{12,0,60},{12,0,437},{13,0,64},{13,0,\n380},{142,0,430},{6,10,392},{7,10,65},{135,10,2019},{6,0,1758},{8,0,520},{9,0,\n345},{9,0,403},{142,0,350},{5,0,47},{10,0,242},{138,0,579},{5,0,139},{7,0,1168},\n{138,0,539},{134,0,1459},{13,0,388},{141,11,388},{134,0,253},{7,10,1260},{135,10\n,1790},{10,0,252},{9,10,222},{139,10,900},{140,0,745},{133,11,946},{4,0,107},{7,\n0,613},{8,0,439},{8,0,504},{9,0,501},{10,0,383},{139,0,477},{135,11,1485},{132,0\n,871},{7,11,411},{7,11,590},{8,11,631},{9,11,323},{10,11,355},{11,11,491},{12,11\n,143},{12,11,402},{13,11,73},{14,11,408},{15,11,107},{146,11,71},{132,0,229},{\n132,0,903},{140,0,71},{133,0,549},{4,0,47},{6,0,373},{7,0,452},{7,0,543},{7,0,\n1828},{7,0,1856},{9,0,6},{11,0,257},{139,0,391},{7,11,1467},{8,11,328},{10,11,\n544},{11,11,955},{13,11,320},{145,11,83},{5,0,980},{134,0,1754},{136,0,865},{5,0\n,705},{137,0,606},{7,0,161},{8,10,201},{136,10,605},{143,11,35},{5,11,835},{6,11\n,483},{140,10,224},{7,0,536},{7,0,1331},{136,0,143},{134,0,1388},{5,0,724},{10,0\n,305},{11,0,151},{12,0,33},{12,0,121},{12,0,381},{17,0,3},{17,0,27},{17,0,78},{\n18,0,18},{19,0,54},{149,0,5},{4,10,523},{133,10,638},{5,0,19},{134,0,533},{5,0,\n395},{5,0,951},{134,0,1776},{135,0,1908},{132,0,846},{10,0,74},{11,0,663},{12,0,\n210},{13,0,166},{13,0,310},{14,0,373},{18,0,95},{19,0,43},{6,10,242},{7,10,227},\n{7,10,1581},{8,10,104},{9,10,113},{9,10,220},{9,10,427},{10,10,239},{11,10,579},\n{11,10,1023},{13,10,4},{13,10,204},{13,10,316},{148,10,86},{9,11,716},{11,11,108\n},{13,11,123},{14,11,252},{19,11,38},{21,11,3},{151,11,11},{8,0,372},{9,0,122},{\n138,0,175},{132,11,677},{7,11,1374},{136,11,540},{135,10,861},{132,0,695},{7,0,\n497},{9,0,387},{147,0,81},{136,0,937},{134,0,718},{7,0,1328},{136,10,494},{132,\n11,331},{6,0,1581},{133,11,747},{5,0,284},{6,0,49},{6,0,350},{7,0,1},{7,0,377},{\n7,0,1693},{8,0,18},{8,0,678},{9,0,161},{9,0,585},{9,0,671},{9,0,839},{11,0,912},\n{141,0,427},{7,10,1306},{8,10,505},{9,10,482},{10,10,126},{11,10,225},{12,10,347\n},{12,10,449},{13,10,19},{14,10,218},{142,10,435},{10,10,764},{12,10,120},{13,10\n,39},{145,10,127},{4,0,597},{133,10,268},{134,0,1094},{4,0,1008},{134,0,1973},{\n132,0,811},{139,0,908},{135,0,1471},{133,11,326},{4,10,384},{135,10,1022},{7,0,\n1935},{8,0,324},{12,0,42},{4,11,691},{7,11,1935},{8,11,324},{9,11,35},{10,11,680\n},{11,11,364},{12,11,42},{13,11,357},{146,11,16},{135,0,2014},{7,0,2007},{9,0,\n101},{9,0,450},{10,0,66},{10,0,842},{11,0,536},{12,0,587},{6,11,32},{7,11,385},{\n7,11,757},{7,11,1916},{8,11,37},{8,11,94},{8,11,711},{9,11,541},{10,11,162},{10,\n11,795},{11,11,989},{11,11,1010},{12,11,14},{142,11,308},{139,0,586},{135,10,\n1703},{7,0,1077},{11,0,28},{9,10,159},{140,10,603},{6,0,1221},{136,10,583},{6,11\n,152},{6,11,349},{6,11,1682},{7,11,1252},{8,11,112},{9,11,435},{9,11,668},{10,11\n,290},{10,11,319},{10,11,815},{11,11,180},{11,11,837},{12,11,240},{13,11,152},{\n13,11,219},{142,11,158},{139,0,62},{132,10,515},{8,10,632},{8,10,697},{137,10,\n854},{134,0,1766},{132,11,581},{6,11,126},{7,11,573},{8,11,397},{142,11,44},{150\n,0,28},{11,0,670},{22,0,25},{4,10,136},{133,10,551},{6,0,1665},{7,0,256},{7,0,\n1388},{138,0,499},{4,0,22},{5,0,10},{7,0,1576},{136,0,97},{134,10,1782},{5,0,481\n},{7,10,1287},{9,10,44},{10,10,552},{10,10,642},{11,10,839},{12,10,274},{12,10,\n275},{12,10,372},{13,10,91},{142,10,125},{133,11,926},{7,11,1232},{137,11,531},{\n6,0,134},{7,0,437},{7,0,1824},{9,0,37},{14,0,285},{142,0,371},{7,0,486},{8,0,155\n},{11,0,93},{140,0,164},{6,0,1391},{134,0,1442},{133,11,670},{133,0,591},{6,10,\n147},{7,10,886},{7,11,1957},{9,10,753},{138,10,268},{5,0,380},{5,0,650},{7,0,\n1173},{136,0,310},{4,0,364},{7,0,1156},{7,0,1187},{137,0,409},{135,11,1621},{134\n,0,482},{133,11,506},{4,0,781},{6,0,487},{7,0,926},{8,0,263},{139,0,500},{138,10\n,137},{135,11,242},{139,11,96},{133,10,414},{135,10,1762},{134,0,804},{5,11,834}\n,{7,11,1202},{8,11,14},{9,11,481},{137,11,880},{134,10,599},{4,0,94},{135,0,1265\n},{4,0,415},{132,0,417},{5,0,348},{6,0,522},{6,10,1749},{7,11,1526},{138,11,465}\n,{134,10,1627},{132,0,1012},{132,10,488},{4,11,357},{6,11,172},{7,11,143},{137,\n11,413},{4,10,83},{4,11,590},{146,11,76},{140,10,676},{7,11,287},{8,11,355},{9,\n11,293},{137,11,743},{134,10,278},{6,0,1803},{18,0,165},{24,0,21},{5,11,169},{7,\n11,333},{136,11,45},{12,10,97},{140,11,97},{4,0,408},{4,0,741},{135,0,500},{132,\n11,198},{7,10,388},{7,10,644},{139,10,781},{4,11,24},{5,11,140},{5,11,185},{7,11\n,1500},{11,11,565},{139,11,838},{6,0,1321},{9,0,257},{7,10,229},{8,10,59},{9,10,\n190},{10,10,378},{140,10,191},{4,11,334},{133,11,593},{135,11,1885},{134,0,1138}\n,{4,0,249},{6,0,73},{135,0,177},{133,0,576},{142,0,231},{137,0,288},{132,10,660}\n,{7,10,1035},{138,10,737},{135,0,1487},{6,0,989},{9,0,433},{7,10,690},{9,10,587}\n,{140,10,521},{7,0,1264},{7,0,1678},{11,0,945},{12,0,341},{12,0,471},{140,0,569}\n,{132,11,709},{133,11,897},{5,11,224},{13,11,174},{146,11,52},{135,11,1840},{134\n,10,1744},{12,0,87},{16,0,74},{4,10,733},{9,10,194},{10,10,92},{11,10,198},{12,\n10,84},{141,10,128},{140,0,779},{135,0,538},{4,11,608},{133,11,497},{133,0,413},\n{7,11,1375},{7,11,1466},{138,11,331},{136,0,495},{6,11,540},{136,11,136},{7,0,54\n},{8,0,312},{10,0,191},{10,0,614},{140,0,567},{6,0,468},{7,0,567},{7,0,1478},{8,\n0,530},{14,0,290},{133,11,999},{4,11,299},{7,10,306},{135,11,1004},{142,11,296},\n{134,0,1484},{133,10,979},{6,0,609},{9,0,815},{12,11,137},{14,11,9},{14,11,24},{\n142,11,64},{133,11,456},{6,0,484},{135,0,822},{133,10,178},{136,11,180},{132,11,\n755},{137,0,900},{135,0,1335},{6,0,1724},{135,0,2022},{135,11,1139},{5,0,640},{\n132,10,390},{6,0,1831},{138,11,633},{135,11,566},{4,11,890},{5,11,805},{5,11,819\n},{5,11,961},{6,11,396},{6,11,1631},{6,11,1678},{7,11,1967},{7,11,2041},{9,11,\n630},{11,11,8},{11,11,1019},{12,11,176},{13,11,225},{14,11,292},{149,11,24},{132\n,0,474},{134,0,1103},{135,0,1504},{134,0,1576},{6,0,961},{6,0,1034},{140,0,655},\n{11,11,514},{149,11,20},{5,0,305},{135,11,1815},{7,11,1505},{10,11,190},{10,11,\n634},{11,11,792},{12,11,358},{140,11,447},{5,11,0},{6,11,536},{7,11,604},{13,11,\n445},{145,11,126},{7,0,1236},{133,10,105},{4,0,480},{6,0,217},{6,0,302},{6,0,\n1642},{7,0,130},{7,0,837},{7,0,1321},{7,0,1547},{7,0,1657},{8,0,429},{9,0,228},{\n13,0,289},{13,0,343},{19,0,101},{6,11,232},{6,11,412},{7,11,1074},{8,11,9},{8,11\n,157},{8,11,786},{9,11,196},{9,11,352},{9,11,457},{10,11,337},{11,11,232},{11,11\n,877},{12,11,480},{140,11,546},{5,10,438},{7,11,958},{9,10,694},{12,10,627},{13,\n11,38},{141,10,210},{4,11,382},{136,11,579},{7,0,278},{10,0,739},{11,0,708},{141\n,0,348},{4,11,212},{135,11,1206},{135,11,1898},{6,0,708},{6,0,1344},{152,10,11},\n{137,11,768},{134,0,1840},{140,0,233},{8,10,25},{138,10,826},{6,0,2017},{133,11,\n655},{6,0,1488},{139,11,290},{132,10,308},{134,0,1590},{134,0,1800},{134,0,1259}\n,{16,0,28},{6,11,231},{7,11,95},{136,11,423},{133,11,300},{135,10,150},{136,10,\n649},{7,11,1874},{137,11,641},{6,11,237},{7,11,611},{8,11,100},{9,11,416},{11,11\n,335},{12,11,173},{146,11,101},{137,0,45},{134,10,521},{17,0,36},{14,11,26},{146\n,11,150},{7,0,1442},{14,0,22},{5,10,339},{15,10,41},{15,10,166},{147,10,66},{8,0\n,378},{6,11,581},{135,11,1119},{134,0,1507},{147,11,117},{139,0,39},{134,0,1054}\n,{6,0,363},{7,0,1955},{136,0,725},{134,0,2036},{133,11,199},{6,0,1871},{9,0,935}\n,{9,0,961},{9,0,1004},{9,0,1016},{12,0,805},{12,0,852},{12,0,853},{12,0,869},{12\n,0,882},{12,0,896},{12,0,906},{12,0,917},{12,0,940},{15,0,170},{15,0,176},{15,0,\n188},{15,0,201},{15,0,205},{15,0,212},{15,0,234},{15,0,244},{18,0,181},{18,0,193\n},{18,0,196},{18,0,201},{18,0,202},{18,0,210},{18,0,217},{18,0,235},{18,0,236},{\n18,0,237},{21,0,54},{21,0,55},{21,0,58},{21,0,59},{152,0,22},{134,10,1628},{137,\n0,805},{5,0,813},{135,0,2046},{142,11,42},{5,0,712},{6,0,1240},{11,0,17},{13,0,\n321},{144,0,67},{132,0,617},{135,10,829},{6,0,320},{7,0,781},{7,0,1921},{9,0,55}\n,{10,0,186},{10,0,273},{10,0,664},{10,0,801},{11,0,996},{11,0,997},{13,0,157},{\n142,0,170},{136,0,271},{5,10,486},{135,10,1349},{18,11,91},{147,11,70},{10,0,445\n},{7,10,1635},{8,10,17},{138,10,295},{136,11,404},{7,0,103},{7,0,863},{11,0,184}\n,{145,0,62},{138,10,558},{137,0,659},{6,11,312},{6,11,1715},{10,11,584},{11,11,\n546},{11,11,692},{12,11,259},{12,11,295},{13,11,46},{141,11,154},{134,0,676},{\n132,11,588},{4,11,231},{5,11,61},{6,11,104},{7,11,729},{7,11,964},{7,11,1658},{\n140,11,414},{6,11,263},{138,11,757},{11,0,337},{142,0,303},{135,11,1363},{132,11\n,320},{140,0,506},{134,10,447},{5,0,77},{7,0,1455},{10,0,843},{147,0,73},{7,10,\n577},{7,10,1432},{9,10,475},{9,10,505},{9,10,526},{9,10,609},{9,10,689},{9,10,\n726},{9,10,735},{9,10,738},{10,10,556},{10,10,674},{10,10,684},{11,10,89},{11,10\n,202},{11,10,272},{11,10,380},{11,10,415},{11,10,505},{11,10,537},{11,10,550},{\n11,10,562},{11,10,640},{11,10,667},{11,10,688},{11,10,847},{11,10,927},{11,10,\n930},{11,10,940},{12,10,144},{12,10,325},{12,10,329},{12,10,389},{12,10,403},{12\n,10,451},{12,10,515},{12,10,604},{12,10,616},{12,10,626},{13,10,66},{13,10,131},\n{13,10,167},{13,10,236},{13,10,368},{13,10,411},{13,10,434},{13,10,453},{13,10,\n461},{13,10,474},{14,10,59},{14,10,60},{14,10,139},{14,10,152},{14,10,276},{14,\n10,353},{14,10,402},{15,10,28},{15,10,81},{15,10,123},{15,10,152},{18,10,136},{\n148,10,88},{132,0,458},{135,0,1420},{6,0,109},{10,0,382},{4,11,405},{4,10,609},{\n7,10,756},{7,11,817},{9,10,544},{11,10,413},{14,11,58},{14,10,307},{16,10,25},{\n17,11,37},{146,11,124},{6,0,330},{7,0,1084},{11,0,142},{133,11,974},{4,10,930},{\n133,10,947},{5,10,939},{142,11,394},{16,0,91},{145,0,87},{5,11,235},{5,10,962},{\n7,11,1239},{11,11,131},{140,11,370},{11,0,492},{5,10,651},{8,10,170},{9,10,61},{\n9,10,63},{10,10,23},{10,10,37},{10,10,834},{11,10,4},{11,10,281},{11,10,503},{11\n,10,677},{12,10,96},{12,10,130},{12,10,244},{14,10,5},{14,10,40},{14,10,162},{14\n,10,202},{146,10,133},{4,10,406},{5,10,579},{12,10,492},{150,10,15},{9,11,137},{\n138,11,221},{134,0,1239},{11,0,211},{140,0,145},{7,11,390},{138,11,140},{135,11,\n1418},{135,11,1144},{134,0,1049},{7,0,321},{6,10,17},{7,10,1001},{7,10,1982},{9,\n10,886},{10,10,489},{10,10,800},{11,10,782},{12,10,320},{13,10,467},{14,10,145},\n{14,10,387},{143,10,119},{145,10,17},{5,11,407},{11,11,489},{19,11,37},{20,11,73\n},{150,11,38},{133,10,458},{135,0,1985},{7,10,1983},{8,10,0},{8,10,171},{9,10,\n120},{9,10,732},{10,10,473},{11,10,656},{11,10,998},{18,10,0},{18,10,2},{147,10,\n21},{5,11,325},{7,11,1483},{8,11,5},{8,11,227},{9,11,105},{10,11,585},{140,11,\n614},{136,0,122},{132,0,234},{135,11,1196},{6,0,976},{6,0,1098},{134,0,1441},{7,\n0,253},{136,0,549},{6,11,621},{13,11,504},{144,11,19},{132,10,519},{5,0,430},{5,\n0,932},{6,0,131},{7,0,417},{9,0,522},{11,0,314},{141,0,390},{14,0,149},{14,0,399\n},{143,0,57},{5,10,907},{6,10,31},{6,11,218},{7,10,491},{7,10,530},{8,10,592},{\n11,10,53},{11,10,779},{12,10,167},{12,10,411},{14,10,14},{14,10,136},{15,10,72},\n{16,10,17},{144,10,72},{140,11,330},{7,11,454},{7,11,782},{136,11,768},{132,0,\n507},{10,11,676},{140,11,462},{6,0,630},{9,0,811},{4,10,208},{5,10,106},{6,10,\n531},{8,10,408},{9,10,188},{138,10,572},{4,0,343},{5,0,511},{134,10,1693},{134,\n11,164},{132,0,448},{7,0,455},{138,0,591},{135,0,1381},{12,10,441},{150,11,50},{\n9,10,449},{10,10,192},{138,10,740},{6,0,575},{132,10,241},{134,0,1175},{134,0,\n653},{134,0,1761},{134,0,1198},{132,10,259},{6,11,343},{7,11,195},{9,11,226},{10\n,11,197},{10,11,575},{11,11,502},{139,11,899},{7,0,1127},{7,0,1572},{10,0,297},{\n10,0,422},{11,0,764},{11,0,810},{12,0,264},{13,0,102},{13,0,300},{13,0,484},{14,\n0,147},{14,0,229},{17,0,71},{18,0,118},{147,0,120},{135,11,666},{132,0,678},{4,\n10,173},{5,10,312},{5,10,512},{135,10,1285},{7,10,1603},{7,10,1691},{9,10,464},{\n11,10,195},{12,10,279},{12,10,448},{14,10,11},{147,10,102},{16,0,99},{146,0,164}\n,{7,11,1125},{9,11,143},{11,11,61},{14,11,405},{150,11,21},{137,11,260},{4,10,\n452},{5,10,583},{5,10,817},{6,10,433},{7,10,593},{7,10,720},{7,10,1378},{8,10,\n161},{9,10,284},{10,10,313},{139,10,886},{132,10,547},{136,10,722},{14,0,35},{\n142,0,191},{141,0,45},{138,0,121},{132,0,125},{134,0,1622},{133,11,959},{8,10,\n420},{139,10,193},{132,0,721},{135,10,409},{136,0,145},{7,0,792},{8,0,147},{10,0\n,821},{11,0,970},{11,0,1021},{136,11,173},{134,11,266},{132,0,715},{7,0,1999},{\n138,10,308},{133,0,531},{5,0,168},{5,0,930},{8,0,74},{9,0,623},{12,0,500},{140,0\n,579},{144,0,65},{138,11,246},{6,0,220},{7,0,1101},{13,0,105},{142,11,314},{5,10\n,1002},{136,10,745},{134,0,960},{20,0,0},{148,11,0},{4,0,1005},{4,10,239},{6,10,\n477},{7,10,1607},{11,10,68},{139,10,617},{6,0,19},{7,0,1413},{139,0,428},{149,10\n,13},{7,0,96},{8,0,401},{8,0,703},{9,0,896},{136,11,300},{134,0,1595},{145,0,116\n},{136,0,1021},{7,0,1961},{7,0,1965},{7,0,2030},{8,0,150},{8,0,702},{8,0,737},{8\n,0,750},{140,0,366},{11,11,75},{142,11,267},{132,10,367},{8,0,800},{9,0,148},{9,\n0,872},{9,0,890},{11,0,309},{11,0,1001},{13,0,267},{13,0,323},{5,11,427},{5,11,\n734},{7,11,478},{136,11,52},{7,11,239},{11,11,217},{142,11,165},{132,11,323},{\n140,11,419},{13,0,299},{142,0,75},{6,11,87},{6,11,1734},{7,11,20},{7,11,1056},{8\n,11,732},{9,11,406},{9,11,911},{138,11,694},{134,0,1383},{132,10,694},{133,11,\n613},{137,0,779},{4,0,598},{140,10,687},{6,0,970},{135,0,424},{133,0,547},{7,11,\n32},{7,11,984},{8,11,85},{8,11,709},{9,11,579},{9,11,847},{9,11,856},{10,11,799}\n,{11,11,258},{11,11,1007},{12,11,331},{12,11,615},{13,11,188},{13,11,435},{14,11\n,8},{15,11,165},{16,11,27},{148,11,40},{6,0,1222},{134,0,1385},{132,0,876},{138,\n11,151},{135,10,213},{4,11,167},{135,11,82},{133,0,133},{6,11,24},{7,11,74},{7,\n11,678},{137,11,258},{5,11,62},{6,11,534},{7,11,684},{7,11,1043},{7,11,1072},{8,\n11,280},{8,11,541},{8,11,686},{10,11,519},{11,11,252},{140,11,282},{136,0,187},{\n8,0,8},{10,0,0},{10,0,818},{139,0,988},{132,11,359},{11,0,429},{15,0,51},{135,10\n,1672},{136,0,685},{5,11,211},{7,11,88},{136,11,627},{134,0,472},{136,0,132},{6,\n11,145},{141,11,336},{4,10,751},{11,10,390},{140,10,32},{6,0,938},{6,0,1060},{4,\n11,263},{4,10,409},{133,10,78},{137,0,874},{8,0,774},{10,0,670},{12,0,51},{4,11,\n916},{6,10,473},{7,10,1602},{10,10,698},{12,10,212},{13,10,307},{145,10,105},{\n146,0,92},{143,10,156},{132,0,830},{137,0,701},{4,11,599},{6,11,1634},{7,11,5},{\n7,11,55},{7,11,67},{7,11,97},{7,11,691},{7,11,979},{7,11,1697},{8,11,207},{8,11,\n214},{8,11,231},{8,11,294},{8,11,336},{8,11,428},{8,11,451},{8,11,460},{8,11,471\n},{8,11,622},{8,11,626},{8,11,679},{8,11,759},{8,11,829},{9,11,11},{9,11,246},{9\n,11,484},{9,11,573},{9,11,706},{9,11,762},{9,11,798},{9,11,855},{9,11,870},{9,11\n,912},{10,11,303},{10,11,335},{10,11,424},{10,11,461},{10,11,543},{10,11,759},{\n10,11,814},{11,11,59},{11,11,199},{11,11,235},{11,11,475},{11,11,590},{11,11,929\n},{11,11,963},{12,11,114},{12,11,182},{12,11,226},{12,11,332},{12,11,439},{12,11\n,575},{12,11,598},{13,11,8},{13,11,125},{13,11,194},{13,11,287},{14,11,197},{14,\n11,383},{15,11,53},{17,11,63},{19,11,46},{19,11,98},{19,11,106},{148,11,85},{4,0\n,127},{5,0,350},{6,0,356},{8,0,426},{9,0,572},{10,0,247},{139,0,312},{134,0,1215\n},{6,0,59},{9,0,603},{13,0,397},{7,11,1853},{138,11,437},{134,0,1762},{147,11,\n126},{135,10,883},{13,0,293},{142,0,56},{133,10,617},{139,10,50},{5,11,187},{7,\n10,1518},{139,10,694},{135,0,441},{6,0,111},{7,0,4},{8,0,163},{8,0,776},{138,0,\n566},{132,0,806},{4,11,215},{9,11,38},{10,11,3},{11,11,23},{11,11,127},{139,11,\n796},{14,0,233},{4,10,546},{135,10,2042},{135,0,1994},{134,0,1739},{135,11,1530}\n,{136,0,393},{5,0,297},{7,0,1038},{14,0,359},{19,0,52},{148,0,47},{135,0,309},{4\n,10,313},{133,10,577},{8,10,184},{141,10,433},{135,10,935},{12,10,186},{12,10,\n292},{14,10,100},{146,10,70},{136,0,363},{14,0,175},{11,10,402},{12,10,109},{12,\n10,431},{13,10,179},{13,10,206},{14,10,217},{16,10,3},{148,10,53},{5,10,886},{6,\n10,46},{6,10,1790},{7,10,14},{7,10,732},{7,10,1654},{8,10,95},{8,10,327},{8,10,\n616},{9,10,892},{10,10,598},{10,10,769},{11,10,134},{11,10,747},{12,10,378},{142\n,10,97},{136,0,666},{135,0,1675},{6,0,655},{134,0,1600},{135,0,808},{133,10,1021\n},{4,11,28},{5,11,440},{7,11,248},{11,11,833},{140,11,344},{134,11,1654},{132,0,\n280},{140,0,54},{4,0,421},{133,0,548},{132,10,153},{6,11,339},{135,11,923},{133,\n11,853},{133,10,798},{132,10,587},{6,11,249},{7,11,1234},{139,11,573},{6,10,598}\n,{7,10,42},{8,10,695},{10,10,212},{11,10,158},{14,10,196},{145,10,85},{7,0,249},\n{5,10,957},{133,10,1008},{4,10,129},{135,10,465},{6,0,254},{7,0,842},{7,0,1659},\n{9,0,109},{10,0,103},{7,10,908},{7,10,1201},{9,10,755},{11,10,906},{12,10,527},{\n146,10,7},{5,0,262},{136,10,450},{144,0,1},{10,11,201},{142,11,319},{7,11,49},{7\n,11,392},{8,11,20},{8,11,172},{8,11,690},{9,11,383},{9,11,845},{10,11,48},{11,11\n,293},{11,11,832},{11,11,920},{141,11,221},{5,11,858},{133,11,992},{134,0,805},{\n139,10,1003},{6,0,1630},{134,11,307},{7,11,1512},{135,11,1794},{6,11,268},{137,\n11,62},{135,10,1868},{133,0,671},{4,0,989},{8,0,972},{136,0,998},{132,11,423},{\n132,0,889},{135,0,1382},{135,0,1910},{7,10,965},{7,10,1460},{135,10,1604},{4,0,\n627},{5,0,775},{138,11,106},{134,11,348},{7,0,202},{11,0,362},{11,0,948},{140,0,\n388},{138,11,771},{6,11,613},{136,11,223},{6,0,560},{7,0,451},{8,0,389},{12,0,\n490},{13,0,16},{13,0,215},{13,0,351},{18,0,132},{147,0,125},{135,0,841},{136,0,\n566},{136,0,938},{132,11,670},{5,0,912},{6,0,1695},{140,11,55},{9,11,40},{139,11\n,136},{7,0,1361},{7,10,982},{10,10,32},{143,10,56},{11,11,259},{140,11,270},{5,0\n,236},{6,0,572},{8,0,492},{11,0,618},{144,0,56},{8,11,572},{9,11,310},{9,11,682}\n,{137,11,698},{134,0,1854},{5,0,190},{136,0,318},{133,10,435},{135,0,1376},{4,11\n,296},{6,11,352},{7,11,401},{7,11,1410},{7,11,1594},{7,11,1674},{8,11,63},{8,11,\n660},{137,11,74},{7,0,349},{5,10,85},{6,10,419},{7,10,305},{7,10,361},{7,10,1337\n},{8,10,71},{140,10,519},{4,11,139},{4,11,388},{140,11,188},{6,0,1972},{6,0,2013\n},{8,0,951},{10,0,947},{10,0,974},{10,0,1018},{142,0,476},{140,10,688},{135,10,\n740},{5,10,691},{7,10,345},{9,10,94},{140,10,169},{9,0,344},{5,10,183},{6,10,582\n},{10,10,679},{140,10,435},{135,10,511},{132,0,850},{8,11,441},{10,11,314},{143,\n11,3},{7,10,1993},{136,10,684},{4,11,747},{6,11,290},{6,10,583},{7,11,649},{7,11\n,1479},{135,11,1583},{133,11,232},{133,10,704},{134,0,910},{4,10,179},{5,10,198}\n,{133,10,697},{7,10,347},{7,10,971},{8,10,181},{138,10,711},{136,11,525},{14,0,\n19},{14,0,28},{144,0,29},{7,0,85},{7,0,247},{8,0,585},{138,0,163},{4,0,487},{7,\n11,472},{7,11,1801},{10,11,748},{141,11,458},{4,10,243},{5,10,203},{7,10,19},{7,\n10,71},{7,10,113},{10,10,405},{11,10,357},{142,10,240},{7,10,1450},{139,10,99},{\n132,11,425},{138,0,145},{147,0,83},{6,10,492},{137,11,247},{4,0,1013},{134,0,\n2033},{5,10,134},{6,10,408},{6,10,495},{135,10,1593},{135,0,1922},{134,11,1768},\n{4,0,124},{10,0,457},{11,0,121},{11,0,169},{11,0,870},{11,0,874},{12,0,214},{14,\n0,187},{143,0,77},{5,0,557},{135,0,1457},{139,0,66},{5,11,943},{6,11,1779},{142,\n10,4},{4,10,248},{4,10,665},{7,10,137},{137,10,349},{7,0,1193},{5,11,245},{6,11,\n576},{7,11,582},{136,11,225},{144,0,82},{7,10,1270},{139,10,612},{5,0,454},{10,0\n,352},{138,11,352},{18,0,57},{5,10,371},{135,10,563},{135,0,1333},{6,0,107},{7,0\n,638},{7,0,1632},{9,0,396},{134,11,610},{5,0,370},{134,0,1756},{4,10,374},{7,10,\n547},{7,10,1700},{7,10,1833},{139,10,858},{133,0,204},{6,0,1305},{9,10,311},{141\n,10,42},{5,0,970},{134,0,1706},{6,10,1647},{7,10,1552},{7,10,2010},{9,10,494},{\n137,10,509},{13,11,455},{15,11,99},{15,11,129},{144,11,68},{135,0,3},{4,0,35},{5\n,0,121},{5,0,483},{5,0,685},{6,0,489},{6,0,782},{6,0,1032},{7,0,1204},{136,0,394\n},{4,0,921},{133,0,1007},{8,11,360},{138,11,63},{135,0,1696},{134,0,1519},{132,\n11,443},{135,11,944},{6,10,123},{7,10,214},{9,10,728},{10,10,157},{11,10,346},{\n11,10,662},{143,10,106},{137,0,981},{135,10,1435},{134,0,1072},{132,0,712},{134,\n0,1629},{134,0,728},{4,11,298},{137,11,483},{6,0,1177},{6,0,1271},{5,11,164},{7,\n11,121},{142,11,189},{7,0,1608},{4,10,707},{5,10,588},{6,10,393},{13,10,106},{18\n,10,49},{147,10,41},{23,0,16},{151,11,16},{6,10,211},{7,10,1690},{11,10,486},{\n140,10,369},{133,0,485},{19,11,15},{149,11,27},{4,11,172},{9,11,611},{10,11,436}\n,{12,11,673},{141,11,255},{5,11,844},{10,11,484},{11,11,754},{12,11,457},{14,11,\n171},{14,11,389},{146,11,153},{4,0,285},{5,0,27},{5,0,317},{6,0,301},{7,0,7},{8,\n0,153},{10,0,766},{11,0,468},{12,0,467},{141,0,143},{134,0,1462},{9,11,263},{10,\n11,147},{138,11,492},{133,11,537},{6,0,1945},{6,0,1986},{6,0,1991},{134,0,2038},\n{134,10,219},{137,11,842},{14,0,52},{17,0,50},{5,10,582},{6,10,1646},{7,10,99},{\n7,10,1962},{7,10,1986},{8,10,515},{8,10,773},{9,10,23},{9,10,491},{12,10,620},{\n142,10,93},{138,11,97},{20,0,21},{20,0,44},{133,10,851},{136,0,819},{139,0,917},\n{5,11,230},{5,11,392},{6,11,420},{8,10,762},{8,10,812},{9,11,568},{9,10,910},{\n140,11,612},{135,0,784},{15,0,135},{143,11,135},{10,0,454},{140,0,324},{4,11,0},\n{5,11,41},{7,11,1459},{7,11,1469},{7,11,1618},{7,11,1859},{9,11,549},{139,11,905\n},{4,10,98},{7,10,1365},{9,10,422},{9,10,670},{10,10,775},{11,10,210},{13,10,26}\n,{13,10,457},{141,10,476},{6,0,1719},{6,0,1735},{7,0,2016},{7,0,2020},{8,0,837},\n{137,0,852},{133,11,696},{135,0,852},{132,0,952},{134,10,1730},{132,11,771},{138\n,0,568},{137,0,448},{139,0,146},{8,0,67},{138,0,419},{133,11,921},{137,10,147},{\n134,0,1826},{10,0,657},{14,0,297},{142,0,361},{6,0,666},{6,0,767},{134,0,1542},{\n139,0,729},{6,11,180},{7,11,1137},{8,11,751},{139,11,805},{4,11,183},{7,11,271},\n{11,11,824},{11,11,952},{13,11,278},{13,11,339},{13,11,482},{14,11,424},{148,11,\n99},{4,0,669},{5,11,477},{5,11,596},{6,11,505},{7,11,1221},{11,11,907},{12,11,\n209},{141,11,214},{135,11,1215},{5,0,402},{6,10,30},{11,10,56},{139,10,305},{7,\n11,564},{142,11,168},{139,0,152},{7,0,912},{135,10,1614},{4,10,150},{5,10,303},{\n134,10,327},{7,0,320},{8,0,51},{9,0,868},{10,0,833},{12,0,481},{12,0,570},{148,0\n,106},{132,0,445},{7,11,274},{11,11,263},{11,11,479},{11,11,507},{140,11,277},{\n10,0,555},{11,0,308},{19,0,95},{6,11,1645},{8,10,192},{10,10,78},{141,10,359},{\n135,10,786},{6,11,92},{6,11,188},{7,11,1269},{7,11,1524},{7,11,1876},{10,11,228}\n,{139,11,1020},{4,11,459},{133,11,966},{11,0,386},{6,10,1638},{7,10,79},{7,10,\n496},{9,10,138},{10,10,336},{12,10,412},{12,10,440},{142,10,305},{133,0,239},{7,\n0,83},{7,0,1990},{8,0,130},{139,0,720},{138,11,709},{4,0,143},{5,0,550},{133,0,\n752},{5,0,123},{6,0,530},{7,0,348},{135,0,1419},{135,0,2024},{6,11,18},{7,11,179\n},{7,11,721},{7,11,932},{8,11,548},{8,11,757},{9,11,54},{9,11,65},{9,11,532},{9,\n11,844},{10,11,113},{10,11,117},{10,11,236},{10,11,315},{10,11,430},{10,11,798},\n{11,11,153},{11,11,351},{11,11,375},{12,11,78},{12,11,151},{12,11,392},{14,11,\n248},{143,11,23},{7,10,204},{7,10,415},{8,10,42},{10,10,85},{139,10,564},{134,0,\n958},{133,11,965},{132,0,210},{135,11,1429},{138,11,480},{134,11,182},{139,11,\n345},{10,11,65},{10,11,488},{138,11,497},{4,10,3},{5,10,247},{5,10,644},{7,10,\n744},{7,10,1207},{7,10,1225},{7,10,1909},{146,10,147},{132,0,430},{5,10,285},{9,\n10,67},{13,10,473},{143,10,82},{144,11,16},{7,11,1162},{9,11,588},{10,11,260},{\n151,10,8},{133,0,213},{138,0,7},{135,0,801},{134,11,1786},{135,11,308},{6,0,936}\n,{134,0,1289},{133,0,108},{132,0,885},{133,0,219},{139,0,587},{4,0,193},{5,0,916\n},{6,0,1041},{7,0,364},{10,0,398},{10,0,726},{11,0,317},{11,0,626},{12,0,142},{\n12,0,288},{12,0,678},{13,0,313},{15,0,113},{146,0,114},{135,0,1165},{6,0,241},{9\n,0,342},{10,0,729},{11,0,284},{11,0,445},{11,0,651},{11,0,863},{13,0,398},{146,0\n,99},{7,0,907},{136,0,832},{9,0,303},{4,10,29},{6,10,532},{7,10,1628},{7,10,1648\n},{9,10,350},{10,10,433},{11,10,97},{11,10,557},{11,10,745},{12,10,289},{12,10,\n335},{12,10,348},{12,10,606},{13,10,116},{13,10,233},{13,10,466},{14,10,181},{14\n,10,209},{14,10,232},{14,10,236},{14,10,300},{16,10,41},{148,10,97},{7,11,423},{\n7,10,1692},{136,11,588},{6,0,931},{134,0,1454},{5,10,501},{7,10,1704},{9,10,553}\n,{11,10,520},{12,10,557},{141,10,249},{136,11,287},{4,0,562},{9,0,254},{139,0,\n879},{132,0,786},{14,11,32},{18,11,85},{20,11,2},{152,11,16},{135,0,1294},{7,11,\n723},{135,11,1135},{6,0,216},{7,0,901},{7,0,1343},{8,0,493},{134,11,403},{7,11,\n719},{8,11,809},{136,11,834},{5,11,210},{6,11,213},{7,11,60},{10,11,364},{139,11\n,135},{7,0,341},{11,0,219},{5,11,607},{8,11,326},{136,11,490},{4,11,701},{5,11,\n472},{5,11,639},{7,11,1249},{9,11,758},{139,11,896},{135,11,380},{135,11,1947},{\n139,0,130},{135,0,1734},{10,0,115},{11,0,420},{12,0,154},{13,0,404},{14,0,346},{\n143,0,54},{134,10,129},{4,11,386},{7,11,41},{8,11,405},{9,11,497},{11,11,110},{\n11,11,360},{15,11,37},{144,11,84},{141,11,282},{5,11,46},{7,11,1452},{7,11,1480}\n,{8,11,634},{140,11,472},{4,11,524},{136,11,810},{10,11,238},{141,11,33},{133,0,\n604},{5,0,1011},{136,0,701},{8,0,856},{8,0,858},{8,0,879},{12,0,702},{142,0,447}\n,{4,0,54},{5,0,666},{7,0,1039},{7,0,1130},{9,0,195},{138,0,302},{4,10,25},{5,10,\n60},{6,10,504},{7,10,614},{7,10,1155},{140,10,0},{7,10,1248},{11,10,621},{139,10\n,702},{133,11,997},{137,10,321},{134,0,1669},{134,0,1791},{4,10,379},{135,10,\n1397},{138,11,372},{5,11,782},{5,11,829},{134,11,1738},{135,0,1228},{4,10,118},{\n6,10,274},{6,10,361},{7,10,75},{141,10,441},{132,0,623},{9,11,279},{10,11,407},{\n14,11,84},{150,11,18},{137,10,841},{135,0,798},{140,10,693},{5,10,314},{6,10,221\n},{7,10,419},{10,10,650},{11,10,396},{12,10,156},{13,10,369},{14,10,333},{145,10\n,47},{135,11,1372},{7,0,122},{9,0,259},{10,0,84},{11,0,470},{12,0,541},{141,0,\n379},{134,0,837},{8,0,1013},{4,11,78},{5,11,96},{5,11,182},{7,11,1724},{7,11,\n1825},{10,11,394},{10,11,471},{11,11,532},{14,11,340},{145,11,88},{134,0,577},{\n135,11,1964},{132,10,913},{134,0,460},{8,0,891},{10,0,901},{10,0,919},{10,0,932}\n,{12,0,715},{12,0,728},{12,0,777},{14,0,457},{144,0,103},{5,0,82},{5,0,131},{7,0\n,1755},{8,0,31},{9,0,168},{9,0,764},{139,0,869},{136,10,475},{6,0,605},{5,10,\n1016},{9,11,601},{9,11,619},{10,11,505},{10,11,732},{11,11,355},{140,11,139},{7,\n10,602},{8,10,179},{10,10,781},{140,10,126},{134,0,1246},{6,10,329},{138,10,111}\n,{6,11,215},{7,11,1028},{7,11,1473},{7,11,1721},{9,11,424},{138,11,779},{5,0,278\n},{137,0,68},{6,0,932},{6,0,1084},{144,0,86},{4,0,163},{5,0,201},{5,0,307},{5,0,\n310},{6,0,335},{7,0,284},{7,0,1660},{136,0,165},{136,0,781},{134,0,707},{6,0,33}\n,{135,0,1244},{5,10,821},{6,11,67},{6,10,1687},{7,11,258},{7,11,1630},{9,11,354}\n,{9,11,675},{10,11,830},{14,11,80},{145,11,80},{6,11,141},{7,11,225},{9,11,59},{\n9,11,607},{10,11,312},{11,11,687},{12,11,555},{13,11,373},{13,11,494},{148,11,58\n},{134,0,1113},{9,0,388},{5,10,71},{7,10,1407},{9,10,704},{10,10,261},{10,10,619\n},{11,10,547},{11,10,619},{143,10,157},{7,0,1953},{136,0,720},{138,0,203},{7,10,\n2008},{9,10,337},{138,10,517},{6,0,326},{7,0,677},{137,0,425},{139,11,81},{7,0,\n1316},{7,0,1412},{7,0,1839},{9,0,589},{11,0,241},{11,0,676},{11,0,811},{11,0,891\n},{12,0,140},{12,0,346},{12,0,479},{13,0,140},{13,0,381},{14,0,188},{18,0,30},{\n148,0,108},{5,0,416},{6,10,86},{6,10,603},{7,10,292},{7,10,561},{8,10,257},{8,10\n,382},{9,10,721},{9,10,778},{11,10,581},{140,10,466},{4,10,486},{133,10,491},{\n134,0,1300},{132,10,72},{7,0,847},{6,10,265},{7,11,430},{139,11,46},{5,11,602},{\n6,11,106},{7,11,1786},{7,11,1821},{7,11,2018},{9,11,418},{137,11,763},{5,0,358},\n{7,0,535},{7,0,1184},{10,0,662},{13,0,212},{13,0,304},{13,0,333},{145,0,98},{5,\n11,65},{6,11,416},{7,11,1720},{7,11,1924},{8,11,677},{10,11,109},{11,11,14},{11,\n11,70},{11,11,569},{11,11,735},{15,11,153},{148,11,80},{6,0,1823},{8,0,839},{8,0\n,852},{8,0,903},{10,0,940},{12,0,707},{140,0,775},{135,11,1229},{6,0,1522},{140,\n0,654},{136,11,595},{139,0,163},{141,0,314},{132,0,978},{4,0,601},{6,0,2035},{\n137,10,234},{5,10,815},{6,10,1688},{134,10,1755},{133,0,946},{136,0,434},{6,10,\n197},{136,10,205},{7,0,411},{7,0,590},{8,0,631},{9,0,323},{10,0,355},{11,0,491},\n{12,0,143},{12,0,402},{13,0,73},{14,0,408},{15,0,107},{146,0,71},{7,0,1467},{8,0\n,328},{10,0,544},{11,0,955},{12,0,13},{13,0,320},{145,0,83},{142,0,410},{11,0,\n511},{13,0,394},{14,0,298},{14,0,318},{146,0,103},{6,10,452},{7,10,312},{138,10,\n219},{138,10,589},{4,10,333},{9,10,176},{12,10,353},{141,10,187},{135,11,329},{\n132,11,469},{5,0,835},{134,0,483},{134,11,1743},{5,11,929},{6,11,340},{8,11,376}\n,{136,11,807},{134,10,1685},{132,0,677},{5,11,218},{7,11,1610},{138,11,83},{5,11\n,571},{135,11,1842},{132,11,455},{137,0,70},{135,0,1405},{7,10,135},{8,10,7},{8,\n10,62},{9,10,243},{10,10,658},{10,10,697},{11,10,456},{139,10,756},{9,10,395},{\n138,10,79},{137,0,108},{6,11,161},{7,11,372},{137,11,597},{132,11,349},{132,0,\n777},{132,0,331},{135,10,631},{133,0,747},{6,11,432},{6,11,608},{139,11,322},{\n138,10,835},{5,11,468},{7,11,1809},{10,11,325},{11,11,856},{12,11,345},{143,11,\n104},{133,11,223},{7,10,406},{7,10,459},{8,10,606},{139,10,726},{132,11,566},{\n142,0,68},{4,11,59},{135,11,1394},{6,11,436},{139,11,481},{4,11,48},{5,11,271},{\n135,11,953},{139,11,170},{5,11,610},{136,11,457},{133,11,755},{135,11,1217},{133\n,10,612},{132,11,197},{132,0,505},{4,10,372},{7,10,482},{8,10,158},{9,10,602},{9\n,10,615},{10,10,245},{10,10,678},{10,10,744},{11,10,248},{139,10,806},{133,0,326\n},{5,10,854},{135,10,1991},{4,0,691},{146,0,16},{6,0,628},{9,0,35},{10,0,680},{\n10,0,793},{11,0,364},{13,0,357},{143,0,164},{138,0,654},{6,0,32},{7,0,385},{7,0,\n757},{7,0,1916},{8,0,37},{8,0,94},{8,0,711},{9,0,541},{10,0,162},{10,0,795},{11,\n0,989},{11,0,1010},{12,0,14},{142,0,308},{133,11,217},{6,0,152},{6,0,349},{6,0,\n1682},{7,0,1252},{8,0,112},{9,0,435},{9,0,668},{10,0,290},{10,0,319},{10,0,815},\n{11,0,180},{11,0,837},{12,0,240},{13,0,152},{13,0,219},{142,0,158},{4,0,581},{\n134,0,726},{5,10,195},{135,10,1685},{6,0,126},{7,0,573},{8,0,397},{142,0,44},{\n138,0,89},{7,10,1997},{8,10,730},{139,10,1006},{134,0,1531},{134,0,1167},{5,0,\n926},{12,0,203},{133,10,751},{4,11,165},{7,11,1398},{135,11,1829},{7,0,1232},{\n137,0,531},{135,10,821},{134,0,943},{133,0,670},{4,0,880},{139,0,231},{134,0,\n1617},{135,0,1957},{5,11,9},{7,11,297},{7,11,966},{140,11,306},{6,0,975},{134,0,\n985},{5,10,950},{5,10,994},{134,10,351},{12,11,21},{151,11,7},{5,11,146},{6,11,\n411},{138,11,721},{7,0,242},{135,0,1942},{6,11,177},{135,11,467},{5,0,421},{7,10\n,47},{137,10,684},{5,0,834},{7,0,1202},{8,0,14},{9,0,481},{137,0,880},{138,0,465\n},{6,0,688},{9,0,834},{132,10,350},{132,0,855},{4,0,357},{6,0,172},{7,0,143},{\n137,0,413},{133,11,200},{132,0,590},{7,10,1812},{13,10,259},{13,10,356},{14,10,\n242},{147,10,114},{133,10,967},{11,0,114},{4,10,473},{7,10,623},{8,10,808},{9,10\n,871},{9,10,893},{11,10,431},{12,10,112},{12,10,217},{12,10,243},{12,10,562},{12\n,10,663},{12,10,683},{13,10,141},{13,10,197},{13,10,227},{13,10,406},{13,10,487}\n,{14,10,156},{14,10,203},{14,10,224},{14,10,256},{18,10,58},{150,10,0},{138,10,\n286},{4,10,222},{7,10,286},{136,10,629},{5,0,169},{7,0,333},{136,0,45},{134,11,\n481},{132,0,198},{4,0,24},{5,0,140},{5,0,185},{7,0,1500},{11,0,565},{11,0,838},{\n4,11,84},{7,11,1482},{10,11,76},{138,11,142},{133,0,585},{141,10,306},{133,11,\n1015},{4,11,315},{5,11,507},{135,11,1370},{136,10,146},{6,0,691},{134,0,1503},{4\n,0,334},{133,0,593},{4,10,465},{135,10,1663},{142,11,173},{135,0,913},{12,0,116}\n,{134,11,1722},{134,0,1360},{132,0,802},{8,11,222},{8,11,476},{9,11,238},{11,11,\n516},{11,11,575},{15,11,109},{146,11,100},{6,0,308},{9,0,673},{7,10,138},{7,10,\n517},{139,10,238},{132,0,709},{6,0,1876},{6,0,1895},{9,0,994},{9,0,1006},{12,0,\n829},{12,0,888},{12,0,891},{146,0,185},{148,10,94},{4,0,228},{133,0,897},{7,0,\n1840},{5,10,495},{7,10,834},{9,10,733},{139,10,378},{133,10,559},{6,10,21},{6,10\n,1737},{7,10,1444},{136,10,224},{4,0,608},{133,0,497},{6,11,40},{135,11,1781},{\n134,0,1573},{135,0,2039},{6,0,540},{136,0,136},{4,0,897},{5,0,786},{133,10,519},\n{6,0,1878},{6,0,1884},{9,0,938},{9,0,948},{9,0,955},{9,0,973},{9,0,1012},{12,0,\n895},{12,0,927},{143,0,254},{134,0,1469},{133,0,999},{4,0,299},{135,0,1004},{4,0\n,745},{133,0,578},{136,11,574},{133,0,456},{134,0,1457},{7,0,1679},{132,10,402},\n{7,0,693},{8,0,180},{12,0,163},{8,10,323},{136,10,479},{11,10,580},{142,10,201},\n{5,10,59},{135,10,672},{132,11,354},{146,10,34},{4,0,755},{135,11,1558},{7,0,\n1740},{146,0,48},{4,10,85},{135,10,549},{139,0,338},{133,10,94},{134,0,1091},{\n135,11,469},{12,0,695},{12,0,704},{20,0,113},{5,11,830},{14,11,338},{148,11,81},\n{135,0,1464},{6,10,11},{135,10,187},{135,0,975},{13,0,335},{132,10,522},{134,0,\n1979},{5,11,496},{135,11,203},{4,10,52},{135,10,661},{7,0,1566},{8,0,269},{9,0,\n212},{9,0,718},{14,0,15},{14,0,132},{142,0,227},{4,0,890},{5,0,805},{5,0,819},{5\n,0,961},{6,0,396},{6,0,1631},{6,0,1678},{7,0,1967},{7,0,2041},{9,0,630},{11,0,8}\n,{11,0,1019},{12,0,176},{13,0,225},{14,0,292},{21,0,24},{4,10,383},{133,10,520},\n{134,11,547},{135,11,1748},{5,11,88},{137,11,239},{146,11,128},{7,11,650},{135,\n11,1310},{4,10,281},{5,10,38},{7,10,194},{7,10,668},{7,10,1893},{137,10,397},{\n135,0,1815},{9,10,635},{139,10,559},{7,0,1505},{10,0,190},{10,0,634},{11,0,792},\n{12,0,358},{140,0,447},{5,0,0},{6,0,536},{7,0,604},{13,0,445},{145,0,126},{7,11,\n1076},{9,11,80},{11,11,78},{11,11,421},{11,11,534},{140,11,545},{8,0,966},{10,0,\n1023},{14,11,369},{146,11,72},{135,11,1641},{6,0,232},{6,0,412},{7,0,1074},{8,0,\n9},{8,0,157},{8,0,786},{9,0,196},{9,0,352},{9,0,457},{10,0,337},{11,0,232},{11,0\n,877},{12,0,480},{140,0,546},{135,0,958},{4,0,382},{136,0,579},{4,0,212},{135,0,\n1206},{4,11,497},{5,11,657},{135,11,1584},{132,0,681},{8,0,971},{138,0,965},{5,\n10,448},{136,10,535},{14,0,16},{146,0,44},{11,0,584},{11,0,616},{14,0,275},{11,\n11,584},{11,11,616},{142,11,275},{136,11,13},{7,10,610},{135,10,1501},{7,11,642}\n,{8,11,250},{11,11,123},{11,11,137},{13,11,48},{142,11,95},{133,0,655},{17,0,67}\n,{147,0,74},{134,0,751},{134,0,1967},{6,0,231},{136,0,423},{5,0,300},{138,0,1016\n},{4,10,319},{5,10,699},{138,10,673},{6,0,237},{7,0,611},{8,0,100},{9,0,416},{11\n,0,335},{12,0,173},{18,0,101},{6,10,336},{8,10,552},{9,10,285},{10,10,99},{139,\n10,568},{134,0,1370},{7,10,1406},{9,10,218},{141,10,222},{133,10,256},{135,0,\n1208},{14,11,213},{148,11,38},{6,0,1219},{135,11,1642},{13,0,417},{14,0,129},{\n143,0,15},{10,11,545},{140,11,301},{17,10,39},{148,10,36},{133,0,199},{4,11,904}\n,{133,11,794},{12,0,427},{146,0,38},{134,0,949},{8,0,665},{135,10,634},{132,10,\n618},{135,10,259},{132,10,339},{133,11,761},{141,10,169},{132,10,759},{5,0,688},\n{7,0,539},{135,0,712},{7,11,386},{138,11,713},{134,0,1186},{6,11,7},{6,11,35},{7\n,11,147},{7,11,1069},{7,11,1568},{7,11,1575},{7,11,1917},{8,11,43},{8,11,208},{9\n,11,128},{9,11,866},{10,11,20},{11,11,981},{147,11,33},{7,11,893},{8,10,482},{\n141,11,424},{6,0,312},{6,0,1715},{10,0,584},{11,0,546},{11,0,692},{12,0,259},{12\n,0,295},{13,0,46},{141,0,154},{5,10,336},{6,10,341},{6,10,478},{6,10,1763},{136,\n10,386},{137,0,151},{132,0,588},{152,0,4},{6,11,322},{9,11,552},{11,11,274},{13,\n11,209},{13,11,499},{14,11,85},{15,11,126},{145,11,70},{135,10,73},{4,0,231},{5,\n0,61},{6,0,104},{7,0,729},{7,0,964},{7,0,1658},{140,0,414},{6,0,263},{138,0,757}\n,{135,10,1971},{4,0,612},{133,0,561},{132,0,320},{135,10,1344},{8,11,83},{8,11,\n817},{9,11,28},{9,11,29},{9,11,885},{10,11,387},{11,11,633},{11,11,740},{13,11,\n235},{13,11,254},{15,11,143},{143,11,146},{5,10,396},{134,10,501},{140,11,49},{\n132,0,225},{4,10,929},{5,10,799},{8,10,46},{136,10,740},{4,0,405},{7,0,817},{14,\n0,58},{17,0,37},{146,0,124},{133,0,974},{4,11,412},{133,11,581},{4,10,892},{133,\n10,770},{4,0,996},{134,0,2026},{4,0,527},{5,0,235},{7,0,1239},{11,0,131},{140,0,\n370},{9,0,16},{13,0,386},{135,11,421},{7,0,956},{7,0,1157},{7,0,1506},{7,0,1606}\n,{7,0,1615},{7,0,1619},{7,0,1736},{7,0,1775},{8,0,590},{9,0,324},{9,0,736},{9,0,\n774},{9,0,776},{9,0,784},{10,0,567},{10,0,708},{11,0,518},{11,0,613},{11,0,695},\n{11,0,716},{11,0,739},{11,0,770},{11,0,771},{11,0,848},{11,0,857},{11,0,931},{11\n,0,947},{12,0,326},{12,0,387},{12,0,484},{12,0,528},{12,0,552},{12,0,613},{13,0,\n189},{13,0,256},{13,0,340},{13,0,432},{13,0,436},{13,0,440},{13,0,454},{14,0,174\n},{14,0,220},{14,0,284},{14,0,390},{145,0,121},{135,10,158},{9,0,137},{138,0,221\n},{4,11,110},{10,11,415},{10,11,597},{142,11,206},{141,11,496},{135,11,205},{151\n,10,25},{135,11,778},{7,11,1656},{7,10,2001},{9,11,369},{10,11,338},{10,11,490},\n{11,11,154},{11,11,545},{11,11,775},{13,11,77},{141,11,274},{4,11,444},{10,11,\n146},{140,11,9},{7,0,390},{138,0,140},{135,0,1144},{134,0,464},{7,10,1461},{140,\n10,91},{132,10,602},{4,11,283},{135,11,1194},{5,0,407},{11,0,204},{11,0,243},{11\n,0,489},{12,0,293},{19,0,37},{20,0,73},{150,0,38},{7,0,1218},{136,0,303},{5,0,\n325},{8,0,5},{8,0,227},{9,0,105},{10,0,585},{12,0,614},{4,10,13},{5,10,567},{7,\n10,1498},{9,10,124},{11,10,521},{140,10,405},{135,10,1006},{7,0,800},{10,0,12},{\n134,11,1720},{135,0,1783},{132,10,735},{138,10,812},{4,10,170},{135,10,323},{6,0\n,621},{13,0,504},{144,0,89},{5,10,304},{135,10,1403},{137,11,216},{6,0,920},{6,0\n,1104},{9,11,183},{139,11,286},{4,0,376},{133,10,742},{134,0,218},{8,0,641},{11,\n0,388},{140,0,580},{7,0,454},{7,0,782},{8,0,768},{140,0,686},{137,11,33},{133,10\n,111},{144,0,0},{10,0,676},{140,0,462},{6,0,164},{136,11,735},{133,10,444},{150,\n0,50},{7,11,1862},{12,11,491},{12,11,520},{13,11,383},{14,11,244},{146,11,12},{5\n,11,132},{9,11,486},{9,11,715},{10,11,458},{11,11,373},{11,11,668},{11,11,795},{\n11,11,897},{12,11,272},{12,11,424},{12,11,539},{12,11,558},{14,11,245},{14,11,\n263},{14,11,264},{14,11,393},{142,11,403},{8,10,123},{15,10,6},{144,10,7},{6,0,\n285},{8,0,654},{11,0,749},{12,0,190},{12,0,327},{13,0,120},{13,0,121},{13,0,327}\n,{15,0,47},{146,0,40},{5,11,8},{6,11,89},{6,11,400},{7,11,1569},{7,11,1623},{7,\n11,1850},{8,11,218},{8,11,422},{9,11,570},{138,11,626},{6,11,387},{7,11,882},{\n141,11,111},{6,0,343},{7,0,195},{9,0,226},{10,0,197},{10,0,575},{11,0,502},{11,0\n,899},{6,11,224},{7,11,877},{137,11,647},{5,10,937},{135,10,100},{135,11,790},{\n150,0,29},{147,0,8},{134,0,1812},{149,0,8},{135,11,394},{7,0,1125},{9,0,143},{11\n,0,61},{14,0,405},{150,0,21},{10,11,755},{147,11,29},{9,11,378},{141,11,162},{\n135,10,922},{5,10,619},{133,10,698},{134,0,1327},{6,0,1598},{137,0,575},{9,11,\n569},{12,11,12},{12,11,81},{12,11,319},{13,11,69},{14,11,259},{16,11,87},{17,11,\n1},{17,11,21},{17,11,24},{18,11,15},{18,11,56},{18,11,59},{18,11,127},{18,11,154\n},{19,11,19},{148,11,31},{6,0,895},{135,11,1231},{5,0,959},{7,11,124},{136,11,38\n},{5,11,261},{7,11,78},{7,11,199},{8,11,815},{9,11,126},{138,11,342},{5,10,917},\n{134,10,1659},{7,0,1759},{5,11,595},{135,11,1863},{136,0,173},{134,0,266},{142,0\n,261},{132,11,628},{5,10,251},{5,10,956},{8,10,268},{9,10,214},{146,10,142},{7,\n11,266},{136,11,804},{135,11,208},{6,11,79},{7,11,1021},{135,11,1519},{11,11,704\n},{141,11,396},{5,10,346},{5,10,711},{136,10,390},{136,11,741},{134,11,376},{134\n,0,1427},{6,0,1033},{6,0,1217},{136,0,300},{133,10,624},{6,11,100},{7,11,244},{7\n,11,632},{7,11,1609},{8,11,178},{8,11,638},{141,11,58},{6,0,584},{5,10,783},{7,\n10,1998},{135,10,2047},{5,0,427},{5,0,734},{7,0,478},{136,0,52},{7,0,239},{11,0,\n217},{142,0,165},{134,0,1129},{6,0,168},{6,0,1734},{7,0,20},{7,0,1056},{8,0,732}\n,{9,0,406},{9,0,911},{138,0,694},{132,10,594},{133,11,791},{7,11,686},{8,11,33},\n{8,11,238},{10,11,616},{11,11,467},{11,11,881},{13,11,217},{13,11,253},{142,11,\n268},{137,11,476},{134,0,418},{133,0,613},{132,0,632},{132,11,447},{7,0,32},{7,0\n,984},{8,0,85},{8,0,709},{9,0,579},{9,0,847},{9,0,856},{10,0,799},{11,0,258},{11\n,0,1007},{12,0,331},{12,0,615},{13,0,188},{13,0,435},{14,0,8},{15,0,165},{16,0,\n27},{20,0,40},{144,11,35},{4,11,128},{5,11,415},{6,11,462},{7,11,294},{7,11,578}\n,{10,11,710},{139,11,86},{5,0,694},{136,0,909},{7,0,1109},{11,0,7},{5,10,37},{6,\n10,39},{6,10,451},{7,10,218},{7,10,1166},{7,10,1687},{8,10,662},{144,10,2},{136,\n11,587},{6,11,427},{7,11,1018},{138,11,692},{4,11,195},{6,10,508},{135,11,802},{\n4,0,167},{135,0,82},{5,0,62},{6,0,24},{6,0,534},{7,0,74},{7,0,678},{7,0,684},{7,\n0,1043},{7,0,1072},{8,0,280},{8,0,541},{8,0,686},{9,0,258},{10,0,519},{11,0,252}\n,{140,0,282},{138,0,33},{4,0,359},{133,11,738},{7,0,980},{9,0,328},{13,0,186},{\n13,0,364},{7,10,635},{7,10,796},{8,10,331},{9,10,330},{9,10,865},{10,10,119},{10\n,10,235},{11,10,111},{11,10,129},{11,10,240},{12,10,31},{12,10,66},{12,10,222},{\n12,10,269},{12,10,599},{12,10,684},{12,10,689},{12,10,691},{142,10,345},{137,10,\n527},{6,0,596},{7,0,585},{135,10,702},{134,11,1683},{133,0,211},{6,0,145},{141,0\n,336},{134,0,1130},{7,0,873},{6,10,37},{7,10,1666},{8,10,195},{8,10,316},{9,10,\n178},{9,10,276},{9,10,339},{9,10,536},{10,10,102},{10,10,362},{10,10,785},{11,10\n,55},{11,10,149},{11,10,773},{13,10,416},{13,10,419},{14,10,38},{14,10,41},{142,\n10,210},{8,0,840},{136,0,841},{132,0,263},{5,11,3},{8,11,578},{9,11,118},{10,11,\n705},{12,11,383},{141,11,279},{132,0,916},{133,11,229},{133,10,645},{15,0,155},{\n16,0,79},{8,11,102},{10,11,578},{10,11,672},{12,11,496},{13,11,408},{14,11,121},\n{145,11,106},{4,0,599},{5,0,592},{6,0,1634},{7,0,5},{7,0,55},{7,0,67},{7,0,97},{\n7,0,691},{7,0,979},{7,0,1600},{7,0,1697},{8,0,207},{8,0,214},{8,0,231},{8,0,294}\n,{8,0,336},{8,0,428},{8,0,471},{8,0,622},{8,0,626},{8,0,679},{8,0,759},{8,0,829}\n,{9,0,11},{9,0,246},{9,0,484},{9,0,573},{9,0,706},{9,0,762},{9,0,798},{9,0,855},\n{9,0,870},{9,0,912},{10,0,303},{10,0,335},{10,0,424},{10,0,461},{10,0,543},{10,0\n,759},{10,0,814},{11,0,59},{11,0,199},{11,0,235},{11,0,590},{11,0,631},{11,0,929\n},{11,0,963},{11,0,987},{12,0,114},{12,0,182},{12,0,226},{12,0,332},{12,0,439},{\n12,0,575},{12,0,598},{12,0,675},{13,0,8},{13,0,125},{13,0,194},{13,0,287},{14,0,\n197},{14,0,383},{15,0,53},{17,0,63},{19,0,46},{19,0,98},{19,0,106},{148,0,85},{7\n,0,1356},{132,10,290},{6,10,70},{7,10,1292},{10,10,762},{139,10,288},{150,11,55}\n,{4,0,593},{8,11,115},{8,11,350},{9,11,489},{10,11,128},{11,11,306},{12,11,373},\n{14,11,30},{17,11,79},{147,11,80},{135,11,1235},{134,0,1392},{4,11,230},{133,11,\n702},{147,0,126},{7,10,131},{7,10,422},{8,10,210},{140,10,573},{134,0,1179},{139\n,11,435},{139,10,797},{134,11,1728},{4,0,162},{18,11,26},{19,11,42},{20,11,43},{\n21,11,0},{23,11,27},{152,11,14},{132,10,936},{6,0,765},{5,10,453},{134,10,441},{\n133,0,187},{135,0,1286},{6,0,635},{6,0,904},{6,0,1210},{134,0,1489},{4,0,215},{8\n,0,890},{9,0,38},{10,0,923},{11,0,23},{11,0,127},{139,0,796},{6,0,1165},{134,0,\n1306},{7,0,716},{13,0,97},{141,0,251},{132,10,653},{136,0,657},{146,10,80},{5,11\n,622},{7,11,1032},{11,11,26},{11,11,213},{11,11,707},{12,11,380},{13,11,226},{\n141,11,355},{6,0,299},{5,11,70},{6,11,334},{9,11,171},{11,11,637},{12,11,202},{\n14,11,222},{145,11,42},{142,0,134},{4,11,23},{5,11,313},{5,11,1014},{6,11,50},{6\n,11,51},{7,11,142},{7,11,384},{9,11,783},{139,11,741},{4,11,141},{7,11,559},{8,\n11,640},{9,11,460},{12,11,183},{141,11,488},{136,11,614},{7,10,1368},{8,10,232},\n{8,10,361},{10,10,682},{138,10,742},{137,10,534},{6,0,1082},{140,0,658},{137,10,\n27},{135,0,2002},{142,10,12},{4,0,28},{5,0,440},{7,0,248},{11,0,833},{140,0,344}\n,{7,10,736},{139,10,264},{134,10,1657},{134,0,1654},{138,0,531},{5,11,222},{9,11\n,140},{138,11,534},{6,0,634},{6,0,798},{134,0,840},{138,11,503},{135,10,127},{\n133,0,853},{5,11,154},{7,11,1491},{10,11,379},{138,11,485},{6,0,249},{7,0,1234},\n{139,0,573},{133,11,716},{7,11,1570},{140,11,542},{136,10,364},{138,0,527},{4,11\n,91},{5,11,388},{5,11,845},{6,11,206},{6,11,252},{6,11,365},{7,11,136},{7,11,531\n},{8,11,264},{136,11,621},{134,0,1419},{135,11,1441},{7,0,49},{7,0,392},{8,0,20}\n,{8,0,172},{8,0,690},{9,0,383},{9,0,845},{10,0,48},{11,0,293},{11,0,832},{11,0,\n920},{11,0,984},{141,0,221},{5,0,858},{133,0,992},{5,0,728},{137,10,792},{5,10,\n909},{9,10,849},{138,10,805},{7,0,525},{7,0,1579},{8,0,497},{136,0,573},{6,0,268\n},{137,0,62},{135,11,576},{134,0,1201},{5,11,771},{5,11,863},{5,11,898},{6,11,\n1632},{6,11,1644},{134,11,1780},{133,11,331},{7,0,193},{7,0,1105},{10,0,495},{7,\n10,397},{8,10,124},{8,10,619},{9,10,305},{11,10,40},{12,10,349},{13,10,134},{13,\n10,295},{14,10,155},{15,10,120},{146,10,105},{138,0,106},{6,0,859},{5,11,107},{7\n,11,201},{136,11,518},{6,11,446},{135,11,1817},{13,0,23},{4,10,262},{135,10,342}\n,{133,10,641},{137,11,851},{6,0,925},{137,0,813},{132,11,504},{6,0,613},{136,0,\n223},{4,10,99},{6,10,250},{6,10,346},{8,10,127},{138,10,81},{136,0,953},{132,10,\n915},{139,11,892},{5,10,75},{9,10,517},{10,10,470},{12,10,155},{141,10,224},{4,0\n,666},{7,0,1017},{7,11,996},{138,11,390},{5,11,883},{133,11,975},{14,10,83},{142\n,11,83},{4,0,670},{5,11,922},{134,11,1707},{135,0,216},{9,0,40},{11,0,136},{135,\n11,787},{5,10,954},{5,11,993},{7,11,515},{137,11,91},{139,0,259},{7,0,1114},{9,0\n,310},{9,0,682},{10,0,440},{13,0,40},{6,10,304},{8,10,418},{11,10,341},{139,10,\n675},{14,0,296},{9,10,410},{139,10,425},{10,11,377},{12,11,363},{13,11,68},{13,\n11,94},{14,11,108},{142,11,306},{7,0,1401},{135,0,1476},{4,0,296},{6,0,475},{7,0\n,401},{7,0,1410},{7,0,1594},{7,0,1674},{8,0,63},{8,0,660},{137,0,74},{4,0,139},{\n4,0,388},{140,0,188},{132,0,797},{132,11,766},{5,11,103},{7,11,921},{8,11,580},{\n8,11,593},{8,11,630},{138,11,28},{4,11,911},{5,11,867},{133,11,1013},{134,10,14}\n,{134,0,1572},{134,10,1708},{21,0,39},{5,10,113},{6,10,243},{7,10,1865},{11,10,\n161},{16,10,37},{145,10,99},{7,11,1563},{141,11,182},{5,11,135},{6,11,519},{7,11\n,1722},{10,11,271},{11,11,261},{145,11,54},{132,10,274},{134,0,1594},{4,11,300},\n{5,11,436},{135,11,484},{4,0,747},{6,0,290},{7,0,649},{7,0,1479},{135,0,1583},{\n133,11,535},{147,11,82},{133,0,232},{137,0,887},{135,10,166},{136,0,521},{4,0,14\n},{7,0,472},{7,0,1801},{10,0,748},{141,0,458},{134,0,741},{134,0,992},{16,0,111}\n,{137,10,304},{4,0,425},{5,11,387},{7,11,557},{12,11,547},{142,11,86},{135,11,\n1747},{5,10,654},{135,11,1489},{7,0,789},{4,11,6},{5,11,708},{136,11,75},{6,10,\n273},{10,10,188},{13,10,377},{146,10,77},{6,0,1593},{4,11,303},{7,11,619},{10,11\n,547},{10,11,687},{11,11,122},{140,11,601},{134,0,1768},{135,10,410},{138,11,772\n},{11,0,233},{139,10,524},{5,0,943},{134,0,1779},{134,10,1785},{136,11,529},{132\n,0,955},{5,0,245},{6,0,576},{7,0,582},{136,0,225},{132,10,780},{142,0,241},{134,\n0,1943},{4,11,106},{7,11,310},{7,11,1785},{10,11,690},{139,11,717},{134,0,1284},\n{5,11,890},{133,11,988},{6,11,626},{142,11,431},{10,11,706},{145,11,32},{137,11,\n332},{132,11,698},{135,0,709},{5,10,948},{138,11,17},{136,0,554},{134,0,1564},{\n139,10,941},{132,0,443},{134,0,909},{134,11,84},{142,0,280},{4,10,532},{5,10,706\n},{135,10,662},{132,0,729},{5,10,837},{6,10,1651},{139,10,985},{135,10,1861},{4,\n0,348},{152,11,3},{5,11,986},{6,11,130},{7,11,1582},{8,11,458},{10,11,101},{10,\n11,318},{138,11,823},{134,0,758},{4,0,298},{137,0,848},{4,10,330},{7,10,933},{7,\n10,2012},{136,10,292},{7,11,1644},{137,11,129},{6,0,1422},{9,0,829},{135,10,767}\n,{5,0,164},{7,0,121},{142,0,189},{7,0,812},{7,0,1261},{7,0,1360},{9,0,632},{140,\n0,352},{135,11,1788},{139,0,556},{135,11,997},{145,10,114},{4,0,172},{9,0,611},{\n10,0,436},{12,0,673},{13,0,255},{137,10,883},{11,0,530},{138,10,274},{133,0,844}\n,{134,0,984},{13,0,232},{18,0,35},{4,10,703},{135,10,207},{132,10,571},{9,0,263}\n,{10,0,147},{138,0,492},{7,11,1756},{137,11,98},{5,10,873},{5,10,960},{8,10,823}\n,{137,10,881},{133,0,537},{132,0,859},{7,11,1046},{139,11,160},{137,0,842},{139,\n10,283},{5,10,33},{6,10,470},{139,10,424},{6,11,45},{7,11,433},{8,11,129},{9,11,\n21},{10,11,392},{11,11,79},{12,11,499},{13,11,199},{141,11,451},{135,0,1291},{\n135,10,1882},{7,11,558},{136,11,353},{134,0,1482},{5,0,230},{5,0,392},{6,0,420},\n{9,0,568},{140,0,612},{6,0,262},{7,10,90},{7,10,664},{7,10,830},{7,10,1380},{7,\n10,2025},{8,11,81},{8,10,448},{8,10,828},{9,11,189},{9,11,201},{11,11,478},{11,\n11,712},{141,11,338},{142,0,31},{5,11,353},{151,11,26},{132,0,753},{4,0,0},{5,0,\n41},{7,0,1459},{7,0,1469},{7,0,1859},{9,0,549},{139,0,905},{9,10,417},{137,10,\n493},{135,11,1113},{133,0,696},{141,11,448},{134,10,295},{132,0,834},{4,0,771},{\n5,10,1019},{6,11,25},{7,11,855},{7,11,1258},{144,11,32},{134,0,1076},{133,0,921}\n,{133,0,674},{4,11,4},{7,11,1118},{7,11,1320},{7,11,1706},{8,11,277},{9,11,622},\n{10,11,9},{11,11,724},{12,11,350},{12,11,397},{13,11,28},{13,11,159},{15,11,89},\n{18,11,5},{19,11,9},{20,11,34},{150,11,47},{134,10,208},{6,0,444},{136,0,308},{6\n,0,180},{7,0,1137},{8,0,751},{139,0,805},{4,0,183},{7,0,271},{11,0,824},{11,0,\n952},{13,0,278},{13,0,339},{13,0,482},{14,0,424},{148,0,99},{7,11,317},{135,11,\n569},{4,0,19},{5,0,477},{5,0,596},{6,0,505},{7,0,1221},{11,0,907},{12,0,209},{\n141,0,214},{135,0,1215},{6,0,271},{7,0,398},{8,0,387},{10,0,344},{7,10,448},{7,\n10,1629},{7,10,1813},{8,10,442},{9,10,710},{10,10,282},{138,10,722},{11,10,844},\n{12,10,104},{140,10,625},{134,11,255},{133,10,787},{134,0,1645},{11,11,956},{151\n,11,3},{6,0,92},{6,0,188},{7,0,209},{7,0,1269},{7,0,1524},{7,0,1876},{8,0,661},{\n10,0,42},{10,0,228},{11,0,58},{11,0,1020},{12,0,58},{12,0,118},{141,0,32},{4,0,\n459},{133,0,966},{4,11,536},{7,11,1141},{10,11,723},{139,11,371},{140,0,330},{\n134,0,1557},{7,11,285},{135,11,876},{136,10,491},{135,11,560},{6,0,18},{7,0,179}\n,{7,0,932},{8,0,548},{8,0,757},{9,0,54},{9,0,65},{9,0,532},{9,0,844},{10,0,113},\n{10,0,117},{10,0,315},{10,0,560},{10,0,622},{10,0,798},{11,0,153},{11,0,351},{11\n,0,375},{12,0,78},{12,0,151},{12,0,392},{12,0,666},{14,0,248},{143,0,23},{6,0,\n1742},{132,11,690},{4,10,403},{5,10,441},{7,10,450},{10,10,840},{11,10,101},{12,\n10,193},{141,10,430},{133,0,965},{134,0,182},{10,0,65},{10,0,488},{138,0,497},{\n135,11,1346},{6,0,973},{6,0,1158},{10,11,200},{19,11,2},{151,11,22},{4,11,190},{\n133,11,554},{133,10,679},{7,0,328},{137,10,326},{133,11,1001},{9,0,588},{138,0,\n260},{133,11,446},{135,10,1128},{135,10,1796},{147,11,119},{134,0,1786},{6,0,\n1328},{6,0,1985},{8,0,962},{138,0,1017},{135,0,308},{11,0,508},{4,10,574},{7,10,\n350},{7,10,1024},{8,10,338},{9,10,677},{138,10,808},{138,11,752},{135,10,1081},{\n137,11,96},{7,10,1676},{135,10,2037},{136,0,588},{132,11,304},{133,0,614},{140,0\n,793},{136,0,287},{137,10,297},{141,10,37},{6,11,53},{6,11,199},{7,11,1408},{8,\n11,32},{8,11,93},{9,11,437},{10,11,397},{10,11,629},{11,11,593},{11,11,763},{13,\n11,326},{145,11,35},{134,11,105},{9,11,320},{10,11,506},{138,11,794},{5,11,114},\n{5,11,255},{141,11,285},{140,0,290},{7,11,2035},{8,11,19},{9,11,89},{138,11,831}\n,{134,0,1136},{7,0,719},{8,0,796},{8,0,809},{8,0,834},{6,10,306},{7,10,1140},{7,\n10,1340},{8,10,133},{138,10,449},{139,10,1011},{5,0,210},{6,0,213},{7,0,60},{10,\n0,364},{139,0,135},{5,0,607},{8,0,326},{136,0,490},{138,11,176},{132,0,701},{5,0\n,472},{7,0,380},{137,0,758},{135,0,1947},{6,0,1079},{138,0,278},{138,11,391},{5,\n10,329},{8,10,260},{139,11,156},{4,0,386},{7,0,41},{8,0,405},{8,0,728},{9,0,497}\n,{11,0,110},{11,0,360},{15,0,37},{144,0,84},{5,0,46},{7,0,1452},{7,0,1480},{8,0,\n634},{140,0,472},{136,0,961},{4,0,524},{136,0,810},{10,0,238},{141,0,33},{132,10\n,657},{152,10,7},{133,0,532},{5,0,997},{135,10,1665},{7,11,594},{7,11,851},{7,11\n,1858},{9,11,411},{9,11,574},{9,11,666},{9,11,737},{10,11,346},{10,11,712},{11,\n11,246},{11,11,432},{11,11,517},{11,11,647},{11,11,679},{11,11,727},{12,11,304},\n{12,11,305},{12,11,323},{12,11,483},{12,11,572},{12,11,593},{12,11,602},{13,11,\n95},{13,11,101},{13,11,171},{13,11,315},{13,11,378},{13,11,425},{13,11,475},{14,\n11,63},{14,11,380},{14,11,384},{15,11,133},{18,11,112},{148,11,72},{5,11,955},{\n136,11,814},{134,0,1301},{5,10,66},{7,10,1896},{136,10,288},{133,11,56},{134,10,\n1643},{6,0,1298},{148,11,100},{5,0,782},{5,0,829},{6,0,671},{6,0,1156},{6,0,1738\n},{137,11,621},{4,0,306},{5,0,570},{7,0,1347},{5,10,91},{5,10,648},{5,10,750},{5\n,10,781},{6,10,54},{6,10,112},{6,10,402},{6,10,1732},{7,10,315},{7,10,749},{7,10\n,1900},{9,10,78},{9,10,508},{10,10,611},{10,10,811},{11,10,510},{11,10,728},{13,\n10,36},{14,10,39},{16,10,83},{17,10,124},{148,10,30},{8,10,570},{9,11,477},{141,\n11,78},{4,11,639},{10,11,4},{10,10,322},{10,10,719},{11,10,407},{11,11,638},{12,\n11,177},{148,11,57},{7,0,1823},{139,0,693},{7,0,759},{5,11,758},{8,10,125},{8,10\n,369},{8,10,524},{10,10,486},{11,10,13},{11,10,381},{11,10,736},{11,10,766},{11,\n10,845},{13,10,114},{13,10,292},{142,10,47},{7,0,1932},{6,10,1684},{6,10,1731},{\n7,10,356},{8,10,54},{8,10,221},{9,10,225},{9,10,356},{10,10,77},{10,10,446},{10,\n10,731},{12,10,404},{141,10,491},{135,11,552},{135,11,1112},{4,0,78},{5,0,96},{5\n,0,182},{6,0,1257},{7,0,1724},{7,0,1825},{10,0,394},{10,0,471},{11,0,532},{14,0,\n340},{145,0,88},{139,11,328},{135,0,1964},{132,10,411},{4,10,80},{5,10,44},{137,\n11,133},{5,11,110},{6,11,169},{6,11,1702},{7,11,400},{8,11,538},{9,11,184},{9,11\n,524},{140,11,218},{4,0,521},{5,10,299},{7,10,1083},{140,11,554},{6,11,133},{9,\n11,353},{12,11,628},{146,11,79},{6,0,215},{7,0,584},{7,0,1028},{7,0,1473},{7,0,\n1721},{9,0,424},{138,0,779},{7,0,857},{7,0,1209},{7,10,1713},{9,10,537},{10,10,\n165},{12,10,219},{140,10,561},{4,10,219},{6,11,93},{7,11,1422},{7,10,1761},{7,11\n,1851},{8,11,673},{9,10,86},{9,11,529},{140,11,43},{137,11,371},{136,0,671},{5,0\n,328},{135,0,918},{132,0,529},{9,11,25},{10,11,467},{138,11,559},{4,11,335},{135\n,11,942},{134,0,716},{134,0,1509},{6,0,67},{7,0,258},{7,0,1630},{9,0,354},{9,0,\n675},{10,0,830},{14,0,80},{17,0,80},{140,10,428},{134,0,1112},{6,0,141},{7,0,225\n},{9,0,59},{9,0,607},{10,0,312},{11,0,687},{12,0,555},{13,0,373},{13,0,494},{148\n,0,58},{133,10,514},{8,11,39},{10,11,773},{11,11,84},{12,11,205},{142,11,1},{8,0\n,783},{5,11,601},{133,11,870},{136,11,594},{4,10,55},{5,10,301},{6,10,571},{14,\n10,49},{146,10,102},{132,11,181},{134,11,1652},{133,10,364},{4,11,97},{5,11,147}\n,{6,11,286},{7,11,1362},{141,11,176},{4,10,76},{7,10,1550},{9,10,306},{9,10,430}\n,{9,10,663},{10,10,683},{11,10,427},{11,10,753},{12,10,334},{12,10,442},{14,10,\n258},{14,10,366},{143,10,131},{137,10,52},{6,0,955},{134,0,1498},{6,11,375},{7,\n11,169},{7,11,254},{136,11,780},{7,0,430},{11,0,46},{14,0,343},{142,11,343},{135\n,0,1183},{5,0,602},{7,0,2018},{9,0,418},{9,0,803},{135,11,1447},{8,0,677},{135,\n11,1044},{139,11,285},{4,10,656},{135,10,779},{135,10,144},{5,11,629},{135,11,\n1549},{135,10,1373},{138,11,209},{7,10,554},{7,10,605},{141,10,10},{5,10,838},{5\n,10,841},{134,10,1649},{133,10,1012},{6,0,1357},{134,0,1380},{144,0,53},{6,0,590\n},{7,10,365},{7,10,1357},{7,10,1497},{8,10,154},{141,10,281},{133,10,340},{132,\n11,420},{135,0,329},{147,11,32},{4,0,469},{10,11,429},{139,10,495},{8,10,261},{9\n,10,144},{9,10,466},{10,10,370},{12,10,470},{13,10,144},{142,10,348},{142,0,460}\n,{4,11,325},{9,10,897},{138,11,125},{6,0,1743},{6,10,248},{9,10,546},{10,10,535}\n,{11,10,681},{141,10,135},{4,0,990},{5,0,929},{6,0,340},{8,0,376},{8,0,807},{8,0\n,963},{8,0,980},{138,0,1007},{134,0,1603},{140,0,250},{4,11,714},{133,11,469},{\n134,10,567},{136,10,445},{5,0,218},{7,0,1610},{8,0,646},{10,0,83},{11,11,138},{\n140,11,40},{7,0,1512},{135,0,1794},{135,11,1216},{11,0,0},{16,0,78},{132,11,718}\n,{133,0,571},{132,0,455},{134,0,1012},{5,11,124},{5,11,144},{6,11,548},{7,11,15}\n,{7,11,153},{137,11,629},{142,11,10},{6,11,75},{7,11,1531},{8,11,416},{9,11,240}\n,{9,11,275},{10,11,100},{11,11,658},{11,11,979},{12,11,86},{13,11,468},{14,11,66\n},{14,11,207},{15,11,20},{15,11,25},{144,11,58},{132,10,577},{5,11,141},{5,11,\n915},{6,11,1783},{7,11,211},{7,11,698},{7,11,1353},{9,11,83},{9,11,281},{10,11,\n376},{10,11,431},{11,11,543},{12,11,664},{13,11,280},{13,11,428},{14,11,61},{14,\n11,128},{17,11,52},{145,11,81},{6,0,161},{7,0,372},{137,0,597},{132,0,349},{10,\n11,702},{139,11,245},{134,0,524},{134,10,174},{6,0,432},{9,0,751},{139,0,322},{\n147,11,94},{4,11,338},{133,11,400},{5,0,468},{10,0,325},{11,0,856},{12,0,345},{\n143,0,104},{133,0,223},{132,0,566},{4,11,221},{5,11,659},{5,11,989},{7,11,697},{\n7,11,1211},{138,11,284},{135,11,1070},{4,0,59},{135,0,1394},{6,0,436},{11,0,481}\n,{5,10,878},{133,10,972},{4,0,48},{5,0,271},{135,0,953},{5,0,610},{136,0,457},{4\n,0,773},{5,0,618},{137,0,756},{133,0,755},{135,0,1217},{138,11,507},{132,10,351}\n,{132,0,197},{143,11,78},{4,11,188},{7,11,805},{11,11,276},{142,11,293},{5,11,\n884},{139,11,991},{132,10,286},{10,0,259},{10,0,428},{7,10,438},{7,10,627},{7,10\n,1516},{8,10,40},{9,10,56},{9,10,294},{11,10,969},{11,10,995},{146,10,148},{4,0,\n356},{5,0,217},{5,0,492},{5,0,656},{8,0,544},{136,11,544},{5,0,259},{6,0,1230},{\n7,0,414},{7,0,854},{142,0,107},{132,0,1007},{15,0,14},{144,0,5},{6,0,1580},{132,\n10,738},{132,11,596},{132,0,673},{133,10,866},{6,0,1843},{135,11,1847},{4,0,165}\n,{7,0,1398},{135,0,1829},{135,11,1634},{147,11,65},{6,0,885},{6,0,1009},{137,0,\n809},{133,10,116},{132,10,457},{136,11,770},{9,0,498},{12,0,181},{10,11,361},{\n142,11,316},{134,11,595},{5,0,9},{7,0,297},{7,0,966},{140,0,306},{4,11,89},{5,11\n,489},{6,11,315},{7,11,553},{7,11,1745},{138,11,243},{134,0,1487},{132,0,437},{5\n,0,146},{6,0,411},{138,0,721},{5,10,527},{6,10,189},{135,10,859},{11,10,104},{11\n,10,554},{15,10,60},{143,10,125},{6,11,1658},{9,11,3},{10,11,154},{11,11,641},{\n13,11,85},{13,11,201},{141,11,346},{6,0,177},{135,0,467},{134,0,1377},{134,10,\n116},{136,11,645},{4,11,166},{5,11,505},{6,11,1670},{137,11,110},{133,10,487},{4\n,10,86},{5,10,667},{5,10,753},{6,10,316},{6,10,455},{135,10,946},{133,0,200},{\n132,0,959},{6,0,1928},{134,0,1957},{139,11,203},{150,10,45},{4,10,79},{7,10,1773\n},{10,10,450},{11,10,589},{13,10,332},{13,10,493},{14,10,183},{14,10,334},{14,10\n,362},{14,10,368},{14,10,376},{14,10,379},{19,10,90},{19,10,103},{19,10,127},{\n148,10,90},{6,0,1435},{135,11,1275},{134,0,481},{7,11,445},{8,11,307},{8,11,704}\n,{10,11,41},{10,11,439},{11,11,237},{11,11,622},{140,11,201},{135,11,869},{4,0,\n84},{7,0,1482},{10,0,76},{138,0,142},{11,11,277},{144,11,14},{135,11,1977},{4,11\n,189},{5,11,713},{136,11,57},{133,0,1015},{138,11,371},{4,0,315},{5,0,507},{135,\n0,1370},{4,11,552},{142,10,381},{9,0,759},{16,0,31},{16,0,39},{16,0,75},{18,0,24\n},{20,0,42},{152,0,1},{134,0,712},{134,0,1722},{133,10,663},{133,10,846},{8,0,\n222},{8,0,476},{9,0,238},{11,0,516},{11,0,575},{15,0,109},{146,0,100},{7,0,1402}\n,{7,0,1414},{12,0,456},{5,10,378},{8,10,465},{9,10,286},{10,10,185},{10,10,562},\n{10,10,635},{11,10,31},{11,10,393},{13,10,312},{18,10,65},{18,10,96},{147,10,89}\n,{4,0,986},{6,0,1958},{6,0,2032},{8,0,934},{138,0,985},{7,10,1880},{9,10,680},{\n139,10,798},{134,10,1770},{145,11,49},{132,11,614},{132,10,648},{5,10,945},{6,10\n,1656},{6,10,1787},{7,10,167},{8,10,824},{9,10,391},{10,10,375},{139,10,185},{\n138,11,661},{7,0,1273},{135,11,1945},{7,0,706},{7,0,1058},{138,0,538},{7,10,1645\n},{8,10,352},{137,10,249},{132,10,152},{11,0,92},{11,0,196},{11,0,409},{11,0,450\n},{11,0,666},{11,0,777},{12,0,262},{13,0,385},{13,0,393},{15,0,115},{16,0,45},{\n145,0,82},{133,10,1006},{6,0,40},{135,0,1781},{9,11,614},{139,11,327},{5,10,420}\n,{135,10,1449},{135,0,431},{10,0,97},{135,10,832},{6,0,423},{7,0,665},{135,0,\n1210},{7,0,237},{8,0,664},{9,0,42},{9,0,266},{9,0,380},{9,0,645},{10,0,177},{138\n,0,276},{7,0,264},{133,10,351},{8,0,213},{5,10,40},{7,10,598},{7,10,1638},{9,10,\n166},{9,10,640},{9,10,685},{9,10,773},{11,10,215},{13,10,65},{14,10,172},{14,10,\n317},{145,10,6},{5,11,84},{134,11,163},{8,10,60},{9,10,343},{139,10,769},{137,0,\n455},{133,11,410},{8,0,906},{12,0,700},{12,0,706},{140,0,729},{21,11,33},{150,11\n,40},{7,10,1951},{8,10,765},{8,10,772},{140,10,671},{7,10,108},{8,10,219},{8,10,\n388},{9,10,639},{9,10,775},{11,10,275},{140,10,464},{5,11,322},{7,11,1941},{8,11\n,186},{9,11,262},{10,11,187},{14,11,208},{146,11,130},{139,0,624},{8,0,574},{5,\n11,227},{140,11,29},{7,11,1546},{11,11,299},{142,11,407},{5,10,15},{6,10,56},{7,\n10,1758},{8,10,500},{9,10,730},{11,10,331},{13,10,150},{142,10,282},{7,11,1395},\n{8,11,486},{9,11,236},{9,11,878},{10,11,218},{11,11,95},{19,11,17},{147,11,31},{\n135,11,2043},{4,0,354},{146,11,4},{140,11,80},{135,0,1558},{134,10,1886},{5,10,\n205},{6,10,438},{137,10,711},{133,11,522},{133,10,534},{7,0,235},{7,0,1475},{15,\n0,68},{146,0,120},{137,10,691},{4,0,942},{6,0,1813},{8,0,917},{10,0,884},{12,0,\n696},{12,0,717},{12,0,723},{12,0,738},{12,0,749},{12,0,780},{16,0,97},{146,0,169\n},{6,10,443},{8,11,562},{9,10,237},{9,10,571},{9,10,695},{10,10,139},{11,10,715}\n,{12,10,417},{141,10,421},{135,0,957},{133,0,830},{134,11,1771},{146,0,23},{5,0,\n496},{6,0,694},{7,0,203},{7,11,1190},{137,11,620},{137,11,132},{6,0,547},{134,0,\n1549},{8,11,258},{9,11,208},{137,11,359},{4,0,864},{5,0,88},{137,0,239},{135,11,\n493},{4,11,317},{135,11,1279},{132,11,477},{4,10,578},{5,11,63},{133,11,509},{7,\n0,650},{135,0,1310},{7,0,1076},{9,0,80},{11,0,78},{11,0,421},{11,0,534},{140,0,\n545},{132,11,288},{12,0,553},{14,0,118},{133,10,923},{7,0,274},{11,0,479},{139,0\n,507},{8,11,89},{8,11,620},{9,11,49},{10,11,774},{11,11,628},{12,11,322},{143,11\n,124},{4,0,497},{135,0,1584},{7,0,261},{7,0,1115},{7,0,1354},{7,0,1404},{7,0,\n1588},{7,0,1705},{7,0,1902},{9,0,465},{10,0,248},{10,0,349},{10,0,647},{11,0,527\n},{11,0,660},{11,0,669},{12,0,529},{13,0,305},{132,10,924},{133,10,665},{136,0,\n13},{6,0,791},{138,11,120},{7,0,642},{8,0,250},{11,0,123},{11,0,137},{13,0,48},{\n142,0,95},{4,10,265},{7,10,807},{135,10,950},{5,10,93},{140,10,267},{135,0,1429}\n,{4,0,949},{10,0,885},{10,0,891},{10,0,900},{10,0,939},{12,0,760},{142,0,449},{\n139,11,366},{132,0,818},{134,11,85},{135,10,994},{7,0,330},{5,10,233},{5,10,320}\n,{6,10,140},{136,10,295},{4,0,1004},{8,0,982},{136,0,993},{133,10,978},{4,10,905\n},{6,10,1701},{137,10,843},{10,0,545},{140,0,301},{6,0,947},{134,0,1062},{134,0,\n1188},{4,0,904},{5,0,794},{152,10,6},{134,0,1372},{135,11,608},{5,11,279},{6,11,\n235},{7,11,468},{8,11,446},{9,11,637},{10,11,717},{11,11,738},{140,11,514},{132,\n10,509},{5,11,17},{6,11,371},{137,11,528},{132,0,693},{4,11,115},{5,11,669},{6,\n11,407},{8,11,311},{11,11,10},{141,11,5},{11,0,377},{7,10,273},{137,11,381},{135\n,0,695},{7,0,386},{138,0,713},{135,10,1041},{134,0,1291},{6,0,7},{6,0,35},{7,0,\n147},{7,0,1069},{7,0,1568},{7,0,1575},{7,0,1917},{8,0,43},{8,0,208},{9,0,128},{9\n,0,866},{10,0,20},{11,0,981},{147,0,33},{7,0,893},{141,0,424},{139,10,234},{150,\n11,56},{5,11,779},{5,11,807},{6,11,1655},{134,11,1676},{5,10,802},{7,10,2021},{\n136,10,805},{4,11,196},{5,10,167},{5,11,558},{5,10,899},{5,11,949},{6,10,410},{\n137,10,777},{137,10,789},{134,10,1705},{8,0,904},{140,0,787},{6,0,322},{9,0,552}\n,{11,0,274},{13,0,209},{13,0,499},{14,0,85},{15,0,126},{145,0,70},{135,10,10},{5\n,10,11},{6,10,117},{6,10,485},{7,10,1133},{9,10,582},{9,10,594},{11,10,21},{11,\n10,818},{12,10,535},{141,10,86},{4,10,264},{7,10,1067},{8,10,204},{8,10,385},{\n139,10,953},{132,11,752},{138,10,56},{133,10,470},{6,0,1808},{8,0,83},{8,0,742},\n{8,0,817},{9,0,28},{9,0,29},{9,0,885},{10,0,387},{11,0,633},{11,0,740},{13,0,235\n},{13,0,254},{15,0,143},{143,0,146},{140,0,49},{134,0,1832},{4,11,227},{5,11,159\n},{5,11,409},{7,11,80},{10,11,294},{10,11,479},{12,11,418},{14,11,50},{14,11,249\n},{142,11,295},{7,11,1470},{8,11,66},{8,11,137},{8,11,761},{9,11,638},{11,11,80}\n,{11,11,212},{11,11,368},{11,11,418},{12,11,8},{13,11,15},{16,11,61},{17,11,59},\n{19,11,28},{148,11,84},{139,10,1015},{138,11,468},{135,0,421},{6,0,415},{7,0,\n1049},{137,0,442},{6,11,38},{7,11,1220},{8,11,185},{8,11,256},{9,11,22},{9,11,\n331},{10,11,738},{11,11,205},{11,11,540},{11,11,746},{13,11,399},{13,11,465},{14\n,11,88},{142,11,194},{139,0,289},{133,10,715},{4,0,110},{10,0,415},{10,0,597},{\n142,0,206},{4,11,159},{6,11,115},{7,11,252},{7,11,257},{7,11,1928},{8,11,69},{9,\n11,384},{10,11,91},{10,11,615},{12,11,375},{14,11,235},{18,11,117},{147,11,123},\n{5,11,911},{136,11,278},{7,0,205},{7,0,2000},{8,10,794},{9,10,400},{10,10,298},{\n142,10,228},{135,11,1774},{4,11,151},{7,11,1567},{8,11,351},{137,11,322},{136,10\n,724},{133,11,990},{7,0,1539},{11,0,512},{13,0,205},{19,0,30},{22,0,36},{23,0,19\n},{135,11,1539},{5,11,194},{7,11,1662},{9,11,90},{140,11,180},{6,10,190},{7,10,\n768},{135,10,1170},{134,0,1340},{4,0,283},{135,0,1194},{133,11,425},{133,11,971}\n,{12,0,549},{14,10,67},{147,10,60},{135,10,1023},{134,0,1720},{138,11,587},{5,11\n,72},{6,11,264},{7,11,21},{7,11,46},{7,11,2013},{8,11,215},{8,11,513},{10,11,266\n},{139,11,22},{5,0,319},{135,0,534},{6,10,137},{9,10,75},{9,10,253},{10,10,194},\n{138,10,444},{7,0,1180},{20,0,112},{6,11,239},{7,11,118},{10,11,95},{11,11,603},\n{13,11,443},{14,11,160},{143,11,4},{134,11,431},{5,11,874},{6,11,1677},{11,10,\n643},{12,10,115},{143,11,0},{134,0,967},{6,11,65},{7,11,939},{7,11,1172},{7,11,\n1671},{9,11,540},{10,11,696},{11,11,265},{11,11,732},{11,11,928},{11,11,937},{12\n,11,399},{13,11,438},{149,11,19},{137,11,200},{135,0,1940},{5,10,760},{7,10,542}\n,{8,10,135},{136,10,496},{140,11,44},{7,11,1655},{136,11,305},{7,10,319},{7,10,\n355},{7,10,763},{10,10,389},{145,10,43},{136,0,735},{138,10,786},{137,11,19},{\n132,11,696},{5,0,132},{9,0,486},{9,0,715},{10,0,458},{11,0,373},{11,0,668},{11,0\n,795},{11,0,897},{12,0,272},{12,0,424},{12,0,539},{12,0,558},{14,0,245},{14,0,\n263},{14,0,264},{14,0,393},{142,0,403},{10,0,38},{139,0,784},{132,0,838},{4,11,\n302},{135,11,1766},{133,0,379},{5,0,8},{6,0,89},{6,0,400},{7,0,1569},{7,0,1623},\n{7,0,1850},{8,0,218},{8,0,422},{9,0,570},{10,0,626},{4,11,726},{133,11,630},{4,0\n,1017},{138,0,660},{6,0,387},{7,0,882},{141,0,111},{6,0,224},{7,0,877},{137,0,\n647},{4,10,58},{5,10,286},{6,10,319},{7,10,402},{7,10,1254},{7,10,1903},{8,10,\n356},{140,10,408},{135,0,790},{9,0,510},{10,0,53},{4,10,389},{9,10,181},{10,10,\n29},{10,10,816},{11,10,311},{11,10,561},{12,10,67},{141,10,181},{142,0,458},{6,\n11,118},{7,11,215},{7,11,1521},{140,11,11},{134,0,954},{135,0,394},{134,0,1367},\n{5,11,225},{133,10,373},{132,0,882},{7,0,1409},{135,10,1972},{135,10,1793},{4,11\n,370},{5,11,756},{135,11,1326},{150,11,13},{7,11,354},{10,11,410},{139,11,815},{\n6,11,1662},{7,11,48},{8,11,771},{10,11,116},{13,11,104},{14,11,105},{14,11,184},\n{15,11,168},{19,11,92},{148,11,68},{7,0,124},{136,0,38},{5,0,261},{7,0,78},{7,0,\n199},{8,0,815},{9,0,126},{10,0,342},{140,0,647},{4,0,628},{140,0,724},{7,0,266},\n{8,0,804},{7,10,1651},{145,10,89},{135,0,208},{134,0,1178},{6,0,79},{135,0,1519}\n,{132,10,672},{133,10,737},{136,0,741},{132,11,120},{4,0,710},{6,0,376},{134,0,\n606},{134,0,1347},{134,0,1494},{6,0,850},{6,0,1553},{137,0,821},{5,10,145},{134,\n11,593},{7,0,1311},{140,0,135},{4,0,467},{5,0,405},{134,0,544},{5,11,820},{135,\n11,931},{6,0,100},{7,0,244},{7,0,632},{7,0,1609},{8,0,178},{8,0,638},{141,0,58},\n{4,10,387},{135,10,1288},{6,11,151},{6,11,1675},{7,11,383},{151,11,10},{132,0,\n481},{135,10,550},{134,0,1378},{6,11,1624},{11,11,11},{12,11,422},{13,11,262},{\n142,11,360},{133,0,791},{4,11,43},{5,11,344},{133,11,357},{7,0,1227},{140,0,978}\n,{7,0,686},{8,0,33},{8,0,238},{10,0,616},{11,0,467},{11,0,881},{13,0,217},{13,0,\n253},{142,0,268},{137,0,857},{8,0,467},{8,0,1006},{7,11,148},{8,11,284},{141,11,\n63},{4,10,576},{135,10,1263},{133,11,888},{5,10,919},{134,10,1673},{20,10,37},{\n148,11,37},{132,0,447},{132,11,711},{4,0,128},{5,0,415},{6,0,462},{7,0,294},{7,0\n,578},{10,0,710},{139,0,86},{4,10,82},{5,10,333},{5,10,904},{6,10,207},{7,10,325\n},{7,10,1726},{8,10,101},{10,10,778},{139,10,220},{136,0,587},{137,11,440},{133,\n10,903},{6,0,427},{7,0,1018},{138,0,692},{4,0,195},{135,0,802},{140,10,147},{134\n,0,1546},{134,0,684},{132,10,705},{136,0,345},{11,11,678},{140,11,307},{133,0,\n365},{134,0,1683},{4,11,65},{5,11,479},{5,11,1004},{7,11,1913},{8,11,317},{9,11,\n302},{10,11,612},{141,11,22},{138,0,472},{4,11,261},{135,11,510},{134,10,90},{\n142,0,433},{151,0,28},{4,11,291},{7,11,101},{9,11,515},{12,11,152},{12,11,443},{\n13,11,392},{142,11,357},{140,0,997},{5,0,3},{8,0,578},{9,0,118},{10,0,705},{141,\n0,279},{135,11,1266},{7,10,813},{12,10,497},{141,10,56},{133,0,229},{6,10,125},{\n135,10,1277},{8,0,102},{10,0,578},{10,0,672},{12,0,496},{13,0,408},{14,0,121},{\n17,0,106},{151,10,12},{6,0,866},{134,0,1080},{136,0,1022},{4,11,130},{135,11,843\n},{5,11,42},{5,11,879},{7,11,245},{7,11,324},{7,11,1532},{11,11,463},{11,11,472}\n,{13,11,363},{144,11,52},{150,0,55},{8,0,115},{8,0,350},{9,0,489},{10,0,128},{11\n,0,306},{12,0,373},{14,0,30},{17,0,79},{19,0,80},{4,11,134},{133,11,372},{134,0,\n657},{134,0,933},{135,11,1147},{4,0,230},{133,0,702},{134,0,1728},{4,0,484},{18,\n0,26},{19,0,42},{20,0,43},{21,0,0},{23,0,27},{152,0,14},{7,0,185},{135,0,703},{6\n,0,417},{10,0,618},{7,10,1106},{9,10,770},{11,10,112},{140,10,413},{134,0,803},{\n132,11,644},{134,0,1262},{7,11,540},{12,10,271},{145,10,109},{135,11,123},{132,0\n,633},{134,11,623},{4,11,908},{5,11,359},{5,11,508},{6,11,1723},{7,11,343},{7,11\n,1996},{135,11,2026},{135,0,479},{10,0,262},{7,10,304},{9,10,646},{9,10,862},{11\n,10,696},{12,10,208},{15,10,79},{147,10,108},{4,11,341},{135,11,480},{134,0,830}\n,{5,0,70},{5,0,622},{6,0,334},{7,0,1032},{9,0,171},{11,0,26},{11,0,213},{11,0,\n637},{11,0,707},{12,0,202},{12,0,380},{13,0,226},{13,0,355},{14,0,222},{145,0,42\n},{135,10,981},{143,0,217},{137,11,114},{4,0,23},{4,0,141},{5,0,313},{5,0,1014},\n{6,0,50},{6,0,51},{7,0,142},{7,0,384},{7,0,559},{8,0,640},{9,0,460},{9,0,783},{\n11,0,741},{12,0,183},{141,0,488},{141,0,360},{7,0,1586},{7,11,1995},{8,11,299},{\n11,11,890},{140,11,674},{132,10,434},{7,0,652},{134,10,550},{7,0,766},{5,10,553}\n,{138,10,824},{7,0,737},{8,0,298},{136,10,452},{4,11,238},{5,11,503},{6,11,179},\n{7,11,2003},{8,11,381},{8,11,473},{9,11,149},{10,11,183},{15,11,45},{143,11,86},\n{133,10,292},{5,0,222},{9,0,655},{138,0,534},{138,10,135},{4,11,121},{5,11,156},\n{5,11,349},{9,11,136},{10,11,605},{14,11,342},{147,11,107},{137,0,906},{6,0,1013\n},{134,0,1250},{6,0,1956},{6,0,2009},{8,0,991},{144,0,120},{135,11,1192},{138,0,\n503},{5,0,154},{7,0,1491},{10,0,379},{138,0,485},{6,0,1867},{6,0,1914},{6,0,1925\n},{9,0,917},{9,0,925},{9,0,932},{9,0,951},{9,0,1007},{9,0,1013},{12,0,806},{12,0\n,810},{12,0,814},{12,0,816},{12,0,824},{12,0,832},{12,0,837},{12,0,863},{12,0,\n868},{12,0,870},{12,0,889},{12,0,892},{12,0,900},{12,0,902},{12,0,908},{12,0,933\n},{12,0,942},{12,0,949},{12,0,954},{15,0,175},{15,0,203},{15,0,213},{15,0,218},{\n15,0,225},{15,0,231},{15,0,239},{15,0,248},{15,0,252},{18,0,190},{18,0,204},{18,\n0,215},{18,0,216},{18,0,222},{18,0,225},{18,0,230},{18,0,239},{18,0,241},{21,0,\n42},{21,0,43},{21,0,44},{21,0,45},{21,0,46},{21,0,53},{24,0,27},{152,0,31},{133,\n0,716},{135,0,844},{4,0,91},{5,0,388},{5,0,845},{6,0,206},{6,0,252},{6,0,365},{7\n,0,136},{7,0,531},{136,0,621},{7,10,393},{10,10,603},{139,10,206},{6,11,80},{6,\n11,1694},{7,11,173},{7,11,1974},{9,11,547},{10,11,730},{14,11,18},{150,11,39},{\n137,0,748},{4,11,923},{134,11,1711},{4,10,912},{137,10,232},{7,10,98},{7,10,1973\n},{136,10,716},{14,0,103},{133,10,733},{132,11,595},{12,0,158},{18,0,8},{19,0,62\n},{20,0,6},{22,0,4},{23,0,2},{23,0,9},{5,11,240},{6,11,459},{7,11,12},{7,11,114}\n,{7,11,502},{7,11,1751},{7,11,1753},{7,11,1805},{8,11,658},{9,11,1},{11,11,959},\n{13,11,446},{142,11,211},{135,0,576},{5,0,771},{5,0,863},{5,0,898},{6,0,648},{6,\n0,1632},{6,0,1644},{134,0,1780},{133,0,331},{7,11,633},{7,11,905},{7,11,909},{7,\n11,1538},{9,11,767},{140,11,636},{140,0,632},{5,0,107},{7,0,201},{136,0,518},{6,\n0,446},{7,0,1817},{134,11,490},{9,0,851},{141,0,510},{7,11,250},{8,11,506},{136,\n11,507},{4,0,504},{137,10,72},{132,11,158},{4,11,140},{7,11,362},{8,11,209},{9,\n11,10},{9,11,160},{9,11,503},{10,11,689},{11,11,350},{11,11,553},{11,11,725},{12\n,11,252},{12,11,583},{13,11,192},{13,11,352},{14,11,269},{14,11,356},{148,11,50}\n,{6,11,597},{135,11,1318},{135,10,1454},{5,0,883},{5,0,975},{8,0,392},{148,0,7},\n{6,11,228},{7,11,1341},{9,11,408},{138,11,343},{11,11,348},{11,10,600},{12,11,99\n},{13,10,245},{18,11,1},{18,11,11},{147,11,4},{134,11,296},{5,0,922},{134,0,1707\n},{132,11,557},{4,11,548},{7,10,164},{7,10,1571},{9,10,107},{140,10,225},{7,11,\n197},{8,11,142},{8,11,325},{9,11,150},{9,11,596},{10,11,350},{10,11,353},{11,11,\n74},{11,11,315},{14,11,423},{143,11,141},{5,0,993},{7,0,515},{137,0,91},{4,0,131\n},{8,0,200},{5,10,484},{5,10,510},{6,10,434},{7,10,1000},{7,10,1098},{136,10,2},\n{152,0,10},{4,11,62},{5,11,83},{6,11,399},{6,11,579},{7,11,692},{7,11,846},{7,11\n,1015},{7,11,1799},{8,11,403},{9,11,394},{10,11,133},{12,11,4},{12,11,297},{12,\n11,452},{16,11,81},{18,11,19},{18,11,25},{21,11,14},{22,11,12},{151,11,18},{140,\n11,459},{132,11,177},{7,0,1433},{9,0,365},{137,11,365},{132,10,460},{5,0,103},{6\n,0,2004},{7,0,921},{8,0,580},{8,0,593},{8,0,630},{10,0,28},{5,11,411},{135,11,\n653},{4,10,932},{133,10,891},{4,0,911},{5,0,867},{5,0,1013},{7,0,2034},{8,0,798}\n,{136,0,813},{7,11,439},{10,11,727},{11,11,260},{139,11,684},{136,10,625},{5,11,\n208},{7,11,753},{135,11,1528},{5,0,461},{7,0,1925},{12,0,39},{13,0,265},{13,0,\n439},{134,10,76},{6,0,853},{8,10,92},{137,10,221},{5,0,135},{6,0,519},{7,0,1722}\n,{10,0,271},{11,0,261},{145,0,54},{139,11,814},{14,0,338},{148,0,81},{4,0,300},{\n133,0,436},{5,0,419},{5,0,687},{7,0,864},{9,0,470},{135,11,864},{9,0,836},{133,\n11,242},{134,0,1937},{4,10,763},{133,11,953},{132,10,622},{132,0,393},{133,10,\n253},{8,0,357},{10,0,745},{14,0,426},{17,0,94},{19,0,57},{135,10,546},{5,11,615}\n,{146,11,37},{9,10,73},{10,10,110},{14,10,185},{145,10,119},{11,0,703},{7,10,624\n},{7,10,916},{10,10,256},{139,10,87},{133,11,290},{5,10,212},{12,10,35},{141,10,\n382},{132,11,380},{5,11,52},{7,11,277},{9,11,368},{139,11,791},{133,0,387},{10,\n11,138},{139,11,476},{4,0,6},{5,0,708},{136,0,75},{7,0,1351},{9,0,581},{10,0,639\n},{11,0,453},{140,0,584},{132,0,303},{138,0,772},{135,10,1175},{4,0,749},{5,10,\n816},{6,11,256},{7,11,307},{7,11,999},{7,11,1481},{7,11,1732},{7,11,1738},{8,11,\n265},{9,11,414},{11,11,316},{12,11,52},{13,11,420},{147,11,100},{135,11,1296},{6\n,0,1065},{5,10,869},{5,10,968},{6,10,1626},{8,10,734},{136,10,784},{4,10,542},{6\n,10,1716},{6,10,1727},{7,10,1082},{7,10,1545},{8,10,56},{8,10,118},{8,10,412},{8\n,10,564},{9,10,888},{9,10,908},{10,10,50},{10,10,423},{11,10,685},{11,10,697},{\n11,10,933},{12,10,299},{13,10,126},{13,10,136},{13,10,170},{141,10,190},{134,0,\n226},{4,0,106},{7,0,310},{11,0,717},{133,11,723},{5,0,890},{5,0,988},{4,10,232},\n{9,10,202},{10,10,474},{140,10,433},{6,0,626},{142,0,431},{10,0,706},{150,0,44},\n{13,0,51},{6,10,108},{7,10,1003},{7,10,1181},{8,10,111},{136,10,343},{132,0,698}\n,{5,11,109},{6,11,1784},{7,11,1895},{12,11,296},{140,11,302},{134,0,828},{134,10\n,1712},{138,0,17},{7,0,1929},{4,10,133},{5,11,216},{7,10,711},{7,10,1298},{7,10,\n1585},{7,11,1879},{9,11,141},{9,11,270},{9,11,679},{10,11,159},{10,11,553},{11,\n11,197},{11,11,438},{12,11,538},{12,11,559},{13,11,193},{13,11,423},{14,11,144},\n{14,11,166},{14,11,167},{15,11,67},{147,11,84},{141,11,127},{7,11,1872},{137,11,\n81},{6,10,99},{7,10,1808},{145,10,57},{134,11,391},{5,0,689},{6,0,84},{7,0,1250}\n,{6,10,574},{7,10,428},{10,10,669},{11,10,485},{11,10,840},{12,10,300},{142,10,\n250},{7,11,322},{136,11,249},{7,11,432},{135,11,1649},{135,10,1871},{137,10,252}\n,{6,11,155},{140,11,234},{7,0,871},{19,0,27},{147,11,27},{140,0,498},{5,0,986},{\n6,0,130},{138,0,823},{6,0,1793},{7,0,1582},{8,0,458},{10,0,101},{10,0,318},{10,0\n,945},{12,0,734},{16,0,104},{18,0,177},{6,10,323},{135,10,1564},{5,11,632},{138,\n11,526},{10,0,435},{7,10,461},{136,10,775},{6,11,144},{7,11,948},{7,11,1042},{7,\n11,1857},{8,11,235},{8,11,461},{9,11,453},{9,11,530},{10,11,354},{17,11,77},{19,\n11,99},{148,11,79},{138,0,966},{7,0,1644},{137,0,129},{135,0,997},{136,0,502},{5\n,11,196},{6,11,486},{7,11,212},{8,11,309},{136,11,346},{7,10,727},{146,10,73},{\n132,0,823},{132,11,686},{135,0,1927},{4,0,762},{7,0,1756},{137,0,98},{136,10,577\n},{24,0,8},{4,11,30},{5,11,43},{152,11,8},{7,0,1046},{139,0,160},{7,0,492},{4,10\n,413},{5,10,677},{7,11,492},{8,10,432},{140,10,280},{6,0,45},{7,0,433},{8,0,129}\n,{9,0,21},{10,0,392},{11,0,79},{12,0,499},{13,0,199},{141,0,451},{7,0,558},{136,\n0,353},{4,11,220},{7,11,1535},{9,11,93},{139,11,474},{7,10,646},{7,10,1730},{11,\n10,446},{141,10,178},{133,0,785},{134,0,1145},{8,0,81},{9,0,189},{9,0,201},{11,0\n,478},{11,0,712},{141,0,338},{5,0,353},{151,0,26},{11,0,762},{132,10,395},{134,0\n,2024},{4,0,611},{133,0,606},{9,10,174},{10,10,164},{11,10,440},{11,10,841},{143\n,10,98},{134,10,426},{10,10,608},{139,10,1002},{138,10,250},{6,0,25},{7,0,855},{\n7,0,1258},{144,0,32},{7,11,1725},{138,11,393},{5,11,263},{134,11,414},{6,0,2011}\n,{133,10,476},{4,0,4},{7,0,1118},{7,0,1320},{7,0,1706},{8,0,277},{9,0,622},{10,0\n,9},{11,0,724},{12,0,350},{12,0,397},{13,0,28},{13,0,159},{15,0,89},{18,0,5},{19\n,0,9},{20,0,34},{22,0,47},{6,11,178},{6,11,1750},{8,11,251},{9,11,690},{10,11,\n155},{10,11,196},{10,11,373},{11,11,698},{13,11,155},{148,11,93},{5,11,97},{137,\n11,393},{7,0,764},{11,0,461},{12,0,172},{5,10,76},{6,10,458},{6,10,497},{7,10,\n868},{9,10,658},{10,10,594},{11,10,566},{12,10,338},{141,10,200},{134,0,1449},{\n138,11,40},{134,11,1639},{134,0,1445},{6,0,1168},{4,10,526},{7,10,1029},{135,10,\n1054},{4,11,191},{7,11,934},{8,11,647},{145,11,97},{132,10,636},{6,0,233},{7,10,\n660},{7,10,1124},{17,10,31},{19,10,22},{151,10,14},{6,10,1699},{136,11,110},{12,\n11,246},{15,11,162},{19,11,64},{20,11,8},{20,11,95},{22,11,24},{152,11,17},{5,11\n,165},{9,11,346},{138,11,655},{5,11,319},{135,11,534},{134,0,255},{9,0,216},{8,\n11,128},{139,11,179},{9,0,183},{139,0,286},{11,0,956},{151,0,3},{4,0,536},{7,0,\n1141},{10,0,723},{139,0,371},{4,10,279},{7,10,301},{137,10,362},{7,0,285},{5,11,\n57},{6,11,101},{6,11,1663},{7,11,132},{7,11,1048},{7,11,1154},{7,11,1415},{7,11,\n1507},{12,11,493},{15,11,105},{151,11,15},{5,11,459},{7,11,1073},{7,10,1743},{8,\n11,241},{136,11,334},{4,10,178},{133,10,399},{135,0,560},{132,0,690},{135,0,1246\n},{18,0,157},{147,0,63},{10,0,599},{11,0,33},{12,0,571},{149,0,1},{6,11,324},{6,\n11,520},{7,11,338},{7,11,1616},{7,11,1729},{8,11,228},{9,11,69},{139,11,750},{7,\n0,1862},{12,0,491},{12,0,520},{13,0,383},{142,0,244},{135,11,734},{134,10,1692},\n{10,0,448},{11,0,630},{17,0,117},{6,10,202},{7,11,705},{12,10,360},{17,10,118},{\n18,10,27},{148,10,67},{4,11,73},{6,11,612},{7,11,927},{7,11,1822},{8,11,217},{9,\n11,472},{9,11,765},{9,11,766},{10,11,408},{11,11,51},{11,11,793},{12,11,266},{15\n,11,158},{20,11,89},{150,11,32},{4,0,190},{133,0,554},{133,0,1001},{5,11,389},{8\n,11,636},{137,11,229},{5,0,446},{7,10,872},{10,10,516},{139,10,167},{137,10,313}\n,{132,10,224},{134,0,1313},{5,10,546},{7,10,35},{8,10,11},{8,10,12},{9,10,315},{\n9,10,533},{10,10,802},{11,10,166},{12,10,525},{142,10,243},{6,0,636},{137,0,837}\n,{5,10,241},{8,10,242},{9,10,451},{10,10,667},{11,10,598},{140,10,429},{22,10,46\n},{150,11,46},{136,11,472},{11,0,278},{142,0,73},{141,11,185},{132,0,868},{134,0\n,972},{4,10,366},{137,10,516},{138,0,1010},{5,11,189},{6,10,1736},{7,11,442},{7,\n11,443},{8,11,281},{12,11,174},{13,11,83},{141,11,261},{139,11,384},{6,11,2},{7,\n11,191},{7,11,446},{7,11,758},{7,11,1262},{7,11,1737},{8,11,22},{8,11,270},{8,11\n,612},{9,11,4},{9,11,167},{9,11,312},{9,11,436},{10,11,156},{10,11,216},{10,11,\n311},{10,11,623},{11,11,72},{11,11,330},{11,11,455},{12,11,101},{12,11,321},{12,\n11,504},{12,11,530},{12,11,543},{13,11,17},{13,11,156},{13,11,334},{14,11,48},{\n15,11,70},{17,11,60},{148,11,64},{6,10,331},{136,10,623},{135,0,1231},{132,0,304\n},{6,11,60},{7,11,670},{7,11,1327},{8,11,411},{8,11,435},{9,11,653},{9,11,740},{\n10,11,385},{11,11,222},{11,11,324},{11,11,829},{140,11,611},{7,0,506},{6,11,166}\n,{7,11,374},{135,11,1174},{14,11,43},{146,11,21},{135,11,1694},{135,10,1888},{5,\n11,206},{134,11,398},{135,11,50},{150,0,26},{6,0,53},{6,0,199},{7,0,1408},{8,0,\n32},{8,0,93},{10,0,397},{10,0,629},{11,0,593},{11,0,763},{13,0,326},{145,0,35},{\n134,0,105},{132,10,394},{4,0,843},{138,0,794},{11,0,704},{141,0,396},{5,0,114},{\n5,0,255},{141,0,285},{6,0,619},{7,0,898},{7,0,1092},{8,0,485},{18,0,28},{19,0,\n116},{135,10,1931},{9,0,145},{7,10,574},{135,10,1719},{7,0,2035},{8,0,19},{9,0,\n89},{138,0,831},{132,10,658},{6,11,517},{7,11,1159},{10,11,621},{139,11,192},{7,\n0,1933},{7,11,1933},{9,10,781},{10,10,144},{11,10,385},{13,10,161},{13,10,228},{\n13,10,268},{148,10,107},{136,10,374},{10,11,223},{139,11,645},{135,0,1728},{7,11\n,64},{7,11,289},{136,11,245},{4,10,344},{6,10,498},{139,10,323},{136,0,746},{135\n,10,1063},{137,10,155},{4,0,987},{6,0,1964},{6,0,1974},{6,0,1990},{136,0,995},{\n133,11,609},{133,10,906},{134,0,1550},{134,0,874},{5,11,129},{6,11,61},{135,11,\n947},{4,0,1018},{6,0,1938},{6,0,2021},{134,0,2039},{132,0,814},{11,0,126},{139,0\n,287},{134,0,1264},{5,0,955},{136,0,814},{141,11,506},{132,11,314},{6,0,981},{\n139,11,1000},{5,0,56},{8,0,892},{8,0,915},{140,0,776},{148,0,100},{10,0,4},{10,0\n,13},{11,0,638},{148,0,57},{148,11,74},{5,0,738},{132,10,616},{133,11,637},{136,\n10,692},{133,0,758},{132,10,305},{137,11,590},{5,11,280},{135,11,1226},{134,11,\n494},{135,0,1112},{133,11,281},{13,0,44},{14,0,214},{5,10,214},{7,10,603},{8,10,\n611},{9,10,686},{10,10,88},{11,10,459},{11,10,496},{12,10,463},{140,10,590},{139\n,0,328},{135,11,1064},{137,0,133},{7,0,168},{13,0,196},{141,0,237},{134,10,1703}\n,{134,0,1152},{135,0,1245},{5,0,110},{6,0,169},{6,0,1702},{7,0,400},{8,0,538},{9\n,0,184},{9,0,524},{140,0,218},{6,0,1816},{10,0,871},{12,0,769},{140,0,785},{132,\n11,630},{7,11,33},{7,11,120},{8,11,489},{9,11,319},{10,11,820},{11,11,1004},{12,\n11,379},{13,11,117},{13,11,412},{14,11,25},{15,11,52},{15,11,161},{16,11,47},{\n149,11,2},{6,0,133},{8,0,413},{9,0,353},{139,0,993},{145,10,19},{4,11,937},{133,\n11,801},{134,0,978},{6,0,93},{6,0,1508},{7,0,1422},{7,0,1851},{8,0,673},{9,0,529\n},{140,0,43},{6,0,317},{10,0,512},{4,10,737},{11,10,294},{12,10,60},{12,10,437},\n{13,10,64},{13,10,380},{142,10,430},{9,0,371},{7,11,1591},{144,11,43},{6,10,1758\n},{8,10,520},{9,10,345},{9,10,403},{142,10,350},{5,0,526},{10,10,242},{138,10,\n579},{9,0,25},{10,0,467},{138,0,559},{5,10,139},{7,10,1168},{138,10,539},{4,0,\n335},{135,0,942},{140,0,754},{132,11,365},{11,0,182},{142,0,195},{142,11,29},{5,\n11,7},{139,11,774},{4,11,746},{135,11,1090},{8,0,39},{10,0,773},{11,0,84},{12,0,\n205},{142,0,1},{5,0,601},{5,0,870},{5,11,360},{136,11,237},{132,0,181},{136,0,\n370},{134,0,1652},{8,0,358},{4,10,107},{7,10,613},{8,10,439},{8,10,504},{9,10,\n501},{10,10,383},{139,10,477},{132,10,229},{137,11,785},{4,0,97},{5,0,147},{6,0,\n286},{7,0,1362},{141,0,176},{6,0,537},{7,0,788},{7,0,1816},{132,10,903},{140,10,\n71},{6,0,743},{134,0,1223},{6,0,375},{7,0,169},{7,0,254},{8,0,780},{135,11,1493}\n,{7,0,1714},{4,10,47},{6,10,373},{7,10,452},{7,10,543},{7,10,1856},{9,10,6},{11,\n10,257},{139,10,391},{6,0,896},{136,0,1003},{135,0,1447},{137,11,341},{5,10,980}\n,{134,10,1754},{145,11,22},{4,11,277},{5,11,608},{6,11,493},{7,11,457},{140,11,\n384},{7,10,536},{7,10,1331},{136,10,143},{140,0,744},{7,11,27},{135,11,316},{18,\n0,126},{5,10,19},{134,10,533},{4,0,788},{11,0,41},{5,11,552},{5,11,586},{5,11,\n676},{6,11,448},{8,11,244},{11,11,1},{11,11,41},{13,11,3},{16,11,54},{17,11,4},{\n146,11,13},{4,0,985},{6,0,1801},{4,11,401},{137,11,264},{5,10,395},{5,10,951},{\n134,10,1776},{5,0,629},{135,0,1549},{11,10,663},{12,10,210},{13,10,166},{13,10,\n310},{14,10,373},{147,10,43},{9,11,543},{10,11,524},{11,11,30},{12,11,524},{14,\n11,315},{16,11,18},{20,11,26},{148,11,65},{4,11,205},{5,11,623},{7,11,104},{136,\n11,519},{5,0,293},{134,0,601},{7,11,579},{9,11,41},{9,11,244},{9,11,669},{10,11,\n5},{11,11,861},{11,11,951},{139,11,980},{132,11,717},{132,10,695},{7,10,497},{9,\n10,387},{147,10,81},{132,0,420},{142,0,37},{6,0,1134},{6,0,1900},{12,0,830},{12,\n0,878},{12,0,894},{15,0,221},{143,0,245},{132,11,489},{7,0,1570},{140,0,542},{8,\n0,933},{136,0,957},{6,0,1371},{7,0,31},{8,0,373},{5,10,284},{6,10,49},{6,10,350}\n,{7,10,377},{7,10,1693},{8,10,678},{9,10,161},{9,10,585},{9,10,671},{9,10,839},{\n11,10,912},{141,10,427},{135,11,892},{4,0,325},{138,0,125},{139,11,47},{132,10,\n597},{138,0,323},{6,0,1547},{7,11,1605},{9,11,473},{11,11,962},{146,11,139},{139\n,10,908},{7,11,819},{9,11,26},{9,11,392},{10,11,152},{10,11,226},{11,11,19},{12,\n11,276},{12,11,426},{12,11,589},{13,11,460},{15,11,97},{19,11,48},{148,11,104},{\n135,11,51},{4,0,718},{135,0,1216},{6,0,1896},{6,0,1905},{6,0,1912},{9,0,947},{9,\n0,974},{12,0,809},{12,0,850},{12,0,858},{12,0,874},{12,0,887},{12,0,904},{12,0,\n929},{12,0,948},{12,0,952},{15,0,198},{15,0,206},{15,0,220},{15,0,227},{15,0,247\n},{18,0,188},{21,0,48},{21,0,50},{24,0,25},{24,0,29},{7,11,761},{7,11,1051},{137\n,11,545},{5,0,124},{5,0,144},{6,0,548},{7,0,15},{7,0,153},{137,0,629},{135,11,\n606},{135,10,2014},{7,10,2007},{9,11,46},{9,10,101},{9,10,450},{10,10,66},{10,10\n,842},{11,10,536},{140,10,587},{6,0,75},{7,0,1531},{8,0,416},{9,0,240},{9,0,275}\n,{10,0,100},{11,0,658},{11,0,979},{12,0,86},{14,0,207},{15,0,20},{143,0,25},{5,0\n,141},{5,0,915},{6,0,1783},{7,0,211},{7,0,698},{7,0,1353},{9,0,83},{9,0,281},{10\n,0,376},{10,0,431},{11,0,543},{12,0,664},{13,0,280},{13,0,428},{14,0,61},{14,0,\n128},{17,0,52},{145,0,81},{132,11,674},{135,0,533},{149,0,6},{132,11,770},{133,0\n,538},{5,11,79},{7,11,1027},{7,11,1477},{139,11,52},{139,10,62},{4,0,338},{133,0\n,400},{5,11,789},{134,11,195},{4,11,251},{4,11,688},{7,11,513},{7,11,1284},{9,11\n,87},{138,11,365},{134,10,1766},{6,0,0},{7,0,84},{11,0,895},{145,0,11},{139,0,\n892},{4,0,221},{5,0,659},{7,0,697},{7,0,1211},{138,0,284},{133,0,989},{133,11,\n889},{4,11,160},{5,11,330},{7,11,1434},{136,11,174},{6,10,1665},{7,10,256},{7,10\n,1388},{10,10,499},{139,10,670},{7,0,848},{4,10,22},{5,10,10},{136,10,97},{138,0\n,507},{133,10,481},{4,0,188},{135,0,805},{5,0,884},{6,0,732},{139,0,991},{135,11\n,968},{11,11,636},{15,11,145},{17,11,34},{19,11,50},{151,11,20},{7,0,959},{16,0,\n60},{6,10,134},{7,10,437},{9,10,37},{14,10,285},{142,10,371},{7,10,486},{8,10,\n155},{11,10,93},{140,10,164},{134,0,1653},{7,0,337},{133,10,591},{6,0,1989},{8,0\n,922},{8,0,978},{133,11,374},{132,0,638},{138,0,500},{133,11,731},{5,10,380},{5,\n10,650},{136,10,310},{138,11,381},{4,10,364},{7,10,1156},{7,10,1187},{137,10,409\n},{137,11,224},{140,0,166},{134,10,482},{4,11,626},{5,11,642},{6,11,425},{10,11,\n202},{139,11,141},{4,10,781},{6,10,487},{7,10,926},{8,10,263},{139,10,500},{135,\n0,418},{4,10,94},{135,10,1265},{136,0,760},{132,10,417},{136,11,835},{5,10,348},\n{134,10,522},{6,0,1277},{134,0,1538},{139,11,541},{135,11,1597},{5,11,384},{8,11\n,455},{140,11,48},{136,0,770},{5,11,264},{134,11,184},{4,0,89},{5,0,489},{6,0,\n315},{7,0,553},{7,0,1745},{138,0,243},{4,10,408},{4,10,741},{135,10,500},{134,0,\n1396},{133,0,560},{6,0,1658},{9,0,3},{10,0,154},{11,0,641},{13,0,85},{13,0,201},\n{141,0,346},{135,11,1595},{5,11,633},{6,11,28},{7,11,219},{135,11,1323},{9,11,\n769},{140,11,185},{135,11,785},{7,11,359},{8,11,243},{140,11,175},{138,0,586},{7\n,0,1271},{134,10,73},{132,11,105},{4,0,166},{5,0,505},{134,0,1670},{133,10,576},\n{4,11,324},{138,11,104},{142,10,231},{6,0,637},{7,10,1264},{7,10,1678},{11,10,\n945},{12,10,341},{12,10,471},{12,10,569},{23,11,21},{151,11,23},{8,11,559},{141,\n11,109},{134,0,1947},{7,0,445},{8,0,307},{8,0,704},{10,0,41},{10,0,439},{11,0,\n237},{11,0,622},{140,0,201},{135,11,963},{135,0,1977},{4,0,189},{5,0,713},{136,0\n,57},{138,0,371},{135,10,538},{132,0,552},{6,0,883},{133,10,413},{6,0,923},{132,\n11,758},{138,11,215},{136,10,495},{7,10,54},{8,10,312},{10,10,191},{10,10,614},{\n140,10,567},{7,11,351},{139,11,128},{7,0,875},{6,10,468},{7,10,1478},{8,10,530},\n{142,10,290},{135,0,1788},{17,0,49},{133,11,918},{12,11,398},{20,11,39},{21,11,\n11},{150,11,41},{10,0,661},{6,10,484},{135,10,822},{135,0,1945},{134,0,794},{137\n,10,900},{135,10,1335},{6,10,1724},{135,10,2022},{132,11,340},{134,0,1135},{4,0,\n784},{133,0,745},{5,0,84},{134,0,163},{133,0,410},{4,0,976},{5,11,985},{7,11,509\n},{7,11,529},{145,11,96},{132,10,474},{134,0,703},{135,11,1919},{5,0,322},{8,0,\n186},{9,0,262},{10,0,187},{142,0,208},{135,10,1504},{133,0,227},{9,0,560},{13,0,\n208},{133,10,305},{132,11,247},{7,0,1395},{8,0,486},{9,0,236},{9,0,878},{10,0,\n218},{11,0,95},{19,0,17},{147,0,31},{7,0,2043},{8,0,672},{141,0,448},{4,11,184},\n{5,11,390},{6,11,337},{7,11,23},{7,11,494},{7,11,618},{7,11,1456},{8,11,27},{8,\n11,599},{10,11,153},{139,11,710},{135,0,466},{135,10,1236},{6,0,167},{7,0,186},{\n7,0,656},{10,0,643},{4,10,480},{6,10,302},{6,10,1642},{7,10,837},{7,10,1547},{7,\n10,1657},{8,10,429},{9,10,228},{13,10,289},{13,10,343},{147,10,101},{134,0,1428}\n,{134,0,1440},{5,0,412},{7,10,278},{10,10,739},{11,10,708},{141,10,348},{134,0,\n1118},{136,0,562},{148,11,46},{9,0,316},{139,0,256},{134,0,1771},{135,0,1190},{\n137,0,132},{10,11,227},{11,11,497},{11,11,709},{140,11,415},{143,0,66},{6,11,360\n},{7,11,1664},{136,11,478},{144,10,28},{4,0,317},{135,0,1279},{5,0,63},{133,0,\n509},{136,11,699},{145,10,36},{134,0,1475},{11,11,343},{142,11,127},{132,11,739}\n,{132,0,288},{135,11,1757},{8,0,89},{8,0,620},{9,0,608},{11,0,628},{12,0,322},{\n143,0,124},{134,0,1225},{7,0,1189},{4,11,67},{5,11,422},{6,10,363},{7,11,1037},{\n7,11,1289},{7,11,1555},{7,10,1955},{8,10,725},{9,11,741},{145,11,108},{134,0,\n1468},{6,0,689},{134,0,1451},{138,0,120},{151,0,1},{137,10,805},{142,0,329},{5,\n10,813},{135,10,2046},{135,0,226},{138,11,96},{7,0,1855},{5,10,712},{11,10,17},{\n13,10,321},{144,10,67},{9,0,461},{6,10,320},{7,10,781},{7,10,1921},{9,10,55},{10\n,10,186},{10,10,273},{10,10,664},{10,10,801},{11,10,996},{11,10,997},{13,10,157}\n,{142,10,170},{8,11,203},{8,10,271},{11,11,823},{11,11,846},{12,11,482},{13,11,\n133},{13,11,277},{13,11,302},{13,11,464},{14,11,205},{142,11,221},{135,0,1346},{\n4,11,449},{133,11,718},{134,0,85},{14,0,299},{7,10,103},{7,10,863},{11,10,184},{\n145,10,62},{4,11,355},{6,11,311},{9,11,256},{138,11,404},{137,10,659},{138,11,\n758},{133,11,827},{5,11,64},{140,11,581},{134,0,1171},{4,11,442},{7,11,1047},{7,\n11,1352},{135,11,1643},{132,0,980},{5,11,977},{6,11,288},{7,11,528},{135,11,1065\n},{5,0,279},{6,0,235},{7,0,468},{8,0,446},{9,0,637},{10,0,717},{11,0,738},{140,0\n,514},{132,0,293},{11,10,337},{142,10,303},{136,11,285},{5,0,17},{6,0,371},{9,0,\n528},{12,0,364},{132,11,254},{5,10,77},{7,10,1455},{10,10,843},{147,10,73},{150,\n0,5},{132,10,458},{6,11,12},{7,11,1219},{145,11,73},{135,10,1420},{6,10,109},{\n138,10,382},{135,11,125},{6,10,330},{7,10,1084},{139,10,142},{6,11,369},{6,11,\n502},{7,11,1036},{8,11,348},{9,11,452},{10,11,26},{11,11,224},{11,11,387},{11,11\n,772},{12,11,95},{12,11,629},{13,11,195},{13,11,207},{13,11,241},{14,11,260},{14\n,11,270},{143,11,140},{132,11,269},{5,11,480},{7,11,532},{7,11,1197},{7,11,1358}\n,{8,11,291},{11,11,349},{142,11,396},{150,0,48},{10,0,601},{13,0,353},{141,0,376\n},{5,0,779},{5,0,807},{6,0,1655},{134,0,1676},{142,11,223},{4,0,196},{5,0,558},{\n133,0,949},{148,11,15},{135,11,1764},{134,0,1322},{132,0,752},{139,0,737},{135,\n11,657},{136,11,533},{135,0,412},{4,0,227},{5,0,159},{5,0,409},{7,0,80},{8,0,556\n},{10,0,479},{12,0,418},{14,0,50},{14,0,123},{14,0,192},{14,0,249},{14,0,295},{\n143,0,27},{7,0,1470},{8,0,66},{8,0,137},{8,0,761},{9,0,638},{11,0,80},{11,0,212}\n,{11,0,368},{11,0,418},{12,0,8},{13,0,15},{16,0,61},{17,0,59},{19,0,28},{148,0,\n84},{135,10,1985},{4,11,211},{4,11,332},{5,11,335},{6,11,238},{7,11,269},{7,11,\n811},{7,11,1797},{8,10,122},{8,11,836},{9,11,507},{141,11,242},{6,0,683},{134,0,\n1252},{4,0,873},{132,10,234},{134,0,835},{6,0,38},{7,0,1220},{8,0,185},{8,0,256}\n,{9,0,22},{9,0,331},{10,0,738},{11,0,205},{11,0,540},{11,0,746},{13,0,465},{14,0\n,88},{142,0,194},{138,0,986},{5,11,1009},{12,11,582},{146,11,131},{4,0,159},{6,0\n,115},{7,0,252},{7,0,257},{7,0,1928},{8,0,69},{9,0,384},{10,0,91},{10,0,615},{12\n,0,375},{14,0,235},{18,0,117},{147,0,123},{133,0,911},{136,0,278},{5,10,430},{5,\n10,932},{6,10,131},{7,10,417},{9,10,522},{11,10,314},{141,10,390},{14,10,149},{\n14,10,399},{143,10,57},{4,0,151},{7,0,1567},{136,0,749},{5,11,228},{6,11,203},{7\n,11,156},{8,11,347},{137,11,265},{132,10,507},{10,0,989},{140,0,956},{133,0,990}\n,{5,0,194},{6,0,927},{7,0,1662},{9,0,90},{140,0,564},{4,10,343},{133,10,511},{\n133,0,425},{7,10,455},{138,10,591},{4,0,774},{7,11,476},{7,11,1592},{138,11,87},\n{5,0,971},{135,10,1381},{5,11,318},{147,11,121},{5,11,291},{7,11,765},{9,11,389}\n,{140,11,548},{134,10,575},{4,0,827},{12,0,646},{12,0,705},{12,0,712},{140,0,714\n},{139,0,752},{137,0,662},{5,0,72},{6,0,264},{7,0,21},{7,0,46},{7,0,2013},{8,0,\n215},{8,0,513},{10,0,266},{139,0,22},{139,11,522},{6,0,239},{7,0,118},{10,0,95},\n{11,0,603},{13,0,443},{14,0,160},{143,0,4},{6,0,431},{134,0,669},{7,10,1127},{7,\n10,1572},{10,10,297},{10,10,422},{11,10,764},{11,10,810},{12,10,264},{13,10,102}\n,{13,10,300},{13,10,484},{14,10,147},{14,10,229},{17,10,71},{18,10,118},{147,10,\n120},{5,0,874},{6,0,1677},{15,0,0},{10,11,525},{139,11,82},{6,0,65},{7,0,939},{7\n,0,1172},{7,0,1671},{9,0,540},{10,0,696},{11,0,265},{11,0,732},{11,0,928},{11,0,\n937},{141,0,438},{134,0,1350},{136,11,547},{132,11,422},{5,11,355},{145,11,0},{\n137,11,905},{5,0,682},{135,0,1887},{132,0,809},{4,0,696},{133,11,865},{6,0,1074}\n,{6,0,1472},{14,10,35},{142,10,191},{5,11,914},{134,11,1625},{133,11,234},{135,\n11,1383},{137,11,780},{132,10,125},{4,0,726},{133,0,630},{8,0,802},{136,0,838},{\n132,10,721},{6,0,1337},{7,0,776},{19,0,56},{136,10,145},{132,0,970},{7,10,792},{\n8,10,147},{10,10,821},{139,10,1021},{139,10,970},{8,0,940},{137,0,797},{135,11,\n1312},{9,0,248},{10,0,400},{7,11,816},{7,11,1241},{7,10,1999},{9,11,283},{9,11,\n520},{10,11,213},{10,11,307},{10,11,463},{10,11,671},{10,11,746},{11,11,401},{11\n,11,794},{12,11,517},{18,11,107},{147,11,115},{6,0,1951},{134,0,2040},{135,11,\n339},{13,0,41},{15,0,93},{5,10,168},{5,10,930},{8,10,74},{9,10,623},{12,10,500},\n{140,10,579},{6,0,118},{7,0,215},{7,0,1521},{140,0,11},{6,10,220},{7,10,1101},{\n141,10,105},{6,11,421},{7,11,61},{7,11,1540},{10,11,11},{138,11,501},{7,0,615},{\n138,0,251},{140,11,631},{135,0,1044},{6,10,19},{7,10,1413},{139,10,428},{133,0,\n225},{7,10,96},{8,10,401},{8,10,703},{137,10,896},{145,10,116},{6,11,102},{7,11,\n72},{15,11,142},{147,11,67},{7,10,1961},{7,10,1965},{8,10,702},{136,10,750},{7,\n10,2030},{8,10,150},{8,10,737},{12,10,366},{151,11,30},{4,0,370},{5,0,756},{7,0,\n1326},{135,11,823},{8,10,800},{9,10,148},{9,10,872},{9,10,890},{11,10,309},{11,\n10,1001},{13,10,267},{141,10,323},{6,0,1662},{7,0,48},{8,0,771},{10,0,116},{13,0\n,104},{14,0,105},{14,0,184},{15,0,168},{19,0,92},{148,0,68},{10,0,209},{135,11,\n1870},{7,11,68},{8,11,48},{8,11,88},{8,11,582},{8,11,681},{9,11,373},{9,11,864},\n{11,11,157},{11,11,336},{11,11,843},{148,11,27},{134,0,930},{4,11,88},{5,11,137}\n,{5,11,174},{5,11,777},{6,11,1664},{6,11,1725},{7,11,77},{7,11,426},{7,11,1317},\n{7,11,1355},{8,11,126},{8,11,563},{9,11,523},{9,11,750},{10,11,310},{10,11,836},\n{11,11,42},{11,11,318},{11,11,731},{12,11,68},{12,11,92},{12,11,507},{12,11,692}\n,{13,11,81},{13,11,238},{13,11,374},{18,11,138},{19,11,78},{19,11,111},{20,11,55\n},{20,11,77},{148,11,92},{4,11,938},{135,11,1831},{5,10,547},{7,10,424},{8,11,\n617},{138,11,351},{6,0,1286},{6,11,1668},{7,11,1499},{8,11,117},{9,11,314},{138,\n11,174},{6,0,759},{6,0,894},{7,11,707},{139,11,563},{4,0,120},{135,0,1894},{9,0,\n385},{149,0,17},{138,0,429},{133,11,403},{5,0,820},{135,0,931},{10,0,199},{133,\n10,133},{6,0,151},{6,0,1675},{7,0,383},{151,0,10},{6,0,761},{136,10,187},{8,0,\n365},{10,10,0},{10,10,818},{139,10,988},{4,11,44},{5,11,311},{6,11,156},{7,11,\n639},{7,11,762},{7,11,1827},{9,11,8},{9,11,462},{148,11,83},{4,11,346},{7,11,115\n},{9,11,180},{9,11,456},{138,11,363},{136,10,685},{7,0,1086},{145,0,46},{6,0,\n1624},{11,0,11},{12,0,422},{13,0,444},{142,0,360},{6,0,1020},{6,0,1260},{134,0,\n1589},{4,0,43},{5,0,344},{5,0,357},{14,0,472},{150,0,58},{6,0,1864},{6,0,1866},{\n6,0,1868},{6,0,1869},{6,0,1874},{6,0,1877},{6,0,1903},{6,0,1911},{9,0,920},{9,0,\n921},{9,0,924},{9,0,946},{9,0,959},{9,0,963},{9,0,970},{9,0,997},{9,0,1008},{9,0\n,1017},{12,0,795},{12,0,797},{12,0,798},{12,0,800},{12,0,803},{12,0,811},{12,0,\n820},{12,0,821},{12,0,839},{12,0,841},{12,0,848},{12,0,911},{12,0,921},{12,0,922\n},{12,0,925},{12,0,937},{12,0,944},{12,0,945},{12,0,953},{15,0,184},{15,0,191},{\n15,0,199},{15,0,237},{15,0,240},{15,0,243},{15,0,246},{18,0,203},{21,0,40},{21,0\n,52},{21,0,57},{24,0,23},{24,0,28},{152,0,30},{134,0,725},{145,11,58},{133,0,888\n},{137,10,874},{4,0,711},{8,10,774},{10,10,670},{140,10,51},{144,11,40},{6,11,\n185},{7,11,1899},{139,11,673},{137,10,701},{137,0,440},{4,11,327},{5,11,478},{7,\n11,1332},{8,11,753},{140,11,227},{4,10,127},{5,10,350},{6,10,356},{8,10,426},{9,\n10,572},{10,10,247},{139,10,312},{5,11,1020},{133,11,1022},{4,11,103},{133,11,\n401},{6,0,1913},{6,0,1926},{6,0,1959},{9,0,914},{9,0,939},{9,0,952},{9,0,979},{9\n,0,990},{9,0,998},{9,0,1003},{9,0,1023},{12,0,827},{12,0,834},{12,0,845},{12,0,\n912},{12,0,935},{12,0,951},{15,0,172},{15,0,174},{18,0,198},{149,0,63},{5,0,958}\n,{5,0,987},{4,11,499},{135,11,1421},{7,0,885},{6,10,59},{6,10,1762},{9,10,603},{\n141,10,397},{10,11,62},{141,11,164},{4,0,847},{135,0,326},{11,0,276},{142,0,293}\n,{4,0,65},{5,0,479},{5,0,1004},{7,0,1913},{8,0,317},{9,0,302},{10,0,612},{13,0,\n22},{132,11,96},{4,0,261},{135,0,510},{135,0,1514},{6,10,111},{7,10,4},{8,10,163\n},{8,10,776},{138,10,566},{4,0,291},{9,0,515},{12,0,152},{12,0,443},{13,0,392},{\n142,0,357},{7,11,399},{135,11,1492},{4,0,589},{139,0,282},{6,11,563},{135,10,\n1994},{5,10,297},{135,10,1038},{4,0,130},{7,0,843},{135,0,1562},{5,0,42},{5,0,\n879},{7,0,245},{7,0,324},{7,0,1532},{11,0,463},{11,0,472},{13,0,363},{144,0,52},\n{4,0,134},{133,0,372},{133,0,680},{136,10,363},{6,0,1997},{8,0,935},{136,0,977},\n{4,0,810},{135,0,1634},{135,10,1675},{7,0,1390},{4,11,910},{133,11,832},{7,10,\n808},{8,11,266},{139,11,578},{132,0,644},{4,0,982},{138,0,867},{132,10,280},{135\n,0,540},{140,10,54},{135,0,123},{134,0,1978},{4,10,421},{133,10,548},{6,0,623},{\n136,0,789},{4,0,908},{5,0,359},{5,0,508},{6,0,1723},{7,0,343},{7,0,1996},{135,0,\n2026},{134,0,1220},{4,0,341},{135,0,480},{6,10,254},{9,10,109},{138,10,103},{134\n,0,888},{8,11,528},{137,11,348},{7,0,1995},{8,0,299},{11,0,890},{12,0,674},{4,11\n,20},{133,11,616},{135,11,1094},{134,10,1630},{4,0,238},{5,0,503},{6,0,179},{7,0\n,2003},{8,0,381},{8,0,473},{9,0,149},{10,0,788},{15,0,45},{15,0,86},{20,0,110},{\n150,0,57},{133,10,671},{4,11,26},{5,11,429},{6,11,245},{7,11,704},{7,11,1379},{\n135,11,1474},{4,0,121},{5,0,156},{5,0,349},{9,0,431},{10,0,605},{142,0,342},{7,\n11,943},{139,11,614},{132,10,889},{132,11,621},{7,10,1382},{7,11,1382},{135,10,\n1910},{132,10,627},{133,10,775},{133,11,542},{133,11,868},{136,11,433},{6,0,1373\n},{7,0,1011},{11,10,362},{11,10,948},{140,10,388},{6,0,80},{7,0,173},{9,0,547},{\n10,0,730},{14,0,18},{22,0,39},{135,11,1495},{6,0,1694},{135,0,1974},{140,0,196},\n{4,0,923},{6,0,507},{6,0,1711},{7,10,451},{8,10,389},{12,10,490},{13,10,16},{13,\n10,215},{13,10,351},{18,10,132},{147,10,125},{6,0,646},{134,0,1047},{135,10,841}\n,{136,10,566},{6,0,1611},{135,0,1214},{139,0,926},{132,11,525},{132,0,595},{5,0,\n240},{6,0,459},{7,0,12},{7,0,114},{7,0,949},{7,0,1753},{7,0,1805},{8,0,658},{9,0\n,1},{11,0,959},{141,0,446},{5,10,912},{134,10,1695},{132,0,446},{7,11,62},{12,11\n,45},{147,11,112},{5,10,236},{6,10,572},{8,10,492},{11,10,618},{144,10,56},{5,10\n,190},{136,10,318},{135,10,1376},{4,11,223},{6,11,359},{11,11,3},{13,11,108},{14\n,11,89},{144,11,22},{132,11,647},{134,0,490},{134,0,491},{134,0,1584},{135,11,\n685},{138,11,220},{7,0,250},{136,0,507},{132,0,158},{4,0,140},{7,0,362},{8,0,209\n},{9,0,10},{9,0,160},{9,0,503},{9,0,614},{10,0,689},{11,0,327},{11,0,553},{11,0,\n725},{11,0,767},{12,0,252},{12,0,583},{13,0,192},{14,0,269},{14,0,356},{148,0,50\n},{19,0,1},{19,0,26},{150,0,9},{132,11,109},{6,0,228},{7,0,1341},{9,0,408},{138,\n0,343},{4,0,373},{5,0,283},{6,0,480},{7,0,609},{10,0,860},{138,0,878},{6,0,779},\n{134,0,1209},{4,0,557},{7,11,263},{7,11,628},{136,11,349},{132,0,548},{7,0,197},\n{8,0,142},{8,0,325},{9,0,150},{9,0,596},{10,0,350},{10,0,353},{11,0,74},{11,0,\n315},{12,0,662},{12,0,681},{14,0,423},{143,0,141},{4,11,40},{10,11,67},{11,11,\n117},{11,11,768},{139,11,935},{7,11,992},{8,11,301},{9,11,722},{12,11,63},{13,11\n,29},{14,11,161},{143,11,18},{6,0,1490},{138,11,532},{5,0,580},{7,0,378},{7,0,\n674},{7,0,1424},{15,0,83},{16,0,11},{15,11,83},{144,11,11},{6,0,1057},{6,0,1335}\n,{10,0,316},{7,10,85},{7,10,247},{8,10,585},{138,10,163},{4,0,169},{5,0,83},{6,0\n,399},{6,0,579},{6,0,1513},{7,0,692},{7,0,846},{7,0,1015},{7,0,1799},{8,0,403},{\n9,0,394},{10,0,133},{12,0,4},{12,0,297},{12,0,452},{16,0,81},{18,0,25},{21,0,14}\n,{22,0,12},{151,0,18},{134,0,1106},{7,0,1546},{11,0,299},{142,0,407},{134,0,1192\n},{132,0,177},{5,0,411},{135,0,653},{7,0,439},{10,0,727},{11,0,260},{139,0,684},\n{138,10,145},{147,10,83},{5,0,208},{7,0,753},{135,0,1528},{137,11,617},{135,10,\n1922},{135,11,825},{11,0,422},{13,0,389},{4,10,124},{10,10,457},{11,10,121},{11,\n10,169},{11,10,870},{12,10,214},{14,10,187},{143,10,77},{11,0,615},{15,0,58},{11\n,11,615},{143,11,58},{9,0,618},{138,0,482},{6,0,1952},{6,0,1970},{142,0,505},{7,\n10,1193},{135,11,1838},{133,0,242},{135,10,1333},{6,10,107},{7,10,638},{7,10,\n1632},{137,10,396},{133,0,953},{5,10,370},{134,10,1756},{5,11,28},{6,11,204},{10\n,11,320},{10,11,583},{13,11,502},{14,11,72},{14,11,274},{14,11,312},{14,11,344},\n{15,11,159},{16,11,62},{16,11,69},{17,11,30},{18,11,42},{18,11,53},{18,11,84},{\n18,11,140},{19,11,68},{19,11,85},{20,11,5},{20,11,45},{20,11,101},{22,11,7},{150\n,11,20},{4,11,558},{6,11,390},{7,11,162},{7,11,689},{9,11,360},{138,11,653},{11,\n0,802},{141,0,67},{133,10,204},{133,0,290},{5,10,970},{134,10,1706},{132,0,380},\n{5,0,52},{7,0,277},{9,0,368},{139,0,791},{5,11,856},{6,11,1672},{6,11,1757},{6,\n11,1781},{7,11,1150},{7,11,1425},{7,11,1453},{140,11,513},{5,11,92},{7,10,3},{10\n,11,736},{140,11,102},{4,0,112},{5,0,653},{5,10,483},{5,10,685},{6,10,489},{7,10\n,1204},{136,10,394},{132,10,921},{6,0,1028},{133,10,1007},{5,11,590},{9,11,213},\n{145,11,91},{135,10,1696},{10,0,138},{139,0,476},{5,0,725},{5,0,727},{135,0,1811\n},{4,0,979},{6,0,1821},{6,0,1838},{8,0,876},{8,0,883},{8,0,889},{8,0,893},{8,0,\n895},{10,0,934},{12,0,720},{14,0,459},{148,0,123},{135,11,551},{4,0,38},{6,0,435\n},{7,0,307},{7,0,999},{7,0,1481},{7,0,1732},{7,0,1738},{8,0,371},{9,0,414},{11,0\n,316},{12,0,52},{13,0,420},{147,0,100},{135,0,1296},{132,10,712},{134,10,1629},{\n133,0,723},{134,0,651},{136,11,191},{9,11,791},{10,11,93},{11,11,301},{16,11,13}\n,{17,11,23},{18,11,135},{19,11,12},{20,11,1},{20,11,12},{148,11,14},{136,11,503}\n,{6,11,466},{135,11,671},{6,0,1200},{134,0,1330},{135,0,1255},{134,0,986},{5,0,\n109},{6,0,1784},{7,0,1895},{12,0,296},{140,0,302},{135,11,983},{133,10,485},{134\n,0,660},{134,0,800},{5,0,216},{5,0,294},{6,0,591},{7,0,1879},{9,0,141},{9,0,270}\n,{9,0,679},{10,0,159},{11,0,197},{11,0,438},{12,0,538},{12,0,559},{14,0,144},{14\n,0,167},{15,0,67},{4,10,285},{5,10,317},{6,10,301},{7,10,7},{8,10,153},{10,10,\n766},{11,10,468},{12,10,467},{141,10,143},{136,0,945},{134,0,1090},{137,0,81},{\n12,11,468},{19,11,96},{148,11,24},{134,0,391},{138,11,241},{7,0,322},{136,0,249}\n,{134,0,1412},{135,11,795},{5,0,632},{138,0,526},{136,10,819},{6,0,144},{7,0,948\n},{7,0,1042},{8,0,235},{8,0,461},{9,0,453},{9,0,796},{10,0,354},{17,0,77},{135,\n11,954},{139,10,917},{6,0,940},{134,0,1228},{4,0,362},{7,0,52},{135,0,303},{6,11\n,549},{8,11,34},{8,11,283},{9,11,165},{138,11,475},{7,11,370},{7,11,1007},{7,11,\n1177},{135,11,1565},{5,11,652},{5,11,701},{135,11,449},{5,0,196},{6,0,486},{7,0,\n212},{8,0,309},{136,0,346},{6,10,1719},{6,10,1735},{7,10,2016},{7,10,2020},{8,10\n,837},{137,10,852},{6,11,159},{6,11,364},{7,11,516},{7,11,1439},{137,11,518},{\n135,0,1912},{135,0,1290},{132,0,686},{141,11,151},{138,0,625},{136,0,706},{138,\n10,568},{139,0,412},{4,0,30},{133,0,43},{8,10,67},{138,10,419},{7,0,967},{141,0,\n11},{12,0,758},{14,0,441},{142,0,462},{10,10,657},{14,10,297},{142,10,361},{139,\n10,729},{4,0,220},{135,0,1535},{7,11,501},{9,11,111},{10,11,141},{11,11,332},{13\n,11,43},{13,11,429},{14,11,130},{14,11,415},{145,11,102},{4,0,950},{6,0,1859},{7\n,0,11},{8,0,873},{12,0,710},{12,0,718},{12,0,748},{12,0,765},{148,0,124},{5,11,\n149},{5,11,935},{136,11,233},{142,11,291},{134,0,1579},{7,0,890},{8,10,51},{9,10\n,868},{10,10,833},{12,10,481},{12,10,570},{148,10,106},{141,0,2},{132,10,445},{\n136,11,801},{135,0,1774},{7,0,1725},{138,0,393},{5,0,263},{134,0,414},{132,11,\n322},{133,10,239},{7,0,456},{7,10,1990},{8,10,130},{139,10,720},{137,0,818},{5,\n10,123},{6,10,530},{7,10,348},{135,10,1419},{135,10,2024},{6,0,178},{6,0,1750},{\n8,0,251},{9,0,690},{10,0,155},{10,0,196},{10,0,373},{11,0,698},{13,0,155},{148,0\n,93},{5,0,97},{137,0,393},{134,0,674},{11,0,223},{140,0,168},{132,10,210},{139,\n11,464},{6,0,1639},{146,0,159},{139,11,2},{7,0,934},{8,0,647},{17,0,97},{19,0,59\n},{150,0,2},{132,0,191},{5,0,165},{9,0,346},{10,0,655},{11,0,885},{4,10,430},{\n135,11,357},{133,0,877},{5,10,213},{133,11,406},{8,0,128},{139,0,179},{6,11,69},\n{135,11,117},{135,0,1297},{11,11,43},{13,11,72},{141,11,142},{135,11,1830},{142,\n0,164},{5,0,57},{6,0,101},{6,0,586},{6,0,1663},{7,0,132},{7,0,1154},{7,0,1415},{\n7,0,1507},{12,0,493},{15,0,105},{151,0,15},{5,0,459},{7,0,1073},{8,0,241},{136,0\n,334},{133,11,826},{133,10,108},{5,10,219},{10,11,132},{11,11,191},{11,11,358},{\n139,11,460},{6,0,324},{6,0,520},{7,0,338},{7,0,1729},{8,0,228},{139,0,750},{21,0\n,30},{22,0,53},{4,10,193},{5,10,916},{7,10,364},{10,10,398},{10,10,726},{11,10,\n317},{11,10,626},{12,10,142},{12,10,288},{12,10,678},{13,10,313},{15,10,113},{\n146,10,114},{6,11,110},{135,11,1681},{135,0,910},{6,10,241},{7,10,907},{8,10,832\n},{9,10,342},{10,10,729},{11,10,284},{11,10,445},{11,10,651},{11,10,863},{13,10,\n398},{146,10,99},{7,0,705},{9,0,734},{5,11,1000},{7,11,733},{137,11,583},{4,0,73\n},{6,0,612},{7,0,927},{7,0,1822},{8,0,217},{9,0,765},{9,0,766},{10,0,408},{11,0,\n51},{11,0,793},{12,0,266},{15,0,158},{20,0,89},{150,0,32},{7,0,1330},{4,11,297},\n{6,11,529},{7,11,152},{7,11,713},{7,11,1845},{8,11,710},{8,11,717},{140,11,639},\n{5,0,389},{136,0,636},{134,0,1409},{4,10,562},{9,10,254},{139,10,879},{134,0,893\n},{132,10,786},{4,11,520},{135,11,575},{136,0,21},{140,0,721},{136,0,959},{7,11,\n1428},{7,11,1640},{9,11,169},{9,11,182},{9,11,367},{9,11,478},{9,11,506},{9,11,\n551},{9,11,648},{9,11,651},{9,11,697},{9,11,705},{9,11,725},{9,11,787},{9,11,794\n},{10,11,198},{10,11,214},{10,11,267},{10,11,275},{10,11,456},{10,11,551},{10,11\n,561},{10,11,613},{10,11,627},{10,11,668},{10,11,675},{10,11,691},{10,11,695},{\n10,11,707},{10,11,715},{11,11,183},{11,11,201},{11,11,244},{11,11,262},{11,11,\n352},{11,11,439},{11,11,493},{11,11,572},{11,11,591},{11,11,608},{11,11,611},{11\n,11,646},{11,11,674},{11,11,711},{11,11,751},{11,11,761},{11,11,776},{11,11,785}\n,{11,11,850},{11,11,853},{11,11,862},{11,11,865},{11,11,868},{11,11,898},{11,11,\n902},{11,11,903},{11,11,910},{11,11,932},{11,11,942},{11,11,957},{11,11,967},{11\n,11,972},{12,11,148},{12,11,195},{12,11,220},{12,11,237},{12,11,318},{12,11,339}\n,{12,11,393},{12,11,445},{12,11,450},{12,11,474},{12,11,509},{12,11,533},{12,11,\n591},{12,11,594},{12,11,597},{12,11,621},{12,11,633},{12,11,642},{13,11,59},{13,\n11,60},{13,11,145},{13,11,239},{13,11,250},{13,11,273},{13,11,329},{13,11,344},{\n13,11,365},{13,11,372},{13,11,387},{13,11,403},{13,11,414},{13,11,456},{13,11,\n478},{13,11,483},{13,11,489},{14,11,55},{14,11,57},{14,11,81},{14,11,90},{14,11,\n148},{14,11,239},{14,11,266},{14,11,321},{14,11,326},{14,11,327},{14,11,330},{14\n,11,347},{14,11,355},{14,11,401},{14,11,411},{14,11,414},{14,11,416},{14,11,420}\n,{15,11,61},{15,11,74},{15,11,87},{15,11,88},{15,11,94},{15,11,96},{15,11,116},{\n15,11,149},{15,11,154},{16,11,50},{16,11,63},{16,11,73},{17,11,2},{17,11,66},{17\n,11,92},{17,11,103},{17,11,112},{18,11,50},{18,11,54},{18,11,82},{18,11,86},{18,\n11,90},{18,11,111},{18,11,115},{18,11,156},{19,11,40},{19,11,79},{20,11,78},{149\n,11,22},{137,11,170},{134,0,1433},{135,11,1307},{139,11,411},{5,0,189},{7,0,442}\n,{7,0,443},{8,0,281},{12,0,174},{141,0,261},{6,10,216},{7,10,901},{7,10,1343},{\n136,10,493},{5,11,397},{6,11,154},{7,10,341},{7,11,676},{8,11,443},{8,11,609},{9\n,11,24},{9,11,325},{10,11,35},{11,10,219},{11,11,535},{11,11,672},{11,11,1018},{\n12,11,637},{144,11,30},{6,0,2},{7,0,191},{7,0,446},{7,0,1262},{7,0,1737},{8,0,22\n},{8,0,270},{8,0,612},{9,0,4},{9,0,312},{9,0,436},{9,0,626},{10,0,216},{10,0,311\n},{10,0,521},{10,0,623},{11,0,72},{11,0,330},{11,0,455},{12,0,321},{12,0,504},{\n12,0,530},{12,0,543},{13,0,17},{13,0,156},{13,0,334},{14,0,131},{17,0,60},{148,0\n,64},{7,0,354},{10,0,410},{139,0,815},{139,10,130},{7,10,1734},{137,11,631},{12,\n0,425},{15,0,112},{10,10,115},{11,10,420},{13,10,404},{14,10,346},{143,10,54},{6\n,0,60},{6,0,166},{7,0,374},{7,0,670},{7,0,1327},{8,0,411},{8,0,435},{9,0,653},{9\n,0,740},{10,0,385},{11,0,222},{11,0,324},{11,0,829},{140,0,611},{7,0,1611},{13,0\n,14},{15,0,44},{19,0,13},{148,0,76},{133,11,981},{4,11,56},{7,11,1791},{8,11,607\n},{8,11,651},{11,11,465},{11,11,835},{12,11,337},{141,11,480},{6,0,1478},{5,10,\n1011},{136,10,701},{139,0,596},{5,0,206},{134,0,398},{4,10,54},{5,10,666},{7,10,\n1039},{7,10,1130},{9,10,195},{138,10,302},{7,0,50},{9,11,158},{138,11,411},{135,\n11,1120},{6,0,517},{7,0,1159},{10,0,621},{11,0,192},{134,10,1669},{4,0,592},{6,0\n,600},{135,0,1653},{10,0,223},{139,0,645},{136,11,139},{7,0,64},{136,0,245},{142\n,0,278},{6,11,622},{135,11,1030},{136,0,604},{134,0,1502},{138,0,265},{141,11,\n168},{7,0,1763},{140,0,310},{7,10,798},{139,11,719},{7,11,160},{10,11,624},{142,\n11,279},{132,11,363},{7,10,122},{9,10,259},{10,10,84},{11,10,470},{12,10,541},{\n141,10,379},{5,0,129},{6,0,61},{135,0,947},{134,0,1356},{135,11,1191},{13,0,505}\n,{141,0,506},{11,0,1000},{5,10,82},{5,10,131},{7,10,1755},{8,10,31},{9,10,168},{\n9,10,764},{139,10,869},{134,0,966},{134,10,605},{134,11,292},{5,11,177},{6,11,\n616},{7,11,827},{9,11,525},{138,11,656},{135,11,1486},{138,11,31},{5,10,278},{\n137,10,68},{4,10,163},{5,10,201},{5,10,307},{5,10,310},{6,10,335},{7,10,284},{\n136,10,165},{6,0,839},{135,10,1660},{136,10,781},{6,10,33},{135,10,1244},{133,0,\n637},{4,11,161},{133,11,631},{137,0,590},{7,10,1953},{136,10,720},{5,0,280},{7,0\n,1226},{138,10,203},{134,0,1386},{5,0,281},{6,0,1026},{6,10,326},{7,10,677},{137\n,10,425},{7,11,1557},{135,11,1684},{135,0,1064},{9,11,469},{9,11,709},{12,11,512\n},{14,11,65},{145,11,12},{134,0,917},{10,11,229},{11,11,73},{11,11,376},{139,11,\n433},{7,0,555},{9,0,192},{13,0,30},{13,0,49},{15,0,150},{16,0,76},{20,0,52},{7,\n10,1316},{7,10,1412},{7,10,1839},{9,10,589},{11,10,241},{11,10,676},{11,10,811},\n{11,10,891},{12,10,140},{12,10,346},{12,10,479},{13,10,381},{14,10,188},{146,10,\n30},{149,0,15},{6,0,1882},{6,0,1883},{6,0,1897},{9,0,945},{9,0,1014},{9,0,1020},\n{12,0,823},{12,0,842},{12,0,866},{12,0,934},{15,0,242},{146,0,208},{6,0,965},{\n134,0,1499},{7,0,33},{7,0,120},{8,0,489},{9,0,319},{10,0,820},{11,0,1004},{12,0,\n379},{12,0,679},{13,0,117},{13,0,412},{14,0,25},{15,0,52},{15,0,161},{16,0,47},{\n149,0,2},{6,11,558},{7,11,651},{8,11,421},{9,11,0},{138,11,34},{4,0,937},{5,0,\n801},{7,0,473},{5,10,358},{7,10,1184},{10,10,662},{13,10,212},{13,10,304},{13,10\n,333},{145,10,98},{132,0,877},{6,0,693},{134,0,824},{132,0,365},{7,11,1832},{138\n,11,374},{5,0,7},{139,0,774},{4,0,734},{5,0,662},{134,0,430},{4,0,746},{135,0,\n1090},{5,0,360},{8,0,237},{10,0,231},{147,0,124},{138,11,348},{6,11,6},{7,11,81}\n,{7,11,771},{7,11,1731},{9,11,405},{138,11,421},{6,0,740},{137,0,822},{133,10,\n946},{7,0,1485},{136,0,929},{7,10,411},{8,10,631},{9,10,323},{10,10,355},{11,10,\n491},{12,10,143},{12,10,402},{13,10,73},{14,10,408},{15,10,107},{146,10,71},{135\n,10,590},{5,11,881},{133,11,885},{150,11,25},{4,0,852},{5,11,142},{134,11,546},{\n7,10,1467},{8,10,328},{10,10,544},{11,10,955},{13,10,320},{145,10,83},{9,0,17},{\n10,0,291},{11,10,511},{13,10,394},{14,10,298},{14,10,318},{146,10,103},{5,11,466\n},{11,11,571},{12,11,198},{13,11,283},{14,11,186},{15,11,21},{143,11,103},{134,0\n,1001},{4,11,185},{5,11,257},{5,11,839},{5,11,936},{7,11,171},{9,11,399},{10,11,\n258},{10,11,395},{10,11,734},{11,11,1014},{12,11,23},{13,11,350},{14,11,150},{\n147,11,6},{143,0,35},{132,0,831},{5,10,835},{134,10,483},{4,0,277},{5,0,608},{6,\n0,493},{7,0,457},{12,0,384},{7,11,404},{7,11,1377},{7,11,1430},{7,11,2017},{8,11\n,149},{8,11,239},{8,11,512},{8,11,793},{8,11,818},{9,11,474},{9,11,595},{10,11,\n122},{10,11,565},{10,11,649},{10,11,783},{11,11,239},{11,11,295},{11,11,447},{11\n,11,528},{11,11,639},{11,11,800},{11,11,936},{12,11,25},{12,11,73},{12,11,77},{\n12,11,157},{12,11,316},{12,11,390},{12,11,391},{12,11,394},{12,11,395},{12,11,\n478},{12,11,503},{12,11,592},{12,11,680},{13,11,50},{13,11,53},{13,11,132},{13,\n11,198},{13,11,275},{13,11,322},{13,11,415},{14,11,71},{14,11,257},{14,11,395},{\n15,11,71},{15,11,136},{17,11,123},{18,11,93},{147,11,58},{134,0,1351},{7,0,27},{\n135,0,316},{136,11,712},{136,0,984},{133,0,552},{137,0,264},{132,0,401},{6,0,710\n},{6,0,1111},{134,0,1343},{134,0,1211},{9,0,543},{10,0,524},{11,0,108},{11,0,653\n},{12,0,524},{13,0,123},{14,0,252},{16,0,18},{19,0,38},{20,0,26},{20,0,65},{21,0\n,3},{151,0,11},{4,0,205},{5,0,623},{7,0,104},{8,0,519},{137,0,716},{132,10,677},\n{4,11,377},{152,11,13},{135,11,1673},{7,0,579},{9,0,41},{9,0,244},{9,0,669},{10,\n0,5},{11,0,861},{11,0,951},{139,0,980},{132,0,717},{136,0,1011},{132,0,805},{4,\n11,180},{135,11,1906},{132,10,777},{132,10,331},{132,0,489},{6,0,1024},{4,11,491\n},{133,10,747},{135,11,1182},{4,11,171},{138,11,234},{4,11,586},{7,11,1186},{138\n,11,631},{135,0,892},{135,11,336},{9,11,931},{10,11,334},{148,11,71},{137,0,473}\n,{6,0,864},{12,0,659},{139,11,926},{7,0,819},{9,0,26},{9,0,392},{10,0,152},{10,0\n,226},{11,0,19},{12,0,276},{12,0,426},{12,0,589},{13,0,460},{15,0,97},{19,0,48},\n{148,0,104},{135,0,51},{133,10,326},{4,10,691},{146,10,16},{9,0,130},{11,0,765},\n{10,10,680},{10,10,793},{141,10,357},{133,11,765},{8,0,229},{6,10,32},{7,10,385}\n,{7,10,757},{7,10,1916},{8,10,94},{8,10,711},{9,10,541},{10,10,162},{10,10,795},\n{11,10,989},{11,10,1010},{12,10,14},{142,10,308},{7,11,474},{137,11,578},{132,0,\n674},{132,0,770},{5,0,79},{7,0,1027},{7,0,1477},{139,0,52},{133,11,424},{134,0,\n1666},{6,0,409},{6,10,349},{6,10,1682},{7,10,1252},{8,10,112},{8,11,714},{9,10,\n435},{9,10,668},{10,10,290},{10,10,319},{10,10,815},{11,10,180},{11,10,837},{12,\n10,240},{13,10,152},{13,10,219},{142,10,158},{5,0,789},{134,0,195},{4,0,251},{4,\n0,688},{7,0,513},{135,0,1284},{132,10,581},{9,11,420},{10,11,269},{10,11,285},{\n10,11,576},{11,11,397},{13,11,175},{145,11,90},{6,10,126},{7,10,573},{8,10,397},\n{142,10,44},{132,11,429},{133,0,889},{4,0,160},{5,0,330},{7,0,1434},{136,0,174},\n{7,11,18},{7,11,699},{7,11,1966},{8,11,752},{9,11,273},{9,11,412},{9,11,703},{10\n,11,71},{10,11,427},{10,11,508},{146,11,97},{6,0,872},{134,0,899},{133,10,926},{\n134,0,1126},{134,0,918},{4,11,53},{5,11,186},{135,11,752},{7,0,268},{136,0,569},\n{134,0,1224},{6,0,1361},{7,10,1232},{137,10,531},{8,11,575},{10,11,289},{139,11,\n319},{133,10,670},{132,11,675},{133,0,374},{135,10,1957},{133,0,731},{11,0,190},\n{15,0,49},{11,11,190},{143,11,49},{4,0,626},{5,0,506},{5,0,642},{6,0,425},{10,0,\n202},{139,0,141},{137,0,444},{7,10,242},{135,10,1942},{6,11,209},{8,11,468},{9,\n11,210},{11,11,36},{12,11,28},{12,11,630},{13,11,21},{13,11,349},{14,11,7},{145,\n11,13},{4,11,342},{135,11,1179},{5,10,834},{7,10,1202},{8,10,14},{9,10,481},{137\n,10,880},{4,11,928},{133,11,910},{4,11,318},{4,11,496},{7,11,856},{139,11,654},{\n136,0,835},{7,0,1526},{138,10,465},{151,0,17},{135,0,477},{4,10,357},{6,10,172},\n{7,10,143},{137,10,413},{6,0,1374},{138,0,994},{18,0,76},{132,10,590},{7,0,287},\n{8,0,355},{9,0,293},{137,0,743},{134,0,1389},{7,11,915},{8,11,247},{147,11,0},{4\n,11,202},{5,11,382},{6,11,454},{7,11,936},{7,11,1803},{8,11,758},{9,11,375},{9,\n11,895},{10,11,743},{10,11,792},{11,11,978},{11,11,1012},{142,11,109},{5,0,384},\n{8,0,455},{140,0,48},{132,11,390},{5,10,169},{7,10,333},{136,10,45},{5,0,264},{\n134,0,184},{138,11,791},{133,11,717},{132,10,198},{6,11,445},{7,11,332},{137,11,\n909},{136,0,1001},{4,10,24},{5,10,140},{5,10,185},{7,10,1500},{11,10,565},{139,\n10,838},{134,11,578},{5,0,633},{6,0,28},{135,0,1323},{132,0,851},{136,11,267},{7\n,0,359},{8,0,243},{140,0,175},{4,10,334},{133,10,593},{141,11,87},{136,11,766},{\n10,0,287},{12,0,138},{10,11,287},{140,11,138},{4,0,105},{132,0,740},{140,10,116}\n,{134,0,857},{135,11,1841},{6,0,1402},{137,0,819},{132,11,584},{132,10,709},{133\n,10,897},{5,0,224},{13,0,174},{146,0,52},{135,10,1840},{4,10,608},{133,10,497},{\n139,11,60},{4,0,758},{135,0,1649},{4,11,226},{4,11,326},{135,11,1770},{5,11,426}\n,{8,11,30},{9,11,2},{11,11,549},{147,11,122},{135,10,2039},{6,10,540},{136,10,\n136},{4,0,573},{8,0,655},{4,10,897},{133,10,786},{7,0,351},{139,0,128},{133,10,\n999},{4,10,299},{135,10,1004},{133,0,918},{132,11,345},{4,11,385},{7,11,265},{\n135,11,587},{133,10,456},{136,10,180},{6,0,687},{134,0,1537},{4,11,347},{5,11,\n423},{5,11,996},{135,11,1329},{132,10,755},{7,11,1259},{9,11,125},{11,11,65},{\n140,11,285},{5,11,136},{6,11,136},{136,11,644},{134,0,1525},{4,0,1009},{135,0,\n1139},{139,10,338},{132,0,340},{135,10,1464},{8,0,847},{10,0,861},{10,0,876},{10\n,0,889},{10,0,922},{10,0,929},{10,0,933},{12,0,784},{140,0,791},{139,0,176},{9,\n11,134},{10,11,2},{10,11,27},{10,11,333},{11,11,722},{143,11,1},{4,11,433},{133,\n11,719},{5,0,985},{7,0,509},{7,0,529},{145,0,96},{132,0,615},{4,10,890},{5,10,\n805},{5,10,819},{5,10,961},{6,10,396},{6,10,1631},{6,10,1678},{7,10,1967},{7,10,\n2041},{9,10,630},{11,10,8},{11,10,1019},{12,10,176},{13,10,225},{14,10,292},{149\n,10,24},{135,0,1919},{134,0,1131},{144,11,21},{144,11,51},{135,10,1815},{4,0,247\n},{7,10,1505},{10,10,190},{10,10,634},{11,10,792},{12,10,358},{140,10,447},{5,10\n,0},{6,10,536},{7,10,604},{13,10,445},{145,10,126},{4,0,184},{5,0,390},{6,0,337}\n,{7,0,23},{7,0,494},{7,0,618},{7,0,1456},{8,0,27},{8,0,599},{10,0,153},{139,0,\n710},{6,10,232},{6,10,412},{7,10,1074},{8,10,9},{8,10,157},{8,10,786},{9,10,196}\n,{9,10,352},{9,10,457},{10,10,337},{11,10,232},{11,10,877},{12,10,480},{140,10,\n546},{13,0,38},{135,10,958},{4,10,382},{136,10,579},{4,10,212},{135,10,1206},{4,\n11,555},{8,11,536},{138,11,288},{11,11,139},{139,11,171},{9,11,370},{138,11,90},\n{132,0,1015},{134,0,1088},{5,10,655},{135,11,977},{134,0,1585},{17,10,67},{147,\n10,74},{10,0,227},{11,0,497},{11,0,709},{140,0,415},{6,0,360},{7,0,1664},{136,0,\n478},{7,0,95},{6,10,231},{136,10,423},{140,11,65},{4,11,257},{135,11,2031},{135,\n11,1768},{133,10,300},{139,11,211},{136,0,699},{6,10,237},{7,10,611},{8,10,100},\n{9,10,416},{11,10,335},{12,10,173},{146,10,101},{14,0,26},{146,0,150},{6,0,581},\n{135,0,1119},{135,10,1208},{132,0,739},{6,11,83},{6,11,1733},{135,11,1389},{137,\n0,869},{4,0,67},{5,0,422},{7,0,1037},{7,0,1289},{7,0,1555},{9,0,741},{145,0,108}\n,{133,10,199},{12,10,427},{146,10,38},{136,0,464},{142,0,42},{10,0,96},{8,11,501\n},{137,11,696},{134,11,592},{4,0,512},{4,0,966},{5,0,342},{6,0,1855},{8,0,869},{\n8,0,875},{8,0,901},{144,0,26},{8,0,203},{11,0,823},{11,0,846},{12,0,482},{13,0,\n277},{13,0,302},{13,0,464},{14,0,205},{142,0,221},{4,0,449},{133,0,718},{7,11,\n1718},{9,11,95},{9,11,274},{10,11,279},{10,11,317},{10,11,420},{11,11,303},{11,\n11,808},{12,11,134},{12,11,367},{13,11,149},{13,11,347},{14,11,349},{14,11,406},\n{18,11,22},{18,11,89},{18,11,122},{147,11,47},{133,11,26},{4,0,355},{6,0,311},{9\n,0,256},{138,0,404},{132,11,550},{10,0,758},{6,10,312},{6,10,1715},{10,10,584},{\n11,10,546},{11,10,692},{12,10,259},{12,10,295},{13,10,46},{141,10,154},{136,11,\n822},{5,0,827},{4,11,902},{5,11,809},{6,11,122},{135,11,896},{5,0,64},{140,0,581\n},{4,0,442},{6,0,739},{7,0,1047},{7,0,1352},{7,0,1643},{7,11,1911},{9,11,449},{\n10,11,192},{138,11,740},{135,11,262},{132,10,588},{133,11,620},{5,0,977},{6,0,\n288},{7,0,528},{4,11,34},{5,11,574},{7,11,279},{7,11,1624},{136,11,601},{6,0,\n1375},{4,10,231},{5,10,61},{6,10,104},{7,10,729},{7,10,964},{7,10,1658},{140,10,\n414},{6,10,263},{138,10,757},{132,10,320},{4,0,254},{7,0,1309},{5,11,332},{135,\n11,1309},{6,11,261},{8,11,182},{139,11,943},{132,10,225},{6,0,12},{135,0,1219},{\n4,0,275},{12,0,376},{6,11,1721},{141,11,490},{4,11,933},{133,11,880},{6,0,951},{\n6,0,1109},{6,0,1181},{7,0,154},{4,10,405},{7,10,817},{14,10,58},{17,10,37},{146,\n10,124},{6,0,1520},{133,10,974},{134,0,1753},{6,0,369},{6,0,502},{7,0,1036},{8,0\n,348},{9,0,452},{10,0,26},{11,0,224},{11,0,387},{11,0,772},{12,0,95},{12,0,629},\n{13,0,195},{13,0,207},{13,0,241},{14,0,260},{14,0,270},{143,0,140},{132,0,269},{\n5,0,480},{7,0,532},{7,0,1197},{7,0,1358},{8,0,291},{11,0,349},{142,0,396},{5,10,\n235},{7,10,1239},{11,10,131},{140,10,370},{7,10,956},{7,10,1157},{7,10,1506},{7,\n10,1606},{7,10,1615},{7,10,1619},{7,10,1736},{7,10,1775},{8,10,590},{9,10,324},{\n9,10,736},{9,10,774},{9,10,776},{9,10,784},{10,10,567},{10,10,708},{11,10,518},{\n11,10,613},{11,10,695},{11,10,716},{11,10,739},{11,10,770},{11,10,771},{11,10,\n848},{11,10,857},{11,10,931},{11,10,947},{12,10,326},{12,10,387},{12,10,484},{12\n,10,528},{12,10,552},{12,10,613},{13,10,189},{13,10,256},{13,10,340},{13,10,432}\n,{13,10,436},{13,10,440},{13,10,454},{14,10,174},{14,10,220},{14,10,284},{14,10,\n390},{145,10,121},{8,11,598},{9,11,664},{138,11,441},{9,10,137},{138,10,221},{\n133,11,812},{148,0,15},{134,0,1341},{6,0,1017},{4,11,137},{7,11,1178},{135,11,\n1520},{7,10,390},{138,10,140},{7,11,1260},{135,11,1790},{137,11,191},{135,10,\n1144},{6,0,1810},{7,0,657},{8,0,886},{10,0,857},{14,0,440},{144,0,96},{8,0,533},\n{6,11,1661},{7,11,1975},{7,11,2009},{135,11,2011},{6,0,1453},{134,10,464},{132,\n11,715},{5,10,407},{11,10,204},{11,10,243},{11,10,489},{12,10,293},{19,10,37},{\n20,10,73},{150,10,38},{133,11,703},{4,0,211},{7,0,1483},{5,10,325},{8,10,5},{8,\n10,227},{9,10,105},{10,10,585},{140,10,614},{4,0,332},{5,0,335},{6,0,238},{7,0,\n269},{7,0,811},{7,0,1797},{8,0,836},{9,0,507},{141,0,242},{5,11,89},{7,11,1915},\n{9,11,185},{9,11,235},{9,11,496},{10,11,64},{10,11,270},{10,11,403},{10,11,469},\n{10,11,529},{10,11,590},{11,11,140},{11,11,860},{13,11,1},{13,11,422},{14,11,341\n},{14,11,364},{17,11,93},{18,11,113},{19,11,97},{147,11,113},{133,11,695},{16,0,\n19},{5,11,6},{6,11,183},{6,10,621},{7,11,680},{7,11,978},{7,11,1013},{7,11,1055}\n,{12,11,230},{13,11,172},{13,10,504},{146,11,29},{136,0,156},{133,0,1009},{6,11,\n29},{139,11,63},{134,0,820},{134,10,218},{7,10,454},{7,10,782},{8,10,768},{140,\n10,686},{5,0,228},{6,0,203},{7,0,156},{8,0,347},{9,0,265},{18,0,39},{20,0,54},{\n21,0,31},{22,0,3},{23,0,0},{15,11,8},{18,11,39},{20,11,54},{21,11,31},{22,11,3},\n{151,11,0},{7,0,1131},{135,0,1468},{144,10,0},{134,0,1276},{10,10,676},{140,10,\n462},{132,11,311},{134,11,1740},{7,11,170},{8,11,90},{8,11,177},{8,11,415},{11,\n11,714},{142,11,281},{134,10,164},{6,0,1792},{138,0,849},{150,10,50},{5,0,291},{\n5,0,318},{7,0,765},{9,0,389},{12,0,548},{8,11,522},{142,11,328},{11,11,91},{13,\n11,129},{15,11,101},{145,11,125},{4,11,494},{6,11,74},{7,11,44},{7,11,407},{8,11\n,551},{12,11,17},{15,11,5},{148,11,11},{4,11,276},{133,11,296},{6,10,343},{7,10,\n195},{7,11,1777},{9,10,226},{10,10,197},{10,10,575},{11,10,502},{139,10,899},{10\n,0,525},{139,0,82},{14,0,453},{4,11,7},{5,11,90},{5,11,158},{6,11,542},{7,11,221\n},{7,11,1574},{9,11,490},{10,11,540},{11,11,443},{139,11,757},{135,0,666},{22,10\n,29},{150,11,29},{4,0,422},{147,10,8},{5,0,355},{145,0,0},{6,0,1873},{9,0,918},{\n7,11,588},{9,11,175},{138,11,530},{143,11,31},{11,0,165},{7,10,1125},{9,10,143},\n{14,10,405},{150,10,21},{9,0,260},{137,0,905},{5,11,872},{6,11,57},{6,11,479},{6\n,11,562},{7,11,471},{7,11,1060},{9,11,447},{9,11,454},{141,11,6},{138,11,704},{\n133,0,865},{5,0,914},{134,0,1625},{133,0,234},{7,0,1383},{5,11,31},{6,11,614},{\n145,11,61},{7,11,1200},{138,11,460},{6,11,424},{135,11,1866},{136,0,306},{5,10,\n959},{12,11,30},{13,11,148},{14,11,87},{14,11,182},{16,11,42},{18,11,92},{148,11\n,70},{6,0,1919},{6,0,1921},{9,0,923},{9,0,930},{9,0,941},{9,0,949},{9,0,987},{9,\n0,988},{9,0,992},{12,0,802},{12,0,815},{12,0,856},{12,0,885},{12,0,893},{12,0,\n898},{12,0,919},{12,0,920},{12,0,941},{12,0,947},{15,0,183},{15,0,185},{15,0,189\n},{15,0,197},{15,0,202},{15,0,233},{18,0,218},{18,0,219},{18,0,233},{143,11,156}\n,{135,10,1759},{136,10,173},{13,0,163},{13,0,180},{18,0,78},{20,0,35},{5,11,13},\n{134,11,142},{134,10,266},{6,11,97},{7,11,116},{8,11,322},{8,11,755},{9,11,548},\n{10,11,714},{11,11,884},{141,11,324},{135,0,1312},{9,0,814},{137,11,676},{133,0,\n707},{135,0,1493},{6,0,421},{7,0,61},{7,0,1540},{10,0,11},{138,0,501},{12,0,733}\n,{12,0,766},{7,11,866},{135,11,1163},{137,0,341},{142,0,98},{145,11,115},{135,11\n,1111},{136,10,300},{136,0,1014},{8,11,1},{9,11,112},{138,11,326},{132,11,730},{\n5,11,488},{6,11,527},{7,11,489},{7,11,1636},{8,11,121},{8,11,144},{8,11,359},{9,\n11,193},{9,11,241},{9,11,336},{9,11,882},{11,11,266},{11,11,372},{11,11,944},{12\n,11,401},{140,11,641},{6,0,971},{134,0,1121},{6,0,102},{7,0,72},{15,0,142},{147,\n0,67},{151,0,30},{135,0,823},{134,0,1045},{5,10,427},{5,10,734},{7,10,478},{136,\n10,52},{7,0,1930},{11,10,217},{142,10,165},{6,0,1512},{135,0,1870},{9,11,31},{10\n,11,244},{10,11,699},{12,11,149},{141,11,497},{133,11,377},{145,11,101},{10,11,\n158},{13,11,13},{13,11,137},{13,11,258},{14,11,111},{14,11,225},{14,11,253},{14,\n11,304},{14,11,339},{14,11,417},{146,11,33},{6,0,87},{6,10,1734},{7,10,20},{7,10\n,1056},{8,10,732},{9,10,406},{9,10,911},{138,10,694},{134,0,1243},{137,0,245},{7\n,0,68},{8,0,48},{8,0,88},{8,0,582},{8,0,681},{9,0,373},{9,0,864},{11,0,157},{11,\n0,336},{11,0,843},{148,0,27},{8,11,663},{144,11,8},{133,10,613},{4,0,88},{5,0,\n137},{5,0,174},{5,0,777},{6,0,1664},{6,0,1725},{7,0,77},{7,0,426},{7,0,1317},{7,\n0,1355},{8,0,126},{8,0,563},{9,0,523},{9,0,750},{10,0,310},{10,0,836},{11,0,42},\n{11,0,318},{11,0,731},{12,0,68},{12,0,92},{12,0,507},{12,0,692},{13,0,81},{13,0,\n238},{13,0,374},{14,0,436},{18,0,138},{19,0,78},{19,0,111},{20,0,55},{20,0,77},{\n148,0,92},{141,0,418},{4,0,938},{137,0,625},{138,0,351},{5,11,843},{7,10,32},{7,\n10,984},{8,10,85},{8,10,709},{9,10,579},{9,10,847},{9,10,856},{10,10,799},{11,10\n,258},{11,10,1007},{12,10,331},{12,10,615},{13,10,188},{13,10,435},{14,10,8},{15\n,10,165},{16,10,27},{148,10,40},{6,0,1668},{7,0,1499},{8,0,117},{9,0,314},{138,0\n,174},{135,0,707},{132,11,554},{133,11,536},{5,0,403},{5,11,207},{9,11,79},{11,\n11,625},{145,11,7},{132,11,424},{136,11,785},{4,10,167},{135,10,82},{9,0,7},{23,\n0,6},{9,11,7},{151,11,6},{6,0,282},{5,10,62},{6,10,534},{7,10,74},{7,10,678},{7,\n10,684},{7,10,1043},{7,10,1072},{8,10,280},{8,10,541},{8,10,686},{9,10,258},{10,\n10,519},{11,10,252},{140,10,282},{138,10,33},{132,10,359},{4,0,44},{5,0,311},{6,\n0,156},{7,0,639},{7,0,762},{7,0,1827},{9,0,8},{9,0,462},{148,0,83},{7,11,769},{9\n,11,18},{138,11,358},{4,0,346},{7,0,115},{9,0,180},{9,0,456},{10,0,363},{4,11,\n896},{134,11,1777},{133,10,211},{7,0,761},{7,0,1051},{137,0,545},{6,10,145},{141\n,10,336},{7,11,750},{9,11,223},{11,11,27},{11,11,466},{12,11,624},{14,11,265},{\n146,11,61},{6,0,752},{6,0,768},{6,0,1195},{6,0,1254},{6,0,1619},{137,0,835},{6,0\n,1936},{8,0,930},{136,0,960},{132,10,263},{132,11,249},{12,0,653},{132,10,916},{\n4,11,603},{133,11,661},{8,0,344},{4,11,11},{6,11,128},{7,11,231},{7,11,1533},{\n138,11,725},{134,0,1483},{134,0,875},{6,0,185},{7,0,1899},{9,0,875},{139,0,673},\n{15,10,155},{144,10,79},{7,0,93},{7,0,210},{7,0,1223},{8,0,451},{8,0,460},{11,0,\n353},{11,0,475},{4,10,599},{6,10,1634},{7,10,67},{7,10,691},{7,10,979},{7,10,\n1697},{8,10,207},{8,10,214},{8,10,231},{8,10,294},{8,10,336},{8,10,428},{8,10,\n471},{8,10,622},{8,10,626},{8,10,679},{8,10,759},{8,10,829},{9,10,11},{9,10,246}\n,{9,10,484},{9,10,573},{9,10,706},{9,10,762},{9,10,798},{9,10,855},{9,10,870},{9\n,10,912},{10,10,303},{10,10,335},{10,10,424},{10,10,461},{10,10,543},{10,10,759}\n,{10,10,814},{11,10,59},{11,10,235},{11,10,590},{11,10,929},{11,10,963},{11,10,\n987},{12,10,114},{12,10,182},{12,10,226},{12,10,332},{12,10,439},{12,10,575},{12\n,10,598},{12,10,675},{13,10,8},{13,10,125},{13,10,194},{13,10,287},{14,10,197},{\n14,10,383},{15,10,53},{17,10,63},{19,10,46},{19,10,98},{19,10,106},{148,10,85},{\n132,11,476},{4,0,327},{5,0,478},{7,0,1332},{136,0,753},{5,0,1020},{133,0,1022},{\n135,11,1807},{4,0,103},{133,0,401},{4,0,499},{135,0,1421},{10,0,207},{13,0,164},\n{147,10,126},{9,11,20},{10,11,324},{139,11,488},{132,0,96},{9,11,280},{138,11,\n134},{135,0,968},{133,10,187},{135,10,1286},{5,11,112},{6,11,103},{134,11,150},{\n8,0,914},{10,0,3},{4,10,215},{9,10,38},{11,10,23},{11,10,127},{139,10,796},{135,\n0,399},{6,0,563},{137,0,224},{6,0,704},{134,0,1214},{4,11,708},{8,11,15},{9,11,\n50},{9,11,386},{11,11,18},{11,11,529},{140,11,228},{4,11,563},{7,11,109},{7,11,\n592},{7,11,637},{7,11,770},{7,11,1701},{8,11,436},{8,11,463},{9,11,60},{9,11,335\n},{9,11,904},{10,11,73},{11,11,434},{12,11,585},{13,11,331},{18,11,110},{148,11,\n60},{134,0,1559},{132,11,502},{6,11,347},{138,11,161},{4,11,33},{5,11,102},{5,11\n,500},{6,11,284},{7,11,1079},{7,11,1423},{7,11,1702},{8,11,470},{9,11,554},{9,11\n,723},{139,11,333},{7,11,246},{135,11,840},{6,11,10},{8,11,571},{9,11,739},{143,\n11,91},{8,0,861},{10,0,905},{12,0,730},{12,0,789},{133,11,626},{134,0,946},{5,0,\n746},{12,0,333},{14,0,332},{12,11,333},{142,11,332},{5,11,18},{6,11,526},{13,11,\n24},{13,11,110},{19,11,5},{147,11,44},{4,0,910},{5,0,832},{135,10,2002},{10,11,\n768},{139,11,787},{4,11,309},{5,11,462},{7,11,970},{135,11,1097},{4,10,28},{5,10\n,440},{7,10,248},{11,10,833},{140,10,344},{134,10,1654},{6,0,632},{6,0,652},{6,0\n,1272},{6,0,1384},{134,0,1560},{134,11,1704},{6,0,1393},{133,10,853},{6,10,249},\n{7,10,1234},{139,10,573},{5,11,86},{7,11,743},{9,11,85},{10,11,281},{10,11,432},\n{11,11,490},{12,11,251},{13,11,118},{14,11,378},{146,11,143},{5,11,524},{133,11,\n744},{134,0,1514},{10,0,201},{142,0,319},{7,0,717},{10,0,510},{7,10,392},{8,10,\n20},{8,10,172},{8,10,690},{9,10,383},{9,10,845},{11,10,293},{11,10,832},{11,10,\n920},{11,10,984},{141,10,221},{134,0,1381},{5,10,858},{133,10,992},{8,0,528},{\n137,0,348},{10,11,107},{140,11,436},{4,0,20},{133,0,616},{134,0,1251},{132,11,\n927},{10,11,123},{12,11,670},{13,11,371},{14,11,142},{146,11,94},{134,0,1163},{7\n,11,1149},{137,11,156},{134,0,307},{133,11,778},{7,0,1091},{135,0,1765},{5,11,\n502},{6,10,268},{137,10,62},{8,11,196},{10,11,283},{139,11,406},{4,0,26},{5,0,\n429},{6,0,245},{7,0,704},{7,0,1379},{135,0,1474},{133,11,855},{132,0,881},{4,0,\n621},{135,11,1596},{7,11,1400},{9,11,446},{138,11,45},{6,0,736},{138,10,106},{\n133,0,542},{134,0,348},{133,0,868},{136,0,433},{135,0,1495},{138,0,771},{6,10,\n613},{136,10,223},{138,0,215},{141,0,124},{136,11,391},{135,11,172},{132,10,670}\n,{140,0,55},{9,10,40},{139,10,136},{7,0,62},{147,0,112},{132,0,856},{132,11,568}\n,{12,0,270},{139,10,259},{8,0,572},{137,0,698},{4,11,732},{9,10,310},{137,10,682\n},{142,10,296},{134,0,939},{136,11,733},{135,11,1435},{7,10,1401},{135,10,1476},\n{6,0,352},{4,10,296},{7,10,401},{7,10,1410},{7,10,1594},{7,10,1674},{8,10,63},{8\n,10,660},{137,10,74},{4,11,428},{133,11,668},{4,10,139},{4,10,388},{140,10,188},\n{7,11,2015},{140,11,665},{132,0,647},{146,0,10},{138,0,220},{142,0,464},{132,0,\n109},{134,0,1746},{6,0,515},{4,10,747},{6,11,1623},{6,11,1681},{7,10,649},{7,10,\n1479},{135,10,1583},{133,10,232},{135,0,566},{137,10,887},{4,0,40},{10,0,67},{11\n,0,117},{11,0,768},{139,0,935},{132,0,801},{7,0,992},{8,0,301},{9,0,722},{12,0,\n63},{13,0,29},{14,0,161},{143,0,18},{139,0,923},{6,11,1748},{8,11,715},{9,11,802\n},{10,11,46},{10,11,819},{13,11,308},{14,11,351},{14,11,363},{146,11,67},{137,11\n,745},{7,0,1145},{4,10,14},{7,10,1801},{10,10,748},{141,10,458},{4,11,63},{5,11,\n347},{134,11,474},{135,0,568},{4,10,425},{7,11,577},{7,11,1432},{9,11,475},{9,11\n,505},{9,11,526},{9,11,609},{9,11,689},{9,11,726},{9,11,735},{9,11,738},{10,11,\n556},{10,11,674},{10,11,684},{11,11,89},{11,11,202},{11,11,272},{11,11,380},{11,\n11,415},{11,11,505},{11,11,537},{11,11,550},{11,11,562},{11,11,640},{11,11,667},\n{11,11,688},{11,11,847},{11,11,927},{11,11,930},{11,11,940},{12,11,144},{12,11,\n325},{12,11,329},{12,11,389},{12,11,403},{12,11,451},{12,11,515},{12,11,604},{12\n,11,616},{12,11,626},{13,11,66},{13,11,131},{13,11,167},{13,11,236},{13,11,368},\n{13,11,411},{13,11,434},{13,11,453},{13,11,461},{13,11,474},{14,11,59},{14,11,60\n},{14,11,139},{14,11,152},{14,11,276},{14,11,353},{14,11,402},{15,11,28},{15,11,\n81},{15,11,123},{15,11,152},{18,11,136},{148,11,88},{137,0,247},{135,11,1622},{9\n,11,544},{11,11,413},{144,11,25},{4,0,645},{7,0,825},{6,10,1768},{135,11,89},{\n140,0,328},{5,10,943},{134,10,1779},{134,0,1363},{5,10,245},{6,10,576},{7,10,582\n},{136,10,225},{134,0,1280},{5,11,824},{133,11,941},{7,11,440},{8,11,230},{139,\n11,106},{5,0,28},{6,0,204},{10,0,320},{10,0,583},{13,0,502},{14,0,72},{14,0,274}\n,{14,0,312},{14,0,344},{15,0,159},{16,0,62},{16,0,69},{17,0,30},{18,0,42},{18,0,\n53},{18,0,84},{18,0,140},{19,0,68},{19,0,85},{20,0,5},{20,0,45},{20,0,101},{22,0\n,7},{150,0,20},{4,0,558},{6,0,390},{7,0,162},{7,0,689},{9,0,360},{138,0,653},{\n134,0,764},{6,0,862},{137,0,833},{5,0,856},{6,0,1672},{6,0,1757},{134,0,1781},{5\n,0,92},{10,0,736},{140,0,102},{6,0,1927},{6,0,1944},{8,0,924},{8,0,948},{10,0,\n967},{138,0,978},{134,0,1479},{5,0,590},{8,0,360},{9,0,213},{138,0,63},{134,0,\n1521},{6,0,709},{134,0,891},{132,10,443},{13,0,477},{14,0,120},{148,0,61},{4,11,\n914},{5,11,800},{133,11,852},{10,11,54},{141,11,115},{4,11,918},{133,11,876},{\n139,11,152},{4,11,92},{133,11,274},{135,11,1901},{9,11,800},{10,11,693},{11,11,\n482},{11,11,734},{139,11,789},{9,0,483},{132,10,298},{6,0,1213},{141,11,498},{\n135,11,1451},{133,11,743},{4,0,1022},{10,0,1000},{12,0,957},{12,0,980},{12,0,\n1013},{14,0,481},{144,0,116},{8,0,503},{17,0,29},{4,11,49},{7,11,280},{135,11,\n1633},{135,0,1712},{134,0,466},{136,11,47},{5,10,164},{7,10,121},{142,10,189},{7\n,10,812},{7,10,1261},{7,10,1360},{9,10,632},{140,10,352},{139,10,556},{132,0,731\n},{5,11,272},{5,11,908},{5,11,942},{7,11,1008},{7,11,1560},{8,11,197},{9,11,47},\n{11,11,538},{139,11,742},{4,10,172},{9,10,611},{10,10,436},{12,10,673},{141,10,\n255},{133,10,844},{10,0,484},{11,0,754},{12,0,457},{14,0,171},{14,0,389},{146,0,\n153},{9,10,263},{10,10,147},{138,10,492},{137,11,891},{138,0,241},{133,10,537},{\n6,0,2005},{136,0,964},{137,10,842},{151,11,8},{4,11,407},{132,11,560},{135,11,\n1884},{6,0,1100},{134,0,1242},{135,0,954},{5,10,230},{5,10,392},{6,10,420},{9,10\n,568},{140,10,612},{4,11,475},{11,11,35},{11,11,90},{13,11,7},{13,11,71},{13,11,\n177},{142,11,422},{136,11,332},{135,0,1958},{6,0,549},{8,0,34},{8,0,283},{9,0,\n165},{138,0,475},{10,0,952},{12,0,966},{140,0,994},{5,0,652},{5,0,701},{135,0,\n449},{4,0,655},{7,0,850},{17,0,75},{146,0,137},{4,0,146},{7,0,1618},{8,0,670},{5\n,10,41},{7,10,1459},{7,10,1469},{7,10,1859},{9,10,549},{139,10,905},{133,10,696}\n,{6,0,159},{6,0,364},{7,0,516},{137,0,518},{135,0,1439},{6,11,222},{7,11,636},{7\n,11,1620},{8,11,409},{9,11,693},{139,11,77},{13,0,151},{141,11,45},{6,0,1027},{4\n,11,336},{132,10,771},{139,11,392},{10,11,121},{11,11,175},{149,11,16},{8,0,950}\n,{138,0,983},{133,10,921},{135,0,993},{6,10,180},{7,10,1137},{8,10,751},{139,10,\n805},{7,0,501},{9,0,111},{10,0,141},{11,0,332},{13,0,43},{13,0,429},{14,0,130},{\n14,0,415},{145,0,102},{4,10,183},{5,11,882},{7,10,271},{11,10,824},{11,10,952},{\n13,10,278},{13,10,339},{13,10,482},{14,10,424},{148,10,99},{4,10,19},{5,10,477},\n{5,10,596},{6,10,505},{7,10,1221},{11,10,907},{12,10,209},{141,10,214},{135,10,\n1215},{133,0,452},{132,11,426},{5,0,149},{136,0,233},{133,0,935},{6,11,58},{7,11\n,654},{7,11,745},{7,11,1969},{8,11,240},{8,11,675},{9,11,479},{9,11,731},{10,11,\n330},{10,11,593},{10,11,817},{11,11,32},{11,11,133},{11,11,221},{145,11,68},{12,\n0,582},{18,0,131},{7,11,102},{137,11,538},{136,0,801},{134,10,1645},{132,0,70},{\n6,10,92},{6,10,188},{7,10,1269},{7,10,1524},{7,10,1876},{10,10,228},{139,10,1020\n},{4,10,459},{133,10,966},{138,0,369},{16,0,36},{140,10,330},{141,11,366},{7,0,\n721},{10,0,236},{12,0,204},{6,10,18},{7,10,932},{8,10,757},{9,10,54},{9,10,65},{\n9,10,844},{10,10,113},{10,10,315},{10,10,798},{11,10,153},{12,10,151},{12,10,392\n},{12,10,666},{142,10,248},{7,0,241},{10,0,430},{8,10,548},{9,10,532},{10,10,117\n},{11,10,351},{11,10,375},{143,10,23},{134,10,1742},{133,10,965},{133,11,566},{6\n,11,48},{135,11,63},{134,10,182},{10,10,65},{10,10,488},{138,10,497},{6,11,114},\n{7,11,1224},{7,11,1556},{136,11,3},{134,0,1817},{8,11,576},{137,11,267},{6,0,\n1078},{144,0,16},{9,10,588},{138,10,260},{138,0,1021},{5,0,406},{134,0,2022},{\n133,11,933},{6,0,69},{135,0,117},{7,0,1830},{136,11,427},{4,0,432},{135,0,824},{\n134,10,1786},{133,0,826},{139,11,67},{133,11,759},{135,10,308},{137,0,816},{133,\n0,1000},{4,0,297},{6,0,529},{7,0,152},{7,0,713},{7,0,1845},{8,0,710},{8,0,717},{\n12,0,639},{140,0,685},{7,0,423},{136,10,588},{136,10,287},{136,0,510},{134,0,\n1048},{6,0,618},{7,11,56},{7,11,1989},{8,11,337},{8,11,738},{9,11,600},{10,11,\n483},{12,11,37},{13,11,447},{142,11,92},{4,0,520},{135,0,575},{8,0,990},{138,0,\n977},{135,11,774},{9,11,347},{11,11,24},{140,11,170},{136,11,379},{140,10,290},{\n132,11,328},{4,0,321},{134,0,569},{4,11,101},{135,11,1171},{7,0,723},{7,0,1135},\n{5,11,833},{136,11,744},{7,10,719},{8,10,809},{136,10,834},{8,0,921},{136,10,796\n},{5,10,210},{6,10,213},{7,10,60},{10,10,364},{139,10,135},{5,0,397},{6,0,154},{\n7,0,676},{8,0,443},{8,0,609},{9,0,24},{9,0,325},{10,0,35},{11,0,535},{11,0,672},\n{11,0,1018},{12,0,637},{16,0,30},{5,10,607},{8,10,326},{136,10,490},{4,10,701},{\n5,10,472},{6,11,9},{6,11,397},{7,11,53},{7,11,1742},{9,10,758},{10,11,632},{11,\n11,828},{140,11,146},{135,10,380},{135,10,1947},{148,11,109},{10,10,278},{138,11\n,278},{134,0,856},{7,0,139},{4,10,386},{8,10,405},{8,10,728},{9,10,497},{11,10,\n110},{11,10,360},{15,10,37},{144,10,84},{141,0,282},{133,0,981},{5,0,288},{7,10,\n1452},{7,10,1480},{8,10,634},{140,10,472},{7,0,1890},{8,11,367},{10,11,760},{14,\n11,79},{20,11,17},{152,11,0},{4,10,524},{136,10,810},{4,0,56},{7,0,1791},{8,0,\n607},{8,0,651},{11,0,465},{11,0,835},{12,0,337},{141,0,480},{10,10,238},{141,10,\n33},{11,11,417},{12,11,223},{140,11,265},{9,0,158},{10,0,411},{140,0,261},{133,\n10,532},{133,10,997},{12,11,186},{12,11,292},{14,11,100},{146,11,70},{6,0,1403},\n{136,0,617},{134,0,1205},{139,0,563},{4,0,242},{134,0,333},{4,11,186},{5,11,157}\n,{8,11,168},{138,11,6},{132,0,369},{133,11,875},{5,10,782},{5,10,829},{134,10,\n1738},{134,0,622},{135,11,1272},{6,0,1407},{7,11,111},{136,11,581},{7,10,1823},{\n139,10,693},{7,0,160},{10,0,624},{142,0,279},{132,0,363},{10,11,589},{12,11,111}\n,{13,11,260},{14,11,82},{18,11,63},{147,11,45},{7,11,1364},{7,11,1907},{141,11,\n158},{4,11,404},{4,11,659},{135,11,675},{13,11,211},{14,11,133},{14,11,204},{15,\n11,64},{15,11,69},{15,11,114},{16,11,10},{19,11,23},{19,11,35},{19,11,39},{19,11\n,51},{19,11,71},{19,11,75},{152,11,15},{4,10,78},{5,10,96},{5,10,182},{7,10,1724\n},{7,10,1825},{10,10,394},{10,10,471},{11,10,532},{14,10,340},{145,10,88},{135,\n10,1964},{133,11,391},{11,11,887},{14,11,365},{142,11,375},{5,11,540},{6,11,1697\n},{7,11,222},{136,11,341},{134,11,78},{9,0,601},{9,0,619},{10,0,505},{10,0,732},\n{11,0,355},{140,0,139},{134,0,292},{139,0,174},{5,0,177},{6,0,616},{7,0,827},{9,\n0,525},{138,0,656},{10,0,31},{6,10,215},{7,10,1028},{7,10,1473},{7,10,1721},{9,\n10,424},{138,10,779},{135,10,584},{136,11,293},{134,0,685},{135,11,1868},{133,11\n,460},{7,0,647},{6,10,67},{7,10,1630},{9,10,354},{9,10,675},{10,10,830},{14,10,\n80},{145,10,80},{4,0,161},{133,0,631},{6,10,141},{7,10,225},{9,10,59},{9,10,607}\n,{10,10,312},{11,10,687},{12,10,555},{13,10,373},{13,10,494},{148,10,58},{7,11,\n965},{7,11,1460},{135,11,1604},{136,10,783},{134,11,388},{6,0,722},{6,0,1267},{4\n,11,511},{9,11,333},{9,11,379},{10,11,602},{11,11,441},{11,11,723},{11,11,976},{\n140,11,357},{134,0,1797},{135,0,1684},{9,0,469},{9,0,709},{12,0,512},{14,0,65},{\n17,0,12},{5,11,938},{136,11,707},{7,0,1230},{136,0,531},{10,0,229},{11,0,73},{11\n,0,376},{139,0,433},{12,0,268},{12,0,640},{142,0,119},{7,10,430},{139,10,46},{6,\n0,558},{7,0,651},{8,0,421},{9,0,0},{10,0,34},{139,0,1008},{6,0,106},{7,0,1786},{\n7,0,1821},{9,0,102},{9,0,763},{5,10,602},{7,10,2018},{137,10,418},{5,0,65},{6,0,\n416},{7,0,1720},{7,0,1924},{10,0,109},{11,0,14},{11,0,70},{11,0,569},{11,0,735},\n{15,0,153},{20,0,80},{136,10,677},{135,11,1625},{137,11,772},{136,0,595},{6,11,\n469},{7,11,1709},{138,11,515},{7,0,1832},{138,0,374},{9,0,106},{9,0,163},{9,0,\n296},{10,0,167},{10,0,172},{10,0,777},{139,0,16},{6,0,6},{7,0,81},{7,0,771},{7,0\n,1731},{9,0,405},{138,0,421},{4,11,500},{135,11,938},{5,11,68},{134,11,383},{5,0\n,881},{133,0,885},{6,0,854},{6,0,1132},{6,0,1495},{6,0,1526},{6,0,1533},{134,0,\n1577},{4,11,337},{6,11,353},{7,11,1934},{8,11,488},{137,11,429},{7,11,236},{7,11\n,1795},{8,11,259},{9,11,135},{9,11,177},{10,11,825},{11,11,115},{11,11,370},{11,\n11,405},{11,11,604},{12,11,10},{12,11,667},{12,11,669},{13,11,76},{14,11,310},{\n15,11,76},{15,11,147},{148,11,23},{5,0,142},{134,0,546},{4,11,15},{5,11,22},{6,\n11,244},{7,11,40},{7,11,200},{7,11,906},{7,11,1199},{9,11,616},{10,11,716},{11,\n11,635},{11,11,801},{140,11,458},{5,0,466},{11,0,571},{12,0,198},{13,0,283},{14,\n0,186},{15,0,21},{15,0,103},{135,10,329},{4,0,185},{5,0,257},{5,0,839},{5,0,936}\n,{9,0,399},{10,0,258},{10,0,395},{10,0,734},{11,0,1014},{12,0,23},{13,0,350},{14\n,0,150},{19,0,6},{135,11,1735},{12,11,36},{141,11,337},{5,11,598},{7,11,791},{8,\n11,108},{137,11,123},{132,10,469},{7,0,404},{7,0,1377},{7,0,1430},{7,0,2017},{8,\n0,149},{8,0,239},{8,0,512},{8,0,793},{8,0,818},{9,0,474},{9,0,595},{10,0,122},{\n10,0,565},{10,0,649},{10,0,783},{11,0,239},{11,0,295},{11,0,447},{11,0,528},{11,\n0,639},{11,0,800},{12,0,25},{12,0,77},{12,0,157},{12,0,256},{12,0,316},{12,0,390\n},{12,0,391},{12,0,395},{12,0,478},{12,0,503},{12,0,592},{12,0,680},{13,0,50},{\n13,0,53},{13,0,132},{13,0,198},{13,0,322},{13,0,415},{13,0,511},{14,0,71},{14,0,\n395},{15,0,71},{15,0,136},{17,0,123},{18,0,93},{147,0,58},{136,0,712},{134,10,\n1743},{5,10,929},{6,10,340},{8,10,376},{136,10,807},{6,0,1848},{8,0,860},{10,0,\n856},{10,0,859},{10,0,925},{10,0,941},{140,0,762},{6,0,629},{6,0,906},{9,0,810},\n{140,0,652},{5,10,218},{7,10,1610},{138,10,83},{7,10,1512},{135,10,1794},{4,0,\n377},{24,0,13},{4,11,155},{7,11,1689},{11,10,0},{144,10,78},{4,11,164},{5,11,151\n},{5,11,730},{5,11,741},{7,11,498},{7,11,870},{7,11,1542},{12,11,213},{14,11,36}\n,{14,11,391},{17,11,111},{18,11,6},{18,11,46},{18,11,151},{19,11,36},{20,11,32},\n{20,11,56},{20,11,69},{20,11,102},{21,11,4},{22,11,8},{22,11,10},{22,11,14},{150\n,11,31},{7,0,1842},{133,10,571},{4,10,455},{4,11,624},{135,11,1752},{134,0,1501}\n,{4,11,492},{5,11,451},{6,10,161},{7,10,372},{137,10,597},{132,10,349},{4,0,180}\n,{135,0,1906},{135,11,835},{141,11,70},{132,0,491},{137,10,751},{6,10,432},{139,\n10,322},{4,0,171},{138,0,234},{6,11,113},{135,11,436},{4,0,586},{7,0,1186},{138,\n0,631},{5,10,468},{10,10,325},{11,10,856},{12,10,345},{143,10,104},{5,10,223},{\n10,11,592},{10,11,753},{12,11,317},{12,11,355},{12,11,465},{12,11,469},{12,11,\n560},{12,11,578},{141,11,243},{132,10,566},{135,11,520},{4,10,59},{135,10,1394},\n{6,10,436},{139,10,481},{9,0,931},{10,0,334},{20,0,71},{4,10,48},{5,10,271},{7,\n10,953},{135,11,1878},{11,0,170},{5,10,610},{136,10,457},{133,10,755},{6,0,1587}\n,{135,10,1217},{4,10,197},{149,11,26},{133,11,585},{137,11,521},{133,0,765},{133\n,10,217},{139,11,586},{133,0,424},{9,11,752},{12,11,610},{13,11,431},{16,11,59},\n{146,11,109},{136,0,714},{7,0,685},{132,11,307},{9,0,420},{10,0,269},{10,0,285},\n{10,0,576},{11,0,397},{13,0,175},{145,0,90},{132,0,429},{133,11,964},{9,11,463},\n{138,11,595},{7,0,18},{7,0,699},{7,0,1966},{8,0,752},{9,0,273},{9,0,412},{9,0,\n703},{10,0,71},{10,0,427},{138,0,508},{4,10,165},{7,10,1398},{135,10,1829},{4,0,\n53},{5,0,186},{7,0,752},{7,0,828},{142,0,116},{8,0,575},{10,0,289},{139,0,319},{\n132,0,675},{134,0,1424},{4,11,75},{5,11,180},{6,11,500},{7,11,58},{7,11,710},{\n138,11,645},{133,11,649},{6,11,276},{7,11,282},{7,11,879},{7,11,924},{8,11,459},\n{9,11,599},{9,11,754},{11,11,574},{12,11,128},{12,11,494},{13,11,52},{13,11,301}\n,{15,11,30},{143,11,132},{6,0,647},{134,0,1095},{5,10,9},{7,10,297},{7,10,966},{\n140,10,306},{132,11,200},{134,0,1334},{5,10,146},{6,10,411},{138,10,721},{6,0,\n209},{6,0,1141},{6,0,1288},{8,0,468},{9,0,210},{11,0,36},{12,0,28},{12,0,630},{\n13,0,21},{13,0,349},{14,0,7},{145,0,13},{6,10,177},{135,10,467},{4,0,342},{135,0\n,1179},{10,11,454},{140,11,324},{4,0,928},{133,0,910},{7,0,1838},{6,11,225},{137\n,11,211},{16,0,101},{20,0,115},{20,0,118},{148,0,122},{4,0,496},{135,0,856},{4,0\n,318},{11,0,654},{7,11,718},{139,11,102},{8,11,58},{9,11,724},{11,11,809},{13,11\n,113},{145,11,72},{5,10,200},{6,11,345},{135,11,1247},{8,11,767},{8,11,803},{9,\n11,301},{137,11,903},{7,0,915},{8,0,247},{19,0,0},{7,11,1949},{136,11,674},{4,0,\n202},{5,0,382},{6,0,454},{7,0,936},{7,0,1803},{8,0,758},{9,0,375},{9,0,895},{10,\n0,743},{10,0,792},{11,0,978},{11,0,1012},{142,0,109},{7,0,1150},{7,0,1425},{7,0,\n1453},{140,0,513},{134,11,259},{138,0,791},{11,0,821},{12,0,110},{12,0,153},{18,\n0,41},{150,0,19},{134,10,481},{132,0,796},{6,0,445},{9,0,909},{136,11,254},{10,0\n,776},{13,0,345},{142,0,425},{4,10,84},{7,10,1482},{10,10,76},{138,10,142},{135,\n11,742},{6,0,578},{133,10,1015},{6,0,1387},{4,10,315},{5,10,507},{135,10,1370},{\n4,0,438},{133,0,555},{136,0,766},{133,11,248},{134,10,1722},{4,11,116},{5,11,95}\n,{5,11,445},{7,11,1688},{8,11,29},{9,11,272},{11,11,509},{139,11,915},{135,0,541\n},{133,11,543},{8,10,222},{8,10,476},{9,10,238},{11,10,516},{11,10,575},{15,10,\n109},{146,10,100},{6,0,880},{134,0,1191},{5,11,181},{136,11,41},{134,0,1506},{\n132,11,681},{7,11,25},{8,11,202},{138,11,536},{139,0,983},{137,0,768},{132,0,584\n},{9,11,423},{140,11,89},{8,11,113},{9,11,877},{10,11,554},{11,11,83},{12,11,136\n},{147,11,109},{7,10,706},{7,10,1058},{138,10,538},{133,11,976},{4,11,206},{135,\n11,746},{136,11,526},{140,0,737},{11,10,92},{11,10,196},{11,10,409},{11,10,450},\n{11,10,666},{11,10,777},{12,10,262},{13,10,385},{13,10,393},{15,10,115},{16,10,\n45},{145,10,82},{4,0,226},{4,0,326},{7,0,1770},{4,11,319},{5,11,699},{138,11,673\n},{6,10,40},{135,10,1781},{5,0,426},{8,0,30},{9,0,2},{11,0,549},{147,0,122},{6,0\n,1161},{134,0,1329},{138,10,97},{6,10,423},{7,10,665},{135,10,1210},{7,11,13},{8\n,11,226},{10,11,537},{11,11,570},{11,11,605},{11,11,799},{11,11,804},{12,11,85},\n{12,11,516},{12,11,623},{13,11,112},{13,11,361},{14,11,77},{14,11,78},{17,11,28}\n,{147,11,110},{132,11,769},{132,11,551},{132,11,728},{147,0,117},{9,11,57},{9,11\n,459},{10,11,425},{11,11,119},{12,11,184},{12,11,371},{13,11,358},{145,11,51},{5\n,11,188},{5,11,814},{8,11,10},{9,11,421},{9,11,729},{10,11,609},{139,11,689},{\n134,11,624},{135,11,298},{135,0,462},{4,0,345},{139,10,624},{136,10,574},{4,0,\n385},{7,0,265},{135,0,587},{6,0,808},{132,11,528},{133,0,398},{132,10,354},{4,0,\n347},{5,0,423},{5,0,996},{135,0,1329},{135,10,1558},{7,0,1259},{9,0,125},{139,0,\n65},{5,0,136},{6,0,136},{136,0,644},{5,11,104},{6,11,173},{135,11,1631},{135,0,\n469},{133,10,830},{4,0,278},{5,0,465},{135,0,1367},{7,11,810},{8,11,138},{8,11,\n342},{9,11,84},{10,11,193},{11,11,883},{140,11,359},{5,10,496},{135,10,203},{4,0\n,433},{133,0,719},{6,11,95},{134,10,547},{5,10,88},{137,10,239},{6,11,406},{10,\n11,409},{10,11,447},{11,11,44},{140,11,100},{134,0,1423},{7,10,650},{135,10,1310\n},{134,0,749},{135,11,1243},{135,0,1363},{6,0,381},{7,0,645},{7,0,694},{8,0,546}\n,{7,10,1076},{9,10,80},{11,10,78},{11,10,421},{11,10,534},{140,10,545},{134,11,\n1636},{135,11,1344},{12,0,277},{7,10,274},{11,10,479},{139,10,507},{6,0,705},{6,\n0,783},{6,0,1275},{6,0,1481},{4,11,282},{7,11,1034},{11,11,398},{11,11,634},{12,\n11,1},{12,11,79},{12,11,544},{14,11,237},{17,11,10},{146,11,20},{134,0,453},{4,0\n,555},{8,0,536},{10,0,288},{11,0,1005},{4,10,497},{135,10,1584},{5,11,118},{5,11\n,499},{6,11,476},{7,11,600},{7,11,888},{135,11,1096},{138,0,987},{7,0,1107},{7,\n10,261},{7,10,1115},{7,10,1354},{7,10,1588},{7,10,1705},{7,10,1902},{9,10,465},{\n10,10,248},{10,10,349},{10,10,647},{11,10,527},{11,10,660},{11,10,669},{12,10,\n529},{141,10,305},{7,11,296},{7,11,596},{8,11,560},{8,11,586},{9,11,612},{11,11,\n100},{11,11,304},{12,11,46},{13,11,89},{14,11,112},{145,11,122},{9,0,370},{138,0\n,90},{136,10,13},{132,0,860},{7,10,642},{8,10,250},{11,10,123},{11,10,137},{13,\n10,48},{142,10,95},{135,10,1429},{137,11,321},{132,0,257},{135,0,2031},{7,0,1768\n},{7,11,1599},{7,11,1723},{8,11,79},{8,11,106},{8,11,190},{8,11,302},{8,11,383},\n{9,11,119},{9,11,233},{9,11,298},{9,11,419},{9,11,471},{10,11,181},{10,11,406},{\n11,11,57},{11,11,85},{11,11,120},{11,11,177},{11,11,296},{11,11,382},{11,11,454}\n,{11,11,758},{11,11,999},{12,11,27},{12,11,98},{12,11,131},{12,11,245},{12,11,\n312},{12,11,446},{12,11,454},{13,11,25},{13,11,98},{13,11,426},{13,11,508},{14,\n11,6},{14,11,163},{14,11,272},{14,11,277},{14,11,370},{15,11,95},{15,11,138},{15\n,11,167},{17,11,18},{17,11,38},{20,11,96},{149,11,32},{5,11,722},{134,11,1759},{\n145,11,16},{6,0,1071},{134,0,1561},{10,10,545},{140,10,301},{6,0,83},{6,0,1733},\n{135,0,1389},{4,0,835},{135,0,1818},{133,11,258},{4,10,904},{133,10,794},{134,0,\n2006},{5,11,30},{7,11,495},{8,11,134},{9,11,788},{140,11,438},{135,11,2004},{137\n,0,696},{5,11,50},{6,11,439},{7,11,780},{135,11,1040},{7,11,772},{7,11,1104},{7,\n11,1647},{11,11,269},{11,11,539},{11,11,607},{11,11,627},{11,11,706},{11,11,975}\n,{12,11,248},{12,11,311},{12,11,434},{12,11,600},{12,11,622},{13,11,297},{13,11,\n367},{13,11,485},{14,11,69},{14,11,409},{143,11,108},{5,11,1},{6,11,81},{138,11,\n520},{7,0,1718},{9,0,95},{9,0,274},{10,0,279},{10,0,317},{10,0,420},{11,0,303},{\n11,0,808},{12,0,134},{12,0,367},{13,0,149},{13,0,347},{14,0,349},{14,0,406},{18,\n0,22},{18,0,89},{18,0,122},{147,0,47},{5,11,482},{8,11,98},{9,11,172},{10,11,222\n},{10,11,700},{10,11,822},{11,11,302},{11,11,778},{12,11,50},{12,11,127},{12,11,\n396},{13,11,62},{13,11,328},{14,11,122},{147,11,72},{7,10,386},{138,10,713},{6,\n10,7},{6,10,35},{7,10,147},{7,10,1069},{7,10,1568},{7,10,1575},{7,10,1917},{8,10\n,43},{8,10,208},{9,10,128},{9,10,866},{10,10,20},{11,10,981},{147,10,33},{133,0,\n26},{132,0,550},{5,11,2},{7,11,1494},{136,11,589},{6,11,512},{7,11,797},{8,11,\n253},{9,11,77},{10,11,1},{10,11,129},{10,11,225},{11,11,118},{11,11,226},{11,11,\n251},{11,11,430},{11,11,701},{11,11,974},{11,11,982},{12,11,64},{12,11,260},{12,\n11,488},{140,11,690},{7,10,893},{141,10,424},{134,0,901},{136,0,822},{4,0,902},{\n5,0,809},{134,0,122},{6,0,807},{134,0,1366},{7,0,262},{5,11,748},{134,11,553},{\n133,0,620},{4,0,34},{5,0,574},{7,0,279},{7,0,1624},{136,0,601},{9,0,170},{6,10,\n322},{9,10,552},{11,10,274},{13,10,209},{13,10,499},{14,10,85},{15,10,126},{145,\n10,70},{132,0,537},{4,11,12},{7,11,420},{7,11,522},{7,11,809},{8,11,797},{141,11\n,88},{133,0,332},{8,10,83},{8,10,742},{8,10,817},{9,10,28},{9,10,29},{9,10,885},\n{10,10,387},{11,10,633},{11,10,740},{13,10,235},{13,10,254},{15,10,143},{143,10,\n146},{6,0,1909},{9,0,964},{12,0,822},{12,0,854},{12,0,865},{12,0,910},{12,0,938}\n,{15,0,169},{15,0,208},{15,0,211},{18,0,205},{18,0,206},{18,0,220},{18,0,223},{\n152,0,24},{140,10,49},{5,11,528},{135,11,1580},{6,0,261},{8,0,182},{139,0,943},{\n134,0,1721},{4,0,933},{133,0,880},{136,11,321},{5,11,266},{9,11,290},{9,11,364},\n{10,11,293},{11,11,606},{142,11,45},{6,0,1609},{4,11,50},{6,11,510},{6,11,594},{\n9,11,121},{10,11,49},{10,11,412},{139,11,834},{7,0,895},{136,11,748},{132,11,466\n},{4,10,110},{10,10,415},{10,10,597},{142,10,206},{133,0,812},{135,11,281},{6,0,\n1890},{6,0,1902},{6,0,1916},{9,0,929},{9,0,942},{9,0,975},{9,0,984},{9,0,986},{9\n,0,1011},{9,0,1019},{12,0,804},{12,0,851},{12,0,867},{12,0,916},{12,0,923},{15,0\n,194},{15,0,204},{15,0,210},{15,0,222},{15,0,223},{15,0,229},{15,0,250},{18,0,\n179},{18,0,186},{18,0,192},{7,10,205},{135,10,2000},{132,11,667},{135,0,778},{4,\n0,137},{7,0,1178},{135,0,1520},{134,0,1314},{4,11,242},{134,11,333},{6,0,1661},{\n7,0,1975},{7,0,2009},{135,0,2011},{134,0,1591},{4,10,283},{135,10,1194},{11,0,\n820},{150,0,51},{4,11,39},{5,11,36},{7,11,1843},{8,11,407},{11,11,144},{140,11,\n523},{134,10,1720},{4,11,510},{7,11,29},{7,11,66},{7,11,1980},{10,11,487},{10,11\n,809},{146,11,9},{5,0,89},{7,0,1915},{9,0,185},{9,0,235},{10,0,64},{10,0,270},{\n10,0,403},{10,0,469},{10,0,529},{10,0,590},{11,0,140},{11,0,860},{13,0,1},{13,0,\n422},{14,0,341},{14,0,364},{17,0,93},{18,0,113},{19,0,97},{147,0,113},{133,0,695\n},{6,0,987},{134,0,1160},{5,0,6},{6,0,183},{7,0,680},{7,0,978},{7,0,1013},{7,0,\n1055},{12,0,230},{13,0,172},{146,0,29},{134,11,570},{132,11,787},{134,11,518},{6\n,0,29},{139,0,63},{132,11,516},{136,11,821},{132,0,311},{134,0,1740},{7,0,170},{\n8,0,90},{8,0,177},{8,0,415},{11,0,714},{14,0,281},{136,10,735},{134,0,1961},{135\n,11,1405},{4,11,10},{7,11,917},{139,11,786},{5,10,132},{9,10,486},{9,10,715},{10\n,10,458},{11,10,373},{11,10,668},{11,10,795},{11,10,897},{12,10,272},{12,10,424}\n,{12,10,539},{12,10,558},{14,10,245},{14,10,263},{14,10,264},{14,10,393},{142,10\n,403},{11,0,91},{13,0,129},{15,0,101},{145,0,125},{135,0,1132},{4,0,494},{6,0,74\n},{7,0,44},{7,0,407},{12,0,17},{15,0,5},{148,0,11},{133,10,379},{5,0,270},{5,11,\n684},{6,10,89},{6,10,400},{7,10,1569},{7,10,1623},{7,10,1850},{8,10,218},{8,10,\n422},{9,10,570},{138,10,626},{4,0,276},{133,0,296},{6,0,1523},{134,11,27},{6,10,\n387},{7,10,882},{141,10,111},{6,10,224},{7,10,877},{137,10,647},{135,10,790},{4,\n0,7},{5,0,90},{5,0,158},{6,0,542},{7,0,221},{7,0,1574},{9,0,490},{10,0,540},{11,\n0,443},{139,0,757},{7,0,588},{9,0,175},{138,0,530},{135,10,394},{142,11,23},{134\n,0,786},{135,0,580},{7,0,88},{136,0,627},{5,0,872},{6,0,57},{7,0,471},{9,0,447},\n{137,0,454},{6,11,342},{6,11,496},{8,11,275},{137,11,206},{4,11,909},{133,11,940\n},{6,0,735},{132,11,891},{8,0,845},{8,0,916},{135,10,1409},{5,0,31},{134,0,614},\n{11,0,458},{12,0,15},{140,0,432},{8,0,330},{140,0,477},{4,0,530},{5,0,521},{7,0,\n1200},{10,0,460},{132,11,687},{6,0,424},{135,0,1866},{9,0,569},{12,0,12},{12,0,\n81},{12,0,319},{13,0,69},{14,0,259},{16,0,87},{17,0,1},{17,0,21},{17,0,24},{18,0\n,15},{18,0,56},{18,0,59},{18,0,127},{18,0,154},{19,0,19},{148,0,31},{7,0,1302},{\n136,10,38},{134,11,253},{5,10,261},{7,10,78},{7,10,199},{8,10,815},{9,10,126},{\n138,10,342},{5,0,595},{135,0,1863},{6,11,41},{141,11,160},{5,0,13},{134,0,142},{\n6,0,97},{7,0,116},{8,0,322},{8,0,755},{9,0,548},{10,0,714},{11,0,884},{13,0,324}\n,{7,11,1304},{138,11,477},{132,10,628},{134,11,1718},{7,10,266},{136,10,804},{\n135,10,208},{7,0,1021},{6,10,79},{135,10,1519},{7,0,1472},{135,0,1554},{6,11,362\n},{146,11,51},{7,0,1071},{7,0,1541},{7,0,1767},{7,0,1806},{11,0,162},{11,0,242},\n{11,0,452},{12,0,605},{15,0,26},{144,0,44},{136,10,741},{133,11,115},{145,0,115}\n,{134,10,376},{6,0,1406},{134,0,1543},{5,11,193},{12,11,178},{13,11,130},{145,11\n,84},{135,0,1111},{8,0,1},{9,0,650},{10,0,326},{5,11,705},{137,11,606},{5,0,488}\n,{6,0,527},{7,0,489},{7,0,1636},{8,0,121},{8,0,144},{8,0,359},{9,0,193},{9,0,241\n},{9,0,336},{9,0,882},{11,0,266},{11,0,372},{11,0,944},{12,0,401},{140,0,641},{\n135,11,174},{6,0,267},{7,10,244},{7,10,632},{7,10,1609},{8,10,178},{8,10,638},{\n141,10,58},{134,0,1983},{134,0,1155},{134,0,1575},{134,0,1438},{9,0,31},{10,0,\n244},{10,0,699},{12,0,149},{141,0,497},{133,0,377},{4,11,122},{5,11,796},{5,11,\n952},{6,11,1660},{6,11,1671},{8,11,567},{9,11,687},{9,11,742},{10,11,686},{11,11\n,356},{11,11,682},{140,11,281},{145,0,101},{11,11,0},{144,11,78},{5,11,179},{5,\n10,791},{7,11,1095},{135,11,1213},{8,11,372},{9,11,122},{138,11,175},{7,10,686},\n{8,10,33},{8,10,238},{10,10,616},{11,10,467},{11,10,881},{13,10,217},{13,10,253}\n,{142,10,268},{9,0,476},{4,11,66},{7,11,722},{135,11,904},{7,11,352},{137,11,684\n},{135,0,2023},{135,0,1836},{132,10,447},{5,0,843},{144,0,35},{137,11,779},{141,\n11,35},{4,10,128},{5,10,415},{6,10,462},{7,10,294},{7,10,578},{10,10,710},{139,\n10,86},{132,0,554},{133,0,536},{136,10,587},{5,0,207},{9,0,79},{11,0,625},{145,0\n,7},{7,0,1371},{6,10,427},{138,10,692},{4,0,424},{4,10,195},{135,10,802},{8,0,\n785},{133,11,564},{135,0,336},{4,0,896},{6,0,1777},{134,11,556},{137,11,103},{\n134,10,1683},{7,11,544},{8,11,719},{138,11,61},{138,10,472},{4,11,5},{5,11,498},\n{136,11,637},{7,0,750},{9,0,223},{11,0,27},{11,0,466},{12,0,624},{14,0,265},{146\n,0,61},{12,0,238},{18,0,155},{12,11,238},{146,11,155},{151,10,28},{133,11,927},{\n12,0,383},{5,10,3},{8,10,578},{9,10,118},{10,10,705},{141,10,279},{4,11,893},{5,\n11,780},{133,11,893},{4,0,603},{133,0,661},{4,0,11},{6,0,128},{7,0,231},{7,0,\n1533},{10,0,725},{5,10,229},{5,11,238},{135,11,1350},{8,10,102},{10,10,578},{10,\n10,672},{12,10,496},{13,10,408},{14,10,121},{145,10,106},{132,0,476},{134,0,1552\n},{134,11,1729},{8,10,115},{8,10,350},{9,10,489},{10,10,128},{11,10,306},{12,10,\n373},{14,10,30},{17,10,79},{19,10,80},{150,10,55},{135,0,1807},{4,0,680},{4,11,\n60},{7,11,760},{7,11,1800},{8,11,314},{9,11,700},{139,11,487},{4,10,230},{5,10,\n702},{148,11,94},{132,11,228},{139,0,435},{9,0,20},{10,0,324},{10,0,807},{139,0,\n488},{6,10,1728},{136,11,419},{4,10,484},{18,10,26},{19,10,42},{20,10,43},{21,10\n,0},{23,10,27},{152,10,14},{135,0,1431},{133,11,828},{5,0,112},{6,0,103},{6,0,\n150},{7,0,1303},{9,0,292},{10,0,481},{20,0,13},{7,11,176},{7,11,178},{7,11,1110}\n,{10,11,481},{148,11,13},{138,0,356},{4,11,51},{5,11,39},{6,11,4},{7,11,591},{7,\n11,849},{7,11,951},{7,11,1129},{7,11,1613},{7,11,1760},{7,11,1988},{9,11,434},{\n10,11,754},{11,11,25},{11,11,37},{139,11,414},{6,0,1963},{134,0,2000},{132,10,\n633},{6,0,1244},{133,11,902},{135,11,928},{140,0,18},{138,0,204},{135,11,1173},{\n134,0,867},{4,0,708},{8,0,15},{9,0,50},{9,0,386},{11,0,18},{11,0,529},{140,0,228\n},{134,11,270},{4,0,563},{7,0,109},{7,0,592},{7,0,637},{7,0,770},{8,0,463},{9,0,\n60},{9,0,335},{9,0,904},{10,0,73},{11,0,434},{12,0,585},{13,0,331},{18,0,110},{\n148,0,60},{132,0,502},{14,11,359},{19,11,52},{148,11,47},{6,11,377},{7,11,1025},\n{9,11,613},{145,11,104},{6,0,347},{10,0,161},{5,10,70},{5,10,622},{6,10,334},{7,\n10,1032},{9,10,171},{11,10,26},{11,10,213},{11,10,637},{11,10,707},{12,10,202},{\n12,10,380},{13,10,226},{13,10,355},{14,10,222},{145,10,42},{132,11,416},{4,0,33}\n,{5,0,102},{6,0,284},{7,0,1079},{7,0,1423},{7,0,1702},{8,0,470},{9,0,554},{9,0,\n723},{11,0,333},{142,11,372},{5,11,152},{5,11,197},{7,11,340},{7,11,867},{10,11,\n548},{10,11,581},{11,11,6},{12,11,3},{12,11,19},{14,11,110},{142,11,289},{7,0,\n246},{135,0,840},{6,0,10},{8,0,571},{9,0,739},{143,0,91},{6,0,465},{7,0,1465},{4\n,10,23},{4,10,141},{5,10,313},{5,10,1014},{6,10,50},{7,10,142},{7,10,559},{8,10,\n640},{9,10,460},{9,10,783},{11,10,741},{12,10,183},{141,10,488},{133,0,626},{136\n,0,614},{138,0,237},{7,11,34},{7,11,190},{8,11,28},{8,11,141},{8,11,444},{8,11,\n811},{9,11,468},{11,11,334},{12,11,24},{12,11,386},{140,11,576},{133,11,757},{5,\n0,18},{6,0,526},{13,0,24},{13,0,110},{19,0,5},{147,0,44},{6,0,506},{134,11,506},\n{135,11,1553},{4,0,309},{5,0,462},{7,0,970},{7,0,1097},{22,0,30},{22,0,33},{7,11\n,1385},{11,11,582},{11,11,650},{11,11,901},{11,11,949},{12,11,232},{12,11,236},{\n13,11,413},{13,11,501},{146,11,116},{9,0,140},{5,10,222},{138,10,534},{6,0,1056}\n,{137,10,906},{134,0,1704},{138,10,503},{134,0,1036},{5,10,154},{7,10,1491},{10,\n10,379},{138,10,485},{4,11,383},{133,10,716},{134,0,1315},{5,0,86},{7,0,743},{9,\n0,85},{10,0,281},{10,0,432},{11,0,825},{12,0,251},{13,0,118},{142,0,378},{8,0,\n264},{4,10,91},{5,10,388},{5,10,845},{6,10,206},{6,10,252},{6,10,365},{7,10,136}\n,{7,10,531},{136,10,621},{5,0,524},{133,0,744},{5,11,277},{141,11,247},{132,11,\n435},{10,0,107},{140,0,436},{132,0,927},{10,0,123},{12,0,670},{146,0,94},{7,0,\n1149},{9,0,156},{138,0,957},{5,11,265},{6,11,212},{135,11,28},{133,0,778},{133,0\n,502},{8,0,196},{10,0,283},{139,0,406},{135,10,576},{136,11,535},{134,0,1312},{5\n,10,771},{5,10,863},{5,10,898},{6,10,1632},{6,10,1644},{134,10,1780},{5,0,855},{\n5,10,331},{135,11,1487},{132,11,702},{5,11,808},{135,11,2045},{7,0,1400},{9,0,\n446},{138,0,45},{140,10,632},{132,0,1003},{5,11,166},{8,11,739},{140,11,511},{5,\n10,107},{7,10,201},{136,10,518},{6,10,446},{135,10,1817},{134,0,1532},{134,0,\n1097},{4,11,119},{5,11,170},{5,11,447},{7,11,1708},{7,11,1889},{9,11,357},{9,11,\n719},{12,11,486},{140,11,596},{9,10,851},{141,10,510},{7,0,612},{8,0,545},{8,0,\n568},{8,0,642},{9,0,717},{10,0,541},{10,0,763},{11,0,449},{12,0,489},{13,0,153},\n{13,0,296},{14,0,138},{14,0,392},{15,0,50},{16,0,6},{16,0,12},{20,0,9},{132,10,\n504},{4,11,450},{135,11,1158},{11,0,54},{13,0,173},{13,0,294},{5,10,883},{5,10,\n975},{8,10,392},{148,10,7},{13,0,455},{15,0,99},{15,0,129},{144,0,68},{135,0,172\n},{132,11,754},{5,10,922},{134,10,1707},{134,0,1029},{17,11,39},{148,11,36},{4,0\n,568},{5,10,993},{7,10,515},{137,10,91},{132,0,732},{10,0,617},{138,11,617},{134\n,0,974},{7,0,989},{10,0,377},{12,0,363},{13,0,68},{13,0,94},{14,0,108},{142,0,\n306},{136,0,733},{132,0,428},{7,0,1789},{135,11,1062},{7,0,2015},{140,0,665},{\n135,10,1433},{5,0,287},{7,10,921},{8,10,580},{8,10,593},{8,10,630},{138,10,28},{\n138,0,806},{4,10,911},{5,10,867},{5,10,1013},{7,10,2034},{8,10,798},{136,10,813}\n,{134,0,1539},{8,11,523},{150,11,34},{135,11,740},{7,11,238},{7,11,2033},{8,11,\n120},{8,11,188},{8,11,659},{9,11,598},{10,11,466},{12,11,342},{12,11,588},{13,11\n,503},{14,11,246},{143,11,92},{7,0,1563},{141,0,182},{5,10,135},{6,10,519},{7,10\n,1722},{10,10,271},{11,10,261},{145,10,54},{14,10,338},{148,10,81},{7,0,484},{4,\n10,300},{133,10,436},{145,11,114},{6,0,1623},{134,0,1681},{133,11,640},{4,11,201\n},{7,11,1744},{8,11,602},{11,11,247},{11,11,826},{145,11,65},{8,11,164},{146,11,\n62},{6,0,1833},{6,0,1861},{136,0,878},{134,0,1569},{8,10,357},{10,10,745},{14,10\n,426},{17,10,94},{147,10,57},{12,0,93},{12,0,501},{13,0,362},{14,0,151},{15,0,40\n},{15,0,59},{16,0,46},{17,0,25},{18,0,14},{18,0,134},{19,0,25},{19,0,69},{20,0,\n16},{20,0,19},{20,0,66},{21,0,23},{21,0,25},{150,0,42},{6,0,1748},{8,0,715},{9,0\n,802},{10,0,46},{10,0,819},{13,0,308},{14,0,351},{14,0,363},{146,0,67},{132,0,\n994},{4,0,63},{133,0,347},{132,0,591},{133,0,749},{7,11,1577},{10,11,304},{10,11\n,549},{11,11,424},{12,11,365},{13,11,220},{13,11,240},{142,11,33},{133,0,366},{7\n,0,557},{12,0,547},{14,0,86},{133,10,387},{135,0,1747},{132,11,907},{5,11,100},{\n10,11,329},{12,11,416},{149,11,29},{4,10,6},{5,10,708},{136,10,75},{7,10,1351},{\n9,10,581},{10,10,639},{11,10,453},{140,10,584},{7,0,89},{132,10,303},{138,10,772\n},{132,11,176},{5,11,636},{5,11,998},{8,11,26},{137,11,358},{7,11,9},{7,11,1508}\n,{9,11,317},{10,11,210},{10,11,292},{10,11,533},{11,11,555},{12,11,526},{12,11,\n607},{13,11,263},{13,11,459},{142,11,271},{134,0,1463},{6,0,772},{6,0,1137},{139\n,11,595},{7,0,977},{139,11,66},{138,0,893},{20,0,48},{148,11,48},{5,0,824},{133,\n0,941},{134,11,295},{7,0,1543},{7,0,1785},{10,0,690},{4,10,106},{139,10,717},{7,\n0,440},{8,0,230},{139,0,106},{5,10,890},{133,10,988},{6,10,626},{142,10,431},{10\n,11,127},{141,11,27},{17,0,32},{10,10,706},{150,10,44},{132,0,216},{137,0,332},{\n4,10,698},{136,11,119},{139,11,267},{138,10,17},{11,11,526},{11,11,939},{141,11,\n290},{7,11,1167},{11,11,934},{13,11,391},{145,11,76},{139,11,39},{134,10,84},{4,\n0,914},{5,0,800},{133,0,852},{10,0,416},{141,0,115},{7,0,564},{142,0,168},{4,0,\n918},{133,0,876},{134,0,1764},{152,0,3},{4,0,92},{5,0,274},{7,11,126},{136,11,84\n},{140,10,498},{136,11,790},{8,0,501},{5,10,986},{6,10,130},{7,10,1582},{8,10,\n458},{10,10,101},{10,10,318},{138,10,823},{6,11,64},{12,11,377},{141,11,309},{5,\n0,743},{138,0,851},{4,0,49},{7,0,280},{135,0,1633},{134,0,879},{136,0,47},{7,10,\n1644},{137,10,129},{132,0,865},{134,0,1202},{9,11,34},{139,11,484},{135,10,997},\n{5,0,272},{5,0,908},{5,0,942},{8,0,197},{9,0,47},{11,0,538},{139,0,742},{6,11,\n1700},{7,11,26},{7,11,293},{7,11,382},{7,11,1026},{7,11,1087},{7,11,2027},{8,11,\n24},{8,11,114},{8,11,252},{8,11,727},{8,11,729},{9,11,30},{9,11,199},{9,11,231},\n{9,11,251},{9,11,334},{9,11,361},{9,11,488},{9,11,712},{10,11,55},{10,11,60},{10\n,11,232},{10,11,332},{10,11,384},{10,11,396},{10,11,504},{10,11,542},{10,11,652}\n,{11,11,20},{11,11,48},{11,11,207},{11,11,291},{11,11,298},{11,11,342},{11,11,\n365},{11,11,394},{11,11,620},{11,11,705},{11,11,1017},{12,11,123},{12,11,340},{\n12,11,406},{12,11,643},{13,11,61},{13,11,269},{13,11,311},{13,11,319},{13,11,486\n},{14,11,234},{15,11,62},{15,11,85},{16,11,71},{18,11,119},{148,11,105},{6,0,\n1455},{150,11,37},{135,10,1927},{135,0,1911},{137,0,891},{7,10,1756},{137,10,98}\n,{7,10,1046},{139,10,160},{132,0,761},{6,11,379},{7,11,270},{7,11,1116},{8,11,\n176},{8,11,183},{9,11,432},{9,11,661},{12,11,247},{12,11,617},{146,11,125},{6,10\n,45},{7,10,433},{8,10,129},{9,10,21},{10,10,392},{11,10,79},{12,10,499},{13,10,\n199},{141,10,451},{4,0,407},{5,11,792},{133,11,900},{132,0,560},{135,0,183},{13,\n0,490},{7,10,558},{136,10,353},{4,0,475},{6,0,731},{11,0,35},{13,0,71},{13,0,177\n},{14,0,422},{133,10,785},{8,10,81},{9,10,189},{9,10,201},{11,10,478},{11,10,712\n},{141,10,338},{4,0,418},{4,0,819},{133,10,353},{151,10,26},{4,11,901},{133,11,\n776},{132,0,575},{7,0,818},{16,0,92},{17,0,14},{17,0,45},{18,0,75},{148,0,18},{6\n,0,222},{7,0,636},{7,0,1620},{8,0,409},{9,0,693},{139,0,77},{6,10,25},{7,10,855}\n,{7,10,1258},{144,10,32},{6,0,1880},{6,0,1887},{6,0,1918},{6,0,1924},{9,0,967},{\n9,0,995},{9,0,1015},{12,0,826},{12,0,849},{12,0,857},{12,0,860},{12,0,886},{12,0\n,932},{18,0,228},{18,0,231},{146,0,240},{134,0,633},{134,0,1308},{4,11,37},{5,11\n,334},{135,11,1253},{10,0,86},{4,10,4},{7,10,1118},{7,10,1320},{7,10,1706},{8,10\n,277},{9,10,622},{11,10,724},{12,10,350},{12,10,397},{13,10,28},{13,10,159},{15,\n10,89},{18,10,5},{19,10,9},{20,10,34},{150,10,47},{132,11,508},{137,11,448},{12,\n11,107},{146,11,31},{132,0,817},{134,0,663},{133,0,882},{134,0,914},{132,11,540}\n,{132,11,533},{136,11,608},{8,0,885},{138,0,865},{132,0,426},{6,0,58},{7,0,745},\n{7,0,1969},{8,0,399},{8,0,675},{9,0,479},{9,0,731},{10,0,330},{10,0,593},{10,0,\n817},{11,0,32},{11,0,133},{11,0,221},{145,0,68},{134,10,255},{7,0,102},{137,0,\n538},{137,10,216},{7,11,253},{136,11,549},{135,11,912},{9,10,183},{139,10,286},{\n11,10,956},{151,10,3},{8,11,527},{18,11,60},{147,11,24},{4,10,536},{7,10,1141},{\n10,10,723},{139,10,371},{133,11,920},{7,0,876},{135,10,285},{135,10,560},{132,10\n,690},{142,11,126},{11,10,33},{12,10,571},{149,10,1},{133,0,566},{9,0,139},{10,0\n,399},{11,0,469},{12,0,634},{13,0,223},{132,11,483},{6,0,48},{135,0,63},{18,0,12\n},{7,10,1862},{12,10,491},{12,10,520},{13,10,383},{142,10,244},{135,11,1665},{\n132,11,448},{9,11,495},{146,11,104},{6,0,114},{7,0,1224},{7,0,1556},{136,0,3},{4\n,10,190},{133,10,554},{8,0,576},{9,0,267},{133,10,1001},{133,10,446},{133,0,933}\n,{139,11,1009},{8,11,653},{13,11,93},{147,11,14},{6,0,692},{6,0,821},{134,0,1077\n},{5,11,172},{135,11,801},{138,0,752},{4,0,375},{134,0,638},{134,0,1011},{140,11\n,540},{9,0,96},{133,11,260},{139,11,587},{135,10,1231},{12,0,30},{13,0,148},{14,\n0,87},{14,0,182},{16,0,42},{20,0,70},{132,10,304},{6,0,1398},{7,0,56},{7,0,1989}\n,{8,0,337},{8,0,738},{9,0,600},{12,0,37},{13,0,447},{142,0,92},{138,0,666},{5,0,\n394},{7,0,487},{136,0,246},{9,0,437},{6,10,53},{6,10,199},{7,10,1408},{8,10,32},\n{8,10,93},{10,10,397},{10,10,629},{11,10,593},{11,10,763},{13,10,326},{145,10,35\n},{134,10,105},{9,0,320},{10,0,506},{138,10,794},{7,11,57},{8,11,167},{8,11,375}\n,{9,11,82},{9,11,561},{10,11,620},{10,11,770},{11,10,704},{141,10,396},{6,0,1003\n},{5,10,114},{5,10,255},{141,10,285},{7,0,866},{135,0,1163},{133,11,531},{132,0,\n328},{7,10,2035},{8,10,19},{9,10,89},{138,10,831},{8,11,194},{136,11,756},{136,0\n,1000},{5,11,453},{134,11,441},{4,0,101},{5,0,833},{7,0,1171},{136,0,744},{133,0\n,726},{136,10,746},{138,0,176},{6,0,9},{6,0,397},{7,0,53},{7,0,1742},{10,0,632},\n{11,0,828},{140,0,146},{135,11,22},{145,11,64},{132,0,839},{11,0,417},{12,0,223}\n,{140,0,265},{4,11,102},{7,11,815},{7,11,1699},{139,11,964},{5,10,955},{136,10,\n814},{6,0,1931},{6,0,2007},{18,0,246},{146,0,247},{8,0,198},{11,0,29},{140,0,534\n},{135,0,1771},{6,0,846},{7,11,1010},{11,11,733},{11,11,759},{12,11,563},{13,11,\n34},{14,11,101},{18,11,45},{146,11,129},{4,0,186},{5,0,157},{8,0,168},{138,0,6},\n{132,11,899},{133,10,56},{148,10,100},{133,0,875},{5,0,773},{5,0,991},{6,0,1635}\n,{134,0,1788},{6,0,1274},{9,0,477},{141,0,78},{4,0,639},{7,0,111},{8,0,581},{12,\n0,177},{6,11,52},{9,11,104},{9,11,559},{10,10,4},{10,10,13},{11,10,638},{12,11,\n308},{19,11,87},{148,10,57},{132,11,604},{4,11,301},{133,10,738},{133,10,758},{\n134,0,1747},{7,11,1440},{11,11,854},{11,11,872},{11,11,921},{12,11,551},{13,11,\n472},{142,11,367},{7,0,1364},{7,0,1907},{141,0,158},{134,0,873},{4,0,404},{4,0,\n659},{7,0,552},{135,0,675},{135,10,1112},{139,10,328},{7,11,508},{137,10,133},{\n133,0,391},{5,10,110},{6,10,169},{6,10,1702},{7,10,400},{8,10,538},{9,10,184},{9\n,10,524},{140,10,218},{6,11,310},{7,11,1849},{8,11,72},{8,11,272},{8,11,431},{9,\n11,12},{9,11,351},{10,11,563},{10,11,630},{10,11,810},{11,11,367},{11,11,599},{\n11,11,686},{140,11,672},{5,0,540},{6,0,1697},{136,0,668},{132,0,883},{134,0,78},\n{12,0,628},{18,0,79},{6,10,133},{9,10,353},{139,10,993},{6,11,181},{7,11,537},{8\n,11,64},{9,11,127},{10,11,496},{12,11,510},{141,11,384},{6,10,93},{7,10,1422},{7\n,10,1851},{8,10,673},{9,10,529},{140,10,43},{137,10,371},{134,0,1460},{134,0,962\n},{4,11,244},{135,11,233},{9,10,25},{10,10,467},{138,10,559},{4,10,335},{135,10,\n942},{133,0,460},{135,11,334},{134,11,1650},{4,0,199},{139,0,34},{5,10,601},{8,\n10,39},{10,10,773},{11,10,84},{12,10,205},{142,10,1},{133,10,870},{134,0,388},{\n14,0,474},{148,0,120},{133,11,369},{139,0,271},{4,0,511},{9,0,333},{9,0,379},{10\n,0,602},{11,0,441},{11,0,723},{11,0,976},{12,0,357},{132,10,181},{134,0,608},{\n134,10,1652},{22,0,49},{137,11,338},{140,0,988},{134,0,617},{5,0,938},{136,0,707\n},{132,10,97},{5,10,147},{6,10,286},{7,10,1362},{141,10,176},{6,0,756},{134,0,\n1149},{133,11,896},{6,10,375},{7,10,169},{7,10,254},{136,10,780},{134,0,1583},{\n135,10,1447},{139,0,285},{7,11,1117},{8,11,393},{136,11,539},{135,0,344},{6,0,\n469},{7,0,1709},{138,0,515},{5,10,629},{135,10,1549},{5,11,4},{5,11,810},{6,11,\n13},{6,11,538},{6,11,1690},{6,11,1726},{7,11,499},{7,11,1819},{8,11,148},{8,11,\n696},{8,11,791},{12,11,125},{13,11,54},{143,11,9},{135,11,1268},{137,0,404},{132\n,0,500},{5,0,68},{134,0,383},{11,0,216},{139,0,340},{4,11,925},{5,11,803},{8,11,\n698},{138,11,828},{4,0,337},{6,0,353},{7,0,1934},{8,0,488},{137,0,429},{7,0,236}\n,{7,0,1795},{8,0,259},{9,0,135},{9,0,177},{9,0,860},{10,0,825},{11,0,115},{11,0,\n370},{11,0,405},{11,0,604},{12,0,10},{12,0,667},{12,0,669},{13,0,76},{14,0,310},\n{15,0,76},{15,0,147},{148,0,23},{4,0,15},{4,0,490},{5,0,22},{6,0,244},{7,0,40},{\n7,0,200},{7,0,906},{7,0,1199},{9,0,616},{10,0,716},{11,0,635},{11,0,801},{140,0,\n458},{12,0,756},{132,10,420},{134,0,1504},{6,0,757},{133,11,383},{6,0,1266},{135\n,0,1735},{5,0,598},{7,0,791},{8,0,108},{9,0,123},{7,10,1570},{140,10,542},{142,\n11,410},{9,11,660},{138,11,347}\n};\n/* GENERATED CODE END */\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_STATIC_DICT_LUT_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/utf8_util.c",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Heuristics for deciding about the UTF8-ness of strings. */\n\n#include \"utf8_util.h\"\n\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic size_t BrotliParseAsUTF8(\n    int* symbol, const uint8_t* input, size_t size) {\n  /* ASCII */\n  if ((input[0] & 0x80) == 0) {\n    *symbol = input[0];\n    if (*symbol > 0) {\n      return 1;\n    }\n  }\n  /* 2-byte UTF8 */\n  if (size > 1u &&\n      (input[0] & 0xE0) == 0xC0 &&\n      (input[1] & 0xC0) == 0x80) {\n    *symbol = (((input[0] & 0x1F) << 6) |\n               (input[1] & 0x3F));\n    if (*symbol > 0x7F) {\n      return 2;\n    }\n  }\n  /* 3-byte UFT8 */\n  if (size > 2u &&\n      (input[0] & 0xF0) == 0xE0 &&\n      (input[1] & 0xC0) == 0x80 &&\n      (input[2] & 0xC0) == 0x80) {\n    *symbol = (((input[0] & 0x0F) << 12) |\n               ((input[1] & 0x3F) << 6) |\n               (input[2] & 0x3F));\n    if (*symbol > 0x7FF) {\n      return 3;\n    }\n  }\n  /* 4-byte UFT8 */\n  if (size > 3u &&\n      (input[0] & 0xF8) == 0xF0 &&\n      (input[1] & 0xC0) == 0x80 &&\n      (input[2] & 0xC0) == 0x80 &&\n      (input[3] & 0xC0) == 0x80) {\n    *symbol = (((input[0] & 0x07) << 18) |\n               ((input[1] & 0x3F) << 12) |\n               ((input[2] & 0x3F) << 6) |\n               (input[3] & 0x3F));\n    if (*symbol > 0xFFFF && *symbol <= 0x10FFFF) {\n      return 4;\n    }\n  }\n  /* Not UTF8, emit a special symbol above the UTF8-code space */\n  *symbol = 0x110000 | input[0];\n  return 1;\n}\n\n/* Returns 1 if at least min_fraction of the data is UTF8-encoded.*/\nBROTLI_BOOL BrotliIsMostlyUTF8(\n    const uint8_t* data, const size_t pos, const size_t mask,\n    const size_t length, const double min_fraction) {\n  size_t size_utf8 = 0;\n  size_t i = 0;\n  while (i < length) {\n    int symbol;\n    size_t bytes_read =\n        BrotliParseAsUTF8(&symbol, &data[(pos + i) & mask], length - i);\n    i += bytes_read;\n    if (symbol < 0x110000) size_utf8 += bytes_read;\n  }\n  return TO_BROTLI_BOOL((double)size_utf8 > min_fraction * (double)length);\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n"
  },
  {
    "path": "third-party/brotli/enc/utf8_util.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Heuristics for deciding about the UTF8-ness of strings. */\n\n#ifndef BROTLI_ENC_UTF8_UTIL_H_\n#define BROTLI_ENC_UTF8_UTIL_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\nstatic const double kMinUTF8Ratio = 0.75;\n\n/* Returns 1 if at least min_fraction of the bytes between pos and\n   pos + length in the (data, mask) ring-buffer is UTF8-encoded, otherwise\n   returns 0. */\nBROTLI_INTERNAL BROTLI_BOOL BrotliIsMostlyUTF8(\n    const uint8_t* data, const size_t pos, const size_t mask,\n    const size_t length, const double min_fraction);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_UTF8_UTIL_H_ */\n"
  },
  {
    "path": "third-party/brotli/enc/write_bits.h",
    "content": "/* Copyright 2010 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Write bits into a byte array. */\n\n#ifndef BROTLI_ENC_WRITE_BITS_H_\n#define BROTLI_ENC_WRITE_BITS_H_\n\n#include <brotli/types.h>\n\n#include \"../common/platform.h\"\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/* This function writes bits into bytes in increasing addresses, and within\n   a byte least-significant-bit first.\n\n   The function can write up to 56 bits in one go with WriteBits\n   Example: let's assume that 3 bits (Rs below) have been written already:\n\n   BYTE-0     BYTE+1       BYTE+2\n\n   0000 0RRR    0000 0000    0000 0000\n\n   Now, we could write 5 or less bits in MSB by just shifting by 3\n   and OR'ing to BYTE-0.\n\n   For n bits, we take the last 5 bits, OR that with high bits in BYTE-0,\n   and locate the rest in BYTE+1, BYTE+2, etc. */\nstatic BROTLI_INLINE void BrotliWriteBits(size_t n_bits,\n                                          uint64_t bits,\n                                          size_t* BROTLI_RESTRICT pos,\n                                          uint8_t* BROTLI_RESTRICT array) {\n  BROTLI_LOG((\"WriteBits  %2d  0x%08x%08x  %10d\\n\", (int)n_bits,\n      (uint32_t)(bits >> 32), (uint32_t)(bits & 0xFFFFFFFF),\n      (int)*pos));\n  BROTLI_DCHECK((bits >> n_bits) == 0);\n  BROTLI_DCHECK(n_bits <= 56);\n#if defined(BROTLI_LITTLE_ENDIAN)\n  /* This branch of the code can write up to 56 bits at a time,\n     7 bits are lost by being perhaps already in *p and at least\n     1 bit is needed to initialize the bit-stream ahead (i.e. if 7\n     bits are in *p and we write 57 bits, then the next write will\n     access a byte that was never initialized). */\n  {\n    uint8_t* p = &array[*pos >> 3];\n    uint64_t v = (uint64_t)(*p);  /* Zero-extend 8 to 64 bits. */\n    v |= bits << (*pos & 7);\n    BROTLI_UNALIGNED_STORE64LE(p, v);  /* Set some bits. */\n    *pos += n_bits;\n  }\n#else\n  /* implicit & 0xFF is assumed for uint8_t arithmetics */\n  {\n    uint8_t* array_pos = &array[*pos >> 3];\n    const size_t bits_reserved_in_first_byte = (*pos & 7);\n    size_t bits_left_to_write;\n    bits <<= bits_reserved_in_first_byte;\n    *array_pos++ |= (uint8_t)bits;\n    for (bits_left_to_write = n_bits + bits_reserved_in_first_byte;\n         bits_left_to_write >= 9;\n         bits_left_to_write -= 8) {\n      bits >>= 8;\n      *array_pos++ = (uint8_t)bits;\n    }\n    *array_pos = 0;\n    *pos += n_bits;\n  }\n#endif\n}\n\nstatic BROTLI_INLINE void BrotliWriteBitsPrepareStorage(\n    size_t pos, uint8_t* array) {\n  BROTLI_LOG((\"WriteBitsPrepareStorage            %10d\\n\", (int)pos));\n  BROTLI_DCHECK((pos & 7) == 0);\n  array[pos >> 3] = 0;\n}\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_WRITE_BITS_H_ */\n"
  },
  {
    "path": "third-party/brotli/include/brotli/decode.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * API for Brotli decompression.\n */\n\n#ifndef BROTLI_DEC_DECODE_H_\n#define BROTLI_DEC_DECODE_H_\n\n#include <brotli/port.h>\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/**\n * Opaque structure that holds decoder state.\n *\n * Allocated and initialized with ::BrotliDecoderCreateInstance.\n * Cleaned up and deallocated with ::BrotliDecoderDestroyInstance.\n */\ntypedef struct BrotliDecoderStateStruct BrotliDecoderState;\n\n/**\n * Result type for ::BrotliDecoderDecompress and\n * ::BrotliDecoderDecompressStream functions.\n */\ntypedef enum {\n  /** Decoding error, e.g. corrupted input or memory allocation problem. */\n  BROTLI_DECODER_RESULT_ERROR = 0,\n  /** Decoding successfully completed. */\n  BROTLI_DECODER_RESULT_SUCCESS = 1,\n  /** Partially done; should be called again with more input. */\n  BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT = 2,\n  /** Partially done; should be called again with more output. */\n  BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT = 3\n} BrotliDecoderResult;\n\n/**\n * Template that evaluates items of ::BrotliDecoderErrorCode.\n *\n * Example: @code {.cpp}\n * // Log Brotli error code.\n * switch (brotliDecoderErrorCode) {\n * #define CASE_(PREFIX, NAME, CODE) \\\n *   case BROTLI_DECODER ## PREFIX ## NAME: \\\n *     LOG(INFO) << \"error code:\" << #NAME; \\\n *     break;\n * #define NEWLINE_\n * BROTLI_DECODER_ERROR_CODES_LIST(CASE_, NEWLINE_)\n * #undef CASE_\n * #undef NEWLINE_\n *   default: LOG(FATAL) << \"unknown brotli error code\";\n * }\n * @endcode\n */\n#define BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE, SEPARATOR)      \\\n  BROTLI_ERROR_CODE(_, NO_ERROR, 0) SEPARATOR                              \\\n  /* Same as BrotliDecoderResult values */                                 \\\n  BROTLI_ERROR_CODE(_, SUCCESS, 1) SEPARATOR                               \\\n  BROTLI_ERROR_CODE(_, NEEDS_MORE_INPUT, 2) SEPARATOR                      \\\n  BROTLI_ERROR_CODE(_, NEEDS_MORE_OUTPUT, 3) SEPARATOR                     \\\n                                                                           \\\n  /* Errors caused by invalid input */                                     \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_NIBBLE, -1) SEPARATOR        \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, RESERVED, -2) SEPARATOR                \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, EXUBERANT_META_NIBBLE, -3) SEPARATOR   \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_ALPHABET, -4) SEPARATOR \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, SIMPLE_HUFFMAN_SAME, -5) SEPARATOR     \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, CL_SPACE, -6) SEPARATOR                \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, HUFFMAN_SPACE, -7) SEPARATOR           \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, CONTEXT_MAP_REPEAT, -8) SEPARATOR      \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_1, -9) SEPARATOR          \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, BLOCK_LENGTH_2, -10) SEPARATOR         \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, TRANSFORM, -11) SEPARATOR              \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, DICTIONARY, -12) SEPARATOR             \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, WINDOW_BITS, -13) SEPARATOR            \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_1, -14) SEPARATOR              \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, PADDING_2, -15) SEPARATOR              \\\n  BROTLI_ERROR_CODE(_ERROR_FORMAT_, DISTANCE, -16) SEPARATOR               \\\n                                                                           \\\n  /* -17 code is reserved */                                               \\\n                                                                           \\\n  BROTLI_ERROR_CODE(_ERROR_, COMPOUND_DICTIONARY, -18) SEPARATOR           \\\n  BROTLI_ERROR_CODE(_ERROR_, DICTIONARY_NOT_SET, -19) SEPARATOR            \\\n  BROTLI_ERROR_CODE(_ERROR_, INVALID_ARGUMENTS, -20) SEPARATOR             \\\n                                                                           \\\n  /* Memory allocation problems */                                         \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MODES, -21) SEPARATOR           \\\n  /* Literal, insert and distance trees together */                        \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, TREE_GROUPS, -22) SEPARATOR             \\\n  /* -23..-24 codes are reserved for distinct tree groups */               \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, CONTEXT_MAP, -25) SEPARATOR             \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_1, -26) SEPARATOR           \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, RING_BUFFER_2, -27) SEPARATOR           \\\n  /* -28..-29 codes are reserved for dynamic ring-buffer allocation */     \\\n  BROTLI_ERROR_CODE(_ERROR_ALLOC_, BLOCK_TYPE_TREES, -30) SEPARATOR        \\\n                                                                           \\\n  /* \"Impossible\" states */                                                \\\n  BROTLI_ERROR_CODE(_ERROR_, UNREACHABLE, -31)\n\n/**\n * Error code for detailed logging / production debugging.\n *\n * See ::BrotliDecoderGetErrorCode and ::BROTLI_LAST_ERROR_CODE.\n */\ntypedef enum {\n#define BROTLI_COMMA_ ,\n#define BROTLI_ERROR_CODE_ENUM_ITEM_(PREFIX, NAME, CODE) \\\n    BROTLI_DECODER ## PREFIX ## NAME = CODE\n  BROTLI_DECODER_ERROR_CODES_LIST(BROTLI_ERROR_CODE_ENUM_ITEM_, BROTLI_COMMA_)\n} BrotliDecoderErrorCode;\n#undef BROTLI_ERROR_CODE_ENUM_ITEM_\n#undef BROTLI_COMMA_\n\n/**\n * The value of the last error code, negative integer.\n *\n * All other error code values are in the range from ::BROTLI_LAST_ERROR_CODE\n * to @c -1. There are also 4 other possible non-error codes @c 0 .. @c 3 in\n * ::BrotliDecoderErrorCode enumeration.\n */\n#define BROTLI_LAST_ERROR_CODE BROTLI_DECODER_ERROR_UNREACHABLE\n\n/** Options to be used with ::BrotliDecoderSetParameter. */\ntypedef enum BrotliDecoderParameter {\n  /**\n   * Disable \"canny\" ring buffer allocation strategy.\n   *\n   * Ring buffer is allocated according to window size, despite the real size of\n   * the content.\n   */\n  BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION = 0,\n  /**\n   * Flag that determines if \"Large Window Brotli\" is used.\n   */\n  BROTLI_DECODER_PARAM_LARGE_WINDOW = 1\n} BrotliDecoderParameter;\n\n/**\n * Sets the specified parameter to the given decoder instance.\n *\n * @param state decoder instance\n * @param param parameter to set\n * @param value new parameter value\n * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid\n * @returns ::BROTLI_TRUE if value is accepted\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderSetParameter(\n    BrotliDecoderState* state, BrotliDecoderParameter param, uint32_t value);\n\n/**\n * Adds LZ77 prefix dictionary, adds or replaces built-in static dictionary and\n * transforms.\n *\n * Attached dictionary ownership is not transferred.\n * Data provided to this method should be kept accessible until\n * decoding is finished and decoder instance is destroyed.\n *\n * @note Dictionaries can NOT be attached after actual decoding is started.\n *\n * @param state decoder instance\n * @param type dictionary data format\n * @param data_size length of memory region pointed by @p data\n * @param data dictionary data in format corresponding to @p type\n * @returns ::BROTLI_FALSE if dictionary is corrupted,\n *          or dictionary count limit is reached\n * @returns ::BROTLI_TRUE if dictionary is accepted / attached\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderAttachDictionary(\n    BrotliDecoderState* state, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);\n\n/**\n * Creates an instance of ::BrotliDecoderState and initializes it.\n *\n * The instance can be used once for decoding and should then be destroyed with\n * ::BrotliDecoderDestroyInstance, it cannot be reused for a new decoding\n * session.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n * @returns @c 0 if instance can not be allocated or initialized\n * @returns pointer to initialized ::BrotliDecoderState otherwise\n */\nBROTLI_DEC_API BrotliDecoderState* BrotliDecoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\n/**\n * Deinitializes and frees ::BrotliDecoderState instance.\n *\n * @param state decoder instance to be cleaned up and deallocated\n */\nBROTLI_DEC_API void BrotliDecoderDestroyInstance(BrotliDecoderState* state);\n\n/**\n * Performs one-shot memory-to-memory decompression.\n *\n * Decompresses the data in @p encoded_buffer into @p decoded_buffer, and sets\n * @p *decoded_size to the decompressed length.\n *\n * @param encoded_size size of @p encoded_buffer\n * @param encoded_buffer compressed data buffer with at least @p encoded_size\n *        addressable bytes\n * @param[in, out] decoded_size @b in: size of @p decoded_buffer; \\n\n *                 @b out: length of decompressed data written to\n *                 @p decoded_buffer\n * @param decoded_buffer decompressed data destination buffer\n * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory\n *          allocation failed, or @p decoded_buffer is not large enough;\n * @returns ::BROTLI_DECODER_RESULT_SUCCESS otherwise\n */\nBROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompress(\n    size_t encoded_size,\n    const uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(encoded_size)],\n    size_t* decoded_size,\n    uint8_t decoded_buffer[BROTLI_ARRAY_PARAM(*decoded_size)]);\n\n/**\n * Decompresses the input stream to the output stream.\n *\n * The values @p *available_in and @p *available_out must specify the number of\n * bytes addressable at @p *next_in and @p *next_out respectively.\n * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL.\n *\n * After each call, @p *available_in will be decremented by the amount of input\n * bytes consumed, and the @p *next_in pointer will be incremented by that\n * amount. Similarly, @p *available_out will be decremented by the amount of\n * output bytes written, and the @p *next_out pointer will be incremented by\n * that amount.\n *\n * @p total_out, if it is not a null-pointer, will be set to the number\n * of bytes decompressed since the last @p state initialization.\n *\n * @note Input is never overconsumed, so @p next_in and @p available_in could be\n * passed to the next consumer after decoding is complete.\n *\n * @param state decoder instance\n * @param[in, out] available_in @b in: amount of available input; \\n\n *                 @b out: amount of unused input\n * @param[in, out] next_in pointer to the next compressed byte\n * @param[in, out] available_out @b in: length of output buffer; \\n\n *                 @b out: remaining size of output buffer\n * @param[in, out] next_out output buffer cursor;\n *                 can be @c NULL if @p available_out is @c 0\n * @param[out] total_out number of bytes decompressed so far; can be @c NULL\n * @returns ::BROTLI_DECODER_RESULT_ERROR if input is corrupted, memory\n *          allocation failed, arguments were invalid, etc.;\n *          use ::BrotliDecoderGetErrorCode to get detailed error code\n * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT decoding is blocked until\n *          more input data is provided\n * @returns ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT decoding is blocked until\n *          more output space is provided\n * @returns ::BROTLI_DECODER_RESULT_SUCCESS decoding is finished, no more\n *          input might be consumed and no more output will be produced\n */\nBROTLI_DEC_API BrotliDecoderResult BrotliDecoderDecompressStream(\n  BrotliDecoderState* state, size_t* available_in, const uint8_t** next_in,\n  size_t* available_out, uint8_t** next_out, size_t* total_out);\n\n/**\n * Checks if decoder has more output.\n *\n * @param state decoder instance\n * @returns ::BROTLI_TRUE, if decoder has some unconsumed output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderHasMoreOutput(\n    const BrotliDecoderState* state);\n\n/**\n * Acquires pointer to internal output buffer.\n *\n * This method is used to make language bindings easier and more efficient:\n *  -# push data to ::BrotliDecoderDecompressStream,\n *     until ::BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT is reported\n *  -# use ::BrotliDecoderTakeOutput to peek bytes and copy to language-specific\n *     entity\n *\n * Also this could be useful if there is an output stream that is able to\n * consume all the provided data (e.g. when data is saved to file system).\n *\n * @attention After every call to ::BrotliDecoderTakeOutput @p *size bytes of\n *            output are considered consumed for all consecutive calls to the\n *            instance methods; returned pointer becomes invalidated as well.\n *\n * @note Decoder output is not guaranteed to be contiguous. This means that\n *       after the size-unrestricted call to ::BrotliDecoderTakeOutput,\n *       immediate next call to ::BrotliDecoderTakeOutput may return more data.\n *\n * @param state decoder instance\n * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if\n *                 any amount could be handled; \\n\n *                 @b out: amount of data pointed by returned pointer and\n *                 considered consumed; \\n\n *                 out value is never greater than in value, unless it is @c 0\n * @returns pointer to output data\n */\nBROTLI_DEC_API const uint8_t* BrotliDecoderTakeOutput(\n    BrotliDecoderState* state, size_t* size);\n\n/**\n * Checks if instance has already consumed input.\n *\n * Instance that returns ::BROTLI_FALSE is considered \"fresh\" and could be\n * reused.\n *\n * @param state decoder instance\n * @returns ::BROTLI_TRUE if decoder has already used some input bytes\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsUsed(const BrotliDecoderState* state);\n\n/**\n * Checks if decoder instance reached the final state.\n *\n * @param state decoder instance\n * @returns ::BROTLI_TRUE if decoder is in a state where it reached the end of\n *          the input and produced all of the output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_DEC_API BROTLI_BOOL BrotliDecoderIsFinished(\n    const BrotliDecoderState* state);\n\n/**\n * Acquires a detailed error code.\n *\n * Should be used only after ::BrotliDecoderDecompressStream returns\n * ::BROTLI_DECODER_RESULT_ERROR.\n *\n * See also ::BrotliDecoderErrorString\n *\n * @param state decoder instance\n * @returns last saved error code\n */\nBROTLI_DEC_API BrotliDecoderErrorCode BrotliDecoderGetErrorCode(\n    const BrotliDecoderState* state);\n\n/**\n * Converts error code to a c-string.\n */\nBROTLI_DEC_API const char* BrotliDecoderErrorString(BrotliDecoderErrorCode c);\n\n/**\n * Gets a decoder library version.\n *\n * Look at BROTLI_MAKE_HEX_VERSION for more information.\n */\nBROTLI_DEC_API uint32_t BrotliDecoderVersion(void);\n\n/**\n * Callback to fire on metadata block start.\n *\n * After this callback is fired, if @p size is not @c 0, it is followed by\n * ::brotli_decoder_metadata_chunk_func as more metadata block contents become\n * accessible.\n *\n * @param opaque callback handle\n * @param size size of metadata block\n */\ntypedef void (*brotli_decoder_metadata_start_func)(void* opaque, size_t size);\n\n/**\n * Callback to fire on metadata block chunk becomes available.\n *\n * This function can be invoked multiple times per metadata block; block should\n * be considered finished when sum of @p size matches the announced metadata\n * block size. Chunks contents pointed by @p data are transient and shouln not\n * be accessed after leaving the callback.\n *\n * @param opaque callback handle\n * @param data pointer to metadata contents\n * @param size size of metadata block chunk, at least @c 1\n */\ntypedef void (*brotli_decoder_metadata_chunk_func)(void* opaque,\n                                                   const uint8_t* data,\n                                                   size_t size);\n\n/**\n * Sets callback for receiving metadata blocks.\n *\n * @param state decoder instance\n * @param start_func callback on metadata block start\n * @param chunk_func callback on metadata block chunk\n * @param opaque callback handle\n */\nBROTLI_DEC_API void BrotliDecoderSetMetadataCallbacks(\n    BrotliDecoderState* state,\n    brotli_decoder_metadata_start_func start_func,\n    brotli_decoder_metadata_chunk_func chunk_func, void* opaque);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n} /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_DEC_DECODE_H_ */\n"
  },
  {
    "path": "third-party/brotli/include/brotli/encode.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * API for Brotli compression.\n */\n\n#ifndef BROTLI_ENC_ENCODE_H_\n#define BROTLI_ENC_ENCODE_H_\n\n#include <brotli/port.h>\n#include <brotli/shared_dictionary.h>\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n/** Minimal value for ::BROTLI_PARAM_LGWIN parameter. */\n#define BROTLI_MIN_WINDOW_BITS 10\n/**\n * Maximal value for ::BROTLI_PARAM_LGWIN parameter.\n *\n * @note equal to @c BROTLI_MAX_DISTANCE_BITS constant.\n */\n#define BROTLI_MAX_WINDOW_BITS 24\n/**\n * Maximal value for ::BROTLI_PARAM_LGWIN parameter\n * in \"Large Window Brotli\" (32-bit).\n */\n#define BROTLI_LARGE_MAX_WINDOW_BITS 30\n/** Minimal value for ::BROTLI_PARAM_LGBLOCK parameter. */\n#define BROTLI_MIN_INPUT_BLOCK_BITS 16\n/** Maximal value for ::BROTLI_PARAM_LGBLOCK parameter. */\n#define BROTLI_MAX_INPUT_BLOCK_BITS 24\n/** Minimal value for ::BROTLI_PARAM_QUALITY parameter. */\n#define BROTLI_MIN_QUALITY 0\n/** Maximal value for ::BROTLI_PARAM_QUALITY parameter. */\n#define BROTLI_MAX_QUALITY 11\n\n/** Options for ::BROTLI_PARAM_MODE parameter. */\ntypedef enum BrotliEncoderMode {\n  /**\n   * Default compression mode.\n   *\n   * In this mode compressor does not know anything in advance about the\n   * properties of the input.\n   */\n  BROTLI_MODE_GENERIC = 0,\n  /** Compression mode for UTF-8 formatted text input. */\n  BROTLI_MODE_TEXT = 1,\n  /** Compression mode used in WOFF 2.0. */\n  BROTLI_MODE_FONT = 2\n} BrotliEncoderMode;\n\n/** Default value for ::BROTLI_PARAM_QUALITY parameter. */\n#define BROTLI_DEFAULT_QUALITY 11\n/** Default value for ::BROTLI_PARAM_LGWIN parameter. */\n#define BROTLI_DEFAULT_WINDOW 22\n/** Default value for ::BROTLI_PARAM_MODE parameter. */\n#define BROTLI_DEFAULT_MODE BROTLI_MODE_GENERIC\n\n/** Operations that can be performed by streaming encoder. */\ntypedef enum BrotliEncoderOperation {\n  /**\n   * Process input.\n   *\n   * Encoder may postpone producing output, until it has processed enough input.\n   */\n  BROTLI_OPERATION_PROCESS = 0,\n  /**\n   * Produce output for all processed input.\n   *\n   * Actual flush is performed when input stream is depleted and there is enough\n   * space in output stream. This means that client should repeat\n   * ::BROTLI_OPERATION_FLUSH operation until @p available_in becomes @c 0, and\n   * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired\n   * via ::BrotliEncoderTakeOutput, then operation should be repeated after\n   * output buffer is drained.\n   *\n   * @warning Until flush is complete, client @b SHOULD @b NOT swap,\n   *          reduce or extend input stream.\n   *\n   * When flush is complete, output data will be sufficient for decoder to\n   * reproduce all the given input.\n   */\n  BROTLI_OPERATION_FLUSH = 1,\n  /**\n   * Finalize the stream.\n   *\n   * Actual finalization is performed when input stream is depleted and there is\n   * enough space in output stream. This means that client should repeat\n   * ::BROTLI_OPERATION_FINISH operation until @p available_in becomes @c 0, and\n   * ::BrotliEncoderHasMoreOutput returns ::BROTLI_FALSE. If output is acquired\n   * via ::BrotliEncoderTakeOutput, then operation should be repeated after\n   * output buffer is drained.\n   *\n   * @warning Until finalization is complete, client @b SHOULD @b NOT swap,\n   *          reduce or extend input stream.\n   *\n   * Helper function ::BrotliEncoderIsFinished checks if stream is finalized and\n   * output fully dumped.\n   *\n   * Adding more input data to finalized stream is impossible.\n   */\n  BROTLI_OPERATION_FINISH = 2,\n  /**\n   * Emit metadata block to stream.\n   *\n   * Metadata is opaque to Brotli: neither encoder, nor decoder processes this\n   * data or relies on it. It may be used to pass some extra information from\n   * encoder client to decoder client without interfering with main data stream.\n   *\n   * @note Encoder may emit empty metadata blocks internally, to pad encoded\n   *       stream to byte boundary.\n   *\n   * @warning Until emitting metadata is complete client @b SHOULD @b NOT swap,\n   *          reduce or extend input stream.\n   *\n   * @warning The whole content of input buffer is considered to be the content\n   *          of metadata block. Do @b NOT @e append metadata to input stream,\n   *          before it is depleted with other operations.\n   *\n   * Stream is soft-flushed before metadata block is emitted. Metadata block\n   * @b MUST be no longer than 16MiB.\n   */\n  BROTLI_OPERATION_EMIT_METADATA = 3\n} BrotliEncoderOperation;\n\n/** Options to be used with ::BrotliEncoderSetParameter. */\ntypedef enum BrotliEncoderParameter {\n  /**\n   * Tune encoder for specific input.\n   *\n   * ::BrotliEncoderMode enumerates all available values.\n   */\n  BROTLI_PARAM_MODE = 0,\n  /**\n   * The main compression speed-density lever.\n   *\n   * The higher the quality, the slower the compression. Range is\n   * from ::BROTLI_MIN_QUALITY to ::BROTLI_MAX_QUALITY.\n   */\n  BROTLI_PARAM_QUALITY = 1,\n  /**\n   * Recommended sliding LZ77 window size.\n   *\n   * Encoder may reduce this value, e.g. if input is much smaller than\n   * window size.\n   *\n   * Window size is `(1 << value) - 16`.\n   *\n   * Range is from ::BROTLI_MIN_WINDOW_BITS to ::BROTLI_MAX_WINDOW_BITS.\n   */\n  BROTLI_PARAM_LGWIN = 2,\n  /**\n   * Recommended input block size.\n   *\n   * Encoder may reduce this value, e.g. if input is much smaller than input\n   * block size.\n   *\n   * Range is from ::BROTLI_MIN_INPUT_BLOCK_BITS to\n   * ::BROTLI_MAX_INPUT_BLOCK_BITS.\n   *\n   * @note Bigger input block size allows better compression, but consumes more\n   *       memory. \\n The rough formula of memory used for temporary input\n   *       storage is `3 << lgBlock`.\n   */\n  BROTLI_PARAM_LGBLOCK = 3,\n  /**\n   * Flag that affects usage of \"literal context modeling\" format feature.\n   *\n   * This flag is a \"decoding-speed vs compression ratio\" trade-off.\n   */\n  BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING = 4,\n  /**\n   * Estimated total input size for all ::BrotliEncoderCompressStream calls.\n   *\n   * The default value is 0, which means that the total input size is unknown.\n   */\n  BROTLI_PARAM_SIZE_HINT = 5,\n  /**\n   * Flag that determines if \"Large Window Brotli\" is used.\n   */\n  BROTLI_PARAM_LARGE_WINDOW = 6,\n  /**\n   * Recommended number of postfix bits (NPOSTFIX).\n   *\n   * Encoder may change this value.\n   *\n   * Range is from 0 to ::BROTLI_MAX_NPOSTFIX.\n   */\n  BROTLI_PARAM_NPOSTFIX = 7,\n  /**\n   * Recommended number of direct distance codes (NDIRECT).\n   *\n   * Encoder may change this value.\n   *\n   * Range is from 0 to (15 << NPOSTFIX) in steps of (1 << NPOSTFIX).\n   */\n  BROTLI_PARAM_NDIRECT = 8,\n  /**\n   * Number of bytes of input stream already processed by a different instance.\n   *\n   * @note It is important to configure all the encoder instances with same\n   *       parameters (except this one) in order to allow all the encoded parts\n   *       obey the same restrictions implied by header.\n   *\n   * If offset is not 0, then stream header is omitted.\n   * In any case output start is byte aligned, so for proper streams stitching\n   * \"predecessor\" stream must be flushed.\n   *\n   * Range is not artificially limited, but all the values greater or equal to\n   * maximal window size have the same effect. Values greater than 2**30 are not\n   * allowed.\n   */\n  BROTLI_PARAM_STREAM_OFFSET = 9\n} BrotliEncoderParameter;\n\n/**\n * Opaque structure that holds encoder state.\n *\n * Allocated and initialized with ::BrotliEncoderCreateInstance.\n * Cleaned up and deallocated with ::BrotliEncoderDestroyInstance.\n */\ntypedef struct BrotliEncoderStateStruct BrotliEncoderState;\n\n/**\n * Sets the specified parameter to the given encoder instance.\n *\n * @param state encoder instance\n * @param param parameter to set\n * @param value new parameter value\n * @returns ::BROTLI_FALSE if parameter is unrecognized, or value is invalid\n * @returns ::BROTLI_FALSE if value of parameter can not be changed at current\n *          encoder state (e.g. when encoding is started, window size might be\n *          already encoded and therefore it is impossible to change it)\n * @returns ::BROTLI_TRUE if value is accepted\n * @warning invalid values might be accepted in case they would not break\n *          encoding process.\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderSetParameter(\n    BrotliEncoderState* state, BrotliEncoderParameter param, uint32_t value);\n\n/**\n * Creates an instance of ::BrotliEncoderState and initializes it.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n * @returns @c 0 if instance can not be allocated or initialized\n * @returns pointer to initialized ::BrotliEncoderState otherwise\n */\nBROTLI_ENC_API BrotliEncoderState* BrotliEncoderCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\n/**\n * Deinitializes and frees ::BrotliEncoderState instance.\n *\n * @param state decoder instance to be cleaned up and deallocated\n */\nBROTLI_ENC_API void BrotliEncoderDestroyInstance(BrotliEncoderState* state);\n\n/* Opaque type for pointer to different possible internal structures containing\n   dictionary prepared for the encoder */\ntypedef struct BrotliEncoderPreparedDictionaryStruct\n    BrotliEncoderPreparedDictionary;\n\n/**\n * Prepares a shared dictionary from the given file format for the encoder.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param type type of dictionary stored in data\n * @param data_size size of @p data buffer\n * @param data pointer to the dictionary data\n * @param quality the maximum Brotli quality to prepare the dictionary for,\n *        use BROTLI_MAX_QUALITY by default\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n */\nBROTLI_ENC_API BrotliEncoderPreparedDictionary*\nBrotliEncoderPrepareDictionary(BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)],\n    int quality,\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\nBROTLI_ENC_API void BrotliEncoderDestroyPreparedDictionary(\n    BrotliEncoderPreparedDictionary* dictionary);\n\n/**\n * Attaches a prepared dictionary of any type to the encoder. Can be used\n * multiple times to attach multiple dictionaries. The dictionary type was\n * determined by BrotliEncoderPrepareDictionary. Multiple raw prefix\n * dictionaries and/or max 1 serialized dictionary with custom words can be\n * attached.\n *\n * @returns ::BROTLI_FALSE in case of error\n * @returns ::BROTLI_TRUE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderAttachPreparedDictionary(\n    BrotliEncoderState* state,\n    const BrotliEncoderPreparedDictionary* dictionary);\n\n/**\n * Calculates the output size bound for the given @p input_size.\n *\n * @warning Result is only valid if quality is at least @c 2 and, in\n *          case ::BrotliEncoderCompressStream was used, no flushes\n *          (::BROTLI_OPERATION_FLUSH) were performed.\n *\n * @param input_size size of projected input\n * @returns @c 0 if result does not fit @c size_t\n */\nBROTLI_ENC_API size_t BrotliEncoderMaxCompressedSize(size_t input_size);\n\n/**\n * Performs one-shot memory-to-memory compression.\n *\n * Compresses the data in @p input_buffer into @p encoded_buffer, and sets\n * @p *encoded_size to the compressed length.\n *\n * @note If ::BrotliEncoderMaxCompressedSize(@p input_size) returns non-zero\n *       value, then output is guaranteed to be no longer than that.\n *\n * @note If @p lgwin is greater than ::BROTLI_MAX_WINDOW_BITS then resulting\n *       stream might be incompatible with RFC 7932; to decode such streams,\n *       decoder should be configured with\n *       ::BROTLI_DECODER_PARAM_LARGE_WINDOW = @c 1\n *\n * @param quality quality parameter value, e.g. ::BROTLI_DEFAULT_QUALITY\n * @param lgwin lgwin parameter value, e.g. ::BROTLI_DEFAULT_WINDOW\n * @param mode mode parameter value, e.g. ::BROTLI_DEFAULT_MODE\n * @param input_size size of @p input_buffer\n * @param input_buffer input data buffer with at least @p input_size\n *        addressable bytes\n * @param[in, out] encoded_size @b in: size of @p encoded_buffer; \\n\n *                 @b out: length of compressed data written to\n *                 @p encoded_buffer, or @c 0 if compression fails\n * @param encoded_buffer compressed data destination buffer\n * @returns ::BROTLI_FALSE in case of compression error\n * @returns ::BROTLI_FALSE if output buffer is too small\n * @returns ::BROTLI_TRUE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompress(\n    int quality, int lgwin, BrotliEncoderMode mode, size_t input_size,\n    const uint8_t input_buffer[BROTLI_ARRAY_PARAM(input_size)],\n    size_t* encoded_size,\n    uint8_t encoded_buffer[BROTLI_ARRAY_PARAM(*encoded_size)]);\n\n/**\n * Compresses input stream to output stream.\n *\n * The values @p *available_in and @p *available_out must specify the number of\n * bytes addressable at @p *next_in and @p *next_out respectively.\n * When @p *available_out is @c 0, @p next_out is allowed to be @c NULL.\n *\n * After each call, @p *available_in will be decremented by the amount of input\n * bytes consumed, and the @p *next_in pointer will be incremented by that\n * amount. Similarly, @p *available_out will be decremented by the amount of\n * output bytes written, and the @p *next_out pointer will be incremented by\n * that amount.\n *\n * @p total_out, if it is not a null-pointer, will be set to the number\n * of bytes compressed since the last @p state initialization.\n *\n *\n *\n * Internally workflow consists of 3 tasks:\n *  -# (optionally) copy input data to internal buffer\n *  -# actually compress data and (optionally) store it to internal buffer\n *  -# (optionally) copy compressed bytes from internal buffer to output stream\n *\n * Whenever all 3 tasks can't move forward anymore, or error occurs, this\n * method returns the control flow to caller.\n *\n * @p op is used to perform flush, finish the stream, or inject metadata block.\n * See ::BrotliEncoderOperation for more information.\n *\n * Flushing the stream means forcing encoding of all input passed to encoder and\n * completing the current output block, so it could be fully decoded by stream\n * decoder. To perform flush set @p op to ::BROTLI_OPERATION_FLUSH.\n * Under some circumstances (e.g. lack of output stream capacity) this operation\n * would require several calls to ::BrotliEncoderCompressStream. The method must\n * be called again until both input stream is depleted and encoder has no more\n * output (see ::BrotliEncoderHasMoreOutput) after the method is called.\n *\n * Finishing the stream means encoding of all input passed to encoder and\n * adding specific \"final\" marks, so stream decoder could determine that stream\n * is complete. To perform finish set @p op to ::BROTLI_OPERATION_FINISH.\n * Under some circumstances (e.g. lack of output stream capacity) this operation\n * would require several calls to ::BrotliEncoderCompressStream. The method must\n * be called again until both input stream is depleted and encoder has no more\n * output (see ::BrotliEncoderHasMoreOutput) after the method is called.\n *\n * @warning When flushing and finishing, @p op should not change until operation\n *          is complete; input stream should not be swapped, reduced or\n *          extended as well.\n *\n * @param state encoder instance\n * @param op requested operation\n * @param[in, out] available_in @b in: amount of available input; \\n\n *                 @b out: amount of unused input\n * @param[in, out] next_in pointer to the next input byte\n * @param[in, out] available_out @b in: length of output buffer; \\n\n *                 @b out: remaining size of output buffer\n * @param[in, out] next_out compressed output buffer cursor;\n *                 can be @c NULL if @p available_out is @c 0\n * @param[out] total_out number of bytes produced so far; can be @c NULL\n * @returns ::BROTLI_FALSE if there was an error\n * @returns ::BROTLI_TRUE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderCompressStream(\n    BrotliEncoderState* state, BrotliEncoderOperation op, size_t* available_in,\n    const uint8_t** next_in, size_t* available_out, uint8_t** next_out,\n    size_t* total_out);\n\n/**\n * Checks if encoder instance reached the final state.\n *\n * @param state encoder instance\n * @returns ::BROTLI_TRUE if encoder is in a state where it reached the end of\n *          the input and produced all of the output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderIsFinished(BrotliEncoderState* state);\n\n/**\n * Checks if encoder has more output.\n *\n * @param state encoder instance\n * @returns ::BROTLI_TRUE, if encoder has some unconsumed output\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_ENC_API BROTLI_BOOL BrotliEncoderHasMoreOutput(\n    BrotliEncoderState* state);\n\n/**\n * Acquires pointer to internal output buffer.\n *\n * This method is used to make language bindings easier and more efficient:\n *  -# push data to ::BrotliEncoderCompressStream,\n *     until ::BrotliEncoderHasMoreOutput returns BROTLI_TRUE\n *  -# use ::BrotliEncoderTakeOutput to peek bytes and copy to language-specific\n *     entity\n *\n * Also this could be useful if there is an output stream that is able to\n * consume all the provided data (e.g. when data is saved to file system).\n *\n * @attention After every call to ::BrotliEncoderTakeOutput @p *size bytes of\n *            output are considered consumed for all consecutive calls to the\n *            instance methods; returned pointer becomes invalidated as well.\n *\n * @note Encoder output is not guaranteed to be contiguous. This means that\n *       after the size-unrestricted call to ::BrotliEncoderTakeOutput,\n *       immediate next call to ::BrotliEncoderTakeOutput may return more data.\n *\n * @param state encoder instance\n * @param[in, out] size @b in: number of bytes caller is ready to take, @c 0 if\n *                 any amount could be handled; \\n\n *                 @b out: amount of data pointed by returned pointer and\n *                 considered consumed; \\n\n *                 out value is never greater than in value, unless it is @c 0\n * @returns pointer to output data\n */\nBROTLI_ENC_API const uint8_t* BrotliEncoderTakeOutput(\n    BrotliEncoderState* state, size_t* size);\n\n/* Returns the estimated peak memory usage (in bytes) of the BrotliCompress()\n   function, not counting the memory needed for the input and output. */\nBROTLI_ENC_EXTRA_API size_t BrotliEncoderEstimatePeakMemoryUsage(\n    int quality, int lgwin, size_t input_size);\n/* Returns 0 if dictionary is not valid; otherwise returns allocation size. */\nBROTLI_ENC_EXTRA_API size_t BrotliEncoderGetPreparedDictionarySize(\n    const BrotliEncoderPreparedDictionary* dictionary);\n\n/**\n * Gets an encoder library version.\n *\n * Look at BROTLI_MAKE_HEX_VERSION for more information.\n */\nBROTLI_ENC_API uint32_t BrotliEncoderVersion(void);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_ENC_ENCODE_H_ */\n"
  },
  {
    "path": "third-party/brotli/include/brotli/port.h",
    "content": "/* Copyright 2016 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* Macros for compiler / platform specific API declarations. */\n\n#ifndef BROTLI_COMMON_PORT_H_\n#define BROTLI_COMMON_PORT_H_\n\n/* The following macros were borrowed from https://github.com/nemequ/hedley\n * with permission of original author - Evan Nemerson <evan@nemerson.com> */\n\n/* >>> >>> >>> hedley macros */\n\n#define BROTLI_MAKE_VERSION(major, minor, revision) \\\n  (((major) * 1000000) + ((minor) * 1000) + (revision))\n\n#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)\n#define BROTLI_GNUC_VERSION \\\n  BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)\n#elif defined(__GNUC__)\n#define BROTLI_GNUC_VERSION BROTLI_MAKE_VERSION(__GNUC__, __GNUC_MINOR__, 0)\n#endif\n\n#if defined(BROTLI_GNUC_VERSION)\n#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_GNUC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_GNUC_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000)\n#define BROTLI_MSVC_VERSION                                \\\n  BROTLI_MAKE_VERSION((_MSC_FULL_VER / 10000000),          \\\n                      (_MSC_FULL_VER % 10000000) / 100000, \\\n                      (_MSC_FULL_VER % 100000) / 100)\n#elif defined(_MSC_FULL_VER)\n#define BROTLI_MSVC_VERSION                              \\\n  BROTLI_MAKE_VERSION((_MSC_FULL_VER / 1000000),         \\\n                      (_MSC_FULL_VER % 1000000) / 10000, \\\n                      (_MSC_FULL_VER % 10000) / 10)\n#elif defined(_MSC_VER)\n#define BROTLI_MSVC_VERSION \\\n  BROTLI_MAKE_VERSION(_MSC_VER / 100, _MSC_VER % 100, 0)\n#endif\n\n#if !defined(_MSC_VER)\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) (0)\n#elif defined(_MSC_VER) && (_MSC_VER >= 1400)\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \\\n  (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))\n#elif defined(_MSC_VER) && (_MSC_VER >= 1200)\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \\\n  (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))\n#else\n#define BROTLI_MSVC_VERSION_CHECK(major, minor, patch) \\\n  (_MSC_VER >= ((major * 100) + (minor)))\n#endif\n\n#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE)\n#define BROTLI_INTEL_VERSION                   \\\n  BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100,  \\\n                      __INTEL_COMPILER % 100,  \\\n                      __INTEL_COMPILER_UPDATE)\n#elif defined(__INTEL_COMPILER)\n#define BROTLI_INTEL_VERSION \\\n  BROTLI_MAKE_VERSION(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)\n#endif\n\n#if defined(BROTLI_INTEL_VERSION)\n#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_INTEL_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_INTEL_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__PGI) && \\\n    defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)\n#define BROTLI_PGI_VERSION \\\n  BROTLI_MAKE_VERSION(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)\n#endif\n\n#if defined(BROTLI_PGI_VERSION)\n#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_PGI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_PGI_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)\n#define BROTLI_SUNPRO_VERSION                                       \\\n  BROTLI_MAKE_VERSION(                                              \\\n    (((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), \\\n    (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf),   \\\n    (__SUNPRO_C & 0xf) * 10)\n#elif defined(__SUNPRO_C)\n#define BROTLI_SUNPRO_VERSION                  \\\n  BROTLI_MAKE_VERSION((__SUNPRO_C >> 8) & 0xf, \\\n                      (__SUNPRO_C >> 4) & 0xf, \\\n                      (__SUNPRO_C) & 0xf)\n#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)\n#define BROTLI_SUNPRO_VERSION                                         \\\n  BROTLI_MAKE_VERSION(                                                \\\n    (((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), \\\n    (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf),   \\\n    (__SUNPRO_CC & 0xf) * 10)\n#elif defined(__SUNPRO_CC)\n#define BROTLI_SUNPRO_VERSION                   \\\n  BROTLI_MAKE_VERSION((__SUNPRO_CC >> 8) & 0xf, \\\n                      (__SUNPRO_CC >> 4) & 0xf, \\\n                      (__SUNPRO_CC) & 0xf)\n#endif\n\n#if defined(BROTLI_SUNPRO_VERSION)\n#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_SUNPRO_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_SUNPRO_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)\n#define BROTLI_ARM_VERSION                                       \\\n  BROTLI_MAKE_VERSION((__ARMCOMPILER_VERSION / 1000000),         \\\n                      (__ARMCOMPILER_VERSION % 1000000) / 10000, \\\n                      (__ARMCOMPILER_VERSION % 10000) / 100)\n#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)\n#define BROTLI_ARM_VERSION                                 \\\n  BROTLI_MAKE_VERSION((__ARMCC_VERSION / 1000000),         \\\n                      (__ARMCC_VERSION % 1000000) / 10000, \\\n                      (__ARMCC_VERSION % 10000) / 100)\n#endif\n\n#if defined(BROTLI_ARM_VERSION)\n#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_ARM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_ARM_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__ibmxl__)\n#define BROTLI_IBM_VERSION                    \\\n  BROTLI_MAKE_VERSION(__ibmxl_version__,      \\\n                      __ibmxl_release__,      \\\n                      __ibmxl_modification__)\n#elif defined(__xlC__) && defined(__xlC_ver__)\n#define BROTLI_IBM_VERSION \\\n  BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)\n#elif defined(__xlC__)\n#define BROTLI_IBM_VERSION BROTLI_MAKE_VERSION(__xlC__ >> 8, __xlC__ & 0xff, 0)\n#endif\n\n#if defined(BROTLI_IBM_VERSION)\n#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_IBM_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_IBM_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__TI_COMPILER_VERSION__)\n#define BROTLI_TI_VERSION                                         \\\n  BROTLI_MAKE_VERSION((__TI_COMPILER_VERSION__ / 1000000),        \\\n                      (__TI_COMPILER_VERSION__ % 1000000) / 1000, \\\n                      (__TI_COMPILER_VERSION__ % 1000))\n#endif\n\n#if defined(BROTLI_TI_VERSION)\n#define BROTLI_TI_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_TI_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_TI_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__IAR_SYSTEMS_ICC__)\n#if __VER__ > 1000\n#define BROTLI_IAR_VERSION                     \\\n  BROTLI_MAKE_VERSION((__VER__ / 1000000),     \\\n                      (__VER__ / 1000) % 1000, \\\n                      (__VER__ % 1000))\n#else\n#define BROTLI_IAR_VERSION BROTLI_MAKE_VERSION(VER / 100, __VER__ % 100, 0)\n#endif\n#endif\n\n#if defined(BROTLI_IAR_VERSION)\n#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_IAR_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_IAR_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__TINYC__)\n#define BROTLI_TINYC_VERSION \\\n  BROTLI_MAKE_VERSION(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)\n#endif\n\n#if defined(BROTLI_TINYC_VERSION)\n#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) \\\n  (BROTLI_TINYC_VERSION >= BROTLI_MAKE_VERSION(major, minor, patch))\n#else\n#define BROTLI_TINYC_VERSION_CHECK(major, minor, patch) (0)\n#endif\n\n#if defined(__has_attribute)\n#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \\\n  __has_attribute(attribute)\n#else\n#define BROTLI_GNUC_HAS_ATTRIBUTE(attribute, major, minor, patch) \\\n  BROTLI_GNUC_VERSION_CHECK(major, minor, patch)\n#endif\n\n#if defined(__has_builtin)\n#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \\\n  __has_builtin(builtin)\n#else\n#define BROTLI_GNUC_HAS_BUILTIN(builtin, major, minor, patch) \\\n  BROTLI_GNUC_VERSION_CHECK(major, minor, patch)\n#endif\n\n#if defined(__has_feature)\n#define BROTLI_HAS_FEATURE(feature) __has_feature(feature)\n#else\n#define BROTLI_HAS_FEATURE(feature) (0)\n#endif\n\n#if defined(_WIN32) || defined(__CYGWIN__)\n#define BROTLI_PUBLIC\n#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) ||                         \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                             \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                         \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                            \\\n    BROTLI_IBM_VERSION_CHECK(13, 1, 0) ||                           \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) &&                            \\\n     defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))\n#define BROTLI_PUBLIC __attribute__ ((visibility (\"default\")))\n#else\n#define BROTLI_PUBLIC\n#endif\n\n/* BROTLI_INTERNAL could be defined to override visibility, e.g. for tests. */\n#if !defined(BROTLI_INTERNAL)\n#if defined(_WIN32) || defined(__CYGWIN__)\n#define BROTLI_INTERNAL\n#elif BROTLI_GNUC_VERSION_CHECK(3, 3, 0) ||                         \\\n    BROTLI_TI_VERSION_CHECK(8, 0, 0) ||                             \\\n    BROTLI_INTEL_VERSION_CHECK(16, 0, 0) ||                         \\\n    BROTLI_ARM_VERSION_CHECK(4, 1, 0) ||                            \\\n    BROTLI_IBM_VERSION_CHECK(13, 1, 0) ||                           \\\n    BROTLI_SUNPRO_VERSION_CHECK(5, 11, 0) ||                        \\\n    (BROTLI_TI_VERSION_CHECK(7, 3, 0) &&                            \\\n     defined(__TI_GNU_ATTRIBUTE_SUPPORT__) && defined(__TI_EABI__))\n#define BROTLI_INTERNAL __attribute__ ((visibility (\"hidden\")))\n#else\n#define BROTLI_INTERNAL\n#endif\n#endif\n\n#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) &&   \\\n    !defined(__STDC_NO_VLA__) && !defined(__cplusplus) &&           \\\n    !defined(__PGI) && !defined(__PGIC__) && !defined(__TINYC__) && \\\n    !defined(__clang__)\n#define BROTLI_ARRAY_PARAM(name) (name)\n#else\n#define BROTLI_ARRAY_PARAM(name)\n#endif\n\n/* <<< <<< <<< end of hedley macros. */\n\n#if defined(BROTLI_SHARED_COMPILATION)\n#if defined(_WIN32)\n#if defined(BROTLICOMMON_SHARED_COMPILATION)\n#define BROTLI_COMMON_API __declspec(dllexport)\n#else\n#define BROTLI_COMMON_API __declspec(dllimport)\n#endif  /* BROTLICOMMON_SHARED_COMPILATION */\n#if defined(BROTLIDEC_SHARED_COMPILATION)\n#define BROTLI_DEC_API __declspec(dllexport)\n#else\n#define BROTLI_DEC_API __declspec(dllimport)\n#endif  /* BROTLIDEC_SHARED_COMPILATION */\n#if defined(BROTLIENC_SHARED_COMPILATION)\n#define BROTLI_ENC_API __declspec(dllexport)\n#else\n#define BROTLI_ENC_API __declspec(dllimport)\n#endif  /* BROTLIENC_SHARED_COMPILATION */\n#else  /* _WIN32 */\n#define BROTLI_COMMON_API BROTLI_PUBLIC\n#define BROTLI_DEC_API BROTLI_PUBLIC\n#define BROTLI_ENC_API BROTLI_PUBLIC\n#endif  /* _WIN32 */\n#else  /* BROTLI_SHARED_COMPILATION */\n#define BROTLI_COMMON_API\n#define BROTLI_DEC_API\n#define BROTLI_ENC_API\n#endif\n\n#if defined(BROTLI_BUILD_ENC_EXTRA_API)\n#define BROTLI_ENC_EXTRA_API BROTLI_ENC_API\n#else\n#define BROTLI_ENC_EXTRA_API BROTLI_INTERNAL\n#endif\n\n#endif  /* BROTLI_COMMON_PORT_H_ */\n"
  },
  {
    "path": "third-party/brotli/include/brotli/shared_dictionary.h",
    "content": "/* Copyright 2017 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/* (Opaque) Shared Dictionary definition and utilities. */\n\n#ifndef BROTLI_COMMON_SHARED_DICTIONARY_H_\n#define BROTLI_COMMON_SHARED_DICTIONARY_H_\n\n#include <brotli/port.h>\n#include <brotli/types.h>\n\n#if defined(__cplusplus) || defined(c_plusplus)\nextern \"C\" {\n#endif\n\n#define SHARED_BROTLI_MIN_DICTIONARY_WORD_LENGTH 4\n#define SHARED_BROTLI_MAX_DICTIONARY_WORD_LENGTH 31\n#define SHARED_BROTLI_NUM_DICTIONARY_CONTEXTS 64\n#define SHARED_BROTLI_MAX_COMPOUND_DICTS 15\n\n/**\n * Opaque structure that holds shared dictionary data.\n *\n * Allocated and initialized with ::BrotliSharedDictionaryCreateInstance.\n * Cleaned up and deallocated with ::BrotliSharedDictionaryDestroyInstance.\n */\ntypedef struct BrotliSharedDictionaryStruct BrotliSharedDictionary;\n\n/**\n * Input data type for ::BrotliSharedDictionaryAttach.\n */\ntypedef enum BrotliSharedDictionaryType {\n  /** Raw LZ77 prefix dictionary. */\n  BROTLI_SHARED_DICTIONARY_RAW = 0,\n  /** Serialized shared dictionary.\n   *\n   * DO NOT USE: methods accepting this value will fail.\n   */\n  BROTLI_SHARED_DICTIONARY_SERIALIZED = 1\n} BrotliSharedDictionaryType;\n\n/**\n * Creates an instance of ::BrotliSharedDictionary.\n *\n * Fresh instance has default word dictionary and transforms\n * and no LZ77 prefix dictionary.\n *\n * @p alloc_func and @p free_func @b MUST be both zero or both non-zero. In the\n * case they are both zero, default memory allocators are used. @p opaque is\n * passed to @p alloc_func and @p free_func when they are called. @p free_func\n * has to return without doing anything when asked to free a NULL pointer.\n *\n * @param alloc_func custom memory allocation function\n * @param free_func custom memory free function\n * @param opaque custom memory manager handle\n * @returns @c 0 if instance can not be allocated or initialized\n * @returns pointer to initialized ::BrotliSharedDictionary otherwise\n */\nBROTLI_COMMON_API BrotliSharedDictionary* BrotliSharedDictionaryCreateInstance(\n    brotli_alloc_func alloc_func, brotli_free_func free_func, void* opaque);\n\n/**\n * Deinitializes and frees ::BrotliSharedDictionary instance.\n *\n * @param dict shared dictionary instance to be cleaned up and deallocated\n */\nBROTLI_COMMON_API void BrotliSharedDictionaryDestroyInstance(\n    BrotliSharedDictionary* dict);\n\n/**\n * Attaches dictionary to a given instance of ::BrotliSharedDictionary.\n *\n * Dictionary to be attached is represented in a serialized format as a region\n * of memory.\n *\n * Provided data it partially referenced by a resulting (compound) dictionary,\n * and should be kept untouched, while at least one compound dictionary uses it.\n * This way memory overhead is kept minimal by the cost of additional resource\n * management.\n *\n * @param dict dictionary to extend\n * @param type type of dictionary to attach\n * @param data_size size of @p data\n * @param data serialized dictionary of type @p type, with at least @p data_size\n *        addressable bytes\n * @returns ::BROTLI_TRUE if provided dictionary is successfully attached\n * @returns ::BROTLI_FALSE otherwise\n */\nBROTLI_COMMON_API BROTLI_BOOL BrotliSharedDictionaryAttach(\n    BrotliSharedDictionary* dict, BrotliSharedDictionaryType type,\n    size_t data_size, const uint8_t data[BROTLI_ARRAY_PARAM(data_size)]);\n\n#if defined(__cplusplus) || defined(c_plusplus)\n}  /* extern \"C\" */\n#endif\n\n#endif  /* BROTLI_COMMON_SHARED_DICTIONARY_H_ */\n"
  },
  {
    "path": "third-party/brotli/include/brotli/types.h",
    "content": "/* Copyright 2013 Google Inc. All Rights Reserved.\n\n   Distributed under MIT license.\n   See file LICENSE for detail or copy at https://opensource.org/licenses/MIT\n*/\n\n/**\n * @file\n * Common types used in decoder and encoder API.\n */\n\n#ifndef BROTLI_COMMON_TYPES_H_\n#define BROTLI_COMMON_TYPES_H_\n\n#include <stddef.h>  /* for size_t */\n\n#if defined(_MSC_VER) && (_MSC_VER < 1600)\ntypedef __int8 int8_t;\ntypedef unsigned __int8 uint8_t;\ntypedef __int16 int16_t;\ntypedef unsigned __int16 uint16_t;\ntypedef __int32 int32_t;\ntypedef unsigned __int32 uint32_t;\ntypedef unsigned __int64 uint64_t;\ntypedef __int64 int64_t;\n#else\n#include <stdint.h>\n#endif  /* defined(_MSC_VER) && (_MSC_VER < 1600) */\n\n/**\n * A portable @c bool replacement.\n *\n * ::BROTLI_BOOL is a \"documentation\" type: actually it is @c int, but in API it\n * denotes a type, whose only values are ::BROTLI_TRUE and ::BROTLI_FALSE.\n *\n * ::BROTLI_BOOL values passed to Brotli should either be ::BROTLI_TRUE or\n * ::BROTLI_FALSE, or be a result of ::TO_BROTLI_BOOL macros.\n *\n * ::BROTLI_BOOL values returned by Brotli should not be tested for equality\n * with @c true, @c false, ::BROTLI_TRUE, ::BROTLI_FALSE, but rather should be\n * evaluated, for example: @code{.cpp}\n * if (SomeBrotliFunction(encoder, BROTLI_TRUE) &&\n *     !OtherBrotliFunction(decoder, BROTLI_FALSE)) {\n *   bool x = !!YetAnotherBrotliFunction(encoder, TO_BROLTI_BOOL(2 * 2 == 4));\n *   DoSomething(x);\n * }\n * @endcode\n */\n#define BROTLI_BOOL int\n/** Portable @c true replacement. */\n#define BROTLI_TRUE 1\n/** Portable @c false replacement. */\n#define BROTLI_FALSE 0\n/** @c bool to ::BROTLI_BOOL conversion macros. */\n#define TO_BROTLI_BOOL(X) (!!(X) ? BROTLI_TRUE : BROTLI_FALSE)\n\n#define BROTLI_MAKE_UINT64_T(high, low) ((((uint64_t)(high)) << 32) | low)\n\n#define BROTLI_UINT32_MAX (~((uint32_t)0))\n#define BROTLI_SIZE_MAX (~((size_t)0))\n\n/**\n * Allocating function pointer type.\n *\n * @param opaque custom memory manager handle provided by client\n * @param size requested memory region size; can not be @c 0\n * @returns @c 0 in the case of failure\n * @returns a valid pointer to a memory region of at least @p size bytes\n *          long otherwise\n */\ntypedef void* (*brotli_alloc_func)(void* opaque, size_t size);\n\n/**\n * Deallocating function pointer type.\n *\n * This function @b SHOULD do nothing if @p address is @c 0.\n *\n * @param opaque custom memory manager handle provided by client\n * @param address memory region pointer returned by ::brotli_alloc_func, or @c 0\n */\ntypedef void (*brotli_free_func)(void* opaque, void* address);\n\n#endif  /* BROTLI_COMMON_TYPES_H_ */\n"
  },
  {
    "path": "third-party/gdb/32bit-avx.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.avx\">\n  <reg name=\"ymm0h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm1h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm2h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm3h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm4h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm5h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm6h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm7h\" bitsize=\"128\" type=\"uint128\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/32bit-avx512.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2014-2024 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.avx512\">\n    <vector id=\"v2ui128\" type=\"uint128\" count=\"2\"/>\n    <reg name=\"zmm0h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm1h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm2h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm3h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm4h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm5h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm6h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm7h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"k0\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k1\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k2\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k3\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k4\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k5\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k6\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k7\" bitsize=\"64\" type=\"uint64\"/>\n  </feature>\n\n"
  },
  {
    "path": "third-party/gdb/32bit-core.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.core\">\n  <flags id=\"i386_eflags\" size=\"4\">\n    <field name=\"CF\" start=\"0\" end=\"0\"/>\n    <field name=\"\" start=\"1\" end=\"1\"/>\n    <field name=\"PF\" start=\"2\" end=\"2\"/>\n    <field name=\"AF\" start=\"4\" end=\"4\"/>\n    <field name=\"ZF\" start=\"6\" end=\"6\"/>\n    <field name=\"SF\" start=\"7\" end=\"7\"/>\n    <field name=\"TF\" start=\"8\" end=\"8\"/>\n    <field name=\"IF\" start=\"9\" end=\"9\"/>\n    <field name=\"DF\" start=\"10\" end=\"10\"/>\n    <field name=\"OF\" start=\"11\" end=\"11\"/>\n    <field name=\"NT\" start=\"14\" end=\"14\"/>\n    <field name=\"RF\" start=\"16\" end=\"16\"/>\n    <field name=\"VM\" start=\"17\" end=\"17\"/>\n    <field name=\"AC\" start=\"18\" end=\"18\"/>\n    <field name=\"VIF\" start=\"19\" end=\"19\"/>\n    <field name=\"VIP\" start=\"20\" end=\"20\"/>\n    <field name=\"ID\" start=\"21\" end=\"21\"/>\n  </flags>\n\n  <reg name=\"eax\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"ecx\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"edx\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"ebx\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"esp\" bitsize=\"32\" type=\"data_ptr\"/>\n  <reg name=\"ebp\" bitsize=\"32\" type=\"data_ptr\"/>\n  <reg name=\"esi\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"edi\" bitsize=\"32\" type=\"int32\"/>\n\n  <reg name=\"eip\" bitsize=\"32\" type=\"code_ptr\"/>\n  <reg name=\"eflags\" bitsize=\"32\" type=\"i386_eflags\"/>\n  <reg name=\"cs\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"ss\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"ds\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"es\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"fs\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"gs\" bitsize=\"32\" type=\"int32\"/>\n\n  <reg name=\"st0\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st1\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st2\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st3\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st4\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st5\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st6\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st7\" bitsize=\"80\" type=\"i387_ext\"/>\n\n  <reg name=\"fctrl\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fstat\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"ftag\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fiseg\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fioff\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"foseg\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fooff\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fop\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/32bit-linux.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.linux\">\n  <reg name=\"orig_eax\" bitsize=\"32\" type=\"int\" regnum=\"41\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/32bit-pkeys.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2016-2021 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.pkeys\">\n\n  <reg name=\"pkru\" bitsize=\"32\" type=\"uint32\"/>\n\n</feature>\n"
  },
  {
    "path": "third-party/gdb/32bit-sse.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.sse\">\n  <vector id=\"v4f\" type=\"ieee_single\" count=\"4\"/>\n  <vector id=\"v2d\" type=\"ieee_double\" count=\"2\"/>\n  <vector id=\"v16i8\" type=\"int8\" count=\"16\"/>\n  <vector id=\"v8i16\" type=\"int16\" count=\"8\"/>\n  <vector id=\"v4i32\" type=\"int32\" count=\"4\"/>\n  <vector id=\"v2i64\" type=\"int64\" count=\"2\"/>\n  <union id=\"vec128\">\n    <field name=\"v4_float\" type=\"v4f\"/>\n    <field name=\"v2_double\" type=\"v2d\"/>\n    <field name=\"v16_int8\" type=\"v16i8\"/>\n    <field name=\"v8_int16\" type=\"v8i16\"/>\n    <field name=\"v4_int32\" type=\"v4i32\"/>\n    <field name=\"v2_int64\" type=\"v2i64\"/>\n    <field name=\"uint128\" type=\"uint128\"/>\n  </union>\n  <flags id=\"i386_mxcsr\" size=\"4\">\n    <field name=\"IE\" start=\"0\" end=\"0\"/>\n    <field name=\"DE\" start=\"1\" end=\"1\"/>\n    <field name=\"ZE\" start=\"2\" end=\"2\"/>\n    <field name=\"OE\" start=\"3\" end=\"3\"/>\n    <field name=\"UE\" start=\"4\" end=\"4\"/>\n    <field name=\"PE\" start=\"5\" end=\"5\"/>\n    <field name=\"DAZ\" start=\"6\" end=\"6\"/>\n    <field name=\"IM\" start=\"7\" end=\"7\"/>\n    <field name=\"DM\" start=\"8\" end=\"8\"/>\n    <field name=\"ZM\" start=\"9\" end=\"9\"/>\n    <field name=\"OM\" start=\"10\" end=\"10\"/>\n    <field name=\"UM\" start=\"11\" end=\"11\"/>\n    <field name=\"PM\" start=\"12\" end=\"12\"/>\n    <field name=\"FZ\" start=\"15\" end=\"15\"/>\n  </flags>\n\n  <reg name=\"xmm0\" bitsize=\"128\" type=\"vec128\" regnum=\"32\"/>\n  <reg name=\"xmm1\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm2\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm3\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm4\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm5\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm6\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm7\" bitsize=\"128\" type=\"vec128\"/>\n\n  <reg name=\"mxcsr\" bitsize=\"32\" type=\"i386_mxcsr\" group=\"vector\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/64bit-avx.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.avx\">\n  <reg name=\"ymm0h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm1h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm2h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm3h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm4h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm5h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm6h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm7h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm8h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm9h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm10h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm11h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm12h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm13h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm14h\" bitsize=\"128\" type=\"uint128\"/>\n  <reg name=\"ymm15h\" bitsize=\"128\" type=\"uint128\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/64bit-avx512.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2014-2024 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.avx512\">\n    <vector id=\"v8bf16\" type=\"bfloat16\" count=\"8\"/>\n    <vector id=\"v8h\" type=\"ieee_half\" count=\"8\"/>\n    <vector id=\"v4f\" type=\"ieee_single\" count=\"4\"/>\n    <vector id=\"v2d\" type=\"ieee_double\" count=\"2\"/>\n    <vector id=\"v16i8\" type=\"int8\" count=\"16\"/>\n    <vector id=\"v8i16\" type=\"int16\" count=\"8\"/>\n    <vector id=\"v4i32\" type=\"int32\" count=\"4\"/>\n    <vector id=\"v2i64\" type=\"int64\" count=\"2\"/>\n    <union id=\"vec128\">\n      <field name=\"v8_bfloat16\" type=\"v8bf16\"/>\n      <field name=\"v8_half\" type=\"v8h\"/>\n      <field name=\"v4_float\" type=\"v4f\"/>\n      <field name=\"v2_double\" type=\"v2d\"/>\n      <field name=\"v16_int8\" type=\"v16i8\"/>\n      <field name=\"v8_int16\" type=\"v8i16\"/>\n      <field name=\"v4_int32\" type=\"v4i32\"/>\n      <field name=\"v2_int64\" type=\"v2i64\"/>\n      <field name=\"uint128\" type=\"uint128\"/>\n    </union>\n    <vector id=\"v2ui128\" type=\"uint128\" count=\"2\"/>\n    <reg name=\"xmm16\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm17\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm18\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm19\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm20\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm21\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm22\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm23\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm24\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm25\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm26\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm27\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm28\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm29\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm30\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"xmm31\" bitsize=\"128\" type=\"vec128\"/>\n    <reg name=\"ymm16h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm17h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm18h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm19h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm20h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm21h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm22h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm23h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm24h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm25h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm26h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm27h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm28h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm29h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm30h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"ymm31h\" bitsize=\"128\" type=\"uint128\"/>\n    <reg name=\"zmm0h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm1h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm2h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm3h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm4h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm5h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm6h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm7h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm8h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm9h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm10h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm11h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm12h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm13h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm14h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm15h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm16h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm17h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm18h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm19h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm20h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm21h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm22h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm23h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm24h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm25h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm26h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm27h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm28h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm29h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm30h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"zmm31h\" bitsize=\"256\" type=\"v2ui128\"/>\n    <reg name=\"k0\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k1\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k2\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k3\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k4\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k5\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k6\" bitsize=\"64\" type=\"uint64\"/>\n    <reg name=\"k7\" bitsize=\"64\" type=\"uint64\"/>\n  </feature>\n\n"
  },
  {
    "path": "third-party/gdb/64bit-core.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.core\">\n  <flags id=\"i386_eflags\" size=\"4\">\n    <field name=\"CF\" start=\"0\" end=\"0\"/>\n    <field name=\"\" start=\"1\" end=\"1\"/>\n    <field name=\"PF\" start=\"2\" end=\"2\"/>\n    <field name=\"AF\" start=\"4\" end=\"4\"/>\n    <field name=\"ZF\" start=\"6\" end=\"6\"/>\n    <field name=\"SF\" start=\"7\" end=\"7\"/>\n    <field name=\"TF\" start=\"8\" end=\"8\"/>\n    <field name=\"IF\" start=\"9\" end=\"9\"/>\n    <field name=\"DF\" start=\"10\" end=\"10\"/>\n    <field name=\"OF\" start=\"11\" end=\"11\"/>\n    <field name=\"NT\" start=\"14\" end=\"14\"/>\n    <field name=\"RF\" start=\"16\" end=\"16\"/>\n    <field name=\"VM\" start=\"17\" end=\"17\"/>\n    <field name=\"AC\" start=\"18\" end=\"18\"/>\n    <field name=\"VIF\" start=\"19\" end=\"19\"/>\n    <field name=\"VIP\" start=\"20\" end=\"20\"/>\n    <field name=\"ID\" start=\"21\" end=\"21\"/>\n  </flags>\n\n  <reg name=\"rax\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"rbx\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"rcx\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"rdx\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"rsi\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"rdi\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"rbp\" bitsize=\"64\" type=\"data_ptr\"/>\n  <reg name=\"rsp\" bitsize=\"64\" type=\"data_ptr\"/>\n  <reg name=\"r8\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r9\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r10\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r11\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r12\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r13\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r14\" bitsize=\"64\" type=\"int64\"/>\n  <reg name=\"r15\" bitsize=\"64\" type=\"int64\"/>\n\n  <reg name=\"rip\" bitsize=\"64\" type=\"code_ptr\"/>\n  <reg name=\"eflags\" bitsize=\"32\" type=\"i386_eflags\"/>\n  <reg name=\"cs\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"ss\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"ds\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"es\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"fs\" bitsize=\"32\" type=\"int32\"/>\n  <reg name=\"gs\" bitsize=\"32\" type=\"int32\"/>\n\n  <reg name=\"st0\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st1\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st2\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st3\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st4\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st5\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st6\" bitsize=\"80\" type=\"i387_ext\"/>\n  <reg name=\"st7\" bitsize=\"80\" type=\"i387_ext\"/>\n\n  <reg name=\"fctrl\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fstat\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"ftag\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fiseg\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fioff\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"foseg\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fooff\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n  <reg name=\"fop\" bitsize=\"32\" type=\"int\" group=\"float\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/64bit-linux.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.linux\">\n  <reg name=\"orig_rax\" bitsize=\"64\" type=\"int\" regnum=\"57\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/64bit-pkeys.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2016-2021 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.pkeys\">\n\n  <reg name=\"pkru\" bitsize=\"32\" type=\"uint32\"/>\n\n</feature>\n"
  },
  {
    "path": "third-party/gdb/64bit-seg.xml",
    "content": "<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.segments\">\n  <reg name=\"fs_base\" bitsize=\"64\" type=\"data_ptr\"/>\n  <reg name=\"gs_base\" bitsize=\"64\" type=\"data_ptr\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/64bit-sse.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2010-2014 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.i386.sse\">\n  <vector id=\"v4f\" type=\"ieee_single\" count=\"4\"/>\n  <vector id=\"v2d\" type=\"ieee_double\" count=\"2\"/>\n  <vector id=\"v16i8\" type=\"int8\" count=\"16\"/>\n  <vector id=\"v8i16\" type=\"int16\" count=\"8\"/>\n  <vector id=\"v4i32\" type=\"int32\" count=\"4\"/>\n  <vector id=\"v2i64\" type=\"int64\" count=\"2\"/>\n  <union id=\"vec128\">\n    <field name=\"v4_float\" type=\"v4f\"/>\n    <field name=\"v2_double\" type=\"v2d\"/>\n    <field name=\"v16_int8\" type=\"v16i8\"/>\n    <field name=\"v8_int16\" type=\"v8i16\"/>\n    <field name=\"v4_int32\" type=\"v4i32\"/>\n    <field name=\"v2_int64\" type=\"v2i64\"/>\n    <field name=\"uint128\" type=\"uint128\"/>\n  </union>\n  <flags id=\"i386_mxcsr\" size=\"4\">\n    <field name=\"IE\" start=\"0\" end=\"0\"/>\n    <field name=\"DE\" start=\"1\" end=\"1\"/>\n    <field name=\"ZE\" start=\"2\" end=\"2\"/>\n    <field name=\"OE\" start=\"3\" end=\"3\"/>\n    <field name=\"UE\" start=\"4\" end=\"4\"/>\n    <field name=\"PE\" start=\"5\" end=\"5\"/>\n    <field name=\"DAZ\" start=\"6\" end=\"6\"/>\n    <field name=\"IM\" start=\"7\" end=\"7\"/>\n    <field name=\"DM\" start=\"8\" end=\"8\"/>\n    <field name=\"ZM\" start=\"9\" end=\"9\"/>\n    <field name=\"OM\" start=\"10\" end=\"10\"/>\n    <field name=\"UM\" start=\"11\" end=\"11\"/>\n    <field name=\"PM\" start=\"12\" end=\"12\"/>\n    <field name=\"FZ\" start=\"15\" end=\"15\"/>\n  </flags>\n\n  <reg name=\"xmm0\" bitsize=\"128\" type=\"vec128\" regnum=\"40\"/>\n  <reg name=\"xmm1\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm2\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm3\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm4\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm5\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm6\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm7\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm8\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm9\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm10\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm11\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm12\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm13\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm14\" bitsize=\"128\" type=\"vec128\"/>\n  <reg name=\"xmm15\" bitsize=\"128\" type=\"vec128\"/>\n\n  <reg name=\"mxcsr\" bitsize=\"32\" type=\"i386_mxcsr\" group=\"vector\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/README",
    "content": "These files, with the exception of 64bit-seg.xml, are taken from\nbinutils-gdb/gdb/features, git tag gdb-7.7-release, with the\nfollowing change:\n\n* A reference to 64bit-seg.xml was added to amd64-avx-linux.xml\nand amd64-linux.xml\n\nUsing the latest gdb files we get errors with gdb 10.1 and probably\nearlier versions, which require flags to have both \"start\" and\n\"end\" attributes.\n\nThese files all have the same BSD-ish license (thanks FSF!).\n"
  },
  {
    "path": "third-party/gdb/aarch64-core.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2009-2020 Free Software Foundation, Inc.\n     Contributed by ARM Ltd.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.aarch64.core\">\n  <reg name=\"x0\" bitsize=\"64\"/>\n  <reg name=\"x1\" bitsize=\"64\"/>\n  <reg name=\"x2\" bitsize=\"64\"/>\n  <reg name=\"x3\" bitsize=\"64\"/>\n  <reg name=\"x4\" bitsize=\"64\"/>\n  <reg name=\"x5\" bitsize=\"64\"/>\n  <reg name=\"x6\" bitsize=\"64\"/>\n  <reg name=\"x7\" bitsize=\"64\"/>\n  <reg name=\"x8\" bitsize=\"64\"/>\n  <reg name=\"x9\" bitsize=\"64\"/>\n  <reg name=\"x10\" bitsize=\"64\"/>\n  <reg name=\"x11\" bitsize=\"64\"/>\n  <reg name=\"x12\" bitsize=\"64\"/>\n  <reg name=\"x13\" bitsize=\"64\"/>\n  <reg name=\"x14\" bitsize=\"64\"/>\n  <reg name=\"x15\" bitsize=\"64\"/>\n  <reg name=\"x16\" bitsize=\"64\"/>\n  <reg name=\"x17\" bitsize=\"64\"/>\n  <reg name=\"x18\" bitsize=\"64\"/>\n  <reg name=\"x19\" bitsize=\"64\"/>\n  <reg name=\"x20\" bitsize=\"64\"/>\n  <reg name=\"x21\" bitsize=\"64\"/>\n  <reg name=\"x22\" bitsize=\"64\"/>\n  <reg name=\"x23\" bitsize=\"64\"/>\n  <reg name=\"x24\" bitsize=\"64\"/>\n  <reg name=\"x25\" bitsize=\"64\"/>\n  <reg name=\"x26\" bitsize=\"64\"/>\n  <reg name=\"x27\" bitsize=\"64\"/>\n  <reg name=\"x28\" bitsize=\"64\"/>\n  <reg name=\"x29\" bitsize=\"64\"/>\n  <reg name=\"x30\" bitsize=\"64\"/>\n  <reg name=\"sp\" bitsize=\"64\" type=\"data_ptr\"/>\n\n  <reg name=\"pc\" bitsize=\"64\" type=\"code_ptr\"/>\n\n  <flags id=\"cpsr_flags\" size=\"4\">\n    <!-- Stack Pointer.  -->\n    <field name=\"SP\" start=\"0\" end=\"0\"/>\n\n    <!-- Exception Level.  -->\n    <field name=\"EL\" start=\"2\" end=\"3\"/>\n    <!-- Execution state.  -->\n    <field name=\"nRW\" start=\"4\" end=\"4\"/>\n\n    <!-- FIQ interrupt mask.  -->\n    <field name=\"F\" start=\"6\" end=\"6\"/>\n    <!-- IRQ interrupt mask.  -->\n    <field name=\"I\" start=\"7\" end=\"7\"/>\n    <!-- SError interrupt mask.  -->\n    <field name=\"A\" start=\"8\" end=\"8\"/>\n    <!-- Debug exception mask.  -->\n    <field name=\"D\" start=\"9\" end=\"9\"/>\n\n    <!-- ARMv8.0-A: Speculative Store Bypass.  -->\n    <field name=\"SSBS\" start=\"12\" end=\"12\"/>\n\n    <!-- Illegal Execution state.  -->\n    <field name=\"IL\" start=\"20\" end=\"20\"/>\n    <!-- Software Step.  -->\n    <field name=\"SS\" start=\"21\" end=\"21\"/>\n    <!-- ARMv8.1-A: Privileged Access Never.  -->\n    <field name=\"PAN\" start=\"22\" end=\"22\"/>\n    <!-- ARMv8.2-A: User Access Override.  -->\n    <field name=\"UAO\" start=\"23\" end=\"23\"/>\n    <!-- ARMv8.4-A: Data Independent Timing.  -->\n    <field name=\"DIT\" start=\"24\" end=\"24\"/>\n    <!-- ARMv8.5-A: Tag Check Override.  -->\n    <field name=\"TCO\" start=\"25\" end=\"25\"/>\n\n    <!-- Overflow Condition flag.  -->\n    <field name=\"V\" start=\"28\" end=\"28\"/>\n    <!-- Carry Condition flag.  -->\n    <field name=\"C\" start=\"29\" end=\"29\"/>\n    <!-- Zero Condition flag.  -->\n    <field name=\"Z\" start=\"30\" end=\"30\"/>\n    <!-- Negative Condition flag.  -->\n    <field name=\"N\" start=\"31\" end=\"31\"/>\n  </flags>\n  <reg name=\"cpsr\" bitsize=\"32\" type=\"cpsr_flags\"/>\n\n</feature>\n"
  },
  {
    "path": "third-party/gdb/aarch64-fpu.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2009-2020 Free Software Foundation, Inc.\n     Contributed by ARM Ltd.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.aarch64.fpu\">\n  <vector id=\"v2d\" type=\"ieee_double\" count=\"2\"/>\n  <vector id=\"v2u\" type=\"uint64\" count=\"2\"/>\n  <vector id=\"v2i\" type=\"int64\" count=\"2\"/>\n  <vector id=\"v4f\" type=\"ieee_single\" count=\"4\"/>\n  <vector id=\"v4u\" type=\"uint32\" count=\"4\"/>\n  <vector id=\"v4i\" type=\"int32\" count=\"4\"/>\n  <vector id=\"v8f\" type=\"ieee_half\" count=\"8\"/>\n  <vector id=\"v8u\" type=\"uint16\" count=\"8\"/>\n  <vector id=\"v8i\" type=\"int16\" count=\"8\"/>\n  <vector id=\"v16u\" type=\"uint8\" count=\"16\"/>\n  <vector id=\"v16i\" type=\"int8\" count=\"16\"/>\n  <vector id=\"v1u\" type=\"uint128\" count=\"1\"/>\n  <vector id=\"v1i\" type=\"int128\" count=\"1\"/>\n  <union id=\"vnd\">\n    <field name=\"f\" type=\"v2d\"/>\n    <field name=\"u\" type=\"v2u\"/>\n    <field name=\"s\" type=\"v2i\"/>\n  </union>\n  <union id=\"vns\">\n    <field name=\"f\" type=\"v4f\"/>\n    <field name=\"u\" type=\"v4u\"/>\n    <field name=\"s\" type=\"v4i\"/>\n  </union>\n  <union id=\"vnh\">\n    <field name=\"f\" type=\"v8f\"/>\n    <field name=\"u\" type=\"v8u\"/>\n    <field name=\"s\" type=\"v8i\"/>\n  </union>\n  <union id=\"vnb\">\n    <field name=\"u\" type=\"v16u\"/>\n    <field name=\"s\" type=\"v16i\"/>\n  </union>\n  <union id=\"vnq\">\n    <field name=\"u\" type=\"v1u\"/>\n    <field name=\"s\" type=\"v1i\"/>\n  </union>\n  <union id=\"aarch64v\">\n    <field name=\"d\" type=\"vnd\"/>\n    <field name=\"s\" type=\"vns\"/>\n    <field name=\"h\" type=\"vnh\"/>\n    <field name=\"b\" type=\"vnb\"/>\n    <field name=\"q\" type=\"vnq\"/>\n  </union>\n  <reg name=\"v0\" bitsize=\"128\" type=\"aarch64v\" regnum=\"34\"/>\n  <reg name=\"v1\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v2\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v3\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v4\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v5\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v6\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v7\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v8\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v9\" bitsize=\"128\" type=\"aarch64v\" />\n  <reg name=\"v10\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v11\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v12\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v13\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v14\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v15\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v16\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v17\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v18\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v19\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v20\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v21\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v22\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v23\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v24\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v25\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v26\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v27\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v28\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v29\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v30\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"v31\" bitsize=\"128\" type=\"aarch64v\"/>\n  <reg name=\"fpsr\" bitsize=\"32\"/>\n  <reg name=\"fpcr\" bitsize=\"32\"/>\n</feature>\n"
  },
  {
    "path": "third-party/gdb/aarch64-pauth.xml",
    "content": "<?xml version=\"1.0\"?>\n<!-- Copyright (C) 2018-2020 Free Software Foundation, Inc.\n\n     Copying and distribution of this file, with or without modification,\n     are permitted in any medium without royalty provided the copyright\n     notice and this notice are preserved.  -->\n\n<!DOCTYPE feature SYSTEM \"gdb-target.dtd\">\n<feature name=\"org.gnu.gdb.aarch64.pauth\">\n  <reg name=\"pauth_dmask\" bitsize=\"64\"/>\n  <reg name=\"pauth_cmask\" bitsize=\"64\"/>\n</feature>\n\n"
  },
  {
    "path": "third-party/proc-service/README",
    "content": "proc_service.h provides some declarations used when implementing the\nAPI used by libthread_db to find TLS locations.\n\nThis file is included in rr because it currently isn't installed by\nglibc.  There is a glibc bug open to address this:\n\n    https://sourceware.org/bugzilla/show_bug.cgi?id=20311\n\nHowever, rather than use the glibc version of this file and attempt to\nunderstand what the LGPL means, we've imported a version from FreeBSD;\nbut slightly modified.  In particular, we:\n\n* Removed __BEGIN_DECLS and __END_DECLS uses\n* Renamed ps_pread and ps_pwrite to match glibc's names\n* Added declarations for ps_getpid and ps_get_thread_area\n* Reordered ps_err_e so that enumerators have the correct values\n"
  },
  {
    "path": "third-party/proc-service/proc_service.h",
    "content": "/*\n * Copyright (c) 2004 David Xu <davidxu@freebsd.org>\n * Copyright (c) 2004 Marcel Moolenaar\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n *\n * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND\n * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE\n * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\n * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS\n * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\n * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY\n * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF\n * SUCH DAMAGE.\n *\n * $FreeBSD: src/include/proc_service.h,v 1.3.2.1 2006/05/17 02:28:14 davidxu Exp $\n */\n\n#ifndef _PROC_SERVICE_H_\n#define\t_PROC_SERVICE_H_\n\n#include <sys/types.h>\n#include <sys/procfs.h>\n\ntypedef enum {\n\tPS_OK = 0,\t\t/* No errors. */\n\tPS_ERR,\t\t\t/* Generic error. */\n\tPS_BADPID,\t\t/* Bad process Id. */\n\tPS_BADLID,\t\t/* Bad LWP Id. */\n\tPS_BADADDR,\t\t/* Bad address. */\n\tPS_NOSYM,\t\t/* Symbol not found. */\n\tPS_NOFREGS,\t\t/* FPU register set not available. */\n} ps_err_e;\n\nstruct ps_prochandle;\t\t/* Opaque type. Defined by the implementor. */\n\nps_err_e ps_lcontinue(struct ps_prochandle *, lwpid_t);\nps_err_e ps_lgetfpregs(struct ps_prochandle *, lwpid_t, prfpregset_t *);\nps_err_e ps_lgetregs(struct ps_prochandle *, lwpid_t, prgregset_t);\nps_err_e ps_lsetfpregs(struct ps_prochandle *, lwpid_t, const prfpregset_t *);\nps_err_e ps_lsetregs(struct ps_prochandle *, lwpid_t, const prgregset_t);\n#ifdef __i386__\nps_err_e ps_lgetxmmregs (struct ps_prochandle *, lwpid_t, char *);\nps_err_e ps_lsetxmmregs (struct ps_prochandle *, lwpid_t, const char *);\n#endif\nps_err_e ps_lstop(struct ps_prochandle *, lwpid_t);\nps_err_e ps_linfo(struct ps_prochandle *, lwpid_t, void *);\nps_err_e ps_pcontinue(struct ps_prochandle *);\nps_err_e ps_pdmodel(struct ps_prochandle *, int *);\nps_err_e ps_pglobal_lookup(struct ps_prochandle *, const char *, const char *,\n    psaddr_t *);\nvoid\t ps_plog(const char *, ...);\nps_err_e ps_pdread(struct ps_prochandle *, psaddr_t, void *, size_t);\nps_err_e ps_pstop(struct ps_prochandle *);\nps_err_e ps_pdwrite(struct ps_prochandle *, psaddr_t, const void *, size_t);\n\npid_t ps_getpid(struct ps_prochandle *);\nps_err_e ps_get_thread_area(const struct ps_prochandle*, lwpid_t, int,\n    psaddr_t *);\n\n#endif /* _PROC_SERVICE_H_ */\n"
  },
  {
    "path": "third-party/zen-pmu-workaround/README",
    "content": "Zen workaround kernel module, Copyright 2020, Mike Hommey.\n\nThis has the same effect as `scripts/zen_workaround.py`, but persists after resuming from sleep.\n\nThere 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.\n\nIf you rely on Secure Boot, assuming you have properly enrolled a new MOK key, you can issue `make signed` to build and sign the kernel module (signature will trigger sudo prompt). It will use the default path of `/var/lib/shim-signed/mok/` for the key.\n"
  },
  {
    "path": "third-party/zen-pmu-workaround/zen_workaround.c",
    "content": "// SPDX-License-Identifier: GPL-2.0-only\n/*\n * Copyright 2020 Mike Hommey <mh@glandium.org>\n * Copyright 2025 RR Community\n*/\n\n#include <linux/module.h>\n#include <linux/tracepoint.h>\n#include <linux/suspend.h>\n#include <linux/version.h>\n#include <asm/msr.h>\n\n#if LINUX_VERSION_CODE < KERNEL_VERSION(6,16,0)\n#define wrmsrq_safe \twrmsrl_safe\n#define rdmsrq_safe \trdmsrl_safe\n#define native_wrmsrq\tnative_wrmsrl\n#endif\n\n#define MODULE_NAME \"zen_workaround\"\n\n#define SPECLOCKMAP_DISABLE BIT_64(54)\n\nstatic u64 set_speclockmap_disable(u64 msr) {\n\treturn msr | SPECLOCKMAP_DISABLE;\n}\n\nstatic u64 unset_speclockmap_disable(u64 msr) {\n\treturn msr & ~SPECLOCKMAP_DISABLE;\n}\n\ntypedef u64 (*edit_msr_func_t)(u64);\n\nstatic void edit_ls_cfg_on_cpu(void *info)\n{\n\tint cpu = get_cpu();\n\tu64 value = 0;\n\n\tif (!rdmsrq_safe(MSR_AMD64_LS_CFG, &value)) {\n\t\tedit_msr_func_t edit_msr = (edit_msr_func_t) info;\n\t\tu64 new_value = edit_msr(value);\n\t\tif (!wrmsrq_safe(MSR_AMD64_LS_CFG, new_value)) {\n\t\t\tpr_info(\"MSR_AMD64_LS_CFG for cpu %d was 0x%llx, setting to 0x%llx\\n\",\n\t\t\t        cpu, value, new_value);\n\t\t} else {\n\t\t\tpr_err(\"MSR_AMD64_LS_CFG for cpu %d was 0x%llx, setting to 0x%llx failed\\n\",\n\t\t\t       cpu, value, new_value);\n\t\t}\n\t}\n\n\tput_cpu();\n}\n\nstatic void do_zen_workaround(edit_msr_func_t edit_msr)\n{\n\tsmp_call_function(edit_ls_cfg_on_cpu, edit_msr, 1);\n\tedit_ls_cfg_on_cpu(edit_msr);\n}\n\nvoid on_write_msr(void *data, unsigned int msr, u64 val, int failed)\n{\n\tif (msr == MSR_AMD64_LS_CFG && !(val & SPECLOCKMAP_DISABLE)) {\n\t\tnative_wrmsrq(MSR_AMD64_LS_CFG, set_speclockmap_disable(val));\n\t}\n}\n\nstatic int install_probe(void)\n{\n\treturn !boot_cpu_has(X86_FEATURE_AMD_SSBD) && !boot_cpu_has(X86_FEATURE_VIRT_SSBD);\n}\n\nstatic int enable_zen_workaround(void)\n{\n\tif (install_probe()) {\n\t\tint ret = tracepoint_probe_register(&__tracepoint_write_msr, on_write_msr, NULL);\n\t\tif (ret) {\n\t\t\tpr_err(\"Registering tracepoint probe failed\\n\");\n\t\t\treturn ret;\n\t\t}\n\t}\n\tdo_zen_workaround(set_speclockmap_disable);\n\treturn 0;\n}\n\nstatic int pm_notification(struct notifier_block *this, unsigned long event, void *ptr)\n{\n\tswitch (event) {\n\t\tcase PM_POST_SUSPEND:\n\t\tcase PM_POST_HIBERNATION:\n\t\tcase PM_POST_RESTORE:\n\t\t\tenable_zen_workaround();\n\t\t\tbreak;\n\t\tcase PM_HIBERNATION_PREPARE:\n\t\tcase PM_SUSPEND_PREPARE:\n\t\t\tif (install_probe()) {\n\t\t\t\ttracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL);\n\t\t\t}\n\t\t\tbreak;\n\t}\n\treturn NOTIFY_DONE;\n}\n\nstatic struct notifier_block pm_notifier = {\n\t.notifier_call = pm_notification,\n};\n\nstatic int __init zen_workaround_init(void)\n{\n\tif (!boot_cpu_has(X86_FEATURE_ZEN)) {\n\t\tpr_err(\"Cannot use the Zen workaround on a non-Zen CPU\\n\");\n\t\treturn -EINVAL;\n\t}\n\tenable_zen_workaround();\n\tregister_pm_notifier(&pm_notifier);\n\treturn 0;\n}\nmodule_init(zen_workaround_init);\n\nstatic void __exit zen_workaround_exit(void)\n{\n\tunregister_pm_notifier(&pm_notifier);\n\tif (install_probe()) {\n\t\ttracepoint_probe_unregister(&__tracepoint_write_msr, on_write_msr, NULL);\n\t}\n\tdo_zen_workaround(unset_speclockmap_disable);\n}\nmodule_exit(zen_workaround_exit);\n\nMODULE_LICENSE(\"GPL\");"
  }
]