Skip to content

Commit

Permalink
Merge PR #39 from tudasc/devel
Browse files Browse the repository at this point in the history
For new TypeART 1.5 release tag, see #39 for gist of changes
  • Loading branch information
ahueck authored Dec 29, 2020
2 parents 2ac6605 + 146fbaf commit aeb9ca5
Show file tree
Hide file tree
Showing 162 changed files with 7,378 additions and 3,497 deletions.
62 changes: 36 additions & 26 deletions .github/workflows/basic-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,64 +7,74 @@ on:

jobs:
build-and-run-test:
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
if: "!contains(github.event.head_commit.message, '[ci skip]')"
steps:
- uses: actions/checkout@v2

- name: Setup LLVM repository
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' -y
sudo apt-get update -q
- name: Install LLVM
run: sudo apt-get install libllvm10 llvm-10 llvm-10-dev

- name: Install Clang
run: sudo apt-get install clang-10
run: sudo apt-get install clang-10 clang-tidy-10

- name: Install OpenMPI
run: sudo apt-get install libopenmpi-dev openmpi-bin

- name: Install lcov
run: sudo apt-get install lcov

- name: Setup env
run: |
sudo ln -f -s /usr/bin/clang-10 /usr/bin/clang
sudo ln -f -s /usr/bin/clang++-10 /usr/bin/clang++
sudo ln -f -s /usr/bin/opt-10 /usr/bin/opt
sudo ln -f -s /usr/bin/FileCheck-10 /usr/bin/FileCheck
sudo ln -f -s /usr/bin/llc-10 /usr/bin/llc
echo "::set-env name=CC::clang-10"
echo "::set-env name=CXX::clang++-10"
echo "::set-env name=EXTERNAL_LIT::/usr/lib/llvm-10/build/utils/lit/lit.py"
sudo ln -f -s /usr/bin/clang-tidy-10 /usr/bin/clang-tidy
echo "CC=clang-10" >> $GITHUB_ENV
echo "CXX=clang++-10" >> $GITHUB_ENV
echo "EXTERNAL_LIT=/usr/lib/llvm-10/build/utils/lit/lit.py" >> $GITHUB_ENV
- name: Build TypeART
run: |
cmake -B build -DTEST_CONFIG=ON -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT}
cmake -B build -DTEST_CONFIG=ON -DENABLE_CODE_COVERAGE=ON -DLLVM_EXTERNAL_LIT=${EXTERNAL_LIT}
cmake --build build --parallel
- name: Test TypeART
run: cmake --build build --target test -- ARGS=-VV
- name: Test TypeART with coverage (exludes lulesh)
run: |
cmake --build build --target lcov-clean
cmake --build build --target test -- ARGS=-VV
- name: Build coverage report
run: cmake --build build --target lcov-html

- name: Build TypeART Release
- name: Build TypeART release
run: |
cmake -B build_lulesh -DCMAKE_BUILD_TYPE=Release -DMPI_INTERCEPT_LIB=ON -DSHOW_STATS=ON
cmake --build build_lulesh --parallel
- name: Test TypeART on lulesh
- name: Test TypeART release on lulesh
working-directory: build_lulesh
run: ctest -V -R lulesh -O lulesh2.0_build.log
- name: Prepare lulesh artifact

- name: Prepare artifact
run: |
mkdir artifact_lulesh
mv build_lulesh/lulesh2.0_build.log artifact_lulesh/
mv test/lulesh/lulesh2.0_out.log artifact_lulesh/
mv test/lulesh/types.yaml artifact_lulesh/lulesh2.0_types.yaml
mkdir -p artifact/lulesh
mkdir -p artifact/coverage
mv build_lulesh/lulesh2.0_build.log artifact/lulesh/
mv test/lulesh/lulesh2.0_out.log artifact/lulesh/
mv test/lulesh/types.yaml artifact/lulesh/lulesh2.0_types.yaml
mv build/profiles/ artifact/coverage
- name: Upload lulesh test artifact
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: typeart-ci
path: artifact

- name: Coveralls
uses: coverallsapp/github-action@master
with:
name: typeart-lulesh-archive
path: artifact_lulesh

github-token: ${{ secrets.GITHUB_TOKEN }}
path-to-lcov: build/typeart.coverage
52 changes: 33 additions & 19 deletions .github/workflows/ext-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,12 @@ name: TypeART-CI-ext

on:
push:
branches:
- master
branches: [ master, devel ]
pull_request:

jobs:
build-and-run-testbench:
runs-on: ubuntu-18.04
runs-on: ubuntu-20.04
if: "!contains(github.event.head_commit.message, '[ci skip]') || !contains(github.event.head_commit.message, '[ci ext skip]')"
steps:
- uses: actions/checkout@v2
Expand All @@ -20,17 +19,19 @@ jobs:
ssh-key: ${{ secrets.AUTH_SSH_CI_EXT }}
path: test-bench

