From 6a68dabac16caf859c9bbf7712c5f746138d48d4 Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 21:35:31 -0500 Subject: [PATCH 01/10] tests: Move tests to repo root This commit also updates CMake files to keep targets building and LIT running. --- CMakeLists.txt | 1 + rewriter/CMakeLists.txt | 9 --------- {rewriter/tests => tests}/CMakeLists.txt | 15 ++++++++++++--- .../tests => tests}/destructors/CMakeLists.txt | 0 .../destructors/include/main/exported_fn.h | 0 .../destructors/include/plugin/plugin.h | 0 {rewriter/tests => tests}/destructors/main.c | 0 {rewriter/tests => tests}/destructors/plugin.c | 0 {rewriter/tests => tests}/ffmpeg/CMakeLists.txt | 0 {rewriter/tests => tests}/ffmpeg/ffmpeg.test | 0 {rewriter/tests => tests}/ffmpeg/lit.local.cfg.py | 0 {rewriter/tests => tests}/ffmpeg/main.c | 0 .../tests => tests}/global_fn_ptr/CMakeLists.txt | 0 .../global_fn_ptr/Output/operations.out | 0 .../global_fn_ptr/include/operations.h | 0 {rewriter/tests => tests}/global_fn_ptr/main.c | 0 .../tests => tests}/global_fn_ptr/operations.c | 0 .../header_includes/CMakeLists.txt | 0 {rewriter/tests => tests}/header_includes/impl.c | 0 .../header_includes/include/impl.h | 0 .../header_includes/include/liboption.h | 0 .../header_includes/include/types.h | 0 .../tests => tests}/header_includes/liboption.c | 0 .../tests => tests}/header_includes/lit.local.cfg | 0 {rewriter/tests => tests}/header_includes/main.c | 0 .../tests => tests}/heap_two_keys/CMakeLists.txt | 0 .../heap_two_keys/Output/clean_exit.out | 0 .../heap_two_keys/Output/fault.out | 0 .../heap_two_keys/include/main/exported_fn.h | 0 .../heap_two_keys/include/plugin/plugin.h | 0 {rewriter/tests => tests}/heap_two_keys/main.c | 0 {rewriter/tests => tests}/heap_two_keys/plugin.c | 0 {rewriter/tests => tests}/libusb/CMakeLists.txt | 0 .../tests => tests}/libusb/include/libusb.h.head | 0 .../libusb/include/libusb.h.typedef-checks | 0 {rewriter/tests => tests}/libusb/libusb.test | 0 {rewriter/tests => tests}/libusb/lit.local.cfg.py | 0 {rewriter/tests => tests}/libusb/main.c | 0 {rewriter/tests => tests}/lit.cfg.py | 4 ++-- {rewriter/tests => tests}/lit.site.cfg.py.in | 4 ++-- .../tests => tests}/macro_attr/CMakeLists.txt | 0 {rewriter/tests => tests}/macro_attr/functions.c | 0 .../macro_attr/include/functions.h | 0 {rewriter/tests => tests}/macro_attr/main.c | 0 {rewriter/tests => tests}/minimal/CMakeLists.txt | 0 .../tests => tests}/minimal/Output/minimal.out | 0 .../tests => tests}/minimal/include/minimal.h | 0 {rewriter/tests => tests}/minimal/main.c | 0 {rewriter/tests => tests}/minimal/minimal.c | 0 .../tests => tests}/mmap_loop/CMakeLists.txt | 0 .../mmap_loop/Output/mmap_loop.out | 0 .../tests => tests}/mmap_loop/include/mmap_loop.h | 0 {rewriter/tests => tests}/mmap_loop/main.c | 0 {rewriter/tests => tests}/mmap_loop/mmap_loop.c | 0 .../tests => tests}/namespaces/CMakeLists.txt | 0 {rewriter/tests => tests}/namespaces/main.cpp | 0 {rewriter/tests => tests}/namespaces/random.cpp | 0 {rewriter/tests => tests}/namespaces/random.hpp | 0 {rewriter/tests => tests}/omit_wrappers/library.h | 0 .../permissive_mode/CMakeLists.txt | 0 .../permissive_mode/permissive_mode.c | 0 .../protected_threads/CMakeLists.txt | 0 .../protected_threads/include/library.h | 0 .../tests => tests}/protected_threads/library.c | 0 .../tests => tests}/protected_threads/main.c | 0 .../tests => tests}/read_config/CMakeLists.txt | 0 .../read_config/Output/read_config.out | 0 {rewriter/tests => tests}/read_config/builtin.c | 0 .../tests => tests}/read_config/include/core.h | 0 .../tests => tests}/read_config/include/plugin.h | 0 .../tests => tests}/read_config/lit.local.cfg | 0 {rewriter/tests => tests}/read_config/main.c | 0 {rewriter/tests => tests}/read_config/plugin.c | 0 .../tests => tests}/recursion/CMakeLists.txt | 0 .../recursion/Output/recursion.out | 0 {rewriter/tests => tests}/recursion/dso.c | 0 .../recursion/include/dso/recursion_dso.h | 0 .../recursion/include/main/recursion_main.h | 0 {rewriter/tests => tests}/recursion/main.c | 0 .../rewrite_fn_ptr_eq/CMakeLists.txt | 0 .../rewrite_fn_ptr_eq/include/lib.h | 0 {rewriter/tests => tests}/rewrite_fn_ptr_eq/lib.c | 0 .../tests => tests}/rewrite_fn_ptr_eq/main.c | 0 .../tests => tests}/rewrite_macros/CMakeLists.txt | 0 .../tests => tests}/rewrite_macros/include/lib.h | 0 {rewriter/tests => tests}/rewrite_macros/lib.c | 0 {rewriter/tests => tests}/rewrite_macros/main.c | 0 .../tests => tests}/ro_sharing/CMakeLists.txt | 0 .../tests => tests}/ro_sharing/Output/main.out | 0 .../tests => tests}/ro_sharing/Output/plugin.out | 0 .../tests => tests}/ro_sharing/include/plugin.h | 0 {rewriter/tests => tests}/ro_sharing/main.c | 0 {rewriter/tests => tests}/ro_sharing/plugin.c | 0 .../tests => tests}/shared_data/CMakeLists.txt | 0 .../shared_data/Output/shared_data.out | 0 .../tests => tests}/shared_data/access_shared.c | 0 .../shared_data/include/access_shared.h | 0 {rewriter/tests => tests}/shared_data/main.c | 0 .../should_segfault/CMakeLists.txt | 0 .../should_segfault/Output/early_segfault.out | 0 .../should_segfault/Output/should_segfault.out | 0 .../should_segfault/include/print_secret.h | 0 {rewriter/tests => tests}/should_segfault/main.c | 0 .../should_segfault/print_secret.c | 0 .../tests => tests}/sighandler/CMakeLists.txt | 0 .../tests => tests}/sighandler/Output/main.out | 0 .../tests => tests}/sighandler/include/lib.h | 0 {rewriter/tests => tests}/sighandler/lib.c | 0 {rewriter/tests => tests}/sighandler/main.c | 0 {rewriter/tests => tests}/simple1/CMakeLists.txt | 0 {rewriter/tests => tests}/simple1/include/hooks.h | 0 .../tests => tests}/simple1/include/simple1.h | 0 {rewriter/tests => tests}/simple1/main.c | 0 {rewriter/tests => tests}/simple1/simple1.c | 0 {rewriter/tests => tests}/structs/CMakeLists.txt | 0 .../tests => tests}/structs/Output/structs.out | 0 .../tests => tests}/structs/include/structs.h | 0 {rewriter/tests => tests}/structs/main.c | 0 {rewriter/tests => tests}/structs/structs.c | 0 {rewriter/tests => tests}/threads/CMakeLists.txt | 0 .../tests => tests}/threads/Output/threads.out | 0 .../tests => tests}/threads/include/library.h | 0 {rewriter/tests => tests}/threads/library.c | 0 {rewriter/tests => tests}/threads/main.c | 0 .../tests => tests}/tls_protected/CMakeLists.txt | 0 .../tls_protected/Output/tls_protected_lib.out | 0 .../tls_protected/Output/tls_protected_main.out | 0 .../tls_protected/include/library.h | 0 {rewriter/tests => tests}/tls_protected/library.c | 0 {rewriter/tests => tests}/tls_protected/main.c | 0 .../tests => tests}/trusted_direct/CMakeLists.txt | 0 .../Output/trusted_direct.clean_exit.out | 0 .../trusted_direct/Output/trusted_direct.out | 0 .../trusted_direct/include/main/exported_fn.h | 0 .../trusted_direct/include/plugin/plugin.h | 0 {rewriter/tests => tests}/trusted_direct/main.c | 0 {rewriter/tests => tests}/trusted_direct/plugin.c | 0 .../trusted_indirect/CMakeLists.txt | 0 .../Output/trusted_indirect.clean_exit.out | 0 .../trusted_indirect/Output/trusted_indirect.out | 0 .../trusted_indirect/include/rand_op.h | 0 {rewriter/tests => tests}/trusted_indirect/main.c | 0 .../tests => tests}/trusted_indirect/rand_op.c | 0 .../two_keys_minimal/CMakeLists.txt | 0 .../two_keys_minimal/Output/clean_exit.out | 0 .../two_keys_minimal/Output/main.out | 0 .../two_keys_minimal/Output/plugin.out | 0 .../two_keys_minimal/include/main/exported_fn.h | 0 .../two_keys_minimal/include/plugin/plugin.h | 0 {rewriter/tests => tests}/two_keys_minimal/main.c | 0 .../tests => tests}/two_keys_minimal/plugin.c | 0 .../two_shared_ranges/CMakeLists.txt | 0 .../two_shared_ranges/Output/clean_exit.out | 0 .../two_shared_ranges/Output/main.out | 0 .../two_shared_ranges/Output/plugin.out | 0 .../two_shared_ranges/include/main/exported_fn.h | 0 .../two_shared_ranges/include/plugin/plugin.h | 0 .../tests => tests}/two_shared_ranges/main.c | 0 .../tests => tests}/two_shared_ranges/plugin.c | 0 .../untrusted_indirect/CMakeLists.txt | 0 .../Output/untrusted_indirect.clean_exit.out | 0 .../Output/untrusted_indirect.out | 0 .../tests => tests}/untrusted_indirect/foo.c | 0 .../untrusted_indirect/include/foo.h | 0 .../tests => tests}/untrusted_indirect/main.c | 0 165 files changed, 17 insertions(+), 16 deletions(-) rename {rewriter/tests => tests}/CMakeLists.txt (79%) rename {rewriter/tests => tests}/destructors/CMakeLists.txt (100%) rename {rewriter/tests => tests}/destructors/include/main/exported_fn.h (100%) rename {rewriter/tests => tests}/destructors/include/plugin/plugin.h (100%) rename {rewriter/tests => tests}/destructors/main.c (100%) rename {rewriter/tests => tests}/destructors/plugin.c (100%) rename {rewriter/tests => tests}/ffmpeg/CMakeLists.txt (100%) rename {rewriter/tests => tests}/ffmpeg/ffmpeg.test (100%) rename {rewriter/tests => tests}/ffmpeg/lit.local.cfg.py (100%) rename {rewriter/tests => tests}/ffmpeg/main.c (100%) rename {rewriter/tests => tests}/global_fn_ptr/CMakeLists.txt (100%) rename {rewriter/tests => tests}/global_fn_ptr/Output/operations.out (100%) rename {rewriter/tests => tests}/global_fn_ptr/include/operations.h (100%) rename {rewriter/tests => tests}/global_fn_ptr/main.c (100%) rename {rewriter/tests => tests}/global_fn_ptr/operations.c (100%) rename {rewriter/tests => tests}/header_includes/CMakeLists.txt (100%) rename {rewriter/tests => tests}/header_includes/impl.c (100%) rename {rewriter/tests => tests}/header_includes/include/impl.h (100%) rename {rewriter/tests => tests}/header_includes/include/liboption.h (100%) rename {rewriter/tests => tests}/header_includes/include/types.h (100%) rename {rewriter/tests => tests}/header_includes/liboption.c (100%) rename {rewriter/tests => tests}/header_includes/lit.local.cfg (100%) rename {rewriter/tests => tests}/header_includes/main.c (100%) rename {rewriter/tests => tests}/heap_two_keys/CMakeLists.txt (100%) rename {rewriter/tests => tests}/heap_two_keys/Output/clean_exit.out (100%) rename {rewriter/tests => tests}/heap_two_keys/Output/fault.out (100%) rename {rewriter/tests => tests}/heap_two_keys/include/main/exported_fn.h (100%) rename {rewriter/tests => tests}/heap_two_keys/include/plugin/plugin.h (100%) rename {rewriter/tests => tests}/heap_two_keys/main.c (100%) rename {rewriter/tests => tests}/heap_two_keys/plugin.c (100%) rename {rewriter/tests => tests}/libusb/CMakeLists.txt (100%) rename {rewriter/tests => tests}/libusb/include/libusb.h.head (100%) rename {rewriter/tests => tests}/libusb/include/libusb.h.typedef-checks (100%) rename {rewriter/tests => tests}/libusb/libusb.test (100%) rename {rewriter/tests => tests}/libusb/lit.local.cfg.py (100%) rename {rewriter/tests => tests}/libusb/main.c (100%) rename {rewriter/tests => tests}/lit.cfg.py (93%) rename {rewriter/tests => tests}/lit.site.cfg.py.in (94%) rename {rewriter/tests => tests}/macro_attr/CMakeLists.txt (100%) rename {rewriter/tests => tests}/macro_attr/functions.c (100%) rename {rewriter/tests => tests}/macro_attr/include/functions.h (100%) rename {rewriter/tests => tests}/macro_attr/main.c (100%) rename {rewriter/tests => tests}/minimal/CMakeLists.txt (100%) rename {rewriter/tests => tests}/minimal/Output/minimal.out (100%) rename {rewriter/tests => tests}/minimal/include/minimal.h (100%) rename {rewriter/tests => tests}/minimal/main.c (100%) rename {rewriter/tests => tests}/minimal/minimal.c (100%) rename {rewriter/tests => tests}/mmap_loop/CMakeLists.txt (100%) rename {rewriter/tests => tests}/mmap_loop/Output/mmap_loop.out (100%) rename {rewriter/tests => tests}/mmap_loop/include/mmap_loop.h (100%) rename {rewriter/tests => tests}/mmap_loop/main.c (100%) rename {rewriter/tests => tests}/mmap_loop/mmap_loop.c (100%) rename {rewriter/tests => tests}/namespaces/CMakeLists.txt (100%) rename {rewriter/tests => tests}/namespaces/main.cpp (100%) rename {rewriter/tests => tests}/namespaces/random.cpp (100%) rename {rewriter/tests => tests}/namespaces/random.hpp (100%) rename {rewriter/tests => tests}/omit_wrappers/library.h (100%) rename {rewriter/tests => tests}/permissive_mode/CMakeLists.txt (100%) rename {rewriter/tests => tests}/permissive_mode/permissive_mode.c (100%) rename {rewriter/tests => tests}/protected_threads/CMakeLists.txt (100%) rename {rewriter/tests => tests}/protected_threads/include/library.h (100%) rename {rewriter/tests => tests}/protected_threads/library.c (100%) rename {rewriter/tests => tests}/protected_threads/main.c (100%) rename {rewriter/tests => tests}/read_config/CMakeLists.txt (100%) rename {rewriter/tests => tests}/read_config/Output/read_config.out (100%) rename {rewriter/tests => tests}/read_config/builtin.c (100%) rename {rewriter/tests => tests}/read_config/include/core.h (100%) rename {rewriter/tests => tests}/read_config/include/plugin.h (100%) rename {rewriter/tests => tests}/read_config/lit.local.cfg (100%) rename {rewriter/tests => tests}/read_config/main.c (100%) rename {rewriter/tests => tests}/read_config/plugin.c (100%) rename {rewriter/tests => tests}/recursion/CMakeLists.txt (100%) rename {rewriter/tests => tests}/recursion/Output/recursion.out (100%) rename {rewriter/tests => tests}/recursion/dso.c (100%) rename {rewriter/tests => tests}/recursion/include/dso/recursion_dso.h (100%) rename {rewriter/tests => tests}/recursion/include/main/recursion_main.h (100%) rename {rewriter/tests => tests}/recursion/main.c (100%) rename {rewriter/tests => tests}/rewrite_fn_ptr_eq/CMakeLists.txt (100%) rename {rewriter/tests => tests}/rewrite_fn_ptr_eq/include/lib.h (100%) rename {rewriter/tests => tests}/rewrite_fn_ptr_eq/lib.c (100%) rename {rewriter/tests => tests}/rewrite_fn_ptr_eq/main.c (100%) rename {rewriter/tests => tests}/rewrite_macros/CMakeLists.txt (100%) rename {rewriter/tests => tests}/rewrite_macros/include/lib.h (100%) rename {rewriter/tests => tests}/rewrite_macros/lib.c (100%) rename {rewriter/tests => tests}/rewrite_macros/main.c (100%) rename {rewriter/tests => tests}/ro_sharing/CMakeLists.txt (100%) rename {rewriter/tests => tests}/ro_sharing/Output/main.out (100%) rename {rewriter/tests => tests}/ro_sharing/Output/plugin.out (100%) rename {rewriter/tests => tests}/ro_sharing/include/plugin.h (100%) rename {rewriter/tests => tests}/ro_sharing/main.c (100%) rename {rewriter/tests => tests}/ro_sharing/plugin.c (100%) rename {rewriter/tests => tests}/shared_data/CMakeLists.txt (100%) rename {rewriter/tests => tests}/shared_data/Output/shared_data.out (100%) rename {rewriter/tests => tests}/shared_data/access_shared.c (100%) rename {rewriter/tests => tests}/shared_data/include/access_shared.h (100%) rename {rewriter/tests => tests}/shared_data/main.c (100%) rename {rewriter/tests => tests}/should_segfault/CMakeLists.txt (100%) rename {rewriter/tests => tests}/should_segfault/Output/early_segfault.out (100%) rename {rewriter/tests => tests}/should_segfault/Output/should_segfault.out (100%) rename {rewriter/tests => tests}/should_segfault/include/print_secret.h (100%) rename {rewriter/tests => tests}/should_segfault/main.c (100%) rename {rewriter/tests => tests}/should_segfault/print_secret.c (100%) rename {rewriter/tests => tests}/sighandler/CMakeLists.txt (100%) rename {rewriter/tests => tests}/sighandler/Output/main.out (100%) rename {rewriter/tests => tests}/sighandler/include/lib.h (100%) rename {rewriter/tests => tests}/sighandler/lib.c (100%) rename {rewriter/tests => tests}/sighandler/main.c (100%) rename {rewriter/tests => tests}/simple1/CMakeLists.txt (100%) rename {rewriter/tests => tests}/simple1/include/hooks.h (100%) rename {rewriter/tests => tests}/simple1/include/simple1.h (100%) rename {rewriter/tests => tests}/simple1/main.c (100%) rename {rewriter/tests => tests}/simple1/simple1.c (100%) rename {rewriter/tests => tests}/structs/CMakeLists.txt (100%) rename {rewriter/tests => tests}/structs/Output/structs.out (100%) rename {rewriter/tests => tests}/structs/include/structs.h (100%) rename {rewriter/tests => tests}/structs/main.c (100%) rename {rewriter/tests => tests}/structs/structs.c (100%) rename {rewriter/tests => tests}/threads/CMakeLists.txt (100%) rename {rewriter/tests => tests}/threads/Output/threads.out (100%) rename {rewriter/tests => tests}/threads/include/library.h (100%) rename {rewriter/tests => tests}/threads/library.c (100%) rename {rewriter/tests => tests}/threads/main.c (100%) rename {rewriter/tests => tests}/tls_protected/CMakeLists.txt (100%) rename {rewriter/tests => tests}/tls_protected/Output/tls_protected_lib.out (100%) rename {rewriter/tests => tests}/tls_protected/Output/tls_protected_main.out (100%) rename {rewriter/tests => tests}/tls_protected/include/library.h (100%) rename {rewriter/tests => tests}/tls_protected/library.c (100%) rename {rewriter/tests => tests}/tls_protected/main.c (100%) rename {rewriter/tests => tests}/trusted_direct/CMakeLists.txt (100%) rename {rewriter/tests => tests}/trusted_direct/Output/trusted_direct.clean_exit.out (100%) rename {rewriter/tests => tests}/trusted_direct/Output/trusted_direct.out (100%) rename {rewriter/tests => tests}/trusted_direct/include/main/exported_fn.h (100%) rename {rewriter/tests => tests}/trusted_direct/include/plugin/plugin.h (100%) rename {rewriter/tests => tests}/trusted_direct/main.c (100%) rename {rewriter/tests => tests}/trusted_direct/plugin.c (100%) rename {rewriter/tests => tests}/trusted_indirect/CMakeLists.txt (100%) rename {rewriter/tests => tests}/trusted_indirect/Output/trusted_indirect.clean_exit.out (100%) rename {rewriter/tests => tests}/trusted_indirect/Output/trusted_indirect.out (100%) rename {rewriter/tests => tests}/trusted_indirect/include/rand_op.h (100%) rename {rewriter/tests => tests}/trusted_indirect/main.c (100%) rename {rewriter/tests => tests}/trusted_indirect/rand_op.c (100%) rename {rewriter/tests => tests}/two_keys_minimal/CMakeLists.txt (100%) rename {rewriter/tests => tests}/two_keys_minimal/Output/clean_exit.out (100%) rename {rewriter/tests => tests}/two_keys_minimal/Output/main.out (100%) rename {rewriter/tests => tests}/two_keys_minimal/Output/plugin.out (100%) rename {rewriter/tests => tests}/two_keys_minimal/include/main/exported_fn.h (100%) rename {rewriter/tests => tests}/two_keys_minimal/include/plugin/plugin.h (100%) rename {rewriter/tests => tests}/two_keys_minimal/main.c (100%) rename {rewriter/tests => tests}/two_keys_minimal/plugin.c (100%) rename {rewriter/tests => tests}/two_shared_ranges/CMakeLists.txt (100%) rename {rewriter/tests => tests}/two_shared_ranges/Output/clean_exit.out (100%) rename {rewriter/tests => tests}/two_shared_ranges/Output/main.out (100%) rename {rewriter/tests => tests}/two_shared_ranges/Output/plugin.out (100%) rename {rewriter/tests => tests}/two_shared_ranges/include/main/exported_fn.h (100%) rename {rewriter/tests => tests}/two_shared_ranges/include/plugin/plugin.h (100%) rename {rewriter/tests => tests}/two_shared_ranges/main.c (100%) rename {rewriter/tests => tests}/two_shared_ranges/plugin.c (100%) rename {rewriter/tests => tests}/untrusted_indirect/CMakeLists.txt (100%) rename {rewriter/tests => tests}/untrusted_indirect/Output/untrusted_indirect.clean_exit.out (100%) rename {rewriter/tests => tests}/untrusted_indirect/Output/untrusted_indirect.out (100%) rename {rewriter/tests => tests}/untrusted_indirect/foo.c (100%) rename {rewriter/tests => tests}/untrusted_indirect/include/foo.h (100%) rename {rewriter/tests => tests}/untrusted_indirect/main.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6651d5b41c..290c505ebf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,3 +13,4 @@ add_subdirectory(rewriter) add_subdirectory(partition-alloc) add_subdirectory(pad-tls) add_subdirectory(runtime) +add_subdirectory(tests) diff --git a/rewriter/CMakeLists.txt b/rewriter/CMakeLists.txt index 98d710c750..e7c67e170d 100644 --- a/rewriter/CMakeLists.txt +++ b/rewriter/CMakeLists.txt @@ -6,10 +6,6 @@ message(STATUS "Found LLVM: ${LLVM_DIR} (found version \"${LLVM_PACKAGE_VERSION} find_package(Clang REQUIRED CONFIG) message(STATUS "Found Clang: ${Clang_DIR}") -# We use the lit CMake functions from LLVM -list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") -include(AddLLVM) - add_definitions(${CLANG_DEFINITIONS} ${LLVM_DEFINITIONS}) include_directories(${CLANG_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS}) @@ -29,8 +25,3 @@ target_link_libraries(ia2-rewriter PRIVATE clang-cpp LLVM ) - -set(IA2_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(IA2_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) - -add_subdirectory(tests) diff --git a/rewriter/tests/CMakeLists.txt b/tests/CMakeLists.txt similarity index 79% rename from rewriter/tests/CMakeLists.txt rename to tests/CMakeLists.txt index 802688a520..f946f4a57c 100644 --- a/rewriter/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -2,9 +2,18 @@ include(CTest) enable_testing() -include("../../cmake/define-ia2-wrapper.cmake") -include("../../cmake/define-test.cmake") -include("../../cmake/add-tls-padded-library.cmake") +include("../cmake/define-ia2-wrapper.cmake") +include("../cmake/define-test.cmake") +include("../cmake/add-tls-padded-library.cmake") + +find_package(LLVM REQUIRED CONFIG) +message(STATUS "Found LLVM: ${LLVM_DIR} (found version \"${LLVM_PACKAGE_VERSION}\")") +find_package(Clang REQUIRED CONFIG) +message(STATUS "Found Clang: ${Clang_DIR}") + +# We use the lit CMake functions from LLVM +list(APPEND CMAKE_MODULE_PATH "${LLVM_CMAKE_DIR}") +include(AddLLVM) configure_lit_site_cfg( ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in diff --git a/rewriter/tests/destructors/CMakeLists.txt b/tests/destructors/CMakeLists.txt similarity index 100% rename from rewriter/tests/destructors/CMakeLists.txt rename to tests/destructors/CMakeLists.txt diff --git a/rewriter/tests/destructors/include/main/exported_fn.h b/tests/destructors/include/main/exported_fn.h similarity index 100% rename from rewriter/tests/destructors/include/main/exported_fn.h rename to tests/destructors/include/main/exported_fn.h diff --git a/rewriter/tests/destructors/include/plugin/plugin.h b/tests/destructors/include/plugin/plugin.h similarity index 100% rename from rewriter/tests/destructors/include/plugin/plugin.h rename to tests/destructors/include/plugin/plugin.h diff --git a/rewriter/tests/destructors/main.c b/tests/destructors/main.c similarity index 100% rename from rewriter/tests/destructors/main.c rename to tests/destructors/main.c diff --git a/rewriter/tests/destructors/plugin.c b/tests/destructors/plugin.c similarity index 100% rename from rewriter/tests/destructors/plugin.c rename to tests/destructors/plugin.c diff --git a/rewriter/tests/ffmpeg/CMakeLists.txt b/tests/ffmpeg/CMakeLists.txt similarity index 100% rename from rewriter/tests/ffmpeg/CMakeLists.txt rename to tests/ffmpeg/CMakeLists.txt diff --git a/rewriter/tests/ffmpeg/ffmpeg.test b/tests/ffmpeg/ffmpeg.test similarity index 100% rename from rewriter/tests/ffmpeg/ffmpeg.test rename to tests/ffmpeg/ffmpeg.test diff --git a/rewriter/tests/ffmpeg/lit.local.cfg.py b/tests/ffmpeg/lit.local.cfg.py similarity index 100% rename from rewriter/tests/ffmpeg/lit.local.cfg.py rename to tests/ffmpeg/lit.local.cfg.py diff --git a/rewriter/tests/ffmpeg/main.c b/tests/ffmpeg/main.c similarity index 100% rename from rewriter/tests/ffmpeg/main.c rename to tests/ffmpeg/main.c diff --git a/rewriter/tests/global_fn_ptr/CMakeLists.txt b/tests/global_fn_ptr/CMakeLists.txt similarity index 100% rename from rewriter/tests/global_fn_ptr/CMakeLists.txt rename to tests/global_fn_ptr/CMakeLists.txt diff --git a/rewriter/tests/global_fn_ptr/Output/operations.out b/tests/global_fn_ptr/Output/operations.out similarity index 100% rename from rewriter/tests/global_fn_ptr/Output/operations.out rename to tests/global_fn_ptr/Output/operations.out diff --git a/rewriter/tests/global_fn_ptr/include/operations.h b/tests/global_fn_ptr/include/operations.h similarity index 100% rename from rewriter/tests/global_fn_ptr/include/operations.h rename to tests/global_fn_ptr/include/operations.h diff --git a/rewriter/tests/global_fn_ptr/main.c b/tests/global_fn_ptr/main.c similarity index 100% rename from rewriter/tests/global_fn_ptr/main.c rename to tests/global_fn_ptr/main.c diff --git a/rewriter/tests/global_fn_ptr/operations.c b/tests/global_fn_ptr/operations.c similarity index 100% rename from rewriter/tests/global_fn_ptr/operations.c rename to tests/global_fn_ptr/operations.c diff --git a/rewriter/tests/header_includes/CMakeLists.txt b/tests/header_includes/CMakeLists.txt similarity index 100% rename from rewriter/tests/header_includes/CMakeLists.txt rename to tests/header_includes/CMakeLists.txt diff --git a/rewriter/tests/header_includes/impl.c b/tests/header_includes/impl.c similarity index 100% rename from rewriter/tests/header_includes/impl.c rename to tests/header_includes/impl.c diff --git a/rewriter/tests/header_includes/include/impl.h b/tests/header_includes/include/impl.h similarity index 100% rename from rewriter/tests/header_includes/include/impl.h rename to tests/header_includes/include/impl.h diff --git a/rewriter/tests/header_includes/include/liboption.h b/tests/header_includes/include/liboption.h similarity index 100% rename from rewriter/tests/header_includes/include/liboption.h rename to tests/header_includes/include/liboption.h diff --git a/rewriter/tests/header_includes/include/types.h b/tests/header_includes/include/types.h similarity index 100% rename from rewriter/tests/header_includes/include/types.h rename to tests/header_includes/include/types.h diff --git a/rewriter/tests/header_includes/liboption.c b/tests/header_includes/liboption.c similarity index 100% rename from rewriter/tests/header_includes/liboption.c rename to tests/header_includes/liboption.c diff --git a/rewriter/tests/header_includes/lit.local.cfg b/tests/header_includes/lit.local.cfg similarity index 100% rename from rewriter/tests/header_includes/lit.local.cfg rename to tests/header_includes/lit.local.cfg diff --git a/rewriter/tests/header_includes/main.c b/tests/header_includes/main.c similarity index 100% rename from rewriter/tests/header_includes/main.c rename to tests/header_includes/main.c diff --git a/rewriter/tests/heap_two_keys/CMakeLists.txt b/tests/heap_two_keys/CMakeLists.txt similarity index 100% rename from rewriter/tests/heap_two_keys/CMakeLists.txt rename to tests/heap_two_keys/CMakeLists.txt diff --git a/rewriter/tests/heap_two_keys/Output/clean_exit.out b/tests/heap_two_keys/Output/clean_exit.out similarity index 100% rename from rewriter/tests/heap_two_keys/Output/clean_exit.out rename to tests/heap_two_keys/Output/clean_exit.out diff --git a/rewriter/tests/heap_two_keys/Output/fault.out b/tests/heap_two_keys/Output/fault.out similarity index 100% rename from rewriter/tests/heap_two_keys/Output/fault.out rename to tests/heap_two_keys/Output/fault.out diff --git a/rewriter/tests/heap_two_keys/include/main/exported_fn.h b/tests/heap_two_keys/include/main/exported_fn.h similarity index 100% rename from rewriter/tests/heap_two_keys/include/main/exported_fn.h rename to tests/heap_two_keys/include/main/exported_fn.h diff --git a/rewriter/tests/heap_two_keys/include/plugin/plugin.h b/tests/heap_two_keys/include/plugin/plugin.h similarity index 100% rename from rewriter/tests/heap_two_keys/include/plugin/plugin.h rename to tests/heap_two_keys/include/plugin/plugin.h diff --git a/rewriter/tests/heap_two_keys/main.c b/tests/heap_two_keys/main.c similarity index 100% rename from rewriter/tests/heap_two_keys/main.c rename to tests/heap_two_keys/main.c diff --git a/rewriter/tests/heap_two_keys/plugin.c b/tests/heap_two_keys/plugin.c similarity index 100% rename from rewriter/tests/heap_two_keys/plugin.c rename to tests/heap_two_keys/plugin.c diff --git a/rewriter/tests/libusb/CMakeLists.txt b/tests/libusb/CMakeLists.txt similarity index 100% rename from rewriter/tests/libusb/CMakeLists.txt rename to tests/libusb/CMakeLists.txt diff --git a/rewriter/tests/libusb/include/libusb.h.head b/tests/libusb/include/libusb.h.head similarity index 100% rename from rewriter/tests/libusb/include/libusb.h.head rename to tests/libusb/include/libusb.h.head diff --git a/rewriter/tests/libusb/include/libusb.h.typedef-checks b/tests/libusb/include/libusb.h.typedef-checks similarity index 100% rename from rewriter/tests/libusb/include/libusb.h.typedef-checks rename to tests/libusb/include/libusb.h.typedef-checks diff --git a/rewriter/tests/libusb/libusb.test b/tests/libusb/libusb.test similarity index 100% rename from rewriter/tests/libusb/libusb.test rename to tests/libusb/libusb.test diff --git a/rewriter/tests/libusb/lit.local.cfg.py b/tests/libusb/lit.local.cfg.py similarity index 100% rename from rewriter/tests/libusb/lit.local.cfg.py rename to tests/libusb/lit.local.cfg.py diff --git a/rewriter/tests/libusb/main.c b/tests/libusb/main.c similarity index 100% rename from rewriter/tests/libusb/main.c rename to tests/libusb/main.c diff --git a/rewriter/tests/lit.cfg.py b/tests/lit.cfg.py similarity index 93% rename from rewriter/tests/lit.cfg.py rename to tests/lit.cfg.py index 0c38818cd5..690c2803c9 100644 --- a/rewriter/tests/lit.cfg.py +++ b/tests/lit.cfg.py @@ -49,14 +49,14 @@ # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) -llvm_config.add_tool_substitutions([ToolSubst('ia2-rewriter')], search_dirs=config.ia2_obj_root) +llvm_config.add_tool_substitutions([ToolSubst('ia2-rewriter')], search_dirs=os.path.join(config.ia2_obj_root, "rewriter")) llvm_config.use_default_substitutions() llvm_config.use_clang() config.substitutions.extend([ ('%ia2_generate_checks', '%s/tests/generate-checks.sh' % config.ia2_src_root), - ('%ia2_include', '%s/../include' % config.ia2_src_root), + ('%ia2_include', '%s/libia2/include' % config.ia2_src_root), ('%binary_dir', config.ia2_obj_root), ('%source_dir', config.ia2_src_root) ]) diff --git a/rewriter/tests/lit.site.cfg.py.in b/tests/lit.site.cfg.py.in similarity index 94% rename from rewriter/tests/lit.site.cfg.py.in rename to tests/lit.site.cfg.py.in index 0143b5db0b..1c3295f7b5 100644 --- a/rewriter/tests/lit.site.cfg.py.in +++ b/tests/lit.site.cfg.py.in @@ -4,8 +4,8 @@ import sys config.host_triple = "@LLVM_HOST_TRIPLE@" config.target_triple = "@LLVM_TARGET_TRIPLE@" or "@TARGET_TRIPLE@" -config.ia2_src_root = r"@IA2_SOURCE_DIR@" -config.ia2_obj_root = r"@IA2_BINARY_DIR@" +config.ia2_src_root = r"@CMAKE_SOURCE_DIR@" +config.ia2_obj_root = r"@CMAKE_BINARY_DIR@" config.llvm_tools_dir = r"@LLVM_TOOLS_DIR@" config.llvm_lib_dir = r"@LLVM_LIBS_DIR@" config.llvm_shlib_dir = r"@SHLIBDIR@" diff --git a/rewriter/tests/macro_attr/CMakeLists.txt b/tests/macro_attr/CMakeLists.txt similarity index 100% rename from rewriter/tests/macro_attr/CMakeLists.txt rename to tests/macro_attr/CMakeLists.txt diff --git a/rewriter/tests/macro_attr/functions.c b/tests/macro_attr/functions.c similarity index 100% rename from rewriter/tests/macro_attr/functions.c rename to tests/macro_attr/functions.c diff --git a/rewriter/tests/macro_attr/include/functions.h b/tests/macro_attr/include/functions.h similarity index 100% rename from rewriter/tests/macro_attr/include/functions.h rename to tests/macro_attr/include/functions.h diff --git a/rewriter/tests/macro_attr/main.c b/tests/macro_attr/main.c similarity index 100% rename from rewriter/tests/macro_attr/main.c rename to tests/macro_attr/main.c diff --git a/rewriter/tests/minimal/CMakeLists.txt b/tests/minimal/CMakeLists.txt similarity index 100% rename from rewriter/tests/minimal/CMakeLists.txt rename to tests/minimal/CMakeLists.txt diff --git a/rewriter/tests/minimal/Output/minimal.out b/tests/minimal/Output/minimal.out similarity index 100% rename from rewriter/tests/minimal/Output/minimal.out rename to tests/minimal/Output/minimal.out diff --git a/rewriter/tests/minimal/include/minimal.h b/tests/minimal/include/minimal.h similarity index 100% rename from rewriter/tests/minimal/include/minimal.h rename to tests/minimal/include/minimal.h diff --git a/rewriter/tests/minimal/main.c b/tests/minimal/main.c similarity index 100% rename from rewriter/tests/minimal/main.c rename to tests/minimal/main.c diff --git a/rewriter/tests/minimal/minimal.c b/tests/minimal/minimal.c similarity index 100% rename from rewriter/tests/minimal/minimal.c rename to tests/minimal/minimal.c diff --git a/rewriter/tests/mmap_loop/CMakeLists.txt b/tests/mmap_loop/CMakeLists.txt similarity index 100% rename from rewriter/tests/mmap_loop/CMakeLists.txt rename to tests/mmap_loop/CMakeLists.txt diff --git a/rewriter/tests/mmap_loop/Output/mmap_loop.out b/tests/mmap_loop/Output/mmap_loop.out similarity index 100% rename from rewriter/tests/mmap_loop/Output/mmap_loop.out rename to tests/mmap_loop/Output/mmap_loop.out diff --git a/rewriter/tests/mmap_loop/include/mmap_loop.h b/tests/mmap_loop/include/mmap_loop.h similarity index 100% rename from rewriter/tests/mmap_loop/include/mmap_loop.h rename to tests/mmap_loop/include/mmap_loop.h diff --git a/rewriter/tests/mmap_loop/main.c b/tests/mmap_loop/main.c similarity index 100% rename from rewriter/tests/mmap_loop/main.c rename to tests/mmap_loop/main.c diff --git a/rewriter/tests/mmap_loop/mmap_loop.c b/tests/mmap_loop/mmap_loop.c similarity index 100% rename from rewriter/tests/mmap_loop/mmap_loop.c rename to tests/mmap_loop/mmap_loop.c diff --git a/rewriter/tests/namespaces/CMakeLists.txt b/tests/namespaces/CMakeLists.txt similarity index 100% rename from rewriter/tests/namespaces/CMakeLists.txt rename to tests/namespaces/CMakeLists.txt diff --git a/rewriter/tests/namespaces/main.cpp b/tests/namespaces/main.cpp similarity index 100% rename from rewriter/tests/namespaces/main.cpp rename to tests/namespaces/main.cpp diff --git a/rewriter/tests/namespaces/random.cpp b/tests/namespaces/random.cpp similarity index 100% rename from rewriter/tests/namespaces/random.cpp rename to tests/namespaces/random.cpp diff --git a/rewriter/tests/namespaces/random.hpp b/tests/namespaces/random.hpp similarity index 100% rename from rewriter/tests/namespaces/random.hpp rename to tests/namespaces/random.hpp diff --git a/rewriter/tests/omit_wrappers/library.h b/tests/omit_wrappers/library.h similarity index 100% rename from rewriter/tests/omit_wrappers/library.h rename to tests/omit_wrappers/library.h diff --git a/rewriter/tests/permissive_mode/CMakeLists.txt b/tests/permissive_mode/CMakeLists.txt similarity index 100% rename from rewriter/tests/permissive_mode/CMakeLists.txt rename to tests/permissive_mode/CMakeLists.txt diff --git a/rewriter/tests/permissive_mode/permissive_mode.c b/tests/permissive_mode/permissive_mode.c similarity index 100% rename from rewriter/tests/permissive_mode/permissive_mode.c rename to tests/permissive_mode/permissive_mode.c diff --git a/rewriter/tests/protected_threads/CMakeLists.txt b/tests/protected_threads/CMakeLists.txt similarity index 100% rename from rewriter/tests/protected_threads/CMakeLists.txt rename to tests/protected_threads/CMakeLists.txt diff --git a/rewriter/tests/protected_threads/include/library.h b/tests/protected_threads/include/library.h similarity index 100% rename from rewriter/tests/protected_threads/include/library.h rename to tests/protected_threads/include/library.h diff --git a/rewriter/tests/protected_threads/library.c b/tests/protected_threads/library.c similarity index 100% rename from rewriter/tests/protected_threads/library.c rename to tests/protected_threads/library.c diff --git a/rewriter/tests/protected_threads/main.c b/tests/protected_threads/main.c similarity index 100% rename from rewriter/tests/protected_threads/main.c rename to tests/protected_threads/main.c diff --git a/rewriter/tests/read_config/CMakeLists.txt b/tests/read_config/CMakeLists.txt similarity index 100% rename from rewriter/tests/read_config/CMakeLists.txt rename to tests/read_config/CMakeLists.txt diff --git a/rewriter/tests/read_config/Output/read_config.out b/tests/read_config/Output/read_config.out similarity index 100% rename from rewriter/tests/read_config/Output/read_config.out rename to tests/read_config/Output/read_config.out diff --git a/rewriter/tests/read_config/builtin.c b/tests/read_config/builtin.c similarity index 100% rename from rewriter/tests/read_config/builtin.c rename to tests/read_config/builtin.c diff --git a/rewriter/tests/read_config/include/core.h b/tests/read_config/include/core.h similarity index 100% rename from rewriter/tests/read_config/include/core.h rename to tests/read_config/include/core.h diff --git a/rewriter/tests/read_config/include/plugin.h b/tests/read_config/include/plugin.h similarity index 100% rename from rewriter/tests/read_config/include/plugin.h rename to tests/read_config/include/plugin.h diff --git a/rewriter/tests/read_config/lit.local.cfg b/tests/read_config/lit.local.cfg similarity index 100% rename from rewriter/tests/read_config/lit.local.cfg rename to tests/read_config/lit.local.cfg diff --git a/rewriter/tests/read_config/main.c b/tests/read_config/main.c similarity index 100% rename from rewriter/tests/read_config/main.c rename to tests/read_config/main.c diff --git a/rewriter/tests/read_config/plugin.c b/tests/read_config/plugin.c similarity index 100% rename from rewriter/tests/read_config/plugin.c rename to tests/read_config/plugin.c diff --git a/rewriter/tests/recursion/CMakeLists.txt b/tests/recursion/CMakeLists.txt similarity index 100% rename from rewriter/tests/recursion/CMakeLists.txt rename to tests/recursion/CMakeLists.txt diff --git a/rewriter/tests/recursion/Output/recursion.out b/tests/recursion/Output/recursion.out similarity index 100% rename from rewriter/tests/recursion/Output/recursion.out rename to tests/recursion/Output/recursion.out diff --git a/rewriter/tests/recursion/dso.c b/tests/recursion/dso.c similarity index 100% rename from rewriter/tests/recursion/dso.c rename to tests/recursion/dso.c diff --git a/rewriter/tests/recursion/include/dso/recursion_dso.h b/tests/recursion/include/dso/recursion_dso.h similarity index 100% rename from rewriter/tests/recursion/include/dso/recursion_dso.h rename to tests/recursion/include/dso/recursion_dso.h diff --git a/rewriter/tests/recursion/include/main/recursion_main.h b/tests/recursion/include/main/recursion_main.h similarity index 100% rename from rewriter/tests/recursion/include/main/recursion_main.h rename to tests/recursion/include/main/recursion_main.h diff --git a/rewriter/tests/recursion/main.c b/tests/recursion/main.c similarity index 100% rename from rewriter/tests/recursion/main.c rename to tests/recursion/main.c diff --git a/rewriter/tests/rewrite_fn_ptr_eq/CMakeLists.txt b/tests/rewrite_fn_ptr_eq/CMakeLists.txt similarity index 100% rename from rewriter/tests/rewrite_fn_ptr_eq/CMakeLists.txt rename to tests/rewrite_fn_ptr_eq/CMakeLists.txt diff --git a/rewriter/tests/rewrite_fn_ptr_eq/include/lib.h b/tests/rewrite_fn_ptr_eq/include/lib.h similarity index 100% rename from rewriter/tests/rewrite_fn_ptr_eq/include/lib.h rename to tests/rewrite_fn_ptr_eq/include/lib.h diff --git a/rewriter/tests/rewrite_fn_ptr_eq/lib.c b/tests/rewrite_fn_ptr_eq/lib.c similarity index 100% rename from rewriter/tests/rewrite_fn_ptr_eq/lib.c rename to tests/rewrite_fn_ptr_eq/lib.c diff --git a/rewriter/tests/rewrite_fn_ptr_eq/main.c b/tests/rewrite_fn_ptr_eq/main.c similarity index 100% rename from rewriter/tests/rewrite_fn_ptr_eq/main.c rename to tests/rewrite_fn_ptr_eq/main.c diff --git a/rewriter/tests/rewrite_macros/CMakeLists.txt b/tests/rewrite_macros/CMakeLists.txt similarity index 100% rename from rewriter/tests/rewrite_macros/CMakeLists.txt rename to tests/rewrite_macros/CMakeLists.txt diff --git a/rewriter/tests/rewrite_macros/include/lib.h b/tests/rewrite_macros/include/lib.h similarity index 100% rename from rewriter/tests/rewrite_macros/include/lib.h rename to tests/rewrite_macros/include/lib.h diff --git a/rewriter/tests/rewrite_macros/lib.c b/tests/rewrite_macros/lib.c similarity index 100% rename from rewriter/tests/rewrite_macros/lib.c rename to tests/rewrite_macros/lib.c diff --git a/rewriter/tests/rewrite_macros/main.c b/tests/rewrite_macros/main.c similarity index 100% rename from rewriter/tests/rewrite_macros/main.c rename to tests/rewrite_macros/main.c diff --git a/rewriter/tests/ro_sharing/CMakeLists.txt b/tests/ro_sharing/CMakeLists.txt similarity index 100% rename from rewriter/tests/ro_sharing/CMakeLists.txt rename to tests/ro_sharing/CMakeLists.txt diff --git a/rewriter/tests/ro_sharing/Output/main.out b/tests/ro_sharing/Output/main.out similarity index 100% rename from rewriter/tests/ro_sharing/Output/main.out rename to tests/ro_sharing/Output/main.out diff --git a/rewriter/tests/ro_sharing/Output/plugin.out b/tests/ro_sharing/Output/plugin.out similarity index 100% rename from rewriter/tests/ro_sharing/Output/plugin.out rename to tests/ro_sharing/Output/plugin.out diff --git a/rewriter/tests/ro_sharing/include/plugin.h b/tests/ro_sharing/include/plugin.h similarity index 100% rename from rewriter/tests/ro_sharing/include/plugin.h rename to tests/ro_sharing/include/plugin.h diff --git a/rewriter/tests/ro_sharing/main.c b/tests/ro_sharing/main.c similarity index 100% rename from rewriter/tests/ro_sharing/main.c rename to tests/ro_sharing/main.c diff --git a/rewriter/tests/ro_sharing/plugin.c b/tests/ro_sharing/plugin.c similarity index 100% rename from rewriter/tests/ro_sharing/plugin.c rename to tests/ro_sharing/plugin.c diff --git a/rewriter/tests/shared_data/CMakeLists.txt b/tests/shared_data/CMakeLists.txt similarity index 100% rename from rewriter/tests/shared_data/CMakeLists.txt rename to tests/shared_data/CMakeLists.txt diff --git a/rewriter/tests/shared_data/Output/shared_data.out b/tests/shared_data/Output/shared_data.out similarity index 100% rename from rewriter/tests/shared_data/Output/shared_data.out rename to tests/shared_data/Output/shared_data.out diff --git a/rewriter/tests/shared_data/access_shared.c b/tests/shared_data/access_shared.c similarity index 100% rename from rewriter/tests/shared_data/access_shared.c rename to tests/shared_data/access_shared.c diff --git a/rewriter/tests/shared_data/include/access_shared.h b/tests/shared_data/include/access_shared.h similarity index 100% rename from rewriter/tests/shared_data/include/access_shared.h rename to tests/shared_data/include/access_shared.h diff --git a/rewriter/tests/shared_data/main.c b/tests/shared_data/main.c similarity index 100% rename from rewriter/tests/shared_data/main.c rename to tests/shared_data/main.c diff --git a/rewriter/tests/should_segfault/CMakeLists.txt b/tests/should_segfault/CMakeLists.txt similarity index 100% rename from rewriter/tests/should_segfault/CMakeLists.txt rename to tests/should_segfault/CMakeLists.txt diff --git a/rewriter/tests/should_segfault/Output/early_segfault.out b/tests/should_segfault/Output/early_segfault.out similarity index 100% rename from rewriter/tests/should_segfault/Output/early_segfault.out rename to tests/should_segfault/Output/early_segfault.out diff --git a/rewriter/tests/should_segfault/Output/should_segfault.out b/tests/should_segfault/Output/should_segfault.out similarity index 100% rename from rewriter/tests/should_segfault/Output/should_segfault.out rename to tests/should_segfault/Output/should_segfault.out diff --git a/rewriter/tests/should_segfault/include/print_secret.h b/tests/should_segfault/include/print_secret.h similarity index 100% rename from rewriter/tests/should_segfault/include/print_secret.h rename to tests/should_segfault/include/print_secret.h diff --git a/rewriter/tests/should_segfault/main.c b/tests/should_segfault/main.c similarity index 100% rename from rewriter/tests/should_segfault/main.c rename to tests/should_segfault/main.c diff --git a/rewriter/tests/should_segfault/print_secret.c b/tests/should_segfault/print_secret.c similarity index 100% rename from rewriter/tests/should_segfault/print_secret.c rename to tests/should_segfault/print_secret.c diff --git a/rewriter/tests/sighandler/CMakeLists.txt b/tests/sighandler/CMakeLists.txt similarity index 100% rename from rewriter/tests/sighandler/CMakeLists.txt rename to tests/sighandler/CMakeLists.txt diff --git a/rewriter/tests/sighandler/Output/main.out b/tests/sighandler/Output/main.out similarity index 100% rename from rewriter/tests/sighandler/Output/main.out rename to tests/sighandler/Output/main.out diff --git a/rewriter/tests/sighandler/include/lib.h b/tests/sighandler/include/lib.h similarity index 100% rename from rewriter/tests/sighandler/include/lib.h rename to tests/sighandler/include/lib.h diff --git a/rewriter/tests/sighandler/lib.c b/tests/sighandler/lib.c similarity index 100% rename from rewriter/tests/sighandler/lib.c rename to tests/sighandler/lib.c diff --git a/rewriter/tests/sighandler/main.c b/tests/sighandler/main.c similarity index 100% rename from rewriter/tests/sighandler/main.c rename to tests/sighandler/main.c diff --git a/rewriter/tests/simple1/CMakeLists.txt b/tests/simple1/CMakeLists.txt similarity index 100% rename from rewriter/tests/simple1/CMakeLists.txt rename to tests/simple1/CMakeLists.txt diff --git a/rewriter/tests/simple1/include/hooks.h b/tests/simple1/include/hooks.h similarity index 100% rename from rewriter/tests/simple1/include/hooks.h rename to tests/simple1/include/hooks.h diff --git a/rewriter/tests/simple1/include/simple1.h b/tests/simple1/include/simple1.h similarity index 100% rename from rewriter/tests/simple1/include/simple1.h rename to tests/simple1/include/simple1.h diff --git a/rewriter/tests/simple1/main.c b/tests/simple1/main.c similarity index 100% rename from rewriter/tests/simple1/main.c rename to tests/simple1/main.c diff --git a/rewriter/tests/simple1/simple1.c b/tests/simple1/simple1.c similarity index 100% rename from rewriter/tests/simple1/simple1.c rename to tests/simple1/simple1.c diff --git a/rewriter/tests/structs/CMakeLists.txt b/tests/structs/CMakeLists.txt similarity index 100% rename from rewriter/tests/structs/CMakeLists.txt rename to tests/structs/CMakeLists.txt diff --git a/rewriter/tests/structs/Output/structs.out b/tests/structs/Output/structs.out similarity index 100% rename from rewriter/tests/structs/Output/structs.out rename to tests/structs/Output/structs.out diff --git a/rewriter/tests/structs/include/structs.h b/tests/structs/include/structs.h similarity index 100% rename from rewriter/tests/structs/include/structs.h rename to tests/structs/include/structs.h diff --git a/rewriter/tests/structs/main.c b/tests/structs/main.c similarity index 100% rename from rewriter/tests/structs/main.c rename to tests/structs/main.c diff --git a/rewriter/tests/structs/structs.c b/tests/structs/structs.c similarity index 100% rename from rewriter/tests/structs/structs.c rename to tests/structs/structs.c diff --git a/rewriter/tests/threads/CMakeLists.txt b/tests/threads/CMakeLists.txt similarity index 100% rename from rewriter/tests/threads/CMakeLists.txt rename to tests/threads/CMakeLists.txt diff --git a/rewriter/tests/threads/Output/threads.out b/tests/threads/Output/threads.out similarity index 100% rename from rewriter/tests/threads/Output/threads.out rename to tests/threads/Output/threads.out diff --git a/rewriter/tests/threads/include/library.h b/tests/threads/include/library.h similarity index 100% rename from rewriter/tests/threads/include/library.h rename to tests/threads/include/library.h diff --git a/rewriter/tests/threads/library.c b/tests/threads/library.c similarity index 100% rename from rewriter/tests/threads/library.c rename to tests/threads/library.c diff --git a/rewriter/tests/threads/main.c b/tests/threads/main.c similarity index 100% rename from rewriter/tests/threads/main.c rename to tests/threads/main.c diff --git a/rewriter/tests/tls_protected/CMakeLists.txt b/tests/tls_protected/CMakeLists.txt similarity index 100% rename from rewriter/tests/tls_protected/CMakeLists.txt rename to tests/tls_protected/CMakeLists.txt diff --git a/rewriter/tests/tls_protected/Output/tls_protected_lib.out b/tests/tls_protected/Output/tls_protected_lib.out similarity index 100% rename from rewriter/tests/tls_protected/Output/tls_protected_lib.out rename to tests/tls_protected/Output/tls_protected_lib.out diff --git a/rewriter/tests/tls_protected/Output/tls_protected_main.out b/tests/tls_protected/Output/tls_protected_main.out similarity index 100% rename from rewriter/tests/tls_protected/Output/tls_protected_main.out rename to tests/tls_protected/Output/tls_protected_main.out diff --git a/rewriter/tests/tls_protected/include/library.h b/tests/tls_protected/include/library.h similarity index 100% rename from rewriter/tests/tls_protected/include/library.h rename to tests/tls_protected/include/library.h diff --git a/rewriter/tests/tls_protected/library.c b/tests/tls_protected/library.c similarity index 100% rename from rewriter/tests/tls_protected/library.c rename to tests/tls_protected/library.c diff --git a/rewriter/tests/tls_protected/main.c b/tests/tls_protected/main.c similarity index 100% rename from rewriter/tests/tls_protected/main.c rename to tests/tls_protected/main.c diff --git a/rewriter/tests/trusted_direct/CMakeLists.txt b/tests/trusted_direct/CMakeLists.txt similarity index 100% rename from rewriter/tests/trusted_direct/CMakeLists.txt rename to tests/trusted_direct/CMakeLists.txt diff --git a/rewriter/tests/trusted_direct/Output/trusted_direct.clean_exit.out b/tests/trusted_direct/Output/trusted_direct.clean_exit.out similarity index 100% rename from rewriter/tests/trusted_direct/Output/trusted_direct.clean_exit.out rename to tests/trusted_direct/Output/trusted_direct.clean_exit.out diff --git a/rewriter/tests/trusted_direct/Output/trusted_direct.out b/tests/trusted_direct/Output/trusted_direct.out similarity index 100% rename from rewriter/tests/trusted_direct/Output/trusted_direct.out rename to tests/trusted_direct/Output/trusted_direct.out diff --git a/rewriter/tests/trusted_direct/include/main/exported_fn.h b/tests/trusted_direct/include/main/exported_fn.h similarity index 100% rename from rewriter/tests/trusted_direct/include/main/exported_fn.h rename to tests/trusted_direct/include/main/exported_fn.h diff --git a/rewriter/tests/trusted_direct/include/plugin/plugin.h b/tests/trusted_direct/include/plugin/plugin.h similarity index 100% rename from rewriter/tests/trusted_direct/include/plugin/plugin.h rename to tests/trusted_direct/include/plugin/plugin.h diff --git a/rewriter/tests/trusted_direct/main.c b/tests/trusted_direct/main.c similarity index 100% rename from rewriter/tests/trusted_direct/main.c rename to tests/trusted_direct/main.c diff --git a/rewriter/tests/trusted_direct/plugin.c b/tests/trusted_direct/plugin.c similarity index 100% rename from rewriter/tests/trusted_direct/plugin.c rename to tests/trusted_direct/plugin.c diff --git a/rewriter/tests/trusted_indirect/CMakeLists.txt b/tests/trusted_indirect/CMakeLists.txt similarity index 100% rename from rewriter/tests/trusted_indirect/CMakeLists.txt rename to tests/trusted_indirect/CMakeLists.txt diff --git a/rewriter/tests/trusted_indirect/Output/trusted_indirect.clean_exit.out b/tests/trusted_indirect/Output/trusted_indirect.clean_exit.out similarity index 100% rename from rewriter/tests/trusted_indirect/Output/trusted_indirect.clean_exit.out rename to tests/trusted_indirect/Output/trusted_indirect.clean_exit.out diff --git a/rewriter/tests/trusted_indirect/Output/trusted_indirect.out b/tests/trusted_indirect/Output/trusted_indirect.out similarity index 100% rename from rewriter/tests/trusted_indirect/Output/trusted_indirect.out rename to tests/trusted_indirect/Output/trusted_indirect.out diff --git a/rewriter/tests/trusted_indirect/include/rand_op.h b/tests/trusted_indirect/include/rand_op.h similarity index 100% rename from rewriter/tests/trusted_indirect/include/rand_op.h rename to tests/trusted_indirect/include/rand_op.h diff --git a/rewriter/tests/trusted_indirect/main.c b/tests/trusted_indirect/main.c similarity index 100% rename from rewriter/tests/trusted_indirect/main.c rename to tests/trusted_indirect/main.c diff --git a/rewriter/tests/trusted_indirect/rand_op.c b/tests/trusted_indirect/rand_op.c similarity index 100% rename from rewriter/tests/trusted_indirect/rand_op.c rename to tests/trusted_indirect/rand_op.c diff --git a/rewriter/tests/two_keys_minimal/CMakeLists.txt b/tests/two_keys_minimal/CMakeLists.txt similarity index 100% rename from rewriter/tests/two_keys_minimal/CMakeLists.txt rename to tests/two_keys_minimal/CMakeLists.txt diff --git a/rewriter/tests/two_keys_minimal/Output/clean_exit.out b/tests/two_keys_minimal/Output/clean_exit.out similarity index 100% rename from rewriter/tests/two_keys_minimal/Output/clean_exit.out rename to tests/two_keys_minimal/Output/clean_exit.out diff --git a/rewriter/tests/two_keys_minimal/Output/main.out b/tests/two_keys_minimal/Output/main.out similarity index 100% rename from rewriter/tests/two_keys_minimal/Output/main.out rename to tests/two_keys_minimal/Output/main.out diff --git a/rewriter/tests/two_keys_minimal/Output/plugin.out b/tests/two_keys_minimal/Output/plugin.out similarity index 100% rename from rewriter/tests/two_keys_minimal/Output/plugin.out rename to tests/two_keys_minimal/Output/plugin.out diff --git a/rewriter/tests/two_keys_minimal/include/main/exported_fn.h b/tests/two_keys_minimal/include/main/exported_fn.h similarity index 100% rename from rewriter/tests/two_keys_minimal/include/main/exported_fn.h rename to tests/two_keys_minimal/include/main/exported_fn.h diff --git a/rewriter/tests/two_keys_minimal/include/plugin/plugin.h b/tests/two_keys_minimal/include/plugin/plugin.h similarity index 100% rename from rewriter/tests/two_keys_minimal/include/plugin/plugin.h rename to tests/two_keys_minimal/include/plugin/plugin.h diff --git a/rewriter/tests/two_keys_minimal/main.c b/tests/two_keys_minimal/main.c similarity index 100% rename from rewriter/tests/two_keys_minimal/main.c rename to tests/two_keys_minimal/main.c diff --git a/rewriter/tests/two_keys_minimal/plugin.c b/tests/two_keys_minimal/plugin.c similarity index 100% rename from rewriter/tests/two_keys_minimal/plugin.c rename to tests/two_keys_minimal/plugin.c diff --git a/rewriter/tests/two_shared_ranges/CMakeLists.txt b/tests/two_shared_ranges/CMakeLists.txt similarity index 100% rename from rewriter/tests/two_shared_ranges/CMakeLists.txt rename to tests/two_shared_ranges/CMakeLists.txt diff --git a/rewriter/tests/two_shared_ranges/Output/clean_exit.out b/tests/two_shared_ranges/Output/clean_exit.out similarity index 100% rename from rewriter/tests/two_shared_ranges/Output/clean_exit.out rename to tests/two_shared_ranges/Output/clean_exit.out diff --git a/rewriter/tests/two_shared_ranges/Output/main.out b/tests/two_shared_ranges/Output/main.out similarity index 100% rename from rewriter/tests/two_shared_ranges/Output/main.out rename to tests/two_shared_ranges/Output/main.out diff --git a/rewriter/tests/two_shared_ranges/Output/plugin.out b/tests/two_shared_ranges/Output/plugin.out similarity index 100% rename from rewriter/tests/two_shared_ranges/Output/plugin.out rename to tests/two_shared_ranges/Output/plugin.out diff --git a/rewriter/tests/two_shared_ranges/include/main/exported_fn.h b/tests/two_shared_ranges/include/main/exported_fn.h similarity index 100% rename from rewriter/tests/two_shared_ranges/include/main/exported_fn.h rename to tests/two_shared_ranges/include/main/exported_fn.h diff --git a/rewriter/tests/two_shared_ranges/include/plugin/plugin.h b/tests/two_shared_ranges/include/plugin/plugin.h similarity index 100% rename from rewriter/tests/two_shared_ranges/include/plugin/plugin.h rename to tests/two_shared_ranges/include/plugin/plugin.h diff --git a/rewriter/tests/two_shared_ranges/main.c b/tests/two_shared_ranges/main.c similarity index 100% rename from rewriter/tests/two_shared_ranges/main.c rename to tests/two_shared_ranges/main.c diff --git a/rewriter/tests/two_shared_ranges/plugin.c b/tests/two_shared_ranges/plugin.c similarity index 100% rename from rewriter/tests/two_shared_ranges/plugin.c rename to tests/two_shared_ranges/plugin.c diff --git a/rewriter/tests/untrusted_indirect/CMakeLists.txt b/tests/untrusted_indirect/CMakeLists.txt similarity index 100% rename from rewriter/tests/untrusted_indirect/CMakeLists.txt rename to tests/untrusted_indirect/CMakeLists.txt diff --git a/rewriter/tests/untrusted_indirect/Output/untrusted_indirect.clean_exit.out b/tests/untrusted_indirect/Output/untrusted_indirect.clean_exit.out similarity index 100% rename from rewriter/tests/untrusted_indirect/Output/untrusted_indirect.clean_exit.out rename to tests/untrusted_indirect/Output/untrusted_indirect.clean_exit.out diff --git a/rewriter/tests/untrusted_indirect/Output/untrusted_indirect.out b/tests/untrusted_indirect/Output/untrusted_indirect.out similarity index 100% rename from rewriter/tests/untrusted_indirect/Output/untrusted_indirect.out rename to tests/untrusted_indirect/Output/untrusted_indirect.out diff --git a/rewriter/tests/untrusted_indirect/foo.c b/tests/untrusted_indirect/foo.c similarity index 100% rename from rewriter/tests/untrusted_indirect/foo.c rename to tests/untrusted_indirect/foo.c diff --git a/rewriter/tests/untrusted_indirect/include/foo.h b/tests/untrusted_indirect/include/foo.h similarity index 100% rename from rewriter/tests/untrusted_indirect/include/foo.h rename to tests/untrusted_indirect/include/foo.h diff --git a/rewriter/tests/untrusted_indirect/main.c b/tests/untrusted_indirect/main.c similarity index 100% rename from rewriter/tests/untrusted_indirect/main.c rename to tests/untrusted_indirect/main.c From ec096acaca132daa6eee30c9b33e22e420880cc0 Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 21:45:16 -0500 Subject: [PATCH 02/10] tools: Move rewriter and pad-tls to top-level tools directory This commit also updates the LIT config files to point to the new rewriter location and updates CMake files to keep targets working. --- CMakeLists.txt | 3 +-- tests/lit.cfg.py | 2 +- tools/CMakeLists.txt | 5 +++++ {pad-tls => tools/pad-tls}/CMakeLists.txt | 0 {pad-tls => tools/pad-tls}/pad-tls.c | 0 {rewriter => tools/rewriter}/CAbi.h | 0 {rewriter => tools/rewriter}/CMakeLists.txt | 2 +- {rewriter => tools/rewriter}/DetermineAbi.cpp | 0 {rewriter => tools/rewriter}/DetermineAbi.h | 0 {rewriter => tools/rewriter}/GenCallAsm.cpp | 0 {rewriter => tools/rewriter}/GenCallAsm.h | 0 {rewriter => tools/rewriter}/SourceRewriter.cpp | 0 {rewriter => tools/rewriter}/TypeOps.cpp | 0 {rewriter => tools/rewriter}/TypeOps.h | 0 14 files changed, 8 insertions(+), 4 deletions(-) create mode 100644 tools/CMakeLists.txt rename {pad-tls => tools/pad-tls}/CMakeLists.txt (100%) rename {pad-tls => tools/pad-tls}/pad-tls.c (100%) rename {rewriter => tools/rewriter}/CAbi.h (100%) rename {rewriter => tools/rewriter}/CMakeLists.txt (97%) rename {rewriter => tools/rewriter}/DetermineAbi.cpp (100%) rename {rewriter => tools/rewriter}/DetermineAbi.h (100%) rename {rewriter => tools/rewriter}/GenCallAsm.cpp (100%) rename {rewriter => tools/rewriter}/GenCallAsm.h (100%) rename {rewriter => tools/rewriter}/SourceRewriter.cpp (100%) rename {rewriter => tools/rewriter}/TypeOps.cpp (100%) rename {rewriter => tools/rewriter}/TypeOps.h (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 290c505ebf..996ce68a29 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,8 +9,7 @@ set(EXTERNAL_DIR ${PROJECT_SOURCE_DIR}/external) add_subdirectory(libia2) add_subdirectory(examples) -add_subdirectory(rewriter) add_subdirectory(partition-alloc) -add_subdirectory(pad-tls) add_subdirectory(runtime) add_subdirectory(tests) +add_subdirectory(tools) diff --git a/tests/lit.cfg.py b/tests/lit.cfg.py index 690c2803c9..6a35ad020b 100644 --- a/tests/lit.cfg.py +++ b/tests/lit.cfg.py @@ -49,7 +49,7 @@ # test_source_root: The root path where tests are located. config.test_source_root = os.path.dirname(__file__) -llvm_config.add_tool_substitutions([ToolSubst('ia2-rewriter')], search_dirs=os.path.join(config.ia2_obj_root, "rewriter")) +llvm_config.add_tool_substitutions([ToolSubst('ia2-rewriter')], search_dirs=os.path.join(config.ia2_obj_root, "tools", "rewriter")) llvm_config.use_default_substitutions() llvm_config.use_clang() diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt new file mode 100644 index 0000000000..bdacdc735c --- /dev/null +++ b/tools/CMakeLists.txt @@ -0,0 +1,5 @@ +cmake_minimum_required(VERSION 3.12) +project(tools) + +add_subdirectory(rewriter) +add_subdirectory(pad-tls) diff --git a/pad-tls/CMakeLists.txt b/tools/pad-tls/CMakeLists.txt similarity index 100% rename from pad-tls/CMakeLists.txt rename to tools/pad-tls/CMakeLists.txt diff --git a/pad-tls/pad-tls.c b/tools/pad-tls/pad-tls.c similarity index 100% rename from pad-tls/pad-tls.c rename to tools/pad-tls/pad-tls.c diff --git a/rewriter/CAbi.h b/tools/rewriter/CAbi.h similarity index 100% rename from rewriter/CAbi.h rename to tools/rewriter/CAbi.h diff --git a/rewriter/CMakeLists.txt b/tools/rewriter/CMakeLists.txt similarity index 97% rename from rewriter/CMakeLists.txt rename to tools/rewriter/CMakeLists.txt index e7c67e170d..2fc0891fa2 100644 --- a/rewriter/CMakeLists.txt +++ b/tools/rewriter/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.12) -project(IA2Rewriter) +project(rewriter) find_package(LLVM REQUIRED CONFIG) message(STATUS "Found LLVM: ${LLVM_DIR} (found version \"${LLVM_PACKAGE_VERSION}\")") diff --git a/rewriter/DetermineAbi.cpp b/tools/rewriter/DetermineAbi.cpp similarity index 100% rename from rewriter/DetermineAbi.cpp rename to tools/rewriter/DetermineAbi.cpp diff --git a/rewriter/DetermineAbi.h b/tools/rewriter/DetermineAbi.h similarity index 100% rename from rewriter/DetermineAbi.h rename to tools/rewriter/DetermineAbi.h diff --git a/rewriter/GenCallAsm.cpp b/tools/rewriter/GenCallAsm.cpp similarity index 100% rename from rewriter/GenCallAsm.cpp rename to tools/rewriter/GenCallAsm.cpp diff --git a/rewriter/GenCallAsm.h b/tools/rewriter/GenCallAsm.h similarity index 100% rename from rewriter/GenCallAsm.h rename to tools/rewriter/GenCallAsm.h diff --git a/rewriter/SourceRewriter.cpp b/tools/rewriter/SourceRewriter.cpp similarity index 100% rename from rewriter/SourceRewriter.cpp rename to tools/rewriter/SourceRewriter.cpp diff --git a/rewriter/TypeOps.cpp b/tools/rewriter/TypeOps.cpp similarity index 100% rename from rewriter/TypeOps.cpp rename to tools/rewriter/TypeOps.cpp diff --git a/rewriter/TypeOps.h b/tools/rewriter/TypeOps.h similarity index 100% rename from rewriter/TypeOps.h rename to tools/rewriter/TypeOps.h From bb614b04395af68a4b9f550255a1b06d4f18ccfd Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 21:50:41 -0500 Subject: [PATCH 03/10] runtime: Create new top-level runtime directory This moves libia2, the PartitionAlloc shim and the tracer into the top-level runtime directory. The tracer subdirectory contains the what was previously in the top-level runtime directory. Thiscommit also updates the CMake files to keep targets working. --- CMakeLists.txt | 6 +-- cmake/define-test.cmake | 2 +- runtime/CMakeLists.txt | 52 ++----------------- {libia2 => runtime/libia2}/CMakeLists.txt | 0 {libia2 => runtime/libia2}/dynsym.syms | 0 {libia2 => runtime/libia2}/exit.c | 0 {libia2 => runtime/libia2}/ia2.c | 0 {libia2 => runtime/libia2}/include/ia2.h | 0 .../libia2}/include/ia2_compartment_init.inc | 0 .../libia2}/include/ia2_get_pkey.h | 0 .../libia2}/include/ia2_internal.h | 0 .../libia2}/include/permissive_mode.h | 0 .../libia2}/include/scrub_registers.h | 0 .../libia2}/include/test_fault_handler.h | 0 {libia2 => runtime/libia2}/main.c | 0 {libia2 => runtime/libia2}/padding.ld | 0 {libia2 => runtime/libia2}/threads.c | 0 .../partition-alloc}/CMakeLists.txt | 0 .../partition-alloc}/README.md | 0 .../partition-alloc/chromium_commit | 0 .../partition-alloc}/include/ia2_allocator.h | 0 .../partition-alloc}/partition_alloc.diff | 0 ...him_default_dispatch_to_partition_alloc.cc | 0 .../partition-alloc}/src/get_pkey.cc | 0 .../partition-alloc}/src/get_pkey.h | 0 .../partition-alloc}/src/shared_allocator.cc | 0 .../partition-alloc}/update.sh | 0 runtime/tracer/CMakeLists.txt | 50 ++++++++++++++++++ runtime/{ => tracer}/forbid_paths.c | 0 runtime/{ => tracer}/forbid_paths.h | 0 runtime/{ => tracer}/get_inferior_pkru.c | 0 runtime/{ => tracer}/get_inferior_pkru.h | 0 runtime/{ => tracer}/landlock.c | 0 runtime/{ => tracer}/landlock.h | 0 runtime/{ => tracer}/landlock_demo.c | 0 runtime/{ => tracer}/landlock_syscall.h | 0 runtime/{ => tracer}/mem_region.h | 0 runtime/{ => tracer}/memory-map/Cargo.toml | 0 runtime/{ => tracer}/memory-map/cbindgen.toml | 0 runtime/{ => tracer}/memory-map/src/lib.rs | 0 runtime/{ => tracer}/memory_map.h | 0 runtime/{ => tracer}/mmap_event.c | 0 runtime/{ => tracer}/mmap_event.h | 0 runtime/{ => tracer}/read_pkru_demo.c | 0 runtime/{ => tracer}/seccomp_filter.c | 0 runtime/{ => tracer}/seccomp_filter.h | 0 runtime/{ => tracer}/seccomp_filter_demo.c | 0 runtime/{ => tracer}/start.c | 0 runtime/{ => tracer}/strv.c | 0 runtime/{ => tracer}/strv.h | 0 runtime/{ => tracer}/track_memory_map.c | 0 runtime/{ => tracer}/track_memory_map.h | 0 runtime/{ => tracer}/track_memory_map_demo.c | 0 53 files changed, 57 insertions(+), 53 deletions(-) rename {libia2 => runtime/libia2}/CMakeLists.txt (100%) rename {libia2 => runtime/libia2}/dynsym.syms (100%) rename {libia2 => runtime/libia2}/exit.c (100%) rename {libia2 => runtime/libia2}/ia2.c (100%) rename {libia2 => runtime/libia2}/include/ia2.h (100%) rename {libia2 => runtime/libia2}/include/ia2_compartment_init.inc (100%) rename {libia2 => runtime/libia2}/include/ia2_get_pkey.h (100%) rename {libia2 => runtime/libia2}/include/ia2_internal.h (100%) rename {libia2 => runtime/libia2}/include/permissive_mode.h (100%) rename {libia2 => runtime/libia2}/include/scrub_registers.h (100%) rename {libia2 => runtime/libia2}/include/test_fault_handler.h (100%) rename {libia2 => runtime/libia2}/main.c (100%) rename {libia2 => runtime/libia2}/padding.ld (100%) rename {libia2 => runtime/libia2}/threads.c (100%) rename {partition-alloc => runtime/partition-alloc}/CMakeLists.txt (100%) rename {partition-alloc => runtime/partition-alloc}/README.md (100%) rename chromium_commit => runtime/partition-alloc/chromium_commit (100%) rename {partition-alloc => runtime/partition-alloc}/include/ia2_allocator.h (100%) rename {scripts/partition_alloc => runtime/partition-alloc}/partition_alloc.diff (100%) rename {partition-alloc => runtime/partition-alloc}/src/allocator_shim_default_dispatch_to_partition_alloc.cc (100%) rename {partition-alloc => runtime/partition-alloc}/src/get_pkey.cc (100%) rename {partition-alloc => runtime/partition-alloc}/src/get_pkey.h (100%) rename {partition-alloc => runtime/partition-alloc}/src/shared_allocator.cc (100%) rename {scripts/partition_alloc => runtime/partition-alloc}/update.sh (100%) create mode 100644 runtime/tracer/CMakeLists.txt rename runtime/{ => tracer}/forbid_paths.c (100%) rename runtime/{ => tracer}/forbid_paths.h (100%) rename runtime/{ => tracer}/get_inferior_pkru.c (100%) rename runtime/{ => tracer}/get_inferior_pkru.h (100%) rename runtime/{ => tracer}/landlock.c (100%) rename runtime/{ => tracer}/landlock.h (100%) rename runtime/{ => tracer}/landlock_demo.c (100%) rename runtime/{ => tracer}/landlock_syscall.h (100%) rename runtime/{ => tracer}/mem_region.h (100%) rename runtime/{ => tracer}/memory-map/Cargo.toml (100%) rename runtime/{ => tracer}/memory-map/cbindgen.toml (100%) rename runtime/{ => tracer}/memory-map/src/lib.rs (100%) rename runtime/{ => tracer}/memory_map.h (100%) rename runtime/{ => tracer}/mmap_event.c (100%) rename runtime/{ => tracer}/mmap_event.h (100%) rename runtime/{ => tracer}/read_pkru_demo.c (100%) rename runtime/{ => tracer}/seccomp_filter.c (100%) rename runtime/{ => tracer}/seccomp_filter.h (100%) rename runtime/{ => tracer}/seccomp_filter_demo.c (100%) rename runtime/{ => tracer}/start.c (100%) rename runtime/{ => tracer}/strv.c (100%) rename runtime/{ => tracer}/strv.h (100%) rename runtime/{ => tracer}/track_memory_map.c (100%) rename runtime/{ => tracer}/track_memory_map.h (100%) rename runtime/{ => tracer}/track_memory_map_demo.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 996ce68a29..e7747d2802 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,11 +5,9 @@ find_package(PkgConfig REQUIRED) set(EXTERNAL_DIR ${PROJECT_SOURCE_DIR}/external) -# libia2 needs to be first so it defines ${libia2_BINARY_DIR} -add_subdirectory(libia2) +# runtime needs to be first so it defines libia2_BINARY_DIR +add_subdirectory(runtime) add_subdirectory(examples) -add_subdirectory(partition-alloc) -add_subdirectory(runtime) add_subdirectory(tests) add_subdirectory(tools) diff --git a/cmake/define-test.cmake b/cmake/define-test.cmake index f83f221469..91be09e052 100644 --- a/cmake/define-test.cmake +++ b/cmake/define-test.cmake @@ -192,7 +192,7 @@ function(define_test) if (DEFINE_TEST_WITHOUT_SANDBOX) add_test(${TEST_NAME} ${WRAPPED_MAIN}) else() - add_test(NAME ${TEST_NAME} COMMAND ${CMAKE_BINARY_DIR}/runtime/ia2-sandbox ${CMAKE_CURRENT_BINARY_DIR}/${WRAPPED_MAIN} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + add_test(NAME ${TEST_NAME} COMMAND ${CMAKE_BINARY_DIR}/runtime/tracer/ia2-sandbox ${CMAKE_CURRENT_BINARY_DIR}/${WRAPPED_MAIN} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) add_dependencies(${WRAPPED_MAIN} ia2-sandbox) endif() add_dependencies(check ${WRAPPED_MAIN}) diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 2d927e75f6..da60ba1487 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -1,50 +1,6 @@ cmake_minimum_required(VERSION 3.12) -project(IA2Runtime) +project(runtime) -add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so - COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} cargo build --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/memory-map/Cargo.toml --release - DEPENDS memory-map/Cargo.toml memory-map/src/lib.rs -) - -add_library(memory-map STATIC IMPORTED) -set_property(TARGET memory-map PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so) -add_custom_target(memory-map-tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so) -add_dependencies(memory-map memory-map-tgt) - -add_executable(read-pkru - read_pkru_demo.c - get_inferior_pkru.c -) - -add_executable(track-memory-map - track_memory_map_demo.c - track_memory_map.c - mmap_event.c - get_inferior_pkru.c -) -target_link_libraries(track-memory-map PRIVATE memory-map) - -add_executable(seccomp-filter - seccomp_filter_demo.c - seccomp_filter.c -) - -add_executable(landlock - landlock_demo.c - landlock.c - strv.c - forbid_paths.c -) - -add_executable(ia2-sandbox - start.c - seccomp_filter.c - track_memory_map.c - mmap_event.c - get_inferior_pkru.c - landlock.c - strv.c - forbid_paths.c -) -target_link_libraries(ia2-sandbox PRIVATE memory-map) +add_subdirectory(libia2) +add_subdirectory(partition-alloc) +add_subdirectory(tracer) diff --git a/libia2/CMakeLists.txt b/runtime/libia2/CMakeLists.txt similarity index 100% rename from libia2/CMakeLists.txt rename to runtime/libia2/CMakeLists.txt diff --git a/libia2/dynsym.syms b/runtime/libia2/dynsym.syms similarity index 100% rename from libia2/dynsym.syms rename to runtime/libia2/dynsym.syms diff --git a/libia2/exit.c b/runtime/libia2/exit.c similarity index 100% rename from libia2/exit.c rename to runtime/libia2/exit.c diff --git a/libia2/ia2.c b/runtime/libia2/ia2.c similarity index 100% rename from libia2/ia2.c rename to runtime/libia2/ia2.c diff --git a/libia2/include/ia2.h b/runtime/libia2/include/ia2.h similarity index 100% rename from libia2/include/ia2.h rename to runtime/libia2/include/ia2.h diff --git a/libia2/include/ia2_compartment_init.inc b/runtime/libia2/include/ia2_compartment_init.inc similarity index 100% rename from libia2/include/ia2_compartment_init.inc rename to runtime/libia2/include/ia2_compartment_init.inc diff --git a/libia2/include/ia2_get_pkey.h b/runtime/libia2/include/ia2_get_pkey.h similarity index 100% rename from libia2/include/ia2_get_pkey.h rename to runtime/libia2/include/ia2_get_pkey.h diff --git a/libia2/include/ia2_internal.h b/runtime/libia2/include/ia2_internal.h similarity index 100% rename from libia2/include/ia2_internal.h rename to runtime/libia2/include/ia2_internal.h diff --git a/libia2/include/permissive_mode.h b/runtime/libia2/include/permissive_mode.h similarity index 100% rename from libia2/include/permissive_mode.h rename to runtime/libia2/include/permissive_mode.h diff --git a/libia2/include/scrub_registers.h b/runtime/libia2/include/scrub_registers.h similarity index 100% rename from libia2/include/scrub_registers.h rename to runtime/libia2/include/scrub_registers.h diff --git a/libia2/include/test_fault_handler.h b/runtime/libia2/include/test_fault_handler.h similarity index 100% rename from libia2/include/test_fault_handler.h rename to runtime/libia2/include/test_fault_handler.h diff --git a/libia2/main.c b/runtime/libia2/main.c similarity index 100% rename from libia2/main.c rename to runtime/libia2/main.c diff --git a/libia2/padding.ld b/runtime/libia2/padding.ld similarity index 100% rename from libia2/padding.ld rename to runtime/libia2/padding.ld diff --git a/libia2/threads.c b/runtime/libia2/threads.c similarity index 100% rename from libia2/threads.c rename to runtime/libia2/threads.c diff --git a/partition-alloc/CMakeLists.txt b/runtime/partition-alloc/CMakeLists.txt similarity index 100% rename from partition-alloc/CMakeLists.txt rename to runtime/partition-alloc/CMakeLists.txt diff --git a/partition-alloc/README.md b/runtime/partition-alloc/README.md similarity index 100% rename from partition-alloc/README.md rename to runtime/partition-alloc/README.md diff --git a/chromium_commit b/runtime/partition-alloc/chromium_commit similarity index 100% rename from chromium_commit rename to runtime/partition-alloc/chromium_commit diff --git a/partition-alloc/include/ia2_allocator.h b/runtime/partition-alloc/include/ia2_allocator.h similarity index 100% rename from partition-alloc/include/ia2_allocator.h rename to runtime/partition-alloc/include/ia2_allocator.h diff --git a/scripts/partition_alloc/partition_alloc.diff b/runtime/partition-alloc/partition_alloc.diff similarity index 100% rename from scripts/partition_alloc/partition_alloc.diff rename to runtime/partition-alloc/partition_alloc.diff diff --git a/partition-alloc/src/allocator_shim_default_dispatch_to_partition_alloc.cc b/runtime/partition-alloc/src/allocator_shim_default_dispatch_to_partition_alloc.cc similarity index 100% rename from partition-alloc/src/allocator_shim_default_dispatch_to_partition_alloc.cc rename to runtime/partition-alloc/src/allocator_shim_default_dispatch_to_partition_alloc.cc diff --git a/partition-alloc/src/get_pkey.cc b/runtime/partition-alloc/src/get_pkey.cc similarity index 100% rename from partition-alloc/src/get_pkey.cc rename to runtime/partition-alloc/src/get_pkey.cc diff --git a/partition-alloc/src/get_pkey.h b/runtime/partition-alloc/src/get_pkey.h similarity index 100% rename from partition-alloc/src/get_pkey.h rename to runtime/partition-alloc/src/get_pkey.h diff --git a/partition-alloc/src/shared_allocator.cc b/runtime/partition-alloc/src/shared_allocator.cc similarity index 100% rename from partition-alloc/src/shared_allocator.cc rename to runtime/partition-alloc/src/shared_allocator.cc diff --git a/scripts/partition_alloc/update.sh b/runtime/partition-alloc/update.sh similarity index 100% rename from scripts/partition_alloc/update.sh rename to runtime/partition-alloc/update.sh diff --git a/runtime/tracer/CMakeLists.txt b/runtime/tracer/CMakeLists.txt new file mode 100644 index 0000000000..67be2b5fce --- /dev/null +++ b/runtime/tracer/CMakeLists.txt @@ -0,0 +1,50 @@ +cmake_minimum_required(VERSION 3.12) +project(tracer) + +add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so + COMMAND CARGO_TARGET_DIR=${CMAKE_CURRENT_BINARY_DIR} cargo build --manifest-path ${CMAKE_CURRENT_SOURCE_DIR}/memory-map/Cargo.toml --release + DEPENDS memory-map/Cargo.toml memory-map/src/lib.rs +) + +add_library(memory-map STATIC IMPORTED) +set_property(TARGET memory-map PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so) +add_custom_target(memory-map-tgt DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/release/libmemory_map.so) +add_dependencies(memory-map memory-map-tgt) + +add_executable(read-pkru + read_pkru_demo.c + get_inferior_pkru.c +) + +add_executable(track-memory-map + track_memory_map_demo.c + track_memory_map.c + mmap_event.c + get_inferior_pkru.c +) +target_link_libraries(track-memory-map PRIVATE memory-map) + +add_executable(seccomp-filter + seccomp_filter_demo.c + seccomp_filter.c +) + +add_executable(landlock + landlock_demo.c + landlock.c + strv.c + forbid_paths.c +) + +add_executable(ia2-sandbox + start.c + seccomp_filter.c + track_memory_map.c + mmap_event.c + get_inferior_pkru.c + landlock.c + strv.c + forbid_paths.c +) +target_link_libraries(ia2-sandbox PRIVATE memory-map) diff --git a/runtime/forbid_paths.c b/runtime/tracer/forbid_paths.c similarity index 100% rename from runtime/forbid_paths.c rename to runtime/tracer/forbid_paths.c diff --git a/runtime/forbid_paths.h b/runtime/tracer/forbid_paths.h similarity index 100% rename from runtime/forbid_paths.h rename to runtime/tracer/forbid_paths.h diff --git a/runtime/get_inferior_pkru.c b/runtime/tracer/get_inferior_pkru.c similarity index 100% rename from runtime/get_inferior_pkru.c rename to runtime/tracer/get_inferior_pkru.c diff --git a/runtime/get_inferior_pkru.h b/runtime/tracer/get_inferior_pkru.h similarity index 100% rename from runtime/get_inferior_pkru.h rename to runtime/tracer/get_inferior_pkru.h diff --git a/runtime/landlock.c b/runtime/tracer/landlock.c similarity index 100% rename from runtime/landlock.c rename to runtime/tracer/landlock.c diff --git a/runtime/landlock.h b/runtime/tracer/landlock.h similarity index 100% rename from runtime/landlock.h rename to runtime/tracer/landlock.h diff --git a/runtime/landlock_demo.c b/runtime/tracer/landlock_demo.c similarity index 100% rename from runtime/landlock_demo.c rename to runtime/tracer/landlock_demo.c diff --git a/runtime/landlock_syscall.h b/runtime/tracer/landlock_syscall.h similarity index 100% rename from runtime/landlock_syscall.h rename to runtime/tracer/landlock_syscall.h diff --git a/runtime/mem_region.h b/runtime/tracer/mem_region.h similarity index 100% rename from runtime/mem_region.h rename to runtime/tracer/mem_region.h diff --git a/runtime/memory-map/Cargo.toml b/runtime/tracer/memory-map/Cargo.toml similarity index 100% rename from runtime/memory-map/Cargo.toml rename to runtime/tracer/memory-map/Cargo.toml diff --git a/runtime/memory-map/cbindgen.toml b/runtime/tracer/memory-map/cbindgen.toml similarity index 100% rename from runtime/memory-map/cbindgen.toml rename to runtime/tracer/memory-map/cbindgen.toml diff --git a/runtime/memory-map/src/lib.rs b/runtime/tracer/memory-map/src/lib.rs similarity index 100% rename from runtime/memory-map/src/lib.rs rename to runtime/tracer/memory-map/src/lib.rs diff --git a/runtime/memory_map.h b/runtime/tracer/memory_map.h similarity index 100% rename from runtime/memory_map.h rename to runtime/tracer/memory_map.h diff --git a/runtime/mmap_event.c b/runtime/tracer/mmap_event.c similarity index 100% rename from runtime/mmap_event.c rename to runtime/tracer/mmap_event.c diff --git a/runtime/mmap_event.h b/runtime/tracer/mmap_event.h similarity index 100% rename from runtime/mmap_event.h rename to runtime/tracer/mmap_event.h diff --git a/runtime/read_pkru_demo.c b/runtime/tracer/read_pkru_demo.c similarity index 100% rename from runtime/read_pkru_demo.c rename to runtime/tracer/read_pkru_demo.c diff --git a/runtime/seccomp_filter.c b/runtime/tracer/seccomp_filter.c similarity index 100% rename from runtime/seccomp_filter.c rename to runtime/tracer/seccomp_filter.c diff --git a/runtime/seccomp_filter.h b/runtime/tracer/seccomp_filter.h similarity index 100% rename from runtime/seccomp_filter.h rename to runtime/tracer/seccomp_filter.h diff --git a/runtime/seccomp_filter_demo.c b/runtime/tracer/seccomp_filter_demo.c similarity index 100% rename from runtime/seccomp_filter_demo.c rename to runtime/tracer/seccomp_filter_demo.c diff --git a/runtime/start.c b/runtime/tracer/start.c similarity index 100% rename from runtime/start.c rename to runtime/tracer/start.c diff --git a/runtime/strv.c b/runtime/tracer/strv.c similarity index 100% rename from runtime/strv.c rename to runtime/tracer/strv.c diff --git a/runtime/strv.h b/runtime/tracer/strv.h similarity index 100% rename from runtime/strv.h rename to runtime/tracer/strv.h diff --git a/runtime/track_memory_map.c b/runtime/tracer/track_memory_map.c similarity index 100% rename from runtime/track_memory_map.c rename to runtime/tracer/track_memory_map.c diff --git a/runtime/track_memory_map.h b/runtime/tracer/track_memory_map.h similarity index 100% rename from runtime/track_memory_map.h rename to runtime/tracer/track_memory_map.h diff --git a/runtime/track_memory_map_demo.c b/runtime/tracer/track_memory_map_demo.c similarity index 100% rename from runtime/track_memory_map_demo.c rename to runtime/tracer/track_memory_map_demo.c From 1fd591ae46698cb4003ae0d9aa80fc08174856af Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Wed, 6 Mar 2024 09:55:35 -0500 Subject: [PATCH 04/10] external/nginx: Update nginx config script with new repo layout --- external/nginx/auto/make | 33 +++++++++++++++++++++------------ external/nginx/auto/sources | 2 +- external/nginx/reconfigure | 4 ++-- 3 files changed, 24 insertions(+), 15 deletions(-) diff --git a/external/nginx/auto/make b/external/nginx/auto/make index dd0eb57197..f98cac815b 100644 --- a/external/nginx/auto/make +++ b/external/nginx/auto/make @@ -27,14 +27,23 @@ LINK = $LINK C_SYSTEM_INCLUDE = `$CC -print-file-name=include` C_SYSTEM_INCLUDE_FIXED = `$CC -print-file-name=include-fixed` + +# Directory for IA2 build artifacts IA2_ROOT = $NGX_OBJS/../ia2 -PAD_TLS = \$(IA2_ROOT)/pad-tls/pad-tls + +LIBIA2_DIR = $REPO_ROOT/runtime/libia2 +LIBIA2_BUILD_DIR = \$(IA2_ROOT)/runtime/libia2 + +PA_DIR = $REPO_ROOT/runtime/partition-alloc +PA_BUILD_DIR = \$(IA2_ROOT)/runtime/partition-alloc + +PAD_TLS = \$(IA2_ROOT)/tools/pad-tls/pad-tls IA2_ENABLE = 1 IA2_CALLGATES_TARGET = $NGX_OBJS/libia2_callgates.so ifneq (\$(IA2_ENABLE),0) -IA2_LIBS = $NGX_OBJS/libia2_callgates.so \$(IA2_ROOT)/libia2/liblibia2.a +IA2_LIBS = $NGX_OBJS/libia2_callgates.so \$(LIBIA2_BUILD_DIR)/liblibia2.a else IA2_LIBS = endif @@ -50,8 +59,8 @@ IA2_CFLAGS = \\ -Wno-error \\ -Werror=incompatible-pointer-types \\ \$(IA2_EXTRA_CFLAGS) \\ - -I $REPO_ROOT/libia2/include \\ - -I $REPO_ROOT/partition-alloc/include + -I \$(LIBIA2_DIR)/include \\ + -I \$(PA_DIR)/include IA2_PREREWRITER_LDFLAGS = \\ -Wl,--wrap=pthread_create @@ -61,10 +70,10 @@ IA2_LDFLAGS = \\ -Wl,--wrap=main \\ -Wl,-z,now \\ -Wl,-z,relro \\ - -Wl,-T\$(IA2_ROOT)/libia2/padding.ld \\ - -Wl,--dynamic-list=\$(IA2_ROOT)/libia2/dynsym.syms \\ + -Wl,-T\$(LIBIA2_BUILD_DIR)/padding.ld \\ + -Wl,--dynamic-list=\$(LIBIA2_BUILD_DIR)/dynsym.syms \\ -Wl,--export-dynamic \\ - -Wl,--rpath=\$(IA2_ROOT)/partition-alloc/ + -Wl,--rpath=\$(PA_BUILD_DIR)/ ifneq (\$(IA2_ENABLE),0) IA2_LDFLAGS += \\ @@ -88,8 +97,8 @@ IA2_MODULE_CFLAGS = \\ -Wno-error \\ -Werror=incompatible-pointer-types \\ \$(IA2_EXTRA_CFLAGS) \\ - -I $REPO_ROOT/libia2/include \\ - -I $REPO_ROOT/partition-alloc/include + -I \$(LIBIA2_DIR)/include \\ + -I \$(PA_DIR)/include IA2_MODULE_LDFLAGS = \\ -Wl,-z,now \\ @@ -97,11 +106,11 @@ IA2_MODULE_LDFLAGS = \\ -pthread \\ -Wl,--wrap=pthread_create \\ -Wl,@$NGX_OBJS/../wrapper_2.ld \\ - -Wl,-T\$(IA2_ROOT)/libia2/padding.ld + -Wl,-T\$(LIBIA2_BUILD_DIR)/padding.ld END -CORE_LIBS="$CORE_LIBS \$(IA2_ROOT)/partition-alloc/libpartition-alloc.so" +CORE_LIBS="$CORE_LIBS \$(PA_BUILD_DIR)/libpartition-alloc.so" if test -n "$NGX_PERL_CFLAGS"; then echo NGX_PERL_CFLAGS = $NGX_PERL_CFLAGS >> $NGX_MAKEFILE @@ -305,7 +314,7 @@ binary: $NGX_OBJS${ngx_dirsep}nginx$ngx_binext \$(IA2_CALLGATES_TARGET): \$(CC) -shared -fPIC -Wl,-z,now $NGX_OBJS/../wrapper.c \ - -I $REPO_ROOT/libia2/include -o \$(IA2_CALLGATES_TARGET) + -I \$(LIBIA2_DIR)/include -o \$(IA2_CALLGATES_TARGET) $NGX_OBJS/ngx_rtmp_module_tls_padded.so: $NGX_OBJS/ngx_rtmp_module.so cp $NGX_OBJS/ngx_rtmp_module.so $NGX_OBJS/ngx_rtmp_module_tls_padded.so diff --git a/external/nginx/auto/sources b/external/nginx/auto/sources index 3a5877a7a9..ad73ef7eb3 100644 --- a/external/nginx/auto/sources +++ b/external/nginx/auto/sources @@ -42,7 +42,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_crypt.h \ src/core/ngx_proxy_protocol.h \ src/core/ngx_syslog.h \ - $REPO_ROOT/libia2/include/permissive_mode.h" + $REPO_ROOT/runtime/libia2/include/permissive_mode.h" CORE_SRCS="src/core/nginx.c \ diff --git a/external/nginx/reconfigure b/external/nginx/reconfigure index a1a74b8825..da8ffbf66e 100755 --- a/external/nginx/reconfigure +++ b/external/nginx/reconfigure @@ -7,8 +7,8 @@ IA2_BUILD_DIR=${BUILD_DIR}/ia2 NGINX_BUILD_DIR=${BUILD_DIR}/nginx NGINX_ROOT=${EXTERNAL_ROOT}/nginx NGINX_RTMP_ROOT=${EXTERNAL_ROOT}/nginx-rtmp-module -SRC_REWRITER=$IA2_BUILD_DIR/rewriter/ia2-rewriter -LIBIA2=$IA2_BUILD_DIR/libia2/liblibia2.a +SRC_REWRITER=$IA2_BUILD_DIR/tools/rewriter/ia2-rewriter +LIBIA2=$IA2_BUILD_DIR/runtime/libia2/liblibia2.a TEMP_FILES=( nginx.pid err.log From 19a75f0d5df1bb116a89d80a9e3c8d008422b20f Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 22:32:14 -0500 Subject: [PATCH 05/10] docs: Document repo directory structure --- docs/directory_structure.md | 59 +++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 docs/directory_structure.md diff --git a/docs/directory_structure.md b/docs/directory_structure.md new file mode 100644 index 0000000000..3389412787 --- /dev/null +++ b/docs/directory_structure.md @@ -0,0 +1,59 @@ +# Repo directory structure + +## cmake +CMake files for writing automated tests + + +## docs +Contains documentation on usage, design and technical details + + +## examples +Compartmentalized demo applications (not tested as part of the automated test +suite) + + +## external +Third-party code. These are git subtrees of upstream codebases and each commit +may only modify one subtree or the main repository. + +#### chromium +The subset of chromium needed to build PartitionAlloc. See +runtime/partition-alloc for subtree's latest upstream commit and details on +pulling upstream changes. + +#### nginx +Nginx web server pulled from github.com/nginx/nginx mirror. Used with the RTMP +module to demo compartmentalizing Nginx plugins. + +#### nginx-rtmp-module +Nginx media streaming RTMP module from github.com/arut/nginx-rtmp-module + + +## runtime +The compartmentalization runtime, including code for both the target process +itself and for tracing the process. + +#### libia2 +The main compartmentalization library. Includes code for interposing libc and +the API for compartmentalizing codebases where manual changes are required. + +#### partition-alloc +A compartment-aware shim for PartitionAlloc. + +#### tracer +A program for restricting syscalls and tracking memory ownership changes as a result of syscalls in compartmentalized programs. + + +## tests +The automated tests that are run as part of the `check` CMake target. + + +## tools +Host tools required to build compartmentalized programs. + +#### rewriter +Source rewriter and code generator for call gates. + +#### pad-tls +Script to patch TLS segments in compartmentalized ELFs. From 25188cf9d1af420734df717719ed82b50ac5b2ca Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 14:34:45 -0500 Subject: [PATCH 06/10] docs: Remove initial Phase 2 design notes --- docs/design.md | 68 -------------------------------------------------- 1 file changed, 68 deletions(-) delete mode 100644 docs/design.md diff --git a/docs/design.md b/docs/design.md deleted file mode 100644 index 34aedcfabc..0000000000 --- a/docs/design.md +++ /dev/null @@ -1,68 +0,0 @@ -# Source-to-Source Header Rewriting Design - -In Phase 1 we relied on compiler instrumentation to insert call gates at -inter-compartment calls and for rewriting object allocations for shared values. -For Phase II we plan to instead use source rewriting and standard linking to -interpose between compartments, removing the requirement for a customized -compiler. - -## Design Structure - -Our goal is to compartmentalize library(s) at the dynamic linking interface -between shared libraries. These libraries generally use the C ABI and declare -their API using C headers. Our rewriter will take these header declarations as -input and produce a new, drop-in replacement library that exposes the same API -but includes compartment transitions when entering and exiting the original -library code. This replacement library will only contain call-gate wrappers for -each exported function and will dynamically link against the original library -for the actual implementations of the API. - -By replacing the original library with our wrapper in the application build -system, users can be sure that they cannot inadvertently call functions in the -compartmentalized library directly, bypassing the compartment transition. This -also handles `dlopen` calls, as long as the applications `dlopen`s the wrapper -library rather than the original. - -The rewriter will produce C files with inline call gates and stack transitions -that users can audit if desired and can build using their existing toolchain. -When we change types of function declarations (e.g. char* -> SharedCharPtr) to -indicate that a type needs to be allocated in the shared memory region, we will -need to produce a replacement header with these rewritten types for users to -include instead of the original library's header. Again, these headers will be -standard C and auditable after creation. - -Using a C API is the lowest common denominator for FFI interop between -languages. Even C++ and Rust usually use the C ABI to interop with other -external libraries. We may need a different design if we want to support -compartmentalizing, e.g., pure Rust crates rather than external C libraries. - -## Compartment Transitions - -### Trusted -> Untrusted direct calls - -Our wrapper library will contain wrappers for every exported function. Each -wrapper will save and clear callee-saved registers to the caller stack, save an -identifier or address to the stack to validate the return site, copy any -parameters on the stack to the callee stack, switch compartments, make a direct -call to the callee. On returning the wrapper will transition back to the -original compartment, check the stack cookie/return address to ensure that the -program returned to the corresponding wrapper, switch to the caller stack, and -return. - -### Untrusted -> Trusted direct calls - -Rare case. During wrapper creation we may be able to scan the target library for -unresolved symbols and provide reverse wrappers for these symbols. - -### Trusted -> Untrusted indirect calls - -Indirect calls to exported functions will go through our wrappers, as taking the -address of an exported function in the target library will give the address of -the wrapper. Private callbacks that aren't exported are trickier. We will -probably need to replace function pointer types in the headers with special -opaque structures that capture the function pointer and redirect it to a call -gate transition. - -### Untrusted -> Trusted indirect calls - -Same as trusted -> untrusted in the wrapper paradigm. \ No newline at end of file From f9ef096e30a074799afe9ed2483a5b38dc756352 Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 16:16:09 -0500 Subject: [PATCH 07/10] docs: Add up-to-date design doc --- docs/design.md | 84 ++++++++++++++++++++++++++++++++++++++++++ docs/img/workflow.png | Bin 0 -> 70716 bytes 2 files changed, 84 insertions(+) create mode 100644 docs/design.md create mode 100644 docs/img/workflow.png diff --git a/docs/design.md b/docs/design.md new file mode 100644 index 0000000000..36f450f5cb --- /dev/null +++ b/docs/design.md @@ -0,0 +1,84 @@ +# Compartmentalization design + +IA2 is a sandboxing framework with the following goals: + +1. Allow sandboxing individual processes at the dynamic shared object (DSO) granularity +2. Allow inspection of code inserted by the framework +3. Avoid changes to existing compilers and linkers +4. Avoid changes to the operating system or dynamic linker + +IA2 can be used in conjunction with multi-process sandboxing and is particularly +suitable for processes that can't feasibly be split into more processes. The x86 +implementation relies on Memory Protection Keys (MPK) for protecting pages and +control-flow integrity (e.g. as provided by Intel's CET). It currently only +supports Linux, but its design does not preclude porting it to other operating +systems that provide access to the previously mentioned hardware primitives. + +# Protected memory + +Compartmentalization protects applications against spatial memory-safety +vulnerabilities in dependencies by placing sets of DSOs in separate +compartments. Memory belonging to each set of DSOs can only be accessed from its +compartment by default. This includes stack variables, static and +dynamically-allocated data and thread-local storage. The on-disk application +and libraries are assumed to be accessible to attackers, so read-only static +data is not protected from other compartments since it can just be read from the +binaries. + +# Building compartmentalized applications + +The following diagram shows the workflow for building compartmentalized +applications. + +![compartmentalization workflow](img/workflow.png) + +The build process works by adding a source code rewriting step before each +build. This creates new source files which are then passed on to an existing +build system with some additional standard compiler flags. The rewriter also +generates a source file with application-specific call-gate code and the +framework provides a static library that must also be linked in. + +## Supported compilers and linkers + +The framework is routinely tested with gcc and clang as compilers and LLVM's lld +and GNU ld as linkers. The gold linker is currently not supported due to its +minimal support for linker scripts. Other compilers may be added as the need +arises. + +# Runtime Initialization + +The runtime initialization happens by interposing `main` using `ld --wrap=main`. +The `main` wrapper switches from the stack initialized by the loader to a +protected stack for the main binary's compartment, initializes the PKRU +register to set memory access permissions for the initial compartment then calls +the real `main` provided by the application. Once the real `main` returns the +wrapper undos these operations before returning control to the C runtime. This +implies protecting against vulnerabilities in the C runtime is out of scope. + +The `INIT_RUNTIME` macro must also be invoked to initialize the stacks and +thread-local storage used by each compartment. Applications require one stack +per (compartment * thread), so to minimize memory usage only one stack per +compartment is initially created and further sets of compartment stacks are +allocated on-demand as new threads are created. + +# Compartment initialization + +When DSOs are loaded, their statically-allocated memory is protected using +`pkey_mprotect`. This happens by including `ia2_compartment_init.inc` in one DSO +per compartment. This inserts a constructor (called automatically) that uses +`dl_iterate_phdr` to find the writeable ELF segments for the DSO and its +dependencies declared using `IA2_COMPARTMENT_LIBRARIES`. + +# Framework code interposition + +Calls to DSOs in different compartments are interposed using call gates. To +provide build-time assurance that call gates cannot be misused, they are +application-specific and generated by the rewriter. Direct cross-compartment +calls are identified by the `__wrap_` prefix. To ensure that compartments can be +mutually distrusting, indirect cross-compartment calls are split into sets of +two half call gates that uses an intermediate PKRU value without access to any +compartment. For each potential indirect call, the rewriter inserts the first +half call gate at the callsite and replaces the function pointer expression with +the second half call gate. To ensure that roundtrip casts between `void *` and +function pointers do not lead to missing call gates, the rewriter also changes +function pointer types in the rewritten sources to ABI-compatible structs. diff --git a/docs/img/workflow.png b/docs/img/workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..ddd3adbbc688eec54dfbec18e35a8aaee86a38cb GIT binary patch literal 70716 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 Date: Thu, 29 Feb 2024 16:49:44 -0500 Subject: [PATCH 08/10] docs: Move CMake build instructions out of README --- README.md | 37 +------------------------------------ docs/build_instructions.md | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 36 deletions(-) create mode 100644 docs/build_instructions.md diff --git a/README.md b/README.md index 8054b1abbc..87d85c2b39 100644 --- a/README.md +++ b/README.md @@ -1,42 +1,7 @@ -# IA2 Phase 2 +# Intent-capturing Annotations for Isolation and Assurance (IA2 Phase 2) This repo provides tools for compartmentalizing an application and its dependencies using Intel's memory protection keys (MPK) for userspace. The repo includes a tool that rewrites headers to create call gate wrappers as well as the runtime to initialize the protection keys for trusted compartments. -## Setup - -Ubuntu 20.04 is used for testing. Other Linux distributions may or may not work. Adjust the commands below accordingly. - -### Install the package prerequisites. - -``` -sudo apt install -y libusb-1.0-0-dev libclang-dev llvm-dev \ - ninja-build zlib1g-dev python3-pip cmake \ - libavformat-dev libavutil-dev pcregrep patchelf -pip install lit -rustup install nightly -``` - -### Configure with CMake - -*Note*: Adjust paths to your version of Clang/LLVM - -``` -mkdir build && pushd build -cmake .. \ - -DClang_DIR=/usr/lib/cmake/clang-12 \ - -DLLVM_DIR=/usr/lib/llvm-12/cmake \ - -DLLVM_EXTERNAL_LIT=`which lit` \ - -G Ninja -``` - -### Build and run the tests - -*Note*: Pass `-v` to ninja to see build commands and output from failing tests. - -``` -ninja check-ia2 -``` - ## Usage ### Defining compartments diff --git a/docs/build_instructions.md b/docs/build_instructions.md new file mode 100644 index 0000000000..37d4a89aea --- /dev/null +++ b/docs/build_instructions.md @@ -0,0 +1,34 @@ +# Setup + +Ubuntu 20.04 is used for testing. Other Linux distributions may or may not work. Adjust the commands below accordingly. + +## Install the package prerequisites. + +``` +sudo apt install -y libusb-1.0-0-dev libclang-dev llvm-dev \ + ninja-build zlib1g-dev python3-pip cmake \ + libavformat-dev libavutil-dev pcregrep patchelf +pip install lit +rustup install nightly +``` + +## Configure with CMake + +*Note*: Adjust paths to your version of Clang/LLVM + +``` +mkdir build && pushd build +cmake .. \ + -DClang_DIR=/usr/lib/cmake/clang-12 \ + -DLLVM_DIR=/usr/lib/llvm-12/cmake \ + -DLLVM_EXTERNAL_LIT=`which lit` \ + -G Ninja +``` + +## Build and run the tests + +*Note*: Pass `-v` to ninja to see build commands and output from failing tests. + +``` +ninja check-ia2 +``` From 857f6437379b2f245be213714f5941eed2e58c56 Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Thu, 29 Feb 2024 21:37:42 -0500 Subject: [PATCH 09/10] docs: update build_instructions.md --- docs/build_instructions.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/docs/build_instructions.md b/docs/build_instructions.md index 37d4a89aea..bba03ee6b8 100644 --- a/docs/build_instructions.md +++ b/docs/build_instructions.md @@ -14,21 +14,30 @@ rustup install nightly ## Configure with CMake -*Note*: Adjust paths to your version of Clang/LLVM +*Note*: Adjust paths to your version of Clang/LLVM or using `llvm-config --cmakedir` ``` mkdir build && pushd build cmake .. \ - -DClang_DIR=/usr/lib/cmake/clang-12 \ - -DLLVM_DIR=/usr/lib/llvm-12/cmake \ + -DClang_DIR=/usr/lib/cmake/clang-15 \ + -DLLVM_DIR=/usr/lib/cmake/llvm-15 \ -DLLVM_EXTERNAL_LIT=`which lit` \ -G Ninja ``` -## Build and run the tests +### Notable CMake variables -*Note*: Pass `-v` to ninja to see build commands and output from failing tests. +- `LIBIA2_DEBUG` - Adds additional runtime assertions to validate control-flow. +- `LIBIA2_AARCH64` - Builds the runtime and tests for Aarch64 using MTE instead of x86-64 with MPK. Tools are still built for the host. +- `CMAKE_TOOLCHAIN_FILE` - Typically set to `cmake/aarch64-toolchain.cmake` to build for Aarch64 using GCC. This also sets LIBIA2_AARCH64. -``` -ninja check-ia2 -``` +## CMake targets + +- `check` - builds and runs the test suite. Pass `-v` to ninja to see build commands and output from failing tests. +- `ia2-rewriter` - builds the source-code rewriter. Depends on libclang-dev and llvm-dev. +- `pad-tls` - builds a script for padding ELF headers for TLS segments. Only required for compartmentalized DSOs that use thread-local storage. +- `libia2` - builds the runtime as a static library. This does not include call gate transitions as those are program-specific and generated by the rewriter. +- `partition-alloc` - builds the compartment-aware shim for Chromium's PartitionAlloc allocator. +- `ia2-sandbox` - builds the syscall tracer. + +Tests are enumerated in `tests/CMakeLists.txt`. To build a specific test use `$TEST_main_wrapped` as the target. See the [`directory structure doc`](docs/directory_structure.md) for an overview of the rest of the repo's contents. From 2b0cf6e40081c621b3e842007ae9e2eea551c562 Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Tue, 12 Mar 2024 16:18:03 -0400 Subject: [PATCH 10/10] docs: update README --- README.md | 49 ++++++++++++------------------------------------- 1 file changed, 12 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 87d85c2b39..f6524f7f61 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,21 @@ -# Intent-capturing Annotations for Isolation and Assurance (IA2 Phase 2) +# IA2 Sandboxing Runtime -This repo provides tools for compartmentalizing an application and its dependencies using Intel's memory protection keys (MPK) for userspace. The repo includes a tool that rewrites headers to create call gate wrappers as well as the runtime to initialize the protection keys for trusted compartments. +IA2 (or Intent-capturing Annotations for Isolation and Assurance) is a runtime and set of tools for compartmentalizing C/C++ applications to provide coarse spatial memory-safety. -## Usage - -### Defining compartments - -First invoke the [`INIT_RUNTIME`](https://github.com/immunant/IA2-Phase2/blob/5cdb743d3a42e8df8e4d8cf61fb3551656001c73/libia2/include/ia2.h#L204) macro once in any binary or shared library to define the number of protection keys that need to be allocated. The argument passed to `INIT_RUNTIME` must be a number between 1 and 15. Then the [`IA2_COMPARTMENT`](https://github.com/immunant/IA2-Phase2/blob/4a3a0c8d2a2b1881e0e41c89db070db3da187f9e/libia2/include/ia2_compartment_init.inc#L3) `#define` is used to define trusted compartments at the shared object level. This can be the main executable ELF or any dynamically-linked shared libraries. Memory belonging to a trusted compartment is assigned one of the [15 protection keys](https://man7.org/linux/man-pages/man7/pkeys.7.html) and can only be accessed by the shared object itself. Objects that don't explicitly define a compartment are treated as untrusted by default. - -To assign a protection key to a trusted compartment, insert `#define IA2_COMPARTMENT n` with an argument between 1-15 specifying the index of the protection key, and include `ia2_compartment_init.inc`: +Applications typically use many third-party C/C++ libraries that may introduce memory-safety vulnerabilities if developers don't have the resources to exhaustively audit them. Putting everything in a single process means that a vulnerability in one library can compromise another and that's a problem for programs that handle security-sensitive information. The IA2 sandbox splits applications into isolated compartments and uses CPU hardware features (Memory Protection Keys on x86-64) to forbid cross-compartment memory accesses. Compartments are delineated along pre-existing boundaries (at the shared library level) avoiding the need to rearchitect a codebase and source-code annotations are used to mark variables that are intentionally shared between compartments. The runtime also ensures that each set of shared libraries in a compartment uses a distinct region of memory for its stack, heap, static and thread-local variables. -```c -#define IA2_COMPARTMENT 1 -#include -``` +## Sandboxing workflow -This argument must differ from the other trusted compartments. Trusted compartments must also be aligned and padded properly by using the `padding.ld` script in `libia2/`. In CMake this is done automatically for executables built with `define_test` while libraries built with `define_shared_lib` must add `LINK_OPTS "-Wl,-T${libia2_BINARY_DIR}/padding.ld"`. To use in manual builds just include `-Wl,-T/path/to/padding.ld` in the final compilation step. Manual builds also require disabling lazy binding with `-Wl,-z,now`. +IA2 uses source-code transformations as part of the build process to sandbox programs. Our [rewriter tool](docs/source_rewriter.md) processes a codebase's source files before each build to produce a set of intermediate sources with annotations for compartment transitions at cross-DSO calls. These intermediate sources are then passed on to a build system using off-the-shelf compilers with some additional flags and the IA2 runtime is linked in to create the compartmentalized program. See the [design doc](docs/design.md) for details. -### Wrapping calls +This workflow treats intermediate sources as build artifacts so the only annotations that need to be checked-in are those that can't be inferred. These are primarily annotations for shared variables and cross-library indirect calls when round-tripping function pointers through `void *`. For the latter the rewriter also does type-system transformations to turn missing annotations into compiler errors and avoid accidental miscompartmentalization. In compartmentalized programs cross-compartment memory accesses kill the process, but they also support a permissive mode which just logs the accesses to aid developers adding shared variable annotations. -Calls between compartments must have call gates to toggle the PKRU permissions at each transition. For direct calls, this is done by rewriting headers to generate the source for a wrapper that provides versions of every function with call gates. These wrappers are specific to both the wrapped library and caller. This means that the generated source must be compiled once per compartment that links against the wrapped library. Each caller's wrapper must define the `CALLER_PKEY` macro with the appropriate value for the caller. +## Features -#### From CMake +- **Hardware checks** Coarse spatial memory safety enforced using CPU hardware features to reduce the runtime cost of bounds checking. On x86-64 this means Memory Protection Keys ([`wrpkru`](https://www.kernel.org/doc/html/next/core-api/protection-keys.html)) for memory permissions and Control-flow Enforcement Technology (`endbr` and [SHSTK](https://docs.kernel.org/next/x86/shstk.html)) to prevent call gate misuse. Support for Aarch64 using Memory Tagging Extensions is in-progress. +- **Minimal developer-facing annotations** Compartment transition annotations that can be inferred are automatically added by the rewriter and only appear in build artifacts. This reduces the developer-facing annotations while allowing developers to audit source-code changes made by the rewriter if necessary. +- **Toolchain-independent** Compartmentalized programs are built with off-the shelf compilers and linkers. -We provide a CMake rule to wrap a library or the main executable. This rule builds a wrapper and provides its dependency information to consumers of its outputs. Specifically, wrapper libs also depend on libia2 and have additional required compilation flags (-fno-omit-frame-pointer) for application code. - -[Usage from CMake](https://github.com/immunant/IA2-Phase2/blob/main/cmake/define-ia2-wrapper.cmake#L10-L32) looks like this (wrapping `myunsafelib` which is used by your existing `my_prog` target): -```diff -+define_ia2_wrapper( -+ WRAPPER my_wrapper_target -+ WRAPPED_LIB myunsafelib-1.0 -+ HEADERS myunsafelib.h myunsafelib_config.h -+ CALLER_PKEY 0 -+) -+ - add_executable(my_prog main.c) --target_link_libraries(my_prog PRIVATE myunsafelib-1.0) -+target_link_libraries(my_prog PRIVATE my_wrapper_target) -``` - -Wrapped libraries are treated as untrusted by default. If the library being wrapped defined a trusted compartment, `COMPARTMENT_PKEY n` must be specified in define_ia2_wrapper. Here `n` is the argument used in `IA2_COMPARTMENT` to define the compartment. If the caller is an untrusted compartment, set `CALLER_PKEY UNTRUSTED`. To create a wrapper for the main binary (i.e. if shared libraries call it directly) the `WRAP_MAIN` option must be specified. - -#### Manual usage +## Usage -See [this doc](https://github.com/immunant/IA2-Phase2/blob/main/docs/usage.md) for notes on manual usage. +See [this doc](docs/build_instructions.md) for instructions on building the tools and tests in this repo. For more detailed instructions on the compartmentalization process see the [usage doc](docs/usage.md).