From a787df5516a0291c092df06d204d73ba7b936f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Mon, 24 Nov 2025 18:12:35 +0100 Subject: [PATCH 1/2] Release updates * Update readme w.r.t. new type serialization scheme * Update API, fixes #174 --- CMakeLists.txt | 2 +- README.md | 170 +++++++++++++++++------------ lib/runtime/RuntimeInterface.h | 2 +- lib/runtime/TypeResolution.cpp | 12 +- test/runtime/38_resolve_struct.c | 2 +- test/runtime/53_get_type.c | 4 +- test/runtime/54_get_type_illegal.c | 4 +- 7 files changed, 111 insertions(+), 85 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 392a35cd..09fc3856 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.20) project(typeart - VERSION 2.1 + VERSION 2.2 HOMEPAGE_URL https://github.com/tudasc/TypeART DESCRIPTION "LLVM-based type and memory allocation tracking sanitizer" ) diff --git a/README.md b/README.md index b76861fc..4b74ef98 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## What is TypeART? -TypeART \[[TA18](#ref-typeart-2018); [TA20](#ref-typeart-2020); [TA22](#ref-typeart-2022)\] is a type and memory +TypeART \[[TA18](#ref-typeart-2018); [TA20](#ref-typeart-2020); [TA22](#ref-typeart-2022); [TA24](#ref-typeart-2024)\] is a type and memory allocation tracking sanitizer based on the [LLVM](https://llvm.org) compiler toolchain for C/C++ (OpenMP) codes. It includes an LLVM compiler pass plugin for instrumentation and a runtime library to monitor memory allocations during program execution. TypeART instruments heap, stack, and global variable allocations with callbacks to its runtime, capturing: @@ -69,8 +69,6 @@ Using TypeART involves two phases: TypeART’s LLVM compiler pass plugins instrument allocations and serialize static type layouts into a YAML file (default: `typeart-types.yaml`). We provide compiler wrapper scripts (available in the bin folder of the TypeART installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations, while MPI wrappers filter allocations unrelated to MPI calls (see [Section 1.1.4](#114-filtering-allocations)). -*Note*: Currently, the compilation must be serialized, e.g., `make -j 1`, to ensure consistent type information across translation units. - #### 1.1.1 Building with TypeART A typical compile invocation may first compile code to object files and then link with any libraries: @@ -82,8 +80,7 @@ $> clang++ -O2 $(COMPILE_FLAGS) -c code.cpp -o code.o $> clang++ $(LINK_FLAGS) code.o -o binary ``` -With TypeART, the recipe needs to be changed to, e.g., use our provided compiler wrapper, as we rely on the LLVM `opt` -(optimizer) tool to load and apply our TypeART passes to a target code: +With TypeART, the recipe needs to be changed to, e.g., use our provided compiler wrapper to load and apply our TypeART passes to a target code: ```shell # Compile, replace direct clang++ call with wrapper of the TypeART installation: @@ -112,7 +109,7 @@ checks, where we do not need TypeART instrumentation: # Temporarily disable wrapper with environment flag TYPEART_WRAPPER=OFF for configuration: $> TYPEART_WRAPPER=OFF cmake -B build -DCMAKE_C_COMPILER=*TypeART bin*/typeart-clang # Compile with typeart-clang: -$> cmake --build build --target install -- -j1 +$> cmake --build build --target install ``` ##### MPI wrapper generation @@ -122,11 +119,11 @@ Here, we rely on detecting the vendor to generate wrappers with appropriate envi the Clang/LLVM compiler. We support detection for OpenMPI, Intel MPI and MPICH based on `mpi.h` symbols, and use the following flags for setting the Clang compiler: -| Vendor | Symbol | C compiler env. var | C++ compiler env. var | -|-----------|---------------|----------------------|------------------------| -| Open MPI | OPEN_MPI | OMPI_CC | OMPI_CXX | -| Intel MPI | I_MPI_VERSION | I_MPI_CC | I_MPI_CXX | -| MPICH | MPICH_NAME | MPICH_CC | MPICH_CXX | +| Vendor | Symbol | C compiler env. var | C++ compiler env. var | +|-----------|---------------|---------------------|-----------------------| +| Open MPI | OPEN_MPI | OMPI_CC | OMPI_CXX | +| Intel MPI | I_MPI_VERSION | I_MPI_CC | I_MPI_CXX | +| MPICH | MPICH_NAME | MPICH_CC | MPICH_CXX | #### 1.1.2 Options for controlling the TypeART pass @@ -141,51 +138,75 @@ Prepending `no-` to boolean flags sets them to false. -| Env. variable | Option name | Default value | Description | -| :----------------------------------------- | ---------------------------------- | :------------------: | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| `TYPEART_OPTIONS` | | | Set multiple options at once, separated by `;`. | -| `TYPEART_OPTIONS_STACK` | | | Same as above for stack phase only. | -| `TYPEART_OPTIONS_HEAP` | | | Same as above for heap phase only. | -| `TYPEART_TYPES` | `types` | `typeart-types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPES`. | -| `TYPEART_HEAP` | `heap` | `true` | Instrument heap allocations | -| `TYPEART_STACK` | `stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | -| `TYPEART_STACK_LIFETIME` | `stack-lifetime` | `true` | Instrument stack `llvm.lifetime.start` instead of `alloca` directly | -| `TYPEART_GLOBAL` | `global` | `false` | Instrument global allocations (see stack). | -| `TYPEART_TYPEGEN` | `typegen` | `dimeta` | Values: `dimeta`, `ir`. How serializing of type information is done, see [Section 1.1.3](#113-serialized-type-information). | -| `TYPEART_STATS` | `stats` | `false` | Show instrumentation statistic counters | -| `TYPEART_FILTER` | `filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | -| `TYPEART_FILTER_IMPLEMENTATION` | `filter-implementation` | `std` | Values: `std`, `none`. See also [Section 1.1.4](#114-filtering-allocations) | -| `TYPEART_FILTER_GLOB` | `filter-glob` | `*MPI_*` | Filter API string target (glob string) | -| `TYPEART_FILTER_GLOB_DEEP` | `filter-glob-deep` | `MPI_*` | Filter values based on specific API: Values passed as ptr are correlated when string matched. | -| `TYPEART_ANALYSIS_FILTER_GLOBAL` | `analysis-filter-global` | `true` | Filter global alloca based on heuristics | -| `TYPEART_ANALYSIS_FILTER_HEAP_ALLOCA` | `analysis-filter-heap-alloca` | `true` | Filter stack alloca that have a store instruction from a heap allocation | -| `TYPEART_ANALYSTS_FILTER_NON_ARRAY_ALLOCA` | `analysis-filter-non-array-alloca` | `false` | Filter scalar valued allocas | -| `TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA` | `analysis-filter-pointer-alloca` | `true` | Filter allocas of pointer types | +| Env. variable | Option name | Default value | Description | +|:-------------------------------------------|------------------------------------|:--------------------:|---------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `TYPEART_OPTIONS` | | | Set multiple options at once, separated by `;`. | +| `TYPEART_OPTIONS_STACK` | | | Same as above for stack phase only. | +| `TYPEART_OPTIONS_HEAP` | | | Same as above for heap phase only. | +| `TYPEART_TYPES` | `types` | `typeart-types.yaml` | Serialized type layout information of user-defined types. File location and name can also be controlled with the env variable `TYPEART_TYPES`. | +| `TYPEART_HEAP` | `heap` | `true` | Instrument heap allocations | +| `TYPEART_STACK` | `stack` | `false` | Instrument stack and global allocations. Enables instrumentation of global allocations. | +| `TYPEART_STACK_LIFETIME` | `stack-lifetime` | `true` | Instrument stack `llvm.lifetime.start` instead of `alloca` directly | +| `TYPEART_GLOBAL` | `global` | `false` | Instrument global allocations (see stack). | +| `TYPEART_TYPEGEN` | `typegen` | `dimeta` | Values: `dimeta`, `ir`. How serializing of type information is done, see [Section 1.1.3](#113-serialized-type-information). | +| `TYPEART_TYPE_SERIALIZATION` | `type-serialization` | `hybrid` | Values: `file`, `hybrid`, `inline`. How type information are stored (in the executable or externally), see [Section 1.1.3](#113-serialized-type-information). | +| `TYPEART_STATS` | `stats` | `false` | Show instrumentation statistic counters | +| `TYPEART_FILTER` | `filter` | `false` | Filter stack and global allocations. See also [Section 1.1.4](#114-filtering-allocations) | +| `TYPEART_FILTER_IMPLEMENTATION` | `filter-implementation` | `std` | Values: `std`, `none`. See also [Section 1.1.4](#114-filtering-allocations) | +| `TYPEART_FILTER_GLOB` | `filter-glob` | `*MPI_*` | Filter API string target (glob string) | +| `TYPEART_FILTER_GLOB_DEEP` | `filter-glob-deep` | `MPI_*` | Filter values based on specific API: Values passed as ptr are correlated when string matched. | +| `TYPEART_ANALYSIS_FILTER_GLOBAL` | `analysis-filter-global` | `true` | Filter global alloca based on heuristics | +| `TYPEART_ANALYSIS_FILTER_HEAP_ALLOCA` | `analysis-filter-heap-alloca` | `true` | Filter stack alloca that have a store instruction from a heap allocation | +| `TYPEART_ANALYSTS_FILTER_NON_ARRAY_ALLOCA` | `analysis-filter-non-array-alloca` | `false` | Filter scalar valued allocas | +| `TYPEART_ANALYSIS_FILTER_POINTER_ALLOCA` | `analysis-filter-pointer-alloca` | `true` | Filter allocas of pointer types | Additionally, there are two debug environment flags for dumping the LLVM IR per phase (pre heap, heap, opt, stack) to a set of files. | Env. variable | Description | -| :------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- | +|:--------------------------------|---------------------------------------------------------------------------------------------------------------------------------| | `TYPEART_WRAPPER_EMIT_IR` | If set, the compiler wrapper will create 4 files for each TypeART phase with the file pattern `${source_basename}_heap.ll` etc. | | `TYPEART_PASS_INTERNAL_EMIT_IR` | Internal pass use only. Toggled by wrapper. | + #### 1.1.3 Serialized type information -After instrumentation, the file `typeart-types.yaml` (`env TYPEART_TYPES`) contains the static type information. Each user-defined type layout is -extracted and an integer `type-id` is attached to it. Built-in types (e.g., float) have pre-defined ids and byte -layouts. To generate these type layouts, TypeART is using either the [LLVM IR type system](https://llvm.org/docs/LangRef.html#type-system) (`typegen=ir`), or using the external library [llvm-dimeta](https://github.com/ahueck/llvm-dimeta) (`typegen=dimeta`) which extracts type information using [LLVM debug metadata](https://llvm.org/docs/SourceLevelDebugging.html). The latter is default, the former only works with LLVM 14. -The TypeART instrumentation callbacks use the `type-id`. The runtime library correlates the allocation with the -respective type (and layout) during execution. Consider the following struct: +The type's layout is then serialized by either storing it as a global variable inside each translation unit (`type-serialization=hybrid` or `inline`), or via an external yaml file (`type-serialization=file`). + +*Note*: With `file` mode (only), the compilation must be serialized, e.g., `make -j 1`, to ensure consistent type information across translation units. -After instrumentation, the `typeart-types.yaml` file (also controlled via the `TYPEART_TYPES` environment variable) stores static type information. -Each user-defined type layout is assigned a unique integer type-id. Built-in types (e.g., float) use predefined type-ids and byte layouts. -During execution, TypeART’s runtime library uses the type-id from callbacks to associate allocations with their type and layout. For example, consider the following C struct: +##### 1.1.3.1 Hybrid and Inline serialization + +Type serialization for each user-defined type (mode `hybrid`) or *all* types (mode `inline`) are stored as (constant) globals with the following format: + +```c +struct GlobalTypeInfo { + std::int32_t type_id; + const std::uint32_t extent; + const std::uint16_t num_members; + const std::uint16_t flag; + const char* name; + const std::uint16_t* offsets; + const std::uint16_t* array_sizes; + const GlobalTypeInfo** member_types; +}; +``` + +Each type is registered at startup with the TypeART runtime using the callback `void __typeart_register_type(const void* type_ptr);`. +The callback adds the type information to our type database (for user queries) and assigns a unique `type-id`. +Each user-defined type layout is assigned a unique integer `type-id` starting at 256. Built-in types (e.g., float) use predefined type-ids (< 256) and byte layouts. +The runtime library correlates the allocation with the respective type (and layout) during execution via the `type-id`. + + +##### 1.1.3.2 File-based serialization +After instrumentation, the file `typeart-types.yaml` (`env TYPEART_TYPES`) contains the static type information. Each user-defined type layout is +extracted and an integer `type-id` is attached to it. +For example, consider the following C struct: ```c struct s1_t { @@ -209,7 +230,8 @@ The TypeART pass may write a `typeart-types.yaml` file with the following conten -##### Limitations of LLVM IR Type System + +##### 1.1.3.3 Side note: Limitations of LLVM IR Type System The list of supported built-in type-ids is defined in [TypeInterface.h](lib/typelib/TypeInterface.h) and reflects the types that TypeART can represent with **LLVM Debug Metadata**. In contrast, when using **LLVM IR Type System**, certain constraints are imposed. For instance, C/C++ types like unsigned integers are unsupported (and represented like signed integers). @@ -245,6 +267,7 @@ callbacks. The library also requires access to the `typeart-types.yaml` file to layouts. To specify its path, you can use the environment variable `TYPEART_TYPES`, e.g.: ```shell +# Only if previously compiled with `serialization-mode=file`, otherwise skip: $> export TYPEART_TYPES=/path/to/typeart-types.yaml # If the TypeART runtime is not resolved, LD_LIBRARY_PATH is set: $> env LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(TYPEART_LIBPATH) ./binary @@ -279,7 +302,7 @@ To compile and run the demo targets: ## 2. Building TypeART -TypeART supports LLVM version 14, 18 and 19, and CMake version >= 3.20. +TypeART supports LLVM version 14, 18-21, and CMake version >= 3.20. ### 2.1 Optional software requirements @@ -312,7 +335,7 @@ $> cmake --build build --target install --parallel | Option | Default | Description | -| ---------------------------- | :-----: | -------------------------------------------------------------------------------- | +|------------------------------|:-------:|----------------------------------------------------------------------------------| | `TYPEART_MPI_WRAPPER` | `ON` | Install TypeART MPI wrapper (mpic, mpic++). Requires MPI. | | `TYPEART_USE_LEGACY_WRAPPER` | `OFF` | Use legacy wrapper invoking opt/llc directly instead of Clang's `-fpass-plugin`. | @@ -338,10 +361,10 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| Option | Default | Description | -|----------------------------------|:--------:|----------------------------------------------------------------------------------------------------------------------------------------------------| -| `TYPEART_DISABLE_THREAD_SAFETY` | `OFF` | Disable thread safety of runtime | -| `TYPEART_SAFEPTR` | `OFF` | Instead of a mutex, use a special data structure wrapper for concurrency, see [object_threadsafe](https://github.com/AlexeyAB/object_threadsafe) | +| Option | Default | Description | +|---------------------------------|:-------:|--------------------------------------------------------------------------------------------------------------------------------------------------| +| `TYPEART_DISABLE_THREAD_SAFETY` | `OFF` | Disable thread safety of runtime | +| `TYPEART_SAFEPTR` | `OFF` | Instead of a mutex, use a special data structure wrapper for concurrency, see [object_threadsafe](https://github.com/AlexeyAB/object_threadsafe) | @@ -349,12 +372,12 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| Option | Default | Description | -|------------------------------|:-------:|---------------------------------------------------------------------------------------------------| -| `TYPEART_SHOW_STATS` | `ON` | Passes show compile-time summary w.r.t. allocations counts | -| `TYPEART_MPI_INTERCEPT_LIB` | `ON` | Library to intercept MPI calls by preloading and check whether TypeART tracks the buffer pointer | -| `TYPEART_MPI_LOGGER` | `ON` | Enable better logging support in MPI execution context | -| `TYPEART_LOG_LEVEL` | `0` | Granularity of pass logger. 3 is most verbose, 0 is least | +| Option | Default | Description | +|-----------------------------|:-------:|--------------------------------------------------------------------------------------------------| +| `TYPEART_SHOW_STATS` | `ON` | Passes show compile-time summary w.r.t. allocations counts | +| `TYPEART_MPI_INTERCEPT_LIB` | `ON` | Library to intercept MPI calls by preloading and check whether TypeART tracks the buffer pointer | +| `TYPEART_MPI_LOGGER` | `ON` | Enable better logging support in MPI execution context | +| `TYPEART_LOG_LEVEL` | `0` | Granularity of pass logger. 3 is most verbose, 0 is least | @@ -362,12 +385,12 @@ Default mode is to protect the global data structure with a (shared) mutex. Two -| Option | Default | Description | -|-------------------------------|:-------:|--------------------------------------------------------------------------------------------------------------| -| `TYPEART_TEST_CONFIG` | `OFF` | Enable testing, and set (force) logging levels to appropriate levels for test runner to succeed | -| `TYPEART_CODE_COVERAGE` | `OFF` | Enable code coverage statistics using LCOV 1.14 and genhtml (gcovr optional) | -| `TYPEART_LLVM_CODE_COVERAGE` | `OFF` | Enable llvm-cov code coverage statistics (llvm-cov and llvm-profdata required) | -| `TYPEART_ASAN, TSAN, UBSAN` | `OFF` | Enable Clang sanitizers (tsan is mutually exclusive w.r.t. ubsan and asan as they don't play well together) | +| Option | Default | Description | +|------------------------------|:-------:|--------------------------------------------------------------------------------------------------------------| +| `TYPEART_TEST_CONFIG` | `OFF` | Enable testing, and set (force) logging levels to appropriate levels for test runner to succeed | +| `TYPEART_CODE_COVERAGE` | `OFF` | Enable code coverage statistics using LCOV 1.14 and genhtml (gcovr optional) | +| `TYPEART_LLVM_CODE_COVERAGE` | `OFF` | Enable llvm-cov code coverage statistics (llvm-cov and llvm-profdata required) | +| `TYPEART_ASAN, TSAN, UBSAN` | `OFF` | Enable Clang sanitizers (tsan is mutually exclusive w.r.t. ubsan and asan as they don't play well together) | @@ -378,7 +401,7 @@ Example using CMake [FetchContent](https://cmake.org/cmake/help/latest/module/Fe FetchContent_Declare( typeart GIT_REPOSITORY https://github.com/tudasc/TypeART - GIT_TAG v2.1 + GIT_TAG v2.2 GIT_SHALLOW 1 ) FetchContent_MakeAvailable(typeart) @@ -392,32 +415,35 @@ target_link_libraries(my_project_target PRIVATE typeart::Runtime) [TA18] Hück, Alexander and Lehr, Jan-Patrick and Kreutzer, Sebastian and Protze, Joachim and Terboven, Christian and Bischof, Christian and Müller, Matthias S. - - Compiler-aided type tracking for correctness checking of MPI applications. + "Compiler-aided type tracking for correctness checking of MPI applications." In 2nd International Workshop on Software Correctness for HPC Applications (Correctness), - pages 51–58. IEEE, 2018. + pages 51–58. IEEE, 2018. DOI: 10.1109/Correctness.2018.00011 [TA20] Hück, Alexander and Protze, Joachim and Lehr, Jan-Patrick and Terboven, Christian and Bischof, Christian and Müller, Matthias S. - - Towards compiler-aided correctness checking of adjoint MPI applications. + "Towards compiler-aided correctness checking of adjoint MPI applications." In 4th International Workshop on Software Correctness for HPC Applications (Correctness), - pages 40–48. IEEE/ACM, 2020. + pages 40–48. IEEE/ACM, 2020. DOI: 10.1109/Correctness51934.2020.00010 [TA22] Hück, Alexander and Kreutzer, Sebastian and Protze, Joachim and Lehr, Jan-Patrick and Bischof, Christian and Terboven, Christian and Müller, Matthias S. - - Compiler-Aided Type Correctness of Hybrid MPI-OpenMP Applications. - In IT Professional, vol. 24, no. 2, pages 45–51. IEEE, 2022. + "Compiler-Aided Type Correctness of Hybrid MPI-OpenMP Applications." + In IT Professional, vol. 24, no. 2, pages 45–51. IEEE, 2022. DOI: 10.1109/MITP.2021.3093949 + + + [TA24] + Hück, Alexander and Ziegler, Tim and Schwitanski, Simon and Jenke, Joachim and Bischof, Christian. + "Compiler-Aided Correctness Checking of CUDA-Aware MPI Applications." + In SC24-W: Workshops of the International Conference for High Performance Computing, Networking, Storage and Analysis, + pages 204–213, IEEE/ACM, 2024. DOI: 10.1109/SCW63240.2024.00032 [MU13] Hilbrich, Tobias and Protze, Joachim and Schulz, Martin and de Supinski, Bronis R. and Müller, Matthias S. - - MPI Runtime Error Detection with MUST: Advances in Deadlock Detection. + "MPI Runtime Error Detection with MUST: Advances in Deadlock Detection." In Scientific Programming, vol. 21, no. 3-4, - pages 109–121, 2013. + pages 109–121, 2013. DOI: 10.3233/SPR-130368 diff --git a/lib/runtime/RuntimeInterface.h b/lib/runtime/RuntimeInterface.h index 97e12d20..df01e259 100644 --- a/lib/runtime/RuntimeInterface.h +++ b/lib/runtime/RuntimeInterface.h @@ -138,7 +138,7 @@ typeart_status typeart_get_type(const void* addr, typeart_type_info* type_info); // typeart_status typeart_get_containing_type(const void* addr, int* type_id, size_t* count, const void** base_address, // size_t* byte_offset); -typeart_status typeart_get_containing_type(typeart_type_info type_info, typeart_base_type_info* containing_type, +typeart_status typeart_get_containing_type(const typeart_type_info* type_info, typeart_base_type_info* containing_type, size_t* byte_offset); /** diff --git a/lib/runtime/TypeResolution.cpp b/lib/runtime/TypeResolution.cpp index 8552d326..056b1a6b 100644 --- a/lib/runtime/TypeResolution.cpp +++ b/lib/runtime/TypeResolution.cpp @@ -359,15 +359,15 @@ typeart_status typeart_get_type(const void* addr, typeart_type_info* base_type) return typeart::detail::query_type(addr, *base_type); } -typeart_status typeart_get_containing_type(typeart_type_info type, typeart_base_type_info* containing_type, +typeart_status typeart_get_containing_type(const typeart_type_info* type, typeart_base_type_info* containing_type, size_t* byte_offset) { typeart::RTGuard guard; - containing_type->type_id = type.base_type_info.type_id; - containing_type->count = type.base_type_info.count; - containing_type->address = type.base_type_info.address; - const typeart::PointerInfo info{type.base_type_info.type_id, type.base_type_info.count}; + containing_type->type_id = type->base_type_info.type_id; + containing_type->count = type->base_type_info.count; + containing_type->address = type->base_type_info.address; + const typeart::PointerInfo info{type->base_type_info.type_id, type->base_type_info.count}; const auto result = typeart::RuntimeSystem::get().type_resolution().getContainingTypeInfo( - type.address, containing_type->address, info, &containing_type->count, byte_offset); + type->address, containing_type->address, info, &containing_type->count, byte_offset); return result; } diff --git a/test/runtime/38_resolve_struct.c b/test/runtime/38_resolve_struct.c index 1c3a5cf9..e8130f22 100644 --- a/test/runtime/38_resolve_struct.c +++ b/test/runtime/38_resolve_struct.c @@ -42,7 +42,7 @@ void type_check_containing(const void* addr) { return; } typeart_base_type_info containing; - status = typeart_get_containing_type(info, &containing, &offset); + status = typeart_get_containing_type(&info, &containing, &offset); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); diff --git a/test/runtime/53_get_type.c b/test/runtime/53_get_type.c index 269d8b0a..67502eee 100644 --- a/test/runtime/53_get_type.c +++ b/test/runtime/53_get_type.c @@ -50,7 +50,7 @@ void type_check_containing(const void* addr) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset); + status = typeart_get_containing_type(&info, &info_base, &offset); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: Status not OK: %i for %p\n", status, addr); @@ -77,7 +77,7 @@ void type_check_sub(const void* addr, size_t offset) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset_containing); + status = typeart_get_containing_type(&info, &info_base, &offset_containing); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: with containing type\n"); return; diff --git a/test/runtime/54_get_type_illegal.c b/test/runtime/54_get_type_illegal.c index aed16b72..42a60276 100644 --- a/test/runtime/54_get_type_illegal.c +++ b/test/runtime/54_get_type_illegal.c @@ -61,7 +61,7 @@ void type_check_containing(const void* addr) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset); + status = typeart_get_containing_type(&info, &info_base, &offset); if (status != TYPEART_OK) { fprintf(stderr, "[Expected]: Status not OK: %s for %p\n", err_code_to_string(status), addr); @@ -88,7 +88,7 @@ void type_check_sub(const void* addr, size_t offset) { return; } typeart_base_type_info info_base; - status = typeart_get_containing_type(info, &info_base, &offset_containing); + status = typeart_get_containing_type(&info, &info_base, &offset_containing); if (status != TYPEART_OK) { fprintf(stderr, "[Error]: with containing type\n"); return; From c20922161d380dbd2c3833eb3f8144c25088c743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alexander=20H=C3=BCck?= Date: Tue, 25 Nov 2025 12:40:49 +0100 Subject: [PATCH 2/2] Readme --- README.md | 44 +++++++++++++++++++------------------------- 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 4b74ef98..b15ae9d0 100644 --- a/README.md +++ b/README.md @@ -3,16 +3,11 @@ ## What is TypeART? TypeART \[[TA18](#ref-typeart-2018); [TA20](#ref-typeart-2020); [TA22](#ref-typeart-2022); [TA24](#ref-typeart-2024)\] is a type and memory -allocation tracking sanitizer based on the [LLVM](https://llvm.org) compiler toolchain for C/C++ (OpenMP) codes. It includes an LLVM compiler pass plugin for instrumentation and a runtime library to monitor memory allocations during program execution. +allocation tracking sanitizer based on the [LLVM](https://llvm.org) compiler toolchain for C/C++ (OpenMP) codes. It pairs a compiler plugin (for instrumentation) with a runtime library to track memory type, size, and location of heap, stack and global allocations. -TypeART instruments heap, stack, and global variable allocations with callbacks to its runtime, capturing: -(1) the memory address, (2) the type-layout information of the allocation (e.g., built-ins, user-defined structs) and (3) number of elements. ## Why use it? -TypeART provides type-related information of allocations in your program to help verify some property, and to help -generate diagnostics if it doesn't hold. - Low-level C APIs often rely on `void*` pointers for generic types, requiring users to manually specify type and size - a process prone to errors. Examples for type unsafe APIs include the Message-Passing Interface (MPI), checkpointing libraries and numeric solver libraries. TypeART simplifies verification, ensuring, for example, that a `void*` argument corresponds to an array of expected type `T` with length `n`. @@ -62,25 +57,26 @@ its [project page](https://itc.rwth-aachen.de/must/). Using TypeART involves two phases: -1. Compilation: Compile your code with Clang/LLVM using the TypeART LLVM pass plugin. The plugin (1) serializes static type information to a file and (2) instruments relevant allocations. See [Section 1.1](#11-compiling-a-target-code). -2. Execution: Run the instrumented program with a TypeART runtime client, which uses the callback data to perform analysis facilitating the static type information. See [Section 1.2](#12-executing-an-instrumented-target-code). +1. Compilation, see [Section 1.1](#11-compiling-a-target-code): Compile your code with Clang/LLVM using the TypeART LLVM pass plugin. The plugin (1) serializes static type information and (2) instruments relevant allocations. +2. Execution, see [Section 1.2](#12-executing-an-instrumented-target-code): Run the instrumented program with a TypeART runtime client, which uses the callback data to perform analysis facilitating the static type information. + ### 1.1 Compiling a target code -TypeART’s LLVM compiler pass plugins instrument allocations and serialize static type layouts into a YAML file (default: `typeart-types.yaml`). We provide compiler wrapper scripts (available in the bin folder of the TypeART installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations, while MPI wrappers filter allocations unrelated to MPI calls (see [Section 1.1.4](#114-filtering-allocations)). +TypeART’s LLVM compiler pass plugins instrument allocations and serialize static type layouts. We provide compiler wrapper scripts (available in the bin folder of the TypeART installation) for Clang and MPI. By default, these wrappers instrument heap, stack, and global allocations, while MPI wrappers filter allocations unrelated to MPI calls (see [Section 1.1.4](#114-filtering-allocations)). #### 1.1.1 Building with TypeART -A typical compile invocation may first compile code to object files and then link with any libraries: +Simply replace your compiler variable: -```shell -# Compile: -$> clang++ -O2 $(COMPILE_FLAGS) -c code.cpp -o code.o -# Link: -$> clang++ $(LINK_FLAGS) code.o -o binary -``` +| Variable | TypeART Wrapper | +|----------|-------------------| +| `CXX` | `typeart-clang++` | +| `CC` | `typeart-clang` | +| `MPICC` | `typeart-mpicc` | +| `MPICXX` | `typeart-mpic++` | -With TypeART, the recipe needs to be changed to, e.g., use our provided compiler wrapper to load and apply our TypeART passes to a target code: +The wrappers handle the LLVM pass injection and linking: ```shell # Compile, replace direct clang++ call with wrapper of the TypeART installation: @@ -99,11 +95,9 @@ The wrapper performs the following steps using Clang's `-fpass-plugin`: *Note*: Heap allocations are instrumented before optimizations to prevent loss of type information in some cases. -##### Wrapper usage in CMake build systems +##### CMake projects -For plain Makefiles, the wrapper replaces the GCC/Clang compiler variables, e.g., `CC` or `MPICC`. For CMake, during the -configuration, it is advised to disable the wrapper temporarily. This is due to CMake executing internal compiler -checks, where we do not need TypeART instrumentation: +When using CMake, the wrapper must be disabled during configuration (to pass internal compiler checks) but enabled for the build. ```shell # Temporarily disable wrapper with environment flag TYPEART_WRAPPER=OFF for configuration: @@ -198,14 +192,14 @@ struct GlobalTypeInfo { ``` Each type is registered at startup with the TypeART runtime using the callback `void __typeart_register_type(const void* type_ptr);`. -The callback adds the type information to our type database (for user queries) and assigns a unique `type-id`. +The callback adds the type information to the type database (for user queries) and assigns a unique `type-id`. Each user-defined type layout is assigned a unique integer `type-id` starting at 256. Built-in types (e.g., float) use predefined type-ids (< 256) and byte layouts. The runtime library correlates the allocation with the respective type (and layout) during execution via the `type-id`. ##### 1.1.3.2 File-based serialization After instrumentation, the file `typeart-types.yaml` (`env TYPEART_TYPES`) contains the static type information. Each user-defined type layout is -extracted and an integer `type-id` is attached to it. +extracted and an integer `type-id` is attached to it (similarly to hybrid and inline serialization). For example, consider the following C struct: ```c @@ -313,7 +307,7 @@ TypeART supports LLVM version 14, 18-21, and CMake version >= 3.20. Other smaller, external dependencies are defined within the [externals folder](externals) (depending on configuration options), see [Section 2.2.1 (Runtime)](#221-cmake-configuration-options-for-users). They are automatically downloaded -during configuration time (internet connection required). +during configuration time. ### 2.2 Building @@ -434,7 +428,7 @@ target_link_libraries(my_project_target PRIVATE typeart::Runtime) [TA24] - Hück, Alexander and Ziegler, Tim and Schwitanski, Simon and Jenke, Joachim and Bischof, Christian. + Hück, Alexander and Ziegler, Tim and Schwitanski, Simon and Jenke, Joachim and Bischof, Christian. "Compiler-Aided Correctness Checking of CUDA-Aware MPI Applications." In SC24-W: Workshops of the International Conference for High Performance Computing, Networking, Storage and Analysis, pages 204–213, IEEE/ACM, 2024. DOI: 10.1109/SCW63240.2024.00032