- name: Setup LLVM repository
run: |
wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key 2>/dev/null | sudo apt-key add -
sudo add-apt-repository 'deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-10 main' -y
sudo apt-get update -q
- name: Checkout AD test-bench
uses: actions/checkout@v2
with:
repository: ahueck/typeart-ad-benchmarks
ssh-key: ${{ secrets.AUTH_SSH_CI_EXT_AD }}
ref: feat/ci
path: ad-test-bench

- name: Install LLVM
run: sudo apt-get install libllvm10 llvm-10 llvm-10-dev

- name: Install Clang
run: sudo apt-get install clang-10
run: sudo apt-get install clang-10 clang-tidy-10

- name: Install OpenMPI
run: sudo apt-get install libopenmpi-dev openmpi-bin
Expand All @@ -41,14 +42,16 @@ jobs:
sudo ln -f -s /usr/bin/clang++-10 /usr/bin/clang++
sudo ln -f -s /usr/bin/opt-10 /usr/bin/opt
sudo ln -f -s /usr/bin/llc-10 /usr/bin/llc
echo "::set-env name=CC::clang-10"
echo "::set-env name=CXX::clang++-10"
sudo ln -f -s /usr/bin/clang-tidy-10 /usr/bin/clang-tidy
echo "CC=clang-10" >> $GITHUB_ENV
echo "CXX=clang++-10" >> $GITHUB_ENV
echo "EXTERNAL_LIT=/usr/lib/llvm-10/build/utils/lit/lit.py" >> $GITHUB_ENV
- name: Build & install TypeART
run: |
cmake -B build -DCMAKE_BUILD_TYPE=Release -DMPI_INTERCEPT_LIB=ON -DSHOW_STATS=ON
cmake --build build --parallel --target install
echo "::set-env name=TYPEART_PATH::${GITHUB_WORKSPACE}/install/typeart"
echo "TYPEART_PATH=${GITHUB_WORKSPACE}/install/typeart" >> $GITHUB_ENV
- name: Setup tests
working-directory: test-bench
Expand All @@ -70,16 +73,27 @@ jobs:
working-directory: test-bench/build
run: ctest -V -R amg2013 -O amg2013_build.log

- name: Prepare test-bench artifact
working-directory: test-bench
- name: Setup AD tests
working-directory: ad-test-bench
run: cmake -B build -DLOG_PATH=${GITHUB_WORKSPACE}/ad-test-bench/artifact

- name: Run AD lulesh
working-directory: ad-test-bench/build
run: ctest -V -R lulesh -O ad-lulesh2.0_build.log

