{"id":19662231,"url":"https://github.com/efeslab/hippocrates","last_synced_at":"2025-04-28T21:32:03.175Z","repository":{"id":55147069,"uuid":"271061107","full_name":"efeslab/hippocrates","owner":"efeslab","description":"Automatically fixing persistency bugs in PM applications. ASPLOS '21.","archived":false,"fork":false,"pushed_at":"2023-05-10T19:08:27.000Z","size":8796,"stargazers_count":7,"open_issues_count":1,"forks_count":3,"subscribers_count":7,"default_branch":"main","last_synced_at":"2025-04-05T11:11:18.209Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/efeslab.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-06-09T17:01:13.000Z","updated_at":"2024-02-16T00:22:26.000Z","dependencies_parsed_at":"2022-08-14T13:30:47.350Z","dependency_job_id":null,"html_url":"https://github.com/efeslab/hippocrates","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efeslab%2Fhippocrates","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efeslab%2Fhippocrates/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efeslab%2Fhippocrates/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/efeslab%2Fhippocrates/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/efeslab","download_url":"https://codeload.github.com/efeslab/hippocrates/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251391251,"owners_count":21582134,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T16:09:59.830Z","updated_at":"2025-04-28T21:31:58.162Z","avatar_url":"https://github.com/efeslab.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Hippocrates (ASPLOS '21)\n\nThis repository contains the artifact for our ASPLOS '21 paper on Hippocrates,\nan automated tool for fixing PM durability bugs.\n\n### ASPLOS '21 Artifact Evaluation\n\nThe [Artifact Evaluation README](./ArtifactEvaluationREADME.md) contains the README\nfrom the original ASPLOS'21 artifact evaluation process.\nThat README will remain relatively static for legacy purposes, while we will keep\nthe following README more up-to-date.\n\nIf you are curious:\n- The artifact evaluation results are presented [here](https://cknow.io/c/lib/19e2593ed9df4ad5/).\n- The ASPLOS'21 Artifact Evaluation page is available at [ctuning.org](https://ctuning.org/ae/asplos2021.html).\n\n### Requirements\n\nThis has been tested on a server configured with Ubuntu 20.04.1 LTS on a CPU\nthat supports the `clwb` instruction\n(to check if your CPU has this feature enabled, run `lscpu` and look for the\n`clwb` flag, e.g. `lscpu | grep clwb`).\n\nOther requirements can be installed via the `./install-deps.sh` script.\nPython requirements can be found in `requirements.txt`.\n\n\n## Compilation\n\nWe now provide an overview of how to build and run Hippocrates.\nWe provide pre-built binaries in `artifact/prebuilt` as an alternative to\nthe following compilation instructions.\n\n### Building Hippocrates\n\n#### Installing Requirements (optional)\n\nThis step is only needed if setting up Hippocrates on a new machine.\n\n```shell\n# Requires root priviledges (sudo)\n./install-deps.sh\n```\n\n#### [GitHub] Setting up the repository (once)\n\nUse the instructions in this section if you are cloning the repository from\nGitHub. If you are using the Zenodo archive, skip to the Zenodo instructions below.\n\nAfter cloning the repository, you need to set up the submodules, which Hippocrates\ndepends on for both the LLVM pass and for running tests.\n\n```shell\ngit clone https://github.com/efeslab/hippocrates.git\ncd hippocrates\n\ngit submodule init\ngit submodule update --recursive\n```\n\nIf you need to re-initialize the submodules for any reason, try:\n\n```shell\ngit submodule deinit --all -f\ngit submodule init\ngit submodule update --recursive\n```\n\n#### [Zenodo] Setting up the repository (once)\n\nOnly use these instructions if you are using the Zenodo archive.\n\n```shell\nunzip \u003cdownload\u003e\ncd efeslab-hippocrates-\u003crevision#\u003e\n./zenodo-setup.sh\n```\n\nThe `zenodo-setup.sh` script clones the requires submodules without using the\n`git submodule` commands.\n\n#### Compiling Hippocrates\n\nStarting in the root of the repository:\n\n```shell\nsource build.env\n\nmkdir build\ncd build\ncmake ..\n\nmake PMFIXER -j$(nproc)\nmake FLUSHREMOVER -j$(nproc)\nmake PMTEST\n# Must build PMEMCHECK before PMINTRINSICS\nmake PMEMCHECK\nmake PMINTRINSICS\n```\n\n#### Updating the repository\n\nWhen updating the repository, to update any of the files generated in the\n`build` directory, you must rerun the compilation steps to rebuild these files.\nIf any of the dependencies are updated, you must rerun the steps listed in\n\"Building Dependencies\" section (below).\n\nNote that this also includes updates to scripts in the `tools` directory, as\nthey are only copied/configured when the above `make` or `cmake` commands are\nrerun. Just running `git pull` will not automatically apply changes to any\nfiles in the `build` directory.\n\n### Building Dependencies\n\n- wllvm (**optional**, only if installing on a new machine):\n\n```shell\ncd deps/whole-program-llvm\nsudo -H pip3 install -e .\n```\n\n- `pmemcheck`:\n\nThis should already be built, however if you need to rebuild:\n\n```shell\nsource build.env\ncd build\nmake -C $REPO_ROOT/deps/valgrind-pmem clean\nmake PMEMCHECK\n```\n\n- PMDK:\n\n```shell\nsource build.env\ncd build\nmake PMDK\n\ncd $REPO_ROOT/build/deps/pmdk/lib/pmdk_debug\nextract-bc libpmem.so\nextract-bc libpmemobj.so\n```\n\n- memcached-pmem (requires PMDK to be built first)\n\n```shell\nsource build.env\ncd $REPO_ROOT/deps/memcached-pmem\ngit checkout master\ngit pull\n\ncd $REPO_ROOT/build\nmake MEMCACHED_PMEM\n\ncd $REPO_ROOT/build/deps/memcached-pmem/bin/\nllvm-link-8 memcached.bc -o memcached.linked.bc $REPO_ROOT/build/deps/pmdk/lib/pmdk_debug/libpmem.so.bc\n```\n\n- RECIPE (P-CLHT)\n\n```shell\nsource build.env\ncd build\nmake p-clht_example\n\ncd ./deps/RECIPE/P-CLHT/\nextract-bc p-clht_example\nllvm-link-8 p-clht_example.bc --override=../../pmdk/lib/pmdk_debug/libpmem.so.bc \\\n        --override=../../pmdk/lib/pmdk_debug/libpmemobj.so.bc -o p-clht_example.linked.bc\n```\n\n- Redis-pmem:\n\n```shell\n# Note: build.env will define the REPO_ROOT variable\nsource build.env\ncd build\n\nmake REDIS -j$(nproc)\n# do this if it hasn't been done already\nmake FLUSHREMOVER -j$(nproc)\nmake PMEMCHECK -j$(nproc)\nmake PMTEST -j$(nproc)\n\ncd $REPO_ROOT/deps/redis/src\nextract-bc redis-server\nllvm-link-8 redis-server.bc --override=$REPO_ROOT/build/deps/pmdk/lib/pmdk_debug/libpmem.so.bc \\\n        --override=$REPO_ROOT/build/deps/pmdk/lib/pmdk_debug/libpmemobj.so.bc -o redis-server.linked.bc\n```\n\n## Evaluation\n\nThere are three main results from Hippocrates:\n\n1. Fixing all previously reported bugs (§6.1)\n2. The Redis performance experiment (§6.3) (Note: this requires access to real PM.)\n3. Hippocrates's overhead (§6.4)\n\n### 1. Fixing previously reported bugs.\n\n#### PMDK bugs\n\nWe provide a script, `build/verify`, which does the following:\n\n1. Gathers the list of all reproducible bugs listed\n2. Patches PMDK to the correct version for each test\n3. Builds the tests\n4. Runs each test, generating a pmemcheck trace\n5. Fixes each test based on the pmemcheck trace\n6. Reruns each test and confirms that the bugs are no longer present.\n\n**Note**: It is expected that the full test suite takes several hours to run.\n\nTo run this script, do the following:\n\n```shell\ncd build\n./verify\n```\n\nThe output should look like:\n\n```shell\n...\n11 issues resolved:\n[447, 452, 458, 459, 460, 461, 585, 940, 942, 943, 945]\n```\n\nIf you instead want to run each issue individually, run the following:\n```shell\n# Issue 447\n./verify --target obj_toid_TEST0_8bbb0af9c\n\n# Issue 452\n./verify --target obj_constructor_TEST0_8bbb0af9c\n./verify --target obj_constructor_TEST2_8bbb0af9c\n\n# Issue 458\n./verify --target pmemspoil_TEST0_8bbb0af9c\n\n# Issue 459\n./verify --target pmem_memcpy_TEST0_8bbb0af9c\n./verify --target pmem_memcpy_TEST1_8bbb0af9c\n./verify --target pmem_memcpy_TEST2_8bbb0af9c\n./verify --target pmem_memcpy_TEST3_8bbb0af9c\n\n# Issue 460\n./verify --target pmem_memmove_TEST0_0fd509d73\n./verify --target pmem_memmove_TEST1_0fd509d73\n./verify --target pmem_memmove_TEST2_0fd509d73\n./verify --target pmem_memmove_TEST3_0fd509d73\n./verify --target pmem_memmove_TEST4_0fd509d73\n./verify --target pmem_memmove_TEST5_0fd509d73\n./verify --target pmem_memmove_TEST6_0fd509d73\n./verify --target pmem_memmove_TEST7_0fd509d73\n./verify --target pmem_memmove_TEST8_0fd509d73\n./verify --target pmem_memmove_TEST9_0fd509d73\n./verify --target pmem_memmove_TEST10_0fd509d73\n./verify --target pmem_memmove_TEST11_0fd509d73\n\n# Issue 461\n./verify --target pmem_memset_TEST1_0fd509d73\n\n# Issue 585\n./verify --target rpmemd_db_TEST0_60e24d2\n\n# Issue 940\n./verify --target obj_first_next_TEST0_e71dfa41b\n./verify --target obj_first_next_TEST1_e71dfa41b\n\n# Issue 942\n./verify --target obj_mem_TEST0_e71dfa41b\n\n# Issue 943\n./verify --target obj_memops_TEST0_e71dfa41b\n\n# Issue 945\n./verify --target pmem_memset_TEST0_e71dfa41b\n```\n\n\n#### RECIPE bugs\n\nTo reproduce the RECIPE bugs, do the following:\n\n1. First, generate the bug report using pmemcheck:\n```shell\nsource build.env\ncd build\n\nrm /mnt/pmem/pool\n./deps/valgrind-pmem/bin/valgrind --tool=pmemcheck --log-file=recipe.log ./deps/RECIPE/P-CLHT/p-clht_example 100 1\n./parse-trace pmemcheck recipe.log -o recipe.trace\n```\n\n2. Apply Hippocrates to fix the bugs:\n```shell\nsource build.env\ncd build\n\n./apply-fixer ./deps/RECIPE/P-CLHT/p-clht_example.linked.bc recipe.trace -o ./deps/RECIPE/P-CLHT/fixed \\\n        --cxx --extra-opt-args=\"-fix-summary-file=recipe_summary.txt -heuristic-raising -trace-aa\"\n```\n\n3. Rerun pmemcheck and generate a new bug report:\n```shell\nrm -f /mnt/pmem/pool\n./deps/valgrind-pmem/bin/valgrind --tool=pmemcheck --log-file=recipe_fixed.log ./deps/RECIPE/P-CLHT/fixed 100 1\n```\n\n4. Confirm the bug report is empty, thus confirming the bugs are fixed:\n```shell\n./parse-trace pmemcheck recipe_fixed.log -o recipe_fixed.trace\n```\n\nThis should produce output similar to the following:\n```shell\nIdentified trace start\n\n\nIdentified trace end\n...\nPrepare to dump.\n        Num items: 1\nPrepare to write.\nReport written to recipe_fixed.trace\n```\n\n#### memcached-pmem bugs\n\nThis assumes you have run the instructions for building memcached-pmem and pmemcheck, which\nyou can find above.\n\n\nAfter building memcached, the bug-fixing process can be automated as follows:\n\n```shell\nsource build.env\ncd $REPO_ROOT/build\n\n./verify-memcached --help\n./verify-memcached\n```\n\nThe `verify-memcached` can also run over the prebuilt files present in `artifact/prebuilt`\nif you run using the `--use-prebuilt` flag.\n\nFor example:\n\n```shell\nsource build.env\ncd $REPO_ROOT/build\n\n./verify-memcached --use-prebuilt\n```\n\nTo reproduce the memcached-pmem bugs manually, do the following:\n\n1. First, find the bugs and generate a pmemcheck trace:\n\n```shell\nsource build.env\ncd $REPO_ROOT/build/deps/memcached-pmem/bin\n\nLD_LIBRARY_PATH=$(realpath $REPO_ROOT/build/deps/pmdk/lib/pmdk_debug) \\\n        $REPO_ROOT/build/deps/valgrind-pmem/bin/valgrind --tool=pmemcheck \\\n        --log-file=memcached.log ./memcached -m 0 -U 0 -t 1 -A -o \\\n        pslab_file=/mnt/pmem/pool-$(whoami),pslab_size=8,pslab_force\n```\n\nIn a second terminal:\n```shell\nsource build.env\n\ntelnet localhost 11211\n# Commands prefixed with \"\u003e\" are entered inside of telnet\n\u003e set foo 1 0 3\n\u003e bar\n\u003e shutdown\n```\n\nThen parse the trace:\n```shell\n# This can be run in either terminal 1 or 2, but assumes you have run\n# `source build.env` already.\ncd $REPO_ROOT/build\n\n./parse-trace pmemcheck ./deps/memcached-pmem/bin/memcached.log -o ./deps/memcached-pmem/bin/memcached.trace\n```\n\n2. Then, apply Hippocrates:\n```shell\nsource build.env\ncd $REPO_ROOT/build\n\n./apply-fixer ./deps/memcached-pmem/bin/memcached.linked.bc ./deps/memcached-pmem/bin/memcached.trace \\\n        -o ./deps/memcached-pmem/bin/memcached-fixed --keep-files \\\n        --extra-opt-args=\"-fix-summary-file=memcached_summary_time.txt -heuristic-raising -trace-aa\"\n```\n\n3. Repeat steps 1, except using the fixed binary. Then confirm the new binary does not have any bugs:\n\n```shell\n# In terminal 1\nsource build.env\ncd $REPO_ROOT/build/deps/memcached-pmem/bin\n\nLD_LIBRARY_PATH=$(realpath $REPO_ROOT/build/pmdk/lib/pmdk_debug) $REPO_ROOT/build/deps/valgrind-pmem/bin/valgrind \\\n        --tool=pmemcheck --log-file=memcached_fixed.log ./memcached-fixed -m 0 -U 0 -t 1 -A -o \\\n        pslab_file=/mnt/pmem/pool-$(whoami),pslab_size=8,pslab_force\n```\n\n```shell\n# In terminal 2\nsource build.env\ncd $REPO_ROOT/build\n\n./parse-trace pmemcheck ./deps/memcached-pmem/bin/memcached_fixed.log -o ./deps/memcached-pmem/bin/memcached_fixed.trace\n```\n\nThe output should be like the following:\n\n```shell\nIdentified trace start\n\n\nIdentified trace end\n...\nPrepare to dump.\n        Num items: 1\nPrepare to write.\nReport written to memcached_fixed.trace\n```\n\n### 2. Performing the Redis experiment\n\n1. First, we need to generate the baseline and the log.\n\n```shell\n# Start in the root of the repository, e.g. /home/your_username/hippocrates_repo\n# --- Note: build.env will define the REPO_ROOT variable\nsource build.env\ncd $REPO_ROOT/build\n\n# This creates the baseline for the redis experiment\n./remove-flushes $REPO_ROOT/deps/redis/src/redis-server.linked.bc -o $REPO_ROOT/deps/redis/src/redis-server-noflush -s\n```\n\n- The following will be run in two terminals (to collect the trace):\n\n```shell\n# TERMINAL 1\n# --- Start in the root of the repository, e.g. /home/your_username/hippocrates_repo\nsource build.env\ncd $REPO_ROOT/deps/redis/src/\n\nrm -f /mnt/pmem/redis-$(whoami).pmem\n$REPO_ROOT/build/deps/valgrind-pmem/bin/valgrind --tool=pmemcheck \\\n        --log-file=redis.log ./redis-server-noflush ../../redis-pmem.conf --pmfile /mnt/pmem/redis-$(whoami).pmem 1gb\n# Wait until Redis displays the following:\n\u003e ... * The server is now ready to accept connections on port 6380\n```\n\n```shell\n# TERMINAL 2\n# --- Start in the root of the repository, e.g. /home/your_username/hippocrates_repo\nsource build.env\n\ntelnet localhost 6380\n\u003e set foo bar\n# ... (repeat set commands as much as you want)\n\u003e shutdown\n```\n\n- This creates a `pmemcheck` log, `$REPO_ROOT/deps/redis/src/redis.log`\n\n- After collecting the trace, run the following in either terminal:\n\n```shell\n# --- \"source build.env\" should have already been run\ncd $REPO_ROOT/build\n\n# This creates a trace file from the pmemcheck log, which is what Hippocrates uses to locate where to insert bug fixes\n./parse-trace pmemcheck $REPO_ROOT/deps/redis/src/redis.log -o $REPO_ROOT/deps/redis/src/redis.trace\n\n# This creates Redis-H-full\n./apply-fixer $REPO_ROOT/deps/redis/src/redis-server-noflush.bc $REPO_ROOT/deps/redis/src/redis.trace \\\n        -o $REPO_ROOT/deps/redis/src/redis-server-trace --keep-files --cxx \\\n        --extra-opt-args=\"-fix-summary-file=redis_summary.txt -heuristic-raising\"\n\n# This creates Redis-H-intra\n./apply-fixer $REPO_ROOT/deps/redis/src/redis-server-noflush.bc $REPO_ROOT/deps/redis/src/redis.trace \\\n        -o $REPO_ROOT/deps/redis/src/redis-server-dumb --keep-files --cxx \\\n        --extra-opt-args=\"-fix-summary-file=redis_intra_summary.txt -disable-raising -intra-only\"\n\n```\n\nNow, run the performance evaluation:\n\n```shell\n# --- \"source build.env\" should have already been run\n\ncd $REPO_ROOT/build\n./run-redis -t 10 --output-file $REPO_ROOT/results/test.csv\n# if using prebuilt:\n./run-redis -t 10 --output-file $REPO_ROOT/results/test.csv -r $REPO_ROOT/artifact/prebuilt\n\ncd $REPO_ROOT/results\n./graph.py test.csv --output test.pdf\n```\n\nThis should create a graph similar to Figure 4 in the paper, and should also produce textual output similar to the following:\n\n```s\n          Redis$_{H-intra}$  Redis-pmem  Redis$_{H-full}$\nWorkload\nLoad               0.215850         1.0          1.003542\nA                  0.797220         1.0          1.009079\nB                  0.721691         1.0          1.029106\nC                  0.728584         1.0          1.034976\nD                  0.682358         1.0          1.004612\nE                  0.167548         1.0          1.027780\nF                  0.680404         1.0          0.997616\n```\n\nYour results may vary, however the trend in the data (i.e., Redis\u003csub\u003eH-intra\u003c/sub\u003e is up to 5-10X worse than either Redis-pmem or Redis\u003csub\u003eH-full\u003c/sub\u003e and Redis\u003csub\u003eH-full\u003c/sub\u003e has around the same or slightly better performance than Redis-pmem) should still hold.\n\n### 3. Hippocrates's overhead\n\nThis information is gathered from examining `./build/apply_fixer.log`. This is a log which is appended to for every invocation of the `apply-fixer` script.\n\nThe format of entries in this log is the following:\n\n\u003cpre\u003e\nFixer stats for \u003cem\u003e{command line string}\u003c/em\u003e\nINFO:root:Fixer time: \u003cem\u003e{time in seconds}\u003c/em\u003e\nINFO:root:Fixer mem: \u003cem\u003e{memory usage in MB}\u003c/em\u003e\n\u003c/pre\u003e\n\nExample for PMDK:\n\n\u003cpre\u003e\nFixer stats for \"/usr/lib/llvm-8/bin/opt -load /home/iangneal/workspace/pm-bug-fixing/build/src/PMFIXER.so -pm-bug-fixer -trace-file /home/iangneal/workspace/pm-bug-fixing/build/tests/validation/obj_toid_TEST0_8bbb0af9c/pmemcheck0.trace -fix-summary-file=obj_toid_TEST0_8bbb0af9c_summary.txt \u003cb\u003e-heuristic-raising\u003c/b\u003e /tmp/tmp9r8nsj59/obj_toid.static-debug_linked.bc\":\nINFO:root:Fixer time: 00:00:05 \u003cb\u003e(5.251097 seconds)\u003c/b\u003e\nINFO:root:Fixer mem: \u003cb\u003e86.9296875\u003c/b\u003e MB\n\u003c/pre\u003e\n\n\n\n[//]: # (Links below)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefeslab%2Fhippocrates","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fefeslab%2Fhippocrates","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fefeslab%2Fhippocrates/lists"}