- name: Prepare artifact
run: |
mkdir -p artifact
mv build/*_build.log artifact
mkdir -p artifact/bench
mkdir -p artifact/ad-bench
mv test-bench/build/*_build.log artifact/bench
mv test-bench/artifact/* artifact/bench
mv ad-test-bench/build/*_build.log artifact/ad-bench
mv ad-test-bench/artifact/* artifact/ad-bench
- name: Upload test-bench artifact
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v2
with:
name: typeart-bench-archive
path: test-bench/artifact
name: typeart-ci-ext
path: artifact


25 changes: 14 additions & 11 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
cmake_minimum_required(VERSION 3.12)
cmake_minimum_required(VERSION 3.14)

project(typeart
VERSION 2.0
VERSION 1.5.0
)

set(TYPEART_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_VERBOSE_MAKEFILE ON)

Expand All @@ -20,18 +22,19 @@ include(CMakePackageConfigHelpers)

add_format_target(format-sources
"Formats project source files"
TARGETS lib/*.cpp
lib/*.h
runtime/*.cpp
runtime/*.h
typelib/*.cpp
typelib/*.h
)
TARGETS
lib/passes/*.cpp
lib/passes/*.h
lib/runtime/*.cpp
lib/runtime/*.h
lib/typelib/*.cpp
lib/typelib/*.h
lib/support/*.cpp
lib/support/*.h
)

add_subdirectory(externals)
add_subdirectory(lib)
add_subdirectory(typelib)
add_subdirectory(runtime)
add_subdirectory(scripts)
enable_testing()
add_subdirectory(test)
95 changes: 66 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
# TypeART   [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)   ![](https://github.com/tudasc/TypeART/workflows/TypeART-CI/badge.svg?branch=master)   ![](https://github.com/tudasc/TypeART/workflows/TypeART-CI-ext/badge.svg?branch=master)
# TypeART · [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) ![](https://github.com/tudasc/TypeART/workflows/TypeART-CI/badge.svg?branch=master) ![](https://github.com/tudasc/TypeART/workflows/TypeART-CI-ext/badge.svg?branch=master) [![Coverage Status](https://coveralls.io/repos/github/tudasc/TypeART/badge.svg?branch=master)](https://coveralls.io/github/tudasc/TypeART)

TypeART \[[TA18](#ref-typeart-2018)\] is a type and memory allocation tracking sanitizer.
It consists of an LLVM compiler pass and a corresponding runtime to track relevant memory allocation information during the execution of a target program.
It instruments heap, stack and global variable allocations with a callback to our runtime.
The callback consists of the runtime memory pointer value, what type (built-ins, user-defined structs etc.) and extent of the value.
This allows users of our runtime to query detailed type information behind arbritary memory locations, as long as they are mapped.
TypeART \[[TA18](#ref-typeart-2018); [TA20](#ref-typeart-2020)\] is a type and memory allocation tracking sanitizer. It
consists of an LLVM compiler pass and a corresponding runtime to track relevant memory allocation information during the
execution of a target program. It instruments heap, stack and global variable allocations with a callback to our
runtime. The callback consists of the runtime memory pointer value, what type (built-ins, user-defined structs etc.) and
extent of the value. This allows users of our runtime to query detailed type information behind arbitrary memory
locations, as long as they are mapped.

### Use Case: MUST - A dynamic MPI correctness checker

TypeART is used in conjunction with MUST \[[MU13](#ref-must-2013)\] to track memory (de-)allocation relevant to MPI communication.
Thus, MUST can check for type compatibility between the type-less communication buffer and the declared MPI datatype at all phases of the MPI communication, namely message assembly, message transfer and message disassembly into the receiving buffer.
A brief summary is given in a subsequent section and more information can be found in our publication:
TypeART is used in conjunction with MUST \[[MU13](#ref-must-2013)\] to track memory (de-)allocation relevant to MPI
communication. Thus, MUST can check for type compatibility between the type-less communication buffer and the declared
MPI datatype at all phases of the MPI communication, namely message assembly, message transfer and message disassembly
into the receiving buffer. A brief summary is given in a subsequent section and more information can be found in our
publication:

#### References

Expand All @@ -23,6 +26,14 @@ A brief summary is given in a subsequent section and more information can be fou
In <i>2nd International Workshop on Software Correctness for HPC Applications (Correctness)</i>,
pages 51–58. IEEE, 2018.</td>
</tr>
<tr>
<td valign="top"><a name="ref-typeart-2020"></a>[TA20]</td>
<td>Hück, Alexander and Protze, Joachim and Lehr, Jan-Patrick and Terboven, Christian and Bischof, Christian and Müller, Matthias S.
<a href=https://doi.org/10.1109/Correctness51934.2020.00010>
Towards compiler-aided correctness checking of adjoint MPI applications</a>.
In <i>4th International Workshop on Software Correctness for HPC Applications (Correctness)</i>,
pages 40–48. IEEE/ACM, 2020.</td>
</tr>
<tr>
<td valign="top"><a name="ref-must-2013"></a>[MU13]</td>
<td>Hilbrich, Tobias and Protze, Joachim and Schulz, Martin and de Supinski, Bronis R. and Müller, Matthias S.
Expand All @@ -35,12 +46,14 @@ A brief summary is given in a subsequent section and more information can be fou

## Software dependencies

TypeART requires [LLVM](https://llvm.org) version 10 and CMake version >= 3.12.
TypeART requires [LLVM](https://llvm.org) version 10 and CMake version >= 3.14.

#### Building TypeART

TypeART uses CMake to build, cf. [GitHub CI build file](.github/workflows/basic-ci.yml) for a complete recipe to build.
Example build recipe (debug build, installs to default prefix)
Example build recipe (debug build, installs to default prefix
`${typeart_SOURCE_DIR}/install/typeart`)

```{.sh}
$> git clone https://github.com/tudasc/TypeART
$> cd TypeART
Expand All @@ -50,54 +63,78 @@ $> cmake --build build --target install --parallel

#### CMake Configuration: Options for users

##### Runtime

- `SOFTCOUNTERS` (default: **off**) : Enable runtime tracking of #tracked addrs. / #distinct checks / etc.
- `USE_BTREE` (default: **on**) : Enable usage of btree-backed map instead of std::map for the runtime, typically resulting in higher performance.
- `USE_ABSL` (default: **on**) : Enable usage of btree-backed map of the abseil project instead of std::map for the
runtime.
- `USE_BTREE` (default: **off**) : Enable usage of a btree-backed map (alternative to abseil) instead of std::map for
the runtime.

##### Logging and Passes

- `SHOW_STATS` (default: **on**) : Passes show the statistics w.r.t. allocations etc.
- `MPI_LOGGER` (default: **on**) : Enable better logging support in MPI execution context
- `MPI_INTERCEPT_LIB` (default: **on**) : Library can be used by preloading to intercept MPI calls and check whether
TypeART tracks the buffer pointer
- `LOG_LEVEL_` and `LOG_LEVEL_RT` (default **0**) : Granularity of logger. 3 ist most verbose, 0 is least.

##### Testing

- `TEST_CONFIG` (default: **off**) : Set (force) logging levels to appropriate levels for test runner to succeed
- `ENABLE_CODE_COVERAGE` (default: **off**) : Enable code coverage statistics using LCOV 1.14 and genhtml (gcovr
optional)
- `ENABLE_LLVM_CODE_COVERAGE` (default: **off**) : Enable llvm-cov code coverage statistics (llvm-cov and llvm-profdata
required)

## Using TypeART

Making use of TypeART consists of two phases:
Making use of TypeART consists of two phases:

1. Compile and instrument the target code with our LLVM passes, and,
2. execute the target program with a runtime library (based on the TypeART runtime) to accept the callbacks from the instrumented code and actually do some useful analysis.
1. Compile and instrument the target code with our LLVM passes, and,
2. execute the target program with a runtime library (based on the TypeART runtime) to accept the callbacks from the
instrumented code and actually do some useful analysis.

To that end, the interface [RuntimeInterface.h](runtime/RuntimeInterface.h) can be used to query type information during the target code execution.
To that end, the interface [RuntimeInterface.h](runtime/RuntimeInterface.h) can be used to query type information during
the target code execution.

#### Example: MPI Demo

The folder [demo](demo) contains an example of MPI related type errors that can be detected using TypeART.
The code is compiled with our instrumentation, and executed by preloading the MPI related check library implemented in [tool.c](demo/tool.c), which is linked against the TypeART runtime and uses the aforementioned query interface.
It overloads the required MPI calls and checks that the passed `void* buffer` is correct.
The folder [demo](demo) contains an example of MPI related type errors that can be detected using TypeART. The code is
compiled with our instrumentation, and executed by preloading the MPI related check library implemented
in [tool.c](demo/tool.c), which is linked against the TypeART runtime and uses the aforementioned query interface. It
overloads the required MPI calls and checks that the passed `void* buffer` is correct.

## LLVM pass

The necessary allocation sites and type information are extracted in LLVM passes.
TypeART analyzes:
The necessary allocation sites and type information are extracted in LLVM passes. TypeART analyzes:

- Calls to ```malloc``` and ```free``` to keep track of active pointers referring to objects allocated on the heap,
- relevant stack space allocations, i.e., allocations that cannot be proven to never lead to ```MPI``` functions,
- relevant stack space allocations, i.e., allocations that cannot be proven to never lead to ```MPI``` functions,
- built-in as well as user-defined types to retrieve type size and the size of the allocation, e.g., for arrays.

The type information is necessary to correlate the type of the buffer passed to an MPI call with the MPI datatype the user declared.
In this prototype we restrict ourselves to:
The type information is necessary to correlate the type of the buffer passed to an MPI call with the MPI datatype the
user declared. In this prototype we restrict ourselves to:

+ primitive types (int, float, long, double, char, unsigned int, unsigned long)
+ arrays of primitive types
+ structs which contain only primitive types

### Example of Instrumentation: Handling malloc

To instrument relevant allocations and extract the necessary type information, the LLVM pass searches for specific patterns, e.g., how calls to ```malloc``` look like in LLVM IR.
Calls to the ```malloc``` function are typically call instructions followed by a ```bitcast``` instruction to cast the returned pointer to the desired type.
To instrument relevant allocations and extract the necessary type information, the LLVM pass searches for specific
patterns, e.g., how calls to ```malloc``` look like in LLVM IR. Calls to the ```malloc``` function are typically call
instructions followed by a ```bitcast``` instruction to cast the returned pointer to the desired type.

~~~{.ll}
; %0 == n * sizeof(float)
%1 = tail call i8* @malloc(i64 %0)
%2 = bitcast i8* %1 to float *
~~~

The patterns has all the information we require for our instrumentation.
Our transformation first detects the type that the returned pointer is casted to, then it computes the extent of the allocation.
The information is passed to our instrumentation function.
The patterns has all the information we require for our instrumentation. Our transformation first detects the type that
the returned pointer is casted to, then it computes the extent of the allocation. The information is passed to our
instrumentation function.

~~~{.ll}
; %0 == n * sizeof(float)
Expand Down
Loading

0 comments on commit aeb9ca5

Please sign in to comment.